зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1539690
- Make a JS::RegExpFlag public API for flag bits, and make a JS::RegExpFlags flag-set abstraction. r=sfink
Differential Revision: https://phabricator.services.mozilla.com/D25177 --HG-- rename : js/public/RegExp.h => js/public/RegExpFlags.h extra : moz-landing-system : lando
This commit is contained in:
Родитель
5d1c793bad
Коммит
feb28d4555
|
@ -6516,7 +6516,7 @@ bool nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern,
|
|||
JS::Rooted<JSObject*> re(
|
||||
cx,
|
||||
JS::NewUCRegExpObject(cx, static_cast<char16_t*>(aPattern.BeginWriting()),
|
||||
aPattern.Length(), JS::RegExpFlags::Unicode));
|
||||
aPattern.Length(), JS::RegExpFlag::Unicode));
|
||||
if (!re) {
|
||||
// Remove extra patterns added above to report with the original pattern.
|
||||
aPattern.Cut(0, 4);
|
||||
|
|
|
@ -772,7 +772,7 @@ bool WrapperAnswer::RecvRegExpToShared(const ObjectId& objId, ReturnStatus* rs,
|
|||
}
|
||||
source->Assign(sourceStr);
|
||||
|
||||
*flags = JS::GetRegExpFlags(cx, obj);
|
||||
*flags = JS::GetRegExpFlags(cx, obj).value();
|
||||
|
||||
return ok(rs);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "jsfriendapi.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "js/RegExp.h"
|
||||
#include "js/RegExpFlags.h"
|
||||
#include "xpcprivate.h"
|
||||
#include "WrapperFactory.h"
|
||||
|
||||
|
@ -833,7 +834,8 @@ RegExpShared* WrapperOwner::regexp_toShared(JSContext* cx, HandleObject proxy) {
|
|||
}
|
||||
|
||||
RootedObject regexp(cx);
|
||||
regexp = JS::NewUCRegExpObject(cx, source.get(), source.Length(), flags);
|
||||
regexp = JS::NewUCRegExpObject(cx, source.get(), source.Length(),
|
||||
RegExpFlags(flags));
|
||||
if (!regexp) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "jstypes.h" // JS_PUBLIC_API
|
||||
|
||||
#include "js/RegExpFlags.h" // JS::RegExpFlags
|
||||
#include "js/RootingAPI.h" // JS::{,Mutable}Handle
|
||||
#include "js/Value.h" // JS::Value
|
||||
|
||||
|
@ -21,46 +22,20 @@ class JSString;
|
|||
|
||||
namespace JS {
|
||||
|
||||
/**
|
||||
* A namespace for all regular expression flags as they appear in the APIs below
|
||||
* as flags values.
|
||||
*/
|
||||
struct RegExpFlags {
|
||||
public:
|
||||
/**
|
||||
* Interpret regular expression source text case-insensitively by folding
|
||||
* uppercase letters to lowercase, i.e. /i.
|
||||
*/
|
||||
static constexpr unsigned IgnoreCase = 0b0'0001;
|
||||
|
||||
/**
|
||||
* Act globally and find *all* matches (rather than stopping after just the
|
||||
* first one), i.e. /g.
|
||||
*/
|
||||
static constexpr unsigned Global = 0b0'0010;
|
||||
|
||||
/** Treat ^ and $ as begin and end of line, i.e. /m. */
|
||||
static constexpr unsigned Multiline = 0b0'0100;
|
||||
|
||||
/** Only match starting from <regular expression>.lastIndex, i.e. /y. */
|
||||
static constexpr unsigned Sticky = 0b0'1000;
|
||||
|
||||
/** Use Unicode semantics, i.e. /u. */
|
||||
static constexpr unsigned Unicode = 0b1'0000;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new RegExp for the given Latin-1-encoded bytes and flags.
|
||||
*/
|
||||
extern JS_PUBLIC_API JSObject* NewRegExpObject(JSContext* cx, const char* bytes,
|
||||
size_t length, unsigned flags);
|
||||
size_t length,
|
||||
RegExpFlags flags);
|
||||
|
||||
/**
|
||||
* Create a new RegExp for the given source and flags.
|
||||
*/
|
||||
extern JS_PUBLIC_API JSObject* NewUCRegExpObject(JSContext* cx,
|
||||
const char16_t* chars,
|
||||
size_t length, unsigned flags);
|
||||
size_t length,
|
||||
RegExpFlags flags);
|
||||
|
||||
extern JS_PUBLIC_API bool SetRegExpInput(JSContext* cx, Handle<JSObject*> obj,
|
||||
Handle<JSString*> input);
|
||||
|
@ -95,10 +70,10 @@ extern JS_PUBLIC_API bool ObjectIsRegExp(JSContext* cx, Handle<JSObject*> obj,
|
|||
|
||||
/**
|
||||
* Given a RegExp object (or a wrapper around one), return the set of all
|
||||
* JS::RegExpFlags::* for it.
|
||||
* JS::RegExpFlag::* for it.
|
||||
*/
|
||||
extern JS_PUBLIC_API unsigned GetRegExpFlags(JSContext* cx,
|
||||
Handle<JSObject*> obj);
|
||||
extern JS_PUBLIC_API RegExpFlags GetRegExpFlags(JSContext* cx,
|
||||
Handle<JSObject*> obj);
|
||||
|
||||
/**
|
||||
* Return the source text for a RegExp object (or a wrapper around one), or null
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=8 sts=2 et sw=2 tw=80:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Regular expression flags. */
|
||||
|
||||
#ifndef js_RegExpFlags_h
|
||||
#define js_RegExpFlags_h
|
||||
|
||||
#include "mozilla/Assertions.h" // MOZ_ASSERT
|
||||
#include "mozilla/Attributes.h" // MOZ_IMPLICIT
|
||||
|
||||
#include <stdint.h> // uint8_t
|
||||
|
||||
namespace JS {
|
||||
|
||||
/**
|
||||
* Regular expression flag values, suitable for initializing a collection of
|
||||
* regular expression flags as defined below in |RegExpFlags|. Flags are listed
|
||||
* in alphabetical order by syntax -- /g, /i, /m, /u, /y.
|
||||
*/
|
||||
class RegExpFlag {
|
||||
// WARNING TO SPIDERMONKEY HACKERS (embedders must assume these values can
|
||||
// change):
|
||||
//
|
||||
// Flag-bit values appear in XDR and structured clone data formats, so none of
|
||||
// these values can be changed (including to assign values in numerically
|
||||
// ascending order) unless you also add a translation layer.
|
||||
|
||||
public:
|
||||
/**
|
||||
* Act globally and find *all* matches (rather than stopping after just the
|
||||
* first one), i.e. /g.
|
||||
*/
|
||||
static constexpr uint8_t Global = 0b0'0010;
|
||||
|
||||
/**
|
||||
* Interpret regular expression source text case-insensitively by folding
|
||||
* uppercase letters to lowercase, i.e. /i.
|
||||
*/
|
||||
static constexpr uint8_t IgnoreCase = 0b0'0001;
|
||||
|
||||
/** Treat ^ and $ as begin and end of line, i.e. /m. */
|
||||
static constexpr uint8_t Multiline = 0b0'0100;
|
||||
|
||||
/** Use Unicode semantics, i.e. /u. */
|
||||
static constexpr uint8_t Unicode = 0b1'0000;
|
||||
|
||||
/** Only match starting from <regular expression>.lastIndex, i.e. /y. */
|
||||
static constexpr uint8_t Sticky = 0b0'1000;
|
||||
|
||||
/** No regular expression flags. */
|
||||
static constexpr uint8_t NoFlags = 0b0'0000;
|
||||
|
||||
/** All regular expression flags. */
|
||||
static constexpr uint8_t AllFlags = 0b1'1111;
|
||||
};
|
||||
|
||||
/**
|
||||
* A collection of regular expression flags. Individual flag values may be
|
||||
* combined into a collection using bitwise operators.
|
||||
*/
|
||||
class RegExpFlags {
|
||||
public:
|
||||
using Flag = uint8_t;
|
||||
|
||||
private:
|
||||
Flag flags_;
|
||||
|
||||
public:
|
||||
RegExpFlags() = default;
|
||||
|
||||
MOZ_IMPLICIT RegExpFlags(Flag flags) : flags_(flags) {
|
||||
MOZ_ASSERT((flags & RegExpFlag::AllFlags) == flags,
|
||||
"flags must not contain unrecognized flags");
|
||||
}
|
||||
|
||||
RegExpFlags(const RegExpFlags&) = default;
|
||||
|
||||
bool operator==(const RegExpFlags& other) const {
|
||||
return flags_ == other.flags_;
|
||||
}
|
||||
|
||||
bool operator!=(const RegExpFlags& other) const { return !(*this == other); }
|
||||
|
||||
RegExpFlags operator&(Flag flag) const { return RegExpFlags(flags_ & flag); }
|
||||
|
||||
RegExpFlags operator|(Flag flag) const { return RegExpFlags(flags_ | flag); }
|
||||
|
||||
RegExpFlags operator^(Flag flag) const { return RegExpFlags(flags_ ^ flag); }
|
||||
|
||||
RegExpFlags operator~() const { return RegExpFlags(~flags_); }
|
||||
|
||||
bool global() const { return flags_ & RegExpFlag::Global; }
|
||||
bool ignoreCase() const { return flags_ & RegExpFlag::IgnoreCase; }
|
||||
bool multiline() const { return flags_ & RegExpFlag::Multiline; }
|
||||
bool unicode() const { return flags_ & RegExpFlag::Unicode; }
|
||||
bool sticky() const { return flags_ & RegExpFlag::Sticky; }
|
||||
|
||||
explicit operator bool() const { return flags_ != 0; }
|
||||
|
||||
Flag value() const { return flags_; }
|
||||
};
|
||||
|
||||
inline RegExpFlags& operator&=(RegExpFlags& flags, RegExpFlags::Flag flag) {
|
||||
flags = flags & flag;
|
||||
return flags;
|
||||
}
|
||||
|
||||
inline RegExpFlags& operator|=(RegExpFlags& flags, RegExpFlags::Flag flag) {
|
||||
flags = flags | flag;
|
||||
return flags;
|
||||
}
|
||||
|
||||
inline RegExpFlags& operator^=(RegExpFlags& flags, RegExpFlags::Flag flag) {
|
||||
flags = flags ^ flag;
|
||||
return flags;
|
||||
}
|
||||
|
||||
} // namespace JS
|
||||
|
||||
#endif // js_RegExpFlags_h
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "builtin/RegExp.h"
|
||||
|
||||
#include "mozilla/Casting.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
|
@ -13,6 +14,7 @@
|
|||
#include "irregexp/RegExpParser.h"
|
||||
#include "jit/InlinableNatives.h"
|
||||
#include "js/PropertySpec.h"
|
||||
#include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags
|
||||
#include "util/StringBuffer.h"
|
||||
#include "util/Unicode.h"
|
||||
#include "vm/JSContext.h"
|
||||
|
@ -26,10 +28,13 @@
|
|||
|
||||
using namespace js;
|
||||
|
||||
using mozilla::AssertedCast;
|
||||
using mozilla::CheckedInt;
|
||||
using mozilla::IsAsciiDigit;
|
||||
|
||||
using JS::CompileOptions;
|
||||
using JS::RegExpFlag;
|
||||
using JS::RegExpFlags;
|
||||
|
||||
/*
|
||||
* ES 2017 draft rev 6a13789aa9e7c6de4e96b7d3e24d9e6eba6584ad 21.2.5.2.2
|
||||
|
@ -187,16 +192,16 @@ bool js::ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res,
|
|||
}
|
||||
|
||||
static bool CheckPatternSyntaxSlow(JSContext* cx, HandleAtom pattern,
|
||||
RegExpFlag flags) {
|
||||
RegExpFlags flags) {
|
||||
LifoAllocScope allocScope(&cx->tempLifoAlloc());
|
||||
CompileOptions options(cx);
|
||||
frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr);
|
||||
return irregexp::ParsePatternSyntax(dummyTokenStream, allocScope.alloc(),
|
||||
pattern, flags & UnicodeFlag);
|
||||
pattern, flags.unicode());
|
||||
}
|
||||
|
||||
static RegExpShared* CheckPatternSyntax(JSContext* cx, HandleAtom pattern,
|
||||
RegExpFlag flags) {
|
||||
RegExpFlags flags) {
|
||||
// If we already have a RegExpShared for this pattern/flags, we can
|
||||
// avoid the much slower CheckPatternSyntaxSlow call.
|
||||
|
||||
|
@ -252,7 +257,7 @@ static bool RegExpInitializeIgnoringLastIndex(JSContext* cx,
|
|||
}
|
||||
|
||||
/* Step 3. */
|
||||
RegExpFlag flags = RegExpFlag(0);
|
||||
RegExpFlags flags = RegExpFlag::NoFlags;
|
||||
if (!flagsValue.isUndefined()) {
|
||||
/* Step 4. */
|
||||
RootedString flagStr(cx, ToString<CanGC>(cx, flagsValue));
|
||||
|
@ -363,7 +368,7 @@ MOZ_ALWAYS_INLINE bool regexp_compile_impl(JSContext* cx,
|
|||
RootedObject patternObj(cx, &patternValue.toObject());
|
||||
|
||||
RootedAtom sourceAtom(cx);
|
||||
RegExpFlag flags;
|
||||
RegExpFlags flags = RegExpFlag::NoFlags;
|
||||
{
|
||||
// Step 3b.
|
||||
RegExpShared* shared = RegExpToShared(cx, patternObj);
|
||||
|
@ -461,7 +466,7 @@ bool js::regexp_construct(JSContext* cx, unsigned argc, Value* vp) {
|
|||
RootedObject patternObj(cx, &patternValue.toObject());
|
||||
|
||||
RootedAtom sourceAtom(cx);
|
||||
RegExpFlag flags;
|
||||
RegExpFlags flags;
|
||||
RootedRegExpShared shared(cx);
|
||||
{
|
||||
// Step 4.a.
|
||||
|
@ -495,7 +500,7 @@ bool js::regexp_construct(JSContext* cx, unsigned argc, Value* vp) {
|
|||
// Step 8.
|
||||
if (args.hasDefined(1)) {
|
||||
// Step 4.c / 21.2.3.2.2 RegExpInitialize step 4.
|
||||
RegExpFlag flagsArg = RegExpFlag(0);
|
||||
RegExpFlags flagsArg = RegExpFlag::NoFlags;
|
||||
RootedString flagStr(cx, ToString<CanGC>(cx, args[1]));
|
||||
if (!flagStr) {
|
||||
return false;
|
||||
|
@ -509,7 +514,7 @@ bool js::regexp_construct(JSContext* cx, unsigned argc, Value* vp) {
|
|||
shared = nullptr;
|
||||
}
|
||||
|
||||
if (!(flags & UnicodeFlag) && flagsArg & UnicodeFlag) {
|
||||
if (!flags.unicode() && flagsArg.unicode()) {
|
||||
// Have to check syntax again when adding 'u' flag.
|
||||
|
||||
// ES 2017 draft rev 9b49a888e9dfe2667008a01b2754c3662059ae56
|
||||
|
@ -594,7 +599,7 @@ bool js::regexp_construct_raw_flags(JSContext* cx, unsigned argc, Value* vp) {
|
|||
}
|
||||
|
||||
// Step 4.c.
|
||||
int32_t flags = int32_t(args[1].toNumber());
|
||||
RegExpFlags flags = AssertedCast<uint8_t>(int32_t(args[1].toNumber()));
|
||||
|
||||
// Step 7.
|
||||
RegExpObject* regexp = RegExpAlloc(cx, GenericObject);
|
||||
|
@ -603,7 +608,7 @@ bool js::regexp_construct_raw_flags(JSContext* cx, unsigned argc, Value* vp) {
|
|||
}
|
||||
|
||||
// Step 8.
|
||||
regexp->initAndZeroLastIndex(sourceAtom, RegExpFlag(flags), cx);
|
||||
regexp->initAndZeroLastIndex(sourceAtom, flags, cx);
|
||||
args.rval().setObject(*regexp);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "js/HashTable.h"
|
||||
#include "js/LocaleSensitive.h"
|
||||
#include "js/PropertySpec.h"
|
||||
#include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags
|
||||
#include "js/SourceText.h"
|
||||
#include "js/StableStringChars.h"
|
||||
#include "js/StructuredClone.h"
|
||||
|
@ -97,6 +98,8 @@ using mozilla::Maybe;
|
|||
|
||||
using JS::AutoStableStringChars;
|
||||
using JS::CompileOptions;
|
||||
using JS::RegExpFlag;
|
||||
using JS::RegExpFlags;
|
||||
using JS::SourceOwnership;
|
||||
using JS::SourceText;
|
||||
|
||||
|
@ -4852,7 +4855,7 @@ static bool ParseRegExp(JSContext* cx, unsigned argc, Value* vp) {
|
|||
return false;
|
||||
}
|
||||
|
||||
RegExpFlag flags = RegExpFlag(0);
|
||||
RegExpFlags flags = RegExpFlag::NoFlags;
|
||||
if (!args.get(1).isUndefined()) {
|
||||
if (!args.get(1).isString()) {
|
||||
ReportUsageErrorASCII(cx, callee,
|
||||
|
@ -4887,9 +4890,7 @@ static bool ParseRegExp(JSContext* cx, unsigned argc, Value* vp) {
|
|||
LifoAllocScope allocScope(&cx->tempLifoAlloc());
|
||||
irregexp::RegExpCompileData data;
|
||||
if (!irregexp::ParsePattern(dummyTokenStream, allocScope.alloc(), pattern,
|
||||
flags & MultilineFlag, match_only,
|
||||
flags & UnicodeFlag, flags & IgnoreCaseFlag,
|
||||
flags & GlobalFlag, flags & StickyFlag, &data)) {
|
||||
match_only, flags, &data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,11 +44,14 @@ cpp:
|
|||
#include "frontend/ParseNode.h"
|
||||
#include "frontend/Parser.h"
|
||||
#include "frontend/SharedContext.h"
|
||||
|
||||
#include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags
|
||||
#include "vm/RegExpObject.h"
|
||||
|
||||
#include "frontend/ParseContext-inl.h"
|
||||
|
||||
using JS::RegExpFlag;
|
||||
using JS::RegExpFlags;
|
||||
|
||||
namespace js {
|
||||
namespace frontend {
|
||||
|
||||
|
@ -1281,18 +1284,18 @@ LiteralRegExpExpression:
|
|||
Chars flags(cx_);
|
||||
MOZ_TRY(tokenizer_->readChars(flags));
|
||||
build: |
|
||||
RegExpFlag reflags = NoFlags;
|
||||
RegExpFlags reflags = RegExpFlag::NoFlags;
|
||||
for (auto c : flags) {
|
||||
if (c == 'g' && !(reflags & GlobalFlag)) {
|
||||
reflags = RegExpFlag(reflags | GlobalFlag);
|
||||
} else if (c == 'i' && !(reflags & IgnoreCaseFlag)) {
|
||||
reflags = RegExpFlag(reflags | IgnoreCaseFlag);
|
||||
} else if (c == 'm' && !(reflags & MultilineFlag)) {
|
||||
reflags = RegExpFlag(reflags | MultilineFlag);
|
||||
} else if (c == 'y' && !(reflags & StickyFlag)) {
|
||||
reflags = RegExpFlag(reflags | StickyFlag);
|
||||
} else if (c == 'u' && !(reflags & UnicodeFlag)) {
|
||||
reflags = RegExpFlag(reflags | UnicodeFlag);
|
||||
if (c == 'g' && !reflags.global()) {
|
||||
reflags |= RegExpFlag::Global;
|
||||
} else if (c == 'i' && !reflags.ignoreCase()) {
|
||||
reflags |= RegExpFlag::IgnoreCase;
|
||||
} else if (c == 'm' && !reflags.multiline()) {
|
||||
reflags |= RegExpFlag::Multiline;
|
||||
} else if (c == 'u' && !reflags.unicode()) {
|
||||
reflags |= RegExpFlag::Unicode;
|
||||
} else if (c == 'y' && !reflags.sticky()) {
|
||||
reflags |= RegExpFlag::Sticky;
|
||||
} else {
|
||||
return raiseError("Invalid regexp flags");
|
||||
}
|
||||
|
|
|
@ -24,11 +24,14 @@
|
|||
#include "frontend/ParseNode.h"
|
||||
#include "frontend/Parser.h"
|
||||
#include "frontend/SharedContext.h"
|
||||
|
||||
#include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags
|
||||
#include "vm/RegExpObject.h"
|
||||
|
||||
#include "frontend/ParseContext-inl.h"
|
||||
|
||||
using JS::RegExpFlag;
|
||||
using JS::RegExpFlags;
|
||||
|
||||
namespace js {
|
||||
namespace frontend {
|
||||
|
||||
|
@ -3522,18 +3525,18 @@ JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLiteralRegExpExpression(
|
|||
Chars flags(cx_);
|
||||
MOZ_TRY(tokenizer_->readChars(flags));
|
||||
|
||||
RegExpFlag reflags = NoFlags;
|
||||
RegExpFlags reflags = RegExpFlag::NoFlags;
|
||||
for (auto c : flags) {
|
||||
if (c == 'g' && !(reflags & GlobalFlag)) {
|
||||
reflags = RegExpFlag(reflags | GlobalFlag);
|
||||
} else if (c == 'i' && !(reflags & IgnoreCaseFlag)) {
|
||||
reflags = RegExpFlag(reflags | IgnoreCaseFlag);
|
||||
} else if (c == 'm' && !(reflags & MultilineFlag)) {
|
||||
reflags = RegExpFlag(reflags | MultilineFlag);
|
||||
} else if (c == 'y' && !(reflags & StickyFlag)) {
|
||||
reflags = RegExpFlag(reflags | StickyFlag);
|
||||
} else if (c == 'u' && !(reflags & UnicodeFlag)) {
|
||||
reflags = RegExpFlag(reflags | UnicodeFlag);
|
||||
if (c == 'g' && !reflags.global()) {
|
||||
reflags |= RegExpFlag::Global;
|
||||
} else if (c == 'i' && !reflags.ignoreCase()) {
|
||||
reflags |= RegExpFlag::IgnoreCase;
|
||||
} else if (c == 'm' && !reflags.multiline()) {
|
||||
reflags |= RegExpFlag::Multiline;
|
||||
} else if (c == 'u' && !reflags.unicode()) {
|
||||
reflags |= RegExpFlag::Unicode;
|
||||
} else if (c == 'y' && !reflags.sticky()) {
|
||||
reflags |= RegExpFlag::Sticky;
|
||||
} else {
|
||||
return raiseError("Invalid regexp flags");
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "frontend/ParseNode.h"
|
||||
#include "frontend/TokenStream.h"
|
||||
#include "irregexp/RegExpParser.h"
|
||||
#include "js/RegExpFlags.h" // JS::RegExpFlags
|
||||
#include "vm/BytecodeUtil.h"
|
||||
#include "vm/JSAtom.h"
|
||||
#include "vm/JSContext.h"
|
||||
|
@ -70,6 +71,7 @@ using mozilla::Utf8Unit;
|
|||
|
||||
using JS::AutoGCRooter;
|
||||
using JS::ReadOnlyCompileOptions;
|
||||
using JS::RegExpFlags;
|
||||
|
||||
namespace js {
|
||||
namespace frontend {
|
||||
|
@ -9257,7 +9259,7 @@ RegExpLiteral* Parser<FullParseHandler, Unit>::newRegExp() {
|
|||
|
||||
// Create the regexp and check its syntax.
|
||||
const auto& chars = tokenStream.getCharBuffer();
|
||||
RegExpFlag flags = anyChars.currentToken().regExpFlags();
|
||||
RegExpFlags flags = anyChars.currentToken().regExpFlags();
|
||||
|
||||
Rooted<RegExpObject*> reobj(cx_);
|
||||
reobj = RegExpObject::create(cx_, chars.begin(), chars.length(), flags,
|
||||
|
@ -9276,13 +9278,13 @@ Parser<SyntaxParseHandler, Unit>::newRegExp() {
|
|||
|
||||
// Only check the regexp's syntax, but don't create a regexp object.
|
||||
const auto& chars = tokenStream.getCharBuffer();
|
||||
RegExpFlag flags = anyChars.currentToken().regExpFlags();
|
||||
RegExpFlags flags = anyChars.currentToken().regExpFlags();
|
||||
|
||||
mozilla::Range<const char16_t> source(chars.begin(), chars.length());
|
||||
{
|
||||
LifoAllocScope scopeAlloc(&alloc_);
|
||||
if (!js::irregexp::ParsePatternSyntax(anyChars, scopeAlloc.alloc(), source,
|
||||
flags & UnicodeFlag)) {
|
||||
flags.unicode())) {
|
||||
return null();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "frontend/Parser.h"
|
||||
#include "frontend/ReservedWords.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "js/RegExpFlags.h" // JS::RegExpFlags
|
||||
#include "js/UniquePtr.h"
|
||||
#include "util/StringBuffer.h"
|
||||
#include "util/Unicode.h"
|
||||
|
@ -56,6 +57,8 @@ using mozilla::PointerRangeSize;
|
|||
using mozilla::Utf8Unit;
|
||||
|
||||
using JS::ReadOnlyCompileOptions;
|
||||
using JS::RegExpFlag;
|
||||
using JS::RegExpFlags;
|
||||
|
||||
struct ReservedWordInfo {
|
||||
const char* chars; // C string with reserved word text
|
||||
|
@ -2319,34 +2322,34 @@ MOZ_MUST_USE bool TokenStreamSpecific<Unit, AnyCharsAccess>::regexpLiteral(
|
|||
} while (true);
|
||||
|
||||
int32_t unit;
|
||||
RegExpFlag reflags = NoFlags;
|
||||
RegExpFlags reflags = RegExpFlag::NoFlags;
|
||||
while (true) {
|
||||
RegExpFlag flag;
|
||||
uint8_t flag;
|
||||
unit = getCodeUnit();
|
||||
if (unit == 'g') {
|
||||
flag = GlobalFlag;
|
||||
flag = RegExpFlag::Global;
|
||||
} else if (unit == 'i') {
|
||||
flag = IgnoreCaseFlag;
|
||||
flag = RegExpFlag::IgnoreCase;
|
||||
} else if (unit == 'm') {
|
||||
flag = MultilineFlag;
|
||||
} else if (unit == 'y') {
|
||||
flag = StickyFlag;
|
||||
flag = RegExpFlag::Multiline;
|
||||
} else if (unit == 'u') {
|
||||
flag = UnicodeFlag;
|
||||
flag = RegExpFlag::Unicode;
|
||||
} else if (unit == 'y') {
|
||||
flag = RegExpFlag::Sticky;
|
||||
} else if (IsAsciiAlpha(unit)) {
|
||||
flag = NoFlags;
|
||||
flag = RegExpFlag::NoFlags;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((reflags & flag) || flag == NoFlags) {
|
||||
if ((reflags & flag) || flag == RegExpFlag::NoFlags) {
|
||||
ungetCodeUnit(unit);
|
||||
char buf[2] = {char(unit), '\0'};
|
||||
error(JSMSG_BAD_REGEXP_FLAG, buf);
|
||||
return badToken();
|
||||
}
|
||||
|
||||
reflags = RegExpFlag(reflags | flag);
|
||||
reflags |= flag;
|
||||
}
|
||||
ungetCodeUnit(unit);
|
||||
|
||||
|
|
|
@ -206,13 +206,13 @@
|
|||
#include "frontend/ErrorReporter.h"
|
||||
#include "frontend/TokenKind.h"
|
||||
#include "js/CompileOptions.h"
|
||||
#include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags
|
||||
#include "js/UniquePtr.h"
|
||||
#include "js/Vector.h"
|
||||
#include "util/Text.h"
|
||||
#include "util/Unicode.h"
|
||||
#include "vm/ErrorReporting.h"
|
||||
#include "vm/JSAtom.h"
|
||||
#include "vm/RegExpConstants.h"
|
||||
#include "vm/StringType.h"
|
||||
|
||||
struct JSContext;
|
||||
|
@ -380,7 +380,7 @@ struct Token {
|
|||
} number;
|
||||
|
||||
/** Regular expression flags; use charBuffer to access source chars. */
|
||||
RegExpFlag reflags;
|
||||
JS::RegExpFlags reflags;
|
||||
} u;
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -407,9 +407,8 @@ struct Token {
|
|||
u.atom = atom;
|
||||
}
|
||||
|
||||
void setRegExpFlags(RegExpFlag flags) {
|
||||
void setRegExpFlags(JS::RegExpFlags flags) {
|
||||
MOZ_ASSERT(type == TokenKind::RegExp);
|
||||
MOZ_ASSERT((flags & AllFlags) == flags);
|
||||
u.reflags = flags;
|
||||
}
|
||||
|
||||
|
@ -432,9 +431,8 @@ struct Token {
|
|||
return u.atom;
|
||||
}
|
||||
|
||||
RegExpFlag regExpFlags() const {
|
||||
JS::RegExpFlags regExpFlags() const {
|
||||
MOZ_ASSERT(type == TokenKind::RegExp);
|
||||
MOZ_ASSERT((u.reflags & AllFlags) == u.reflags);
|
||||
return u.reflags;
|
||||
}
|
||||
|
||||
|
@ -1999,7 +1997,8 @@ class GeneralTokenStreamChars : public SpecializedTokenStreamCharsBase<Unit> {
|
|||
token->setName(name);
|
||||
}
|
||||
|
||||
void newRegExpToken(RegExpFlag reflags, TokenStart start, TokenKind* out) {
|
||||
void newRegExpToken(JS::RegExpFlags reflags, TokenStart start,
|
||||
TokenKind* out) {
|
||||
Token* token =
|
||||
newToken(TokenKind::RegExp, start, TokenStreamShared::Operand, out);
|
||||
token->setRegExpFlags(reflags);
|
||||
|
@ -2802,7 +2801,8 @@ template <typename Unit>
|
|||
template <class AnyCharsAccess>
|
||||
inline TokenStreamPosition<Unit>::TokenStreamPosition(
|
||||
AutoKeepAtoms& keepAtoms,
|
||||
TokenStreamSpecific<Unit, AnyCharsAccess>& tokenStream) {
|
||||
TokenStreamSpecific<Unit, AnyCharsAccess>& tokenStream)
|
||||
: currentToken(tokenStream.anyCharsAccess().currentToken()) {
|
||||
TokenStreamAnyChars& anyChars = tokenStream.anyCharsAccess();
|
||||
|
||||
buf =
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "frontend/TokenStream.h"
|
||||
#include "gc/GC.h"
|
||||
#include "irregexp/RegExpCharacters.h"
|
||||
#include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags
|
||||
#include "util/StringBuffer.h"
|
||||
#include "util/Text.h"
|
||||
#include "util/Unicode.h"
|
||||
|
@ -49,6 +50,9 @@ using namespace js::irregexp;
|
|||
using mozilla::AssertedCast;
|
||||
using mozilla::PointerRangeSize;
|
||||
|
||||
using JS::RegExpFlag;
|
||||
using JS::RegExpFlags;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// RegExpBuilder
|
||||
|
||||
|
@ -240,9 +244,9 @@ RegExpBuilder::AddQuantifierToAtom(int min, int max,
|
|||
// RegExpParser
|
||||
|
||||
template <typename CharT>
|
||||
RegExpParser<CharT>::RegExpParser(frontend::TokenStreamAnyChars& ts, LifoAlloc* alloc,
|
||||
const CharT* chars, const CharT* end, bool multiline_mode,
|
||||
bool unicode, bool ignore_case)
|
||||
RegExpParser<CharT>::RegExpParser(frontend::TokenStreamAnyChars& ts,
|
||||
LifoAlloc* alloc, RegExpFlags flags,
|
||||
const CharT* chars, const CharT* end)
|
||||
: ts(ts),
|
||||
alloc(alloc),
|
||||
captures_(nullptr),
|
||||
|
@ -252,9 +256,9 @@ RegExpParser<CharT>::RegExpParser(frontend::TokenStreamAnyChars& ts, LifoAlloc*
|
|||
current_(kEndMarker),
|
||||
capture_count_(0),
|
||||
has_more_(true),
|
||||
multiline_(multiline_mode),
|
||||
unicode_(unicode),
|
||||
ignore_case_(ignore_case),
|
||||
multiline_(flags.multiline()),
|
||||
unicode_(flags.unicode()),
|
||||
ignore_case_(flags.ignoreCase()),
|
||||
simple_(false),
|
||||
contains_anchor_(false),
|
||||
is_scanned_for_captures_(false)
|
||||
|
@ -1931,13 +1935,12 @@ template class irregexp::RegExpParser<char16_t>;
|
|||
template <typename CharT>
|
||||
static bool
|
||||
ParsePattern(frontend::TokenStreamAnyChars& ts, LifoAlloc& alloc,
|
||||
const CharT* chars, size_t length,
|
||||
bool multiline, bool match_only, bool unicode, bool ignore_case,
|
||||
bool global, bool sticky, RegExpCompileData* data)
|
||||
const CharT* chars, size_t length, bool match_only,
|
||||
RegExpFlags flags, RegExpCompileData* data)
|
||||
{
|
||||
// We shouldn't strip pattern for exec, or test with global/sticky,
|
||||
// to reflect correct match position and lastIndex.
|
||||
if (match_only && !global && !sticky) {
|
||||
if (match_only && !flags.global() && !flags.sticky()) {
|
||||
// Try to strip a leading '.*' from the RegExp, but only if it is not
|
||||
// followed by a '?' (which will affect how the .* is parsed). This
|
||||
// pattern will affect the captures produced by the RegExp, but not
|
||||
|
@ -1958,7 +1961,7 @@ ParsePattern(frontend::TokenStreamAnyChars& ts, LifoAlloc& alloc,
|
|||
}
|
||||
}
|
||||
|
||||
RegExpParser<CharT> parser(ts, &alloc, chars, chars + length, multiline, unicode, ignore_case);
|
||||
RegExpParser<CharT> parser(ts, &alloc, flags, chars, chars + length);
|
||||
data->tree = parser.ParsePattern();
|
||||
if (!data->tree)
|
||||
return false;
|
||||
|
@ -1970,16 +1973,16 @@ ParsePattern(frontend::TokenStreamAnyChars& ts, LifoAlloc& alloc,
|
|||
}
|
||||
|
||||
bool
|
||||
irregexp::ParsePattern(frontend::TokenStreamAnyChars& ts, LifoAlloc& alloc, JSAtom* str,
|
||||
bool multiline, bool match_only, bool unicode, bool ignore_case,
|
||||
bool global, bool sticky, RegExpCompileData* data)
|
||||
irregexp::ParsePattern(frontend::TokenStreamAnyChars& ts, LifoAlloc& alloc,
|
||||
JSAtom* str, bool match_only, RegExpFlags flags,
|
||||
RegExpCompileData* data)
|
||||
{
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
return str->hasLatin1Chars()
|
||||
? ::ParsePattern(ts, alloc, str->latin1Chars(nogc), str->length(),
|
||||
multiline, match_only, unicode, ignore_case, global, sticky, data)
|
||||
match_only, flags, data)
|
||||
: ::ParsePattern(ts, alloc, str->twoByteChars(nogc), str->length(),
|
||||
multiline, match_only, unicode, ignore_case, global, sticky, data);
|
||||
match_only, flags, data);
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
|
@ -1987,7 +1990,8 @@ static bool
|
|||
ParsePatternSyntax(frontend::TokenStreamAnyChars& ts, LifoAlloc& alloc,
|
||||
const CharT* chars, size_t length, bool unicode)
|
||||
{
|
||||
RegExpParser<CharT> parser(ts, &alloc, chars, chars + length, false, unicode, false);
|
||||
RegExpParser<CharT> parser(ts, &alloc, unicode ? RegExpFlag::Unicode : 0,
|
||||
chars, chars + length);
|
||||
return parser.ParsePattern() != nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <stdarg.h>
|
||||
|
||||
#include "irregexp/RegExpAST.h"
|
||||
#include "js/RegExpFlags.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
|
@ -47,8 +48,7 @@ namespace irregexp {
|
|||
|
||||
extern bool
|
||||
ParsePattern(frontend::TokenStreamAnyChars& ts, LifoAlloc& alloc, JSAtom* str,
|
||||
bool multiline, bool match_only, bool unicode, bool ignore_case,
|
||||
bool global, bool sticky, RegExpCompileData* data);
|
||||
bool match_only, JS::RegExpFlags flags, RegExpCompileData* data);
|
||||
|
||||
extern bool
|
||||
ParsePatternSyntax(frontend::TokenStreamAnyChars& ts, LifoAlloc& alloc, JSAtom* str,
|
||||
|
@ -185,8 +185,7 @@ class RegExpParser
|
|||
{
|
||||
public:
|
||||
RegExpParser(frontend::TokenStreamAnyChars& ts, LifoAlloc* alloc,
|
||||
const CharT* chars, const CharT* end, bool multiline_mode, bool unicode,
|
||||
bool ignore_case);
|
||||
JS::RegExpFlags flags, const CharT* chars, const CharT* end);
|
||||
|
||||
RegExpTree* ParsePattern();
|
||||
RegExpTree* ParseDisjunction();
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "jit/SharedICHelpers.h"
|
||||
#include "jit/StackSlotAllocator.h"
|
||||
#include "jit/VMFunctions.h"
|
||||
#include "js/RegExpFlags.h" // JS::RegExpFlag
|
||||
#include "util/Unicode.h"
|
||||
#include "vm/AsyncFunction.h"
|
||||
#include "vm/AsyncIteration.h"
|
||||
|
@ -1943,7 +1944,7 @@ static bool PrepareAndExecuteRegExp(
|
|||
|
||||
masm.branchTest32(Assembler::Zero,
|
||||
Address(temp1, RegExpShared::offsetOfFlags()),
|
||||
Imm32(UnicodeFlag), &done);
|
||||
Imm32(int32_t(JS::RegExpFlag::Unicode)), &done);
|
||||
|
||||
// If input is latin1, there should not be surrogate pair.
|
||||
masm.branchLatin1String(input, &done);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "jit/Lowering.h"
|
||||
#include "jit/MIR.h"
|
||||
#include "jit/MIRGraph.h"
|
||||
#include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags
|
||||
#include "vm/ArgumentsObject.h"
|
||||
#include "vm/ArrayBufferObject.h"
|
||||
#include "vm/JSObject.h"
|
||||
|
@ -43,6 +44,8 @@ using mozilla::AssertedCast;
|
|||
using mozilla::Maybe;
|
||||
|
||||
using JS::DoubleNaNValue;
|
||||
using JS::RegExpFlag;
|
||||
using JS::RegExpFlags;
|
||||
using JS::TrackedOutcome;
|
||||
|
||||
namespace js {
|
||||
|
@ -624,7 +627,7 @@ IonBuilder::InliningResult IonBuilder::inlineNativeGetter(CallInfo& callInfo,
|
|||
}
|
||||
|
||||
// Try to optimize RegExp getters.
|
||||
RegExpFlag mask = NoFlags;
|
||||
RegExpFlags mask = RegExpFlag::NoFlags;
|
||||
if (RegExpObject::isOriginalFlagGetter(native, &mask)) {
|
||||
const Class* clasp = thisTypes->getKnownClass(constraints());
|
||||
if (clasp != &RegExpObject::class_) {
|
||||
|
@ -635,7 +638,7 @@ IonBuilder::InliningResult IonBuilder::inlineNativeGetter(CallInfo& callInfo,
|
|||
MLoadFixedSlot::New(alloc(), thisArg, RegExpObject::flagsSlot());
|
||||
current->add(flags);
|
||||
flags->setResultType(MIRType::Int32);
|
||||
MConstant* maskConst = MConstant::New(alloc(), Int32Value(mask));
|
||||
MConstant* maskConst = MConstant::New(alloc(), Int32Value(mask.value()));
|
||||
current->add(maskConst);
|
||||
MBitAnd* maskedFlag = MBitAnd::New(alloc(), flags, maskConst);
|
||||
maskedFlag->setInt32Specialization();
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "js/RegExp.h"
|
||||
#include "js/RegExpFlags.h"
|
||||
#include "jsapi-tests/tests.h"
|
||||
|
||||
BEGIN_TEST(testObjectIsRegExp) {
|
||||
|
@ -30,16 +31,19 @@ BEGIN_TEST(testGetRegExpFlags) {
|
|||
|
||||
EVAL("/foopy/", &val);
|
||||
obj = val.toObjectOrNull();
|
||||
CHECK_EQUAL(JS::GetRegExpFlags(cx, obj), 0u);
|
||||
CHECK_EQUAL(JS::GetRegExpFlags(cx, obj),
|
||||
JS::RegExpFlags(JS::RegExpFlag::NoFlags));
|
||||
|
||||
EVAL("/foopy/g", &val);
|
||||
obj = val.toObjectOrNull();
|
||||
CHECK(JS::GetRegExpFlags(cx, obj) == JS::RegExpFlags::Global);
|
||||
CHECK_EQUAL(JS::GetRegExpFlags(cx, obj),
|
||||
JS::RegExpFlags(JS::RegExpFlag::Global));
|
||||
|
||||
EVAL("/foopy/gi", &val);
|
||||
obj = val.toObjectOrNull();
|
||||
CHECK(JS::GetRegExpFlags(cx, obj) ==
|
||||
(JS::RegExpFlags::Global | JS::RegExpFlags::IgnoreCase));
|
||||
CHECK_EQUAL(
|
||||
JS::GetRegExpFlags(cx, obj),
|
||||
JS::RegExpFlags(JS::RegExpFlag::Global | JS::RegExpFlag::IgnoreCase));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "js/AllocPolicy.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "js/Equality.h" // JS::SameValue
|
||||
#include "js/RegExpFlags.h" // JS::RegExpFlags
|
||||
#include "js/Vector.h"
|
||||
#include "vm/JSContext.h"
|
||||
|
||||
|
@ -159,6 +160,26 @@ class JSAPITest {
|
|||
return JSAPITestString(v ? "true" : "false");
|
||||
}
|
||||
|
||||
JSAPITestString toSource(JS::RegExpFlags flags) {
|
||||
JSAPITestString str;
|
||||
if (flags.global()) {
|
||||
str += "g";
|
||||
}
|
||||
if (flags.ignoreCase()) {
|
||||
str += "i";
|
||||
}
|
||||
if (flags.multiline()) {
|
||||
str += "m";
|
||||
}
|
||||
if (flags.unicode()) {
|
||||
str += "u";
|
||||
}
|
||||
if (flags.sticky()) {
|
||||
str += "y";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
JSAPITestString toSource(JSAtom* v) {
|
||||
JS::RootedValue val(cx, JS::StringValue((JSString*)v));
|
||||
return jsvalToSource(val);
|
||||
|
|
|
@ -161,6 +161,7 @@ EXPORTS.js += [
|
|||
'../public/RealmOptions.h',
|
||||
'../public/RefCounted.h',
|
||||
'../public/RegExp.h',
|
||||
'../public/RegExpFlags.h',
|
||||
'../public/RequiredDefines.h',
|
||||
'../public/Result.h',
|
||||
'../public/RootingAPI.h',
|
||||
|
|
|
@ -11,24 +11,6 @@
|
|||
|
||||
namespace js {
|
||||
|
||||
enum RegExpFlag : uint8_t {
|
||||
IgnoreCaseFlag = 0x01,
|
||||
GlobalFlag = 0x02,
|
||||
MultilineFlag = 0x04,
|
||||
StickyFlag = 0x08,
|
||||
UnicodeFlag = 0x10,
|
||||
|
||||
NoFlags = 0x00,
|
||||
AllFlags = 0x1f
|
||||
};
|
||||
|
||||
static_assert(IgnoreCaseFlag == REGEXP_IGNORECASE_FLAG &&
|
||||
GlobalFlag == REGEXP_GLOBAL_FLAG &&
|
||||
MultilineFlag == REGEXP_MULTILINE_FLAG &&
|
||||
StickyFlag == REGEXP_STICKY_FLAG &&
|
||||
UnicodeFlag == REGEXP_UNICODE_FLAG,
|
||||
"Flag values should be in sync with self-hosted JS");
|
||||
|
||||
enum RegExpRunStatus {
|
||||
RegExpRunStatus_Error,
|
||||
RegExpRunStatus_Success,
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#endif
|
||||
|
||||
#include "builtin/RegExp.h"
|
||||
#include "builtin/SelfHostingDefines.h" // REGEXP_*_FLAG
|
||||
#include "frontend/TokenStream.h"
|
||||
#include "gc/HashUtil.h"
|
||||
#ifdef DEBUG
|
||||
|
@ -23,6 +24,7 @@
|
|||
#include "irregexp/RegExpParser.h"
|
||||
#include "jit/VMFunctions.h"
|
||||
#include "js/RegExp.h"
|
||||
#include "js/RegExpFlags.h" // JS::RegExpFlags
|
||||
#include "js/StableStringChars.h"
|
||||
#include "util/StringBuffer.h"
|
||||
#include "vm/MatchPairs.h"
|
||||
|
@ -42,6 +44,8 @@ using namespace js;
|
|||
|
||||
using JS::AutoStableStringChars;
|
||||
using JS::CompileOptions;
|
||||
using JS::RegExpFlag;
|
||||
using JS::RegExpFlags;
|
||||
using js::frontend::TokenStream;
|
||||
using mozilla::ArrayLength;
|
||||
using mozilla::DebugOnly;
|
||||
|
@ -49,16 +53,16 @@ using mozilla::PodCopy;
|
|||
|
||||
using JS::AutoCheckCannotGC;
|
||||
|
||||
static_assert(IgnoreCaseFlag == JS::RegExpFlags::IgnoreCase,
|
||||
"public/internal /i flag bits must agree");
|
||||
static_assert(GlobalFlag == JS::RegExpFlags::Global,
|
||||
"public/internal /g flag bits must agree");
|
||||
static_assert(MultilineFlag == JS::RegExpFlags::Multiline,
|
||||
"public/internal /m flag bits must agree");
|
||||
static_assert(StickyFlag == JS::RegExpFlags::Sticky,
|
||||
"public/internal /y flag bits must agree");
|
||||
static_assert(UnicodeFlag == JS::RegExpFlags::Unicode,
|
||||
"public/internal /u flag bits must agree");
|
||||
static_assert(RegExpFlag::Global == REGEXP_GLOBAL_FLAG,
|
||||
"self-hosted JS and /g flag bits must agree");
|
||||
static_assert(RegExpFlag::IgnoreCase == REGEXP_IGNORECASE_FLAG,
|
||||
"self-hosted JS and /i flag bits must agree");
|
||||
static_assert(RegExpFlag::Multiline == REGEXP_MULTILINE_FLAG,
|
||||
"self-hosted JS and /m flag bits must agree");
|
||||
static_assert(RegExpFlag::Unicode == REGEXP_UNICODE_FLAG,
|
||||
"self-hosted JS and /u flag bits must agree");
|
||||
static_assert(RegExpFlag::Sticky == REGEXP_STICKY_FLAG,
|
||||
"self-hosted JS and /y flag bits must agree");
|
||||
|
||||
RegExpObject* js::RegExpAlloc(JSContext* cx, NewObjectKind newKind,
|
||||
HandleObject proto /* = nullptr */) {
|
||||
|
@ -117,25 +121,25 @@ RegExpShared* RegExpObject::getShared(JSContext* cx,
|
|||
}
|
||||
|
||||
/* static */
|
||||
bool RegExpObject::isOriginalFlagGetter(JSNative native, RegExpFlag* mask) {
|
||||
bool RegExpObject::isOriginalFlagGetter(JSNative native, RegExpFlags* mask) {
|
||||
if (native == regexp_global) {
|
||||
*mask = GlobalFlag;
|
||||
*mask = RegExpFlag::Global;
|
||||
return true;
|
||||
}
|
||||
if (native == regexp_ignoreCase) {
|
||||
*mask = IgnoreCaseFlag;
|
||||
*mask = RegExpFlag::IgnoreCase;
|
||||
return true;
|
||||
}
|
||||
if (native == regexp_multiline) {
|
||||
*mask = MultilineFlag;
|
||||
*mask = RegExpFlag::Multiline;
|
||||
return true;
|
||||
}
|
||||
if (native == regexp_sticky) {
|
||||
*mask = StickyFlag;
|
||||
*mask = RegExpFlag::Sticky;
|
||||
return true;
|
||||
}
|
||||
if (native == regexp_unicode) {
|
||||
*mask = UnicodeFlag;
|
||||
*mask = RegExpFlag::Unicode;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -198,7 +202,7 @@ const Class RegExpObject::protoClass_ = {
|
|||
|
||||
template <typename CharT>
|
||||
RegExpObject* RegExpObject::create(JSContext* cx, const CharT* chars,
|
||||
size_t length, RegExpFlag flags,
|
||||
size_t length, RegExpFlags flags,
|
||||
frontend::TokenStreamAnyChars& tokenStream,
|
||||
NewObjectKind newKind) {
|
||||
static_assert(mozilla::IsSame<CharT, char16_t>::value,
|
||||
|
@ -213,12 +217,12 @@ RegExpObject* RegExpObject::create(JSContext* cx, const CharT* chars,
|
|||
}
|
||||
|
||||
template RegExpObject* RegExpObject::create(
|
||||
JSContext* cx, const char16_t* chars, size_t length, RegExpFlag flags,
|
||||
JSContext* cx, const char16_t* chars, size_t length, RegExpFlags flags,
|
||||
frontend::TokenStreamAnyChars& tokenStream, NewObjectKind newKind);
|
||||
|
||||
template <typename CharT>
|
||||
RegExpObject* RegExpObject::create(JSContext* cx, const CharT* chars,
|
||||
size_t length, RegExpFlag flags,
|
||||
size_t length, RegExpFlags flags,
|
||||
NewObjectKind newKind) {
|
||||
static_assert(mozilla::IsSame<CharT, char16_t>::value,
|
||||
"this code may need updating if/when CharT encodes UTF-8");
|
||||
|
@ -233,16 +237,16 @@ RegExpObject* RegExpObject::create(JSContext* cx, const CharT* chars,
|
|||
|
||||
template RegExpObject* RegExpObject::create(JSContext* cx,
|
||||
const char16_t* chars,
|
||||
size_t length, RegExpFlag flags,
|
||||
size_t length, RegExpFlags flags,
|
||||
NewObjectKind newKind);
|
||||
|
||||
RegExpObject* RegExpObject::create(JSContext* cx, HandleAtom source,
|
||||
RegExpFlag flags,
|
||||
RegExpFlags flags,
|
||||
frontend::TokenStreamAnyChars& tokenStream,
|
||||
NewObjectKind newKind) {
|
||||
LifoAllocScope allocScope(&cx->tempLifoAlloc());
|
||||
if (!irregexp::ParsePatternSyntax(tokenStream, allocScope.alloc(), source,
|
||||
flags & UnicodeFlag)) {
|
||||
flags.unicode())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -257,14 +261,14 @@ RegExpObject* RegExpObject::create(JSContext* cx, HandleAtom source,
|
|||
}
|
||||
|
||||
RegExpObject* RegExpObject::create(JSContext* cx, HandleAtom source,
|
||||
RegExpFlag flags, NewObjectKind newKind) {
|
||||
RegExpFlags flags, NewObjectKind newKind) {
|
||||
CompileOptions dummyOptions(cx);
|
||||
TokenStream dummyTokenStream(cx, dummyOptions, (const char16_t*)nullptr, 0,
|
||||
nullptr);
|
||||
|
||||
LifoAllocScope allocScope(&cx->tempLifoAlloc());
|
||||
if (!irregexp::ParsePatternSyntax(dummyTokenStream, allocScope.alloc(),
|
||||
source, flags & UnicodeFlag)) {
|
||||
source, flags.unicode())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -304,7 +308,7 @@ Shape* RegExpObject::assignInitialShape(JSContext* cx,
|
|||
LAST_INDEX_SLOT, JSPROP_PERMANENT);
|
||||
}
|
||||
|
||||
void RegExpObject::initIgnoringLastIndex(JSAtom* source, RegExpFlag flags) {
|
||||
void RegExpObject::initIgnoringLastIndex(JSAtom* source, RegExpFlags flags) {
|
||||
// If this is a re-initialization with an existing RegExpShared, 'flags'
|
||||
// may not match getShared()->flags, so forget the RegExpShared.
|
||||
sharedRef() = nullptr;
|
||||
|
@ -313,7 +317,7 @@ void RegExpObject::initIgnoringLastIndex(JSAtom* source, RegExpFlag flags) {
|
|||
setFlags(flags);
|
||||
}
|
||||
|
||||
void RegExpObject::initAndZeroLastIndex(JSAtom* source, RegExpFlag flags,
|
||||
void RegExpObject::initAndZeroLastIndex(JSAtom* source, RegExpFlags flags,
|
||||
JSContext* cx) {
|
||||
initIgnoringLastIndex(source, flags);
|
||||
zeroLastIndex(cx);
|
||||
|
@ -898,7 +902,7 @@ bool js::StringHasRegExpMetaChars(JSLinearString* str) {
|
|||
|
||||
/* RegExpShared */
|
||||
|
||||
RegExpShared::RegExpShared(JSAtom* source, RegExpFlag flags)
|
||||
RegExpShared::RegExpShared(JSAtom* source, RegExpFlags flags)
|
||||
: source(source), flags(flags), canStringMatch(false), parenCount(0) {}
|
||||
|
||||
void RegExpShared::traceChildren(JSTracer* trc) {
|
||||
|
@ -956,9 +960,7 @@ bool RegExpShared::compile(JSContext* cx, MutableHandleRegExpShared re,
|
|||
LifoAllocScope allocScope(&cx->tempLifoAlloc());
|
||||
irregexp::RegExpCompileData data;
|
||||
if (!irregexp::ParsePattern(dummyTokenStream, allocScope.alloc(), pattern,
|
||||
re->multiline(), mode == MatchOnly, re->unicode(),
|
||||
re->ignoreCase(), re->global(), re->sticky(),
|
||||
&data)) {
|
||||
mode == MatchOnly, re->getFlags(), &data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1250,7 +1252,7 @@ void RegExpRealm::sweep() {
|
|||
}
|
||||
|
||||
RegExpShared* RegExpZone::get(JSContext* cx, HandleAtom source,
|
||||
RegExpFlag flags) {
|
||||
RegExpFlags flags) {
|
||||
DependentAddPtr<Set> p(cx, set_, Key(source, flags));
|
||||
if (p) {
|
||||
return *p;
|
||||
|
@ -1272,7 +1274,7 @@ RegExpShared* RegExpZone::get(JSContext* cx, HandleAtom source,
|
|||
}
|
||||
|
||||
RegExpShared* RegExpZone::get(JSContext* cx, HandleAtom atom, JSString* opt) {
|
||||
RegExpFlag flags = RegExpFlag(0);
|
||||
RegExpFlags flags = RegExpFlag::NoFlags;
|
||||
if (opt && !ParseRegExpFlags(cx, opt, &flags)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1315,26 +1317,26 @@ JSObject* js::CloneRegExpObject(JSContext* cx, Handle<RegExpObject*> regex) {
|
|||
|
||||
template <typename CharT>
|
||||
static bool ParseRegExpFlags(const CharT* chars, size_t length,
|
||||
RegExpFlag* flagsOut, char16_t* invalidFlag) {
|
||||
*flagsOut = RegExpFlag(0);
|
||||
RegExpFlags* flagsOut, char16_t* invalidFlag) {
|
||||
*flagsOut = RegExpFlag::NoFlags;
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
RegExpFlag flag;
|
||||
uint8_t flag;
|
||||
switch (chars[i]) {
|
||||
case 'i':
|
||||
flag = IgnoreCaseFlag;
|
||||
break;
|
||||
case 'g':
|
||||
flag = GlobalFlag;
|
||||
flag = RegExpFlag::Global;
|
||||
break;
|
||||
case 'i':
|
||||
flag = RegExpFlag::IgnoreCase;
|
||||
break;
|
||||
case 'm':
|
||||
flag = MultilineFlag;
|
||||
break;
|
||||
case 'y':
|
||||
flag = StickyFlag;
|
||||
flag = RegExpFlag::Multiline;
|
||||
break;
|
||||
case 'u':
|
||||
flag = UnicodeFlag;
|
||||
flag = RegExpFlag::Unicode;
|
||||
break;
|
||||
case 'y':
|
||||
flag = RegExpFlag::Sticky;
|
||||
break;
|
||||
default:
|
||||
*invalidFlag = chars[i];
|
||||
|
@ -1344,14 +1346,14 @@ static bool ParseRegExpFlags(const CharT* chars, size_t length,
|
|||
*invalidFlag = chars[i];
|
||||
return false;
|
||||
}
|
||||
*flagsOut = RegExpFlag(*flagsOut | flag);
|
||||
*flagsOut |= flag;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool js::ParseRegExpFlags(JSContext* cx, JSString* flagStr,
|
||||
RegExpFlag* flagsOut) {
|
||||
RegExpFlags* flagsOut) {
|
||||
JSLinearString* linear = flagStr->ensureLinear(cx);
|
||||
if (!linear) {
|
||||
return false;
|
||||
|
@ -1391,19 +1393,19 @@ XDRResult js::XDRScriptRegExpObject(XDRState<mode>* xdr,
|
|||
/* NB: Keep this in sync with CloneScriptRegExpObject. */
|
||||
|
||||
RootedAtom source(xdr->cx());
|
||||
uint32_t flagsword = 0;
|
||||
uint8_t flags = 0;
|
||||
|
||||
if (mode == XDR_ENCODE) {
|
||||
MOZ_ASSERT(objp);
|
||||
RegExpObject& reobj = *objp;
|
||||
source = reobj.getSource();
|
||||
flagsword = reobj.getFlags();
|
||||
flags = reobj.getFlags().value();
|
||||
}
|
||||
MOZ_TRY(XDRAtom(xdr, &source));
|
||||
MOZ_TRY(xdr->codeUint32(&flagsword));
|
||||
MOZ_TRY(xdr->codeUint8(&flags));
|
||||
if (mode == XDR_DECODE) {
|
||||
RegExpObject* reobj = RegExpObject::create(
|
||||
xdr->cx(), source, RegExpFlag(flagsword), TenuredObject);
|
||||
xdr->cx(), source, RegExpFlags(flags), TenuredObject);
|
||||
if (!reobj) {
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
|
@ -1443,7 +1445,7 @@ JS::ubi::Node::Size JS::ubi::Concrete<RegExpShared>::size(
|
|||
* Regular Expressions.
|
||||
*/
|
||||
JS_PUBLIC_API JSObject* JS::NewRegExpObject(JSContext* cx, const char* bytes,
|
||||
size_t length, unsigned flags) {
|
||||
size_t length, RegExpFlags flags) {
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
|
||||
|
@ -1452,18 +1454,17 @@ JS_PUBLIC_API JSObject* JS::NewRegExpObject(JSContext* cx, const char* bytes,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return RegExpObject::create(cx, chars.get(), length, RegExpFlag(flags),
|
||||
GenericObject);
|
||||
return RegExpObject::create(cx, chars.get(), length, flags, GenericObject);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API JSObject* JS::NewUCRegExpObject(JSContext* cx,
|
||||
const char16_t* chars,
|
||||
size_t length, unsigned flags) {
|
||||
size_t length,
|
||||
RegExpFlags flags) {
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
|
||||
return RegExpObject::create(cx, chars, length, RegExpFlag(flags),
|
||||
GenericObject);
|
||||
return RegExpObject::create(cx, chars, length, flags, GenericObject);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API bool JS::SetRegExpInput(JSContext* cx, HandleObject obj,
|
||||
|
@ -1548,13 +1549,13 @@ JS_PUBLIC_API bool JS::ObjectIsRegExp(JSContext* cx, HandleObject obj,
|
|||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API unsigned JS::GetRegExpFlags(JSContext* cx, HandleObject obj) {
|
||||
JS_PUBLIC_API RegExpFlags JS::GetRegExpFlags(JSContext* cx, HandleObject obj) {
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
|
||||
RegExpShared* shared = RegExpToShared(cx, obj);
|
||||
if (!shared) {
|
||||
return false;
|
||||
return RegExpFlag::NoFlags;
|
||||
}
|
||||
return shared->getFlags();
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "builtin/SelfHostingDefines.h"
|
||||
#include "gc/Marking.h"
|
||||
#include "js/GCHashTable.h"
|
||||
#include "js/RegExpFlags.h"
|
||||
#include "proxy/Proxy.h"
|
||||
#include "vm/ArrayObject.h"
|
||||
#include "vm/JSContext.h"
|
||||
|
@ -70,19 +71,19 @@ class RegExpObject : public NativeObject {
|
|||
|
||||
template <typename CharT>
|
||||
static RegExpObject* create(JSContext* cx, const CharT* chars, size_t length,
|
||||
RegExpFlag flags, NewObjectKind newKind);
|
||||
JS::RegExpFlags flags, NewObjectKind newKind);
|
||||
|
||||
template <typename CharT>
|
||||
static RegExpObject* create(JSContext* cx, const CharT* chars, size_t length,
|
||||
RegExpFlag flags,
|
||||
JS::RegExpFlags flags,
|
||||
frontend::TokenStreamAnyChars& ts,
|
||||
NewObjectKind kind);
|
||||
|
||||
static RegExpObject* create(JSContext* cx, HandleAtom source,
|
||||
RegExpFlag flags, NewObjectKind newKind);
|
||||
JS::RegExpFlags flags, NewObjectKind newKind);
|
||||
|
||||
static RegExpObject* create(JSContext* cx, HandleAtom source,
|
||||
RegExpFlag flags,
|
||||
JS::RegExpFlags flags,
|
||||
frontend::TokenStreamAnyChars& ts,
|
||||
NewObjectKind newKind);
|
||||
|
||||
|
@ -131,18 +132,20 @@ class RegExpObject : public NativeObject {
|
|||
|
||||
static unsigned flagsSlot() { return FLAGS_SLOT; }
|
||||
|
||||
RegExpFlag getFlags() const {
|
||||
return RegExpFlag(getFixedSlot(FLAGS_SLOT).toInt32());
|
||||
JS::RegExpFlags getFlags() const {
|
||||
return JS::RegExpFlags(getFixedSlot(FLAGS_SLOT).toInt32());
|
||||
}
|
||||
void setFlags(JS::RegExpFlags flags) {
|
||||
setFixedSlot(FLAGS_SLOT, Int32Value(flags.value()));
|
||||
}
|
||||
void setFlags(RegExpFlag flags) { setSlot(FLAGS_SLOT, Int32Value(flags)); }
|
||||
|
||||
bool ignoreCase() const { return getFlags() & IgnoreCaseFlag; }
|
||||
bool global() const { return getFlags() & GlobalFlag; }
|
||||
bool multiline() const { return getFlags() & MultilineFlag; }
|
||||
bool sticky() const { return getFlags() & StickyFlag; }
|
||||
bool unicode() const { return getFlags() & UnicodeFlag; }
|
||||
bool global() const { return getFlags().global(); }
|
||||
bool ignoreCase() const { return getFlags().ignoreCase(); }
|
||||
bool multiline() const { return getFlags().multiline(); }
|
||||
bool unicode() const { return getFlags().unicode(); }
|
||||
bool sticky() const { return getFlags().sticky(); }
|
||||
|
||||
static bool isOriginalFlagGetter(JSNative native, RegExpFlag* mask);
|
||||
static bool isOriginalFlagGetter(JSNative native, JS::RegExpFlags* mask);
|
||||
|
||||
static RegExpShared* getShared(JSContext* cx, Handle<RegExpObject*> regexp);
|
||||
|
||||
|
@ -161,12 +164,13 @@ class RegExpObject : public NativeObject {
|
|||
static void trace(JSTracer* trc, JSObject* obj);
|
||||
void trace(JSTracer* trc);
|
||||
|
||||
void initIgnoringLastIndex(JSAtom* source, RegExpFlag flags);
|
||||
void initIgnoringLastIndex(JSAtom* source, JS::RegExpFlags flags);
|
||||
|
||||
// NOTE: This method is *only* safe to call on RegExps that haven't been
|
||||
// exposed to script, because it requires that the "lastIndex"
|
||||
// property be writable.
|
||||
void initAndZeroLastIndex(JSAtom* source, RegExpFlag flags, JSContext* cx);
|
||||
void initAndZeroLastIndex(JSAtom* source, JS::RegExpFlags flags,
|
||||
JSContext* cx);
|
||||
|
||||
#ifdef DEBUG
|
||||
static MOZ_MUST_USE bool dumpBytecode(JSContext* cx,
|
||||
|
@ -193,7 +197,8 @@ class RegExpObject : public NativeObject {
|
|||
*
|
||||
* N.B. flagStr must be rooted.
|
||||
*/
|
||||
bool ParseRegExpFlags(JSContext* cx, JSString* flagStr, RegExpFlag* flagsOut);
|
||||
bool ParseRegExpFlags(JSContext* cx, JSString* flagStr,
|
||||
JS::RegExpFlags* flagsOut);
|
||||
|
||||
// Assuming GetBuiltinClass(obj) is ESClass::RegExp, return a RegExpShared for
|
||||
// obj.
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "gc/Marking.h"
|
||||
#include "gc/Zone.h"
|
||||
#include "js/AllocPolicy.h"
|
||||
#include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags
|
||||
#include "js/UbiNode.h"
|
||||
#include "js/Vector.h"
|
||||
#include "vm/ArrayObject.h"
|
||||
|
@ -83,7 +84,7 @@ class RegExpShared : public gc::TenuredCell {
|
|||
/* Source to the RegExp, for lazy compilation. */
|
||||
GCPtr<JSAtom*> source;
|
||||
|
||||
RegExpFlag flags;
|
||||
JS::RegExpFlags flags;
|
||||
bool canStringMatch;
|
||||
size_t parenCount;
|
||||
|
||||
|
@ -103,7 +104,7 @@ class RegExpShared : public gc::TenuredCell {
|
|||
JitCodeTables tables;
|
||||
|
||||
/* Internal functions. */
|
||||
RegExpShared(JSAtom* source, RegExpFlag flags);
|
||||
RegExpShared(JSAtom* source, JS::RegExpFlags flags);
|
||||
|
||||
static bool compile(JSContext* cx, MutableHandleRegExpShared res,
|
||||
HandleLinearString input, CompilationMode mode,
|
||||
|
@ -148,12 +149,13 @@ class RegExpShared : public gc::TenuredCell {
|
|||
size_t pairCount() const { return getParenCount() + 1; }
|
||||
|
||||
JSAtom* getSource() const { return source; }
|
||||
RegExpFlag getFlags() const { return flags; }
|
||||
bool ignoreCase() const { return flags & IgnoreCaseFlag; }
|
||||
bool global() const { return flags & GlobalFlag; }
|
||||
bool multiline() const { return flags & MultilineFlag; }
|
||||
bool sticky() const { return flags & StickyFlag; }
|
||||
bool unicode() const { return flags & UnicodeFlag; }
|
||||
JS::RegExpFlags getFlags() const { return flags; }
|
||||
|
||||
bool global() const { return flags.global(); }
|
||||
bool ignoreCase() const { return flags.ignoreCase(); }
|
||||
bool multiline() const { return flags.multiline(); }
|
||||
bool unicode() const { return flags.unicode(); }
|
||||
bool sticky() const { return flags.sticky(); }
|
||||
|
||||
bool isCompiled(CompilationMode mode, bool latin1,
|
||||
ForceByteCodeEnum force = DontForceByteCode) const {
|
||||
|
@ -197,22 +199,22 @@ class RegExpShared : public gc::TenuredCell {
|
|||
|
||||
class RegExpZone {
|
||||
struct Key {
|
||||
JSAtom* atom;
|
||||
uint16_t flag;
|
||||
JSAtom* atom = nullptr;
|
||||
JS::RegExpFlags flags = JS::RegExpFlag::NoFlags;
|
||||
|
||||
Key() : atom(nullptr), flag(0) {}
|
||||
Key(JSAtom* atom, RegExpFlag flag) : atom(atom), flag(flag) {}
|
||||
Key() = default;
|
||||
Key(JSAtom* atom, JS::RegExpFlags flags) : atom(atom), flags(flags) {}
|
||||
MOZ_IMPLICIT Key(const ReadBarriered<RegExpShared*>& shared)
|
||||
: atom(shared.unbarrieredGet()->getSource()),
|
||||
flag(shared.unbarrieredGet()->getFlags()) {}
|
||||
flags(shared.unbarrieredGet()->getFlags()) {}
|
||||
|
||||
typedef Key Lookup;
|
||||
static HashNumber hash(const Lookup& l) {
|
||||
HashNumber hash = DefaultHasher<JSAtom*>::hash(l.atom);
|
||||
return mozilla::AddToHash(hash, l.flag);
|
||||
return mozilla::AddToHash(hash, l.flags.value());
|
||||
}
|
||||
static bool match(Key l, Key r) {
|
||||
return l.atom == r.atom && l.flag == r.flag;
|
||||
return l.atom == r.atom && l.flags == r.flags;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -231,12 +233,12 @@ class RegExpZone {
|
|||
|
||||
bool empty() const { return set_.empty(); }
|
||||
|
||||
RegExpShared* maybeGet(JSAtom* source, RegExpFlag flags) const {
|
||||
RegExpShared* maybeGet(JSAtom* source, JS::RegExpFlags flags) const {
|
||||
Set::Ptr p = set_.lookup(Key(source, flags));
|
||||
return p ? *p : nullptr;
|
||||
}
|
||||
|
||||
RegExpShared* get(JSContext* cx, HandleAtom source, RegExpFlag flags);
|
||||
RegExpShared* get(JSContext* cx, HandleAtom source, JS::RegExpFlags flags);
|
||||
|
||||
/* Like 'get', but compile 'maybeOpt' (if non-null). */
|
||||
RegExpShared* get(JSContext* cx, HandleAtom source, JSString* maybeOpt);
|
||||
|
|
|
@ -29,7 +29,7 @@ class RegExpStatics {
|
|||
* a different compartment via evalcx().
|
||||
*/
|
||||
HeapPtr<JSAtom*> lazySource;
|
||||
RegExpFlag lazyFlags;
|
||||
JS::RegExpFlags lazyFlags;
|
||||
size_t lazyIndex;
|
||||
|
||||
/* The latest RegExp input, set before execution. */
|
||||
|
@ -274,7 +274,7 @@ inline void RegExpStatics::clear() {
|
|||
matches.forgetArray();
|
||||
matchesInput = nullptr;
|
||||
lazySource = nullptr;
|
||||
lazyFlags = RegExpFlag(0);
|
||||
lazyFlags = JS::RegExpFlag::NoFlags;
|
||||
lazyIndex = size_t(-1);
|
||||
pendingInput = nullptr;
|
||||
pendingLazyEvaluation = false;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "js/StructuredClone.h"
|
||||
|
||||
#include "mozilla/Casting.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/EndianUtils.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
@ -46,6 +47,7 @@
|
|||
#include "js/ArrayBuffer.h" // JS::{ArrayBufferHasData,DetachArrayBuffer,IsArrayBufferObject,New{,Mapped}ArrayBufferWithContents,ReleaseMappedArrayBufferContents}
|
||||
#include "js/Date.h"
|
||||
#include "js/GCHashTable.h"
|
||||
#include "js/RegExpFlags.h" // JS::RegExpFlags
|
||||
#include "js/SharedArrayBuffer.h" // JS::IsSharedArrayBufferObject
|
||||
#include "js/Wrapper.h"
|
||||
#include "vm/BigIntType.h"
|
||||
|
@ -64,7 +66,9 @@
|
|||
using namespace js;
|
||||
|
||||
using JS::CanonicalizeNaN;
|
||||
using JS::RegExpFlags;
|
||||
using JS::RootedValueVector;
|
||||
using mozilla::AssertedCast;
|
||||
using mozilla::BitwiseCast;
|
||||
using mozilla::NativeEndian;
|
||||
using mozilla::NumbersAreIdentical;
|
||||
|
@ -1669,7 +1673,7 @@ bool JSStructuredCloneWriter::startWrite(HandleValue v) {
|
|||
if (!re) {
|
||||
return false;
|
||||
}
|
||||
return out.writePair(SCTAG_REGEXP_OBJECT, re->getFlags()) &&
|
||||
return out.writePair(SCTAG_REGEXP_OBJECT, re->getFlags().value()) &&
|
||||
writeString(SCTAG_STRING, re->getSource());
|
||||
}
|
||||
case ESClass::ArrayBuffer: {
|
||||
|
@ -2448,7 +2452,7 @@ bool JSStructuredCloneReader::startRead(MutableHandleValue vp) {
|
|||
}
|
||||
|
||||
case SCTAG_REGEXP_OBJECT: {
|
||||
RegExpFlag flags = RegExpFlag(data);
|
||||
RegExpFlags flags = AssertedCast<uint8_t>(data);
|
||||
uint32_t tag2, stringData;
|
||||
if (!in.readPair(&tag2, &stringData)) {
|
||||
return false;
|
||||
|
|
Загрузка…
Ссылка в новой задаче