Title: [198554] trunk
Revision
198554
Author
[email protected]
Date
2016-03-22 14:42:06 -0700 (Tue, 22 Mar 2016)

Log Message

[ES6] Implement RegExp.prototype[@@match]
https://bugs.webkit.org/show_bug.cgi?id=155711

Reviewed by Filip Pizlo.

Source/_javascript_Core:

Implemented ES6 spec for String.prototype.match and RegExp.prototype[@@match].
Implemented both as builtins, with String.prototype.match calling 
RegExp.prototype[@@match].

For performance reasons, RegExp.prototype[@@match] has a C++ fast path when
RegExp.prototype.exec has not been overridden.  This fast path,
RegExpObject::matchGlobal, was taken from the prior StringPrototype::match.
It only handles global matches.

Added new test, stress/regexp-match.js.

Updated various tests for changes exception string and now passing ES6 behavior.

* CMakeLists.txt: 
* DerivedSources.make:
* _javascript_Core.xcodeproj/project.pbxproj:
Added builtins/RegExpPrototype.js and eliminated RegExpPrototype.lut.h.

* builtins/RegExpPrototype.js: Added.
(match.advanceStringIndexUnicode): Helper.
(match): Implements RegExp.prototype[@@match].
* builtins/StringPrototype.js:
(match): Implements String.prototype.match.

* bytecode/BytecodeIntrinsicRegistry.cpp:
(JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry):
(JSC::BytecodeIntrinsicRegistry::lookup):
* bytecode/BytecodeIntrinsicRegistry.h:
* runtime/CommonIdentifiers.h:
Added Symbol.match and builtins @match and @exec.

* runtime/RegExpObject.cpp:
* runtime/RegExpObject.h:
* runtime/RegExpObjectInlines.h:
(JSC::RegExpObject::matchGlobal): Added.
(JSC::RegExpObject::advanceStringUnicode): Added helper.

* runtime/RegExpPrototype.cpp:
* runtime/RegExpPrototype.h:
(JSC::RegExpPrototype::RegExpPrototype):
(JSC::RegExpPrototype::finishCreation):
(JSC::RegExpPrototype::visitChildren):
(JSC::regExpProtoFuncMatchPrivate):
(JSC::RegExpPrototype::getOwnPropertySlot): Deleted.
(JSC::RegExpPrototype::create):
Restructured to create properties explicitly due to having two names for native regExpProtoFuncExec.

* runtime/StringPrototype.cpp:
(JSC::StringPrototype::finishCreation):
Made match a builtin.
Removed unused declaration of stringProtoFuncSearch() since it was made a builtin.

* tests/es6.yaml:
* tests/stress/regexp-match.js: Added.
(shouldBe):
(shouldThrow):
(errorKey.toString):
(primitive.of.primitives.shouldThrow):
(testRegExpMatch):
(testMatch):
(testBoth):
(alwaysUnmatch):

LayoutTests:

Updated tests for exception string changes and added Symbol.match.

* js/Object-getOwnPropertyNames-expected.txt:
* js/dom/string-prototype-properties-expected.txt:
* js/script-tests/Object-getOwnPropertyNames.js:
* sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.10_String.prototype.match/S15.5.4.10_A1_T3-expected.txt:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (198553 => 198554)


--- trunk/LayoutTests/ChangeLog	2016-03-22 21:31:16 UTC (rev 198553)
+++ trunk/LayoutTests/ChangeLog	2016-03-22 21:42:06 UTC (rev 198554)
@@ -1,3 +1,17 @@
+2016-03-22  Michael Saboff  <[email protected]>
+
+        [ES6] Implement RegExp.prototype[@@match]
+        https://bugs.webkit.org/show_bug.cgi?id=155711
+
+        Reviewed by Filip Pizlo.
+
+        Updated tests for exception string changes and added Symbol.match.
+
+        * js/Object-getOwnPropertyNames-expected.txt:
+        * js/dom/string-prototype-properties-expected.txt:
+        * js/script-tests/Object-getOwnPropertyNames.js:
+        * sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.10_String.prototype.match/S15.5.4.10_A1_T3-expected.txt:
+
 2016-03-22  Daniel Bates  <[email protected]>
 
         CSP: Should only execute <script> or apply <style> if its hash appears in all policies

Modified: trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt (198553 => 198554)


--- trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt	2016-03-22 21:31:16 UTC (rev 198553)
+++ trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt	2016-03-22 21:42:06 UTC (rev 198554)
@@ -61,7 +61,7 @@
 PASS getSortedOwnPropertyNames(Error.prototype) is ['constructor', 'message', 'name', 'toString']
 PASS getSortedOwnPropertyNames(Math) is ['E','LN10','LN2','LOG10E','LOG2E','PI','SQRT1_2','SQRT2','abs','acos','acosh','asin','asinh','atan','atan2','atanh','cbrt','ceil','clz32','cos','cosh','exp','expm1','floor','fround','hypot','imul','log','log10','log1p','log2','max','min','pow','random','round','sign','sin','sinh','sqrt','tan','tanh','trunc']
 PASS getSortedOwnPropertyNames(JSON) is ['parse', 'stringify']
-PASS getSortedOwnPropertyNames(Symbol) is ['for', 'hasInstance', 'iterator', 'keyFor', 'length', 'name', 'prototype', 'search', 'species', 'toPrimitive', 'toStringTag', 'unscopables']
+PASS getSortedOwnPropertyNames(Symbol) is ['for', 'hasInstance', 'iterator', 'keyFor', 'length', 'match', 'name', 'prototype', 'search', 'species', 'toPrimitive', 'toStringTag', 'unscopables']
 PASS getSortedOwnPropertyNames(Symbol.prototype) is ['constructor', 'toString', 'valueOf']
 PASS getSortedOwnPropertyNames(Map) is ['length', 'name', 'prototype']
 PASS getSortedOwnPropertyNames(Map.prototype) is ['clear', 'constructor', 'delete', 'entries', 'forEach', 'get', 'has', 'keys', 'set', 'size', 'values']

Modified: trunk/LayoutTests/js/dom/string-prototype-properties-expected.txt (198553 => 198554)


