Unreviewed, rolling out r237054.
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 15 Oct 2018 18:42:44 +0000 (18:42 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 15 Oct 2018 18:42:44 +0000 (18:42 +0000)
https://bugs.webkit.org/show_bug.cgi?id=190593

"this regressed JetStream 2 by 6% on iOS" (Requested by
saamyjoon on #webkit).

Reverted changeset:

"[JSC] JSC should have "parseFunction" to optimize Function
constructor"
https://bugs.webkit.org/show_bug.cgi?id=190340
https://trac.webkit.org/changeset/237054

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@237128 268f45cc-cd09-0410-ab3c-d52691b4dbfc

29 files changed:
JSTests/ChakraCore/test/Function/FuncBodyES5.baseline-jsc
JSTests/ChangeLog
JSTests/stress/function-cache-with-parameters-end-position.js [deleted file]
JSTests/stress/function-constructor-name.js [deleted file]
JSTests/test262/expectations.yaml
LayoutTests/ChangeLog
LayoutTests/fast/dom/attribute-event-listener-errors-expected.txt
LayoutTests/fast/events/attribute-listener-deletion-crash-expected.txt
LayoutTests/fast/events/window-onerror-syntax-error-in-attr-expected.txt
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/inline-event-handler-ordering-expected.txt
LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/invalid-uncompiled-raw-handler-compiled-late-expected.txt
LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-attribute-expected.txt
LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-body-onerror-expected.txt
LayoutTests/js/dom/invalid-syntax-for-function-expected.txt
LayoutTests/js/dom/script-start-end-locations-expected.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp
Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h
Source/JavaScriptCore/parser/Parser.cpp
Source/JavaScriptCore/parser/Parser.h
Source/JavaScriptCore/parser/ParserModes.h
Source/JavaScriptCore/parser/ParserTokens.h
Source/JavaScriptCore/parser/SourceCodeKey.h
Source/JavaScriptCore/runtime/CodeCache.cpp
Source/JavaScriptCore/runtime/CodeCache.h
Source/JavaScriptCore/runtime/FunctionConstructor.cpp
Source/JavaScriptCore/runtime/FunctionExecutable.cpp
Source/JavaScriptCore/runtime/FunctionExecutable.h

index 38248d7..36f2a20 100644 (file)
@@ -9,13 +9,13 @@ PASS: 7: new Function succeeded as expected
 PASS: 8: new Function succeeded as expected
 PASS: 9: new Function succeeded as expected
 PASS: 10: new Function succeeded as expected
-PASS: 100: new Function failed as expected. SyntaxError: Parser error
-PASS: 100: new Function failed as expected. SyntaxError: Parser error
-PASS: 101: new Function failed as expected. SyntaxError: Parser error
-PASS: 102: new Function failed as expected. SyntaxError: Parameters should match arguments offered as parameters in Function constructor.
-PASS: 103: new Function failed as expected. SyntaxError: Parser error
-PASS: 104: new Function failed as expected. SyntaxError: Parameters should match arguments offered as parameters in Function constructor.
-PASS: 105: new Function failed as expected. SyntaxError: Parser error
+PASS: 100: new Function failed as expected. SyntaxError: Unexpected token '{'. Expected ')' to end a compound expression.
+PASS: 100: new Function failed as expected. SyntaxError: Unexpected token '{'. Expected ')' to end a compound expression.
+PASS: 101: new Function failed as expected. SyntaxError: Unexpected keyword 'function'. Expected ')' to end a compound expression.
+PASS: 102: new Function failed as expected. SyntaxError: Unexpected keyword 'function'. Expected ')' to end a compound expression.
+PASS: 103: new Function failed as expected. SyntaxError: Unexpected keyword 'function'. Expected ')' to end a compound expression.
+PASS: 104: new Function failed as expected. SyntaxError: Unexpected token ';'. Expected ')' to end a compound expression.
+PASS: 105: new Function failed as expected. SyntaxError: Unexpected token ';'. Expected ')' to end a compound expression.
 PASS: 200: new Function failed as expected. SyntaxError: Unexpected token ','. Expected a parameter pattern or a ')' in parameter list.
 PASS: 200: new Function failed as expected. SyntaxError: Unexpected token ','. Expected a parameter pattern or a ')' in parameter list.
 PASS: 201: new Function failed as expected. SyntaxError: Unexpected token ','. Expected a parameter pattern or a ')' in parameter list.
index 1a9be08..472bbdd 100644 (file)
@@ -1,3 +1,18 @@
+2018-10-15  Commit Queue  <commit-queue@webkit.org>
+
+        Unreviewed, rolling out r237054.
+        https://bugs.webkit.org/show_bug.cgi?id=190593
+
+        "this regressed JetStream 2 by 6% on iOS" (Requested by
+        saamyjoon on #webkit).
+
+        Reverted changeset:
+
+        "[JSC] JSC should have "parseFunction" to optimize Function
+        constructor"
+        https://bugs.webkit.org/show_bug.cgi?id=190340
+        https://trac.webkit.org/changeset/237054
+
 2018-10-13  Yusuke Suzuki  <yusukesuzuki@slowstart.org>
 
         [JSC] JSON.stringify can accept call-with-no-arguments
diff --git a/JSTests/stress/function-cache-with-parameters-end-position.js b/JSTests/stress/function-cache-with-parameters-end-position.js
deleted file mode 100644 (file)
index b0ff221..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-function shouldBe(actual, expected) {
-    if (actual !== expected)
-        throw new Error('bad value: ' + actual);
-}
-
-function shouldThrow(func, errorMessage) {
-    var errorThrown = false;
-    var error = null;
-    try {
-        func();
-    } catch (e) {
-        errorThrown = true;
-        error = e;
-    }
-    if (!errorThrown)
-        throw new Error('not thrown');
-    if (String(error) !== errorMessage)
-        throw new Error(`bad error: ${String(error)}`);
-}
-
-for (var i = 0; i < 10; ++i) {
-    var f = Function('/*) {\n*/', 'return 42');
-    shouldBe(f.toString(),
-`function anonymous(/*) {
-*/) {
-return 42
-}`);
-}
-shouldThrow(() => Function('/*', '*/){\nreturn 42'), `SyntaxError: Parameters should match arguments offered as parameters in Function constructor.`);
-
-shouldThrow(() => Function('/*', '*/){\nreturn 43'), `SyntaxError: Parameters should match arguments offered as parameters in Function constructor.`);
-for (var i = 0; i < 10; ++i) {
-    var f = Function('/*) {\n*/', 'return 43');
-    shouldBe(f.toString(),
-`function anonymous(/*) {
-*/) {
-return 43
-}`);
-}
-
diff --git a/JSTests/stress/function-constructor-name.js b/JSTests/stress/function-constructor-name.js
deleted file mode 100644 (file)
index bf7e945..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-function shouldBe(actual, expected) {
-    if (actual !== expected)
-        throw new Error('bad value: ' + actual);
-}
-
-var GeneratorFunction = function*(){}.constructor;
-var AsyncFunction = async function(){}.constructor;
-var AsyncGeneratorFunction = async function*(){}.constructor;
-
-var f = Function(`return 42`);
-shouldBe(typeof anonymous, `undefined`);
-shouldBe(f.toString(),
-`function anonymous() {
-return 42
-}`);
-
-var gf = GeneratorFunction(`return 42`);
-shouldBe(typeof anonymous, `undefined`);
-shouldBe(gf.toString(),
-`function* anonymous() {
-return 42
-}`);
-
-var af = AsyncFunction(`return 42`);
-shouldBe(typeof anonymous, `undefined`);
-shouldBe(af.toString(),
-`async function anonymous() {
-return 42
-}`);
-
-var agf = AsyncGeneratorFunction(`return 42`);
-shouldBe(typeof anonymous, `undefined`);
-shouldBe(agf.toString(),
-`async function* anonymous() {
-return 42
-}`);
index d399f33..08ca9b1 100644 (file)
@@ -900,14 +900,14 @@ test/built-ins/Function/prototype/restricted-property-caller.js:
   default: "ReferenceError: Can't find variable: verifyNotEnumerable"
   strict mode: "ReferenceError: Can't find variable: verifyNotEnumerable"
 test/built-ins/Function/prototype/toString/AsyncFunction.js:
-  default: "SyntaxError: Unexpected token ';'. Expected a ')' or a ',' after a parameter declaration."
-  strict mode: "SyntaxError: Unexpected token ';'. Expected a ')' or a ',' after a parameter declaration."
+  default: "SyntaxError: Unexpected token '}'. Expected a ')' or a ',' after a parameter declaration."
+  strict mode: "SyntaxError: Unexpected token '}'. Expected a ')' or a ',' after a parameter declaration."
 test/built-ins/Function/prototype/toString/Function.js:
-  default: "SyntaxError: Unexpected token ';'. Expected a ')' or a ',' after a parameter declaration."
-  strict mode: "SyntaxError: Unexpected token ';'. Expected a ')' or a ',' after a parameter declaration."
+  default: "SyntaxError: Unexpected token '}'. Expected a ')' or a ',' after a parameter declaration."
+  strict mode: "SyntaxError: Unexpected token '}'. Expected a ')' or a ',' after a parameter declaration."
 test/built-ins/Function/prototype/toString/GeneratorFunction.js:
-  default: "SyntaxError: Unexpected keyword 'yield'. Expected a ')' or a ',' after a parameter declaration."
-  strict mode: "SyntaxError: Unexpected keyword 'yield'. Expected a ')' or a ',' after a parameter declaration."
+  default: "SyntaxError: Unexpected token '}'. Expected a ')' or a ',' after a parameter declaration."
+  strict mode: "SyntaxError: Unexpected token '}'. Expected a ')' or a ',' after a parameter declaration."
 test/built-ins/Function/prototype/toString/async-arrow-function.js:
   default: "Test262Error: Conforms to NativeFunction Syntax: 'async ( /* b */ a /* c */ , /* d */ b /* e */ ) /* f */ => /* g */ { /* h */ ; /* i */ }'.(async /* a */ ( /* b */ a /* c */ , /* d */ b /* e */ ) /* f */ => /* g */ { /* h */ ; /* i */ })"
   strict mode: "Test262Error: Conforms to NativeFunction Syntax: 'async ( /* b */ a /* c */ , /* d */ b /* e */ ) /* f */ => /* g */ { /* h */ ; /* i */ }'.(async /* a */ ( /* b */ a /* c */ , /* d */ b /* e */ ) /* f */ => /* g */ { /* h */ ; /* i */ })"
index c7da7d2..e313a23 100644 (file)
@@ -1,3 +1,18 @@
+2018-10-15  Commit Queue  <commit-queue@webkit.org>
+
+        Unreviewed, rolling out r237054.
+        https://bugs.webkit.org/show_bug.cgi?id=190593
+
+        "this regressed JetStream 2 by 6% on iOS" (Requested by
+        saamyjoon on #webkit).
+
+        Reverted changeset:
+
+        "[JSC] JSC should have "parseFunction" to optimize Function
+        constructor"
+        https://bugs.webkit.org/show_bug.cgi?id=190340
+        https://trac.webkit.org/changeset/237054
+
 2018-10-15  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         Changing view scale should zoom to initial scale if the page is already at initial scale
index 4236767..1df9397 100644 (file)
@@ -1,4 +1,4 @@
 CONSOLE MESSAGE: line 4: ReferenceError: Can't find variable: error
-CONSOLE MESSAGE: line 5: SyntaxError: Invalid character: '@'
+CONSOLE MESSAGE: line 9: SyntaxError: Invalid character: '@'
 This test verifies that an attribute event listener error shows the right line number even if the attribute contains newlines.
   
index 5824baa..0db7728 100644 (file)
@@ -1,21 +1,21 @@
-CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
-CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
+CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'
 PASS
index 68edd01..5ac9501 100644 (file)
@@ -1,6 +1,6 @@
 Test that window.onerror is called on window object when there is a syntax error in attribute handler. Bug 70991.
 
-Main frame window.onerror: SyntaxError: Unexpected token '%' at window-onerror-syntax-error-in-attr.html:10:38 SyntaxError: Unexpected token '%'
-Main frame window.onerror: SyntaxError: Unexpected token '%' at window-onerror-syntax-error-in-attr.html:36:38 SyntaxError: Unexpected token '%'
-Main frame window.onerror: SyntaxError: Unexpected token '%' at window-onerror-syntax-error-in-attr.html:36:14 SyntaxError: Unexpected token '%'
+Main frame window.onerror: SyntaxError: Unexpected token '%' at window-onerror-syntax-error-in-attr.html:11:38 SyntaxError: Unexpected token '%'
+Main frame window.onerror: SyntaxError: Unexpected token '%' at window-onerror-syntax-error-in-attr.html:37:38 SyntaxError: Unexpected token '%'
+Main frame window.onerror: SyntaxError: Unexpected token '%' at window-onerror-syntax-error-in-attr.html:37:14 SyntaxError: Unexpected token '%'
 Button 1 Button 2 Button 3
index 22c7660..64495c2 100644 (file)
@@ -1,3 +1,18 @@
+2018-10-15  Commit Queue  <commit-queue@webkit.org>
+
+        Unreviewed, rolling out r237054.
+        https://bugs.webkit.org/show_bug.cgi?id=190593
+
+        "this regressed JetStream 2 by 6% on iOS" (Requested by
+        saamyjoon on #webkit).
+
+        Reverted changeset:
+
+        "[JSC] JSC should have "parseFunction" to optimize Function
+        constructor"
+        https://bugs.webkit.org/show_bug.cgi?id=190340
+        https://trac.webkit.org/changeset/237054
+
 2018-10-15  YUHAN WU  <yuhan_wu@apple.com>
 
         Implement error handler of MediaRecorder
index 43095a3..6199cde 100644 (file)
@@ -1,5 +1,5 @@
 CONSOLE MESSAGE: line 19: SyntaxError: Unexpected token '}'
-CONSOLE MESSAGE: line 52: SyntaxError: Unexpected token '}'
+CONSOLE MESSAGE: line 54: SyntaxError: Unexpected token '}'
 
 PASS Inline event handlers retain their ordering when invalid and force-compiled 
 PASS Inline event handlers retain their ordering when invalid and force-compiled via dispatch 
index 9ad5ac6..a86e064 100644 (file)
@@ -1,5 +1,5 @@
-CONSOLE MESSAGE: line 24: SyntaxError: Parser error
-CONSOLE MESSAGE: line 21: SyntaxError: Parser error
+CONSOLE MESSAGE: line 26: SyntaxError: Unexpected token '}'. Expected ')' to end a compound expression.
+CONSOLE MESSAGE: line 21: SyntaxError: Unexpected token '}'. Expected ')' to end a compound expression.
 
 FAIL Invalid uncompiled raw handlers should only be compiled when about to call them. assert_array_equals: lengths differ, expected 3 got 4
 
index f50fce7..329a417 100644 (file)
@@ -1,3 +1,3 @@
-CONSOLE MESSAGE: line 1: SyntaxError: Invalid character: '#'
+CONSOLE MESSAGE: line 2: SyntaxError: Invalid character: '#'
 This test ensures we don't crash when we are given garbage for an attribute expecting a function.
 https://bugs.webkit.org/show_bug.cgi?id=19025
index 32ec07f..ca955d3 100644 (file)
@@ -243,32 +243,32 @@ function "exi2b" { 1:138 - 1:221 }
 eval { 1:1 - 1:56 }
 
   new Function Object:
-function "anonymous" { 1:19 - 2:228 }
+function "anonymous" { 1:20 - 2:228 }
 function "nf1a" { 2:57 - 2:219 }
 function "nf1b" { 2:87 - 2:209 }
 function "nf1c" { 2:117 - 2:199 }
 eval { 1:1 - 1:56 }
-function "anonymous" { 1:19 - 18:8 }
+function "anonymous" { 1:20 - 18:8 }
 function "nf2a" { 5:18 - 16:5 }
 function "nf2b" { 7:22 - 14:9 }
 function "nf2c" { 9:26 - 12:13 }
 eval { 1:1 - 1:56 }
-function "anonymous" { 1:19 - 2:228 }
+function "anonymous" { 1:20 - 2:228 }
 function "nf1a" { 2:57 - 2:219 }
 function "nf1b" { 2:87 - 2:209 }
 function "nf1c" { 2:117 - 2:199 }
 eval { 1:1 - 1:56 }
-function "anonymous" { 1:19 - 2:237 }
+function "anonymous" { 1:20 - 2:237 }
 function "nfi1a" { 2:58 - 2:227 }
 function "nfi1b" { 2:90 - 2:216 }
 function "nfi1c" { 2:122 - 2:205 }
 eval { 1:1 - 1:56 }
-function "anonymous" { 1:19 - 18:8 }
+function "anonymous" { 1:20 - 18:8 }
 function "nf2a" { 5:18 - 16:5 }
 function "nf2b" { 7:22 - 14:9 }
 function "nf2c" { 9:26 - 12:13 }
 eval { 1:1 - 1:56 }
-function "anonymous" { 1:19 - 18:9 }
+function "anonymous" { 1:20 - 18:9 }
 function "nfi2a" { 5:19 - 16:5 }
 function "nfi2b" { 7:23 - 14:9 }
 function "nfi2c" { 9:27 - 12:13 }
index 2e9e632..0bbec8f 100644 (file)
@@ -1,3 +1,18 @@
+2018-10-15  Commit Queue  <commit-queue@webkit.org>
+
+        Unreviewed, rolling out r237054.
+        https://bugs.webkit.org/show_bug.cgi?id=190593
+
+        "this regressed JetStream 2 by 6% on iOS" (Requested by
+        saamyjoon on #webkit).
+
+        Reverted changeset:
+
+        "[JSC] JSC should have "parseFunction" to optimize Function
+        constructor"
+        https://bugs.webkit.org/show_bug.cgi?id=190340
+        https://trac.webkit.org/changeset/237054
+
 2018-10-14  David Kilzer  <ddkilzer@apple.com>
 
         REGRESSION (r237084): JavaScriptCore fails to build on Linux
index 71b1374..e540a24 100644 (file)
@@ -174,14 +174,14 @@ FunctionExecutable* UnlinkedFunctionExecutable::link(VM& vm, const SourceCode& p
 
 UnlinkedFunctionExecutable* UnlinkedFunctionExecutable::fromGlobalCode(
     const Identifier& name, ExecState& exec, const SourceCode& source, 
-    JSObject*& exception, int overrideLineNumber, std::optional<int> functionConstructorParametersEndPosition)
+    JSObject*& exception, int overrideLineNumber)
 {
     ParserError error;
     VM& vm = exec.vm();
     auto& globalObject = *exec.lexicalGlobalObject();
     CodeCache* codeCache = vm.codeCache();
     DebuggerMode debuggerMode = globalObject.hasInteractiveDebugger() ? DebuggerOn : DebuggerOff;
-    UnlinkedFunctionExecutable* executable = codeCache->getUnlinkedGlobalFunctionExecutable(vm, name, source, debuggerMode, functionConstructorParametersEndPosition, error);
+    UnlinkedFunctionExecutable* executable = codeCache->getUnlinkedGlobalFunctionExecutable(vm, name, source, debuggerMode, error);
 
     if (globalObject.hasDebugger())
         globalObject.debugger()->sourceParsed(&exec, source.provider(), error.line(), error.message());
index 313d666..f9e8939 100644 (file)
@@ -107,7 +107,7 @@ public:
 
     static UnlinkedFunctionExecutable* fromGlobalCode(
         const Identifier&, ExecState&, const SourceCode&, JSObject*& exception, 
-        int overrideLineNumber, std::optional<int> functionConstructorParametersEndPosition);
+        int overrideLineNumber);
 
     JS_EXPORT_PRIVATE FunctionExecutable* link(VM&, const SourceCode& parentSource, std::optional<int> overrideLineNumber = std::nullopt, Intrinsic = NoIntrinsic);
 
index 935ad3f..4395dc2 100644 (file)
@@ -194,7 +194,7 @@ Parser<LexerType>::~Parser()
 }
 
 template <typename LexerType>
-String Parser<LexerType>::parseInner(const Identifier& calleeName, SourceParseMode parseMode, ParsingContext parsingContext, std::optional<int> functionConstructorParametersEndPosition)
+String Parser<LexerType>::parseInner(const Identifier& calleeName, SourceParseMode parseMode)
 {
     String parseError = String();
 
@@ -238,8 +238,6 @@ String Parser<LexerType>::parseInner(const Identifier& calleeName, SourceParseMo
             sourceElements = parseGeneratorFunctionSourceElements(context, calleeName, CheckForStrictMode);
         else if (isAsyncGeneratorWrapperParseMode(parseMode))
             sourceElements = parseAsyncGeneratorFunctionSourceElements(context, parseMode, isArrowFunctionBodyExpression, CheckForStrictMode);
-        else if (parsingContext == ParsingContext::FunctionConstructor)
-            sourceElements = parseSingleFunction(context, functionConstructorParametersEndPosition);
         else
             sourceElements = parseSourceElements(context, CheckForStrictMode);
     }
@@ -612,38 +610,6 @@ template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseAsyncGen
         
     return sourceElements;
 }
-
-template <typename LexerType>
-template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSingleFunction(TreeBuilder& context, std::optional<int> functionConstructorParametersEndPosition)
-{
-    TreeSourceElements sourceElements = context.createSourceElements();
-    TreeStatement statement = 0;
-    switch (m_token.m_type) {
-    case FUNCTION:
-        statement = parseFunctionDeclaration(context, ExportType::NotExported, DeclarationDefaultContext::Standard, functionConstructorParametersEndPosition);
-        break;
-    case IDENT:
-        if (*m_token.m_data.ident == m_vm->propertyNames->async && !m_token.m_data.escaped) {
-            next();
-            failIfFalse(match(FUNCTION) && !m_lexer->prevTerminator(), "Cannot parse the async function");
-            statement = parseAsyncFunctionDeclaration(context, ExportType::NotExported, DeclarationDefaultContext::Standard, functionConstructorParametersEndPosition);
-            break;
-        }
-        FALLTHROUGH;
-    default:
-        failDueToUnexpectedToken();
-        break;
-    }
-
-    if (statement) {
-        context.setEndOffset(statement, m_lastTokenEndPosition.offset);
-        context.appendStatement(sourceElements, statement);
-    }
-
-    propagateError();
-    return sourceElements;
-}
-
     
 template <typename LexerType>
 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatementListItem(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
@@ -2297,7 +2263,7 @@ template <class TreeBuilder> typename TreeBuilder::FormalParameterList Parser<Le
 }
 
 template <typename LexerType>
-template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionNameRequirements requirements, SourceParseMode mode, bool nameIsInContainingScope, ConstructorKind constructorKind, SuperBinding expectedSuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>& functionInfo, FunctionDefinitionType functionDefinitionType, std::optional<int> functionConstructorParametersEndPosition)
+template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionNameRequirements requirements, SourceParseMode mode, bool nameIsInContainingScope, ConstructorKind constructorKind, SuperBinding expectedSuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>& functionInfo, FunctionDefinitionType functionDefinitionType)
 {
     RELEASE_ASSERT(isFunctionParseMode(mode));
 
@@ -2493,10 +2459,6 @@ template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuild
         }
         
         matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body");
-
-        // If the code is invoked from function constructor, we need to ensure that parameters are only composed by the string offered as parameters.
-        if (functionConstructorParametersEndPosition)
-            semanticFailIfFalse(lastTokenEndPosition().offset == *functionConstructorParametersEndPosition, "Parameters should match arguments offered as parameters in Function constructor");
         
         // BytecodeGenerator emits code to throw TypeError when a class constructor is "call"ed.
         // Set ConstructorKind to None for non-constructor methods of classes.
@@ -2631,7 +2593,7 @@ static NO_RETURN_DUE_TO_CRASH FunctionMetadataNode* getMetadata(ParserFunctionIn
 static FunctionMetadataNode* getMetadata(ParserFunctionInfo<ASTBuilder>& info) { return info.body; }
 
 template <typename LexerType>
-template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext, std::optional<int> functionConstructorParametersEndPosition)
+template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext)
 {
     ASSERT(match(FUNCTION));
     JSTokenLocation location(tokenLocation());
@@ -2668,7 +2630,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDecla
         functionInfo.name = &m_vm->propertyNames->builtinNames().starDefaultPrivateName();
     }
 
-    failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration, functionConstructorParametersEndPosition)), "Cannot parse this function");
+    failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration)), "Cannot parse this function");
     ASSERT(functionInfo.name);
 
     std::pair<DeclarationResultMask, ScopeRef> functionDeclaration = declareFunction(functionInfo.name);
