Changeset 196261 in webkit


Ignore:
Timestamp:
Feb 8, 2016 11:29:24 AM (8 years ago)
Author:
commit-queue@webkit.org
Message:

[ES6] Arrow function syntax. Using 'super' in arrow function that declared out of the class should lead to Syntax error
https://bugs.webkit.org/show_bug.cgi?id=150893

Patch by Skachkov Oleksandr <gskachkov@gmail.com> on 2016-02-08
Reviewed by Saam Barati.
Source/JavaScriptCore:

'super' and 'super()' inside of the arrow function should lead to syntax error if they are used
out of the class context or they wrapped by ordinary function. Now JSC returns ReferenceError but
should return SyntaxError according to the following specs:
http://www.ecma-international.org/ecma-262/6.0/#sec-function-definitions-static-semantics-early-errors
and http://www.ecma-international.org/ecma-262/6.0/#sec-arrow-function-definitions-runtime-semantics-evaluation
Curren patch implemented only one case when super/super() are used inside of the arrow function
Case when super/super() are used within the eval:

class A {}
class B extends A {

costructor() { eval("super()");}

}

is not part of this patch and will be implemented in this issue https://bugs.webkit.org/show_bug.cgi?id=153864.
The same for case when eval with super/super() is invoked in arrow function will be
implemented in issue https://bugs.webkit.org/show_bug.cgi?id=153977.

  • parser/Parser.cpp:

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

  • parser/Parser.h:

(JSC::Scope::Scope):
(JSC::Scope::setExpectedSuperBinding):
(JSC::Scope::expectedSuperBinding):
(JSC::Scope::setConstructorKind):
(JSC::Scope::constructorKind):
(JSC::Parser::closestParentNonArrowFunctionNonLexicalScope):

  • tests/stress/arrowfunction-lexical-bind-supercall-4.js:
  • tests/stress/arrowfunction-lexical-bind-superproperty.js:

LayoutTests:

Adding tests for using of the 'super' inside of the arrow function

  • js/arrowfunction-superproperty-expected.txt:
  • js/arrowfunction-syntax-errors-expected.txt:
  • js/script-tests/arrowfunction-superproperty.js:
  • js/script-tests/arrowfunction-syntax-errors.js:
