Title: [233377] trunk
Revision
233377
Author
sbar...@apple.com
Date
2018-06-29 16:40:25 -0700 (Fri, 29 Jun 2018)

Log Message

We shouldn't recurse into the parser when gathering metadata about various function offsets
https://bugs.webkit.org/show_bug.cgi?id=184074
<rdar://problem/37165897>

Reviewed by Mark Lam.

JSTests:

* microbenchmarks/try-get-by-id-basic.js:
(const.bench.f.const.fooPlusBar.createBuiltin):
* microbenchmarks/try-get-by-id-polymorphic.js:
(fooPlusBar.createBuiltin):
* stress/array-push-with-force-exit.js:
* stress/dont-crash-on-stack-overflow-when-parsing-builtin.js: Added.
(f):
* stress/dont-crash-on-stack-overflow-when-parsing-default-constructor.js: Added.
(foo):
(prototype.runNearStackLimit):
* stress/is-constructor.js:
* stress/tailCallForwardArguments.js:
(putFuncToPrivateName.createBuiltin):

Source/_javascript_Core:

Prior to this patch, when we made a builtin, we had to make an UnlinkedFunctionExecutable
for that builtin. This required calling into the parser. However, the parser
may throw a stack overflow. We were not able to recover from that. The only
reason we called into the parser here is that we were gathering text offsets
and various metadata for things in the builtin function. This patch writes a
mini parser that figures this information out without calling into the full
parser. (I've also added a debug assert that verifies the mini parser stays in
sync with the full parser.) The result of this is that BuiltinExecutbles::createExecutable
always succeeds.

* builtins/AsyncFromSyncIteratorPrototype.js:
(globalPrivate.createAsyncFromSyncIterator):
(globalPrivate.AsyncFromSyncIteratorConstructor):
* builtins/BuiltinExecutables.cpp:
(JSC::BuiltinExecutables::createExecutable):
* builtins/GlobalOperations.js:
(globalPrivate.getter.overriddenName.string_appeared_here.speciesGetter):
(globalPrivate.speciesConstructor):
(globalPrivate.copyDataProperties):
(globalPrivate.copyDataPropertiesNoExclusions):
* builtins/PromiseOperations.js:
(globalPrivate.newHandledRejectedPromise):
* builtins/RegExpPrototype.js:
(globalPrivate.hasObservableSideEffectsForRegExpMatch):
(globalPrivate.hasObservableSideEffectsForRegExpSplit):
* builtins/StringPrototype.js:
(globalPrivate.hasObservableSideEffectsForStringReplace):
(globalPrivate.getDefaultCollator):
* parser/Nodes.cpp:
(JSC::FunctionMetadataNode::FunctionMetadataNode):
(JSC::FunctionMetadataNode::operator== const):
(JSC::FunctionMetadataNode::dump const):
* parser/Nodes.h:
* parser/Parser.h:
(JSC::parse):
* parser/ParserError.h:
(JSC::ParserError::type const):
* parser/ParserTokens.h:
(JSC::JSTextPosition::operator== const):
(JSC::JSTextPosition::operator!= const):
* parser/SourceCode.h:
(JSC::SourceCode::operator== const):
(JSC::SourceCode::operator!= const):
(JSC::SourceCode::subExpression const):
(JSC::SourceCode::subExpression): Deleted.

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (233376 => 233377)


--- trunk/JSTests/ChangeLog	2018-06-29 23:33:30 UTC (rev 233376)
+++ trunk/JSTests/ChangeLog	2018-06-29 23:40:25 UTC (rev 233377)
@@ -1,3 +1,25 @@
+2018-06-29  Saam Barati  <sbar...@apple.com>
+
+        We shouldn't recurse into the parser when gathering metadata about various function offsets
+        https://bugs.webkit.org/show_bug.cgi?id=184074
+        <rdar://problem/37165897>
+
+        Reviewed by Mark Lam.
+
+        * microbenchmarks/try-get-by-id-basic.js:
+        (const.bench.f.const.fooPlusBar.createBuiltin):
+        * microbenchmarks/try-get-by-id-polymorphic.js:
+        (fooPlusBar.createBuiltin):
+        * stress/array-push-with-force-exit.js:
+        * stress/dont-crash-on-stack-overflow-when-parsing-builtin.js: Added.
+        (f):
+        * stress/dont-crash-on-stack-overflow-when-parsing-default-constructor.js: Added.
+        (foo):
+        (prototype.runNearStackLimit):
+        * stress/is-constructor.js:
+        * stress/tailCallForwardArguments.js:
+        (putFuncToPrivateName.createBuiltin):
+
 2018-06-27  Mark Lam  <mark....@apple.com>
 
         DFG's compileReallocatePropertyStorage() and compileAllocatePropertyStorage() slow paths should also clear unused properties.

Modified: trunk/JSTests/microbenchmarks/try-get-by-id-basic.js (233376 => 233377)