--- trunk/LayoutTests/js/dom/string-prototype-properties-expected.txt	2016-03-22 21:31:16 UTC (rev 198553)
+++ trunk/LayoutTests/js/dom/string-prototype-properties-expected.txt	2016-03-22 21:42:06 UTC (rev 198554)
@@ -10,7 +10,7 @@
 PASS String.prototype.concat.call(undefined, 'five') threw exception TypeError: Type error.
 PASS String.prototype.indexOf.call(undefined, '2') threw exception TypeError: Type error.
 PASS String.prototype.lastIndexOf.call(undefined, '2') threw exception TypeError: Type error.
-PASS String.prototype.match.call(undefined, /2+/) threw exception TypeError: Type error.
+PASS String.prototype.match.call(undefined, /2+/) threw exception TypeError: String.prototype.match requires that |this| not be undefined.
 PASS String.prototype.replace.call(undefined, /2+/, '-') threw exception TypeError: Type error.
 PASS String.prototype.search.call(undefined, '4') threw exception TypeError: String.prototype.search requires that |this| not be undefined.
 PASS String.prototype.slice.call(undefined, 1, 3) threw exception TypeError: Type error.

Modified: trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js (198553 => 198554)


--- trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js	2016-03-22 21:31:16 UTC (rev 198553)
+++ trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js	2016-03-22 21:42:06 UTC (rev 198554)
@@ -70,7 +70,7 @@
     "Error.prototype": "['constructor', 'message', 'name', 'toString']",
     "Math": "['E','LN10','LN2','LOG10E','LOG2E','PI','SQRT1_2','SQRT2','abs','acos','acosh','asin','asinh','atan','atan2','atanh','cbrt','ceil','clz32','cos','cosh','exp','expm1','floor','fround','hypot','imul','log','log10','log1p','log2','max','min','pow','random','round','sign','sin','sinh','sqrt','tan','tanh','trunc']",
     "JSON": "['parse', 'stringify']",
-    "Symbol": "['for', 'hasInstance', 'iterator', 'keyFor', 'length', 'name', 'prototype', 'search', 'species', 'toPrimitive', 'toStringTag', 'unscopables']",
+    "Symbol": "['for', 'hasInstance', 'iterator', 'keyFor', 'length', 'match', 'name', 'prototype', 'search', 'species', 'toPrimitive', 'toStringTag', 'unscopables']",
     "Symbol.prototype": "['constructor', 'toString', 'valueOf']",
     "Map": "['length', 'name', 'prototype']",
     "Map.prototype": "['clear', 'constructor', 'delete', 'entries', 'forEach', 'get', 'has', 'keys', 'set', 'size', 'values']",

Modified: trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.10_String.prototype.match/S15.5.4.10_A1_T3-expected.txt (198553 => 198554)


--- trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.10_String.prototype.match/S15.5.4.10_A1_T3-expected.txt	2016-03-22 21:31:16 UTC (rev 198553)
+++ trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.10_String.prototype.match/S15.5.4.10_A1_T3-expected.txt	2016-03-22 21:42:06 UTC (rev 198554)
@@ -1,6 +1,6 @@
 S15.5.4.10_A1_T3
 
-FAIL TypeError: Type error
+FAIL TypeError: String.prototype.match requires that |this| not be undefined
 
 TEST COMPLETE
 

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (198553 => 198554)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2016-03-22 21:31:16 UTC (rev 198553)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2016-03-22 21:42:06 UTC (rev 198554)
@@ -1219,6 +1219,7 @@
     ${_javascript_CORE_DIR}/builtins/PromiseOperations.js
     ${_javascript_CORE_DIR}/builtins/PromisePrototype.js
     ${_javascript_CORE_DIR}/builtins/ReflectObject.js
+    ${_javascript_CORE_DIR}/builtins/RegExpPrototype.js
     ${_javascript_CORE_DIR}/builtins/SetPrototype.js
     ${_javascript_CORE_DIR}/builtins/StringConstructor.js
     ${_javascript_CORE_DIR}/builtins/StringIteratorPrototype.js

Modified: trunk/Source/_javascript_Core/ChangeLog (198553 => 198554)


--- trunk/Source/_javascript_Core/ChangeLog	2016-03-22 21:31:16 UTC (rev 198553)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-03-22 21:42:06 UTC (rev 198554)
@@ -1,3 +1,73 @@
+2016-03-22  Michael Saboff  <[email protected]>
+
+        [ES6] Implement RegExp.prototype[@@match]
+        https://bugs.webkit.org/show_bug.cgi?id=155711
+
+        Reviewed by Filip Pizlo.
+
+        Implemented ES6 spec for String.prototype.match and RegExp.prototype[@@match].
+        Implemented both as builtins, with String.prototype.match calling 
+        RegExp.prototype[@@match].
+
+        For performance reasons, RegExp.prototype[@@match] has a C++ fast path when
+        RegExp.prototype.exec has not been overridden.  This fast path,
+        RegExpObject::matchGlobal, was taken from the prior StringPrototype::match.
+        It only handles global matches.
+
+        Added new test, stress/regexp-match.js.
+
+        Updated various tests for changes exception string and now passing ES6 behavior.
+
+        * CMakeLists.txt: 
+        * DerivedSources.make:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        Added builtins/RegExpPrototype.js and eliminated RegExpPrototype.lut.h.
+
+        * builtins/RegExpPrototype.js: Added.
+        (match.advanceStringIndexUnicode): Helper.
+        (match): Implements RegExp.prototype[@@match].
+        * builtins/StringPrototype.js:
+        (match): Implements String.prototype.match.
+
+        * bytecode/BytecodeIntrinsicRegistry.cpp:
+        (JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry):
+        (JSC::BytecodeIntrinsicRegistry::lookup):
+        * bytecode/BytecodeIntrinsicRegistry.h:
+        * runtime/CommonIdentifiers.h:
+        Added Symbol.match and builtins @match and @exec.
+
+        * runtime/RegExpObject.cpp:
+        * runtime/RegExpObject.h:
+        * runtime/RegExpObjectInlines.h:
+        (JSC::RegExpObject::matchGlobal): Added.
+        (JSC::RegExpObject::advanceStringUnicode): Added helper.
+
+        * runtime/RegExpPrototype.cpp:
+        * runtime/RegExpPrototype.h:
+        (JSC::RegExpPrototype::RegExpPrototype):
+        (JSC::RegExpPrototype::finishCreation):
+        (JSC::RegExpPrototype::visitChildren):
+        (JSC::regExpProtoFuncMatchPrivate):
+        (JSC::RegExpPrototype::getOwnPropertySlot): Deleted.
+        (JSC::RegExpPrototype::create):
+        Restructured to create properties explicitly due to having two names for native regExpProtoFuncExec.
+
+        * runtime/StringPrototype.cpp:
+        (JSC::StringPrototype::finishCreation):
+        Made match a builtin.
+        Removed unused declaration of stringProtoFuncSearch() since it was made a builtin.
+
+        * tests/es6.yaml:
+        * tests/stress/regexp-match.js: Added.
+        (shouldBe):
+        (shouldThrow):
+        (errorKey.toString):
+        (primitive.of.primitives.shouldThrow):
+        (testRegExpMatch):
+        (testMatch):
+        (testBoth):
+        (alwaysUnmatch):
+
 2016-03-22  Caitlin Potter  <[email protected]>
 
         [JSC] allow duplicate property names returned from Proxy ownKeys() trap

