Diff
Modified: trunk/JSTests/ChakraCore/test/Function/FuncBodyES5.baseline-jsc (237053 => 237054)
--- trunk/JSTests/ChakraCore/test/Function/FuncBodyES5.baseline-jsc 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/JSTests/ChakraCore/test/Function/FuncBodyES5.baseline-jsc 2018-10-11 23:43:58 UTC (rev 237054)
@@ -9,13 +9,13 @@
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: 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: 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: 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.
Modified: trunk/JSTests/ChangeLog (237053 => 237054)
--- trunk/JSTests/ChangeLog 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/JSTests/ChangeLog 2018-10-11 23:43:58 UTC (rev 237054)
@@ -1,3 +1,28 @@
+2018-10-08 Yusuke Suzuki <[email protected]>
+
+ [JSC] JSC should have "parseFunction" to optimize Function constructor
+ https://bugs.webkit.org/show_bug.cgi?id=190340
+
+ Reviewed by Mark Lam.
+
+ This patch fixes the line number of syntax errors raised by the Function constructor,
+ since we now parse the final code only once. And we no longer use block statement
+ for Function constructor's parsing.
+
+ * ChakraCore/test/Function/FuncBodyES5.baseline-jsc:
+ * stress/function-cache-with-parameters-end-position.js: Added.
+ (shouldBe):
+ (shouldThrow):
+ (i.anonymous):
+ * stress/function-constructor-name.js: Added.
+ (shouldBe):
+ (GeneratorFunction):
+ (AsyncFunction.async):
+ (AsyncGeneratorFunction.async):
+ (anonymous):
+ (async.anonymous):
+ * test262/expectations.yaml:
+
2018-10-10 Guillaume Emont <[email protected]>
Skip JSC test stress/sampling-profiler-richards.js on armv7/linux
Added: trunk/JSTests/stress/function-cache-with-parameters-end-position.js (0 => 237054)
--- trunk/JSTests/stress/function-cache-with-parameters-end-position.js (rev 0)
+++ trunk/JSTests/stress/function-cache-with-parameters-end-position.js 2018-10-11 23:43:58 UTC (rev 237054)
@@ -0,0 +1,40 @@
+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
+}`);
+}
+
Added: trunk/JSTests/stress/function-constructor-name.js (0 => 237054)
--- trunk/JSTests/stress/function-constructor-name.js (rev 0)
+++ trunk/JSTests/stress/function-constructor-name.js 2018-10-11 23:43:58 UTC (rev 237054)
@@ -0,0 +1,36 @@
+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
+}`);
Modified: trunk/JSTests/test262/expectations.yaml (237053 => 237054)
--- trunk/JSTests/test262/expectations.yaml 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/JSTests/test262/expectations.yaml 2018-10-11 23:43:58 UTC (rev 237054)
@@ -900,14 +900,14 @@
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 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 keyword 'yield'. Expected a ')' or a ',' after a parameter declaration."
+ strict mode: "SyntaxError: Unexpected keyword 'yield'. 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 */ })"
Modified: trunk/LayoutTests/ChangeLog (237053 => 237054)
--- trunk/LayoutTests/ChangeLog 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/LayoutTests/ChangeLog 2018-10-11 23:43:58 UTC (rev 237054)
@@ -1,3 +1,16 @@
+2018-10-08 Yusuke Suzuki <[email protected]>
+
+ [JSC] JSC should have "parseFunction" to optimize Function constructor
+ https://bugs.webkit.org/show_bug.cgi?id=190340
+
+ Reviewed by Mark Lam.
+
+ * fast/dom/attribute-event-listener-errors-expected.txt:
+ * fast/events/attribute-listener-deletion-crash-expected.txt:
+ * fast/events/window-onerror-syntax-error-in-attr-expected.txt:
+ * js/dom/invalid-syntax-for-function-expected.txt:
+ * js/dom/script-start-end-locations-expected.txt:
+
2018-10-11 Thibault Saunier <[email protected]>
[GStreamer] Support arbitrary video resolution in getUserMedia API
Modified: trunk/LayoutTests/fast/dom/attribute-event-listener-errors-expected.txt (237053 => 237054)
--- trunk/LayoutTests/fast/dom/attribute-event-listener-errors-expected.txt 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/LayoutTests/fast/dom/attribute-event-listener-errors-expected.txt 2018-10-11 23:43:58 UTC (rev 237054)
@@ -1,4 +1,4 @@
CONSOLE MESSAGE: line 4: ReferenceError: Can't find variable: error
-CONSOLE MESSAGE: line 9: SyntaxError: Invalid character: '@'
+CONSOLE MESSAGE: line 5: SyntaxError: Invalid character: '@'
This test verifies that an attribute event listener error shows the right line number even if the attribute contains newlines.
Modified: trunk/LayoutTests/fast/events/attribute-listener-deletion-crash-expected.txt (237053 => 237054)
--- trunk/LayoutTests/fast/events/attribute-listener-deletion-crash-expected.txt 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/LayoutTests/fast/events/attribute-listener-deletion-crash-expected.txt 2018-10-11 23:43:58 UTC (rev 237054)
@@ -1,21 +1,21 @@
-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 '|'
+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 '|'
PASS
Modified: trunk/LayoutTests/fast/events/window-onerror-syntax-error-in-attr-expected.txt (237053 => 237054)
--- trunk/LayoutTests/fast/events/window-onerror-syntax-error-in-attr-expected.txt 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/LayoutTests/fast/events/window-onerror-syntax-error-in-attr-expected.txt 2018-10-11 23:43:58 UTC (rev 237054)
@@ -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: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 '%'
+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 '%'
Button 1 Button 2 Button 3
Modified: trunk/LayoutTests/imported/w3c/ChangeLog (237053 => 237054)
--- trunk/LayoutTests/imported/w3c/ChangeLog 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/LayoutTests/imported/w3c/ChangeLog 2018-10-11 23:43:58 UTC (rev 237054)
@@ -1,3 +1,15 @@
+2018-10-08 Yusuke Suzuki <[email protected]>
+
+ [JSC] JSC should have "parseFunction" to optimize Function constructor
+ https://bugs.webkit.org/show_bug.cgi?id=190340
+
+ Reviewed by Mark Lam.
+
+ * web-platform-tests/html/webappapis/scripting/events/inline-event-handler-ordering-expected.txt:
+ * web-platform-tests/html/webappapis/scripting/events/invalid-uncompiled-raw-handler-compiled-late-expected.txt:
+ * web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-attribute-expected.txt:
+ * web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-body-onerror-expected.txt:
+
2018-10-10 Chris Dumez <[email protected]>
Unreviewed, rolling out r236802.
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/inline-event-handler-ordering-expected.txt (237053 => 237054)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/inline-event-handler-ordering-expected.txt 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/inline-event-handler-ordering-expected.txt 2018-10-11 23:43:58 UTC (rev 237054)
@@ -1,5 +1,5 @@
CONSOLE MESSAGE: line 19: SyntaxError: Unexpected token '}'
-CONSOLE MESSAGE: line 54: SyntaxError: Unexpected token '}'
+CONSOLE MESSAGE: line 52: 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
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/invalid-uncompiled-raw-handler-compiled-late-expected.txt (237053 => 237054)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/invalid-uncompiled-raw-handler-compiled-late-expected.txt 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/events/invalid-uncompiled-raw-handler-compiled-late-expected.txt 2018-10-11 23:43:58 UTC (rev 237054)
@@ -1,5 +1,5 @@
-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_.
+CONSOLE MESSAGE: line 24: SyntaxError: Parser error
+CONSOLE MESSAGE: line 21: SyntaxError: Parser error
FAIL Invalid uncompiled raw handlers should only be compiled when about to call them. assert_array_equals: lengths differ, expected 3 got 4
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-attribute-expected.txt (237053 => 237054)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-attribute-expected.txt 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-attribute-expected.txt 2018-10-11 23:43:58 UTC (rev 237054)
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 26: SyntaxError: Unexpected token ')'
+CONSOLE MESSAGE: line 24: SyntaxError: Unexpected end of script
PASS window.onerror - compile error in attribute
PASS window.onerror - compile error in attribute (column)
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-body-onerror-expected.txt (237053 => 237054)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-body-onerror-expected.txt 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-body-onerror-expected.txt 2018-10-11 23:43:58 UTC (rev 237054)
@@ -1,5 +1,5 @@
CONSOLE MESSAGE: line 19: SyntaxError: Unexpected token ')'
-CONSOLE MESSAGE: line 18: SyntaxError: Unexpected token ')'
+CONSOLE MESSAGE: line 16: SyntaxError: Unexpected end of script
PASS window.onerror - compile error in <body onerror>
Modified: trunk/LayoutTests/js/dom/invalid-syntax-for-function-expected.txt (237053 => 237054)
--- trunk/LayoutTests/js/dom/invalid-syntax-for-function-expected.txt 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/LayoutTests/js/dom/invalid-syntax-for-function-expected.txt 2018-10-11 23:43:58 UTC (rev 237054)
@@ -1,3 +1,3 @@
-CONSOLE MESSAGE: line 2: SyntaxError: Invalid character: '#'
+CONSOLE MESSAGE: line 1: 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
Modified: trunk/LayoutTests/js/dom/script-start-end-locations-expected.txt (237053 => 237054)
--- trunk/LayoutTests/js/dom/script-start-end-locations-expected.txt 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/LayoutTests/js/dom/script-start-end-locations-expected.txt 2018-10-11 23:43:58 UTC (rev 237054)
@@ -243,32 +243,32 @@
eval { 1:1 - 1:56 }
new Function Object:
-function "anonymous" { 1:20 - 2:228 }
+function "anonymous" { 1:19 - 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:20 - 18:8 }
+function "anonymous" { 1:19 - 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:20 - 2:228 }
+function "anonymous" { 1:19 - 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:20 - 2:237 }
+function "anonymous" { 1:19 - 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:20 - 18:8 }
+function "anonymous" { 1:19 - 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:20 - 18:9 }
+function "anonymous" { 1:19 - 18:9 }
function "nfi2a" { 5:19 - 16:5 }
function "nfi2b" { 7:23 - 14:9 }
function "nfi2c" { 9:27 - 12:13 }
Modified: trunk/Source/_javascript_Core/ChangeLog (237053 => 237054)
--- trunk/Source/_javascript_Core/ChangeLog 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/Source/_javascript_Core/ChangeLog 2018-10-11 23:43:58 UTC (rev 237054)
@@ -1,3 +1,78 @@
+2018-10-08 Yusuke Suzuki <[email protected]>
+
+ [JSC] JSC should have "parseFunction" to optimize Function constructor
+ https://bugs.webkit.org/show_bug.cgi?id=190340
+
+ Reviewed by Mark Lam.
+
+ The current Function constructor is suboptimal. We parse the piece of the same code three times to meet
+ the spec requirement. (1) check parameters syntax, (2) check body syntax, and (3) parse the entire function.
+ And to parse 1-3 correctly, we create two strings, the parameters and the entire function. This operation
+ is really costly and ideally we should meet the above requirement by the one time parsing.
+
+ To meet the above requirement, we add a special function for Parser, parseSingleFunction. This function
+ takes `std::optional<int> functionConstructorParametersEndPosition` and check this end position is correct in the parser.
+ For example, if we run the code,
+
+ Function('/*', '*/){')
+
+ According to the spec, this should produce '/*' parameter string and '*/){' body string. And parameter
+ string should be syntax-checked by the parser, and raise the error since it is incorrect. Instead of doing
+ that, in our implementation, we first create the entire string.
+
+ function anonymous(/*) {
+ */){
+ }
+
+ And we parse it. At that time, we also pass the end position of the parameters to the parser. In the above case,
+ the position of the `function anonymous(/*)' <> is passed. And in the parser, we check that the last token
+ offset of the parameters is the given end position. This check allows us to raise the error correctly to the
+ above example while we parse the entire function only once. And we do not need to create two strings too.
+
+ This improves the performance of the Function constructor significantly. And web-tooling-benchmark/uglify-js is
+ significantly sped up (28.2%).
+
+ Before:
+ uglify-js: 2.94 runs/s
+ After:
+ uglify-js: 3.77 runs/s
+
+ * bytecode/UnlinkedFunctionExecutable.cpp:
+ (JSC::UnlinkedFunctionExecutable::fromGlobalCode):
+ * bytecode/UnlinkedFunctionExecutable.h:
+ * parser/Parser.cpp:
+ (JSC::Parser<LexerType>::parseInner):
+ (JSC::Parser<LexerType>::parseSingleFunction):
+ (JSC::Parser<LexerType>::parseFunctionInfo):
+ (JSC::Parser<LexerType>::parseFunctionDeclaration):
+ (JSC::Parser<LexerType>::parseAsyncFunctionDeclaration):
+ (JSC::Parser<LexerType>::parseClass):
+ (JSC::Parser<LexerType>::parsePropertyMethod):
+ (JSC::Parser<LexerType>::parseGetterSetter):
+ (JSC::Parser<LexerType>::parseFunctionExpression):
+ (JSC::Parser<LexerType>::parseAsyncFunctionExpression):
+ (JSC::Parser<LexerType>::parseArrowFunctionExpression):
+ * parser/Parser.h:
+ (JSC::Parser<LexerType>::parse):
+ (JSC::parse):
+ (JSC::parseFunctionForFunctionConstructor):
+ * parser/ParserModes.h:
+ * parser/ParserTokens.h:
+ (JSC::JSTextPosition::JSTextPosition):
+ (JSC::JSTokenLocation::JSTokenLocation): Deleted.
+ * parser/SourceCodeKey.h:
+ (JSC::SourceCodeKey::SourceCodeKey):
+ (JSC::SourceCodeKey::operator== const):
+ * runtime/CodeCache.cpp:
+ (JSC::CodeCache::getUnlinkedGlobalCodeBlock):
+ (JSC::CodeCache::getUnlinkedGlobalFunctionExecutable):
+ * runtime/CodeCache.h:
+ * runtime/FunctionConstructor.cpp:
+ (JSC::constructFunctionSkippingEvalEnabledCheck):
+ * runtime/FunctionExecutable.cpp:
+ (JSC::FunctionExecutable::fromGlobalCode):
+ * runtime/FunctionExecutable.h:
+
2018-10-11 Ross Kirsling <[email protected]>
Fix non-existent define `CPU(JSVALUE64)`
Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp (237053 => 237054)
--- trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp 2018-10-11 23:43:58 UTC (rev 237054)
@@ -174,7 +174,7 @@
UnlinkedFunctionExecutable* UnlinkedFunctionExecutable::fromGlobalCode(
const Identifier& name, ExecState& exec, const SourceCode& source,
- JSObject*& exception, int overrideLineNumber)
+ JSObject*& exception, int overrideLineNumber, std::optional<int> functionConstructorParametersEndPosition)
{
ParserError error;
VM& vm = exec.vm();
@@ -181,7 +181,7 @@
auto& globalObject = *exec.lexicalGlobalObject();
CodeCache* codeCache = vm.codeCache();
DebuggerMode debuggerMode = globalObject.hasInteractiveDebugger() ? DebuggerOn : DebuggerOff;
- UnlinkedFunctionExecutable* executable = codeCache->getUnlinkedGlobalFunctionExecutable(vm, name, source, debuggerMode, error);
+ UnlinkedFunctionExecutable* executable = codeCache->getUnlinkedGlobalFunctionExecutable(vm, name, source, debuggerMode, functionConstructorParametersEndPosition, error);
if (globalObject.hasDebugger())
globalObject.debugger()->sourceParsed(&exec, source.provider(), error.line(), error.message());
Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h (237053 => 237054)
--- trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h 2018-10-11 23:43:58 UTC (rev 237054)
@@ -107,7 +107,7 @@
static UnlinkedFunctionExecutable* fromGlobalCode(
const Identifier&, ExecState&, const SourceCode&, JSObject*& exception,
- int overrideLineNumber);
+ int overrideLineNumber, std::optional<int> functionConstructorParametersEndPosition);
JS_EXPORT_PRIVATE FunctionExecutable* link(VM&, const SourceCode& parentSource, std::optional<int> overrideLineNumber = std::nullopt, Intrinsic = NoIntrinsic);
Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (237053 => 237054)
--- trunk/Source/_javascript_Core/parser/Parser.cpp 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp 2018-10-11 23:43:58 UTC (rev 237054)
@@ -195,7 +195,7 @@
}
template <typename LexerType>
-String Parser<LexerType>::parseInner(const Identifier& calleeName, SourceParseMode parseMode)
+String Parser<LexerType>::parseInner(const Identifier& calleeName, SourceParseMode parseMode, ParsingContext parsingContext, std::optional<int> functionConstructorParametersEndPosition)
{
String parseError = String();
@@ -239,6 +239,8 @@
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);
}
@@ -611,6 +613,38 @@
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)
@@ -2264,7 +2298,7 @@
}
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)
+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)
{
RELEASE_ASSERT(isFunctionParseMode(mode));
@@ -2460,6 +2494,10 @@
}
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.
@@ -2594,7 +2632,7 @@
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)
+template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext, std::optional<int> functionConstructorParametersEndPosition)
{
ASSERT(match(FUNCTION));
JSTokenLocation location(tokenLocation());
@@ -2631,7 +2669,7 @@
functionInfo.name = &m_vm->propertyNames->builtinNames().starDefaultPrivateName();
}
- failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration)), "Cannot parse this function");
+ failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration, functionConstructorParametersEndPosition)), "Cannot parse this function");
ASSERT(functionInfo.name);
std::pair<DeclarationResultMask, ScopeRef> functionDeclaration = declareFunction(functionInfo.name);
@@ -2652,7 +2690,7 @@
}
template <typename LexerType>
-template <class TreeBuilder> TreeStatement Parser<LexerType>::parseAsyncFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext)
+template <class TreeBuilder> TreeStatement Parser<LexerType>::parseAsyncFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext, std::optional<int> functionConstructorParametersEndPosition)
{
ASSERT(match(FUNCTION));
JSTokenLocation location(tokenLocation());
@@ -2689,7 +2727,7 @@
functionInfo.name = &m_vm->propertyNames->builtinNames().starDefaultPrivateName();
}
- failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration)), "Cannot parse this async function");
+ failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration, functionConstructorParametersEndPosition)), "Cannot parse this async function");
failIfFalse(functionInfo.name, "Async function statements must have a name");
std::pair<DeclarationResultMask, ScopeRef> functionDeclaration = declareFunction(functionInfo.name);
Modified: trunk/Source/_javascript_Core/parser/Parser.h (237053 => 237054)
--- trunk/Source/_javascript_Core/parser/Parser.h 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/Source/_javascript_Core/parser/Parser.h 2018-10-11 23:43:58 UTC (rev 237054)
@@ -859,10 +859,8 @@
unsigned m_index;
};
-enum class ArgumentType {
- Normal,
- Spread
-};
+enum class ArgumentType { Normal, Spread };
+enum class ParsingContext { Program, FunctionConstructor, Eval };
template <typename LexerType>
class Parser {
@@ -874,7 +872,7 @@
~Parser();
template <class ParsedNode>
- std::unique_ptr<ParsedNode> parse(ParserError&, const Identifier&, SourceParseMode);
+ std::unique_ptr<ParsedNode> parse(ParserError&, const Identifier&, SourceParseMode, ParsingContext, std::optional<int> functionConstructorParametersEndPosition = std::nullopt);
JSTextPosition positionBeforeLastNewline() const { return m_lexer->positionBeforeLastNewline(); }
JSTokenLocation locationBeforeLastToken() const { return m_lexer->lastTokenLocation(); }
@@ -1312,8 +1310,9 @@
}
Parser();
- String parseInner(const Identifier&, SourceParseMode);
+ String parseInner(const Identifier&, SourceParseMode, ParsingContext, std::optional<int> functionConstructorParametersEndPosition = std::nullopt);
+
void didFinishParsing(SourceElements*, DeclarationStacks::FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, CodeFeatures, int);
// Used to determine type of error to report.
@@ -1524,13 +1523,14 @@
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);
+ template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard, std::optional<int> functionConstructorParametersEndPosition = std::nullopt);
template <class TreeBuilder> TreeStatement parseFunctionDeclarationStatement(TreeBuilder&, bool isAsync, bool parentAllowsFunctionDeclarationAsStatement);
- template <class TreeBuilder> TreeStatement parseAsyncFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard);
+ template <class TreeBuilder> TreeStatement parseAsyncFunctionDeclaration(TreeBuilder&, ExportType = ExportType::NotExported, DeclarationDefaultContext = DeclarationDefaultContext::Standard, std::optional<int> functionConstructorParametersEndPosition = std::nullopt);
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 @@
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);
+ 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);
ALWAYS_INLINE bool isArrowFunctionParameters();
@@ -1848,7 +1848,7 @@
template <typename LexerType>
template <class ParsedNode>
-std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const Identifier& calleeName, SourceParseMode parseMode)
+std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const Identifier& calleeName, SourceParseMode parseMode, ParsingContext parsingContext, std::optional<int> functionConstructorParametersEndPosition)
{
int errLine;
String errMsg;
@@ -1865,7 +1865,7 @@
ASSERT(m_source->startColumn() > OrdinalNumber::beforeFirst());
unsigned startColumn = m_source->startColumn().zeroBasedInt();
- String parseError = parseInner(calleeName, parseMode);
+ String parseError = parseInner(calleeName, parseMode, parsingContext, functionConstructorParametersEndPosition);
int lineNumber = m_lexer->lineNumber();
bool lexError = m_lexer->sawError();
@@ -1960,7 +1960,7 @@
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);
+ result = parser.parse<ParsedNode>(error, name, parseMode, isEvalNode<ParsedNode>() ? ParsingContext::Eval : ParsingContext::Program);
if (positionBeforeLastNewline)
*positionBeforeLastNewline = parser.positionBeforeLastNewline();
if (builtinMode == JSParserBuiltinMode::Builtin) {
@@ -1973,7 +1973,7 @@
} 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);
+ result = parser.parse<ParsedNode>(error, name, parseMode, isEvalNode<ParsedNode>() ? ParsingContext::Eval : ParsingContext::Program);
if (positionBeforeLastNewline)
*positionBeforeLastNewline = parser.positionBeforeLastNewline();
}
@@ -1987,4 +1987,37 @@
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
Modified: trunk/Source/_javascript_Core/parser/ParserModes.h (237053 => 237054)
--- trunk/Source/_javascript_Core/parser/ParserModes.h 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/Source/_javascript_Core/parser/ParserModes.h 2018-10-11 23:43:58 UTC (rev 237054)
@@ -33,7 +33,6 @@
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 };
Modified: trunk/Source/_javascript_Core/parser/ParserTokens.h (237053 => 237054)
--- trunk/Source/_javascript_Core/parser/ParserTokens.h 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/Source/_javascript_Core/parser/ParserTokens.h 2018-10-11 23:43:58 UTC (rev 237054)
@@ -193,7 +193,6 @@
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); }
@@ -246,13 +245,6 @@
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 };
Modified: trunk/Source/_javascript_Core/parser/SourceCodeKey.h (237053 => 237054)
--- trunk/Source/_javascript_Core/parser/SourceCodeKey.h 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/Source/_javascript_Core/parser/SourceCodeKey.h 2018-10-11 23:43:58 UTC (rev 237054)
@@ -29,6 +29,7 @@
#include "ParserModes.h"
#include "UnlinkedSourceCode.h"
#include <wtf/HashTraits.h>
+#include <wtf/Hasher.h>
namespace JSC {
@@ -71,18 +72,17 @@
class SourceCodeKey {
public:
- SourceCodeKey()
- {
- }
+ SourceCodeKey() = default;
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)
+ DebuggerMode debuggerMode, TypeProfilerEnabled typeProfilerEnabled, ControlFlowProfilerEnabled controlFlowProfilerEnabled, std::optional<int> functionConstructorParametersEndPosition)
: m_sourceCode(sourceCode)
, m_name(name)
, m_flags(codeType, strictMode, scriptMode, derivedContextType, evalContextType, isArrowFunctionContext, debuggerMode, typeProfilerEnabled, controlFlowProfilerEnabled)
- , m_hash(sourceCode.hash() ^ m_flags.bits())
+ , m_functionConstructorParametersEndPosition(functionConstructorParametersEndPosition.value_or(-1))
+ , m_hash(sourceCode.hash() ^ computeHash(m_flags.bits(), m_functionConstructorParametersEndPosition))
{
}
@@ -108,6 +108,7 @@
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();
}
@@ -127,7 +128,8 @@
UnlinkedSourceCode m_sourceCode;
String m_name;
SourceCodeFlags m_flags;
- unsigned m_hash;
+ int m_functionConstructorParametersEndPosition { -1 };
+ unsigned m_hash { 0 };
};
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/CodeCache.cpp (237053 => 237054)
--- trunk/Source/_javascript_Core/runtime/CodeCache.cpp 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/Source/_javascript_Core/runtime/CodeCache.cpp 2018-10-11 23:43:58 UTC (rev 237054)
@@ -57,7 +57,8 @@
source, String(), CacheTypes<UnlinkedCodeBlockType>::codeType, strictMode, scriptMode,
derivedContextType, evalContextType, isArrowFunctionContext, debuggerMode,
vm.typeProfiler() ? TypeProfilerEnabled::Yes : TypeProfilerEnabled::No,
- vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No);
+ vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No,
+ std::nullopt);
SourceCodeValue* cache = m_sourceCode.findCacheAndUpdateAge(key);
if (cache && Options::useCodeCache()) {
UnlinkedCodeBlockType* unlinkedCodeBlock = jsCast<UnlinkedCodeBlockType*>(cache->cell.get());
@@ -95,7 +96,7 @@
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, ParserError& error)
+UnlinkedFunctionExecutable* CodeCache::getUnlinkedGlobalFunctionExecutable(VM& vm, const Identifier& name, const SourceCode& source, DebuggerMode debuggerMode, std::optional<int> functionConstructorParametersEndPosition, ParserError& error)
{
bool isArrowFunctionContext = false;
SourceCodeKey key(
@@ -107,7 +108,8 @@
isArrowFunctionContext,
debuggerMode,
vm.typeProfiler() ? TypeProfilerEnabled::Yes : TypeProfilerEnabled::No,
- vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No);
+ vm.controlFlowProfiler() ? ControlFlowProfilerEnabled::Yes : ControlFlowProfilerEnabled::No,
+ functionConstructorParametersEndPosition);
SourceCodeValue* cache = m_sourceCode.findCacheAndUpdateAge(key);
if (cache && Options::useCodeCache()) {
UnlinkedFunctionExecutable* executable = jsCast<UnlinkedFunctionExecutable*>(cache->cell.get());
@@ -117,10 +119,7 @@
}
JSTextPosition positionBeforeLastNewline;
- std::unique_ptr<ProgramNode> program = parse<ProgramNode>(
- &vm, source, Identifier(), JSParserBuiltinMode::NotBuiltin,
- JSParserStrictMode::NotStrict, JSParserScriptMode::Classic, SourceParseMode::ProgramMode, SuperBinding::NotNeeded,
- error, &positionBeforeLastNewline);
+ std::unique_ptr<ProgramNode> program = parseFunctionForFunctionConstructor(vm, source, error, &positionBeforeLastNewline, functionConstructorParametersEndPosition);
if (!program) {
RELEASE_ASSERT(error.isValid());
return nullptr;
@@ -127,15 +126,7 @@
}
// This function assumes an input string that would result in a single function declaration.
- 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();
+ StatementNode* funcDecl = program->singleStatement();
if (UNLIKELY(!funcDecl)) {
JSToken token;
error = ParserError(ParserError::SyntaxError, ParserError::SyntaxErrorIrrecoverable, token, "Parser error", -1);
Modified: trunk/Source/_javascript_Core/runtime/CodeCache.h (237053 => 237054)
--- trunk/Source/_javascript_Core/runtime/CodeCache.h 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/Source/_javascript_Core/runtime/CodeCache.h 2018-10-11 23:43:58 UTC (rev 237054)
@@ -194,7 +194,7 @@
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, ParserError&);
+ UnlinkedFunctionExecutable* getUnlinkedGlobalFunctionExecutable(VM&, const Identifier&, const SourceCode&, DebuggerMode, std::optional<int> functionConstructorParametersEndPosition, ParserError&);
void clear() { m_sourceCode.clear(); }
Modified: trunk/Source/_javascript_Core/runtime/FunctionConstructor.cpp (237053 => 237054)
--- trunk/Source/_javascript_Core/runtime/FunctionConstructor.cpp 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/Source/_javascript_Core/runtime/FunctionConstructor.cpp 2018-10-11 23:43:58 UTC (rev 237054)
@@ -94,82 +94,48 @@
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);
- checkBody(body);
- RETURN_IF_EXCEPTION(scope, nullptr);
- program = makeString("{", prefix, functionName.string(), "() {\n", body, "\n}}");
+ 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);
- parameterBuilder.append(viewWithString.view);
+ builder.append(viewWithString.view);
for (size_t i = 1; i < args.size() - 1; i++) {
- parameterBuilder.appendLiteral(", ");
+ builder.appendLiteral(", ");
auto viewWithString = args.at(i).toString(exec)->viewWithUnderlyingString(exec);
RETURN_IF_EXCEPTION(scope, nullptr);
- parameterBuilder.append(viewWithString.view);
+ builder.append(viewWithString.view);
}
- auto body = args.at(args.size() - 1).toWTFString(exec);
- RETURN_IF_EXCEPTION(scope, nullptr);
+ functionConstructorParametersEndPosition = builder.length() + 1;
+ builder.appendLiteral(") {\n");
- {
- // 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;
- }
- }
-
- builder.append(parameterBuilder);
- builder.appendLiteral(") {\n");
- checkBody(body);
+ auto body = args.at(args.size() - 1).toString(exec)->viewWithUnderlyingString(exec);
RETURN_IF_EXCEPTION(scope, nullptr);
- builder.append(body);
- builder.appendLiteral("\n}}");
+ builder.append(body.view);
+ 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);
+ FunctionExecutable* function = FunctionExecutable::fromGlobalCode(functionName, *exec, source, exception, overrideLineNumber, functionConstructorParametersEndPosition);
if (!function) {
ASSERT(exception);
return throwException(exec, scope, exception);
Modified: trunk/Source/_javascript_Core/runtime/FunctionExecutable.cpp (237053 => 237054)
--- trunk/Source/_javascript_Core/runtime/FunctionExecutable.cpp 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/Source/_javascript_Core/runtime/FunctionExecutable.cpp 2018-10-11 23:43:58 UTC (rev 237054)
@@ -94,11 +94,11 @@
FunctionExecutable* FunctionExecutable::fromGlobalCode(
const Identifier& name, ExecState& exec, const SourceCode& source,
- JSObject*& exception, int overrideLineNumber)
+ JSObject*& exception, int overrideLineNumber, std::optional<int> functionConstructorParametersEndPosition)
{
UnlinkedFunctionExecutable* unlinkedExecutable =
UnlinkedFunctionExecutable::fromGlobalCode(
- name, exec, source, exception, overrideLineNumber);
+ name, exec, source, exception, overrideLineNumber, functionConstructorParametersEndPosition);
if (!unlinkedExecutable)
return nullptr;
Modified: trunk/Source/_javascript_Core/runtime/FunctionExecutable.h (237053 => 237054)
--- trunk/Source/_javascript_Core/runtime/FunctionExecutable.h 2018-10-11 23:41:18 UTC (rev 237053)
+++ trunk/Source/_javascript_Core/runtime/FunctionExecutable.h 2018-10-11 23:43:58 UTC (rev 237054)
@@ -55,7 +55,7 @@
}
static FunctionExecutable* fromGlobalCode(
const Identifier& name, ExecState&, const SourceCode&,
- JSObject*& exception, int overrideLineNumber);
+ JSObject*& exception, int overrideLineNumber, std::optional<int> functionConstructorParametersEndPosition);
static void destroy(JSCell*);