@@ -2689,7 +2651,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDecla
 }
 
 template <typename LexerType>
-template <class TreeBuilder> TreeStatement Parser<LexerType>::parseAsyncFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext, std::optional<int> functionConstructorParametersEndPosition)
+template <class TreeBuilder> TreeStatement Parser<LexerType>::parseAsyncFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext)
 {
     ASSERT(match(FUNCTION));
     JSTokenLocation location(tokenLocation());
@@ -2726,7 +2688,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseAsyncFunction
         functionInfo.name = &m_vm->propertyNames->builtinNames().starDefaultPrivateName();
     }
 
-    failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration, functionConstructorParametersEndPosition)), "Cannot parse this async function");
+    failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration)), "Cannot parse this async function");
     failIfFalse(functionInfo.name, "Async function statements must have a name");
 
     std::pair<DeclarationResultMask, ScopeRef> functionDeclaration = declareFunction(functionInfo.name);
index 6533ef9..4a6ee25 100644 (file)
@@ -859,8 +859,10 @@ private:
     unsigned m_index;
 };
 
-enum class ArgumentType { Normal, Spread };
-enum class ParsingContext { Program, FunctionConstructor, Eval };
+enum class ArgumentType {
+    Normal,
+    Spread
+};
 
 template <typename LexerType>
 class Parser {
@@ -872,7 +874,7 @@ public:
     ~Parser();
 
     template <class ParsedNode>
-    std::unique_ptr<ParsedNode> parse(ParserError&, const Identifier&, SourceParseMode, ParsingContext, std::optional<int> functionConstructorParametersEndPosition = std::nullopt);
+    std::unique_ptr<ParsedNode> parse(ParserError&, const Identifier&, SourceParseMode);
 
     JSTextPosition positionBeforeLastNewline() const { return m_lexer->positionBeforeLastNewline(); }
     JSTokenLocation locationBeforeLastToken() const { return m_lexer->lastTokenLocation(); }
@@ -1310,8 +1312,7 @@ private:
     }
 
     Parser();
