Title: [242699] trunk
Revision
242699
Author
[email protected]
Date
2019-03-10 23:20:53 -0700 (Sun, 10 Mar 2019)

Log Message

Invalid flags in a RegExp literal should be an early SyntaxError
https://bugs.webkit.org/show_bug.cgi?id=195514

Reviewed by Darin Adler.

JSTests:

* test262/expectations.yaml:
Mark 4 test cases as passing.

* stress/regexp-syntax-error-invalid-flags.js:
* stress/regress-161995.js: Removed.
Update existing test, merging in an older test for the same behavior.

Source/_javascript_Core:

Currently we're throwing a *runtime* SyntaxError; this should occur at parse time.

  12.2.8.1 Static Semantics: Early Errors
    PrimaryExpression : RegularExpressionLiteral
      - It is a Syntax Error if BodyText of RegularExpressionLiteral cannot be recognized
        using the goal symbol Pattern of the ECMAScript RegExp grammar specified in 21.2.1.
      - It is a Syntax Error if FlagText of RegularExpressionLiteral contains any code points
        other than "g", "i", "m",  "s", "u", or "y", or if it contains the same code point more than once.

In fixing this, let's also move flag handling from runtime/ to yarr/.

* yarr/YarrSyntaxChecker.cpp:
(JSC::Yarr::checkSyntax):
Check flags before checking pattern.

* CMakeLists.txt:
* _javascript_Core.xcodeproj/project.pbxproj:
* Sources.txt:
* bytecompiler/NodesCodegen.cpp:
(JSC::RegExpNode::emitBytecode):
* inspector/ContentSearchUtilities.cpp:
(Inspector::ContentSearchUtilities::findMagicComment):
* runtime/CachedTypes.cpp:
* runtime/RegExp.cpp:
(JSC::RegExp::RegExp):
(JSC::RegExp::createWithoutCaching):
(JSC::RegExp::create):
(JSC::regExpFlags): Deleted.
* runtime/RegExp.h:
* runtime/RegExpCache.cpp:
(JSC::RegExpCache::lookupOrCreate):
(JSC::RegExpCache::ensureEmptyRegExpSlow):
* runtime/RegExpCache.h:
* runtime/RegExpConstructor.cpp:
(JSC::toFlags):
(JSC::regExpCreate):
(JSC::constructRegExp):
* runtime/RegExpKey.h:
(JSC::RegExpKey::RegExpKey):
(WTF::HashTraits<JSC::RegExpKey>::constructDeletedValue):
(WTF::HashTraits<JSC::RegExpKey>::isDeletedValue):
(): Deleted.
* runtime/RegExpPrototype.cpp:
(JSC::regExpProtoFuncCompile):
* testRegExp.cpp:
(parseRegExpLine):
* yarr/RegularExpression.cpp:
(JSC::Yarr::RegularExpression::Private::compile):
* yarr/YarrFlags.cpp: Added.
(JSC::Yarr::parseFlags):
* yarr/YarrFlags.h: Added.
* yarr/YarrInterpreter.h:
(JSC::Yarr::BytecodePattern::ignoreCase const):
(JSC::Yarr::BytecodePattern::multiline const):
(JSC::Yarr::BytecodePattern::sticky const):
(JSC::Yarr::BytecodePattern::unicode const):
(JSC::Yarr::BytecodePattern::dotAll const):
* yarr/YarrPattern.cpp:
(JSC::Yarr::YarrPattern::compile):
(JSC::Yarr::YarrPattern::YarrPattern):
(JSC::Yarr::YarrPattern::dumpPattern):
* yarr/YarrPattern.h:
(JSC::Yarr::YarrPattern::global const):
(JSC::Yarr::YarrPattern::ignoreCase const):
(JSC::Yarr::YarrPattern::multiline const):
(JSC::Yarr::YarrPattern::sticky const):
(JSC::Yarr::YarrPattern::unicode const):
(JSC::Yarr::YarrPattern::dotAll const):
Move flag handling to Yarr and modernize API.

Source/WebCore:

* bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneDeserializer::readTerminal):
Consume YarrFlags.

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/JSTests/ChangeLog (242698 => 242699)


--- trunk/JSTests/ChangeLog	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/JSTests/ChangeLog	2019-03-11 06:20:53 UTC (rev 242699)
@@ -1,3 +1,17 @@
+2019-03-10  Ross Kirsling  <[email protected]>
+
+        Invalid flags in a RegExp literal should be an early SyntaxError
+        https://bugs.webkit.org/show_bug.cgi?id=195514
+
+        Reviewed by Darin Adler.
+
+        * test262/expectations.yaml:
+        Mark 4 test cases as passing.
+
+        * stress/regexp-syntax-error-invalid-flags.js:
+        * stress/regress-161995.js: Removed.
+        Update existing test, merging in an older test for the same behavior.
+
 2019-03-08  Mark Lam  <[email protected]>
 
         Stack overflow crash in JSC::JSObject::hasInstance.

Modified: trunk/JSTests/stress/regexp-syntax-error-invalid-flags.js (242698 => 242699)