Modified: trunk/Source/_javascript_Core/DerivedSources.make (198553 => 198554)


--- trunk/Source/_javascript_Core/DerivedSources.make	2016-03-22 21:31:16 UTC (rev 198553)
+++ trunk/Source/_javascript_Core/DerivedSources.make	2016-03-22 21:42:06 UTC (rev 198554)
@@ -99,6 +99,7 @@
     $(_javascript_Core)/builtins/PromiseOperations.js \
     $(_javascript_Core)/builtins/PromisePrototype.js \
     $(_javascript_Core)/builtins/ReflectObject.js \
+    $(_javascript_Core)/builtins/RegExpPrototype.js \
     $(_javascript_Core)/builtins/SetPrototype.js \
     $(_javascript_Core)/builtins/StringConstructor.js \
     $(_javascript_Core)/builtins/StringIteratorPrototype.js \
@@ -147,7 +148,6 @@
     ObjectConstructor.lut.h \
     ReflectObject.lut.h \
     RegExpConstructor.lut.h \
-    RegExpPrototype.lut.h \
     SetPrototype.lut.h \
     StringConstructor.lut.h \
     StringIteratorPrototype.lut.h \

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (198553 => 198554)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2016-03-22 21:31:16 UTC (rev 198553)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2016-03-22 21:42:06 UTC (rev 198554)
@@ -1464,7 +1464,6 @@
 		996B73211BDA08EF00331B84 /* NumberPrototype.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = 996B730D1BD9FA2C00331B84 /* NumberPrototype.lut.h */; };
 		996B73221BDA08EF00331B84 /* ObjectConstructor.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = 996B730E1BD9FA2C00331B84 /* ObjectConstructor.lut.h */; };
 		996B73231BDA08EF00331B84 /* ReflectObject.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = 996B730F1BD9FA2C00331B84 /* ReflectObject.lut.h */; };
-		996B73241BDA08EF00331B84 /* RegExpPrototype.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = 996B73101BD9FA2C00331B84 /* RegExpPrototype.lut.h */; };
 		996B73251BDA08EF00331B84 /* StringConstructor.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = 996B73111BD9FA2C00331B84 /* StringConstructor.lut.h */; };
 		996B73261BDA08EF00331B84 /* StringIteratorPrototype.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = 996B73121BD9FA2C00331B84 /* StringIteratorPrototype.lut.h */; };
 		996B73271BDA08EF00331B84 /* SymbolConstructor.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = 996B73131BD9FA2C00331B84 /* SymbolConstructor.lut.h */; };
@@ -3355,6 +3354,7 @@
 		6540C79F1B82D9CE000F6B79 /* RegisterAtOffset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterAtOffset.h; sourceTree = "<group>"; };
 		6546F51F1A32A59C006F07D5 /* NullGetterFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = NullGetterFunction.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
 		6546F5201A32A59C006F07D5 /* NullGetterFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NullGetterFunction.h; sourceTree = "<group>"; };
+		654788421C937D2C000781A0 /* RegExpPrototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; path = RegExpPrototype.js; sourceTree = "<group>"; };
 		65525FC31A6DD3B3007B5495 /* NullSetterFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NullSetterFunction.cpp; sourceTree = "<group>"; };
 		65525FC41A6DD3B3007B5495 /* NullSetterFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NullSetterFunction.h; sourceTree = "<group>"; };
 		6553A32F17A1F1EE008CF6F3 /* CommonSlowPathsExceptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CommonSlowPathsExceptions.cpp; sourceTree = "<group>"; };
@@ -3669,7 +3669,6 @@
 		996B730D1BD9FA2C00331B84 /* NumberPrototype.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NumberPrototype.lut.h; sourceTree = "<group>"; };
 		996B730E1BD9FA2C00331B84 /* ObjectConstructor.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectConstructor.lut.h; sourceTree = "<group>"; };
 		996B730F1BD9FA2C00331B84 /* ReflectObject.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReflectObject.lut.h; sourceTree = "<group>"; };
-		996B73101BD9FA2C00331B84 /* RegExpPrototype.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpPrototype.lut.h; sourceTree = "<group>"; };
 		996B73111BD9FA2C00331B84 /* StringConstructor.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringConstructor.lut.h; sourceTree = "<group>"; };
 		996B73121BD9FA2C00331B84 /* StringIteratorPrototype.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringIteratorPrototype.lut.h; sourceTree = "<group>"; };
 		996B73131BD9FA2C00331B84 /* SymbolConstructor.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolConstructor.lut.h; sourceTree = "<group>"; };
@@ -5370,7 +5369,6 @@
 				996B730F1BD9FA2C00331B84 /* ReflectObject.lut.h */,
 				BCD202D50E170708002C7E82 /* RegExpConstructor.lut.h */,
 				A718F61A11754A21002465A7 /* RegExpJitTables.h */,