-
-    String parseInner(const Identifier&, SourceParseMode, ParsingContext, std::optional<int> functionConstructorParametersEndPosition = std::nullopt);
+    String parseInner(const Identifier&, SourceParseMode);
 
     void didFinishParsing(SourceElements*, DeclarationStacks::FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, CodeFeatures, int);
 
@@ -1523,14 +1524,13 @@ private:
     template <class TreeBuilder> TreeSourceElements parseGeneratorFunctionSourceElements(TreeBuilder&, const Identifier& name, SourceElementsMode);
     template <class TreeBuilder> TreeSourceElements parseAsyncFunctionSourceElements(TreeBuilder&, SourceParseMode, bool isArrowFunctionBodyExpression, SourceElementsMode);
     template <class TreeBuilder> TreeSourceElements parseAsyncGeneratorFunctionSourceElements(TreeBuilder&, SourceParseMode, bool isArrowFunctionBodyExpression, SourceElementsMode);
-    template <class TreeBuilder> TreeSourceElements parseSingleFunction(TreeBuilder&, std::optional<int> functionConstructorParametersEndPosition);
     template <class TreeBuilder> TreeStatement parseStatementListItem(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength);
     template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength = 0);
     enum class ExportType { Exported, NotExported };
     template <class TreeBuilder> TreeStatement parseClassDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard);
