Changeset 200824 in webkit


Ignore:
Timestamp:
May 13, 2016 1:22:21 AM (8 years ago)
Author:
gskachkov@gmail.com
Message:

Assertion failure for super() call in arrow function default parameters
https://bugs.webkit.org/show_bug.cgi?id=157079

Reviewed by Saam Barati.

Source/JavaScriptCore:

Root of the issue that in arrow function we load bounded variables this/super/new.target just after
input parameters were initialized, and did not covered case of default values for function parameters.
Current patch tried to fix issue and allow to load bounded variables earlier, before the input
parameters are assigned by default values.

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::BytecodeGenerator):

  • tests/stress/arrowfunction-lexical-bind-this-2.js:

LayoutTests:

  • js/arrowfunction-lexical-bind-arguments-non-strict-expected.txt:
  • js/arrowfunction-lexical-bind-this-expected.txt:
  • js/arrowfunction-supercall-expected.txt:
  • js/arrowfunction-superproperty-expected.txt:
  • js/script-tests/arrowfunction-lexical-bind-arguments-non-strict.js:
  • js/script-tests/arrowfunction-lexical-bind-this.js:
  • js/script-tests/arrowfunction-supercall.js:
  • js/script-tests/arrowfunction-superproperty.js:
Location:
trunk
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r200821 r200824  
     12016-05-13  Skachkov Oleksandr  <gskachkov@gmail.com>
     2
     3        Assertion failure for super() call in arrow function default parameters
     4        https://bugs.webkit.org/show_bug.cgi?id=157079
     5
     6        Reviewed by Saam Barati.
     7
     8        * js/arrowfunction-lexical-bind-arguments-non-strict-expected.txt:
     9        * js/arrowfunction-lexical-bind-this-expected.txt:
     10        * js/arrowfunction-supercall-expected.txt:
     11        * js/arrowfunction-superproperty-expected.txt:
     12        * js/script-tests/arrowfunction-lexical-bind-arguments-non-strict.js:
     13        * js/script-tests/arrowfunction-lexical-bind-this.js:
     14        * js/script-tests/arrowfunction-supercall.js:
     15        * js/script-tests/arrowfunction-superproperty.js:
     16
    1172016-05-12  Sergio Villar Senin  <svillar@igalia.com>
    218
  • trunk/LayoutTests/js/arrowfunction-lexical-bind-arguments-non-strict-expected.txt

    r195581 r200824  
    2323PASS foo(10, 11, 12).next().value()[1] is 11
    2424PASS foo(10, 11, 12).next().value()[2] is 12
     25PASS (function (a, b, c) { return (a = arguments) => {return a;}; })('1-1', '2-2', '3-3')()[1] is '2-2'
    2526PASS successfullyParsed is true
    2627
  • trunk/LayoutTests/js/arrowfunction-lexical-bind-this-expected.txt

    r198978 r200824  
    2020PASS fooObject.arr() is internal_value_1
    2121PASS fooObject._id is internal_value_2
    22 PASS boo.call(o1) is o1
     22PASS boo.call(expected) is expected
     23PASS (function () { return (a = this)=>{return a;}; }).call(expected)() is expected
    2324PASS successfullyParsed is true
    2425
  • trunk/LayoutTests/js/arrowfunction-supercall-expected.txt

    r193766 r200824  
    2222PASS indexOfarrowInChildConstructorInStackError > -1 && errorStack.indexOf('arrowInChildConstructor', indexOfarrowInChildConstructorInStackError + 1) === -1 is true
    2323PASS indexOfChildClassInStackError > -1 && errorStack.indexOf('ChildClass', indexOfChildClassInStackError + 1) === -1 is true
     24PASS (new class extends A { constructor() { ((a = super())=>{})() } }).id is value
     25PASS (new class extends A { constructor() { ((a = this)=>{ return a; })() } }) threw exception ReferenceError: Cannot access uninitialized variable..
     26PASS (new class extends A { constructor() { ((a = this, b=super())=>{ return a; })() } }) threw exception ReferenceError: Cannot access uninitialized variable..
     27PASS (new class extends A { constructor() { ((a = new.target)=>{ return a; })(); super(); } }) did not throw exception.
     28PASS (new class extends A { constructor() { ((a = new.target, b=super())=>{ return a; })() } }) did not throw exception.
    2429PASS successfullyParsed is true
    2530
  • trunk/LayoutTests/js/arrowfunction-superproperty-expected.txt

    r198714 r200824  
    1313PASS (new F()).genGetParentValue().next().value is expectedValue
    1414PASS (new F()).genGetParentValueDeepArrow().next().value is expectedValue
     15PASS (new class extends A { constructor() { ((a = super(), b = super.getValue())=>{ this.id = b; })() } }).id is expectedValue
     16PASS (new class extends A { constructor() { ((a = super(), b = new.target)=>{ this.newTarget = b; })(); expectedNewTarget = new.target;} }).newTarget is expectedNewTarget
     17PASS (new class extends A { constructor() { ((a = super.getValue())=>{ this.id = a; })() } }) threw exception ReferenceError: Cannot access uninitialized variable..
     18PASS (new class extends A { constructor() { ((a = super.getValue(), b=super())=>{ this.id = a; })() } }) threw exception ReferenceError: Cannot access uninitialized variable..
     19PASS (new class extends F { constructor() { ((a = super.prop)=>{ return a; })() } }) threw exception ReferenceError: Cannot access uninitialized variable..
     20PASS (new class extends F { constructor() { ((a = super.prop, b=super())=>{ return a; })() } }) threw exception ReferenceError: Cannot access uninitialized variable..
     21PASS (new class extends F { constructor() { ((a = (super.prop = "value"))=>{ this.id = a; })() } }) threw exception ReferenceError: Cannot access uninitialized variable..
     22PASS (new class extends F { constructor() { ((a = (super.prop = "value"), b=super())=>{ this.id = a; })() } }) threw exception ReferenceError: Cannot access uninitialized variable..
     23PASS (new class extends F { constructor() { ((a = super.genGetParentValue().next().value)=>{ this.id = a; })() } }) threw exception ReferenceError: Cannot access uninitialized variable..
     24PASS (new class extends F { constructor() { ((a = super.genGetParentValue().next().value, b=super())=>{ this.id = a; })() } }) threw exception ReferenceError: Cannot access uninitialized variable..
    1525PASS successfullyParsed is true
    1626
  • trunk/LayoutTests/js/script-tests/arrowfunction-lexical-bind-arguments-non-strict.js

    r195581 r200824  
    146146shouldBe("foo(10, 11, 12).next().value()[1]", "11");
    147147shouldBe("foo(10, 11, 12).next().value()[2]", "12");
     148shouldBe("(function (a, b, c) { return (a = arguments) => {return a;}; })('1-1', '2-2', '3-3')()[1]", "'2-2'");
    148149
    149150var successfullyParsed = true;
  • trunk/LayoutTests/js/script-tests/arrowfunction-lexical-bind-this.js

    r198978 r200824  
    108108}
    109109
    110 let o1 = {'this': 20};
     110let expected = {'this': 20};
    111111
    112 shouldBe('boo.call(o1)', 'o1');
     112shouldBe('boo.call(expected)', 'expected');
     113shouldBe('(function () { return (a = this)=>{return a;}; }).call(expected)()', 'expected');
    113114
    114115var successfullyParsed = true;
  • trunk/LayoutTests/js/script-tests/arrowfunction-supercall.js

    r193766 r200824  
    149149shouldBeTrue("indexOfChildClassInStackError > -1 && errorStack.indexOf('ChildClass', indexOfChildClassInStackError + 1) === -1");
    150150
     151shouldBe("(new class extends A { constructor() { ((a = super())=>{})() } }).id", "value");
     152shouldThrow('(new class extends A { constructor() { ((a = this)=>{ return a; })() } })', '"ReferenceError: Cannot access uninitialized variable."');
     153shouldThrow('(new class extends A { constructor() { ((a = this, b=super())=>{ return a; })() } })', '"ReferenceError: Cannot access uninitialized variable."');
     154shouldNotThrow('(new class extends A { constructor() { ((a = new.target)=>{ return a; })(); super(); } })', '"ReferenceError: Cannot access uninitialized variable."');
     155shouldNotThrow('(new class extends A { constructor() { ((a = new.target, b=super())=>{ return a; })() } })', '"ReferenceError: Cannot access uninitialized variable."');
     156
    151157var successfullyParsed = true;
  • trunk/LayoutTests/js/script-tests/arrowfunction-superproperty.js

    r198714 r200824  
    9393shouldBe('(new F()).genGetParentValue().next().value', 'expectedValue');
    9494shouldBe('(new F()).genGetParentValueDeepArrow().next().value', 'expectedValue');
     95shouldBe('(new class extends A { constructor() { ((a = super(), b = super.getValue())=>{ this.id = b; })() } }).id', 'expectedValue');
     96var expectedNewTarget;
     97shouldBe('(new class extends A { constructor() { ((a = super(), b = new.target)=>{ this.newTarget = b; })(); expectedNewTarget = new.target;} }).newTarget', 'expectedNewTarget');
     98shouldThrow('(new class extends A { constructor() { ((a = super.getValue())=>{ this.id = a; })() } })', '"ReferenceError: Cannot access uninitialized variable."');
     99shouldThrow('(new class extends A { constructor() { ((a = super.getValue(), b=super())=>{ this.id = a; })() } })', '"ReferenceError: Cannot access uninitialized variable."');
     100shouldThrow('(new class extends F { constructor() { ((a = super.prop)=>{ return a; })() } })', '"ReferenceError: Cannot access uninitialized variable."');
     101shouldThrow('(new class extends F { constructor() { ((a = super.prop, b=super())=>{ return a; })() } })', '"ReferenceError: Cannot access uninitialized variable."');
     102shouldThrow('(new class extends F { constructor() { ((a = (super.prop = "value"))=>{ this.id = a; })() } })', '"ReferenceError: Cannot access uninitialized variable."');
     103shouldThrow('(new class extends F { constructor() { ((a = (super.prop = "value"), b=super())=>{ this.id = a; })() } })', '"ReferenceError: Cannot access uninitialized variable."');
     104shouldThrow('(new class extends F { constructor() { ((a = super.genGetParentValue().next().value)=>{ this.id = a; })() } })', '"ReferenceError: Cannot access uninitialized variable."');
     105shouldThrow('(new class extends F { constructor() { ((a = super.genGetParentValue().next().value, b=super())=>{ this.id = a; })() } })', '"ReferenceError: Cannot access uninitialized variable."');
    95106
    96107var successfullyParsed = true;
  • trunk/Source/JavaScriptCore/ChangeLog

    r200796 r200824  
     12016-05-13  Skachkov Oleksandr  <gskachkov@gmail.com>
     2
     3        Assertion failure for super() call in arrow function default parameters
     4        https://bugs.webkit.org/show_bug.cgi?id=157079
     5
     6        Reviewed by Saam Barati.
     7
     8        Root of the issue that in arrow function we load bounded variables this/super/new.target just after
     9        input parameters were initialized, and did not covered case of default values for
     10        function parameters.
     11        Current patch tried to fix issue and allow to load bounded variables earlier, before the input
     12        parameters are assigned by default values.
     13
     14        * bytecompiler/BytecodeGenerator.cpp:
     15        (JSC::BytecodeGenerator::BytecodeGenerator):
     16        * tests/stress/arrowfunction-lexical-bind-this-2.js:
     17
    1182016-05-12  Mark Lam  <mark.lam@apple.com>
    219
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r200586 r200824  
    558558    }
    559559
     560    // We need load |super| & |this| for arrow function before initializeDefaultParameterValuesAndSetupFunctionScopeStack
     561    // if we have default parameter expression. Because |super| & |this| values can be used there
     562    if (SourceParseMode::ArrowFunctionMode == parseMode && !isSimpleParameterList) {
     563        if (functionNode->usesThis() || functionNode->usesSuperProperty())
     564            emitLoadThisFromArrowFunctionLexicalEnvironment();
     565
     566        if (m_scopeNode->usesNewTarget() || m_scopeNode->usesSuperCall())
     567            emitLoadNewTargetFromArrowFunctionLexicalEnvironment();
     568    }
     569
    560570    // All "addVar()"s needs to happen before "initializeDefaultParameterValuesAndSetupFunctionScopeStack()" is called
    561571    // because a function's default parameter ExpressionNodes will use temporary registers.
     
    563573    initializeDefaultParameterValuesAndSetupFunctionScopeStack(parameters, isSimpleParameterList, functionNode, functionSymbolTable, symbolTableConstantIndex, captures);
    564574   
    565     // Loading |this| inside an arrow function must be done after initializeDefaultParameterValuesAndSetupFunctionScopeStack()
    566     // because that function sets up the SymbolTable stack and emitLoadThisFromArrowFunctionLexicalEnvironment()
    567     // consults the SymbolTable stack
    568     if (SourceParseMode::ArrowFunctionMode == parseMode) {
     575    // If we don't have  default parameter expression, then loading |this| inside an arrow function must be done
     576    // after initializeDefaultParameterValuesAndSetupFunctionScopeStack() because that function sets up the
     577    // SymbolTable stack and emitLoadThisFromArrowFunctionLexicalEnvironment() consults the SymbolTable stack
     578    if (SourceParseMode::ArrowFunctionMode == parseMode && isSimpleParameterList) {
    569579        if (functionNode->usesThis() || functionNode->usesSuperProperty())
    570580            emitLoadThisFromArrowFunctionLexicalEnvironment();
  • trunk/Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-this-2.js

    r194340 r200824  
    7171var fooObject = new foo();
    7272
     73function fooDefault() {
     74    let arr = (that = this) => {
     75        var x = 123;
     76        function bas() {
     77            return x;
     78        };
     79        that._id = '12345';
     80        return bas();
     81    };
     82    this.arr = arr;
     83};
     84
     85var fooDefaultObject = new fooDefault();
     86
    7387for (var i=0; i < 10000; i++) {
    7488    testCase(fooObject.arr() === 123, true, "Error: this is not lexically binded inside of the arrow function #7");
    7589    testCase(fooObject._id === '12345', true, "Error: this is not lexically binded inside of the arrow function #8");
     90    testCase(fooDefaultObject.arr() === 123, true, "Error: this is not lexically binded inside of the arrow function #7");
     91    testCase(fooDefaultObject._id === '12345', true, "Error: this is not lexically binded inside of the arrow function #8");
    7692}
Note: See TracChangeset for help on using the changeset viewer.