Diff
Modified: trunk/LayoutTests/ChangeLog (181489 => 181490)
--- trunk/LayoutTests/ChangeLog 2015-03-13 22:30:36 UTC (rev 181489)
+++ trunk/LayoutTests/ChangeLog 2015-03-13 23:01:51 UTC (rev 181490)
@@ -1,3 +1,17 @@
+2015-03-13 Ryosuke Niwa <[email protected]>
+
+ Class constructor should throw TypeError when "called"
+ https://bugs.webkit.org/show_bug.cgi?id=142566
+
+ Reviewed by Michael Saboff.
+
+ Added tests for calling class constructors.
+
+ * TestExpectations: Skipped the test since ES6 class syntax isn't enabled by default.
+ * js/class-syntax-call-expected.txt: Added.
+ * js/class-syntax-call.html: Added.
+ * js/script-tests/class-syntax-call.js: Added.
+
2015-03-13 Doug Russell <[email protected]>
AX: Provide API for assistive tech to ignore DOM key event handlers
Modified: trunk/LayoutTests/TestExpectations (181489 => 181490)
--- trunk/LayoutTests/TestExpectations 2015-03-13 22:30:36 UTC (rev 181489)
+++ trunk/LayoutTests/TestExpectations 2015-03-13 23:01:51 UTC (rev 181490)
@@ -67,6 +67,7 @@
webkit.org/b/127860 [ Debug ] js/function-apply-aliased.html [ Skip ]
# ES6 class syntax hasn't been enabled yet.
+webkit.org/b/140491 js/class-syntax-call.html [ Failure ]
webkit.org/b/140491 js/class-syntax-declaration.html [ Failure ]
webkit.org/b/140491 js/class-syntax-_expression_.html [ Failure ]
webkit.org/b/140491 js/class-syntax-extends.html [ Failure ]
Added: trunk/LayoutTests/js/class-syntax-call-expected.txt (0 => 181490)
--- trunk/LayoutTests/js/class-syntax-call-expected.txt (rev 0)
+++ trunk/LayoutTests/js/class-syntax-call-expected.txt 2015-03-13 23:01:51 UTC (rev 181490)
@@ -0,0 +1,12 @@
+PASS class A { constructor() {} }; window.A = A; new A did not throw exception.
+PASS A() threw exception TypeError: Cannot call a class constructor.
+PASS class B extends A { constructor() { super() } }; window.B = B; new A did not throw exception.
+PASS B() threw exception TypeError: Cannot call a class constructor.
+PASS new (class { constructor() {} })() did not throw exception.
+PASS (class { constructor() {} })() threw exception TypeError: Cannot call a class constructor.
+PASS new (class extends null { constructor() { super() } })() did not throw exception.
+PASS (class extends null { constructor() { super() } })() threw exception TypeError: Cannot call a class constructor.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/class-syntax-call.html (0 => 181490)
--- trunk/LayoutTests/js/class-syntax-call.html (rev 0)
+++ trunk/LayoutTests/js/class-syntax-call.html 2015-03-13 23:01:51 UTC (rev 181490)
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/script-tests/class-syntax-call.js (0 => 181490)
--- trunk/LayoutTests/js/script-tests/class-syntax-call.js (rev 0)
+++ trunk/LayoutTests/js/script-tests/class-syntax-call.js 2015-03-13 23:01:51 UTC (rev 181490)
@@ -0,0 +1,12 @@
+//@ skip
+
+shouldNotThrow('class A { constructor() {} }; window.A = A; new A');
+shouldThrow('A()', '"TypeError: Cannot call a class constructor"');
+shouldNotThrow('class B extends A { constructor() { super() } }; window.B = B; new A');
+shouldThrow('B()', '"TypeError: Cannot call a class constructor"');
+shouldNotThrow('new (class { constructor() {} })()');
+shouldThrow('(class { constructor() {} })()', '"TypeError: Cannot call a class constructor"');
+shouldNotThrow('new (class extends null { constructor() { super() } })()');
+shouldThrow('(class extends null { constructor() { super() } })()', '"TypeError: Cannot call a class constructor"');
+
+var successfullyParsed = true;
Modified: trunk/Source/_javascript_Core/ChangeLog (181489 => 181490)
--- trunk/Source/_javascript_Core/ChangeLog 2015-03-13 22:30:36 UTC (rev 181489)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-03-13 23:01:51 UTC (rev 181490)
@@ -1,3 +1,63 @@
+2015-03-13 Ryosuke Niwa <[email protected]>
+
+ Class constructor should throw TypeError when "called"
+ https://bugs.webkit.org/show_bug.cgi?id=142566
+
+ Reviewed by Michael Saboff.
+
+ Added ConstructorKind::None to denote code that doesn't belong to an ES6 class.
+ This allows BytecodeGenerator to emit code to throw TypeError when generating code block
+ to call ES6 class constructors.
+
+ Most of changes are about increasing the number of bits to store ConstructorKind from one
+ bit to two bits.
+
+ * bytecode/UnlinkedCodeBlock.cpp:
+ (JSC::generateFunctionCodeBlock):
+ (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
+ (JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
+ * bytecode/UnlinkedCodeBlock.h:
+ (JSC::ExecutableInfo::ExecutableInfo):
+ (JSC::ExecutableInfo::needsActivation):
+ (JSC::ExecutableInfo::usesEval):
+ (JSC::ExecutableInfo::isStrictMode):
+ (JSC::ExecutableInfo::isConstructor):
+ (JSC::ExecutableInfo::isBuiltinFunction):
+ (JSC::ExecutableInfo::constructorKind):
+ (JSC::UnlinkedFunctionExecutable::constructorKind):
+ (JSC::UnlinkedCodeBlock::constructorKind):
+ (JSC::UnlinkedFunctionExecutable::constructorKindIsDerived): Deleted.
+ (JSC::UnlinkedCodeBlock::constructorKindIsDerived): Deleted.
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::generate): Don't emit bytecode when we had already emitted code
+ to throw TypeError.
+ (JSC::BytecodeGenerator::BytecodeGenerator): Emit code to throw TypeError when generating
+ code to call.
+ (JSC::BytecodeGenerator::emitReturn):
+ * bytecompiler/BytecodeGenerator.h:
+ (JSC::BytecodeGenerator::constructorKind):
+ (JSC::BytecodeGenerator::constructorKindIsDerived): Deleted.
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::ThisNode::emitBytecode):
+ (JSC::FunctionCallValueNode::emitBytecode):
+ * parser/Nodes.cpp:
+ (JSC::FunctionBodyNode::FunctionBodyNode):
+ * parser/Nodes.h:
+ * parser/Parser.cpp:
+ (JSC::Parser<LexerType>::parseFunctionInfo): Renamed the incoming function argument to
+ ownerClassKind. Set constructorKind to Base or Derived only if we're parsing a constructor.
+ (JSC::Parser<LexerType>::parseFunctionDeclaration):
+ (JSC::Parser<LexerType>::parseClass): Don't parse static methods using MethodMode since that
+ would result in BytecodeGenerator erroneously treating static method named "constructor" as
+ a class constructor.
+ (JSC::Parser<LexerType>::parsePropertyMethod):
+ (JSC::Parser<LexerType>::parsePrimaryExpression):
+ * parser/Parser.h:
+ * parser/ParserModes.h:
+ * runtime/Executable.h:
+ (JSC::EvalExecutable::executableInfo):
+ (JSC::ProgramExecutable::executableInfo):
+
2015-03-13 Filip Pizlo <[email protected]>
DFG::PutStackSinkingPhase should eliminate GetStacks that have an obviously known source
Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp (181489 => 181490)
--- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp 2015-03-13 22:30:36 UTC (rev 181489)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp 2015-03-13 23:01:51 UTC (rev 181490)
@@ -62,7 +62,7 @@
executable->recordParse(function->features(), function->hasCapturedVariables());
UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&vm, FunctionCode,
- ExecutableInfo(function->needsActivation(), function->usesEval(), function->isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction, executable->constructorKindIsDerived()));
+ ExecutableInfo(function->needsActivation(), function->usesEval(), function->isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction, executable->constructorKind()));
auto generator(std::make_unique<BytecodeGenerator>(vm, function.get(), result, debuggerMode, profilerMode));
error = generator->generate();
if (error.isValid())
@@ -85,7 +85,7 @@
, m_isInStrictContext(node->isInStrictContext())
, m_hasCapturedVariables(false)
, m_isBuiltinFunction(kind == UnlinkedBuiltinFunction)
- , m_constructorKindIsDerived(node->constructorKindIsDerived())
+ , m_constructorKind(static_cast<unsigned>(node->constructorKind()))
, m_name(node->ident())
, m_inferredName(node->inferredName())
, m_parameters(node->parameters())
@@ -101,6 +101,7 @@
, m_features(0)
, m_functionMode(node->functionMode())
{
+ ASSERT(m_constructorKind == static_cast<unsigned>(node->constructorKind()));
}
size_t UnlinkedFunctionExecutable::parameterCount() const
@@ -224,14 +225,14 @@
, m_vm(vm)
, m_argumentsRegister(VirtualRegister())
, m_globalObjectRegister(VirtualRegister())
- , m_needsFullScopeChain(info.m_needsActivation)
- , m_usesEval(info.m_usesEval)
+ , m_needsFullScopeChain(info.needsActivation())
+ , m_usesEval(info.usesEval())
, m_isNumericCompareFunction(false)
- , m_isStrictMode(info.m_isStrictMode)
- , m_isConstructor(info.m_isConstructor)
+ , m_isStrictMode(info.isStrictMode())
+ , m_isConstructor(info.isConstructor())
, m_hasCapturedVariables(false)
- , m_isBuiltinFunction(info.m_isBuiltinFunction)
- , m_constructorKindIsDerived(info.m_constructorKindIsDerived)
+ , m_isBuiltinFunction(info.isBuiltinFunction())
+ , m_constructorKind(static_cast<unsigned>(info.constructorKind()))
, m_firstLine(0)
, m_lineCount(0)
, m_endColumn(UINT_MAX)
@@ -246,7 +247,7 @@
, m_bytecodeCommentIterator(0)
#endif
{
-
+ ASSERT(m_constructorKind == static_cast<unsigned>(info.constructorKind()));
}
void UnlinkedCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h (181489 => 181490)
--- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h 2015-03-13 22:30:36 UTC (rev 181489)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h 2015-03-13 23:01:51 UTC (rev 181490)
@@ -65,21 +65,31 @@
typedef unsigned UnlinkedLLIntCallLinkInfo;
struct ExecutableInfo {
- ExecutableInfo(bool needsActivation, bool usesEval, bool isStrictMode, bool isConstructor, bool isBuiltinFunction, bool constructorKindIsDerived)
+ ExecutableInfo(bool needsActivation, bool usesEval, bool isStrictMode, bool isConstructor, bool isBuiltinFunction, ConstructorKind constructorKind)
: m_needsActivation(needsActivation)
, m_usesEval(usesEval)
, m_isStrictMode(isStrictMode)
, m_isConstructor(isConstructor)
, m_isBuiltinFunction(isBuiltinFunction)
- , m_constructorKindIsDerived(constructorKindIsDerived)
+ , m_constructorKind(static_cast<unsigned>(constructorKind))
{
+ ASSERT(m_constructorKind == static_cast<unsigned>(constructorKind));
}
- bool m_needsActivation : 1;
- bool m_usesEval : 1;
- bool m_isStrictMode : 1;
- bool m_isConstructor : 1;
- bool m_isBuiltinFunction : 1;
- bool m_constructorKindIsDerived : 1;
+
+ bool needsActivation() const { return m_needsActivation; }
+ bool usesEval() const { return m_usesEval; }
+ bool isStrictMode() const { return m_isStrictMode; }
+ bool isConstructor() const { return m_isConstructor; }
+ bool isBuiltinFunction() const { return m_isBuiltinFunction; }
+ ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); }
+
+private:
+ unsigned m_needsActivation : 1;
+ unsigned m_usesEval : 1;
+ unsigned m_isStrictMode : 1;
+ unsigned m_isConstructor : 1;
+ unsigned m_isBuiltinFunction : 1;
+ unsigned m_constructorKind : 2;
};
enum UnlinkedFunctionKind {
@@ -118,7 +128,7 @@
return JSParseStrict;
return JSParseNormal;
}
- bool constructorKindIsDerived() const { return m_constructorKindIsDerived; }
+ ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); }
unsigned unlinkedFunctionNameStart() const { return m_unlinkedFunctionNameStart; }
unsigned unlinkedBodyStartColumn() const { return m_unlinkedBodyStartColumn; }
@@ -167,10 +177,10 @@
WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForCall;
WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForConstruct;
- bool m_isInStrictContext : 1;
- bool m_hasCapturedVariables : 1;
- bool m_isBuiltinFunction : 1;
- bool m_constructorKindIsDerived : 1;
+ unsigned m_isInStrictContext : 1;
+ unsigned m_hasCapturedVariables : 1;
+ unsigned m_isBuiltinFunction : 1;
+ unsigned m_constructorKind : 2;
Identifier m_name;
Identifier m_inferredName;
@@ -346,7 +356,7 @@
bool isBuiltinFunction() const { return m_isBuiltinFunction; }
- bool constructorKindIsDerived() const { return m_constructorKindIsDerived; }
+ ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); }
void shrinkToFit()
{
@@ -532,14 +542,15 @@
VirtualRegister m_lexicalEnvironmentRegister;
VirtualRegister m_globalObjectRegister;
- bool m_needsFullScopeChain : 1;
- bool m_usesEval : 1;
- bool m_isNumericCompareFunction : 1;
- bool m_isStrictMode : 1;
- bool m_isConstructor : 1;
- bool m_hasCapturedVariables : 1;
- bool m_isBuiltinFunction : 1;
- bool m_constructorKindIsDerived : 1;
+ unsigned m_needsFullScopeChain : 1;
+ unsigned m_usesEval : 1;
+ unsigned m_isNumericCompareFunction : 1;
+ unsigned m_isStrictMode : 1;
+ unsigned m_isConstructor : 1;
+ unsigned m_hasCapturedVariables : 1;
+ unsigned m_isBuiltinFunction : 1;
+ unsigned m_constructorKind : 2;
+
unsigned m_firstLine;
unsigned m_lineCount;
unsigned m_endColumn;
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (181489 => 181490)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2015-03-13 22:30:36 UTC (rev 181489)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2015-03-13 23:01:51 UTC (rev 181490)
@@ -68,7 +68,9 @@
entry.second->bindValue(*this, entry.first.get());
}
- m_scopeNode->emitBytecode(*this);
+ bool callingClassConstructor = constructorKind() != ConstructorKind::None && !isConstructor();
+ if (!callingClassConstructor)
+ m_scopeNode->emitBytecode(*this);
m_staticPropertyAnalyzer.kill();
@@ -401,12 +403,14 @@
addCallee(functionNode, calleeRegister);
if (isConstructor()) {
- if (constructorKindIsDerived()) {
+ if (constructorKind() == ConstructorKind::Derived) {
m_newTargetRegister = addVar();
emitMove(m_newTargetRegister, &m_thisRegister);
emitMove(&m_thisRegister, addConstantEmptyValue());
} else
emitCreateThis(&m_thisRegister);
+ } else if (constructorKind() != ConstructorKind::None) {
+ emitThrowTypeError("Cannot call a class constructor");
} else if (functionNode->usesThis() || codeBlock->usesEval()) {
m_codeBlock->addPropertyAccessInstruction(instructions().size());
emitOpcode(op_to_this);
@@ -1912,7 +1916,7 @@
instructions().append(m_lexicalEnvironmentRegister ? m_lexicalEnvironmentRegister->index() : emitLoad(0, JSValue())->index());
}
- bool thisMightBeUninitialized = constructorKindIsDerived();
+ bool thisMightBeUninitialized = constructorKind() == ConstructorKind::Derived;
bool srcIsThis = src->index() == m_thisRegister.index();
if (isConstructor() && (!srcIsThis || thisMightBeUninitialized)) {
RefPtr<Label> isObjectOrUndefinedLabel = newLabel();
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (181489 => 181490)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2015-03-13 22:30:36 UTC (rev 181489)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2015-03-13 23:01:51 UTC (rev 181490)
@@ -271,9 +271,9 @@
bool isConstructor() const { return m_codeBlock->isConstructor(); }
#if ENABLE(ES6_CLASS_SYNTAX)
- bool constructorKindIsDerived() const { return m_codeBlock->constructorKindIsDerived(); }
+ ConstructorKind constructorKind() const { return m_codeBlock->constructorKind(); }
#else
- bool constructorKindIsDerived() const { return false; }
+ ConstructorKind constructorKind() const { return ConstructorKind::None; }
#endif
ParserError generate();
Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (181489 => 181490)
--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2015-03-13 22:30:36 UTC (rev 181489)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2015-03-13 23:01:51 UTC (rev 181490)
@@ -144,7 +144,7 @@
RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- if (generator.constructorKindIsDerived())
+ if (generator.constructorKind() == ConstructorKind::Derived)
generator.emitTDZCheck(generator.thisRegister());
if (dst == generator.ignoredResult())
@@ -574,7 +574,8 @@
RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
CallArguments callArguments(generator, m_args);
if (m_expr->isSuperNode()) {
- ASSERT(generator.constructorKindIsDerived());
+ ASSERT(generator.isConstructor());
+ ASSERT(generator.constructorKind() == ConstructorKind::Derived);
generator.emitMove(callArguments.thisRegister(), generator.newTarget());
RegisterID* ret = generator.emitConstruct(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
generator.emitMove(generator.thisRegister(), ret);
Modified: trunk/Source/_javascript_Core/parser/Nodes.cpp (181489 => 181490)
--- trunk/Source/_javascript_Core/parser/Nodes.cpp 2015-03-13 22:30:36 UTC (rev 181489)
+++ trunk/Source/_javascript_Core/parser/Nodes.cpp 2015-03-13 23:01:51 UTC (rev 181490)
@@ -173,8 +173,9 @@
, m_endColumn(endColumn)
, m_startStartOffset(startLocation.startOffset)
, m_isInStrictContext(isInStrictContext)
- , m_constructorKindIsDerived(constructorKind == ConstructorKind::Derived)
+ , m_constructorKind(static_cast<unsigned>(constructorKind))
{
+ ASSERT(m_constructorKind == static_cast<unsigned>(constructorKind));
}
void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter, const Identifier& ident, enum FunctionMode functionMode)
Modified: trunk/Source/_javascript_Core/parser/Nodes.h (181489 => 181490)
--- trunk/Source/_javascript_Core/parser/Nodes.h 2015-03-13 22:30:36 UTC (rev 181489)
+++ trunk/Source/_javascript_Core/parser/Nodes.h 2015-03-13 23:01:51 UTC (rev 181490)
@@ -1587,7 +1587,7 @@
int startStartOffset() const { return m_startStartOffset; }
bool isInStrictContext() const { return m_isInStrictContext; }
- bool constructorKindIsDerived() { return m_constructorKindIsDerived; }
+ ConstructorKind constructorKind() { return static_cast<ConstructorKind>(m_constructorKind); }
protected:
Identifier m_ident;
@@ -1600,8 +1600,8 @@
unsigned m_endColumn;
SourceCode m_source;
int m_startStartOffset;
- bool m_isInStrictContext : 1;
- bool m_constructorKindIsDerived : 1;
+ unsigned m_isInStrictContext : 1;
+ unsigned m_constructorKind : 2;
};
class FunctionNode final : public ScopeNode {
Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (181489 => 181490)
--- trunk/Source/_javascript_Core/parser/Parser.cpp 2015-03-13 22:30:36 UTC (rev 181489)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp 2015-03-13 23:01:51 UTC (rev 181490)
@@ -1291,7 +1291,7 @@
template <typename LexerType>
template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionRequirements requirements, FunctionParseMode mode,
- bool nameIsInContainingScope, ConstructorKind constructorKind, ParserFunctionInfo<TreeBuilder>& info)
+ bool nameIsInContainingScope, ConstructorKind ownerClassKind, ParserFunctionInfo<TreeBuilder>& info)
{
AutoPopScopeRef functionScope(this, pushScope());
functionScope->setIsFunction();
@@ -1321,7 +1321,12 @@
}
consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body");
-
+
+ // BytecodeGenerator emits code to throw TypeError when a class constructor is "call"ed.
+ // Set ConstructorKind to None for non-constructor methods of classes.
+ bool isClassConstructor = mode == MethodMode && info.name && *info.name == m_vm->propertyNames->constructor;
+ ConstructorKind constructorKind = isClassConstructor ? ownerClassKind : ConstructorKind::None;
+
info.openBraceOffset = m_token.m_data.offset;
info.bodyStartLine = tokenLine();
info.bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset;
@@ -1377,12 +1382,11 @@
semanticFailIfTrue(m_vm->propertyNames->eval == *info.name, "'", info.name->impl(), "' is not a valid function name in strict mode");
}
if (functionScope->hasDirectSuper()) {
- bool isClassConstructor = mode == MethodMode && info.name && *info.name == m_vm->propertyNames->constructor;
semanticFailIfTrue(!isClassConstructor, "Cannot call super() outside of a class constructor");
- semanticFailIfTrue(constructorKind == ConstructorKind::Base, "Cannot call super() in a base class constructor");
+ semanticFailIfTrue(ownerClassKind != ConstructorKind::Derived, "Cannot call super() in a base class constructor");
}
if (functionScope->needsSuperBinding())
- semanticFailIfTrue(constructorKind == ConstructorKind::Base, "super can only be used in a method of a derived class");
+ semanticFailIfTrue(ownerClassKind != ConstructorKind::Derived, "super can only be used in a method of a derived class");
info.closeBraceOffset = m_token.m_data.offset;
unsigned closeBraceLine = m_token.m_data.line;
@@ -1424,7 +1428,7 @@
unsigned functionKeywordStart = tokenStart();
next();
ParserFunctionInfo<TreeBuilder> info;
- failIfFalse((parseFunctionInfo(context, FunctionNeedsName, FunctionMode, true, ConstructorKind::Base, info)), "Cannot parse this function");
+ failIfFalse((parseFunctionInfo(context, FunctionNeedsName, FunctionMode, true, ConstructorKind::None, info)), "Cannot parse this function");
failIfFalse(info.name, "Function statements must have a name");
failIfFalseIfStrict(declareVariable(info.name), "Cannot declare a function named '", info.name->impl(), "' in strict mode");
return context.createFuncDeclStatement(location, info, functionKeywordStart);
@@ -1512,7 +1516,7 @@
failIfFalse(property, "Cannot parse this method");
} else {
ParserFunctionInfo<TreeBuilder> methodInfo;
- failIfFalse((parseFunctionInfo(context, FunctionNeedsName, MethodMode, false, constructorKind, methodInfo)), "Cannot parse this method");
+ failIfFalse((parseFunctionInfo(context, FunctionNeedsName, isStaticMethod ? FunctionMode : MethodMode, false, constructorKind, methodInfo)), "Cannot parse this method");
failIfFalse(methodInfo.name, "method must have a name");
failIfFalse(declareVariable(methodInfo.name), "Cannot declare a method named '", methodInfo.name->impl(), "'");
@@ -2017,7 +2021,7 @@
JSTokenLocation methodLocation(tokenLocation());
unsigned methodStart = tokenStart();
ParserFunctionInfo<TreeBuilder> methodInfo;
- failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, MethodMode, false, ConstructorKind::Base, methodInfo)), "Cannot parse this method");
+ failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, MethodMode, false, ConstructorKind::None, methodInfo)), "Cannot parse this method");
methodInfo.name = methodName;
return context.createFunctionExpr(methodLocation, methodInfo, methodStart);
}
@@ -2231,7 +2235,7 @@
next();
ParserFunctionInfo<TreeBuilder> info;
info.name = &m_vm->propertyNames->nullIdentifier;
- failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, false, ConstructorKind::Base, info)), "Cannot parse function _expression_");
+ failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, false, ConstructorKind::None, info)), "Cannot parse function _expression_");
return context.createFunctionExpr(location, info, functionKeywordStart);
}
#if ENABLE(ES6_CLASS_SYNTAX)
Modified: trunk/Source/_javascript_Core/parser/Parser.h (181489 => 181490)
--- trunk/Source/_javascript_Core/parser/Parser.h 2015-03-13 22:30:36 UTC (rev 181489)
+++ trunk/Source/_javascript_Core/parser/Parser.h 2015-03-13 23:01:51 UTC (rev 181490)
@@ -758,7 +758,7 @@
template <class TreeBuilder> ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&, SpreadMode);
template <class TreeBuilder> TreeProperty parseProperty(TreeBuilder&, bool strict);
template <class TreeBuilder> TreeExpression parsePropertyMethod(TreeBuilder& context, const Identifier* methodName);
- template <class TreeBuilder> TreeProperty parseGetterSetter(TreeBuilder&, bool strict, PropertyNode::Type, unsigned getterOrSetterStartOffset, ConstructorKind = ConstructorKind::Base, SuperBinding = SuperBinding::NotNeeded);
+ template <class TreeBuilder> TreeProperty parseGetterSetter(TreeBuilder&, bool strict, PropertyNode::Type, unsigned getterOrSetterStartOffset, ConstructorKind = ConstructorKind::None, SuperBinding = SuperBinding::NotNeeded);
template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&, ConstructorKind);
template <class TreeBuilder> ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&);
enum VarDeclarationListContext { ForLoopContext, VarDeclarationContext };
Modified: trunk/Source/_javascript_Core/parser/ParserModes.h (181489 => 181490)
--- trunk/Source/_javascript_Core/parser/ParserModes.h 2015-03-13 22:30:36 UTC (rev 181489)
+++ trunk/Source/_javascript_Core/parser/ParserModes.h 2015-03-13 23:01:51 UTC (rev 181490)
@@ -34,7 +34,7 @@
enum JSParserStrictness { JSParseNormal, JSParseBuiltin, JSParseStrict };
enum JSParserMode { JSParseProgramCode, JSParseFunctionCode };
-enum class ConstructorKind { Base, Derived };
+enum class ConstructorKind { None, Base, Derived };
enum class SuperBinding { Needed, NotNeeded };
enum ProfilerMode { ProfilerOff, ProfilerOn };
Modified: trunk/Source/_javascript_Core/runtime/Executable.h (181489 => 181490)
--- trunk/Source/_javascript_Core/runtime/Executable.h 2015-03-13 22:30:36 UTC (rev 181489)
+++ trunk/Source/_javascript_Core/runtime/Executable.h 2015-03-13 23:01:51 UTC (rev 181490)
@@ -467,7 +467,7 @@
void clearCode();
- ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, false); }
+ ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None); }
unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); }
unsigned numberOfFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); }
@@ -522,7 +522,7 @@
void clearCode();
- ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, false); }
+ ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None); }
private:
friend class ScriptExecutable;