--- trunk/JSTests/stress/regexp-syntax-error-invalid-flags.js	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/JSTests/stress/regexp-syntax-error-invalid-flags.js	2019-03-11 06:20:53 UTC (rev 242699)
@@ -1,23 +1,17 @@
-function shouldThrow(func, errorMessage) {
-    var errorThrown = false;
-    var error = null;
+function shouldThrowSyntaxError(script) {
+    let error;
     try {
-        func();
+        eval(script);
     } catch (e) {
-        errorThrown = true;
         error = e;
     }
-    if (!errorThrown)
+
+    if (!error)
         throw new Error('not thrown');
-    if (String(error) !== errorMessage)
+    if (String(error) !== 'SyntaxError: Invalid regular _expression_: invalid flags')
         throw new Error(`bad error: ${String(error)}`);
 }
 
-function test()
-{
-    return /Hello/cocoa;
-}
-noInline(test);
-
-for (var i = 0; i < 1e4; ++i)
-    shouldThrow(test, `SyntaxError: Invalid regular _expression_: invalid flags`);
+shouldThrowSyntaxError('/Hello/cocoa');
+shouldThrowSyntaxError('/a/Z');
+shouldThrowSyntaxError('/./ii');

Deleted: trunk/JSTests/stress/regress-161995.js (242698 => 242699)


--- trunk/JSTests/stress/regress-161995.js	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/JSTests/stress/regress-161995.js	2019-03-11 06:20:53 UTC (rev 242699)
@@ -1,14 +0,0 @@
-// Regression test for 161995.
-
-function testStatic()
-{
-    return /a/Z;
-}
-
-try {
-    testStatic();
-    throw "Expected a SyntaxEerror for bad RegExp flags, but didn't get one.";
-} catch(e) {
-    if (e != "SyntaxError: Invalid regular _expression_: invalid flags")
-        throw "Incorrect exception for bad RegExp flags.  Got: " + e;
-}

Modified: trunk/JSTests/test262/expectations.yaml (242698 => 242699)


--- trunk/JSTests/test262/expectations.yaml	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/JSTests/test262/expectations.yaml	2019-03-11 06:20:53 UTC (rev 242699)
@@ -2396,12 +2396,6 @@
 test/language/literals/numeric/numeric-separator-literal-sign-plus-dds-nsl-dd.js:
   default: 'SyntaxError: No identifiers allowed directly after numeric literal'
   strict mode: 'SyntaxError: No identifiers allowed directly after numeric literal'
-test/language/literals/regexp/early-err-bad-flag.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
-test/language/literals/regexp/early-err-dup-flag.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
 test/language/literals/regexp/named-groups/invalid-dangling-groupname-2-u.js:
   default: 'Test262: This statement should not be evaluated.'
   strict mode: 'Test262: This statement should not be evaluated.'

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (242698 => 242699)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2019-03-11 06:20:53 UTC (rev 242699)
@@ -1000,6 +1000,7 @@
     yarr/RegularExpression.h
     yarr/Yarr.h
     yarr/YarrErrorCode.h
+    yarr/YarrFlags.h
     yarr/YarrInterpreter.h
     yarr/YarrJIT.h
     yarr/YarrParser.h

Modified: trunk/Source/_javascript_Core/ChangeLog (242698 => 242699)


--- trunk/Source/_javascript_Core/ChangeLog	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/Source/_javascript_Core/ChangeLog	2019-03-11 06:20:53 UTC (rev 242699)
@@ -1,3 +1,80 @@
+2019-03-10  Ross Kirsling  <[email protected]>
+
+        Invalid flags in a RegExp literal should be an early SyntaxError
+        https://bugs.webkit.org/show_bug.cgi?id=195514
+
+        Reviewed by Darin Adler.
+
+        Currently we're throwing a *runtime* SyntaxError; this should occur at parse time. 
+
+          12.2.8.1 Static Semantics: Early Errors
+            PrimaryExpression : RegularExpressionLiteral
+              - It is a Syntax Error if BodyText of RegularExpressionLiteral cannot be recognized
+                using the goal symbol Pattern of the ECMAScript RegExp grammar specified in 21.2.1.
+              - It is a Syntax Error if FlagText of RegularExpressionLiteral contains any code points
+                other than "g", "i", "m",  "s", "u", or "y", or if it contains the same code point more than once.
+
+        In fixing this, let's also move flag handling from runtime/ to yarr/.
+
+        * yarr/YarrSyntaxChecker.cpp:
+        (JSC::Yarr::checkSyntax):
+        Check flags before checking pattern.
+
+        * CMakeLists.txt:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * Sources.txt:
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::RegExpNode::emitBytecode):
+        * inspector/ContentSearchUtilities.cpp:
+        (Inspector::ContentSearchUtilities::findMagicComment):
+        * runtime/CachedTypes.cpp:
+        * runtime/RegExp.cpp:
+        (JSC::RegExp::RegExp):
+        (JSC::RegExp::createWithoutCaching):
+        (JSC::RegExp::create):
+        (JSC::regExpFlags): Deleted.
+        * runtime/RegExp.h:
+        * runtime/RegExpCache.cpp:
+        (JSC::RegExpCache::lookupOrCreate):
+        (JSC::RegExpCache::ensureEmptyRegExpSlow):
+        * runtime/RegExpCache.h:
+        * runtime/RegExpConstructor.cpp:
+        (JSC::toFlags):
+        (JSC::regExpCreate):
+        (JSC::constructRegExp):
+        * runtime/RegExpKey.h:
+        (JSC::RegExpKey::RegExpKey):
+        (WTF::HashTraits<JSC::RegExpKey>::constructDeletedValue):
+        (WTF::HashTraits<JSC::RegExpKey>::isDeletedValue):
+        (): Deleted.
+        * runtime/RegExpPrototype.cpp:
+        (JSC::regExpProtoFuncCompile):
+        * testRegExp.cpp:
+        (parseRegExpLine):
+        * yarr/RegularExpression.cpp:
+        (JSC::Yarr::RegularExpression::Private::compile):
+        * yarr/YarrFlags.cpp: Added.
+        (JSC::Yarr::parseFlags):
+        * yarr/YarrFlags.h: Added.
+        * yarr/YarrInterpreter.h:
+        (JSC::Yarr::BytecodePattern::ignoreCase const):
+        (JSC::Yarr::BytecodePattern::multiline const):
+        (JSC::Yarr::BytecodePattern::sticky const):
+        (JSC::Yarr::BytecodePattern::unicode const):
+        (JSC::Yarr::BytecodePattern::dotAll const):
+        * yarr/YarrPattern.cpp:
+        (JSC::Yarr::YarrPattern::compile):
+        (JSC::Yarr::YarrPattern::YarrPattern):
+        (JSC::Yarr::YarrPattern::dumpPattern):
+        * yarr/YarrPattern.h:
+        (JSC::Yarr::YarrPattern::global const):
+        (JSC::Yarr::YarrPattern::ignoreCase const):
+        (JSC::Yarr::YarrPattern::multiline const):
+        (JSC::Yarr::YarrPattern::sticky const):
+        (JSC::Yarr::YarrPattern::unicode const):
+        (JSC::Yarr::YarrPattern::dotAll const):
+        Move flag handling to Yarr and modernize API.
+
 2019-03-09  Robin Morisset  <[email protected]>
 
         Compilation can be shrunk by 8 bytes

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (242698 => 242699)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2019-03-11 06:20:53 UTC (rev 242699)
@@ -1339,6 +1339,7 @@
 		A1D792FD1B43864B004516F5 /* IntlNumberFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = A1D792F71B43864B004516F5 /* IntlNumberFormat.h */; };
 		A1D792FF1B43864B004516F5 /* IntlNumberFormatConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = A1D792F91B43864B004516F5 /* IntlNumberFormatConstructor.h */; };
 		A1D793011B43864B004516F5 /* IntlNumberFormatPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = A1D792FB1B43864B004516F5 /* IntlNumberFormatPrototype.h */; };