-    template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard, std::optional<int> functionConstructorParametersEndPosition = std::nullopt);
+    template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard);
     template <class TreeBuilder> TreeStatement parseFunctionDeclarationStatement(TreeBuilder&, bool isAsync, bool parentAllowsFunctionDeclarationAsStatement);
-    template <class TreeBuilder> TreeStatement parseAsyncFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard, std::optional<int> functionConstructorParametersEndPosition = std::nullopt);
+    template <class TreeBuilder> TreeStatement parseAsyncFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard);
     template <class TreeBuilder> NEVER_INLINE bool maybeParseAsyncFunctionDeclarationStatement(TreeBuilder& context, TreeStatement& result, bool parentAllowsFunctionDeclarationAsStatement);
     template <class TreeBuilder> TreeStatement parseVariableDeclaration(TreeBuilder&, DeclarationType, ExportType = ExportType::NotExported);
     template <class TreeBuilder> TreeStatement parseDoWhileStatement(TreeBuilder&);
@@ -1599,7 +1599,7 @@ private:
     template <class TreeBuilder> ALWAYS_INLINE TreeExpression createResolveAndUseVariable(TreeBuilder&, const Identifier*, bool isEval, const JSTextPosition&, const JSTokenLocation&);
 
     enum class FunctionDefinitionType { Expression, Declaration, Method };
