Changeset 204895 in webkit


Ignore:
Timestamp:
Aug 24, 2016 6:35:38 AM (8 years ago)
Author:
gskachkov@gmail.com
Message:

2016] Allow assignment in for-in head in not-strict mode
https://bugs.webkit.org/show_bug.cgi?id=160955

Reviewed by Saam Barati.

This patch allow make assignment in for..in head in not-strict mode,
according to the spec https://tc39.github.io/ecma262/#sec-initializers-in-forin-statement-heads

Source/JavaScriptCore:

  • bytecompiler/NodesCodegen.cpp:

(JSC::ForInNode::emitLoopHeader):
(JSC::ForInNode::emitMultiLoopBytecode):

  • parser/Nodes.h:

(JSC::ExpressionNode::isAssignResolveNode):
(JSC::AssignResolveNode::identifier):
(JSC::ExpressionNode::isResolveNode): Deleted.

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::parseForStatement):

JSTests:

  • stress/for-in-tests.js:

(foo):
(boo):
(catch):

LayoutTests:

  • js/parser-syntax-check-expected.txt:
  • js/script-tests/parser-syntax-check.js:
Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r204881 r204895  
     12016-08-24  Skachkov Oleksandr  <gskachkov@gmail.com>
     2
     3        [ES2016] Allow assignment in for-in head in not-strict mode
     4        https://bugs.webkit.org/show_bug.cgi?id=160955
     5
     6        Reviewed by Saam Barati.
     7
     8        * stress/for-in-tests.js:
     9        (foo):
     10        (boo):
     11        (catch):
     12
    1132016-08-23  Benjamin Poulain  <benjamin@webkit.org>
    214
  • trunk/JSTests/stress/for-in-tests.js

    r172413 r204895  
    9999    }
    100100})();
     101
     102(function() {
     103    var foo = function(a, b) {
     104        for (var p = b in a) {}
     105        return p;
     106    };
     107    noInline(foo);
     108    for (var i = 0; i < 10000; ++i) {
     109        var expected = 'expected-result';
     110        var result = foo({}, expected);
     111        if (expected !== result)
     112            throw new Error("bad result: " + result + "!==" + expected);
     113    }
     114    for (var i = 0; i < 10000; ++i) {
     115        var expected = 'a';
     116        var result = foo({a:'abcd'}, expected);
     117        if (expected !== result)
     118            throw new Error("bad result: " + result + "!==" + expected);
     119    }
     120    for (var i = 0; i < 10000; ++i) {
     121        var expected = 'b';
     122        var result = foo({a:'abcd', b: 'bcde'}, expected);
     123        if (expected !== result)
     124            throw new Error("bad result: " + result + "!==" + expected);
     125    }
     126
     127    for (var i = 0; i < 10000; ++i) {
     128        var expected = 'c';
     129        var o = {a:'abcd', b: 'bcde'};
     130        o.c = 'cdef';
     131        var result = foo(o, expected);
     132        if (expected !== result)
     133            throw new Error("bad result: " + result + "!==" + expected);
     134    }
     135})();
     136
     137(function() {
     138    var boo = function () { return 'expected-result'; };
     139    var foo = function(a) {
     140        for (var p = boo() in a) {}
     141        return p;
     142    };
     143    noInline(foo);
     144    for (var i = 0; i < 10000; ++i) {
     145        var expected = 'expected-result';
     146        var result = foo({});
     147        if (expected !== result)
     148            throw new Error("bad result: " + result + "!==" + expected);
     149    }
     150})();
     151
     152(function() {
     153    var foo = function(a, b, first) {
     154        {   
     155            let p = 'some-value';
     156            for (var p = b in a) {}
     157            if (first)
     158                return p;
     159        }
     160        return p;
     161    };
     162    noInline(foo);
     163    for (var i = 0; i < 10000; ++i) {
     164        var expected = 'expected-result';
     165        var result = foo({}, expected, true);
     166        if (expected !== result)
     167            throw new Error("bad result: " + result + "!==" + expected);
     168    }
     169    for (var i = 0; i < 10000; ++i) {
     170        var expected = 'expected-result';
     171        var result = foo({}, expected, false);
     172        if (typeof result !== 'undefined')
     173            throw new Error("bad result: " + result + "!== undefined");
     174    }
     175})();
     176
     177(function() {
     178    var foo = function(a, b, c) {
     179        for (var p = b + c in a) {}
     180        return p;
     181    };
     182    noInline(foo);
     183    for (var i = 0; i < 10000; ++i) {
     184        var expected = 'expected-result';
     185        var result = foo({}, 'expected', '-result');
     186        if (expected !== result)
     187            throw new Error("bad result: " + result + "!==" + expected);
     188    }
     189})();
     190
     191(function() {
     192    var error = false;
     193    try {
     194        eval("(function() { 'use strict'; for (var i = 0 in {}) {}})()");
     195    } catch(e) {
     196        error = e instanceof SyntaxError;
     197    }
     198    if (!error)
     199        throw new Error("Expected SyntaxError error");
     200})();
     201
     202(function() {
     203    var error = false;
     204    try {
     205        eval("(function() { const i = 10; for (var i = 0 in {}) {}})()");
     206    } catch(e) {
     207        error = e instanceof SyntaxError;
     208    }
     209    if (!error)
     210        throw new Error("Expected SyntaxError error");
     211})();
  • trunk/LayoutTests/ChangeLog

    r204891 r204895  
     12016-08-24  Skachkov Oleksandr  <gskachkov@gmail.com>
     2
     3        [ES2016] Allow assignment in for-in head in not-strict mode
     4        https://bugs.webkit.org/show_bug.cgi?id=160955
     5
     6        Reviewed by Saam Barati.
     7
     8        * js/parser-syntax-check-expected.txt:
     9        * js/script-tests/parser-syntax-check.js:
     10
    1112016-08-24  Youenn Fablet  <youenn@apple.com>
    212
  • trunk/LayoutTests/js/parser-syntax-check-expected.txt

    r204078 r204895  
    507507PASS Valid:   "for (var a = 5 += 6 in b) break" with ReferenceError
    508508PASS Valid:   "function f() { for (var a = 5 += 6 in b) break }"
    509 PASS Valid:   "for (var a = debug('should not be hit') in b) break" with ReferenceError
    510 PASS Valid:   "function f() { for (var a = debug('should not be hit') in b) break }"
     509PASS Valid:   "for (var a = foo('should be hit') in b) break" with ReferenceError
     510PASS Valid:   "function f() { for (var a = foo('should be hit') in b) break }"
    511511PASS Invalid: "for (var a += 5 in b) break"
    512512PASS Invalid: "function f() { for (var a += 5 in b) break }"
  • trunk/LayoutTests/js/script-tests/parser-syntax-check.js

    r204078 r204895  
    347347valid  ("for (var a in b in c) break");
    348348valid("for (var a = 5 += 6 in b) break");
    349 valid("for (var a = debug('should not be hit') in b) break");
     349valid("for (var a = foo('should be hit') in b) break");
    350350invalid("for (var a += 5 in b) break");
    351351invalid("for (var a = in b) break");
  • trunk/Source/JavaScriptCore/ChangeLog

    r204882 r204895  
     12016-08-24  Skachkov Oleksandr  <gskachkov@gmail.com>
     2
     3        [ES2016] Allow assignment in for-in head in not-strict mode
     4        https://bugs.webkit.org/show_bug.cgi?id=160955
     5
     6        Reviewed by Saam Barati.
     7
     8        This patch allow make assignment in for..in head in not-strict mode,
     9        according to the spec https://tc39.github.io/ecma262/#sec-initializers-in-forin-statement-heads
     10
     11        * bytecompiler/NodesCodegen.cpp:
     12        (JSC::ForInNode::emitLoopHeader):
     13        (JSC::ForInNode::emitMultiLoopBytecode):
     14        * parser/Nodes.h:
     15        (JSC::ExpressionNode::isAssignResolveNode):
     16        (JSC::AssignResolveNode::identifier):
     17        (JSC::ExpressionNode::isResolveNode): Deleted.
     18        * parser/Parser.cpp:
     19        (JSC::Parser<LexerType>::parseForStatement):
     20
    1212016-08-23  Saam Barati  <sbarati@apple.com>
    222
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r204597 r204895  
    25602560void ForInNode::emitLoopHeader(BytecodeGenerator& generator, RegisterID* propertyName)
    25612561{
    2562     if (m_lexpr->isResolveNode()) {
    2563         const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
     2562    auto lambdaEmitResolveVariable = [&](const Identifier& ident)
     2563    {
    25642564        Variable var = generator.variable(ident);
    25652565        if (RegisterID* local = var.local()) {
     
    25772577        }
    25782578        generator.emitProfileType(propertyName, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
     2579    };
     2580
     2581    if (m_lexpr->isResolveNode()) {
     2582        const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
     2583        lambdaEmitResolveVariable(ident);
    25792584        return;
    25802585    }
     2586
     2587    if (m_lexpr->isAssignResolveNode()) {
     2588        const Identifier& ident = static_cast<AssignResolveNode*>(m_lexpr)->identifier();
     2589        lambdaEmitResolveVariable(ident);
     2590        return;
     2591    }
     2592
    25812593    if (m_lexpr->isDotAccessorNode()) {
    25822594        DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
     
    26312643void ForInNode::emitMultiLoopBytecode(BytecodeGenerator& generator, RegisterID* dst)
    26322644{
    2633     if (!m_lexpr->isAssignmentLocation()) {
     2645    if (!m_lexpr->isAssignResolveNode() && !m_lexpr->isAssignmentLocation()) {
    26342646        emitThrowReferenceError(generator, ASCIILiteral("Left side of for-in statement is not a reference."));
    26352647        return;
     
    26422654
    26432655    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
     2656
     2657    if (m_lexpr->isAssignResolveNode())
     2658        generator.emitNode(generator.ignoredResult(), m_lexpr);
    26442659
    26452660    RefPtr<RegisterID> base = generator.newTemporary();
    26462661    RefPtr<RegisterID> length;
    26472662    RefPtr<RegisterID> enumerator;
     2663
    26482664    generator.emitNode(base.get(), m_expr);
    26492665    RefPtr<RegisterID> local = this->tryGetBoundLocal(generator);
  • trunk/Source/JavaScriptCore/parser/Nodes.h

    r204854 r204895  
    169169        virtual bool isAssignmentLocation() const { return isLocation(); }
    170170        virtual bool isResolveNode() const { return false; }
     171        virtual bool isAssignResolveNode() const { return false; }
    171172        virtual bool isBracketAccessorNode() const { return false; }
    172173        virtual bool isDotAccessorNode() const { return false; }
     
    12181219    public:
    12191220        AssignResolveNode(const JSTokenLocation&, const Identifier&, ExpressionNode* right, AssignmentContext);
     1221        bool isAssignResolveNode() const override { return true; }
     1222        const Identifier& identifier() const { return m_ident; }
    12201223
    12211224    private:
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r204842 r204895  
    12041204        if (isOfEnumeration)
    12051205            result = context.createForOfLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
    1206         else
    1207             result = context.createForInLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
     1206        else {
     1207            if (isVarDeclaraton && forInInitializer)
     1208                result = context.createForInLoop(location, decls, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
     1209            else
     1210                result = context.createForInLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
     1211        }
    12081212        popLexicalScopeIfNecessary();
    12091213        return result;
Note: See TracChangeset for help on using the changeset viewer.