https://bugs.webkit.org/show_bug.cgi?id=142566
Reviewed by Michael Saboff.
Source/JavaScriptCore:
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):
LayoutTests:
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.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@181490
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2015-03-13 Ryosuke Niwa <rniwa@webkit.org>
+
+ 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 <d_russell@apple.com>
AX: Provide API for assistive tech to ignore DOM key event handlers
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 ]
--- /dev/null
+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
+
--- /dev/null
+<!DOCTYPE html>
+<html>
+<body>
+<script src="../resources/js-test-pre.js"></script>
+<script src="script-tests/class-syntax-call.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
--- /dev/null
+//@ 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;
+2015-03-13 Ryosuke Niwa <rniwa@webkit.org>
+
+ 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 <fpizlo@apple.com>
DFG::PutStackSinkingPhase should eliminate GetStacks that have an obviously known source
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())
, 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())
, m_features(0)
, m_functionMode(node->functionMode())
{
+ ASSERT(m_constructorKind == static_cast<unsigned>(node->constructorKind()));
}
size_t UnlinkedFunctionExecutable::parameterCount() const
, 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)
, m_bytecodeCommentIterator(0)
#endif
{
-
+ ASSERT(m_constructorKind == static_cast<unsigned>(info.constructorKind()));
}
void UnlinkedCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
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 {
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; }
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;
bool isBuiltinFunction() const { return m_isBuiltinFunction; }
- bool constructorKindIsDerived() const { return m_constructorKindIsDerived; }
+ ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); }
void shrinkToFit()
{
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;
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();
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);
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();
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();
RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- if (generator.constructorKindIsDerived())
+ if (generator.constructorKind() == ConstructorKind::Derived)
generator.emitTDZCheck(generator.thisRegister());
if (dst == generator.ignoredResult())
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);
, 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)
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;
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 {
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();
}
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;
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;
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);
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(), "'");
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);
}
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)
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 };
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 };
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(); }
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;