-    template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionNameRequirements, SourceParseMode, bool nameIsInContainingScope, ConstructorKind, SuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>&, FunctionDefinitionType, std::optional<int> functionConstructorParametersEndPosition = std::nullopt);
+    template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionNameRequirements, SourceParseMode, bool nameIsInContainingScope, ConstructorKind, SuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>&, FunctionDefinitionType);
     
     ALWAYS_INLINE bool isArrowFunctionParameters();
     
@@ -1847,7 +1847,7 @@ private:
 
 template <typename LexerType>
 template <class ParsedNode>
-std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const Identifier& calleeName, SourceParseMode parseMode, ParsingContext parsingContext, std::optional<int> functionConstructorParametersEndPosition)
+std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const Identifier& calleeName, SourceParseMode parseMode)
 {
     int errLine;
     String errMsg;
@@ -1864,7 +1864,7 @@ std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const I
     ASSERT(m_source->startColumn() > OrdinalNumber::beforeFirst());
     unsigned startColumn = m_source->startColumn().zeroBasedInt();
 
-    String parseError = parseInner(calleeName, parseMode, parsingContext, functionConstructorParametersEndPosition);
+    String parseError = parseInner(calleeName, parseMode);
 
     int lineNumber = m_lexer->lineNumber();
     bool lexError = m_lexer->sawError();
@@ -1959,7 +1959,7 @@ std::unique_ptr<ParsedNode> parse(
     std::unique_ptr<ParsedNode> result;
     if (source.provider()->source().is8Bit()) {
         Parser<Lexer<LChar>> parser(vm, source, builtinMode, strictMode, scriptMode, parseMode, superBinding, defaultConstructorKind, derivedContextType, isEvalNode<ParsedNode>(), evalContextType, debuggerParseData);
-        result = parser.parse<ParsedNode>(error, name, parseMode, isEvalNode<ParsedNode>() ? ParsingContext::Eval : ParsingContext::Program);
+        result = parser.parse<ParsedNode>(error, name, parseMode);
         if (positionBeforeLastNewline)
             *positionBeforeLastNewline = parser.positionBeforeLastNewline();
         if (builtinMode == JSParserBuiltinMode::Builtin) {
@@ -1972,7 +1972,7 @@ std::unique_ptr<ParsedNode> parse(
     } else {
         ASSERT_WITH_MESSAGE(defaultConstructorKind == ConstructorKind::None, "BuiltinExecutables::createDefaultConstructor should always use a 8-bit string");
         Parser<Lexer<UChar>> parser(vm, source, builtinMode, strictMode, scriptMode, parseMode, superBinding, defaultConstructorKind, derivedContextType, isEvalNode<ParsedNode>(), evalContextType, debuggerParseData);
-        result = parser.parse<ParsedNode>(error, name, parseMode, isEvalNode<ParsedNode>() ? ParsingContext::Eval : ParsingContext::Program);
+        result = parser.parse<ParsedNode>(error, name, parseMode);
         if (positionBeforeLastNewline)
             *positionBeforeLastNewline = parser.positionBeforeLastNewline();
     }
@@ -1986,37 +1986,4 @@ std::unique_ptr<ParsedNode> parse(
     return result;
 }
 
-inline std::unique_ptr<ProgramNode> parseFunctionForFunctionConstructor(VM& vm, const SourceCode& source, ParserError& error, JSTextPosition* positionBeforeLastNewline, std::optional<int> functionConstructorParametersEndPosition)
-{
-    ASSERT(!source.provider()->source().isNull());
-
-    MonotonicTime before;
-    if (UNLIKELY(Options::reportParseTimes()))
-        before = MonotonicTime::now();
-
-    Identifier name;
-    bool isEvalNode = false;
-    std::unique_ptr<ProgramNode> result;
-    if (source.provider()->source().is8Bit()) {
-        Parser<Lexer<LChar>> parser(&vm, source, JSParserBuiltinMode::NotBuiltin, JSParserStrictMode::NotStrict, JSParserScriptMode::Classic, SourceParseMode::ProgramMode, SuperBinding::NotNeeded, ConstructorKind::None, DerivedContextType::None, isEvalNode, EvalContextType::None, nullptr);
-        result = parser.parse<ProgramNode>(error, name, SourceParseMode::ProgramMode, ParsingContext::FunctionConstructor, functionConstructorParametersEndPosition);
-        if (positionBeforeLastNewline)
-            *positionBeforeLastNewline = parser.positionBeforeLastNewline();
-    } else {
-        Parser<Lexer<UChar>> parser(&vm, source, JSParserBuiltinMode::NotBuiltin, JSParserStrictMode::NotStrict, JSParserScriptMode::Classic, SourceParseMode::ProgramMode, SuperBinding::NotNeeded, ConstructorKind::None, DerivedContextType::None, isEvalNode, EvalContextType::None, nullptr);
-        result = parser.parse<ProgramNode>(error, name, SourceParseMode::ProgramMode, ParsingContext::FunctionConstructor, functionConstructorParametersEndPosition);
-        if (positionBeforeLastNewline)
-            *positionBeforeLastNewline = parser.positionBeforeLastNewline();
-    }
-
-    if (UNLIKELY(Options::reportParseTimes())) {
-        MonotonicTime after = MonotonicTime::now();
-        ParseHash hash(source);
-        dataLogLn(result ? "Parsed #" : "Failed to parse #", hash.hashForCall(), "/#", hash.hashForConstruct(), " in ", (after - before).milliseconds(), " ms.");
-    }
-
-    return result;
-}
-
-
 } // namespace
index 9e637c4..6960e51 100644 (file)
@@ -33,6 +33,7 @@ namespace JSC {
 enum class JSParserStrictMode { NotStrict, Strict };
 enum class JSParserBuiltinMode { NotBuiltin, Builtin };
 enum class JSParserScriptMode { Classic, Module };
+enum class JSParserCodeType { Program, Function, Module };
 
 enum class ConstructorKind { None, Base, Extends };
 enum class SuperBinding { Needed, NotNeeded };
index 59cb0fb..8692603 100644 (file)
@@ -193,6 +193,7 @@ enum JSTokenType {
 struct JSTextPosition {
     JSTextPosition() = default;
     JSTextPosition(int _line, int _offset, int _lineStartOffset) : line(_line), offset(_offset), lineStartOffset(_lineStartOffset) { }
+    JSTextPosition(const JSTextPosition& other) : line(other.line), offset(other.offset), lineStartOffset(other.lineStartOffset) { }
 
     JSTextPosition operator+(int adjustment) const { return JSTextPosition(line, offset + adjustment, lineStartOffset); }
     JSTextPosition operator+(unsigned adjustment) const { return *this + static_cast<int>(adjustment); }
@@ -245,6 +246,13 @@ union JSTokenData {
 
 struct JSTokenLocation {
     JSTokenLocation() = default;
+    JSTokenLocation(const JSTokenLocation& location)
+    {
+        line = location.line;
+        lineStartOffset = location.lineStartOffset;
+        startOffset = location.startOffset;
+        endOffset = location.endOffset;
+    }
 
     int line { 0 };
     unsigned lineStartOffset { 0 };
index b0f0575..abe4181 100644 (file)
@@ -29,7 +29,6 @@
 #include "ParserModes.h"
 #include "UnlinkedSourceCode.h"
 #include <wtf/HashTraits.h>
-#include <wtf/Hasher.h>
 
 namespace JSC {
 
@@ -72,17 +71,18 @@ private:
 
 class SourceCodeKey {
 public:
-    SourceCodeKey() = default;
+    SourceCodeKey()
+    {
+    }
 
     SourceCodeKey(
         const UnlinkedSourceCode& sourceCode, const String& name, SourceCodeType codeType, JSParserStrictMode strictMode, 
         JSParserScriptMode scriptMode, DerivedContextType derivedContextType, EvalContextType evalContextType, bool isArrowFunctionContext,
-        DebuggerMode debuggerMode, TypeProfilerEnabled typeProfilerEnabled, ControlFlowProfilerEnabled controlFlowProfilerEnabled, std::optional<int> functionConstructorParametersEndPosition)
+        DebuggerMode debuggerMode, TypeProfilerEnabled typeProfilerEnabled, ControlFlowProfilerEnabled controlFlowProfilerEnabled)
             : m_sourceCode(sourceCode)
             , m_name(name)
             , m_flags(codeType, strictMode, scriptMode, derivedContextType, evalContextType, isArrowFunctionContext, debuggerMode, typeProfilerEnabled, controlFlowProfilerEnabled)
-            , m_functionConstructorParametersEndPosition(functionConstructorParametersEndPosition.value_or(-1))
-            , m_hash(sourceCode.hash() ^ computeHash(m_flags.bits(), m_functionConstructorParametersEndPosition))
+            , m_hash(sourceCode.hash() ^ m_flags.bits())
     {
     }
 
@@ -108,7 +108,6 @@ public:
         return m_hash == other.m_hash
             && length() == other.length()
             && m_flags == other.m_flags
-            && m_functionConstructorParametersEndPosition == other.m_functionConstructorParametersEndPosition
             && m_name == other.m_name
             && string() == other.string();
     }
@@ -128,8 +127,7 @@ private:
     UnlinkedSourceCode m_sourceCode;
     String m_name;
     SourceCodeFlags m_flags;
-    int m_functionConstructorParametersEndPosition { -1 };
-    unsigned m_hash { 0 };
+    unsigned m_hash;
 };
 
 } // namespace JSC
index faafb72..00a827a 100644 (file)
@@ -57,8 +57,7 @@ UnlinkedCodeBlockType* CodeCache::getUnlinkedGlobalCodeBlock(VM& vm, ExecutableT
         source, String(), CacheTypes<UnlinkedCodeBlockType>::codeType, strictMode, scriptMode, 
         derivedContextType, evalContextType, isArrowFunctionContext, debuggerMode, 
         vm.typeProfiler() ? TypeProfilerEnabled::Yes : TypeProfilerEnabled::No, 
-        vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No,
-        std::nullopt);
+        vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No);
     SourceCodeValue* cache = m_sourceCode.findCacheAndUpdateAge(key);
     if (cache && Options::useCodeCache()) {
         UnlinkedCodeBlockType* unlinkedCodeBlock = jsCast<UnlinkedCodeBlockType*>(cache->cell.get());
@@ -96,7 +95,7 @@ UnlinkedModuleProgramCodeBlock* CodeCache::getUnlinkedModuleProgramCodeBlock(VM&
     return getUnlinkedGlobalCodeBlock<UnlinkedModuleProgramCodeBlock>(vm, executable, source, JSParserStrictMode::Strict, JSParserScriptMode::Module, debuggerMode, error, EvalContextType::None);
 }
 
-UnlinkedFunctionExecutable* CodeCache::getUnlinkedGlobalFunctionExecutable(VM& vm, const Identifier& name, const SourceCode& source, DebuggerMode debuggerMode, std::optional<int> functionConstructorParametersEndPosition, ParserError& error)
+UnlinkedFunctionExecutable* CodeCache::getUnlinkedGlobalFunctionExecutable(VM& vm, const Identifier& name, const SourceCode& source, DebuggerMode debuggerMode, ParserError& error)
 {
     bool isArrowFunctionContext = false;
     SourceCodeKey key(
@@ -108,8 +107,7 @@ UnlinkedFunctionExecutable* CodeCache::getUnlinkedGlobalFunctionExecutable(VM& v
         isArrowFunctionContext,
         debuggerMode, 
         vm.typeProfiler() ? TypeProfilerEnabled::Yes : TypeProfilerEnabled::No, 
-        vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No,
-        functionConstructorParametersEndPosition);
+        vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No);
     SourceCodeValue* cache = m_sourceCode.findCacheAndUpdateAge(key);
     if (cache && Options::useCodeCache()) {
         UnlinkedFunctionExecutable* executable = jsCast<UnlinkedFunctionExecutable*>(cache->cell.get());
@@ -119,14 +117,25 @@ UnlinkedFunctionExecutable* CodeCache::getUnlinkedGlobalFunctionExecutable(VM& v
     }
 
     JSTextPosition positionBeforeLastNewline;
-    std::unique_ptr<ProgramNode> program = parseFunctionForFunctionConstructor(vm, source, error, &positionBeforeLastNewline, functionConstructorParametersEndPosition);
+    std::unique_ptr<ProgramNode> program = parse<ProgramNode>(
+        &vm, source, Identifier(), JSParserBuiltinMode::NotBuiltin,
+        JSParserStrictMode::NotStrict, JSParserScriptMode::Classic, SourceParseMode::ProgramMode, SuperBinding::NotNeeded,
+        error, &positionBeforeLastNewline);
     if (!program) {
         RELEASE_ASSERT(error.isValid());
         return nullptr;
     }
 
     // This function assumes an input string that would result in a single function declaration.
-    StatementNode* funcDecl = program->singleStatement();
+    StatementNode* statement = program->singleStatement();
+    if (UNLIKELY(!statement)) {
+        JSToken token;
+        error = ParserError(ParserError::SyntaxError, ParserError::SyntaxErrorIrrecoverable, token, "Parser error", -1);
+        return nullptr;
+    }
+    ASSERT(statement->isBlock());
+
+    StatementNode* funcDecl = static_cast<BlockNode*>(statement)->singleStatement();
     if (UNLIKELY(!funcDecl)) {
         JSToken token;
         error = ParserError(ParserError::SyntaxError, ParserError::SyntaxErrorIrrecoverable, token, "Parser error", -1);
index 53e3fda..ab70b65 100644 (file)
@@ -194,7 +194,7 @@ public:
     UnlinkedProgramCodeBlock* getUnlinkedProgramCodeBlock(VM&, ProgramExecutable*, const SourceCode&, JSParserStrictMode, DebuggerMode, ParserError&);
     UnlinkedEvalCodeBlock* getUnlinkedEvalCodeBlock(VM&, IndirectEvalExecutable*, const SourceCode&, JSParserStrictMode, DebuggerMode, ParserError&, EvalContextType);
     UnlinkedModuleProgramCodeBlock* getUnlinkedModuleProgramCodeBlock(VM&, ModuleProgramExecutable*, const SourceCode&, DebuggerMode, ParserError&);
-    UnlinkedFunctionExecutable* getUnlinkedGlobalFunctionExecutable(VM&, const Identifier&, const SourceCode&, DebuggerMode, std::optional<int> functionConstructorParametersEndPosition, ParserError&);
+    UnlinkedFunctionExecutable* getUnlinkedGlobalFunctionExecutable(VM&, const Identifier&, const SourceCode&, DebuggerMode, ParserError&);
 
     void clear() { m_sourceCode.clear(); }
 
index 9b3d35d..265049f 100644 (file)
@@ -94,48 +94,82 @@ JSObject* constructFunctionSkippingEvalEnabledCheck(
         prefix = "async function ";
         break;
     case FunctionConstructionMode::AsyncGenerator:
-        prefix = "async function*";
+        prefix = "{async function*";
         break;
     }
 
+    auto checkBody = [&] (const String& body) {
+        // The spec mandates that the body parses a valid function body independent
+        // of the parameters.
+        String program = makeString("(", prefix, "(){\n", body, "\n})");
+        SourceCode source = makeSource(program, sourceOrigin, sourceURL, position);
+        JSValue exception;
+        checkSyntax(exec, source, &exception);
+        if (exception) {
+            scope.throwException(exec, exception);
+            return;
+        }
+    };
+
     // How we stringify functions is sometimes important for web compatibility.
     // See https://bugs.webkit.org/show_bug.cgi?id=24350.
     String program;
-    std::optional<int> functionConstructorParametersEndPosition = std::nullopt;
     if (args.isEmpty())
-        program = makeString(prefix, functionName.string(), "() {\n\n}");
+        program = makeString("{", prefix, functionName.string(), "() {\n\n}}");
     else if (args.size() == 1) {
         auto body = args.at(0).toWTFString(exec);
         RETURN_IF_EXCEPTION(scope, nullptr);
-        program = makeString(prefix, functionName.string(), "() {\n", body, "\n}");
+        checkBody(body);
+        RETURN_IF_EXCEPTION(scope, nullptr);
+        program = makeString("{", prefix, functionName.string(), "() {\n", body, "\n}}");
     } else {
         StringBuilder builder;
+        builder.append('{');
         builder.append(prefix);
         builder.append(functionName.string());
-
         builder.append('(');
+        StringBuilder parameterBuilder;
         auto viewWithString = args.at(0).toString(exec)->viewWithUnderlyingString(exec);
         RETURN_IF_EXCEPTION(scope, nullptr);
-        builder.append(viewWithString.view);
+        parameterBuilder.append(viewWithString.view);
         for (size_t i = 1; i < args.size() - 1; i++) {
-            builder.appendLiteral(", ");
+            parameterBuilder.appendLiteral(", ");
             auto viewWithString = args.at(i).toString(exec)->viewWithUnderlyingString(exec);
             RETURN_IF_EXCEPTION(scope, nullptr);
-            builder.append(viewWithString.view);
+            parameterBuilder.append(viewWithString.view);
+        }
+        auto body = args.at(args.size() - 1).toWTFString(exec);
+        RETURN_IF_EXCEPTION(scope, nullptr);
+
+        {
+            // The spec mandates that the parameters parse as a valid parameter list
+            // independent of the function body.
+            String program = tryMakeString("(", prefix, "(", parameterBuilder.toString(), "){\n\n})");
+            if (UNLIKELY(!program)) {
+                throwOutOfMemoryError(exec, scope);
+                return nullptr;
+            }
+            SourceCode source = makeSource(program, sourceOrigin, sourceURL, position);
+            JSValue exception;
+            checkSyntax(exec, source, &exception);
+            if (exception) {
+                scope.throwException(exec, exception);
+                return nullptr;
+            }
         }
-        functionConstructorParametersEndPosition = builder.length() + 1;
-        builder.appendLiteral(") {\n");
 
-        auto body = args.at(args.size() - 1).toString(exec)->viewWithUnderlyingString(exec);
+        builder.append(parameterBuilder);
+        builder.appendLiteral(") {\n");
+        checkBody(body);
         RETURN_IF_EXCEPTION(scope, nullptr);
-        builder.append(body.view);
-        builder.appendLiteral("\n}");
+        builder.append(body);
+        builder.appendLiteral("\n}}");
         program = builder.toString();
     }
 
     SourceCode source = makeSource(program, sourceOrigin, sourceURL, position);
     JSObject* exception = nullptr;
-    FunctionExecutable* function = FunctionExecutable::fromGlobalCode(functionName, *exec, source, exception, overrideLineNumber, functionConstructorParametersEndPosition);
+    FunctionExecutable* function = FunctionExecutable::fromGlobalCode(functionName, *exec, source, exception, overrideLineNumber);
     if (!function) {
         ASSERT(exception);
         return throwException(exec, scope, exception);
index eed3c21..d5770d4 100644 (file)
@@ -94,11 +94,11 @@ void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
 
 FunctionExecutable* FunctionExecutable::fromGlobalCode(
     const Identifier& name, ExecState& exec, const SourceCode& source, 
-    JSObject*& exception, int overrideLineNumber, std::optional<int> functionConstructorParametersEndPosition)
+    JSObject*& exception, int overrideLineNumber)
 {
     UnlinkedFunctionExecutable* unlinkedExecutable = 
         UnlinkedFunctionExecutable::fromGlobalCode(
-            name, exec, source, exception, overrideLineNumber, functionConstructorParametersEndPosition);
+            name, exec, source, exception, overrideLineNumber);
     if (!unlinkedExecutable)
         return nullptr;
 
index 6ba85a1..3a93b58 100644 (file)
@@ -55,7 +55,7 @@ public:
     }
     static FunctionExecutable* fromGlobalCode(
         const Identifier& name, ExecState&, const SourceCode&, 
-        JSObject*& exception, int overrideLineNumber, std::optional<int> functionConstructorParametersEndPosition);
+        JSObject*& exception, int overrideLineNumber);
 
     static void destroy(JSCell*);