Diff
Modified: trunk/JSTests/ChangeLog (229607 => 229608)
--- trunk/JSTests/ChangeLog 2018-03-14 19:54:28 UTC (rev 229607)
+++ trunk/JSTests/ChangeLog 2018-03-14 20:00:21 UTC (rev 229608)
@@ -1,3 +1,23 @@
+2018-03-14 Caitlin Potter <ca...@igalia.com>
+
+ [JSC] fix order of evaluation for ClassDefinitionEvaluation
+ https://bugs.webkit.org/show_bug.cgi?id=183523
+
+ Reviewed by Keith Miller.
+
+ Computed property names need to be evaluated in source order during class
+ definition evaluation, as it's observable (and specified to work this way).
+
+ This change improves compatibility with Chromium.
+
+ * stress/class_elements.js: Added.
+ (test):
+ (test.C.prototype.effect):
+ (test.C.effect):
+ (test.C.prototype.get effect):
+ (test.C.prototype.set effect):
+ (test.C):
+
2018-03-11 Yusuke Suzuki <utatane....@gmail.com>
[DFG] AI should convert CreateThis to NewObject if the prototype object is proved
Added: trunk/JSTests/stress/class_elements.js (0 => 229608)
--- trunk/JSTests/stress/class_elements.js (rev 0)
+++ trunk/JSTests/stress/class_elements.js 2018-03-14 20:00:21 UTC (rev 229608)
@@ -0,0 +1,24 @@
+function test() {
+
+let log = [];
+function effect(desc) { log.push(desc); return desc; }
+
+class C {
+ [effect("instance#1")]() {}
+ static [effect("static#2")]() {}
+ get [effect("instanceGetter#3")]() {}
+ static get [effect("staticGetter#4")]() {}
+ set [effect("instanceSetter#5")](v) {}
+ static [effect("staticSetter#6")](v) {}
+}
+
+return log[0] === "instance#1" &&
+ log[1] === "static#2" &&
+ log[2] === "instanceGetter#3" &&
+ log[3] === "staticGetter#4" &&
+ log[4] === "instanceSetter#5" &&
+ log[5] === "staticSetter#6";
+}
+
+if (!test())
+ throw new Error("Test failed");
\ No newline at end of file
Modified: trunk/Source/_javascript_Core/ChangeLog (229607 => 229608)
--- trunk/Source/_javascript_Core/ChangeLog 2018-03-14 19:54:28 UTC (rev 229607)
+++ trunk/Source/_javascript_Core/ChangeLog 2018-03-14 20:00:21 UTC (rev 229608)
@@ -1,3 +1,43 @@
+2018-03-14 Caitlin Potter <ca...@igalia.com>
+
+ [JSC] fix order of evaluation for ClassDefinitionEvaluation
+ https://bugs.webkit.org/show_bug.cgi?id=183523
+
+ Reviewed by Keith Miller.
+
+ Computed property names need to be evaluated in source order during class
+ definition evaluation, as it's observable (and specified to work this way).
+
+ This change improves compatibility with Chromium.
+
+ * bytecompiler/BytecodeGenerator.h:
+ (JSC::BytecodeGenerator::emitDefineClassElements):
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::PropertyListNode::emitBytecode):
+ (JSC::ClassExprNode::emitBytecode):
+ * parser/ASTBuilder.h:
+ (JSC::ASTBuilder::createClassExpr):
+ (JSC::ASTBuilder::createGetterOrSetterProperty):
+ (JSC::ASTBuilder::createProperty):
+ * parser/NodeConstructors.h:
+ (JSC::PropertyNode::PropertyNode):
+ (JSC::ClassExprNode::ClassExprNode):
+ * parser/Nodes.cpp:
+ (JSC::PropertyListNode::hasStaticallyNamedProperty):
+ * parser/Nodes.h:
+ (JSC::PropertyNode::isClassProperty const):
+ (JSC::PropertyNode::isStaticClassProperty const):
+ (JSC::PropertyNode::isInstanceClassProperty const):
+ * parser/Parser.cpp:
+ (JSC::Parser<LexerType>::parseClass):
+ (JSC::Parser<LexerType>::parseProperty):
+ (JSC::Parser<LexerType>::parseGetterSetter):
+ * parser/Parser.h:
+ * parser/SyntaxChecker.h:
+ (JSC::SyntaxChecker::createClassExpr):
+ (JSC::SyntaxChecker::createProperty):
+ (JSC::SyntaxChecker::createGetterOrSetterProperty):
+
2018-03-14 Keith Miller <keith_mil...@apple.com>
Move jsc CLI breakpoint function to $vm
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (229607 => 229608)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2018-03-14 19:54:28 UTC (rev 229607)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2018-03-14 20:00:21 UTC (rev 229608)
@@ -521,6 +521,16 @@
return emitNodeInTailPosition(nullptr, n);
}
+ RegisterID* emitDefineClassElements(PropertyListNode* n, RegisterID* constructor, RegisterID* prototype)
+ {
+ ASSERT(constructor->refCount() && prototype->refCount());
+ if (UNLIKELY(!m_vm->isSafeToRecurse()))
+ return emitThrowExpressionTooDeepException();
+ if (UNLIKELY(n->needsDebugHook()))
+ emitDebugHook(n);
+ return n->emitBytecode(*this, constructor, prototype);
+ }
+
RegisterID* emitNodeForProperty(RegisterID* dst, ExpressionNode* node)
{
if (node->isString()) {
Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (229607 => 229608)
--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2018-03-14 19:54:28 UTC (rev 229607)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2018-03-14 20:00:21 UTC (rev 229608)
@@ -508,12 +508,15 @@
generator.emitPutById(function, generator.propertyNames().builtinNames().homeObjectPrivateName(), homeObject);
}
-RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dstOrConstructor, RegisterID* prototype)
{
// Fast case: this loop just handles regular value properties.
PropertyListNode* p = this;
- for (; p && (p->m_node->m_type & PropertyNode::Constant); p = p->m_next)
+ RegisterID* dst = nullptr;
+ for (; p && (p->m_node->m_type & PropertyNode::Constant); p = p->m_next) {
+ dst = p->m_node->isInstanceClassProperty() ? prototype : dstOrConstructor;
emitPutConstantProperty(generator, dst, *p->m_node);
+ }
// Were there any get/set properties?
if (p) {
@@ -523,7 +526,8 @@
typedef std::pair<PropertyNode*, PropertyNode*> GetterSetterPair;
typedef HashMap<UniquedStringImpl*, GetterSetterPair, IdentifierRepHash> GetterSetterMap;
- GetterSetterMap map;
+ GetterSetterMap instanceMap;
+ GetterSetterMap staticMap;
// Build a map, pairing get/set values together.
for (PropertyListNode* q = p; q; q = q->m_next) {
@@ -538,6 +542,7 @@
// Duplicates are possible.
GetterSetterPair pair(node, static_cast<PropertyNode*>(nullptr));
+ GetterSetterMap& map = node->isStaticClassProperty() ? staticMap : instanceMap;
GetterSetterMap::AddResult result = map.add(node->name()->impl(), pair);
auto& resultPair = result.iterator->value;
if (!result.isNewEntry) {
@@ -555,6 +560,7 @@
// Iterate over the remaining properties in the list.
for (; p; p = p->m_next) {
PropertyNode* node = p->m_node;
+ dst = node->isInstanceClassProperty() ? prototype : dstOrConstructor;
// Handle regular values.
if (node->m_type & PropertyNode::Constant) {
@@ -595,6 +601,7 @@
}
// This is a get/set property pair.
+ GetterSetterMap& map = node->isStaticClassProperty() ? staticMap : instanceMap;
GetterSetterMap::iterator it = map.find(node->name()->impl());
ASSERT(it != map.end());
GetterSetterPair& pair = it->value;
@@ -639,7 +646,7 @@
}
}
- return dst;
+ return dstOrConstructor;
}
void PropertyListNode::emitPutConstantProperty(BytecodeGenerator& generator, RegisterID* newObj, PropertyNode& node)
@@ -3951,12 +3958,9 @@
RefPtr<RegisterID> prototypeNameRegister = generator.emitLoad(nullptr, propertyNames.prototype);
generator.emitCallDefineProperty(constructor.get(), prototypeNameRegister.get(), prototype.get(), nullptr, nullptr, 0, m_position);
- if (m_staticMethods)
- generator.emitNode(constructor.get(), m_staticMethods);
+ if (m_classElements)
+ generator.emitDefineClassElements(m_classElements, constructor.get(), prototype.get());
- if (m_instanceMethods)
- generator.emitNode(prototype.get(), m_instanceMethods);
-
if (!m_name.isNull()) {
Variable classNameVar = generator.variable(m_name);
RELEASE_ASSERT(classNameVar.isResolved());
Modified: trunk/Source/_javascript_Core/parser/ASTBuilder.h (229607 => 229608)
--- trunk/Source/_javascript_Core/parser/ASTBuilder.h 2018-03-14 19:54:28 UTC (rev 229607)
+++ trunk/Source/_javascript_Core/parser/ASTBuilder.h 2018-03-14 20:00:21 UTC (rev 229608)
@@ -397,10 +397,10 @@
}
ClassExprNode* createClassExpr(const JSTokenLocation& location, const ParserClassInfo<ASTBuilder>& classInfo, VariableEnvironment& classEnvironment, ExpressionNode* constructor,
- ExpressionNode* parentClass, PropertyListNode* instanceMethods, PropertyListNode* staticMethods)
+ ExpressionNode* parentClass, PropertyListNode* classElements)
{
SourceCode source = m_sourceCode->subExpression(classInfo.startOffset, classInfo.endOffset, classInfo.startLine, classInfo.startColumn);
- return new (m_parserArena) ClassExprNode(location, *classInfo.className, source, classEnvironment, constructor, parentClass, instanceMethods, staticMethods);
+ return new (m_parserArena) ClassExprNode(location, *classInfo.className, source, classEnvironment, constructor, parentClass, classElements);
}
ExpressionNode* createFunctionExpr(const JSTokenLocation& location, const ParserFunctionInfo<ASTBuilder>& functionInfo)
@@ -470,7 +470,7 @@
ArgumentListNode* createArgumentsList(const JSTokenLocation& location, ArgumentListNode* args, ExpressionNode* arg) { return new (m_parserArena) ArgumentListNode(location, args, arg); }
NEVER_INLINE PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type, bool,
- const Identifier* name, const ParserFunctionInfo<ASTBuilder>& functionInfo, bool isClassProperty)
+ const Identifier* name, const ParserFunctionInfo<ASTBuilder>& functionInfo, ClassElementTag tag)
{
ASSERT(name);
functionInfo.body->setLoc(functionInfo.startLine, functionInfo.endLine, location.startOffset, location.lineStartOffset);
@@ -478,30 +478,30 @@
functionInfo.body->setInferredName(*name);
SourceCode source = m_sourceCode->subExpression(functionInfo.startOffset, functionInfo.endOffset, functionInfo.startLine, functionInfo.parametersStartColumn);
MethodDefinitionNode* methodDef = new (m_parserArena) MethodDefinitionNode(location, m_vm->propertyNames->nullIdentifier, functionInfo.body, source);
- return new (m_parserArena) PropertyNode(*name, methodDef, type, PropertyNode::Unknown, SuperBinding::Needed, isClassProperty);
+ return new (m_parserArena) PropertyNode(*name, methodDef, type, PropertyNode::Unknown, SuperBinding::Needed, tag);
}
NEVER_INLINE PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type, bool,
- ExpressionNode* name, const ParserFunctionInfo<ASTBuilder>& functionInfo, bool isClassProperty)
+ ExpressionNode* name, const ParserFunctionInfo<ASTBuilder>& functionInfo, ClassElementTag tag)
{
ASSERT(name);
functionInfo.body->setLoc(functionInfo.startLine, functionInfo.endLine, location.startOffset, location.lineStartOffset);
SourceCode source = m_sourceCode->subExpression(functionInfo.startOffset, functionInfo.endOffset, functionInfo.startLine, functionInfo.parametersStartColumn);
MethodDefinitionNode* methodDef = new (m_parserArena) MethodDefinitionNode(location, m_vm->propertyNames->nullIdentifier, functionInfo.body, source);
- return new (m_parserArena) PropertyNode(name, methodDef, type, PropertyNode::Unknown, SuperBinding::Needed, isClassProperty);
+ return new (m_parserArena) PropertyNode(name, methodDef, type, PropertyNode::Unknown, SuperBinding::Needed, tag);
}
NEVER_INLINE PropertyNode* createGetterOrSetterProperty(VM* vm, ParserArena& parserArena, const JSTokenLocation& location, PropertyNode::Type type, bool,
- double name, const ParserFunctionInfo<ASTBuilder>& functionInfo, bool isClassProperty)
+ double name, const ParserFunctionInfo<ASTBuilder>& functionInfo, ClassElementTag tag)
{
functionInfo.body->setLoc(functionInfo.startLine, functionInfo.endLine, location.startOffset, location.lineStartOffset);
const Identifier& ident = parserArena.identifierArena().makeNumericIdentifier(vm, name);
SourceCode source = m_sourceCode->subExpression(functionInfo.startOffset, functionInfo.endOffset, functionInfo.startLine, functionInfo.parametersStartColumn);
MethodDefinitionNode* methodDef = new (m_parserArena) MethodDefinitionNode(location, vm->propertyNames->nullIdentifier, functionInfo.body, source);
- return new (m_parserArena) PropertyNode(ident, methodDef, type, PropertyNode::Unknown, SuperBinding::Needed, isClassProperty);
+ return new (m_parserArena) PropertyNode(ident, methodDef, type, PropertyNode::Unknown, SuperBinding::Needed, tag);
}
- PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, InferName inferName, bool isClassProperty)
+ PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, InferName inferName, ClassElementTag tag)
{
if (inferName == InferName::Allowed) {
if (node->isBaseFuncExprNode()) {
@@ -511,17 +511,17 @@
} else if (node->isClassExprNode())
static_cast<ClassExprNode*>(node)->setEcmaName(*propertyName);
}
- return new (m_parserArena) PropertyNode(*propertyName, node, type, putType, superBinding, isClassProperty);
+ return new (m_parserArena) PropertyNode(*propertyName, node, type, putType, superBinding, tag);
}
- PropertyNode* createProperty(ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, bool isClassProperty)
+ PropertyNode* createProperty(ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, ClassElementTag tag)
{
- return new (m_parserArena) PropertyNode(node, type, putType, superBinding, isClassProperty);
+ return new (m_parserArena) PropertyNode(node, type, putType, superBinding, tag);
}
- PropertyNode* createProperty(VM* vm, ParserArena& parserArena, double propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, bool isClassProperty)
+ PropertyNode* createProperty(VM* vm, ParserArena& parserArena, double propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, ClassElementTag tag)
{
- return new (m_parserArena) PropertyNode(parserArena.identifierArena().makeNumericIdentifier(vm, propertyName), node, type, putType, superBinding, isClassProperty);
+ return new (m_parserArena) PropertyNode(parserArena.identifierArena().makeNumericIdentifier(vm, propertyName), node, type, putType, superBinding, tag);
}
- PropertyNode* createProperty(ExpressionNode* propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, bool isClassProperty) { return new (m_parserArena) PropertyNode(propertyName, node, type, putType, superBinding, isClassProperty); }
+ PropertyNode* createProperty(ExpressionNode* propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, ClassElementTag tag) { return new (m_parserArena) PropertyNode(propertyName, node, type, putType, superBinding, tag); }
PropertyListNode* createPropertyList(const JSTokenLocation& location, PropertyNode* property) { return new (m_parserArena) PropertyListNode(location, property); }
PropertyListNode* createPropertyList(const JSTokenLocation& location, PropertyNode* property, PropertyListNode* tail) { return new (m_parserArena) PropertyListNode(location, property, tail); }
Modified: trunk/Source/_javascript_Core/parser/NodeConstructors.h (229607 => 229608)
--- trunk/Source/_javascript_Core/parser/NodeConstructors.h 2018-03-14 19:54:28 UTC (rev 229607)
+++ trunk/Source/_javascript_Core/parser/NodeConstructors.h 2018-03-14 20:00:21 UTC (rev 229608)
@@ -242,29 +242,29 @@
{
}
- inline PropertyNode::PropertyNode(const Identifier& name, ExpressionNode* assign, Type type, PutType putType, SuperBinding superBinding, bool isClassProperty)
+ inline PropertyNode::PropertyNode(const Identifier& name, ExpressionNode* assign, Type type, PutType putType, SuperBinding superBinding, ClassElementTag tag)
: m_name(&name)
, m_assign(assign)
, m_type(type)
, m_needsSuperBinding(superBinding == SuperBinding::Needed)
, m_putType(putType)
- , m_isClassProperty(isClassProperty)
+ , m_classElementTag(static_cast<unsigned>(tag))
, m_isOverriddenByDuplicate(false)
{
}
- inline PropertyNode::PropertyNode(ExpressionNode* assign, Type type, PutType putType, SuperBinding superBinding, bool isClassProperty)
+ inline PropertyNode::PropertyNode(ExpressionNode* assign, Type type, PutType putType, SuperBinding superBinding, ClassElementTag tag)
: m_name(nullptr)
, m_assign(assign)
, m_type(type)
, m_needsSuperBinding(superBinding == SuperBinding::Needed)
, m_putType(putType)
- , m_isClassProperty(isClassProperty)
+ , m_classElementTag(static_cast<unsigned>(tag))
, m_isOverriddenByDuplicate(false)
{
}
- inline PropertyNode::PropertyNode(ExpressionNode* name, ExpressionNode* assign, Type type, PutType putType, SuperBinding superBinding, bool isClassProperty)
+ inline PropertyNode::PropertyNode(ExpressionNode* name, ExpressionNode* assign, Type type, PutType putType, SuperBinding superBinding, ClassElementTag tag)
: m_name(nullptr)
, m_expression(name)
, m_assign(assign)
@@ -271,7 +271,7 @@
, m_type(type)
, m_needsSuperBinding(superBinding == SuperBinding::Needed)
, m_putType(putType)
- , m_isClassProperty(isClassProperty)
+ , m_classElementTag(static_cast<unsigned>(tag))
, m_isOverriddenByDuplicate(false)
{
}
@@ -993,7 +993,7 @@
{
}
- inline ClassExprNode::ClassExprNode(const JSTokenLocation& location, const Identifier& name, const SourceCode& classSource, VariableEnvironment& classEnvironment, ExpressionNode* constructorExpression, ExpressionNode* classHeritage, PropertyListNode* instanceMethods, PropertyListNode* staticMethods)
+ inline ClassExprNode::ClassExprNode(const JSTokenLocation& location, const Identifier& name, const SourceCode& classSource, VariableEnvironment& classEnvironment, ExpressionNode* constructorExpression, ExpressionNode* classHeritage, PropertyListNode* classElements)
: ExpressionNode(location)
, VariableEnvironmentNode(classEnvironment)
, m_classSource(classSource)
@@ -1001,8 +1001,7 @@
, m_ecmaName(&name)
, m_constructorExpression(constructorExpression)
, m_classHeritage(classHeritage)
- , m_instanceMethods(instanceMethods)
- , m_staticMethods(staticMethods)
+ , m_classElements(classElements)
{
}
Modified: trunk/Source/_javascript_Core/parser/Nodes.cpp (229607 => 229608)
--- trunk/Source/_javascript_Core/parser/Nodes.cpp 2018-03-14 19:54:28 UTC (rev 229607)
+++ trunk/Source/_javascript_Core/parser/Nodes.cpp 2018-03-14 20:00:21 UTC (rev 229608)
@@ -248,9 +248,11 @@
{
PropertyListNode* list = this;
while (list) {
- const Identifier* currentNodeName = list->m_node->name();
- if (currentNodeName && *currentNodeName == propName)
- return true;
+ if (list->m_node->isStaticClassProperty()) {
+ const Identifier* currentNodeName = list->m_node->name();
+ if (currentNodeName && *currentNodeName == propName)
+ return true;
+ }
list = list->m_next;
}
return false;
Modified: trunk/Source/_javascript_Core/parser/Nodes.h (229607 => 229608)
--- trunk/Source/_javascript_Core/parser/Nodes.h 2018-03-14 19:54:28 UTC (rev 229607)
+++ trunk/Source/_javascript_Core/parser/Nodes.h 2018-03-14 20:00:21 UTC (rev 229608)
@@ -695,14 +695,15 @@
bool m_optional;
};
+ enum class ClassElementTag { No, Instance, Static, LastTag };
class PropertyNode : public ParserArenaFreeable {
public:
enum Type { Constant = 1, Getter = 2, Setter = 4, Computed = 8, Shorthand = 16, Spread = 32 };
enum PutType { Unknown, KnownDirect };
- PropertyNode(const Identifier&, ExpressionNode*, Type, PutType, SuperBinding, bool isClassProperty);
- PropertyNode(ExpressionNode*, Type, PutType, SuperBinding, bool isClassProperty);
- PropertyNode(ExpressionNode* propertyName, ExpressionNode*, Type, PutType, SuperBinding, bool isClassProperty);
+ PropertyNode(const Identifier&, ExpressionNode*, Type, PutType, SuperBinding, ClassElementTag);
+ PropertyNode(ExpressionNode*, Type, PutType, SuperBinding, ClassElementTag);
+ PropertyNode(ExpressionNode* propertyName, ExpressionNode*, Type, PutType, SuperBinding, ClassElementTag);
ExpressionNode* expressionName() const { return m_expression; }
const Identifier* name() const { return m_name; }
@@ -709,7 +710,9 @@
Type type() const { return static_cast<Type>(m_type); }
bool needsSuperBinding() const { return m_needsSuperBinding; }
- bool isClassProperty() const { return m_isClassProperty; }
+ bool isClassProperty() const { return static_cast<ClassElementTag>(m_classElementTag) != ClassElementTag::No; }
+ bool isStaticClassProperty() const { return static_cast<ClassElementTag>(m_classElementTag) == ClassElementTag::Static; }
+ bool isInstanceClassProperty() const { return static_cast<ClassElementTag>(m_classElementTag) == ClassElementTag::Instance; }
bool isOverriddenByDuplicate() const { return m_isOverriddenByDuplicate; }
void setIsOverriddenByDuplicate() { m_isOverriddenByDuplicate = true; }
PutType putType() const { return static_cast<PutType>(m_putType); }
@@ -722,7 +725,8 @@
unsigned m_type : 6;
unsigned m_needsSuperBinding : 1;
unsigned m_putType : 1;
- unsigned m_isClassProperty: 1;
+ static_assert(1 << 2 > static_cast<unsigned>(ClassElementTag::LastTag), "ClassElementTag shouldn't use more than two bits");
+ unsigned m_classElementTag : 2;
unsigned m_isOverriddenByDuplicate: 1;
};
@@ -733,8 +737,13 @@
bool hasStaticallyNamedProperty(const Identifier& propName);
+ RegisterID* emitBytecode(BytecodeGenerator&, RegisterID*, RegisterID*);
+
private:
- RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
+ RegisterID* emitBytecode(BytecodeGenerator& generator, RegisterID* dst = nullptr) override
+ {
+ return emitBytecode(generator, dst, nullptr);
+ }
void emitPutConstantProperty(BytecodeGenerator&, RegisterID*, PropertyNode&);
PropertyNode* m_node;
@@ -2139,13 +2148,13 @@
public:
ClassExprNode(const JSTokenLocation&, const Identifier&, const SourceCode& classSource,
VariableEnvironment& classEnvironment, ExpressionNode* constructorExpresssion,
- ExpressionNode* parentClass, PropertyListNode* instanceMethods, PropertyListNode* staticMethods);
+ ExpressionNode* parentClass, PropertyListNode* classElements);
const Identifier& name() { return m_name; }
const Identifier& ecmaName() { return m_ecmaName ? *m_ecmaName : m_name; }
void setEcmaName(const Identifier& name) { m_ecmaName = m_name.isNull() ? &name : &m_name; }
- bool hasStaticProperty(const Identifier& propName) { return m_staticMethods ? m_staticMethods->hasStaticallyNamedProperty(propName) : false; }
+ bool hasStaticProperty(const Identifier& propName) { return m_classElements ? m_classElements->hasStaticallyNamedProperty(propName) : false; }
private:
RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
@@ -2157,8 +2166,7 @@
const Identifier* m_ecmaName;
ExpressionNode* m_constructorExpression;
ExpressionNode* m_classHeritage;
- PropertyListNode* m_instanceMethods;
- PropertyListNode* m_staticMethods;
+ PropertyListNode* m_classElements;
};
class DestructuringPatternNode : public ParserArenaFreeable {
Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (229607 => 229608)
--- trunk/Source/_javascript_Core/parser/Parser.cpp 2018-03-14 19:54:28 UTC (rev 229607)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp 2018-03-14 20:00:21 UTC (rev 229608)
@@ -2795,10 +2795,8 @@
consumeOrFail(OPENBRACE, "Expected opening '{' at the start of a class body");
TreeExpression constructor = 0;
- TreePropertyList staticMethods = 0;
- TreePropertyList instanceMethods = 0;
- TreePropertyList instanceMethodsTail = 0;
- TreePropertyList staticMethodsTail = 0;
+ TreePropertyList classElements = 0;
+ TreePropertyList classElementsTail = 0;
while (!match(CLOSEBRACE)) {
if (match(SEMICOLON)) {
next();
@@ -2809,7 +2807,7 @@
unsigned methodStart = tokenStart();
// For backwards compatibility, "static" is a non-reserved keyword in non-strict mode.
- bool isStaticMethod = false;
+ ClassElementTag tag = ClassElementTag::Instance;
if (match(RESERVED_IF_STRICT) && *m_token.m_data.ident == m_vm->propertyNames->staticKeyword) {
SavePoint savePoint = createSavePoint();
next();
@@ -2817,7 +2815,7 @@
// Reparse "static()" as a method named "static".
restoreSavePoint(savePoint);
} else
- isStaticMethod = true;
+ tag = ClassElementTag::Static;
}
// FIXME: Figure out a way to share more code with parseProperty.
@@ -2883,13 +2881,12 @@
TreeProperty property;
const bool alwaysStrictInsideClass = true;
if (isGetter || isSetter) {
- bool isClassProperty = true;
property = parseGetterSetter(context, alwaysStrictInsideClass, isGetter ? PropertyNode::Getter : PropertyNode::Setter,
- methodStart, ConstructorKind::None, isClassProperty, isStaticMethod);
+ methodStart, ConstructorKind::None, tag);
failIfFalse(property, "Cannot parse this method");
} else {
ParserFunctionInfo<TreeBuilder> methodInfo;
- bool isConstructor = !isStaticMethod && *ident == propertyNames.constructor;
+ bool isConstructor = tag == ClassElementTag::Instance && *ident == propertyNames.constructor;
if (isAsyncMethodParseMode(parseMode) || isAsyncGeneratorMethodParseMode(parseMode) || isGeneratorMethodParseMode(parseMode)) {
isConstructor = false;
semanticFailIfTrue(*ident == m_vm->propertyNames->prototype, "Cannot declare ", stringArticleForFunctionMode(parseMode), stringForFunctionMode(parseMode), " named 'prototype'");
@@ -2907,35 +2904,28 @@
}
// FIXME: Syntax error when super() is called
- semanticFailIfTrue(isStaticMethod && methodInfo.name && *methodInfo.name == propertyNames.prototype,
+ semanticFailIfTrue(tag == ClassElementTag::Static && methodInfo.name && *methodInfo.name == propertyNames.prototype,
"Cannot declare a static method named 'prototype'");
- bool isClassProperty = true;
if (computedPropertyName) {
property = context.createProperty(computedPropertyName, method, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed),
- PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed, isClassProperty);
+ PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed, tag);
} else {
property = context.createProperty(methodInfo.name, method, PropertyNode::Constant,
- PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed, InferName::Allowed, isClassProperty);
+ PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed, InferName::Allowed, tag);
}
}
- TreePropertyList& tail = isStaticMethod ? staticMethodsTail : instanceMethodsTail;
- if (tail)
- tail = context.createPropertyList(methodLocation, property, tail);
- else {
- tail = context.createPropertyList(methodLocation, property);
- if (isStaticMethod)
- staticMethods = tail;
- else
- instanceMethods = tail;
- }
+ if (classElementsTail)
+ classElementsTail = context.createPropertyList(methodLocation, property, classElementsTail);
+ else
+ classElements = classElementsTail = context.createPropertyList(methodLocation, property);
}
info.endOffset = tokenLocation().endOffset - 1;
consumeOrFail(CLOSEBRACE, "Expected a closing '}' after a class body");
- auto classExpression = context.createClassExpr(location, info, classScope->finalizeLexicalEnvironment(), constructor, parentClass, instanceMethods, staticMethods);
+ auto classExpression = context.createClassExpr(location, info, classScope->finalizeLexicalEnvironment(), constructor, parentClass, classElements);
popScope(classScope, TreeBuilder::NeedsFreeVariableInfo);
return classExpression;
}
@@ -3898,8 +3888,6 @@
{
SourceParseMode parseMode = SourceParseMode::MethodMode;
bool wasIdent = false;
- bool isClassProperty = false;
- bool isStaticMethod = false;
if (consume(TIMES))
parseMode = SourceParseMode::GeneratorWrapperMethodMode;
@@ -3948,13 +3936,13 @@
failIfFalse(node, "Cannot parse _expression_ for property declaration");
context.setEndOffset(node, m_lexer->currentOffset());
InferName inferName = ident && *ident == m_vm->propertyNames->underscoreProto ? InferName::Disallowed : InferName::Allowed;
- return context.createProperty(ident, node, PropertyNode::Constant, PropertyNode::Unknown, complete, SuperBinding::NotNeeded, inferName, isClassProperty);
+ return context.createProperty(ident, node, PropertyNode::Constant, PropertyNode::Unknown, complete, SuperBinding::NotNeeded, inferName, ClassElementTag::No);
}
if (match(OPENPAREN)) {
auto method = parsePropertyMethod(context, ident, parseMode);
propagateError();
- return context.createProperty(ident, method, PropertyNode::Constant, PropertyNode::KnownDirect, complete, SuperBinding::Needed, InferName::Allowed, isClassProperty);
+ return context.createProperty(ident, method, PropertyNode::Constant, PropertyNode::KnownDirect, complete, SuperBinding::Needed, InferName::Allowed, ClassElementTag::No);
}
failIfTrue(parseMode != SourceParseMode::MethodMode, "Expected a parenthesis for argument list");
@@ -3968,7 +3956,7 @@
if (currentScope()->isArrowFunction())
currentScope()->setInnerArrowFunctionUsesEval();
TreeExpression node = context.createResolve(location, *ident, start, lastTokenEndPosition());
- return context.createProperty(ident, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Shorthand), PropertyNode::KnownDirect, complete, SuperBinding::NotNeeded, InferName::Allowed, isClassProperty);
+ return context.createProperty(ident, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Shorthand), PropertyNode::KnownDirect, complete, SuperBinding::NotNeeded, InferName::Allowed, ClassElementTag::No);
}
if (match(EQUAL)) // CoverInitializedName is exclusive to BindingPattern and AssignmentPattern
@@ -3981,7 +3969,7 @@
type = PropertyNode::Setter;
else
failWithMessage("Expected a ':' following the property name '", ident->impl(), "'");
- return parseGetterSetter(context, complete, type, getterOrSetterStartOffset, ConstructorKind::None, isClassProperty, isStaticMethod);
+ return parseGetterSetter(context, complete, type, getterOrSetterStartOffset, ConstructorKind::None, ClassElementTag::No);
}
case DOUBLE:
case INTEGER: {
@@ -3992,7 +3980,7 @@
const Identifier& ident = m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), propertyName);
auto method = parsePropertyMethod(context, &ident, parseMode);
propagateError();
- return context.createProperty(&ident, method, PropertyNode::Constant, PropertyNode::Unknown, complete, SuperBinding::Needed, InferName::Allowed, isClassProperty);
+ return context.createProperty(&ident, method, PropertyNode::Constant, PropertyNode::Unknown, complete, SuperBinding::Needed, InferName::Allowed, ClassElementTag::No);
}
failIfTrue(parseMode != SourceParseMode::MethodMode, "Expected a parenthesis for argument list");
@@ -4000,7 +3988,7 @@
TreeExpression node = parseAssignmentExpression(context);
failIfFalse(node, "Cannot parse _expression_ for property declaration");
context.setEndOffset(node, m_lexer->currentOffset());
- return context.createProperty(const_cast<VM*>(m_vm), m_parserArena, propertyName, node, PropertyNode::Constant, PropertyNode::Unknown, complete, SuperBinding::NotNeeded, isClassProperty);
+ return context.createProperty(const_cast<VM*>(m_vm), m_parserArena, propertyName, node, PropertyNode::Constant, PropertyNode::Unknown, complete, SuperBinding::NotNeeded, ClassElementTag::No);
}
case OPENBRACKET: {
next();
@@ -4011,7 +3999,7 @@
if (match(OPENPAREN)) {
auto method = parsePropertyMethod(context, &m_vm->propertyNames->nullIdentifier, parseMode);
propagateError();
- return context.createProperty(propertyName, method, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::KnownDirect, complete, SuperBinding::Needed, isClassProperty);
+ return context.createProperty(propertyName, method, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::KnownDirect, complete, SuperBinding::Needed, ClassElementTag::No);
}
failIfTrue(parseMode != SourceParseMode::MethodMode, "Expected a parenthesis for argument list");
@@ -4019,7 +4007,7 @@
TreeExpression node = parseAssignmentExpression(context);
failIfFalse(node, "Cannot parse _expression_ for property declaration");
context.setEndOffset(node, m_lexer->currentOffset());
- return context.createProperty(propertyName, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::Unknown, complete, SuperBinding::NotNeeded, isClassProperty);
+ return context.createProperty(propertyName, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::Unknown, complete, SuperBinding::NotNeeded, ClassElementTag::No);
}
case DOTDOTDOT: {
if (m_useObjectRestSpread) {
@@ -4030,7 +4018,7 @@
TreeExpression elem = parseAssignmentExpressionOrPropagateErrorClass(context);
failIfFalse(elem, "Cannot parse subject of a spread operation");
auto node = context.createObjectSpreadExpression(spreadLocation, elem, start, divot, m_lastTokenEndPosition);
- return context.createProperty(node, PropertyNode::Spread, PropertyNode::Unknown, complete, SuperBinding::NotNeeded, isClassProperty);
+ return context.createProperty(node, PropertyNode::Spread, PropertyNode::Unknown, complete, SuperBinding::NotNeeded, ClassElementTag::No);
}
FALLTHROUGH;
}
@@ -4055,7 +4043,7 @@
template <typename LexerType>
template <class TreeBuilder> TreeProperty Parser<LexerType>::parseGetterSetter(TreeBuilder& context, bool strict, PropertyNode::Type type, unsigned getterOrSetterStartOffset,
- ConstructorKind constructorKind, bool isClassProperty, bool isStaticMethod)
+ ConstructorKind constructorKind, ClassElementTag tag)
{
const Identifier* stringPropertyName = 0;
double numericPropertyName = 0;
@@ -4065,9 +4053,9 @@
if (matchSpecIdentifier() || match(STRING) || m_token.m_type & KeywordTokenFlag) {
stringPropertyName = m_token.m_data.ident;
- semanticFailIfTrue(isClassProperty && isStaticMethod && *stringPropertyName == m_vm->propertyNames->prototype,
+ semanticFailIfTrue(tag == ClassElementTag::Static && *stringPropertyName == m_vm->propertyNames->prototype,
"Cannot declare a static method named 'prototype'");
- semanticFailIfTrue(isClassProperty && !isStaticMethod && *stringPropertyName == m_vm->propertyNames->constructor,
+ semanticFailIfTrue(tag == ClassElementTag::Instance && *stringPropertyName == m_vm->propertyNames->constructor,
"Cannot declare a getter or setter named 'constructor'");
next();
} else if (match(DOUBLE) || match(INTEGER)) {
@@ -4091,12 +4079,12 @@
}
if (stringPropertyName)
- return context.createGetterOrSetterProperty(location, type, strict, stringPropertyName, info, isClassProperty);
+ return context.createGetterOrSetterProperty(location, type, strict, stringPropertyName, info, tag);
if (computedPropertyName)
- return context.createGetterOrSetterProperty(location, static_cast<PropertyNode::Type>(type | PropertyNode::Computed), strict, computedPropertyName, info, isClassProperty);
+ return context.createGetterOrSetterProperty(location, static_cast<PropertyNode::Type>(type | PropertyNode::Computed), strict, computedPropertyName, info, tag);
- return context.createGetterOrSetterProperty(const_cast<VM*>(m_vm), m_parserArena, location, type, strict, numericPropertyName, info, isClassProperty);
+ return context.createGetterOrSetterProperty(const_cast<VM*>(m_vm), m_parserArena, location, type, strict, numericPropertyName, info, tag);
}
template <typename LexerType>
Modified: trunk/Source/_javascript_Core/parser/Parser.h (229607 => 229608)
--- trunk/Source/_javascript_Core/parser/Parser.h 2018-03-14 19:54:28 UTC (rev 229607)
+++ trunk/Source/_javascript_Core/parser/Parser.h 2018-03-14 20:00:21 UTC (rev 229608)
@@ -1570,7 +1570,7 @@
template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseArgument(TreeBuilder&, ArgumentType&);
template <class TreeBuilder> TreeProperty parseProperty(TreeBuilder&, bool strict);
template <class TreeBuilder> TreeExpression parsePropertyMethod(TreeBuilder& context, const Identifier* methodName, SourceParseMode);
- template <class TreeBuilder> TreeProperty parseGetterSetter(TreeBuilder&, bool strict, PropertyNode::Type, unsigned getterOrSetterStartOffset, ConstructorKind, bool isClassProperty, bool isStaticMethod);
+ template <class TreeBuilder> TreeProperty parseGetterSetter(TreeBuilder&, bool strict, PropertyNode::Type, unsigned getterOrSetterStartOffset, ConstructorKind, ClassElementTag);
template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&, SyntaxChecker&, const JSTokenLocation&, int, int functionKeywordStart, int functionNameStart, int parametersStart, ConstructorKind, SuperBinding, FunctionBodyType, unsigned, SourceParseMode);
template <class TreeBuilder> ALWAYS_INLINE bool parseFormalParameters(TreeBuilder&, TreeFormalParameterList, bool isArrowFunction, bool isMethod, unsigned&);
enum VarDeclarationListContext { ForLoopContext, VarDeclarationContext };
Modified: trunk/Source/_javascript_Core/parser/SyntaxChecker.h (229607 => 229608)
--- trunk/Source/_javascript_Core/parser/SyntaxChecker.h 2018-03-14 19:54:28 UTC (rev 229607)
+++ trunk/Source/_javascript_Core/parser/SyntaxChecker.h 2018-03-14 20:00:21 UTC (rev 229608)
@@ -191,7 +191,7 @@
ExpressionType createYield(const JSTokenLocation&) { return YieldExpr; }
ExpressionType createYield(const JSTokenLocation&, ExpressionType, bool, int, int, int) { return YieldExpr; }
ExpressionType createAwait(const JSTokenLocation&, ExpressionType, int, int, int) { return AwaitExpr; }
- ClassExpression createClassExpr(const JSTokenLocation&, const ParserClassInfo<SyntaxChecker>&, VariableEnvironment&, ExpressionType, ExpressionType, PropertyList, PropertyList) { return ClassExpr; }
+ ClassExpression createClassExpr(const JSTokenLocation&, const ParserClassInfo<SyntaxChecker>&, VariableEnvironment&, ExpressionType, ExpressionType, PropertyList) { return ClassExpr; }
ExpressionType createFunctionExpr(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }
ExpressionType createGeneratorFunctionBody(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&, const Identifier&) { return FunctionExpr; }
ExpressionType createAsyncFunctionBody(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }
@@ -214,7 +214,7 @@
int createArgumentsList(const JSTokenLocation&, int) { return ArgumentsListResult; }
int createArgumentsList(const JSTokenLocation&, int, int) { return ArgumentsListResult; }
- Property createProperty(const Identifier* name, int, PropertyNode::Type type, PropertyNode::PutType, bool complete, SuperBinding, InferName, bool)
+ Property createProperty(const Identifier* name, int, PropertyNode::Type type, PropertyNode::PutType, bool complete, SuperBinding, InferName, ClassElementTag)
{
if (!complete)
return Property(type);
@@ -221,17 +221,17 @@
ASSERT(name);
return Property(name, type);
}
- Property createProperty(int, PropertyNode::Type type, PropertyNode::PutType, bool, SuperBinding, bool)
+ Property createProperty(int, PropertyNode::Type type, PropertyNode::PutType, bool, SuperBinding, ClassElementTag)
{
return Property(type);
}
- Property createProperty(VM* vm, ParserArena& parserArena, double name, int, PropertyNode::Type type, PropertyNode::PutType, bool complete, SuperBinding, bool)
+ Property createProperty(VM* vm, ParserArena& parserArena, double name, int, PropertyNode::Type type, PropertyNode::PutType, bool complete, SuperBinding, ClassElementTag)
{
if (!complete)
return Property(type);
return Property(&parserArena.identifierArena().makeNumericIdentifier(vm, name), type);
}
- Property createProperty(int, int, PropertyNode::Type type, PropertyNode::PutType, bool, SuperBinding, bool)
+ Property createProperty(int, int, PropertyNode::Type type, PropertyNode::PutType, bool, SuperBinding, ClassElementTag)
{
return Property(type);
}
@@ -285,7 +285,7 @@
void appendExportSpecifier(ExportSpecifierList, ExportSpecifier) { }
int appendConstDecl(const JSTokenLocation&, int, const Identifier*, int) { return StatementResult; }
- Property createGetterOrSetterProperty(const JSTokenLocation&, PropertyNode::Type type, bool strict, const Identifier* name, const ParserFunctionInfo<SyntaxChecker>&, bool)
+ Property createGetterOrSetterProperty(const JSTokenLocation&, PropertyNode::Type type, bool strict, const Identifier* name, const ParserFunctionInfo<SyntaxChecker>&, ClassElementTag)
{
ASSERT(name);
if (!strict)
@@ -292,11 +292,11 @@
return Property(type);
return Property(name, type);
}
- Property createGetterOrSetterProperty(const JSTokenLocation&, PropertyNode::Type type, bool, int, const ParserFunctionInfo<SyntaxChecker>&, bool)
+ Property createGetterOrSetterProperty(const JSTokenLocation&, PropertyNode::Type type, bool, int, const ParserFunctionInfo<SyntaxChecker>&, ClassElementTag)
{
return Property(type);
}
- Property createGetterOrSetterProperty(VM* vm, ParserArena& parserArena, const JSTokenLocation&, PropertyNode::Type type, bool strict, double name, const ParserFunctionInfo<SyntaxChecker>&, bool)
+ Property createGetterOrSetterProperty(VM* vm, ParserArena& parserArena, const JSTokenLocation&, PropertyNode::Type type, bool strict, double name, const ParserFunctionInfo<SyntaxChecker>&, ClassElementTag)
{
if (!strict)
return Property(type);