--- trunk/JSTests/microbenchmarks/try-get-by-id-basic.js	2018-06-29 23:33:30 UTC (rev 233376)
+++ trunk/JSTests/microbenchmarks/try-get-by-id-basic.js	2018-06-29 23:40:25 UTC (rev 233377)
@@ -8,7 +8,7 @@
 
 const bench = f => {
     // Re-create the builtin each time, so each benchmark gets its own value prediction.
-    const fooPlusBar = createBuiltin(`(function(o) { return @tryGetById(o, "foo") + @tryGetById(o, "bar"); })`);
+    const fooPlusBar = createBuiltin(`(function (o) { return @tryGetById(o, "foo") + @tryGetById(o, "bar"); })`);
     noInline(fooPlusBar);
     f(fooPlusBar);
 }

Modified: trunk/JSTests/microbenchmarks/try-get-by-id-polymorphic.js (233376 => 233377)


--- trunk/JSTests/microbenchmarks/try-get-by-id-polymorphic.js	2018-06-29 23:33:30 UTC (rev 233376)
+++ trunk/JSTests/microbenchmarks/try-get-by-id-polymorphic.js	2018-06-29 23:40:25 UTC (rev 233377)
@@ -6,7 +6,7 @@
 
 const check = (got, expect) => { if (got != expect) throw "Error: bad result got " + got + " expected " + expect; };
 
-fooPlusBar = createBuiltin(`(function(o) { return @tryGetById(o, "foo") + @tryGetById(o, "bar"); })`);
+fooPlusBar = createBuiltin(`(function (o) { return @tryGetById(o, "foo") + @tryGetById(o, "bar"); })`);
 noInline(fooPlusBar);
 
 const bench = f => { f(); }

Modified: trunk/JSTests/stress/array-push-with-force-exit.js (233376 => 233377)


--- trunk/JSTests/stress/array-push-with-force-exit.js	2018-06-29 23:33:30 UTC (rev 233376)
+++ trunk/JSTests/stress/array-push-with-force-exit.js	2018-06-29 23:40:25 UTC (rev 233377)
@@ -1,6 +1,6 @@
 var createBuiltin = $vm.createBuiltin;
 