Location:
trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r196250 r196261  
     12016-02-08  Skachkov Oleksandr  <gskachkov@gmail.com>
     2
     3        [ES6] Arrow function syntax. Using 'super' in arrow function that declared out of the class should lead to Syntax error
     4        https://bugs.webkit.org/show_bug.cgi?id=150893
     5
     6        Reviewed by Saam Barati.
     7       
     8        Adding tests for using of the 'super' inside of the arrow function
     9 
     10        * js/arrowfunction-superproperty-expected.txt:
     11        * js/arrowfunction-syntax-errors-expected.txt:
     12        * js/script-tests/arrowfunction-superproperty.js:
     13        * js/script-tests/arrowfunction-syntax-errors.js:
     14
    1152016-02-08  Adrien Plazas  <aplazas@igalia.com>
    216
  • trunk/LayoutTests/js/arrowfunction-superproperty-expected.txt

    r194449 r196261  
    1010PASS f.prop is expectedValue + "-" + "new-value"
    1111PASS (new F()).getParentValue() is expectedValue
    12 PASS (new F()).getParentValueWithError()() threw exception TypeError: undefined is not an object (evaluating 'super.getValue').
    1312PASS successfullyParsed is true
    1413
  • trunk/LayoutTests/js/arrowfunction-syntax-errors-expected.txt

    r195178 r196261  
    132132PASS var arr3 = {c:a,d:b} => a + b; threw exception SyntaxError: Unexpected token '=>'. Expected ';' after variable declaration..
    133133PASS var arr3 = {c:b,d:a} => a + b; threw exception SyntaxError: Unexpected token '=>'. Expected ';' after variable declaration..
     134PASS var arr4 = () => { super(); }; threw exception SyntaxError: Cannot call super() outside of a class constructor..
     135PASS var arr4 = () => { super; }; threw exception SyntaxError: Cannot reference super..
     136PASS var arr5 = () => { super.getValue(); }; threw exception SyntaxError: super can only be used in a method of a derived class..
     137PASS var arr6 = () =>  super(); threw exception SyntaxError: Cannot call super() outside of a class constructor..
     138PASS var arr7 = () =>  super; threw exception SyntaxError: Cannot reference super..
     139PASS var arr8 = () =>  super.getValue(); threw exception SyntaxError: super can only be used in a method of a derived class..
     140PASS class A { constructor() { function a () { return () => { super(); };}} threw exception SyntaxError: Cannot call super() outside of a class constructor..
     141PASS class B { constructor() { function b () { return () => { super; }; }; }} threw exception SyntaxError: Cannot reference super..
     142PASS class C { constructor() { function c () { return () => { super.getValue(); };}} threw exception SyntaxError: super can only be used in a method of a derived class..
     143PASS class D { constructor() { function a () { return () => super(); }} threw exception SyntaxError: Cannot call super() outside of a class constructor..
     144PASS class E { constructor() { function b () { return () => super; }; }} threw exception SyntaxError: Cannot reference super..
     145PASS class F { constructor() { function c () { return () => super.getValue(); }} threw exception SyntaxError: super can only be used in a method of a derived class..
     146PASS class G {}; class G2 extends G { getValue() { function c () { return () => super.getValue(); }} threw exception SyntaxError: super can only be used in a method of a derived class..
    134147PASS successfullyParsed is true
    135148
  • trunk/LayoutTests/js/script-tests/arrowfunction-superproperty.js

    r194449 r196261  
    6464        return arrow()();
    6565    }
    66     getParentValueWithError() {
    67         var f =  function () {
    68             return () => super.getValue();
    69         };
    70         return f();
    71     }
    7266 };
    7367
     
    9185shouldBe('(new F()).getParentValue()', 'expectedValue');
    9286
    93 shouldThrow('(new F()).getParentValueWithError()()');
    94 
    9587var successfullyParsed = true;
  • trunk/LayoutTests/js/script-tests/arrowfunction-syntax-errors.js

    r195178 r196261  
    4949shouldThrow('var arr3 = {c:b,d:a} => a + b;');
    5050
     51shouldThrow('var arr4 = () => { super(); };', '"SyntaxError: Cannot call super() outside of a class constructor."');
     52shouldThrow('var arr4 = () => { super; };', '"SyntaxError: Cannot reference super."');
     53shouldThrow('var arr5 = () => { super.getValue(); };', '"SyntaxError: super can only be used in a method of a derived class."');
     54
     55shouldThrow('var arr6 = () =>  super();', '"SyntaxError: Cannot call super() outside of a class constructor."');
     56shouldThrow('var arr7 = () =>  super;', '"SyntaxError: Cannot reference super."');
     57shouldThrow('var arr8 = () =>  super.getValue();', '"SyntaxError: super can only be used in a method of a derived class."');
     58
     59shouldThrow('class A { constructor() { function a () { return () => { super(); };}}', '"SyntaxError: Cannot call super() outside of a class constructor."');
     60shouldThrow('class B { constructor() { function b () { return () => { super; }; }; }}', '"SyntaxError: Cannot reference super."');
     61shouldThrow('class C { constructor() { function c () { return () => { super.getValue(); };}}', '"SyntaxError: super can only be used in a method of a derived class."');
     62
     63shouldThrow('class D { constructor() { function a () { return () => super(); }}', '"SyntaxError: Cannot call super() outside of a class constructor."');
     64shouldThrow('class E { constructor() { function b () { return () => super; }; }}', '"SyntaxError: Cannot reference super."');
     65shouldThrow('class F { constructor() { function c () { return () => super.getValue(); }}', '"SyntaxError: super can only be used in a method of a derived class."');
     66shouldThrow('class G {}; class G2 extends G { getValue() { function c () { return () => super.getValue(); }}', '"SyntaxError: super can only be used in a method of a derived class."');
     67
    5168var successfullyParsed = true;
  • trunk/Source/JavaScriptCore/ChangeLog

    r196258 r196261  
     12016-02-08  Skachkov Oleksandr  <gskachkov@gmail.com>
     2
     3        [ES6] Arrow function syntax. Using 'super' in arrow function that declared out of the class should lead to Syntax error
     4        https://bugs.webkit.org/show_bug.cgi?id=150893
     5
     6        Reviewed by Saam Barati.
     7
     8        'super' and 'super()' inside of the arrow function should lead to syntax error if they are used
     9        out of the class context or they wrapped by ordinary function. Now JSC returns ReferenceError but
     10        should return SyntaxError according to the following specs:
     11        http://www.ecma-international.org/ecma-262/6.0/#sec-function-definitions-static-semantics-early-errors
     12        and http://www.ecma-international.org/ecma-262/6.0/#sec-arrow-function-definitions-runtime-semantics-evaluation
     13        Curren patch implemented only one case when super/super() are used inside of the arrow function
     14        Case when super/super() are used within the eval:
     15           class A {}
     16           class B extends A {
     17               costructor() { eval("super()");}
     18           }
     19        is not part of this patch and will be implemented in this issue https://bugs.webkit.org/show_bug.cgi?id=153864.
     20        The same for case when eval with super/super() is invoked in arrow function will be
     21        implemented in issue https://bugs.webkit.org/show_bug.cgi?id=153977.
     22 
     23        * parser/Parser.cpp:
     24        (JSC::Parser<LexerType>::parseFunctionInfo):
     25        * parser/Parser.h:
     26        (JSC::Scope::Scope):
     27        (JSC::Scope::setExpectedSuperBinding):
     28        (JSC::Scope::expectedSuperBinding):
     29        (JSC::Scope::setConstructorKind):
     30        (JSC::Scope::constructorKind):
     31        (JSC::Parser::closestParentNonArrowFunctionNonLexicalScope):
     32        * tests/stress/arrowfunction-lexical-bind-supercall-4.js:
     33        * tests/stress/arrowfunction-lexical-bind-superproperty.js:
     34
    1352016-02-08  Filip Pizlo  <fpizlo@apple.com>
    236
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r196258 r196261  
    19771977    }
    19781978
    1979     bool isClassConstructor = constructorKind != ConstructorKind::None;
    1980    
     1979    functionScope->setConstructorKind(constructorKind);
     1980    functionScope->setExpectedSuperBinding(expectedSuperBinding);
     1981
    19811982    functionInfo.bodyStartColumn = startColumn;
    19821983   
     
    20672068        semanticFailIfTrue(m_vm->propertyNames->eval == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
    20682069    }
    2069     if (functionScope->hasDirectSuper() && functionBodyType == StandardFunctionBodyBlock) {
    2070         semanticFailIfTrue(!isClassConstructor, "Cannot call super() outside of a class constructor");
    2071         semanticFailIfTrue(constructorKind != ConstructorKind::Derived, "Cannot call super() in a base class constructor");
    2072     }
    2073     if (functionScope->needsSuperBinding() && functionBodyType == StandardFunctionBodyBlock)
    2074         semanticFailIfTrue(expectedSuperBinding == SuperBinding::NotNeeded, "super can only be used in a method of a derived class");
     2070    // It unncecessary to check of using super during reparsing one more time. Also it can lead to syntax error
     2071    // in case of arrow function becuase during reparsing we don't know that parse arrow function
     2072    // inside of the constructor or method
     2073    if (!m_lexer->isReparsingFunction()) {
     2074        if (functionScope->hasDirectSuper()) {
     2075            ConstructorKind functionConstructorKind = functionBodyType == StandardFunctionBodyBlock
     2076                ? constructorKind
     2077                : closestParentNonArrowFunctionNonLexicalScope()->constructorKind();
     2078            semanticFailIfTrue(functionConstructorKind == ConstructorKind::None, "Cannot call super() outside of a class constructor");
     2079            semanticFailIfTrue(functionConstructorKind != ConstructorKind::Derived, "Cannot call super() in a base class constructor");
     2080        }
     2081        if (functionScope->needsSuperBinding()) {
     2082            SuperBinding functionSuperBinding = functionBodyType == StandardFunctionBodyBlock
     2083                ? expectedSuperBinding
     2084                : closestParentNonArrowFunctionNonLexicalScope()->expectedSuperBinding();
     2085            semanticFailIfTrue(functionSuperBinding == SuperBinding::NotNeeded, "super can only be used in a method of a derived class");
     2086        }
     2087    }
    20752088
    20762089    JSTokenLocation location = JSTokenLocation(m_token.m_location);
     
    20842097    // Cache the tokenizer state and the function scope the first time the function is parsed.
    20852098    // Any future reparsing can then skip the function.
    2086     static const int minimumFunctionLengthToCache = 16;
     2099    // For arrow function is 8 = x=>x + 4 symbols;
     2100    // For ordinary function is 16  = function(){} + 4 symbols
     2101    const int minimumFunctionLengthToCache = functionBodyType == StandardFunctionBodyBlock ? 16 : 8;
    20872102    std::unique_ptr<SourceProviderCacheItem> newInfo;
    20882103    int functionLength = functionInfo.endOffset - functionInfo.startOffset;
  • trunk/Source/JavaScriptCore/parser/Parser.h

    r195581 r196261  
    176176        , m_isValidStrictMode(true)
    177177        , m_hasArguments(false)
     178        , m_constructorKind(static_cast<unsigned>(ConstructorKind::None))
     179        , m_expectedSuperBinding(static_cast<unsigned>(SuperBinding::NotNeeded))
    178180        , m_loopDepth(0)
    179181        , m_switchDepth(0)
     
    198200        , m_isValidStrictMode(rhs.m_isValidStrictMode)
    199201        , m_hasArguments(rhs.m_hasArguments)
     202        , m_constructorKind(rhs.m_constructorKind)
     203        , m_expectedSuperBinding(rhs.m_expectedSuperBinding)
    200204        , m_loopDepth(rhs.m_loopDepth)
    201205        , m_switchDepth(rhs.m_switchDepth)
     
    459463    bool needsSuperBinding() { return m_needsSuperBinding; }
    460464    void setNeedsSuperBinding() { m_needsSuperBinding = true; }
     465   
     466    void setExpectedSuperBinding(SuperBinding superBinding) { m_expectedSuperBinding = static_cast<unsigned>(superBinding); }
     467    SuperBinding expectedSuperBinding() const { return static_cast<SuperBinding>(m_expectedSuperBinding); }
     468    void setConstructorKind(ConstructorKind constructorKind) { m_constructorKind = static_cast<unsigned>(constructorKind); }
     469    ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); }
    461470
    462471    void collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables)
     
    615624    bool m_isValidStrictMode : 1;
    616625    bool m_hasArguments : 1;
     626    unsigned m_constructorKind : 2;
     627    unsigned m_expectedSuperBinding : 2;
    617628    int m_loopDepth;
    618629    int m_switchDepth;
     
    867878    }
    868879
     880    ScopeRef closestParentNonArrowFunctionNonLexicalScope()
     881    {
     882        unsigned i = m_scopeStack.size() - 1;
     883        ASSERT(i < m_scopeStack.size() && m_scopeStack.size());
     884        while (i && (!m_scopeStack[i].isFunctionBoundary() || m_scopeStack[i].isArrowFunction()))
     885            i--;
     886        // When reaching the top level scope (it can be non function scope), we return it.
     887        return ScopeRef(&m_scopeStack, i);
     888    }
    869889   
    870890    ScopeRef pushScope()
  • trunk/Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-supercall-4.js

    r193766 r196261  
    5252};
    5353
     54// FIXME: Arrow function does not support using of eval with super/super()
     55// https://bugs.webkit.org/show_bug.cgi?id=153977
     56/*
    5457for (var i=0; i < 1000; i++) {
    5558    new B(true);
     
    6164    testCase(e.id, 'new-value', 'Error during set value in eval #3');
    6265}
     66*/
    6367
    6468var testException = function (value, index) {
  • trunk/Source/JavaScriptCore/tests/stress/arrowfunction-lexical-bind-superproperty.js

    r194449 r196261  
    124124         return super.getValue();
    125125     }
    126      getParentValueWithError() {
    127          var f =  function () {
    128              return () => super.getValue();
    129          };
    130          return f();
    131      }
    132126 };
    133127
     
    149143    testCase(getValue(), 'new-value', 'Error: Some problem with using arrow and "super" inside of the method that retun arrow function');
    150144}
    151 
    152 var g2 = new G();
    153 for (var i = 0; i < 10000; i++) {
    154     let error = false;
    155     try {
    156        g2.getParentValueWithError()();
    157     } catch(e) {
    158       // FIXME: should by check if e instanceof SyntaxError
    159       // https://bugs.webkit.org/show_bug.cgi?id=150893
    160       error = true;
    161     }
    162     testCase(error, true, 'Error: using "super" should lead to error');
    163 }
    164 
    165145
    166146var H = class H extends A {
Note: See TracChangeset for help on using the changeset viewer.