-				996B73101BD9FA2C00331B84 /* RegExpPrototype.lut.h */,
 				7035587F1C418458004BD7BF /* SetPrototype.lut.h */,
 				996B73111BD9FA2C00331B84 /* StringConstructor.lut.h */,
 				996B73121BD9FA2C00331B84 /* StringIteratorPrototype.lut.h */,
@@ -6843,6 +6841,7 @@
 				7CFBAC1C18B535E500D00750 /* PromisePrototype.js */,
 				7CF9BC5E1B65D9B1009DB1EF /* PromiseConstructor.js */,
 				7CF9BC5F1B65D9B1009DB1EF /* ReflectObject.js */,
+				654788421C937D2C000781A0 /* RegExpPrototype.js */,
 				7035587D1C418419004BD7BF /* SetPrototype.js */,
 				7CF9BC601B65D9B1009DB1EF /* StringConstructor.js */,
 				7CF9BC611B65D9B1009DB1EF /* StringIteratorPrototype.js */,
@@ -7897,7 +7896,6 @@
 				A1712B4111C7B235007A5315 /* RegExpKey.h in Headers */,
 				BC18C45B0E16F5CD00B34460 /* RegExpObject.h in Headers */,
 				BCD202C40E1706A7002C7E82 /* RegExpPrototype.h in Headers */,
-				996B73241BDA08EF00331B84 /* RegExpPrototype.lut.h in Headers */,
 				BC18C45D0E16F5CD00B34460 /* Register.h in Headers */,
 				969A072B0ED1CE6900F1F681 /* RegisterID.h in Headers */,
 				623A37EC1B87A7C000754209 /* RegisterMap.h in Headers */,

Added: trunk/Source/_javascript_Core/builtins/RegExpPrototype.js (0 => 198554)


--- trunk/Source/_javascript_Core/builtins/RegExpPrototype.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/builtins/RegExpPrototype.js	2016-03-22 21:42:06 UTC (rev 198554)
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * 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. ``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
+ * 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. 
+ */
+
+function match(str)
+{
+    "use strict";
+
+    function advanceStringIndexUnicode(string, stringLength, index)
+    {
+        if (index + 1 >= stringLength)
+            return index + 1;
+
+        let first = string.@charCodeAt(index);
+        if (first < 0xD800 || first > 0xDBFF)
+            return index + 1;
+
+        let second = string.@charCodeAt(index + 1);
+        if (second < 0xDC00 || second > 0xDFFF)
+            return index + 1;
+
+        return index + 2;
+    }
+
+    if (!(this instanceof @Object))
+        throw new @TypeError("RegExp.prototype.@@match requires that |this| be an Object");
+
+    let regexp = @Object(this);
+    let stringArg = @toString(str);
+
+    if (!regexp.global)
+        return regexp.exec(stringArg);
+
+    regexp.lastIndex = 0;
+
+    let resultList = [];
+
+    if (regexp.exec !== @RegExp.prototype.@exec && typeof(regexp.exec) === "function") {
+        // Match using the overridden exec.
+        let unicode = regexp.unicode;
+        let stringLength = str.length;
+
+        while (true) {
+            let result = regexp.exec(stringArg);
+            
+            if (result === null) {
+                if (resultList.length === 0)
+                    return null;
+                return resultList;
+            } else if (!@isObject(result))
+                throw new @TypeError("RegExp.prototype.@@match call to RegExp.exec didn't return null or an object");
+
+            let resultString = @toString(result[0]);
+
+            if (!resultString.length) {
+                if (unicode)
+                    regexp.lastIndex = advanceStringIndexUnicode(stringArg, stringLength, regexp.lastIndex);
+                else
+                    regexp.lastIndex++;
+            }
+
+            resultList.@push(resultString);
+        }
+    }
+
+    return regexp.@match(stringArg);
+}
+

Modified: trunk/Source/_javascript_Core/builtins/StringPrototype.js (198553 => 198554)


--- trunk/Source/_javascript_Core/builtins/StringPrototype.js	2016-03-22 21:31:16 UTC (rev 198553)
+++ trunk/Source/_javascript_Core/builtins/StringPrototype.js	2016-03-22 21:42:06 UTC (rev 198554)
@@ -26,6 +26,27 @@
 
 // @conditional=ENABLE(INTL)
 
+function match(regexp)
+{
+    "use strict";
+
+    if (this == null) {
+        if (this === null)
+            throw new @TypeError("String.prototype.match requires that |this| not be null");
+        throw new @TypeError("String.prototype.match requires that |this| not be undefined");
+    }
+
+    if (regexp != null) {
+        var matcher = regexp[@symbolMatch];
+        if (matcher !== @undefined)
+            return matcher.@call(regexp, this);
+    }
+
+    let thisString = @toString(this);
+    let createdRegExp = new @RegExp(regexp, @undefined);
+    return createdRegExp[@symbolMatch](thisString);
+}
+
 function search(regexp)
 {
     "use strict";

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.cpp (198553 => 198554)


--- trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.cpp	2016-03-22 21:31:16 UTC (rev 198553)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.cpp	2016-03-22 21:42:06 UTC (rev 198554)
@@ -51,6 +51,7 @@
     m_promiseStateFulfilled.set(m_vm, jsNumber(static_cast<unsigned>(JSPromise::Status::Fulfilled)));
     m_promiseStateRejected.set(m_vm, jsNumber(static_cast<unsigned>(JSPromise::Status::Rejected)));
     m_symbolIterator.set(m_vm, Symbol::create(m_vm, static_cast<SymbolImpl&>(*m_vm.propertyNames->iteratorSymbol.impl())));
+    m_symbolMatch.set(m_vm, Symbol::create(m_vm, static_cast<SymbolImpl&>(*m_vm.propertyNames->matchSymbol.impl())));
     m_symbolSearch.set(m_vm, Symbol::create(m_vm, static_cast<SymbolImpl&>(*m_vm.propertyNames->searchSymbol.impl())));
     m_symbolSpecies.set(m_vm, Symbol::create(m_vm, static_cast<SymbolImpl&>(*m_vm.propertyNames->speciesSymbol.impl())));
 }

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h (198553 => 198554)


--- trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h	2016-03-22 21:31:16 UTC (rev 198553)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h	2016-03-22 21:42:06 UTC (rev 198554)
@@ -53,6 +53,7 @@
     macro(promiseStateFulfilled) \
     macro(promiseStateRejected) \
     macro(symbolIterator) \
+    macro(symbolMatch) \
     macro(symbolSearch) \
     macro(symbolSpecies)
 

Modified: trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h (198553 => 198554)


--- trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h	2016-03-22 21:31:16 UTC (rev 198553)
+++ trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h	2016-03-22 21:42:06 UTC (rev 198554)
@@ -274,13 +274,13 @@
 
 #define JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL_NOT_IMPLEMENTED_YET(macro)\
     macro(isConcatSpreadable) \
-    macro(match) \
     macro(replace) \
-    macro(split) \
+    macro(split)
 
 #define JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(macro) \
     macro(hasInstance) \
     macro(iterator) \
+    macro(match) \
     macro(search) \
     macro(species) \
     macro(toPrimitive) \
@@ -352,6 +352,7 @@
     macro(Uint32Array) \
     macro(Float32Array) \
     macro(Float64Array) \
+    macro(exec) \
     macro(generator) \
     macro(generatorNext) \
     macro(generatorState) \

Modified: trunk/Source/_javascript_Core/runtime/RegExpObject.cpp (198553 => 198554)


--- trunk/Source/_javascript_Core/runtime/RegExpObject.cpp	2016-03-22 21:31:16 UTC (rev 198553)
+++ trunk/Source/_javascript_Core/runtime/RegExpObject.cpp	2016-03-22 21:42:06 UTC (rev 198554)
@@ -169,4 +169,65 @@
     return matchInline(exec, globalObject, string);
 }
 
+JSValue RegExpObject::matchGlobal(ExecState* exec, JSGlobalObject* globalObject, JSString* string)
+{
+    RegExp* regExp = this->regExp();
+
+    ASSERT(regExp->global());
+
+    VM* vm = &globalObject->vm();
+
+    setLastIndex(exec, 0);
+    if (exec->hadException())
+        return jsUndefined();
+
+    String s = string->value(exec);
+    RegExpConstructor* regExpConstructor = globalObject->regExpConstructor();
+    MatchResult result = regExpConstructor->performMatch(*vm, regExp, string, s, 0);
+
+    // return array of matches
+    MarkedArgumentBuffer list;
+    // We defend ourselves from crazy.
+    const size_t maximumReasonableMatchSize = 1000000000;
+
+    if (regExp->unicode()) {
+        while (result) {
+            if (list.size() > maximumReasonableMatchSize) {
+                throwOutOfMemoryError(exec);
+                return jsUndefined();
+            }
+
+            size_t end = result.end;
+            size_t length = end - result.start;
+            list.append(jsSubstring(exec, s, result.start, length));
+            if (!length)
+                end = advanceStringUnicode(s, length, end);
+            result = regExpConstructor->performMatch(*vm, regExp, string, s, end);
+        }
+    } else {
+        while (result) {
+            if (list.size() > maximumReasonableMatchSize) {
+                throwOutOfMemoryError(exec);
+                return jsUndefined();
+            }
+
+            size_t end = result.end;
+            size_t length = end - result.start;
+            list.append(jsSubstring(exec, s, result.start, length));
+            if (!length)
+                ++end;
+            result = regExpConstructor->performMatch(*vm, regExp, string, s, end);
+        }
+    }
+
+    if (list.isEmpty()) {
+        // if there are no matches at all, it's important to return
+        // Null instead of an empty array, because this matches
+        // other browsers and because Null is a false value.
+        return jsNull();
+    }
+
+    return constructArray(exec, static_cast<ArrayAllocationProfile*>(0), list);
+}
+
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/RegExpObject.h (198553 => 198554)


--- trunk/Source/_javascript_Core/runtime/RegExpObject.h	2016-03-22 21:31:16 UTC (rev 198553)
+++ trunk/Source/_javascript_Core/runtime/RegExpObject.h	2016-03-22 21:42:06 UTC (rev 198554)
@@ -70,6 +70,8 @@
     bool testInline(ExecState* exec, JSGlobalObject* globalObject, JSString* string) { return !!matchInline(exec, globalObject, string); }
     JSValue exec(ExecState*, JSGlobalObject*, JSString*);
     JSValue execInline(ExecState*, JSGlobalObject*, JSString*);
+    MatchResult match(ExecState*, JSGlobalObject*, JSString*);
+    JSValue matchGlobal(ExecState*, JSGlobalObject*, JSString*);
 
     static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
     static bool put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
@@ -102,9 +104,9 @@
     JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
     JS_EXPORT_PRIVATE static void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
     JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
+    unsigned advanceStringUnicode(String, unsigned, unsigned);
 
 private:
-    MatchResult match(ExecState*, JSGlobalObject*, JSString*);
     MatchResult matchInline(ExecState*, JSGlobalObject*, JSString*);
 
     WriteBarrier<RegExp> m_regExp;

Modified: trunk/Source/_javascript_Core/runtime/RegExpObjectInlines.h (198553 => 198554)


--- trunk/Source/_javascript_Core/runtime/RegExpObjectInlines.h	2016-03-22 21:31:16 UTC (rev 198553)
+++ trunk/Source/_javascript_Core/runtime/RegExpObjectInlines.h	2016-03-22 21:42:06 UTC (rev 198554)
@@ -108,6 +108,22 @@
     return result;
 }
 
+unsigned RegExpObject::advanceStringUnicode(String s, unsigned length, unsigned currentIndex)
+{
+    if (currentIndex + 1 >= length)
+        return currentIndex + 1;
+
+    UChar first = s[currentIndex];
+    if (first < 0xD800 || first > 0xDBFF)
+        return currentIndex + 1;
+
+    UChar second = s[currentIndex];
+    if (second < 0xDC00 || second > 0xDFFF)
+        return currentIndex + 1;
+
+    return currentIndex + 2;
+}
+
 } // namespace JSC
 
 #endif // RegExpObjectInlines_h

Modified: trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp (198553 => 198554)


--- trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp	2016-03-22 21:31:16 UTC (rev 198553)
+++ trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp	2016-03-22 21:42:06 UTC (rev 198554)
@@ -22,8 +22,10 @@
 #include "RegExpPrototype.h"
 
 #include "ArrayPrototype.h"
+#include "BuiltinNames.h"
 #include "Error.h"
 #include "JSArray.h"
+#include "JSCBuiltins.h"
 #include "JSCJSValue.h"
 #include "JSFunction.h"
 #include "JSObject.h"
@@ -36,12 +38,14 @@
 #include "RegExp.h"
 #include "RegExpCache.h"
 #include "RegExpConstructor.h"
+#include "RegExpMatchesArray.h"
 #include "StringRecursionChecker.h"
 
 namespace JSC {
 
 static EncodedJSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState*);
 static EncodedJSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState*);
+static EncodedJSValue JSC_HOST_CALL regExpProtoFuncMatchPrivate(ExecState*);
 static EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState*);
 static EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState*);
 static EncodedJSValue JSC_HOST_CALL regExpProtoFuncSearch(ExecState*);
@@ -53,30 +57,8 @@
 static EncodedJSValue JSC_HOST_CALL regExpProtoGetterSource(ExecState*);
 static EncodedJSValue JSC_HOST_CALL regExpProtoGetterFlags(ExecState*);
 
-}
+const ClassInfo RegExpPrototype::s_info = { "Object", &Base::s_info, 0, CREATE_METHOD_TABLE(RegExpPrototype) };
 
-#include "RegExpPrototype.lut.h"
-
-namespace JSC {
-
-const ClassInfo RegExpPrototype::s_info = { "Object", &Base::s_info, &regExpPrototypeTable, CREATE_METHOD_TABLE(RegExpPrototype) };
-
-/* Source for RegExpPrototype.lut.h
-@begin regExpPrototypeTable
-  compile       regExpProtoFuncCompile      DontEnum|Function 2
-  exec          regExpProtoFuncExec         DontEnum|Function 1
-  test          regExpProtoFuncTest         DontEnum|Function 1
-  toString      regExpProtoFuncToString     DontEnum|Function 0
-  global        regExpProtoGetterGlobal     DontEnum|Accessor
-  ignoreCase    regExpProtoGetterIgnoreCase DontEnum|Accessor
-  multiline     regExpProtoGetterMultiline  DontEnum|Accessor
-  sticky        regExpProtoGetterSticky     DontEnum|Accessor
-  unicode       regExpProtoGetterUnicode    DontEnum|Accessor
-  source        regExpProtoGetterSource     DontEnum|Accessor
-  flags         regExpProtoGetterFlags      DontEnum|Accessor
-@end
-*/
-
 RegExpPrototype::RegExpPrototype(VM& vm, Structure* structure)
     : JSNonFinalObject(vm, structure)
 {
@@ -86,16 +68,27 @@
 {
     Base::finishCreation(vm);
     ASSERT(inherits(info()));
-    JSC_NATIVE_FUNCTION(vm.propertyNames->searchSymbol, regExpProtoFuncSearch, DontEnum, 1);
+    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->compile, regExpProtoFuncCompile, DontEnum, 2);
+    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->test, regExpProtoFuncTest, DontEnum, 1);
+    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->toString, regExpProtoFuncToString, DontEnum, 0);
+    JSC_NATIVE_GETTER(vm.propertyNames->global, regExpProtoGetterGlobal, DontEnum | Accessor);
+    JSC_NATIVE_GETTER(vm.propertyNames->ignoreCase, regExpProtoGetterIgnoreCase, DontEnum | Accessor);
+    JSC_NATIVE_GETTER(vm.propertyNames->multiline, regExpProtoGetterMultiline, DontEnum | Accessor);
+    JSC_NATIVE_GETTER(vm.propertyNames->sticky, regExpProtoGetterSticky, DontEnum | Accessor);
+    JSC_NATIVE_GETTER(vm.propertyNames->unicode, regExpProtoGetterUnicode, DontEnum | Accessor);
+    JSC_NATIVE_GETTER(vm.propertyNames->source, regExpProtoGetterSource, DontEnum | Accessor);
+    JSC_NATIVE_GETTER(vm.propertyNames->flags, regExpProtoGetterFlags, DontEnum | Accessor);
+    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().matchPrivateName(), regExpProtoFuncMatchPrivate, DontEnum | DontDelete | ReadOnly, 1);
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->matchSymbol, regExpPrototypeMatchCodeGenerator, DontEnum);
+    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->searchSymbol, regExpProtoFuncSearch, DontEnum, 1);
 
+    JSFunction* execFunction = JSFunction::create(vm, globalObject, 1, vm.propertyNames->exec.string(), regExpProtoFuncExec, RegExpExecIntrinsic);
+    putDirectWithoutTransition(vm, vm.propertyNames->execPrivateName, execFunction, DontEnum | DontDelete | ReadOnly);
+    putDirectWithoutTransition(vm, vm.propertyNames->exec, execFunction, DontEnum);
+
     m_emptyRegExp.set(vm, this, RegExp::create(vm, "", NoFlags));
 }
 
-bool RegExpPrototype::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot &slot)
-{
-    return getStaticFunctionSlot<Base>(exec, regExpPrototypeTable, jsCast<RegExpPrototype*>(object), propertyName, slot);
-}
-
 void RegExpPrototype::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
     RegExpPrototype* thisObject = jsCast<RegExpPrototype*>(cell);
@@ -129,6 +122,17 @@
     return JSValue::encode(asRegExpObject(thisValue)->exec(exec, exec->lexicalGlobalObject(), string));
 }
 