-var target = createBuiltin(`(function(array)
+var target = createBuiltin(`(function (array)
 {
     if (array) {
         @idWithProfile(array, "SpecOther").push(42);

Added: trunk/JSTests/stress/dont-crash-on-stack-overflow-when-parsing-builtin.js (0 => 233377)


--- trunk/JSTests/stress/dont-crash-on-stack-overflow-when-parsing-builtin.js	                        (rev 0)
+++ trunk/JSTests/stress/dont-crash-on-stack-overflow-when-parsing-builtin.js	2018-06-29 23:40:25 UTC (rev 233377)
@@ -0,0 +1,13 @@
+//@ runDefault("--softReservedZoneSize=16384", "--reservedZoneSize=0", "--useJIT=0", "--validateBytecode=1", "--maxPerThreadStackUsage=500000")
+
+function f() {
+    try {
+        f();
+    } catch (e) {
+        try {
+            Map.prototype.forEach.call('', {});
+        } catch (e) {}
+    }
+}
+
+f()

Added: trunk/JSTests/stress/dont-crash-on-stack-overflow-when-parsing-default-constructor.js (0 => 233377)


--- trunk/JSTests/stress/dont-crash-on-stack-overflow-when-parsing-default-constructor.js	                        (rev 0)
+++ trunk/JSTests/stress/dont-crash-on-stack-overflow-when-parsing-default-constructor.js	2018-06-29 23:40:25 UTC (rev 233377)
@@ -0,0 +1,17 @@
+//@ runDefault("--softReservedZoneSize=16384", "--reservedZoneSize=0", "--useJIT=0", "--validateBytecode=1", "--maxPerThreadStackUsage=500000")
+
+function runNearStackLimit(f) {
+    function t() {
+        try {
+            return t();
+        } catch (e) {
+            new class extends (class {}) {}();
+            return f();
+        }
+    }
+    return t();
+}
+function foo() {
+    new class extends (class {}) {}();
+}
+runNearStackLimit(() => { return foo(); });

Modified: trunk/JSTests/stress/is-constructor.js (233376 => 233377)


--- trunk/JSTests/stress/is-constructor.js	2018-06-29 23:33:30 UTC (rev 233376)
+++ trunk/JSTests/stress/is-constructor.js	2018-06-29 23:40:25 UTC (rev 233377)
@@ -5,7 +5,7 @@
         throw Error("Bad");
 }
 
-let isConstructor = createBuiltin("(function(c) { return @isConstructor(c); })");
+let isConstructor = createBuiltin("(function (c) { return @isConstructor(c); })");
 
 // Functions.
 assert(isConstructor(assert));

Modified: trunk/JSTests/stress/tailCallForwardArguments.js (233376 => 233377)


--- trunk/JSTests/stress/tailCallForwardArguments.js	2018-06-29 23:33:30 UTC (rev 233376)
+++ trunk/JSTests/stress/tailCallForwardArguments.js	2018-06-29 23:40:25 UTC (rev 233377)
@@ -1,7 +1,7 @@
 var createBuiltin = $vm.createBuiltin;
 
 // This is pretty bad but I need a private name.
-var putFuncToPrivateName = createBuiltin(`(function(func) { @arrayIteratorIsDone = func })`)
+var putFuncToPrivateName = createBuiltin(`(function (func) { @arrayIteratorIsDone = func })`)
 putFuncToPrivateName(function (a,b) { return b; })
 
 function createTailCallForwardingFuncWith(body, thisValue) {

Modified: trunk/Source/_javascript_Core/ChangeLog (233376 => 233377)


--- trunk/Source/_javascript_Core/ChangeLog	2018-06-29 23:33:30 UTC (rev 233376)
+++ trunk/Source/_javascript_Core/ChangeLog	2018-06-29 23:40:25 UTC (rev 233377)
@@ -1,3 +1,57 @@
+2018-06-29  Saam Barati  <sbar...@apple.com>
+
+        We shouldn't recurse into the parser when gathering metadata about various function offsets
+        https://bugs.webkit.org/show_bug.cgi?id=184074
+        <rdar://problem/37165897>
+
+        Reviewed by Mark Lam.
+
+        Prior to this patch, when we made a builtin, we had to make an UnlinkedFunctionExecutable
+        for that builtin. This required calling into the parser. However, the parser
+        may throw a stack overflow. We were not able to recover from that. The only
+        reason we called into the parser here is that we were gathering text offsets
+        and various metadata for things in the builtin function. This patch writes a
+        mini parser that figures this information out without calling into the full
+        parser. (I've also added a debug assert that verifies the mini parser stays in
+        sync with the full parser.) The result of this is that BuiltinExecutbles::createExecutable
+        always succeeds.
+
+        * builtins/AsyncFromSyncIteratorPrototype.js:
+        (globalPrivate.createAsyncFromSyncIterator):
+        (globalPrivate.AsyncFromSyncIteratorConstructor):
+        * builtins/BuiltinExecutables.cpp:
+        (JSC::BuiltinExecutables::createExecutable):
+        * builtins/GlobalOperations.js:
+        (globalPrivate.getter.overriddenName.string_appeared_here.speciesGetter):
+        (globalPrivate.speciesConstructor):
+        (globalPrivate.copyDataProperties):
+        (globalPrivate.copyDataPropertiesNoExclusions):
+        * builtins/PromiseOperations.js:
+        (globalPrivate.newHandledRejectedPromise):
+        * builtins/RegExpPrototype.js:
+        (globalPrivate.hasObservableSideEffectsForRegExpMatch):
+        (globalPrivate.hasObservableSideEffectsForRegExpSplit):
+        * builtins/StringPrototype.js:
+        (globalPrivate.hasObservableSideEffectsForStringReplace):
+        (globalPrivate.getDefaultCollator):
+        * parser/Nodes.cpp:
+        (JSC::FunctionMetadataNode::FunctionMetadataNode):
+        (JSC::FunctionMetadataNode::operator== const):
+        (JSC::FunctionMetadataNode::dump const):
+        * parser/Nodes.h:
+        * parser/Parser.h:
+        (JSC::parse):
+        * parser/ParserError.h:
+        (JSC::ParserError::type const):
+        * parser/ParserTokens.h:
+        (JSC::JSTextPosition::operator== const):
+        (JSC::JSTextPosition::operator!= const):
+        * parser/SourceCode.h:
+        (JSC::SourceCode::operator== const):
+        (JSC::SourceCode::operator!= const):
+        (JSC::SourceCode::subExpression const):
+        (JSC::SourceCode::subExpression): Deleted.
+
 2018-06-28  Michael Saboff  <msab...@apple.com>
   
         IsoCellSet::sweepToFreeList() not safe when Full GC in process

Modified: trunk/Source/_javascript_Core/builtins/AsyncFromSyncIteratorPrototype.js (233376 => 233377)


--- trunk/Source/_javascript_Core/builtins/AsyncFromSyncIteratorPrototype.js	2018-06-29 23:33:30 UTC (rev 233376)
+++ trunk/Source/_javascript_Core/builtins/AsyncFromSyncIteratorPrototype.js	2018-06-29 23:40:25 UTC (rev 233377)
@@ -151,6 +151,8 @@
 @globalPrivate
 function createAsyncFromSyncIterator(syncIterator, nextMethod)
 {
+    "use strict";
+
     if (!@isObject(syncIterator))
         @throwTypeError('Only objects can be wrapped by async-from-sync wrapper');
 
@@ -161,6 +163,8 @@
 @constructor
 function AsyncFromSyncIteratorConstructor(syncIterator, nextMethod)
 {
+    "use strict";
+
     @putByIdDirectPrivate(this, "syncIterator", syncIterator);
     @putByIdDirectPrivate(this, "nextMethod", nextMethod);
 }

Modified: trunk/Source/_javascript_Core/builtins/BuiltinExecutables.cpp (233376 => 233377)


--- trunk/Source/_javascript_Core/builtins/BuiltinExecutables.cpp	2018-06-29 23:33:30 UTC (rev 233376)
+++ trunk/Source/_javascript_Core/builtins/BuiltinExecutables.cpp	2018-06-29 23:40:25 UTC (rev 233377)
@@ -85,40 +85,174 @@
 
 UnlinkedFunctionExecutable* BuiltinExecutables::createExecutable(VM& vm, const SourceCode& source, const Identifier& name, ConstructorKind constructorKind, ConstructAbility constructAbility)
 {
+    // Someone should get mad at me for writing this code. But, it prevents us from recursing into
+    // the parser, and hence, from throwing stack overflow when parsing a builtin.
+    StringView view = source.view();
+    RELEASE_ASSERT(!view.isNull());
+    RELEASE_ASSERT(view.is8Bit());
+    auto* characters = view.characters8();
+    RELEASE_ASSERT(view.length() >= 15); // strlen("(function (){})") == 15
+    RELEASE_ASSERT(characters[0] ==  '(');
+    RELEASE_ASSERT(characters[1] ==  'f');
+    RELEASE_ASSERT(characters[2] ==  'u');
+    RELEASE_ASSERT(characters[3] ==  'n');
+    RELEASE_ASSERT(characters[4] ==  'c');
+    RELEASE_ASSERT(characters[5] ==  't');
+    RELEASE_ASSERT(characters[6] ==  'i');
+    RELEASE_ASSERT(characters[7] ==  'o');
+    RELEASE_ASSERT(characters[8] ==  'n');
+    RELEASE_ASSERT(characters[9] ==  ' ');
+    RELEASE_ASSERT(characters[10] == '(');
+
+    JSTokenLocation start;
+    start.line = -1;
+    start.lineStartOffset = -1;
+    start.startOffset = 10;
+    start.endOffset = -1;
+
+    JSTokenLocation end;
+    end.line = 1;
+    end.lineStartOffset = 0;
+    end.startOffset = 1;
+    end.endOffset = -1;
+
+    unsigned startColumn = 10; // strlen("function (") == 10
+    int functionKeywordStart = 1; // (f
+    int functionNameStart = 10;
+    int parametersStart = 10;
+    bool isInStrictContext = false;
+    bool isArrowFunctionBodyExpression = false;
+
+    unsigned parameterCount;
+    {
+        unsigned i = 11;
+        unsigned commas = 0;
+        bool sawOneParam = false;
+        bool hasRestParam = false;
+        while (true) {
+            ASSERT(i < view.length());
+            if (characters[i] == ')')
+                break;
+
+            if (characters[i] == ',')
+                ++commas;
+            else if (!Lexer<LChar>::isWhiteSpace(characters[i]))
+                sawOneParam = true;
+
+            if (i + 2 < view.length() && characters[i] == '.' && characters[i + 1] == '.' && characters[i + 2] == '.') {
+                hasRestParam = true;
+                i += 2;
+            }
+
+            ++i;
+        }
+
+        if (commas)
+            parameterCount = commas + 1;
+        else if (sawOneParam)
+            parameterCount = 1;
+        else
+            parameterCount = 0;
+
+        if (hasRestParam) {
+            RELEASE_ASSERT(parameterCount);
+            --parameterCount;
+        }
+    }
+
+    unsigned lineCount = 0;
+    unsigned endColumn = 0;
+    unsigned offsetOfLastNewline = 0;
+    std::optional<unsigned> offsetOfSecondToLastNewline;
+    for (unsigned i = 0; i < view.length(); ++i) {
+        if (characters[i] == '\n') {
+            if (lineCount)
+                offsetOfSecondToLastNewline = offsetOfLastNewline;
+            ++lineCount;
+            endColumn = 0;
+            offsetOfLastNewline = i;
+        } else
+            ++endColumn;
+
+        if (!isInStrictContext && (characters[i] == '"' || characters[i] == '\'')) {
+            const unsigned useStrictLength = strlen("use strict");
+            if (i + 1 + useStrictLength < view.length()) {
+                if (!memcmp(characters + i + 1, "use strict", useStrictLength)) {
+                    isInStrictContext = true;
+                    i += 1 + useStrictLength;
+                }
+            }
+        }
+    }
+
+    unsigned positionBeforeLastNewlineLineStartOffset = offsetOfSecondToLastNewline ? *offsetOfSecondToLastNewline + 1 : 0;
+
+    int closeBraceOffsetFromEnd = 1;
+    while (true) {
+        if (characters[view.length() - closeBraceOffsetFromEnd] == '}')
+            break;
+        ++closeBraceOffsetFromEnd;
+    }
+
     JSTextPosition positionBeforeLastNewline;
-    ParserError error;
+    positionBeforeLastNewline.line = lineCount;
+    positionBeforeLastNewline.offset = offsetOfLastNewline;
+    positionBeforeLastNewline.lineStartOffset = positionBeforeLastNewlineLineStartOffset;
+
+    SourceCode newSource = source.subExpression(10, view.length() - closeBraceOffsetFromEnd, 0, 10);
     bool isBuiltinDefaultClassConstructor = constructorKind != ConstructorKind::None;
-    JSParserBuiltinMode builtinMode = isBuiltinDefaultClassConstructor ? JSParserBuiltinMode::NotBuiltin : JSParserBuiltinMode::Builtin;
     UnlinkedFunctionKind kind = isBuiltinDefaultClassConstructor ? UnlinkedNormalFunction : UnlinkedBuiltinFunction;
-    std::unique_ptr<ProgramNode> program = parse<ProgramNode>(
-        &vm, source, Identifier(), builtinMode,
-        JSParserStrictMode::NotStrict, JSParserScriptMode::Classic, SourceParseMode::ProgramMode, SuperBinding::NotNeeded, error,
-        &positionBeforeLastNewline, constructorKind);
 
-    if (!program) {
-        dataLog("Fatal error compiling builtin function '", name.string(), "': ", error.message());
-        CRASH();
+    FunctionMetadataNode metadata(
+        start, end, startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart,
+        isInStrictContext, constructorKind, constructorKind == ConstructorKind::Extends ? SuperBinding::Needed : SuperBinding::NotNeeded,
+        parameterCount, SourceParseMode::NormalFunctionMode, isArrowFunctionBodyExpression);
+
+    metadata.finishParsing(newSource, Identifier(), FunctionMode::FunctionExpression);
+    metadata.overrideName(name);
+    metadata.setEndPosition(positionBeforeLastNewline);
+
+    if (!ASSERT_DISABLED || Options::validateBytecode()) {
+        JSTextPosition positionBeforeLastNewlineFromParser;
+        ParserError error;
+        JSParserBuiltinMode builtinMode = isBuiltinDefaultClassConstructor ? JSParserBuiltinMode::NotBuiltin : JSParserBuiltinMode::Builtin;
+        std::unique_ptr<ProgramNode> program = parse<ProgramNode>(
+            &vm, source, Identifier(), builtinMode,
+            JSParserStrictMode::NotStrict, JSParserScriptMode::Classic, SourceParseMode::ProgramMode, SuperBinding::NotNeeded, error,
+            &positionBeforeLastNewlineFromParser, constructorKind);
+
+        if (program) {
+            StatementNode* exprStatement = program->singleStatement();
+            RELEASE_ASSERT(exprStatement);
+            RELEASE_ASSERT(exprStatement->isExprStatement());
+            ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
+            RELEASE_ASSERT(funcExpr);
+            RELEASE_ASSERT(funcExpr->isFuncExprNode());
+            FunctionMetadataNode* metadataFromParser = static_cast<FuncExprNode*>(funcExpr)->metadata();
+            RELEASE_ASSERT(!program->hasCapturedVariables());
+            
+            metadataFromParser->setEndPosition(positionBeforeLastNewlineFromParser);
+            RELEASE_ASSERT(metadataFromParser);
+            RELEASE_ASSERT(metadataFromParser->ident().isNull());
+            
+            // This function assumes an input string that would result in a single anonymous function _expression_.
+            metadataFromParser->setEndPosition(positionBeforeLastNewlineFromParser);
+            RELEASE_ASSERT(metadataFromParser);
+            metadataFromParser->overrideName(name);
+            metadataFromParser->setEndPosition(positionBeforeLastNewlineFromParser);
+
+            if (metadata != *metadataFromParser || positionBeforeLastNewlineFromParser != positionBeforeLastNewline) {
+                WTFLogAlways("Metadata of parser and hand rolled parser don't match\n");
+                CRASH();
+            }
+        } else {
+            RELEASE_ASSERT(error.isValid());
+            RELEASE_ASSERT(error.type() == ParserError::StackOverflow);
+        }
     }
 
-    StatementNode* exprStatement = program->singleStatement();
-    RELEASE_ASSERT(exprStatement);
-    RELEASE_ASSERT(exprStatement->isExprStatement());
-    ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
-    RELEASE_ASSERT(funcExpr);
-    RELEASE_ASSERT(funcExpr->isFuncExprNode());
-    FunctionMetadataNode* metadata = static_cast<FuncExprNode*>(funcExpr)->metadata();
-    RELEASE_ASSERT(!program->hasCapturedVariables());
-    
-    metadata->setEndPosition(positionBeforeLastNewline);
-    RELEASE_ASSERT(metadata);
-    RELEASE_ASSERT(metadata->ident().isNull());
-    
-    // This function assumes an input string that would result in a single anonymous function _expression_.
-    metadata->setEndPosition(positionBeforeLastNewline);
-    RELEASE_ASSERT(metadata);
-    metadata->overrideName(name);
     VariableEnvironment dummyTDZVariables;
-    UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, metadata, kind, constructAbility, JSParserScriptMode::Classic, dummyTDZVariables, DerivedContextType::None, isBuiltinDefaultClassConstructor);
+    UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, &metadata, kind, constructAbility, JSParserScriptMode::Classic, dummyTDZVariables, DerivedContextType::None, isBuiltinDefaultClassConstructor);
     return functionExecutable;
 }
 

Modified: trunk/Source/_javascript_Core/builtins/GlobalOperations.js (233376 => 233377)


--- trunk/Source/_javascript_Core/builtins/GlobalOperations.js	2018-06-29 23:33:30 UTC (rev 233376)
+++ trunk/Source/_javascript_Core/builtins/GlobalOperations.js	2018-06-29 23:40:25 UTC (rev 233377)
@@ -62,6 +62,7 @@
 @overriddenName="get [Symbol.species]"
 function speciesGetter()
 {
+    "use strict";
     return this;
 }
 
@@ -68,6 +69,8 @@
 @globalPrivate
 function speciesConstructor(obj, defaultConstructor)
 {
+    "use strict";
+
     var constructor = obj.constructor;
     if (constructor === @undefined)
         return defaultConstructor;
@@ -84,6 +87,8 @@
 @globalPrivate
 function copyDataProperties(target, source, excludedSet)
 {
+    "use strict";
+
     if (!@isObject(target))
         @throwTypeError("target needs to be an object");
 
@@ -109,6 +114,8 @@
 @globalPrivate
 function copyDataPropertiesNoExclusions(target, source)
 {
+    "use strict";
+
     if (!@isObject(target))
         @throwTypeError("target needs to be an object");
 

Modified: trunk/Source/_javascript_Core/builtins/PromiseOperations.js (233376 => 233377)


--- trunk/Source/_javascript_Core/builtins/PromiseOperations.js	2018-06-29 23:33:30 UTC (rev 233376)
+++ trunk/Source/_javascript_Core/builtins/PromiseOperations.js	2018-06-29 23:40:25 UTC (rev 233377)
@@ -87,6 +87,7 @@
 @globalPrivate
 function newHandledRejectedPromise(error)
 {
+    "use strict";
     let promise = @Promise.@reject(error);
     @putByIdDirectPrivate(promise, "promiseIsHandled", true);
     return promise;

Modified: trunk/Source/_javascript_Core/builtins/RegExpPrototype.js (233376 => 233377)


--- trunk/Source/_javascript_Core/builtins/RegExpPrototype.js	2018-06-29 23:33:30 UTC (rev 233376)
+++ trunk/Source/_javascript_Core/builtins/RegExpPrototype.js	2018-06-29 23:40:25 UTC (rev 233377)
@@ -63,7 +63,10 @@
 }
 
 @globalPrivate
-function hasObservableSideEffectsForRegExpMatch(regexp) {
+function hasObservableSideEffectsForRegExpMatch(regexp)
+{
+    "use strict";
+
     // This is accessed by the RegExpExec internal function.
     let regexpExec = @tryGetById(regexp, "exec");
     if (regexpExec !== @regExpBuiltinExec)
@@ -351,7 +354,10 @@
 }
 
 @globalPrivate
-function hasObservableSideEffectsForRegExpSplit(regexp) {
+function hasObservableSideEffectsForRegExpSplit(regexp)
+{
+    "use strict";
+
     // This is accessed by the RegExpExec internal function.
     let regexpExec = @tryGetById(regexp, "exec");
     if (regexpExec !== @regExpBuiltinExec)

Modified: trunk/Source/_javascript_Core/builtins/StringPrototype.js (233376 => 233377)


--- trunk/Source/_javascript_Core/builtins/StringPrototype.js	2018-06-29 23:33:30 UTC (rev 233376)
+++ trunk/Source/_javascript_Core/builtins/StringPrototype.js	2018-06-29 23:40:25 UTC (rev 233377)
@@ -191,7 +191,10 @@
 }
 
 @globalPrivate
-function hasObservableSideEffectsForStringReplace(regexp, replacer) {
+function hasObservableSideEffectsForStringReplace(regexp, replacer)
+{
+    "use strict";
+
     if (replacer !== @regExpPrototypeSymbolReplace)
         return true;
     
@@ -235,6 +238,8 @@
 @globalPrivate
 function getDefaultCollator()
 {
+    "use strict";
+
     return @getDefaultCollator.collator || (@getDefaultCollator.collator = new @Collator());
 }
     

Modified: trunk/Source/_javascript_Core/parser/Nodes.cpp (233376 => 233377)


--- trunk/Source/_javascript_Core/parser/Nodes.cpp	2018-06-29 23:33:30 UTC (rev 233376)
+++ trunk/Source/_javascript_Core/parser/Nodes.cpp	2018-06-29 23:40:25 UTC (rev 233377)
@@ -214,6 +214,29 @@
     ASSERT(m_constructorKind == static_cast<unsigned>(constructorKind));
 }
 
+FunctionMetadataNode::FunctionMetadataNode(
+    const JSTokenLocation& startLocation, 
+    const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, 
+    int functionKeywordStart, int functionNameStart, int parametersStart, bool isInStrictContext, 
+    ConstructorKind constructorKind, SuperBinding superBinding, unsigned parameterCount, SourceParseMode mode, bool isArrowFunctionBodyExpression)
+        : Node(endLocation)
+        , m_startColumn(startColumn)
+        , m_endColumn(endColumn)
+        , m_functionKeywordStart(functionKeywordStart)
+        , m_functionNameStart(functionNameStart)
+        , m_parametersStart(parametersStart)
+        , m_startStartOffset(startLocation.startOffset)
+        , m_parameterCount(parameterCount)
+        , m_parseMode(mode)
+        , m_isInStrictContext(isInStrictContext)
+        , m_superBinding(static_cast<unsigned>(superBinding))
+        , m_constructorKind(static_cast<unsigned>(constructorKind))
+        , m_isArrowFunctionBodyExpression(isArrowFunctionBodyExpression)
+{
+    ASSERT(m_superBinding == static_cast<unsigned>(superBinding));
+    ASSERT(m_constructorKind == static_cast<unsigned>(constructorKind));
+}
+
 void FunctionMetadataNode::finishParsing(const SourceCode& source, const Identifier& ident, FunctionMode functionMode)
 {
     m_source = source;
@@ -227,6 +250,55 @@
     m_endColumn = position.offset - position.lineStartOffset;
 }
 
+bool FunctionMetadataNode::operator==(const FunctionMetadataNode& other) const
+{
+    return m_ident == other.m_ident
+        && m_ecmaName == other.m_ecmaName
+        && m_inferredName == other.m_inferredName
+        && m_functionMode== other.m_functionMode
+        && m_startColumn== other.m_startColumn
+        && m_endColumn== other.m_endColumn
+        && m_functionKeywordStart== other.m_functionKeywordStart
+        && m_functionNameStart== other.m_functionNameStart
+        && m_parametersStart== other.m_parametersStart
+        && m_source== other.m_source
+        && m_classSource== other.m_classSource
+        && m_startStartOffset== other.m_startStartOffset
+        && m_parameterCount== other.m_parameterCount
+        && m_lastLine== other.m_lastLine
+        && m_parseMode== other.m_parseMode
+        && m_isInStrictContext == other.m_isInStrictContext 
+        && m_superBinding == other.m_superBinding 
+        && m_constructorKind == other.m_constructorKind 
+        && m_isArrowFunctionBodyExpression == other.m_isArrowFunctionBodyExpression
+        && m_position == other.m_position;
+}
+
+void FunctionMetadataNode::dump(PrintStream& stream) const
+{
+    stream.println("m_ident ", m_ident);
+    stream.println("m_ecmaName ", m_ecmaName);
+    stream.println("m_inferredName ", m_inferredName);
+    stream.println("m_functionMode ", static_cast<uint32_t>(m_functionMode));
+    stream.println("m_startColumn ", m_startColumn);
+    stream.println("m_endColumn ", m_endColumn);
+    stream.println("m_functionKeywordStart ", m_functionKeywordStart);
+    stream.println("m_functionNameStart ", m_functionNameStart);
+    stream.println("m_parametersStart ", m_parametersStart);
+    stream.println("m_classSource.isNull() ", m_classSource.isNull());
+    stream.println("m_startStartOffset ", m_startStartOffset);
+    stream.println("m_parameterCount ", m_parameterCount);
+    stream.println("m_lastLine ", m_lastLine);
+    stream.println("m_parseMode ", static_cast<uint32_t>(m_parseMode));
+    stream.println("m_isInStrictContext ", m_isInStrictContext);
+    stream.println("m_superBinding ", m_superBinding);
+    stream.println("m_constructorKind ", m_constructorKind);
+    stream.println("m_isArrowFunctionBodyExpression ", m_isArrowFunctionBodyExpression);
+    stream.println("position().line ", position().line);
+    stream.println("position().offset ", position().offset);
+    stream.println("position().lineStartOffset ", position().lineStartOffset);
+}
+
 // ------------------------------ FunctionNode -----------------------------
 
 FunctionNode::FunctionNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment& varEnvironment, FunctionStack&& funcStack, VariableEnvironment& lexicalVariables, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, FunctionParameters* parameters, const SourceCode& sourceCode, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&)

Modified: trunk/Source/_javascript_Core/parser/Nodes.h (233376 => 233377)


--- trunk/Source/_javascript_Core/parser/Nodes.h	2018-06-29 23:33:30 UTC (rev 233376)
+++ trunk/Source/_javascript_Core/parser/Nodes.h	2018-06-29 23:40:25 UTC (rev 233377)
@@ -1988,7 +1988,15 @@
             int functionNameStart, int parametersStart, bool isInStrictContext, 
             ConstructorKind, SuperBinding, unsigned parameterCount,
             SourceParseMode, bool isArrowFunctionBodyExpression);
+        FunctionMetadataNode(
+            const JSTokenLocation& start, const JSTokenLocation& end, 
+            unsigned startColumn, unsigned endColumn, int functionKeywordStart, 
+            int functionNameStart, int parametersStart, bool isInStrictContext, 
+            ConstructorKind, SuperBinding, unsigned parameterCount,
+            SourceParseMode, bool isArrowFunctionBodyExpression);
 
+        void dump(PrintStream&) const;
+
         void finishParsing(const SourceCode&, const Identifier&, FunctionMode);
         
         void overrideName(const Identifier& ident) { m_ident = ident; }
@@ -2028,7 +2036,13 @@
         }
         unsigned lastLine() const { return m_lastLine; }
 
-    protected:
+        bool operator==(const FunctionMetadataNode&) const;
+        bool operator!=(const FunctionMetadataNode& other) const
+        {
+            return !(*this == other);
+        }
+
+    public:
         Identifier m_ident;
         Identifier m_ecmaName;
         Identifier m_inferredName;

Modified: trunk/Source/_javascript_Core/parser/Parser.h (233376 => 233377)


--- trunk/Source/_javascript_Core/parser/Parser.h	2018-06-29 23:33:30 UTC (rev 233376)
+++ trunk/Source/_javascript_Core/parser/Parser.h	2018-06-29 23:40:25 UTC (rev 233377)
@@ -1964,8 +1964,11 @@
         if (positionBeforeLastNewline)
             *positionBeforeLastNewline = parser.positionBeforeLastNewline();
         if (builtinMode == JSParserBuiltinMode::Builtin) {
-            if (!result)
-                dataLogLn("Error compiling builtin: ", error.message());
+            if (!result) {
+                ASSERT(error.isValid());
+                if (error.type() != ParserError::StackOverflow)
+                    dataLogLn("Unexpected error compiling builtin: ", error.message());
+            }
         }
     } else {
         ASSERT_WITH_MESSAGE(defaultConstructorKind == ConstructorKind::None, "BuiltinExecutables::createDefaultConstructor should always use a 8-bit string");

Modified: trunk/Source/_javascript_Core/parser/ParserError.h (233376 => 233377)


--- trunk/Source/_javascript_Core/parser/ParserError.h	2018-06-29 23:33:30 UTC (rev 233376)
+++ trunk/Source/_javascript_Core/parser/ParserError.h	2018-06-29 23:40:25 UTC (rev 233377)
@@ -83,6 +83,7 @@
     const JSToken& token() const { return m_token; }
     const String& message() const { return m_message; }
     int line() const { return m_line; }
+    ErrorType type() const { return m_type; }
 
     JSObject* toErrorObject(
         JSGlobalObject* globalObject, const SourceCode& source, 

Modified: trunk/Source/_javascript_Core/parser/ParserTokens.h (233376 => 233377)


--- trunk/Source/_javascript_Core/parser/ParserTokens.h	2018-06-29 23:33:30 UTC (rev 233376)
+++ trunk/Source/_javascript_Core/parser/ParserTokens.h	2018-06-29 23:40:25 UTC (rev 233377)
@@ -202,6 +202,17 @@
 
     operator int() const { return offset; }
 
+    bool operator==(const JSTextPosition& other) const
+    {
+        return line == other.line
+            && offset == other.offset
+            && lineStartOffset == other.lineStartOffset;
+    }
+    bool operator!=(const JSTextPosition& other) const
+    {
+        return !(*this == other);
+    }
+
     int line;
     int offset;
     int lineStartOffset;

Modified: trunk/Source/_javascript_Core/parser/SourceCode.h (233376 => 233377)


--- trunk/Source/_javascript_Core/parser/SourceCode.h	2018-06-29 23:33:30 UTC (rev 233376)
+++ trunk/Source/_javascript_Core/parser/SourceCode.h	2018-06-29 23:40:25 UTC (rev 233377)
@@ -79,8 +79,22 @@
 
         SourceProvider* provider() const { return m_provider.get(); }
 
-        SourceCode subExpression(unsigned openBrace, unsigned closeBrace, int firstLine, int startColumn);
+        SourceCode subExpression(unsigned openBrace, unsigned closeBrace, int firstLine, int startColumn) const;
 
+        bool operator==(const SourceCode& other) const
+        {
+            return m_firstLine == other.m_firstLine
+                && m_startColumn == other.m_startColumn
+                && m_provider == other.m_provider
+                && m_startOffset == other.m_startOffset
+                && m_endOffset == other.m_endOffset;
+        }
+
+        bool operator!=(const SourceCode& other) const
+        {
+            return !(*this == other);
+        }
+
     private:
         OrdinalNumber m_firstLine;
         OrdinalNumber m_startColumn;
@@ -91,7 +105,7 @@
         return SourceCode(StringSourceProvider::create(source, sourceOrigin, url, startPosition, sourceType), startPosition.m_line.oneBasedInt(), startPosition.m_column.oneBasedInt());
     }
     
-    inline SourceCode SourceCode::subExpression(unsigned openBrace, unsigned closeBrace, int firstLine, int startColumn)
+    inline SourceCode SourceCode::subExpression(unsigned openBrace, unsigned closeBrace, int firstLine, int startColumn) const
     {
         startColumn += 1; // Convert to base 1.
         return SourceCode(RefPtr<SourceProvider> { provider() }, openBrace, closeBrace + 1, firstLine, startColumn);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to