Ignore:
Timestamp:
Apr 19, 2016, 1:47:44 AM (9 years ago)
Author:
[email protected]
Message:

calling super() a second time in a constructor should throw
https://bugs.webkit.org/show_bug.cgi?id=151113

Reviewed by Saam Barati and Keith Miller.

Source/JavaScriptCore:

Currently, our implementation checks if 'super()' was called in a constructor more
than once and raises a RuntimeError before the second call. According to the spec
we need to raise an error just after the second super() is finished and before
the new 'this' is assigned https://esdiscuss.org/topic/duplicate-super-call-behaviour.
To implement this behavior this patch adds a new op code, op_is_empty, that is used
to check if 'this' is empty.

  • bytecode/BytecodeList.json:
  • bytecode/BytecodeUseDef.h:

(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::dumpBytecode):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitIsEmpty):

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::FunctionCallValueNode::emitBytecode):

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGCapabilities.cpp:

(JSC::DFG::capabilityLevel):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGNodeType.h:
  • dfg/DFGPredictionPropagationPhase.cpp:

(JSC::DFG::PredictionPropagationPhase::propagate):

  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileIsEmpty):

  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):

  • jit/JIT.h:
  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_is_empty):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_is_empty):

  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • tests/stress/class-syntax-double-constructor.js: Added.

LayoutTests:

  • js/class-syntax-super-expected.txt:
  • js/script-tests/class-syntax-super.js:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r199699 r199712  
    759759        generator.emitMove(callArguments.thisRegister(), generator.newTarget());
    760760        RegisterID* ret = generator.emitConstruct(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
     761
     762        bool isConstructorKindDerived = generator.constructorKind() == ConstructorKind::Derived;
     763        bool doWeUseArrowFunctionInConstructor = isConstructorKindDerived && generator.needsToUpdateArrowFunctionContext();
     764
     765        if (generator.isDerivedConstructorContext() || (doWeUseArrowFunctionInConstructor && generator.isSuperCallUsedInInnerArrowFunction()))
     766            generator.emitLoadThisFromArrowFunctionLexicalEnvironment();
     767       
     768        RefPtr<Label> thisIsEmptyLabel = generator.newLabel();
     769        generator.emitJumpIfTrue(generator.emitIsEmpty(generator.newTemporary(), generator.thisRegister()), thisIsEmptyLabel.get());
     770        generator.emitThrowReferenceError(ASCIILiteral("'super()' can't be called more than once in a constructor."));
     771        generator.emitLabel(thisIsEmptyLabel.get());
     772
    761773        generator.emitMove(generator.thisRegister(), ret);
    762774       
    763         bool isConstructorKindDerived = generator.constructorKind() == ConstructorKind::Derived;
    764         if (generator.isDerivedConstructorContext() || (isConstructorKindDerived && generator.needsToUpdateArrowFunctionContext()))
     775        if (generator.isDerivedConstructorContext() || doWeUseArrowFunctionInConstructor)
    765776            generator.emitPutThisToArrowFunctionContextScope();
    766777       
Note: See TracChangeset for help on using the changeset viewer.