Changeset 210958 in webkit


Ignore:
Timestamp:
Jan 20, 2017 3:43:24 AM (7 years ago)
Author:
gskachkov@gmail.com
Message:

Super property access in base class constructor doesn't work
https://bugs.webkit.org/show_bug.cgi?id=166665

Reviewed by Ryosuke Niwa.

Source/JavaScriptCore:

Allow to use super inside of the constructor for classes
without parent class.
Parser checks if super used within the constructor and
add this information to function metedata, and later it is used
during byte code generation.

  • bytecompiler/NodesCodegen.cpp:

(JSC::ClassExprNode::emitBytecode):

  • parser/Parser.cpp:

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

  • parser/Parser.h:

(JSC::Scope::usesEval):
(JSC::Scope::fillParametersForSourceProviderCache):
(JSC::Scope::restoreFromSourceProviderCache):
(JSC::Parser::adjustSuperBindingForBaseConstructor):

  • parser/SourceProviderCacheItem.h:

(JSC::SourceProviderCacheItem::SourceProviderCacheItem):

LayoutTests:

  • js/class-syntax-super-expected.txt:
  • js/script-tests/class-syntax-super.js:
Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r210951 r210958  
     12017-01-20  Skachkov Oleksandr  <gskachkov@gmail.com>
     2
     3        Super property access in base class constructor doesn't work
     4        https://bugs.webkit.org/show_bug.cgi?id=166665
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        * js/class-syntax-super-expected.txt:
     9        * js/script-tests/class-syntax-super.js:
     10
    1112017-01-19  Said Abou-Hallawa  <sabouhallawa@apple.com>
    212
  • trunk/LayoutTests/js/class-syntax-super-expected.txt

    r204058 r210958  
    2323PASS (new x).method1():::ReferenceError: Cannot delete a super property
    2424PASS (new x).method2():::ReferenceError: Cannot delete a super property
     25PASS (new (class { constructor() { super.property = "ABC"; } })).property === "ABC"
     26PASS (new (class extends Base { constructor() { super(); super.property = "ABC"; } })).property === "ABC"
     27PASS (new (class { constructor() { var arr = () => super.property = "ABC"; arr(); } })).property === "ABC"
     28PASS (new (class { constructor() { var async_arr = async () => super.property = "ABC"; async_arr(); } })).property === "ABC"
     29PASS (new (class { constructor() { eval('super.property = "ABC"'); } })).property === "ABC"
     30PASS (new (class { constructor() { var arr = () => eval('super.property = "ABC"'); arr(); } })).property === "ABC"
    2531PASS new (class { constructor() { return undefined; } }) instanceof Object
    2632PASS new (class { constructor() { return 1; } }) instanceof Object
  • trunk/LayoutTests/js/script-tests/class-syntax-super.js

    r204058 r210958  
    106106shouldThrow('(new x).method1()', '"ReferenceError: Cannot delete a super property"');
    107107shouldThrow('(new x).method2()', '"ReferenceError: Cannot delete a super property"');
     108shouldBeTrue('(new (class { constructor() { super.property = "ABC"; } })).property === "ABC"');
     109shouldBeTrue('(new (class extends Base { constructor() { super(); super.property = "ABC"; } })).property === "ABC"');
     110shouldBeTrue('(new (class { constructor() { var arr = () => super.property = "ABC"; arr(); } })).property === "ABC"');
     111shouldBeTrue('(new (class { constructor() { var async_arr = async () => super.property = "ABC"; async_arr(); } })).property === "ABC"');
     112shouldBeTrue('(new (class { constructor() { eval(\'super.property = "ABC"\'); } })).property === "ABC"');
     113shouldBeTrue('(new (class { constructor() { var arr = () => eval(\'super.property = "ABC"\'); arr(); } })).property === "ABC"');
    108114shouldBeTrue('new (class { constructor() { return undefined; } }) instanceof Object');
    109115shouldBeTrue('new (class { constructor() { return 1; } }) instanceof Object');
  • trunk/Source/JavaScriptCore/ChangeLog

    r210949 r210958  
     12017-01-20  Skachkov Oleksandr  <gskachkov@gmail.com>
     2
     3        Super property access in base class constructor doesn't work
     4        https://bugs.webkit.org/show_bug.cgi?id=166665
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        Allow to use super inside of the constructor for classes
     9        without parent class.
     10        Parser checks if super used within the constructor and
     11        add this information to function metedata, and later it is used
     12        during byte code generation.
     13
     14        * bytecompiler/NodesCodegen.cpp:
     15        (JSC::ClassExprNode::emitBytecode):
     16        * parser/Parser.cpp:
     17        (JSC::Parser<LexerType>::parseFunctionBody):
     18        (JSC::Parser<LexerType>::parseFunctionInfo):
     19        * parser/Parser.h:
     20        (JSC::Scope::usesEval):
     21        (JSC::Scope::fillParametersForSourceProviderCache):
     22        (JSC::Scope::restoreFromSourceProviderCache):
     23        (JSC::Parser::adjustSuperBindingForBaseConstructor):
     24        * parser/SourceProviderCacheItem.h:
     25        (JSC::SourceProviderCacheItem::SourceProviderCacheItem):
     26
    1272017-01-19  Chris Dumez  <cdumez@apple.com>
    228
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r210925 r210958  
    36823682
    36833683    RefPtr<RegisterID> constructor;
     3684    bool needsHomeObject = false;
    36843685
    36853686    // FIXME: Make the prototype non-configurable & non-writable.
     
    36913692        constructor = generator.emitNode(dst, m_constructorExpression);
    36923693        if (m_classHeritage) {
     3694            needsHomeObject = true;
    36933695            RefPtr<RegisterID> isDerivedConstructor = generator.newTemporary();
    36943696            generator.emitUnaryOp(op_not, isDerivedConstructor.get(),
    36953697                generator.emitUnaryOp(op_eq_null, isDerivedConstructor.get(), superclass.get()));
    36963698            generator.emitDirectPutById(constructor.get(), generator.propertyNames().builtinNames().isDerivedConstructorPrivateName(), isDerivedConstructor.get(), PropertyNode::Unknown);
    3697         }
     3699        } else if (metadata->superBinding() == SuperBinding::Needed)
     3700            needsHomeObject = true;
    36983701    } else {
    36993702        if (m_classHeritage) {
     
    37503753        generator.emitLabel(superclassIsNullLabel.get());
    37513754        generator.emitDirectPutById(prototype.get(), generator.propertyNames().underscoreProto, protoParent.get(), PropertyNode::Unknown);
    3752 
     3755    }
     3756
     3757    if (needsHomeObject)
    37533758        emitPutHomeObject(generator, constructor.get(), prototype.get());
    3754     }
    37553759
    37563760    RefPtr<RegisterID> constructorNameRegister = generator.emitLoad(nullptr, propertyNames.constructor);
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r210535 r210958  
    18641864        if (match(CLOSEBRACE)) {
    18651865            unsigned endColumn = tokenColumn();
    1866             return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, superBinding, parameterCount, functionLength, parseMode, isArrowFunctionBodyExpression);
     1866            SuperBinding functionSuperBinding = adjustSuperBindingForBaseConstructor(constructorKind, superBinding, currentScope());
     1867            return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, functionSuperBinding, parameterCount, functionLength, parseMode, isArrowFunctionBodyExpression);
    18671868        }
    18681869    }
     
    18821883    }
    18831884    unsigned endColumn = tokenColumn();
    1884     return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, superBinding, parameterCount, functionLength, parseMode, isArrowFunctionBodyExpression);
     1885    SuperBinding functionSuperBinding = adjustSuperBindingForBaseConstructor(constructorKind, superBinding, currentScope());
     1886    return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, functionSuperBinding, parameterCount, functionLength, parseMode, isArrowFunctionBodyExpression);
    18851887}
    18861888
     
    20822084            else
    20832085                functionBodyType = StandardFunctionBodyBlock;
    2084            
     2086
     2087            SuperBinding functionSuperBinding = adjustSuperBindingForBaseConstructor(constructorKind, expectedSuperBinding, cachedInfo->needsSuperBinding, cachedInfo->usesEval, cachedInfo->innerArrowFunctionFeatures);
     2088
    20852089            functionInfo.body = context.createFunctionMetadata(
    20862090                startLocation, endLocation, startColumn, bodyEndColumn,
    20872091                functionKeywordStart, functionNameStart, parametersStart,
    2088                 cachedInfo->strictMode, constructorKind, expectedSuperBinding,
     2092                cachedInfo->strictMode, constructorKind, functionSuperBinding,
    20892093                cachedInfo->parameterCount, cachedInfo->functionLength,
    20902094                mode, functionBodyType == ArrowFunctionBodyExpression);
  • trunk/Source/JavaScriptCore/parser/Parser.h

    r210151 r210958  
    315315    }
    316316    bool isLexicalScope() { return m_isLexicalScope; }
     317    bool usesEval() { return m_usesEval; }
    317318
    318319    const HashSet<UniquedStringImpl*>& closedVariableCandidates() const { return m_closedVariableCandidates; }
     
    684685        parameters.needsFullActivation = m_needsFullActivation;
    685686        parameters.innerArrowFunctionFeatures = m_innerArrowFunctionFeatures;
     687        parameters.needsSuperBinding = m_needsSuperBinding;
    686688        for (const UniquedStringImplPtrSet& set : m_usedVariables)
    687689            copyCapturedVariablesToVector(set, parameters.usedVariables);
     
    707709        m_innerArrowFunctionFeatures = info->innerArrowFunctionFeatures;
    708710        m_needsFullActivation = info->needsFullActivation;
     711        m_needsSuperBinding = info->needsSuperBinding;
    709712        UniquedStringImplPtrSet& destSet = m_usedVariables.last();
    710713        for (unsigned i = 0; i < info->usedVariablesCount; ++i)
     
    15991602        return token.m_type == AWAIT && (!m_parserState.allowAwait || currentScope()->isAsyncFunctionBoundary() || m_scriptMode == JSParserScriptMode::Module);
    16001603    }
     1604   
     1605    ALWAYS_INLINE SuperBinding adjustSuperBindingForBaseConstructor(ConstructorKind constructorKind, SuperBinding superBinding, ScopeRef functionScope)
     1606    {
     1607        return adjustSuperBindingForBaseConstructor(constructorKind, superBinding, functionScope->needsSuperBinding(), functionScope->usesEval(), functionScope->innerArrowFunctionFeatures());
     1608    }
     1609   
     1610    ALWAYS_INLINE SuperBinding adjustSuperBindingForBaseConstructor(ConstructorKind constructorKind, SuperBinding superBinding, bool scopeNeedsSuperBinding, bool currentScopeUsesEval, InnerArrowFunctionCodeFeatures innerArrowFunctionFeatures)
     1611    {
     1612        SuperBinding methodSuperBinding = superBinding;
     1613       
     1614        if (constructorKind == ConstructorKind::Base) {
     1615            bool isSuperUsedInInnerArrowFunction = innerArrowFunctionFeatures & SuperPropertyInnerArrowFunctionFeature;
     1616            methodSuperBinding = (scopeNeedsSuperBinding || isSuperUsedInInnerArrowFunction || currentScopeUsesEval) ? SuperBinding::Needed : SuperBinding::NotNeeded;
     1617        }
     1618       
     1619        return methodSuperBinding;
     1620    }
    16011621
    16021622    const char* disallowedIdentifierAwaitReason()
  • trunk/Source/JavaScriptCore/parser/SourceProviderCacheItem.h

    r206525 r210958  
    4545    bool usesEval;
    4646    bool strictMode;
     47    bool needsSuperBinding;
    4748    InnerArrowFunctionCodeFeatures innerArrowFunctionFeatures;
    4849    Vector<UniquedStringImpl*, 8> usedVariables;
     
    8990    unsigned parameterCount : 31;
    9091    unsigned expectedSuperBinding : 1; // SuperBinding
     92    bool needsSuperBinding: 1;
    9193    unsigned functionLength;
    9294    unsigned lastTokenLineStartOffset;
     
    130132    , parameterCount(parameters.parameterCount)
    131133    , expectedSuperBinding(static_cast<unsigned>(parameters.expectedSuperBinding))
     134    , needsSuperBinding(parameters.needsSuperBinding)
    132135    , functionLength(parameters.functionLength)
    133136    , lastTokenLineStartOffset(parameters.lastTokenLineStartOffset)
Note: See TracChangeset for help on using the changeset viewer.