Changeset 237254 in webkit
- Timestamp:
- Oct 18, 2018, 6:04:22 AM (8 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 27 edited
-
JSTests/ChakraCore/test/Function/FuncBodyES5.baseline-jsc (modified) (1 diff)
-
JSTests/ChangeLog (modified) (1 diff)
-
JSTests/stress/function-cache-with-parameters-end-position.js (added)
-
JSTests/stress/function-constructor-name.js (added)
-
JSTests/test262/expectations.yaml (modified) (1 diff)
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/fast/dom/attribute-event-listener-errors-expected.txt (modified) (1 diff)
-
LayoutTests/fast/events/attribute-listener-deletion-crash-expected.txt (modified) (1 diff)
-
LayoutTests/fast/events/window-onerror-syntax-error-in-attr-expected.txt (modified) (1 diff)
-
LayoutTests/imported/w3c/ChangeLog (modified) (1 diff)
-
LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/inline-event-handler-ordering-expected.txt (modified) (1 diff)
-
LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/invalid-uncompiled-raw-handler-compiled-late-expected.txt (modified) (1 diff)
-
LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-attribute-expected.txt (modified) (1 diff)
-
LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-body-onerror-expected.txt (modified) (1 diff)
-
LayoutTests/js/dom/invalid-syntax-for-function-expected.txt (modified) (1 diff)
-
LayoutTests/js/dom/script-start-end-locations-expected.txt (modified) (1 diff)
-
Source/JavaScriptCore/ChangeLog (modified) (1 diff)
-
Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h (modified) (1 diff)
-
Source/JavaScriptCore/parser/Parser.cpp (modified) (9 diffs)
-
Source/JavaScriptCore/parser/Parser.h (modified) (10 diffs)
-
Source/JavaScriptCore/parser/ParserModes.h (modified) (1 diff)
-
Source/JavaScriptCore/parser/ParserTokens.h (modified) (2 diffs)
-
Source/JavaScriptCore/parser/SourceCodeKey.h (modified) (4 diffs)
-
Source/JavaScriptCore/runtime/CodeCache.cpp (modified) (5 diffs)
-
Source/JavaScriptCore/runtime/CodeCache.h (modified) (1 diff)
-
Source/JavaScriptCore/runtime/FunctionConstructor.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/FunctionExecutable.cpp (modified) (1 diff)
-
Source/JavaScriptCore/runtime/FunctionExecutable.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChakraCore/test/Function/FuncBodyES5.baseline-jsc
r237128 r237254 10 10 PASS: 9: new Function succeeded as expected 11 11 PASS: 10: new Function succeeded as expected 12 PASS: 100: new Function failed as expected. SyntaxError: Unexpected token '{'. Expected ')' to end a compound expression.13 PASS: 100: new Function failed as expected. SyntaxError: Unexpected token '{'. Expected ')' to end a compound expression.14 PASS: 101: new Function failed as expected. SyntaxError: Unexpected keyword 'function'. Expected ')' to end a compound expression.15 PASS: 102: new Function failed as expected. SyntaxError: Unexpected keyword 'function'. Expected ')' to end a compound expression.16 PASS: 103: new Function failed as expected. SyntaxError: Unexpected keyword 'function'. Expected ')' to end a compound expression.17 PASS: 104: new Function failed as expected. SyntaxError: Unexpected token ';'. Expected ')' to end a compound expression.18 PASS: 105: new Function failed as expected. SyntaxError: Unexpected token ';'. Expected ')' to end a compound expression.12 PASS: 100: new Function failed as expected. SyntaxError: Parser error 13 PASS: 100: new Function failed as expected. SyntaxError: Parser error 14 PASS: 101: new Function failed as expected. SyntaxError: Parser error 15 PASS: 102: new Function failed as expected. SyntaxError: Parameters should match arguments offered as parameters in Function constructor. 16 PASS: 103: new Function failed as expected. SyntaxError: Parser error 17 PASS: 104: new Function failed as expected. SyntaxError: Parameters should match arguments offered as parameters in Function constructor. 18 PASS: 105: new Function failed as expected. SyntaxError: Parser error 19 19 PASS: 200: new Function failed as expected. SyntaxError: Unexpected token ','. Expected a parameter pattern or a ')' in parameter list. 20 20 PASS: 200: new Function failed as expected. SyntaxError: Unexpected token ','. Expected a parameter pattern or a ')' in parameter list. -
trunk/JSTests/ChangeLog
r237253 r237254 1 2018-10-18 Yusuke Suzuki <yusukesuzuki@slowstart.org> 2 3 [JSC] JSC should have "parseFunction" to optimize Function constructor 4 https://bugs.webkit.org/show_bug.cgi?id=190340 5 6 Reviewed by Mark Lam. 7 8 This patch fixes the line number of syntax errors raised by the Function constructor, 9 since we now parse the final code only once. And we no longer use block statement 10 for Function constructor's parsing. 11 12 * ChakraCore/test/Function/FuncBodyES5.baseline-jsc: 13 * stress/function-cache-with-parameters-end-position.js: Added. 14 (shouldBe): 15 (shouldThrow): 16 (i.anonymous): 17 * stress/function-constructor-name.js: Added. 18 (shouldBe): 19 (GeneratorFunction): 20 (AsyncFunction.async): 21 (AsyncGeneratorFunction.async): 22 (anonymous): 23 (async.anonymous): 24 * test262/expectations.yaml: 25 1 26 2018-10-18 Commit Queue <commit-queue@webkit.org> 2 27 -
trunk/JSTests/test262/expectations.yaml
r237128 r237254 901 901 strict mode: "ReferenceError: Can't find variable: verifyNotEnumerable" 902 902 test/built-ins/Function/prototype/toString/AsyncFunction.js: 903 default: "SyntaxError: Unexpected token ' }'. Expected a ')' or a ',' after a parameter declaration."904 strict mode: "SyntaxError: Unexpected token ' }'. Expected a ')' or a ',' after a parameter declaration."903 default: "SyntaxError: Unexpected token ';'. Expected a ')' or a ',' after a parameter declaration." 904 strict mode: "SyntaxError: Unexpected token ';'. Expected a ')' or a ',' after a parameter declaration." 905 905 test/built-ins/Function/prototype/toString/Function.js: 906 default: "SyntaxError: Unexpected token ' }'. Expected a ')' or a ',' after a parameter declaration."907 strict mode: "SyntaxError: Unexpected token ' }'. Expected a ')' or a ',' after a parameter declaration."906 default: "SyntaxError: Unexpected token ';'. Expected a ')' or a ',' after a parameter declaration." 907 strict mode: "SyntaxError: Unexpected token ';'. Expected a ')' or a ',' after a parameter declaration." 908 908 test/built-ins/Function/prototype/toString/GeneratorFunction.js: 909 default: "SyntaxError: Unexpected token '}'. Expected a ')' or a ',' after a parameter declaration."910 strict mode: "SyntaxError: Unexpected token '}'. Expected a ')' or a ',' after a parameter declaration."909 default: "SyntaxError: Unexpected keyword 'yield'. Expected a ')' or a ',' after a parameter declaration." 910 strict mode: "SyntaxError: Unexpected keyword 'yield'. Expected a ')' or a ',' after a parameter declaration." 911 911 test/built-ins/Function/prototype/toString/async-arrow-function.js: 912 912 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 */ })" -
trunk/LayoutTests/ChangeLog
r237245 r237254 1 2018-10-18 Yusuke Suzuki <yusukesuzuki@slowstart.org> 2 3 [JSC] JSC should have "parseFunction" to optimize Function constructor 4 https://bugs.webkit.org/show_bug.cgi?id=190340 5 6 Reviewed by Mark Lam. 7 8 * fast/dom/attribute-event-listener-errors-expected.txt: 9 * fast/events/attribute-listener-deletion-crash-expected.txt: 10 * fast/events/window-onerror-syntax-error-in-attr-expected.txt: 11 * js/dom/invalid-syntax-for-function-expected.txt: 12 * js/dom/script-start-end-locations-expected.txt: 13 1 14 2018-10-17 Wenson Hsieh <wenson_hsieh@apple.com> 2 15 -
trunk/LayoutTests/fast/dom/attribute-event-listener-errors-expected.txt
r237128 r237254 1 1 CONSOLE MESSAGE: line 4: ReferenceError: Can't find variable: error 2 CONSOLE MESSAGE: line 9: SyntaxError: Invalid character: '@'2 CONSOLE MESSAGE: line 5: SyntaxError: Invalid character: '@' 3 3 This test verifies that an attribute event listener error shows the right line number even if the attribute contains newlines. 4 4 -
trunk/LayoutTests/fast/events/attribute-listener-deletion-crash-expected.txt
r237128 r237254 1 CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'2 CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'3 CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'4 CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'5 CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'6 CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'7 CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'8 CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'9 CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'10 CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'11 CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'12 CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'13 CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'14 CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'15 CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'16 CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'17 CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'18 CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'19 CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'20 CONSOLE MESSAGE: line 2: SyntaxError: Unexpected token '|'1 CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|' 2 CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|' 3 CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|' 4 CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|' 5 CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|' 6 CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|' 7 CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|' 8 CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|' 9 CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|' 10 CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|' 11 CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|' 12 CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|' 13 CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|' 14 CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|' 15 CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|' 16 CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|' 17 CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|' 18 CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|' 19 CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|' 20 CONSOLE MESSAGE: line 1: SyntaxError: Unexpected token '|' 21 21 PASS -
trunk/LayoutTests/fast/events/window-onerror-syntax-error-in-attr-expected.txt
r237128 r237254 1 1 Test that window.onerror is called on window object when there is a syntax error in attribute handler. Bug 70991. 2 2 3 Main frame window.onerror: SyntaxError: Unexpected token '%' at window-onerror-syntax-error-in-attr.html:1 1:38 SyntaxError: Unexpected token '%'4 Main frame window.onerror: SyntaxError: Unexpected token '%' at window-onerror-syntax-error-in-attr.html:3 7:38 SyntaxError: Unexpected token '%'5 Main frame window.onerror: SyntaxError: Unexpected token '%' at window-onerror-syntax-error-in-attr.html:3 7:14 SyntaxError: Unexpected token '%'3 Main frame window.onerror: SyntaxError: Unexpected token '%' at window-onerror-syntax-error-in-attr.html:10:38 SyntaxError: Unexpected token '%' 4 Main frame window.onerror: SyntaxError: Unexpected token '%' at window-onerror-syntax-error-in-attr.html:36:38 SyntaxError: Unexpected token '%' 5 Main frame window.onerror: SyntaxError: Unexpected token '%' at window-onerror-syntax-error-in-attr.html:36:14 SyntaxError: Unexpected token '%' 6 6 Button 1 Button 2 Button 3 -
trunk/LayoutTests/imported/w3c/ChangeLog
r237245 r237254 1 2018-10-18 Yusuke Suzuki <yusukesuzuki@slowstart.org> 2 3 [JSC] JSC should have "parseFunction" to optimize Function constructor 4 https://bugs.webkit.org/show_bug.cgi?id=190340 5 6 Reviewed by Mark Lam. 7 8 * web-platform-tests/html/webappapis/scripting/events/inline-event-handler-ordering-expected.txt: 9 * web-platform-tests/html/webappapis/scripting/events/invalid-uncompiled-raw-handler-compiled-late-expected.txt: 10 * web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-attribute-expected.txt: 11 * web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-body-onerror-expected.txt: 12 1 13 2018-10-17 Wenson Hsieh <wenson_hsieh@apple.com> 2 14 -
trunk/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/inline-event-handler-ordering-expected.txt
r237128 r237254 1 1 CONSOLE MESSAGE: line 19: SyntaxError: Unexpected token '}' 2 CONSOLE MESSAGE: line 5 4: SyntaxError: Unexpected token '}'2 CONSOLE MESSAGE: line 52: SyntaxError: Unexpected token '}' 3 3 4 4 PASS Inline event handlers retain their ordering when invalid and force-compiled -
trunk/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/invalid-uncompiled-raw-handler-compiled-late-expected.txt
r237128 r237254 1 CONSOLE MESSAGE: line 2 6: SyntaxError: Unexpected token '}'. Expected ')' to end a compound expression.2 CONSOLE MESSAGE: line 21: SyntaxError: Unexpected token '}'. Expected ')' to end a compound expression.1 CONSOLE MESSAGE: line 24: SyntaxError: Parser error 2 CONSOLE MESSAGE: line 21: SyntaxError: Parser error 3 3 4 4 FAIL Invalid uncompiled raw handlers should only be compiled when about to call them. assert_array_equals: lengths differ, expected 3 got 4 -
trunk/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-attribute-expected.txt
r237128 r237254 1 CONSOLE MESSAGE: line 2 6: SyntaxError: Unexpected token ')'1 CONSOLE MESSAGE: line 24: SyntaxError: Unexpected end of script 2 2 3 3 PASS window.onerror - compile error in attribute -
trunk/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-body-onerror-expected.txt
r237128 r237254 1 1 CONSOLE MESSAGE: line 19: SyntaxError: Unexpected token ')' 2 CONSOLE MESSAGE: line 1 8: SyntaxError: Unexpected token ')'2 CONSOLE MESSAGE: line 16: SyntaxError: Unexpected end of script 3 3 4 4 PASS window.onerror - compile error in <body onerror> -
trunk/LayoutTests/js/dom/invalid-syntax-for-function-expected.txt
r237128 r237254 1 CONSOLE MESSAGE: line 2: SyntaxError: Invalid character: '#'1 CONSOLE MESSAGE: line 1: SyntaxError: Invalid character: '#' 2 2 This test ensures we don't crash when we are given garbage for an attribute expecting a function. 3 3 https://bugs.webkit.org/show_bug.cgi?id=19025 -
trunk/LayoutTests/js/dom/script-start-end-locations-expected.txt
r237128 r237254 244 244 245 245 new Function Object: 246 function "anonymous" { 1: 20- 2:228 }246 function "anonymous" { 1:19 - 2:228 } 247 247 function "nf1a" { 2:57 - 2:219 } 248 248 function "nf1b" { 2:87 - 2:209 } 249 249 function "nf1c" { 2:117 - 2:199 } 250 250 eval { 1:1 - 1:56 } 251 function "anonymous" { 1: 20- 18:8 }251 function "anonymous" { 1:19 - 18:8 } 252 252 function "nf2a" { 5:18 - 16:5 } 253 253 function "nf2b" { 7:22 - 14:9 } 254 254 function "nf2c" { 9:26 - 12:13 } 255 255 eval { 1:1 - 1:56 } 256 function "anonymous" { 1: 20- 2:228 }256 function "anonymous" { 1:19 - 2:228 } 257 257 function "nf1a" { 2:57 - 2:219 } 258 258 function "nf1b" { 2:87 - 2:209 } 259 259 function "nf1c" { 2:117 - 2:199 } 260 260 eval { 1:1 - 1:56 } 261 function "anonymous" { 1: 20- 2:237 }261 function "anonymous" { 1:19 - 2:237 } 262 262 function "nfi1a" { 2:58 - 2:227 } 263 263 function "nfi1b" { 2:90 - 2:216 } 264 264 function "nfi1c" { 2:122 - 2:205 } 265 265 eval { 1:1 - 1:56 } 266 function "anonymous" { 1: 20- 18:8 }266 function "anonymous" { 1:19 - 18:8 } 267 267 function "nf2a" { 5:18 - 16:5 } 268 268 function "nf2b" { 7:22 - 14:9 } 269 269 function "nf2c" { 9:26 - 12:13 } 270 270 eval { 1:1 - 1:56 } 271 function "anonymous" { 1: 20- 18:9 }271 function "anonymous" { 1:19 - 18:9 } 272 272 function "nfi2a" { 5:19 - 16:5 } 273 273 function "nfi2b" { 7:23 - 14:9 } -
trunk/Source/JavaScriptCore/ChangeLog
r237253 r237254 1 2018-10-18 Yusuke Suzuki <yusukesuzuki@slowstart.org> 2 3 [JSC] JSC should have "parseFunction" to optimize Function constructor 4 https://bugs.webkit.org/show_bug.cgi?id=190340 5 6 Reviewed by Mark Lam. 7 8 The current Function constructor is suboptimal. We parse the piece of the same code three times to meet 9 the spec requirement. (1) check parameters syntax, (2) check body syntax, and (3) parse the entire function. 10 And to parse 1-3 correctly, we create two strings, the parameters and the entire function. This operation 11 is really costly and ideally we should meet the above requirement by the one time parsing. 12 13 To meet the above requirement, we add a special function for Parser, parseSingleFunction. This function 14 takes `std::optional<int> functionConstructorParametersEndPosition` and check this end position is correct in the parser. 15 For example, if we run the code, 16 17 Function('/*', '*/){') 18 19 According to the spec, this should produce '/*' parameter string and '*/){' body string. And parameter 20 string should be syntax-checked by the parser, and raise the error since it is incorrect. Instead of doing 21 that, in our implementation, we first create the entire string. 22 23 function anonymous(/*) { 24 */){ 25 } 26 27 And we parse it. At that time, we also pass the end position of the parameters to the parser. In the above case, 28 the position of the `function anonymous(/*)' <> is passed. And in the parser, we check that the last token 29 offset of the parameters is the given end position. This check allows us to raise the error correctly to the 30 above example while we parse the entire function only once. And we do not need to create two strings too. 31 32 This improves the performance of the Function constructor significantly. And web-tooling-benchmark/uglify-js is 33 significantly sped up (28.2%). 34 35 Before: 36 uglify-js: 2.94 runs/s 37 After: 38 uglify-js: 3.77 runs/s 39 40 * bytecode/UnlinkedFunctionExecutable.cpp: 41 (JSC::UnlinkedFunctionExecutable::fromGlobalCode): 42 * bytecode/UnlinkedFunctionExecutable.h: 43 * parser/Parser.cpp: 44 (JSC::Parser<LexerType>::parseInner): 45 (JSC::Parser<LexerType>::parseSingleFunction): 46 (JSC::Parser<LexerType>::parseFunctionInfo): 47 (JSC::Parser<LexerType>::parseFunctionDeclaration): 48 (JSC::Parser<LexerType>::parseAsyncFunctionDeclaration): 49 * parser/Parser.h: 50 (JSC::Parser<LexerType>::parse): 51 (JSC::parse): 52 (JSC::parseFunctionForFunctionConstructor): 53 * parser/ParserModes.h: 54 * parser/ParserTokens.h: 55 (JSC::JSTextPosition::JSTextPosition): 56 (JSC::JSTokenLocation::JSTokenLocation): Deleted. 57 * parser/SourceCodeKey.h: 58 (JSC::SourceCodeKey::SourceCodeKey): 59 (JSC::SourceCodeKey::operator== const): 60 * runtime/CodeCache.cpp: 61 (JSC::CodeCache::getUnlinkedGlobalCodeBlock): 62 (JSC::CodeCache::getUnlinkedGlobalFunctionExecutable): 63 * runtime/CodeCache.h: 64 * runtime/FunctionConstructor.cpp: 65 (JSC::constructFunctionSkippingEvalEnabledCheck): 66 * runtime/FunctionExecutable.cpp: 67 (JSC::FunctionExecutable::fromGlobalCode): 68 * runtime/FunctionExecutable.h: 69 1 70 2018-10-18 Commit Queue <commit-queue@webkit.org> 2 71 -
trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp
r237128 r237254 175 175 UnlinkedFunctionExecutable* UnlinkedFunctionExecutable::fromGlobalCode( 176 176 const Identifier& name, ExecState& exec, const SourceCode& source, 177 JSObject*& exception, int overrideLineNumber )177 JSObject*& exception, int overrideLineNumber, std::optional<int> functionConstructorParametersEndPosition) 178 178 { 179 179 ParserError error; … … 182 182 CodeCache* codeCache = vm.codeCache(); 183 183 DebuggerMode debuggerMode = globalObject.hasInteractiveDebugger() ? DebuggerOn : DebuggerOff; 184 UnlinkedFunctionExecutable* executable = codeCache->getUnlinkedGlobalFunctionExecutable(vm, name, source, debuggerMode, error);184 UnlinkedFunctionExecutable* executable = codeCache->getUnlinkedGlobalFunctionExecutable(vm, name, source, debuggerMode, functionConstructorParametersEndPosition, error); 185 185 186 186 if (globalObject.hasDebugger()) -
trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h
r237128 r237254 108 108 static UnlinkedFunctionExecutable* fromGlobalCode( 109 109 const Identifier&, ExecState&, const SourceCode&, JSObject*& exception, 110 int overrideLineNumber );110 int overrideLineNumber, std::optional<int> functionConstructorParametersEndPosition); 111 111 112 112 JS_EXPORT_PRIVATE FunctionExecutable* link(VM&, const SourceCode& parentSource, std::optional<int> overrideLineNumber = std::nullopt, Intrinsic = NoIntrinsic); -
trunk/Source/JavaScriptCore/parser/Parser.cpp
r237128 r237254 195 195 196 196 template <typename LexerType> 197 String Parser<LexerType>::parseInner(const Identifier& calleeName, SourceParseMode parseMode )197 String Parser<LexerType>::parseInner(const Identifier& calleeName, SourceParseMode parseMode, ParsingContext parsingContext, std::optional<int> functionConstructorParametersEndPosition) 198 198 { 199 199 String parseError = String(); … … 239 239 else if (isAsyncGeneratorWrapperParseMode(parseMode)) 240 240 sourceElements = parseAsyncGeneratorFunctionSourceElements(context, parseMode, isArrowFunctionBodyExpression, CheckForStrictMode); 241 else if (parsingContext == ParsingContext::FunctionConstructor) 242 sourceElements = parseSingleFunction(context, functionConstructorParametersEndPosition); 241 243 else 242 244 sourceElements = parseSourceElements(context, CheckForStrictMode); … … 611 613 return sourceElements; 612 614 } 615 616 template <typename LexerType> 617 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSingleFunction(TreeBuilder& context, std::optional<int> functionConstructorParametersEndPosition) 618 { 619 TreeSourceElements sourceElements = context.createSourceElements(); 620 TreeStatement statement = 0; 621 switch (m_token.m_type) { 622 case FUNCTION: 623 statement = parseFunctionDeclaration(context, ExportType::NotExported, DeclarationDefaultContext::Standard, functionConstructorParametersEndPosition); 624 break; 625 case IDENT: 626 if (*m_token.m_data.ident == m_vm->propertyNames->async && !m_token.m_data.escaped) { 627 next(); 628 failIfFalse(match(FUNCTION) && !m_lexer->prevTerminator(), "Cannot parse the async function"); 629 statement = parseAsyncFunctionDeclaration(context, ExportType::NotExported, DeclarationDefaultContext::Standard, functionConstructorParametersEndPosition); 630 break; 631 } 632 FALLTHROUGH; 633 default: 634 failDueToUnexpectedToken(); 635 break; 636 } 637 638 if (statement) { 639 context.setEndOffset(statement, m_lastTokenEndPosition.offset); 640 context.appendStatement(sourceElements, statement); 641 } 642 643 propagateError(); 644 return sourceElements; 645 } 646 613 647 614 648 template <typename LexerType> … … 2264 2298 2265 2299 template <typename LexerType> 2266 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 )2300 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) 2267 2301 { 2268 2302 RELEASE_ASSERT(isFunctionParseMode(mode)); … … 2460 2494 2461 2495 matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body"); 2496 2497 // If the code is invoked from function constructor, we need to ensure that parameters are only composed by the string offered as parameters. 2498 if (functionConstructorParametersEndPosition) 2499 semanticFailIfFalse(lastTokenEndPosition().offset == *functionConstructorParametersEndPosition, "Parameters should match arguments offered as parameters in Function constructor"); 2462 2500 2463 2501 // BytecodeGenerator emits code to throw TypeError when a class constructor is "call"ed. … … 2594 2632 2595 2633 template <typename LexerType> 2596 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext )2634 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext, std::optional<int> functionConstructorParametersEndPosition) 2597 2635 { 2598 2636 ASSERT(match(FUNCTION)); … … 2631 2669 } 2632 2670 2633 failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration )), "Cannot parse this function");2671 failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration, functionConstructorParametersEndPosition)), "Cannot parse this function"); 2634 2672 ASSERT(functionInfo.name); 2635 2673 … … 2652 2690 2653 2691 template <typename LexerType> 2654 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseAsyncFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext )2692 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseAsyncFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext, std::optional<int> functionConstructorParametersEndPosition) 2655 2693 { 2656 2694 ASSERT(match(FUNCTION)); … … 2689 2727 } 2690 2728 2691 failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration )), "Cannot parse this async function");2729 failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration, functionConstructorParametersEndPosition)), "Cannot parse this async function"); 2692 2730 failIfFalse(functionInfo.name, "Async function statements must have a name"); 2693 2731 -
trunk/Source/JavaScriptCore/parser/Parser.h
r237128 r237254 860 860 }; 861 861 862 enum class ArgumentType { 863 Normal, 864 Spread 865 }; 862 enum class ArgumentType { Normal, Spread }; 863 enum class ParsingContext { Program, FunctionConstructor, Eval }; 866 864 867 865 template <typename LexerType> … … 875 873 876 874 template <class ParsedNode> 877 std::unique_ptr<ParsedNode> parse(ParserError&, const Identifier&, SourceParseMode );875 std::unique_ptr<ParsedNode> parse(ParserError&, const Identifier&, SourceParseMode, ParsingContext, std::optional<int> functionConstructorParametersEndPosition = std::nullopt); 878 876 879 877 JSTextPosition positionBeforeLastNewline() const { return m_lexer->positionBeforeLastNewline(); } … … 1313 1311 1314 1312 Parser(); 1315 String parseInner(const Identifier&, SourceParseMode); 1313 1314 String parseInner(const Identifier&, SourceParseMode, ParsingContext, std::optional<int> functionConstructorParametersEndPosition = std::nullopt); 1316 1315 1317 1316 void didFinishParsing(SourceElements*, DeclarationStacks::FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, CodeFeatures, int); … … 1525 1524 template <class TreeBuilder> TreeSourceElements parseAsyncFunctionSourceElements(TreeBuilder&, SourceParseMode, bool isArrowFunctionBodyExpression, SourceElementsMode); 1526 1525 template <class TreeBuilder> TreeSourceElements parseAsyncGeneratorFunctionSourceElements(TreeBuilder&, SourceParseMode, bool isArrowFunctionBodyExpression, SourceElementsMode); 1526 template <class TreeBuilder> TreeSourceElements parseSingleFunction(TreeBuilder&, std::optional<int> functionConstructorParametersEndPosition); 1527 1527 template <class TreeBuilder> TreeStatement parseStatementListItem(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength); 1528 1528 template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength = 0); 1529 1529 enum class ExportType { Exported, NotExported }; 1530 1530 template <class TreeBuilder> TreeStatement parseClassDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard); 1531 template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard );1531 template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard, std::optional<int> functionConstructorParametersEndPosition = std::nullopt); 1532 1532 template <class TreeBuilder> TreeStatement parseFunctionDeclarationStatement(TreeBuilder&, bool isAsync, bool parentAllowsFunctionDeclarationAsStatement); 1533 template <class TreeBuilder> TreeStatement parseAsyncFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard );1533 template <class TreeBuilder> TreeStatement parseAsyncFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard, std::optional<int> functionConstructorParametersEndPosition = std::nullopt); 1534 1534 template <class TreeBuilder> NEVER_INLINE bool maybeParseAsyncFunctionDeclarationStatement(TreeBuilder& context, TreeStatement& result, bool parentAllowsFunctionDeclarationAsStatement); 1535 1535 template <class TreeBuilder> TreeStatement parseVariableDeclaration(TreeBuilder&, DeclarationType, ExportType = ExportType::NotExported); … … 1600 1600 1601 1601 enum class FunctionDefinitionType { Expression, Declaration, Method }; 1602 template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionNameRequirements, SourceParseMode, bool nameIsInContainingScope, ConstructorKind, SuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>&, FunctionDefinitionType );1602 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); 1603 1603 1604 1604 ALWAYS_INLINE bool isArrowFunctionParameters(); … … 1848 1848 template <typename LexerType> 1849 1849 template <class ParsedNode> 1850 std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const Identifier& calleeName, SourceParseMode parseMode )1850 std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const Identifier& calleeName, SourceParseMode parseMode, ParsingContext parsingContext, std::optional<int> functionConstructorParametersEndPosition) 1851 1851 { 1852 1852 int errLine; … … 1865 1865 unsigned startColumn = m_source->startColumn().zeroBasedInt(); 1866 1866 1867 String parseError = parseInner(calleeName, parseMode );1867 String parseError = parseInner(calleeName, parseMode, parsingContext, functionConstructorParametersEndPosition); 1868 1868 1869 1869 int lineNumber = m_lexer->lineNumber(); … … 1960 1960 if (source.provider()->source().is8Bit()) { 1961 1961 Parser<Lexer<LChar>> parser(vm, source, builtinMode, strictMode, scriptMode, parseMode, superBinding, defaultConstructorKind, derivedContextType, isEvalNode<ParsedNode>(), evalContextType, debuggerParseData); 1962 result = parser.parse<ParsedNode>(error, name, parseMode );1962 result = parser.parse<ParsedNode>(error, name, parseMode, isEvalNode<ParsedNode>() ? ParsingContext::Eval : ParsingContext::Program); 1963 1963 if (positionBeforeLastNewline) 1964 1964 *positionBeforeLastNewline = parser.positionBeforeLastNewline(); … … 1973 1973 ASSERT_WITH_MESSAGE(defaultConstructorKind == ConstructorKind::None, "BuiltinExecutables::createDefaultConstructor should always use a 8-bit string"); 1974 1974 Parser<Lexer<UChar>> parser(vm, source, builtinMode, strictMode, scriptMode, parseMode, superBinding, defaultConstructorKind, derivedContextType, isEvalNode<ParsedNode>(), evalContextType, debuggerParseData); 1975 result = parser.parse<ParsedNode>(error, name, parseMode );1975 result = parser.parse<ParsedNode>(error, name, parseMode, isEvalNode<ParsedNode>() ? ParsingContext::Eval : ParsingContext::Program); 1976 1976 if (positionBeforeLastNewline) 1977 1977 *positionBeforeLastNewline = parser.positionBeforeLastNewline(); … … 1987 1987 } 1988 1988 1989 inline std::unique_ptr<ProgramNode> parseFunctionForFunctionConstructor(VM& vm, const SourceCode& source, ParserError& error, JSTextPosition* positionBeforeLastNewline, std::optional<int> functionConstructorParametersEndPosition) 1990 { 1991 ASSERT(!source.provider()->source().isNull()); 1992 1993 MonotonicTime before; 1994 if (UNLIKELY(Options::reportParseTimes())) 1995 before = MonotonicTime::now(); 1996 1997 Identifier name; 1998 bool isEvalNode = false; 1999 std::unique_ptr<ProgramNode> result; 2000 if (source.provider()->source().is8Bit()) { 2001 Parser<Lexer<LChar>> parser(&vm, source, JSParserBuiltinMode::NotBuiltin, JSParserStrictMode::NotStrict, JSParserScriptMode::Classic, SourceParseMode::ProgramMode, SuperBinding::NotNeeded, ConstructorKind::None, DerivedContextType::None, isEvalNode, EvalContextType::None, nullptr); 2002 result = parser.parse<ProgramNode>(error, name, SourceParseMode::ProgramMode, ParsingContext::FunctionConstructor, functionConstructorParametersEndPosition); 2003 if (positionBeforeLastNewline) 2004 *positionBeforeLastNewline = parser.positionBeforeLastNewline(); 2005 } else { 2006 Parser<Lexer<UChar>> parser(&vm, source, JSParserBuiltinMode::NotBuiltin, JSParserStrictMode::NotStrict, JSParserScriptMode::Classic, SourceParseMode::ProgramMode, SuperBinding::NotNeeded, ConstructorKind::None, DerivedContextType::None, isEvalNode, EvalContextType::None, nullptr); 2007 result = parser.parse<ProgramNode>(error, name, SourceParseMode::ProgramMode, ParsingContext::FunctionConstructor, functionConstructorParametersEndPosition); 2008 if (positionBeforeLastNewline) 2009 *positionBeforeLastNewline = parser.positionBeforeLastNewline(); 2010 } 2011 2012 if (UNLIKELY(Options::reportParseTimes())) { 2013 MonotonicTime after = MonotonicTime::now(); 2014 ParseHash hash(source); 2015 dataLogLn(result ? "Parsed #" : "Failed to parse #", hash.hashForCall(), "/#", hash.hashForConstruct(), " in ", (after - before).milliseconds(), " ms."); 2016 } 2017 2018 return result; 2019 } 2020 2021 1989 2022 } // namespace -
trunk/Source/JavaScriptCore/parser/ParserModes.h
r237128 r237254 34 34 enum class JSParserBuiltinMode { NotBuiltin, Builtin }; 35 35 enum class JSParserScriptMode { Classic, Module }; 36 enum class JSParserCodeType { Program, Function, Module };37 36 38 37 enum class ConstructorKind { None, Base, Extends }; -
trunk/Source/JavaScriptCore/parser/ParserTokens.h
r237128 r237254 194 194 JSTextPosition() = default; 195 195 JSTextPosition(int _line, int _offset, int _lineStartOffset) : line(_line), offset(_offset), lineStartOffset(_lineStartOffset) { } 196 JSTextPosition(const JSTextPosition& other) : line(other.line), offset(other.offset), lineStartOffset(other.lineStartOffset) { }197 196 198 197 JSTextPosition operator+(int adjustment) const { return JSTextPosition(line, offset + adjustment, lineStartOffset); } … … 247 246 struct JSTokenLocation { 248 247 JSTokenLocation() = default; 249 JSTokenLocation(const JSTokenLocation& location)250 {251 line = location.line;252 lineStartOffset = location.lineStartOffset;253 startOffset = location.startOffset;254 endOffset = location.endOffset;255 }256 248 257 249 int line { 0 }; -
trunk/Source/JavaScriptCore/parser/SourceCodeKey.h
r237128 r237254 30 30 #include "UnlinkedSourceCode.h" 31 31 #include <wtf/HashTraits.h> 32 #include <wtf/Hasher.h> 32 33 33 34 namespace JSC { … … 72 73 class SourceCodeKey { 73 74 public: 74 SourceCodeKey() 75 { 76 } 75 SourceCodeKey() = default; 77 76 78 77 SourceCodeKey( 79 78 const UnlinkedSourceCode& sourceCode, const String& name, SourceCodeType codeType, JSParserStrictMode strictMode, 80 79 JSParserScriptMode scriptMode, DerivedContextType derivedContextType, EvalContextType evalContextType, bool isArrowFunctionContext, 81 DebuggerMode debuggerMode, TypeProfilerEnabled typeProfilerEnabled, ControlFlowProfilerEnabled controlFlowProfilerEnabled )80 DebuggerMode debuggerMode, TypeProfilerEnabled typeProfilerEnabled, ControlFlowProfilerEnabled controlFlowProfilerEnabled, std::optional<int> functionConstructorParametersEndPosition) 82 81 : m_sourceCode(sourceCode) 83 82 , m_name(name) 84 83 , m_flags(codeType, strictMode, scriptMode, derivedContextType, evalContextType, isArrowFunctionContext, debuggerMode, typeProfilerEnabled, controlFlowProfilerEnabled) 85 , m_hash(sourceCode.hash() ^ m_flags.bits()) 84 , m_functionConstructorParametersEndPosition(functionConstructorParametersEndPosition.value_or(-1)) 85 , m_hash(sourceCode.hash() ^ computeHash(m_flags.bits(), m_functionConstructorParametersEndPosition)) 86 86 { 87 87 } … … 109 109 && length() == other.length() 110 110 && m_flags == other.m_flags 111 && m_functionConstructorParametersEndPosition == other.m_functionConstructorParametersEndPosition 111 112 && m_name == other.m_name 112 113 && string() == other.string(); … … 128 129 String m_name; 129 130 SourceCodeFlags m_flags; 130 unsigned m_hash; 131 int m_functionConstructorParametersEndPosition { -1 }; 132 unsigned m_hash { 0 }; 131 133 }; 132 134 -
trunk/Source/JavaScriptCore/runtime/CodeCache.cpp
r237128 r237254 58 58 derivedContextType, evalContextType, isArrowFunctionContext, debuggerMode, 59 59 vm.typeProfiler() ? TypeProfilerEnabled::Yes : TypeProfilerEnabled::No, 60 vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No); 60 vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No, 61 std::nullopt); 61 62 SourceCodeValue* cache = m_sourceCode.findCacheAndUpdateAge(key); 62 63 if (cache && Options::useCodeCache()) { … … 96 97 } 97 98 98 UnlinkedFunctionExecutable* CodeCache::getUnlinkedGlobalFunctionExecutable(VM& vm, const Identifier& name, const SourceCode& source, DebuggerMode debuggerMode, ParserError& error)99 UnlinkedFunctionExecutable* CodeCache::getUnlinkedGlobalFunctionExecutable(VM& vm, const Identifier& name, const SourceCode& source, DebuggerMode debuggerMode, std::optional<int> functionConstructorParametersEndPosition, ParserError& error) 99 100 { 100 101 bool isArrowFunctionContext = false; … … 108 109 debuggerMode, 109 110 vm.typeProfiler() ? TypeProfilerEnabled::Yes : TypeProfilerEnabled::No, 110 vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No); 111 vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No, 112 functionConstructorParametersEndPosition); 111 113 SourceCodeValue* cache = m_sourceCode.findCacheAndUpdateAge(key); 112 114 if (cache && Options::useCodeCache()) { … … 118 120 119 121 JSTextPosition positionBeforeLastNewline; 120 std::unique_ptr<ProgramNode> program = parse<ProgramNode>( 121 &vm, source, Identifier(), JSParserBuiltinMode::NotBuiltin, 122 JSParserStrictMode::NotStrict, JSParserScriptMode::Classic, SourceParseMode::ProgramMode, SuperBinding::NotNeeded, 123 error, &positionBeforeLastNewline); 122 std::unique_ptr<ProgramNode> program = parseFunctionForFunctionConstructor(vm, source, error, &positionBeforeLastNewline, functionConstructorParametersEndPosition); 124 123 if (!program) { 125 124 RELEASE_ASSERT(error.isValid()); … … 128 127 129 128 // This function assumes an input string that would result in a single function declaration. 130 StatementNode* statement = program->singleStatement(); 131 if (UNLIKELY(!statement)) { 132 JSToken token; 133 error = ParserError(ParserError::SyntaxError, ParserError::SyntaxErrorIrrecoverable, token, "Parser error", -1); 134 return nullptr; 135 } 136 ASSERT(statement->isBlock()); 137 138 StatementNode* funcDecl = static_cast<BlockNode*>(statement)->singleStatement(); 129 StatementNode* funcDecl = program->singleStatement(); 139 130 if (UNLIKELY(!funcDecl)) { 140 131 JSToken token; -
trunk/Source/JavaScriptCore/runtime/CodeCache.h
r237128 r237254 195 195 UnlinkedEvalCodeBlock* getUnlinkedEvalCodeBlock(VM&, IndirectEvalExecutable*, const SourceCode&, JSParserStrictMode, DebuggerMode, ParserError&, EvalContextType); 196 196 UnlinkedModuleProgramCodeBlock* getUnlinkedModuleProgramCodeBlock(VM&, ModuleProgramExecutable*, const SourceCode&, DebuggerMode, ParserError&); 197 UnlinkedFunctionExecutable* getUnlinkedGlobalFunctionExecutable(VM&, const Identifier&, const SourceCode&, DebuggerMode, ParserError&);197 UnlinkedFunctionExecutable* getUnlinkedGlobalFunctionExecutable(VM&, const Identifier&, const SourceCode&, DebuggerMode, std::optional<int> functionConstructorParametersEndPosition, ParserError&); 198 198 199 199 void clear() { m_sourceCode.clear(); } -
trunk/Source/JavaScriptCore/runtime/FunctionConstructor.cpp
r237128 r237254 95 95 break; 96 96 case FunctionConstructionMode::AsyncGenerator: 97 prefix = " {async function*";97 prefix = "async function*"; 98 98 break; 99 99 } 100 101 auto checkBody = [&] (const String& body) {102 // The spec mandates that the body parses a valid function body independent103 // of the parameters.104 String program = makeString("(", prefix, "(){\n", body, "\n})");105 SourceCode source = makeSource(program, sourceOrigin, sourceURL, position);106 JSValue exception;107 checkSyntax(exec, source, &exception);108 if (exception) {109 scope.throwException(exec, exception);110 return;111 }112 };113 100 114 101 // How we stringify functions is sometimes important for web compatibility. 115 102 // See https://bugs.webkit.org/show_bug.cgi?id=24350. 116 103 String program; 104 std::optional<int> functionConstructorParametersEndPosition = std::nullopt; 117 105 if (args.isEmpty()) 118 program = makeString( "{", prefix, functionName.string(), "() {\n\n}}");106 program = makeString(prefix, functionName.string(), "() {\n\n}"); 119 107 else if (args.size() == 1) { 120 108 auto body = args.at(0).toWTFString(exec); 121 109 RETURN_IF_EXCEPTION(scope, nullptr); 122 checkBody(body); 123 RETURN_IF_EXCEPTION(scope, nullptr); 124 program = makeString("{", prefix, functionName.string(), "() {\n", body, "\n}}"); 110 program = makeString(prefix, functionName.string(), "() {\n", body, "\n}"); 125 111 } else { 126 112 StringBuilder builder; 127 builder.append('{');128 113 builder.append(prefix); 129 114 builder.append(functionName.string()); 115 130 116 builder.append('('); 131 StringBuilder parameterBuilder;132 117 auto viewWithString = args.at(0).toString(exec)->viewWithUnderlyingString(exec); 133 118 RETURN_IF_EXCEPTION(scope, nullptr); 134 parameterBuilder.append(viewWithString.view);119 builder.append(viewWithString.view); 135 120 for (size_t i = 1; i < args.size() - 1; i++) { 136 parameterBuilder.appendLiteral(", ");121 builder.appendLiteral(", "); 137 122 auto viewWithString = args.at(i).toString(exec)->viewWithUnderlyingString(exec); 138 123 RETURN_IF_EXCEPTION(scope, nullptr); 139 parameterBuilder.append(viewWithString.view);124 builder.append(viewWithString.view); 140 125 } 141 auto body = args.at(args.size() - 1).toWTFString(exec); 126 functionConstructorParametersEndPosition = builder.length() + 1; 127 builder.appendLiteral(") {\n"); 128 129 auto body = args.at(args.size() - 1).toString(exec)->viewWithUnderlyingString(exec); 142 130 RETURN_IF_EXCEPTION(scope, nullptr); 143 144 { 145 // The spec mandates that the parameters parse as a valid parameter list 146 // independent of the function body. 147 String program = tryMakeString("(", prefix, "(", parameterBuilder.toString(), "){\n\n})"); 148 if (UNLIKELY(!program)) { 149 throwOutOfMemoryError(exec, scope); 150 return nullptr; 151 } 152 SourceCode source = makeSource(program, sourceOrigin, sourceURL, position); 153 JSValue exception; 154 checkSyntax(exec, source, &exception); 155 if (exception) { 156 scope.throwException(exec, exception); 157 return nullptr; 158 } 159 } 160 161 builder.append(parameterBuilder); 162 builder.appendLiteral(") {\n"); 163 checkBody(body); 164 RETURN_IF_EXCEPTION(scope, nullptr); 165 builder.append(body); 166 builder.appendLiteral("\n}}"); 131 builder.append(body.view); 132 builder.appendLiteral("\n}"); 167 133 program = builder.toString(); 168 134 } … … 170 136 SourceCode source = makeSource(program, sourceOrigin, sourceURL, position); 171 137 JSObject* exception = nullptr; 172 FunctionExecutable* function = FunctionExecutable::fromGlobalCode(functionName, *exec, source, exception, overrideLineNumber );138 FunctionExecutable* function = FunctionExecutable::fromGlobalCode(functionName, *exec, source, exception, overrideLineNumber, functionConstructorParametersEndPosition); 173 139 if (!function) { 174 140 ASSERT(exception); -
trunk/Source/JavaScriptCore/runtime/FunctionExecutable.cpp
r237128 r237254 95 95 FunctionExecutable* FunctionExecutable::fromGlobalCode( 96 96 const Identifier& name, ExecState& exec, const SourceCode& source, 97 JSObject*& exception, int overrideLineNumber )97 JSObject*& exception, int overrideLineNumber, std::optional<int> functionConstructorParametersEndPosition) 98 98 { 99 99 UnlinkedFunctionExecutable* unlinkedExecutable = 100 100 UnlinkedFunctionExecutable::fromGlobalCode( 101 name, exec, source, exception, overrideLineNumber );101 name, exec, source, exception, overrideLineNumber, functionConstructorParametersEndPosition); 102 102 if (!unlinkedExecutable) 103 103 return nullptr; -
trunk/Source/JavaScriptCore/runtime/FunctionExecutable.h
r237128 r237254 56 56 static FunctionExecutable* fromGlobalCode( 57 57 const Identifier& name, ExecState&, const SourceCode&, 58 JSObject*& exception, int overrideLineNumber );58 JSObject*& exception, int overrideLineNumber, std::optional<int> functionConstructorParametersEndPosition); 59 59 60 60 static void destroy(JSCell*);
Note:
See TracChangeset
for help on using the changeset viewer.