+		A3FF9BC72234749100B1A9AB /* YarrFlags.h in Headers */ = {isa = PBXBuildFile; fileRef = A3FF9BC52234746600B1A9AB /* YarrFlags.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		A503FA1A188E0FB000110F14 /* _javascript_CallFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = A503FA14188E0FAF00110F14 /* _javascript_CallFrame.h */; };
 		A503FA1E188E0FB000110F14 /* JSJavaScriptCallFramePrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = A503FA18188E0FB000110F14 /* JSJavaScriptCallFramePrototype.h */; };
 		A503FA21188EFF6800110F14 /* ScriptBreakpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = A503FA1F188EFF6800110F14 /* ScriptBreakpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -4086,6 +4087,8 @@
 		A1E0451B1C25B4B100BB663C /* StringPrototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; path = StringPrototype.js; sourceTree = "<group>"; };
 		A1FE1EB01C2C537E00A289FF /* DatePrototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; path = DatePrototype.js; sourceTree = "<group>"; };
 		A27958D7FA1142B0AC9E364D /* WasmContextInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmContextInlines.h; sourceTree = "<group>"; };
+		A3FF9BC52234746600B1A9AB /* YarrFlags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = YarrFlags.h; path = yarr/YarrFlags.h; sourceTree = "<group>"; };
+		A3FF9BC62234746600B1A9AB /* YarrFlags.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = YarrFlags.cpp; path = yarr/YarrFlags.cpp; sourceTree = "<group>"; };
 		A503FA13188E0FAF00110F14 /* _javascript_CallFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = _javascript_CallFrame.cpp; sourceTree = "<group>"; };
 		A503FA14188E0FAF00110F14 /* _javascript_CallFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _javascript_CallFrame.h; sourceTree = "<group>"; };
 		A503FA15188E0FB000110F14 /* JSJavaScriptCallFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSJavaScriptCallFrame.cpp; sourceTree = "<group>"; };
@@ -7303,6 +7306,8 @@
 				65C6BEE021128C3B006849C3 /* YarrDisassembler.h */,
 				E3282BB91FE930A300EDAF71 /* YarrErrorCode.cpp */,
 				E3282BBA1FE930A400EDAF71 /* YarrErrorCode.h */,
+				A3FF9BC62234746600B1A9AB /* YarrFlags.cpp */,
+				A3FF9BC52234746600B1A9AB /* YarrFlags.h */,
 				86704B7D12DBA33700A9FE7B /* YarrInterpreter.cpp */,
 				86704B7E12DBA33700A9FE7B /* YarrInterpreter.h */,
 				86704B7F12DBA33700A9FE7B /* YarrJIT.cpp */,
@@ -9896,6 +9901,7 @@
 				9959E92E1BD17FA4001AA413 /* xxd.pl in Headers */,
 				451539B912DC994500EF7AC4 /* Yarr.h in Headers */,
 				E3282BBB1FE930AF00EDAF71 /* YarrErrorCode.h in Headers */,
+				A3FF9BC72234749100B1A9AB /* YarrFlags.h in Headers */,
 				86704B8512DBA33700A9FE7B /* YarrInterpreter.h in Headers */,
 				86704B8712DBA33700A9FE7B /* YarrJIT.h in Headers */,
 				86704B8812DBA33700A9FE7B /* YarrParser.h in Headers */,

Modified: trunk/Source/_javascript_Core/Sources.txt (242698 => 242699)


--- trunk/Source/_javascript_Core/Sources.txt	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/Source/_javascript_Core/Sources.txt	2019-03-11 06:20:53 UTC (rev 242699)
@@ -1045,6 +1045,7 @@
 yarr/YarrCanonicalizeUCS2.cpp
 yarr/YarrDisassembler.cpp
 yarr/YarrErrorCode.cpp
+yarr/YarrFlags.cpp
 yarr/YarrInterpreter.cpp
 yarr/YarrJIT.cpp
 yarr/YarrPattern.cpp

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (242698 => 242699)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2019-03-11 06:20:53 UTC (rev 242699)
@@ -41,6 +41,7 @@
 #include "Lexer.h"
 #include "Parser.h"
 #include "StackAlignment.h"
+#include "YarrFlags.h"
 #include <wtf/Assertions.h>
 #include <wtf/Threading.h>
 #include <wtf/text/StringBuilder.h>