+EncodedJSValue JSC_HOST_CALL regExpProtoFuncMatchPrivate(ExecState* exec)
+{
+    JSValue thisValue = exec->thisValue();
+    if (!thisValue.inherits(RegExpObject::info()))
+        return throwVMTypeError(exec);
+    JSString* string = exec->argument(0).toStringOrNull(exec);
+    if (!string)
+        return JSValue::encode(jsUndefined());
+    return JSValue::encode(asRegExpObject(thisValue)->matchGlobal(exec, exec->lexicalGlobalObject(), string));
+}
+
 EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec)
 {
     JSValue thisValue = exec->thisValue();

Modified: trunk/Source/_javascript_Core/runtime/RegExpPrototype.h (198553 => 198554)


--- trunk/Source/_javascript_Core/runtime/RegExpPrototype.h	2016-03-22 21:31:16 UTC (rev 198553)
+++ trunk/Source/_javascript_Core/runtime/RegExpPrototype.h	2016-03-22 21:42:06 UTC (rev 198554)
@@ -29,7 +29,7 @@
 class RegExpPrototype : public JSNonFinalObject {
 public:
     typedef JSNonFinalObject Base;
-    static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot;
+    static const unsigned StructureFlags = Base::StructureFlags;
 
     static RegExpPrototype* create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
     {
@@ -54,7 +54,6 @@
 
 private:
     void finishCreation(VM&, JSGlobalObject*);
-    static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
 
     WriteBarrier<RegExp> m_emptyRegExp;
 };

Modified: trunk/Source/_javascript_Core/runtime/StringPrototype.cpp (198553 => 198554)


--- trunk/Source/_javascript_Core/runtime/StringPrototype.cpp	2016-03-22 21:31:16 UTC (rev 198553)
+++ trunk/Source/_javascript_Core/runtime/StringPrototype.cpp	2016-03-22 21:42:06 UTC (rev 198554)
@@ -66,10 +66,8 @@
 EncodedJSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState*);
 EncodedJSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState*);
 EncodedJSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState*);
-EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState*);
 EncodedJSValue JSC_HOST_CALL stringProtoFuncRepeat(ExecState*);
 EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState*);
-EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState*);
 EncodedJSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState*);
 EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState*);
 EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstr(ExecState*);
@@ -111,6 +109,7 @@
 
 /* Source for StringConstructor.lut.h
 @begin stringPrototypeTable
+    match     JSBuiltin    DontEnum|Function 1
     search    JSBuiltin    DontEnum|Function 1
 @end
 */
@@ -134,7 +133,6 @@
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("concat", stringProtoFuncConcat, DontEnum, 1);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("indexOf", stringProtoFuncIndexOf, DontEnum, 1);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("lastIndexOf", stringProtoFuncLastIndexOf, DontEnum, 1);
-    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("match", stringProtoFuncMatch, DontEnum, 1);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("repeat", stringProtoFuncRepeat, DontEnum, 1);
     JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION("replace", stringProtoFuncReplace, DontEnum, 2, StringPrototypeReplaceIntrinsic);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("slice", stringProtoFuncSlice, DontEnum, 2);
@@ -1030,107 +1028,6 @@
     return JSValue::encode(jsNumber(result));
 }
 
-EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec)
-{
-    JSValue thisValue = exec->thisValue();
-    if (!checkObjectCoercible(thisValue))
-        return throwVMTypeError(exec);
-    JSString* string = thisValue.toString(exec);
-    String s = string->value(exec);
-    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
-    VM* vm = &globalObject->vm();
-
-    JSValue a0 = exec->argument(0);
-
-    RegExp* regExp;
-    unsigned startOffset = 0;
-    bool global = false;
-    bool sticky = false;
-    RegExpObject* regExpObject = nullptr;
-    if (a0.inherits(RegExpObject::info())) {
-        regExpObject = asRegExpObject(a0);
-        regExp = regExpObject->regExp();
-        if ((global = regExp->global())) {
-            // ES6 21.2.5.6 step 6.b.
-            regExpObject->setLastIndex(exec, 0);
-            if (exec->hadException())
-                return JSValue::encode(jsUndefined());
-        }
-        sticky = regExp->sticky();
-        if (!global && sticky) {
-            JSValue jsLastIndex = regExpObject->getLastIndex();
-            unsigned lastIndex;
-            if (LIKELY(jsLastIndex.isUInt32())) {
-                lastIndex = jsLastIndex.asUInt32();
-                if (lastIndex > s.length()) {
-                    regExpObject->setLastIndex(exec, 0);
-                    return JSValue::encode(jsUndefined());
-                }
-            } else {
-                double doubleLastIndex = jsLastIndex.toInteger(exec);
-                if (doubleLastIndex < 0 || doubleLastIndex > s.length()) {
-                    regExpObject->setLastIndex(exec, 0);
-                    return JSValue::encode(jsUndefined());
-                }
-                lastIndex = static_cast<unsigned>(doubleLastIndex);
-            }
-
-            startOffset = lastIndex;
-        }
-    } else {
-        /*
-         *  ECMA 15.5.4.12 String.prototype.search (regexp)
-         *  If regexp is not an object whose [[Class]] property is "RegExp", it is
-         *  replaced with the result of the _expression_ new RegExp(regexp).
-         *  Per ECMA 15.10.4.1, if a0 is undefined substitute the empty string.
-         */
-        String patternString = emptyString();
-        if (!a0.isUndefined()) {
-            patternString = a0.toString(exec)->value(exec);
-            if (exec->hadException())
-                return JSValue::encode(jsUndefined());
-        }
-        regExp = RegExp::create(exec->vm(), patternString, NoFlags);
-        if (!regExp->isValid())
-            return throwVMError(exec, createSyntaxError(exec, regExp->errorMessage()));
-    }
-    RegExpConstructor* regExpConstructor = globalObject->regExpConstructor();
-    MatchResult result = regExpConstructor->performMatch(*vm, regExp, string, s, startOffset);
-    // case without 'g' flag is handled like RegExp.prototype.exec
-    if (!global) {
-        if (sticky)
-            regExpObject->setLastIndex(exec, result ? result.end : 0);
-
-        return JSValue::encode(result ? createRegExpMatchesArray(exec, globalObject, string, regExp, result.start) : jsNull());
-    }
-
-    // return array of matches
-    MarkedArgumentBuffer list;
-    while (result) {
-        // We defend ourselves from crazy.
-        const size_t maximumReasonableMatchSize = 1000000000;
-        if (list.size() > maximumReasonableMatchSize) {
-            throwOutOfMemoryError(exec);
-            return JSValue::encode(jsUndefined());
-        }
-        
-        size_t end = result.end;
-        size_t length = end - result.start;
-        list.append(jsSubstring(exec, s, result.start, length));
-        if (!length)
-            ++end;
-        result = regExpConstructor->performMatch(*vm, regExp, string, s, end);
-    }
-    if (list.isEmpty()) {
-        // if there are no matches at all, it's important to return
-        // Null instead of an empty array, because this matches
-        // other browsers and because Null is a false value.
-        return JSValue::encode(jsNull());
-    }
-
-    return JSValue::encode(constructArray(exec, static_cast<ArrayAllocationProfile*>(0), list));
-}
-
 EncodedJSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState* exec)
 {
     JSValue thisValue = exec->thisValue();

Modified: trunk/Source/_javascript_Core/tests/es6.yaml (198553 => 198554)


--- trunk/Source/_javascript_Core/tests/es6.yaml	2016-03-22 21:31:16 UTC (rev 198553)
+++ trunk/Source/_javascript_Core/tests/es6.yaml	2016-03-22 21:42:06 UTC (rev 198554)
@@ -1007,7 +1007,7 @@
 - path: es6/Proxy_internal_get_calls_RegExp_constructor.js
   cmd: runES6 :fail
 - path: es6/Proxy_internal_get_calls_String.prototype.match.js
-  cmd: runES6 :fail
+  cmd: runES6 :normal
 - path: es6/Proxy_internal_get_calls_String.prototype.replace.js
   cmd: runES6 :fail
 - path: es6/Proxy_internal_get_calls_String.prototype.search.js
@@ -1083,7 +1083,7 @@
 - path: es6/Reflect_Reflect.set.js
   cmd: runES6 :normal
 - path: es6/RegExp.prototype_properties_RegExp.prototype[Symbol.match].js
-  cmd: runES6 :fail
+  cmd: runES6 :normal
 - path: es6/RegExp.prototype_properties_RegExp.prototype[Symbol.replace].js
   cmd: runES6 :fail
 - path: es6/RegExp.prototype_properties_RegExp.prototype[Symbol.search].js
@@ -1193,7 +1193,7 @@
 - path: es6/well-known_symbols_Symbol.isConcatSpreadable.js
   cmd: runES6 :fail
 - path: es6/well-known_symbols_Symbol.match.js
-  cmd: runES6 :fail
+  cmd: runES6 :normal
 - path: es6/well-known_symbols_Symbol.replace.js
   cmd: runES6 :fail
 - path: es6/well-known_symbols_Symbol.search.js

Added: trunk/Source/_javascript_Core/tests/stress/regexp-match.js (0 => 198554)


--- trunk/Source/_javascript_Core/tests/stress/regexp-match.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/regexp-match.js	2016-03-22 21:42:06 UTC (rev 198554)
@@ -0,0 +1,102 @@
+
+function shouldBe(actual, expected) {
+    if (actual !== expected && !(actual !== null && typeof(expected) === "string" && actual.toString() == expected))
+        throw new Error('expected: ' + expected + ', bad value: ' + actual);
+}
+
+function shouldThrow(func, expected) {
+    var error = null;
+    try {
+        func();
+    } catch (e) {
+        error = e;
+    }
+    if (!error)
+        throw new Error('not thrown');
+    shouldBe(String(error), expected);
+}
+
+var errorKey = {
+    toString() {
+        throw new Error('out');
+    }
+};
+var string = 'Cocoa, Cappuccino, Rize, Matcha, Kilimanjaro';
+
+shouldThrow(function () {
+    String.prototype.match.call(null, /Cocoa/);
+}, "TypeError: String.prototype.match requires that |this| not be null");
+
+shouldThrow(function () {
+    String.prototype.match.call(undefined, /Cocoa/);
+}, "TypeError: String.prototype.match requires that |this| not be undefined");
+
+shouldThrow(function () {
+    string.match(errorKey);
+}, "Error: out");
+
+shouldBe('Cocoa'.match(/Cocoa/), "Cocoa");
+
+shouldBe(string.match(/Rize/), "Rize");
+shouldBe(string.match('Rize'), "Rize");
+shouldBe(string.match(/Matcha/), "Matcha");
+shouldBe(string.match('Matcha'), "Matcha");
+
+shouldBe('    undefined'.match(), "");
+shouldBe('    undefined'.match('undefined'), "undefined");
+
+shouldBe((/Cocoa/)[Symbol.match]('Cocoa'), "Cocoa");
+
+var primitives = [
+    '',
+    'string',
+    42,
+    Symbol('Cocoa'),
+];
+
+for (var primitive of primitives) {
+    shouldThrow(function () {
+        RegExp.prototype[Symbol.match].call(primitive)
+    }, 'TypeError: RegExp.prototype.@@match requires that |this| be an Object');
+}
+
+shouldThrow(function () {
+    /Cocoa/[Symbol.match](errorKey);
+}, "Error: out");
+
+
+function testRegExpMatch(regexp, string, result, lastIndex) {
+    shouldBe(regexp[Symbol.match](string), result);
+    shouldBe(regexp.lastIndex, lastIndex);
+}
+
+function testMatch(regexp, string, result, lastIndex) {
+    shouldBe(string.match(regexp), result);
+    shouldBe(regexp.lastIndex, lastIndex);
+}
+
+function testBoth(regexp, string, result, lastIndex) {
+    testMatch(regexp, string, result, lastIndex);
+    testRegExpMatch(regexp, string, result, lastIndex);
+}
+
+var cocoa = /Cocoa/;
+cocoa.lastIndex = 20;
+testBoth(cocoa, 'Cocoa', "Cocoa", 20);
+testBoth(cocoa, '  Cocoa', "Cocoa", 20);
+testBoth(cocoa, '  ', null, 20);
+
+var multibyte = /ココア/;
+multibyte.lastIndex = 20;
+testBoth(multibyte, 'ココア', 'ココア', 20);
+testBoth(multibyte, '  Cocoa', null, 20);
+testBoth(multibyte, 'カプチーノ', null, 20);
+
+function alwaysUnmatch(string) {
+    return null;
+}
+
+var regexp = new RegExp('ココア');
+regexp[Symbol.match] = alwaysUnmatch;
+shouldBe(regexp[Symbol.match], alwaysUnmatch);
+testBoth(regexp, 'ココア', null, 0);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to