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:
Jeff Walden 2019-04-02 03:16:43 +00:00
Родитель 5d1c793bad
Коммит feb28d4555
25 изменённых файлов: 382 добавлений и 237 удалений

Просмотреть файл

@ -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

124
js/public/RegExpFlags.h Normal file
Просмотреть файл

@ -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;