@@ -141,9 +142,13 @@
 {
     if (dst == generator.ignoredResult())
         return nullptr;
-    RegExp* regExp = RegExp::create(*generator.vm(), m_pattern.string(), regExpFlags(m_flags.string()));
+
+    auto flags = Yarr::parseFlags(m_flags.string());
+    ASSERT(flags.hasValue());
+    RegExp* regExp = RegExp::create(*generator.vm(), m_pattern.string(), flags.value());
     if (regExp->isValid())
         return generator.emitNewRegExp(generator.finalDestination(dst), regExp);
+
     const char* messageCharacters = regExp->errorMessage();
     const Identifier& message = generator.parserArena().identifierArena().makeIdentifier(generator.vm(), bitwise_cast<const LChar*>(messageCharacters), strlen(messageCharacters));
     generator.emitThrowStaticError(ErrorType::SyntaxError, message);

Modified: trunk/Source/_javascript_Core/inspector/ContentSearchUtilities.cpp (242698 => 242699)


--- trunk/Source/_javascript_Core/inspector/ContentSearchUtilities.cpp	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/Source/_javascript_Core/inspector/ContentSearchUtilities.cpp	2019-03-11 06:20:53 UTC (rev 242699)
@@ -31,6 +31,7 @@
 
 #include "RegularExpression.h"
 #include "Yarr.h"
+#include "YarrFlags.h"
 #include "YarrInterpreter.h"
 #include <wtf/BumpPointerAllocator.h>
 #include <wtf/StdLibExtras.h>
@@ -167,7 +168,7 @@
         return String();
 
     JSC::Yarr::ErrorCode error { JSC::Yarr::ErrorCode::NoError };
-    YarrPattern pattern(patternString, JSC::RegExpFlags::FlagMultiline, error);
+    YarrPattern pattern(patternString, JSC::Yarr::Flags::Multiline, error);
     ASSERT(!hasError(error));
     BumpPointerAllocator regexAllocator;
     auto bytecodePattern = byteCompile(pattern, &regexAllocator);

Modified: trunk/Source/_javascript_Core/runtime/CachedTypes.cpp (242698 => 242699)


--- trunk/Source/_javascript_Core/runtime/CachedTypes.cpp	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/Source/_javascript_Core/runtime/CachedTypes.cpp	2019-03-11 06:20:53 UTC (rev 242699)
@@ -28,7 +28,6 @@
 
 #include "BytecodeCacheVersion.h"
 #include "BytecodeLivenessAnalysis.h"
-#include "JSCast.h"
 #include "JSImmutableButterfly.h"
 #include "JSTemplateObjectDescriptor.h"
 #include "ScopedArgumentsTable.h"
@@ -40,7 +39,6 @@
 #include "UnlinkedModuleProgramCodeBlock.h"
 #include "UnlinkedProgramCodeBlock.h"
 #include <wtf/FastMalloc.h>
-#include <wtf/Forward.h>
 #include <wtf/Optional.h>
 #include <wtf/UUID.h>
 #include <wtf/text/AtomicStringImpl.h>
@@ -47,6 +45,10 @@
 
 namespace JSC {
 
+namespace Yarr {
+enum class Flags : uint8_t;
+}
+
 template <typename T, typename = void>
 struct SourceTypeImpl {
     using type = T;
@@ -1111,7 +1113,7 @@
 
 private:
     CachedString m_patternString;
-    RegExpFlags m_flags;
+    OptionSet<Yarr::Flags> m_flags;
 };
 
 class CachedTemplateObjectDescriptor : public CachedObject<TemplateObjectDescriptor> {

Modified: trunk/Source/_javascript_Core/runtime/RegExp.cpp (242698 => 242699)


--- trunk/Source/_javascript_Core/runtime/RegExp.cpp	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/Source/_javascript_Core/runtime/RegExp.cpp	2019-03-11 06:20:53 UTC (rev 242699)
@@ -28,7 +28,6 @@
 #include "JSCInlines.h"
 #include "RegExpCache.h"
 #include "RegExpInlines.h"
-#include "Yarr.h"
 #include "YarrJIT.h"
 #include <wtf/Assertions.h>
 
@@ -36,56 +35,6 @@
 
 const ClassInfo RegExp::s_info = { "RegExp", nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(RegExp) };
 
-RegExpFlags regExpFlags(const String& string)
-{
-    RegExpFlags flags = NoFlags;
-
-    for (unsigned i = 0; i < string.length(); ++i) {
-        switch (string[i]) {
-        case 'g':
-            if (flags & FlagGlobal)
-                return InvalidFlags;
-            flags = static_cast<RegExpFlags>(flags | FlagGlobal);
-            break;
-
-        case 'i':
-            if (flags & FlagIgnoreCase)
-                return InvalidFlags;
-            flags = static_cast<RegExpFlags>(flags | FlagIgnoreCase);
-            break;
-
-        case 'm':
-            if (flags & FlagMultiline)
-                return InvalidFlags;
-            flags = static_cast<RegExpFlags>(flags | FlagMultiline);
-            break;
-
-        case 's':
-            if (flags & FlagDotAll)
-                return InvalidFlags;
-            flags = static_cast<RegExpFlags>(flags | FlagDotAll);
-            break;
-            
-        case 'u':
-            if (flags & FlagUnicode)
-                return InvalidFlags;
-            flags = static_cast<RegExpFlags>(flags | FlagUnicode);
-            break;
-                
-        case 'y':
-            if (flags & FlagSticky)
-                return InvalidFlags;
-            flags = static_cast<RegExpFlags>(flags | FlagSticky);
-            break;
-
-        default:
-            return InvalidFlags;
-        }
-    }
-
-    return flags;
-}
-
 #if REGEXP_FUNC_TEST_DATA_GEN
 const char* const RegExpFunctionalTestCollector::s_fileName = "/tmp/RegExpTestsData";
 RegExpFunctionalTestCollector* RegExpFunctionalTestCollector::s_instance = 0;
@@ -210,11 +159,12 @@
 }
 #endif
 
-RegExp::RegExp(VM& vm, const String& patternString, RegExpFlags flags)
+RegExp::RegExp(VM& vm, const String& patternString, OptionSet<Yarr::Flags> flags)
     : JSCell(vm, vm.regExpStructure.get())
     , m_patternString(patternString)
     , m_flags(flags)
 {
+    ASSERT(m_flags != Yarr::Flags::DeletedValue);
 }
 
 void RegExp::finishCreation(VM& vm)
@@ -249,7 +199,7 @@
     return Base::estimatedSize(cell, vm) + regexDataSize;
 }
 
-RegExp* RegExp::createWithoutCaching(VM& vm, const String& patternString, RegExpFlags flags)
+RegExp* RegExp::createWithoutCaching(VM& vm, const String& patternString, OptionSet<Yarr::Flags> flags)
 {
     RegExp* regExp = new (NotNull, allocateCell<RegExp>(vm.heap)) RegExp(vm, patternString, flags);
     regExp->finishCreation(vm);
@@ -256,7 +206,7 @@
     return regExp;
 }
 
-RegExp* RegExp::create(VM& vm, const String& patternString, RegExpFlags flags)
+RegExp* RegExp::create(VM& vm, const String& patternString, OptionSet<Yarr::Flags> flags)
 {
     return vm.regExpCache()->lookupOrCreate(patternString, flags);
 }

Modified: trunk/Source/_javascript_Core/runtime/RegExp.h (242698 => 242699)


--- trunk/Source/_javascript_Core/runtime/RegExp.h	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/Source/_javascript_Core/runtime/RegExp.h	2019-03-11 06:20:53 UTC (rev 242699)
@@ -38,8 +38,6 @@
 struct RegExpRepresentation;
 class VM;
 
-JS_EXPORT_PRIVATE RegExpFlags regExpFlags(const String&);
-
 class RegExp final : public JSCell {
     friend class CachedRegExp;
 
@@ -47,23 +45,23 @@
     typedef JSCell Base;
     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
 
-    JS_EXPORT_PRIVATE static RegExp* create(VM&, const String& pattern, RegExpFlags);
+    JS_EXPORT_PRIVATE static RegExp* create(VM&, const String& pattern, OptionSet<Yarr::Flags>);
     static const bool needsDestruction = true;
     static void destroy(JSCell*);
     static size_t estimatedSize(JSCell*, VM&);
     JS_EXPORT_PRIVATE static void dumpToStream(const JSCell*, PrintStream&);
 
-    bool global() const { return m_flags & FlagGlobal; }
-    bool ignoreCase() const { return m_flags & FlagIgnoreCase; }
-    bool multiline() const { return m_flags & FlagMultiline; }
-    bool sticky() const { return m_flags & FlagSticky; }
+    bool global() const { return m_flags.contains(Yarr::Flags::Global); }
+    bool ignoreCase() const { return m_flags.contains(Yarr::Flags::IgnoreCase); }
+    bool multiline() const { return m_flags.contains(Yarr::Flags::Multiline); }
+    bool sticky() const { return m_flags.contains(Yarr::Flags::Sticky); }
     bool globalOrSticky() const { return global() || sticky(); }
-    bool unicode() const { return m_flags & FlagUnicode; }
-    bool dotAll() const { return m_flags & FlagDotAll; }
+    bool unicode() const { return m_flags.contains(Yarr::Flags::Unicode); }
+    bool dotAll() const { return m_flags.contains(Yarr::Flags::DotAll); }
 
     const String& pattern() const { return m_patternString; }
 
-    bool isValid() const { return !Yarr::hasError(m_constructionErrorCode) && m_flags != InvalidFlags; }
+    bool isValid() const { return !Yarr::hasError(m_constructionErrorCode); }
     const char* errorMessage() const { return Yarr::errorMessage(m_constructionErrorCode); }
     JSObject* errorToThrow(ExecState* exec) { return Yarr::errorToThrow(exec, m_constructionErrorCode); }
     void reset()
@@ -136,9 +134,9 @@
 
 private:
     friend class RegExpCache;
-    RegExp(VM&, const String&, RegExpFlags);
+    RegExp(VM&, const String&, OptionSet<Yarr::Flags>);
 
-    static RegExp* createWithoutCaching(VM&, const String&, RegExpFlags);
+    static RegExp* createWithoutCaching(VM&, const String&, OptionSet<Yarr::Flags>);
 
     enum RegExpState : uint8_t {
         ParseError,
@@ -161,7 +159,7 @@
 
     String m_patternString;
     RegExpState m_state { NotCompiled };
-    RegExpFlags m_flags;
+    OptionSet<Yarr::Flags> m_flags;
     ConcurrentJSLock m_lock;
     Yarr::ErrorCode m_constructionErrorCode { Yarr::ErrorCode::NoError };
     unsigned m_numSubpatterns { 0 };

Modified: trunk/Source/_javascript_Core/runtime/RegExpCache.cpp (242698 => 242699)


--- trunk/Source/_javascript_Core/runtime/RegExpCache.cpp	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/Source/_javascript_Core/runtime/RegExpCache.cpp	2019-03-11 06:20:53 UTC (rev 242699)
@@ -35,7 +35,7 @@
 
 namespace JSC {
 
-RegExp* RegExpCache::lookupOrCreate(const String& patternString, RegExpFlags flags)
+RegExp* RegExpCache::lookupOrCreate(const String& patternString, OptionSet<Yarr::Flags> flags)
 {
     RegExpKey key(flags, patternString);
     if (RegExp* regExp = m_weakCache.get(key))
@@ -58,7 +58,7 @@
 
 RegExp* RegExpCache::ensureEmptyRegExpSlow(VM& vm)
 {
-    RegExp* regExp = RegExp::create(vm, "", NoFlags);
+    RegExp* regExp = RegExp::create(vm, "", { });
     m_emptyRegExp.set(vm, regExp);
     return regExp;
 }

Modified: trunk/Source/_javascript_Core/runtime/RegExpCache.h (242698 => 242699)


--- trunk/Source/_javascript_Core/runtime/RegExpCache.h	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/Source/_javascript_Core/runtime/RegExpCache.h	2019-03-11 06:20:53 UTC (rev 242699)
@@ -36,6 +36,10 @@
 
 namespace JSC {
 
+namespace Yarr {
+enum class Flags : uint8_t;
+}
+
 class RegExpCache : private WeakHandleOwner {
     WTF_MAKE_FAST_ALLOCATED;
 
@@ -63,7 +67,7 @@
 
     RegExp* ensureEmptyRegExpSlow(VM&);
 
-    RegExp* lookupOrCreate(const WTF::String& patternString, RegExpFlags);
+    RegExp* lookupOrCreate(const WTF::String& patternString, OptionSet<Yarr::Flags>);
     void addToStrongCache(RegExp*);
     RegExpCacheMap m_weakCache; // Holds all regular expressions currently live.
     int m_nextEntryInStrongCache;

Modified: trunk/Source/_javascript_Core/runtime/RegExpConstructor.cpp (242698 => 242699)


--- trunk/Source/_javascript_Core/runtime/RegExpConstructor.cpp	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/Source/_javascript_Core/runtime/RegExpConstructor.cpp	2019-03-11 06:20:53 UTC (rev 242699)
@@ -24,10 +24,10 @@
 
 #include "Error.h"
 #include "GetterSetter.h"
-#include "JSCInlines.h"
 #include "RegExpGlobalDataInlines.h"
 #include "RegExpPrototype.h"
 #include "StructureInlines.h"
+#include "YarrFlags.h"
 
 namespace JSC {
 
@@ -177,23 +177,22 @@
     return structure;
 }
 
-inline RegExpFlags toFlags(ExecState* exec, JSValue flags)
+inline OptionSet<Yarr::Flags> toFlags(ExecState* exec, JSValue flags)
 {
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     if (flags.isUndefined())
-        return NoFlags;
-    JSString* flagsString = flags.toStringOrNull(exec);
-    EXCEPTION_ASSERT(!!scope.exception() == !flagsString);
-    if (UNLIKELY(!flagsString))
-        return InvalidFlags;
+        return { };
+    
+    auto result = Yarr::parseFlags(flags.toWTFString(exec));
+    RETURN_IF_EXCEPTION(scope, { });
+    if (!result) {
+        throwSyntaxError(exec, scope, "Invalid flags supplied to RegExp constructor."_s);
+        return { };
+    }
 
-    RegExpFlags result = regExpFlags(flagsString->value(exec));
-    RETURN_IF_EXCEPTION(scope, InvalidFlags);
-    if (result == InvalidFlags)
-        throwSyntaxError(exec, scope, "Invalid flags supplied to RegExp constructor."_s);
-    return result;
+    return result.value();
 }
 
 static JSObject* regExpCreate(ExecState* exec, JSGlobalObject* globalObject, JSValue newTarget, JSValue patternArg, JSValue flagsArg)
@@ -204,10 +203,8 @@
     String pattern = patternArg.isUndefined() ? emptyString() : patternArg.toWTFString(exec);
     RETURN_IF_EXCEPTION(scope, nullptr);
 
-    RegExpFlags flags = toFlags(exec, flagsArg);
-    EXCEPTION_ASSERT(!!scope.exception() == (flags == InvalidFlags));
-    if (UNLIKELY(flags == InvalidFlags))
-        return nullptr;
+    auto flags = toFlags(exec, flagsArg);
+    RETURN_IF_EXCEPTION(scope, nullptr);
 
     RegExp* regExp = RegExp::create(vm, pattern, flags);
     if (UNLIKELY(!regExp->isValid())) {
@@ -246,12 +243,10 @@
         RETURN_IF_EXCEPTION(scope, nullptr);
 
         if (!flagsArg.isUndefined()) {
-            RegExpFlags flags = toFlags(exec, flagsArg);
-            EXCEPTION_ASSERT(!!scope.exception() == (flags == InvalidFlags));
-            if (flags == InvalidFlags)
-                return nullptr;
+            auto flags = toFlags(exec, flagsArg);
+            RETURN_IF_EXCEPTION(scope, nullptr);
+
             regExp = RegExp::create(vm, regExp->pattern(), flags);
-
             if (UNLIKELY(!regExp->isValid())) {
                 throwException(exec, scope, regExp->errorToThrow(exec));
                 return nullptr;

Modified: trunk/Source/_javascript_Core/runtime/RegExpKey.h (242698 => 242699)


--- trunk/Source/_javascript_Core/runtime/RegExpKey.h	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/Source/_javascript_Core/runtime/RegExpKey.h	2019-03-11 06:20:53 UTC (rev 242699)
@@ -27,50 +27,38 @@
 
 #pragma once
 
+#include "YarrFlags.h"
+#include <wtf/OptionSet.h>
 #include <wtf/text/StringHash.h>
-#include <wtf/text/WTFString.h>
 
 namespace JSC {
 
-enum RegExpFlags : int8_t {
-    NoFlags = 0,
-    FlagGlobal = 1,
-    FlagIgnoreCase = 2,
-    FlagMultiline = 4,
-    FlagSticky = 8,
-    FlagUnicode = 16,
-    FlagDotAll = 32,
-    InvalidFlags = 64,
-    DeletedValueFlags = -1
-};
-
 struct RegExpKey {
-    RegExpFlags flagsValue;
+    OptionSet<Yarr::Flags> flagsValue;
     RefPtr<StringImpl> pattern;
 
     RegExpKey()
-        : flagsValue(NoFlags)
     {
     }
 
-    RegExpKey(RegExpFlags flags)
+    RegExpKey(OptionSet<Yarr::Flags> flags)
         : flagsValue(flags)
     {
     }
 
-    RegExpKey(RegExpFlags flags, const String& pattern)
+    RegExpKey(OptionSet<Yarr::Flags> flags, const String& pattern)
         : flagsValue(flags)
         , pattern(pattern.impl())
     {
     }
 
-    RegExpKey(RegExpFlags flags, RefPtr<StringImpl>&& pattern)
+    RegExpKey(OptionSet<Yarr::Flags> flags, RefPtr<StringImpl>&& pattern)
         : flagsValue(flags)
         , pattern(WTFMove(pattern))
     {
     }
 
-    RegExpKey(RegExpFlags flags, const RefPtr<StringImpl>& pattern)
+    RegExpKey(OptionSet<Yarr::Flags> flags, const RefPtr<StringImpl>& pattern)
         : flagsValue(flags)
         , pattern(pattern)
     {
@@ -107,7 +95,7 @@
 
 template<> struct HashTraits<JSC::RegExpKey> : GenericHashTraits<JSC::RegExpKey> {
     static const bool emptyValueIsZero = true;
-    static void constructDeletedValue(JSC::RegExpKey& slot) { slot.flagsValue = JSC::DeletedValueFlags; }
-    static bool isDeletedValue(const JSC::RegExpKey& value) { return value.flagsValue == JSC::DeletedValueFlags; }
+    static void constructDeletedValue(JSC::RegExpKey& slot) { slot.flagsValue = JSC::Yarr::Flags::DeletedValue; }
+    static bool isDeletedValue(const JSC::RegExpKey& value) { return value.flagsValue == JSC::Yarr::Flags::DeletedValue; }
 };
 } // namespace WTF

Modified: trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp (242698 => 242699)


--- trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp	2019-03-11 06:20:53 UTC (rev 242699)
@@ -29,16 +29,15 @@
 #include "JSCInlines.h"
 #include "JSCJSValue.h"
 #include "JSFunction.h"
-#include "JSObject.h"
 #include "JSStringInlines.h"
 #include "Lexer.h"
 #include "ObjectPrototype.h"
-#include "RegExp.h"
 #include "RegExpCache.h"
 #include "RegExpObject.h"
 #include "RegExpObjectInlines.h"
 #include "StringObject.h"
 #include "StringRecursionChecker.h"
+#include "YarrFlags.h"
 #include <wtf/text/StringBuilder.h>
 
 namespace JSC {
@@ -149,14 +148,12 @@
         String pattern = arg0.isUndefined() ? emptyString() : arg0.toWTFString(exec);
         RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
-        RegExpFlags flags = NoFlags;
-        if (!arg1.isUndefined()) {
-            flags = regExpFlags(arg1.toWTFString(exec));
-            RETURN_IF_EXCEPTION(scope, encodedJSValue());
-            if (flags == InvalidFlags)
-                return throwVMError(exec, scope, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor."_s));
-        }
-        regExp = RegExp::create(vm, pattern, flags);
+        auto flags = arg1.isUndefined() ? makeOptional(OptionSet<Yarr::Flags> { }) : Yarr::parseFlags(arg1.toWTFString(exec));
+        RETURN_IF_EXCEPTION(scope, encodedJSValue());
+        if (!flags)
+            return throwVMError(exec, scope, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor."_s));
+
+        regExp = RegExp::create(vm, pattern, flags.value());
     }
 
     if (!regExp->isValid())

Modified: trunk/Source/_javascript_Core/testRegExp.cpp (242698 => 242699)


--- trunk/Source/_javascript_Core/testRegExp.cpp	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/Source/_javascript_Core/testRegExp.cpp	2019-03-11 06:20:53 UTC (rev 242699)
@@ -24,6 +24,7 @@
 #include "InitializeThreading.h"
 #include "JSCInlines.h"
 #include "JSGlobalObject.h"
+#include "YarrFlags.h"
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -328,11 +329,18 @@
 
     ++i;
 
-    RegExp* r = RegExp::create(vm, pattern.toString(), regExpFlags(line + i));
+    auto flags = Yarr::parseFlags(line + i);
+    if (!flags) {
+        *regexpError = Yarr::errorMessage(Yarr::ErrorCode::InvalidRegularExpressionFlags);
+        return nullptr;
+    }
+
+    RegExp* r = RegExp::create(vm, pattern.toString(), flags.value());
     if (!r->isValid()) {
         *regexpError = r->errorMessage();
         return nullptr;
     }
+
     return r;
 }
 

Modified: trunk/Source/_javascript_Core/yarr/RegularExpression.cpp (242698 => 242699)


--- trunk/Source/_javascript_Core/yarr/RegularExpression.cpp	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/Source/_javascript_Core/yarr/RegularExpression.cpp	2019-03-11 06:20:53 UTC (rev 242699)
@@ -29,6 +29,7 @@
 #include "RegularExpression.h"
 
 #include "Yarr.h"
+#include "YarrFlags.h"
 #include "YarrInterpreter.h"
 #include <wtf/Assertions.h>
 #include <wtf/BumpPointerAllocator.h>
@@ -55,16 +56,16 @@
 
     std::unique_ptr<JSC::Yarr::BytecodePattern> compile(const String& patternString, TextCaseSensitivity caseSensitivity, MultilineMode multilineMode, UnicodeMode unicodeMode)
     {
-        RegExpFlags flags = NoFlags;
+        OptionSet<JSC::Yarr::Flags> flags;
 
         if (caseSensitivity == TextCaseInsensitive)
-            flags = static_cast<RegExpFlags>(flags | FlagIgnoreCase);
+            flags.add(Flags::IgnoreCase);
 
         if (multilineMode == MultilineEnabled)
-            flags = static_cast<RegExpFlags>(flags | FlagMultiline);
+            flags.add(Flags::Multiline);
 
         if (unicodeMode == UnicodeAwareMode)
-            flags = static_cast<RegExpFlags>(flags | FlagUnicode);
+            flags.add(Flags::Unicode);
 
         JSC::Yarr::YarrPattern pattern(patternString, flags, m_constructionErrorCode);
         if (JSC::Yarr::hasError(m_constructionErrorCode)) {

Added: trunk/Source/_javascript_Core/yarr/YarrFlags.cpp (0 => 242699)


--- trunk/Source/_javascript_Core/yarr/YarrFlags.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/yarr/YarrFlags.cpp	2019-03-11 06:20:53 UTC (rev 242699)
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2019 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "YarrFlags.h"
+
+#include <wtf/OptionSet.h>
+#include <wtf/text/StringView.h>
+
+namespace JSC { namespace Yarr {
+
+Optional<OptionSet<Flags>> parseFlags(StringView string)
+{
+    OptionSet<Flags> flags;
+    for (auto character : string.codeUnits()) {
+        switch (character) {
+        case 'g':
+            if (flags.contains(Flags::Global))
+                return WTF::nullopt;
+            flags.add(Flags::Global);
+            break;
+
+        case 'i':
+            if (flags.contains(Flags::IgnoreCase))
+                return WTF::nullopt;
+            flags.add(Flags::IgnoreCase);
+            break;
+
+        case 'm':
+            if (flags.contains(Flags::Multiline))
+                return WTF::nullopt;
+            flags.add(Flags::Multiline);
+            break;
+
+        case 's':
+            if (flags.contains(Flags::DotAll))
+                return WTF::nullopt;
+            flags.add(Flags::DotAll);
+            break;
+            
+        case 'u':
+            if (flags.contains(Flags::Unicode))
+                return WTF::nullopt;
+            flags.add(Flags::Unicode);
+            break;
+                
+        case 'y':
+            if (flags.contains(Flags::Sticky))
+                return WTF::nullopt;
+            flags.add(Flags::Sticky);
+            break;
+
+        default:
+            return WTF::nullopt;
+        }
+    }
+
+    return makeOptional(flags);
+}
+
+} } // namespace JSC::Yarr

Added: trunk/Source/_javascript_Core/yarr/YarrFlags.h (0 => 242699)


--- trunk/Source/_javascript_Core/yarr/YarrFlags.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/yarr/YarrFlags.h	2019-03-11 06:20:53 UTC (rev 242699)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/Forward.h>
+#include <wtf/Optional.h>
+
+namespace JSC { namespace Yarr {
+
+enum class Flags : uint8_t {
+    Global = 1 << 0,
+    IgnoreCase = 1 << 1,
+    Multiline = 1 << 2,
+    Sticky = 1 << 3,
+    Unicode = 1 << 4,
+    DotAll = 1 << 5,
+    DeletedValue = 1 << 6
+};
+
+JS_EXPORT_PRIVATE Optional<OptionSet<Flags>> parseFlags(StringView);
+
+} } // namespace JSC::Yarr

Modified: trunk/Source/_javascript_Core/yarr/YarrInterpreter.h (242698 => 242699)


--- trunk/Source/_javascript_Core/yarr/YarrInterpreter.h	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/Source/_javascript_Core/yarr/YarrInterpreter.h	2019-03-11 06:20:53 UTC (rev 242699)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include "ConcurrentJSLock.h"
+#include "YarrFlags.h"
 #include "YarrPattern.h"
 
 namespace WTF {
@@ -367,14 +368,14 @@
 
     size_t estimatedSizeInBytes() const { return m_body->estimatedSizeInBytes(); }
     
-    bool ignoreCase() const { return m_flags & FlagIgnoreCase; }
-    bool multiline() const { return m_flags & FlagMultiline; }
-    bool sticky() const { return m_flags & FlagSticky; }
-    bool unicode() const { return m_flags & FlagUnicode; }
-    bool dotAll() const { return m_flags & FlagDotAll; }
+    bool ignoreCase() const { return m_flags.contains(Flags::IgnoreCase); }
+    bool multiline() const { return m_flags.contains(Flags::Multiline); }
+    bool sticky() const { return m_flags.contains(Flags::Sticky); }
+    bool unicode() const { return m_flags.contains(Flags::Unicode); }
+    bool dotAll() const { return m_flags.contains(Flags::DotAll); }
 
     std::unique_ptr<ByteDisjunction> m_body;
-    RegExpFlags m_flags;
+    OptionSet<Flags> m_flags;
     // Each BytecodePattern is associated with a RegExp, each RegExp is associated
     // with a VM.  Cache a pointer to out VM's m_regExpAllocator.
     BumpPointerAllocator* m_allocator;

Modified: trunk/Source/_javascript_Core/yarr/YarrPattern.cpp (242698 => 242699)


--- trunk/Source/_javascript_Core/yarr/YarrPattern.cpp	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/Source/_javascript_Core/yarr/YarrPattern.cpp	2019-03-11 06:20:53 UTC (rev 242699)
@@ -36,7 +36,6 @@
 #include <wtf/StackPointer.h>
 #include <wtf/Threading.h>
 #include <wtf/Vector.h>
-#include <wtf/text/WTFString.h>
 
 namespace JSC { namespace Yarr {
 
@@ -1110,9 +1109,6 @@
 {
     YarrPatternConstructor constructor(*this, stackLimit);
 
-    if (m_flags == InvalidFlags)
-        return ErrorCode::InvalidRegularExpressionFlags;
-
     {
         ErrorCode error = parse(constructor, patternString, unicode());
         if (hasError(error))
@@ -1152,7 +1148,7 @@
     return ErrorCode::NoError;
 }
 
-YarrPattern::YarrPattern(const String& pattern, RegExpFlags flags, ErrorCode& error, void* stackLimit)
+YarrPattern::YarrPattern(const String& pattern, OptionSet<Flags> flags, ErrorCode& error, void* stackLimit)
     : m_containsBackreferences(false)
     , m_containsBOL(false)
     , m_containsUnsignedLengthPattern(false)
@@ -1160,6 +1156,7 @@
     , m_saveInitialStartValue(false)
     , m_flags(flags)
 {
+    ASSERT(m_flags != Flags::DeletedValue);
     error = compile(pattern, stackLimit);
 }
 
@@ -1420,7 +1417,7 @@
     out.print("RegExp pattern for ");
     dumpPatternString(out, patternString);
 
-    if (m_flags != NoFlags) {
+    if (m_flags) {
         bool printSeperator = false;
         out.print(" (");
         if (global()) {

Modified: trunk/Source/_javascript_Core/yarr/YarrPattern.h (242698 => 242699)


--- trunk/Source/_javascript_Core/yarr/YarrPattern.h	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/Source/_javascript_Core/yarr/YarrPattern.h	2019-03-11 06:20:53 UTC (rev 242699)
@@ -26,14 +26,15 @@
 
 #pragma once
 
-#include "RegExpKey.h"
 #include "YarrErrorCode.h"
+#include "YarrFlags.h"
 #include "YarrUnicodeProperties.h"
 #include <wtf/CheckedArithmetic.h>
 #include <wtf/HashMap.h>
+#include <wtf/OptionSet.h>
 #include <wtf/PrintStream.h>
 #include <wtf/Vector.h>
-#include <wtf/text/WTFString.h>
+#include <wtf/text/StringHash.h>
 
 namespace JSC { namespace Yarr {
 
@@ -352,7 +353,7 @@
 
 
 struct YarrPattern {
-    JS_EXPORT_PRIVATE YarrPattern(const String& pattern, RegExpFlags, ErrorCode&, void* stackLimit = nullptr);
+    JS_EXPORT_PRIVATE YarrPattern(const String& pattern, OptionSet<Flags>, ErrorCode&, void* stackLimit = nullptr);
 
     void resetForReparsing()
     {
@@ -507,12 +508,12 @@
     void dumpPattern(const String& pattern);
     void dumpPattern(PrintStream& out, const String& pattern);
 
-    bool global() const { return m_flags & FlagGlobal; }
-    bool ignoreCase() const { return m_flags & FlagIgnoreCase; }
-    bool multiline() const { return m_flags & FlagMultiline; }
-    bool sticky() const { return m_flags & FlagSticky; }
-    bool unicode() const { return m_flags & FlagUnicode; }
-    bool dotAll() const { return m_flags & FlagDotAll; }
+    bool global() const { return m_flags.contains(Flags::Global); }
+    bool ignoreCase() const { return m_flags.contains(Flags::IgnoreCase); }
+    bool multiline() const { return m_flags.contains(Flags::Multiline); }
+    bool sticky() const { return m_flags.contains(Flags::Sticky); }
+    bool unicode() const { return m_flags.contains(Flags::Unicode); }
+    bool dotAll() const { return m_flags.contains(Flags::DotAll); }
 
     bool m_containsBackreferences : 1;
     bool m_containsBOL : 1;
@@ -519,7 +520,7 @@
     bool m_containsUnsignedLengthPattern : 1;
     bool m_hasCopiedParenSubexpressions : 1;
     bool m_saveInitialStartValue : 1;
-    RegExpFlags m_flags;
+    OptionSet<Flags> m_flags;
     unsigned m_numSubpatterns { 0 };
     unsigned m_maxBackReference { 0 };
     unsigned m_initialStartValueFrameLocation { 0 };

Modified: trunk/Source/_javascript_Core/yarr/YarrSyntaxChecker.cpp (242698 => 242699)


--- trunk/Source/_javascript_Core/yarr/YarrSyntaxChecker.cpp	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/Source/_javascript_Core/yarr/YarrSyntaxChecker.cpp	2019-03-11 06:20:53 UTC (rev 242699)
@@ -26,9 +26,9 @@
 #include "config.h"
 #include "YarrSyntaxChecker.h"
 
+#include "YarrFlags.h"
 #include "YarrParser.h"
 #include <wtf/Optional.h>
-#include <wtf/text/WTFString.h>
 
 namespace JSC { namespace Yarr {
 
@@ -58,7 +58,12 @@
 ErrorCode checkSyntax(const String& pattern, const String& flags)
 {
     SyntaxChecker syntaxChecker;
-    return parse(syntaxChecker, pattern, flags.contains('u'));
+
+    auto parsedFlags = parseFlags(flags);
+    if (!parsedFlags)
+        return ErrorCode::InvalidRegularExpressionFlags;
+
+    return parse(syntaxChecker, pattern, parsedFlags->contains(Flags::Unicode));
 }
 
 }} // JSC::Yarr

Modified: trunk/Source/WebCore/ChangeLog (242698 => 242699)


--- trunk/Source/WebCore/ChangeLog	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/Source/WebCore/ChangeLog	2019-03-11 06:20:53 UTC (rev 242699)
@@ -1,3 +1,14 @@
+2019-03-10  Ross Kirsling  <[email protected]>
+
+        Invalid flags in a RegExp literal should be an early SyntaxError
+        https://bugs.webkit.org/show_bug.cgi?id=195514
+
+        Reviewed by Darin Adler.
+
+        * bindings/js/SerializedScriptValue.cpp:
+        (WebCore::CloneDeserializer::readTerminal):
+        Consume YarrFlags.
+
 2019-03-10  Tim Horton  <[email protected]>
 
         Add SPI to retrieve the set of text inputs in a given rect, and later focus one

Modified: trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp (242698 => 242699)


--- trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp	2019-03-11 06:04:00 UTC (rev 242698)
+++ trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp	2019-03-11 06:20:53 UTC (rev 242699)
@@ -56,7 +56,6 @@
 #include "SharedBuffer.h"
 #include "WebCoreJSClientData.h"
 #include <_javascript_Core/APICast.h>
-#include <_javascript_Core/ArrayBuffer.h>
 #include <_javascript_Core/BooleanObject.h>
 #include <_javascript_Core/CatchScope.h>
 #include <_javascript_Core/DateInstance.h>
@@ -81,6 +80,7 @@
 #include <_javascript_Core/TypedArrayInlines.h>
 #include <_javascript_Core/TypedArrays.h>
 #include <_javascript_Core/WasmModule.h>
+#include <_javascript_Core/YarrFlags.h>
 #include <limits>
 #include <wtf/MainThread.h>
 #include <wtf/RunLoop.h>
@@ -2891,10 +2891,10 @@
             CachedStringRef flags;
             if (!readStringData(flags))
                 return JSValue();
-            RegExpFlags reFlags = regExpFlags(flags->string());
-            ASSERT(reFlags != InvalidFlags);
+            auto reFlags = Yarr::parseFlags(flags->string());
+            ASSERT(reFlags.hasValue());
             VM& vm = m_exec->vm();
-            RegExp* regExp = RegExp::create(vm, pattern->string(), reFlags);
+            RegExp* regExp = RegExp::create(vm, pattern->string(), reFlags.value());
             return RegExpObject::create(vm, m_globalObject->regExpStructure(), regExp);
         }
         case ObjectReferenceTag: {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to