Diff
Modified: trunk/JSTests/ChangeLog (266116 => 266117)
--- trunk/JSTests/ChangeLog 2020-08-25 15:48:30 UTC (rev 266116)
+++ trunk/JSTests/ChangeLog 2020-08-25 15:58:40 UTC (rev 266117)
@@ -1,3 +1,12 @@
+2020-08-25 Alexey Shvayka <[email protected]>
+
+ Invalid early error for object literal method named "__proto__"
+ https://bugs.webkit.org/show_bug.cgi?id=215760
+
+ Reviewed by Ross Kirsling.
+
+ * test262/expectations.yaml: Mark 2 test cases as passing.
+
2020-08-25 Paulo Matos <[email protected]>
Skip failing tests on MIPS for later investigation
Modified: trunk/JSTests/test262/expectations.yaml (266116 => 266117)
--- trunk/JSTests/test262/expectations.yaml 2020-08-25 15:48:30 UTC (rev 266116)
+++ trunk/JSTests/test262/expectations.yaml 2020-08-25 15:58:40 UTC (rev 266117)
@@ -2382,9 +2382,6 @@
test/language/expressions/new/non-ctor-err-realm.js:
default: 'Test262Error: production including Arguments Expected a TypeError but got a TypeError'
strict mode: 'Test262Error: production including Arguments Expected a TypeError but got a TypeError'
-test/language/expressions/object/__proto__-permitted-dup.js:
- default: 'SyntaxError: Attempted to redefine __proto__ property.'
- strict mode: 'SyntaxError: Attempted to redefine __proto__ property.'
test/language/expressions/object/covered-ident-name-prop-name-literal-break-escaped.js:
default: "SyntaxError: Unexpected escaped characters in keyword token: 'bre\\u0061k'"
strict mode: "SyntaxError: Unexpected escaped characters in keyword token: 'bre\\u0061k'"
Modified: trunk/Source/_javascript_Core/ChangeLog (266116 => 266117)
--- trunk/Source/_javascript_Core/ChangeLog 2020-08-25 15:48:30 UTC (rev 266116)
+++ trunk/Source/_javascript_Core/ChangeLog 2020-08-25 15:58:40 UTC (rev 266117)
@@ -1,3 +1,53 @@
+2020-08-25 Alexey Shvayka <[email protected]>
+
+ Invalid early error for object literal method named "__proto__"
+ https://bugs.webkit.org/show_bug.cgi?id=215760
+
+ Reviewed by Ross Kirsling.
+
+ According to Annex B [1], `{ __proto__: null, __proto__() {} }` is a valid object literal as the second
+ `__proto__` wasn't obtained from `PropertyDefinition : PropertyName : AssignmentExpression` production.
+ Currently, JSC throws an early SyntaxError, unlike V8 and SpiderMonkey.
+
+ Since a method needs `super` binding, the most straightforward fix would be adding SuperBinding field
+ to SyntaxChecker::Property and exposing it via an accessor. However, given that Property is a very
+ common structure, this approach would noticeably increase memory pressure during parsing.
+
+ Instead, this patch reworks SyntaxChecker::Property to accept `isUnderscoreProtoSetter` parameter,
+ removing optional `name` field, its accessor, and shouldCheckPropertyForUnderscoreProtoDuplicate(),
+ which reduces sizeof(SyntaxChecker::Property) by a factor of 8: from 16 to 2 bytes.
+ Also, this change avoids two extra makeNumericIdentifier() calls, speeding up numeric keys parsing.
+
+ This approach is feasible because "__proto__" is the only identifier-based early error for object
+ literals [2], with no such errors being added in upcoming stage 2-4 proposals.
+
+ Additionally, this patch removes `strict` / `complete` bool parameter from {parse,create}Property()
+ signatures as a) it was always `true`, b) is now unused, and c) strict mode can be checked via scope.
+
+ [1]: https://tc39.es/ecma262/#sec-__proto__-property-names-in-object-initializers
+ [2]: https://tc39.es/ecma262/#sec-object-initializer-static-semantics-early-errors
+
+ * parser/ASTBuilder.h:
+ (JSC::ASTBuilder::createGetterOrSetterProperty):
+ (JSC::ASTBuilder::createProperty):
+ (JSC::ASTBuilder::isUnderscoreProtoSetter const):
+ (JSC::ASTBuilder::getName const): Deleted.
+ * parser/Nodes.h:
+ * parser/Parser.cpp:
+ (JSC::Parser<LexerType>::parseClass):
+ (JSC::Parser<LexerType>::parseProperty):
+ (JSC::Parser<LexerType>::parseGetterSetter):
+ (JSC::Parser<LexerType>::parseObjectLiteral):
+ (JSC::Parser<LexerType>::shouldCheckPropertyForUnderscoreProtoDuplicate): Deleted.
+ * parser/Parser.h:
+ * parser/SyntaxChecker.h:
+ (JSC::SyntaxChecker::SyntaxChecker):
+ (JSC::SyntaxChecker::Property::Property):
+ (JSC::SyntaxChecker::Property::operator!):
+ (JSC::SyntaxChecker::createProperty):
+ (JSC::SyntaxChecker::createGetterOrSetterProperty):
+ (JSC::SyntaxChecker::operatorStackPop):
+
2020-08-25 Yusuke Suzuki <[email protected]>
[JSC] Add concurrency-aware version of isCallable / isConstructor to make it usable in DFG compiler
Modified: trunk/Source/_javascript_Core/parser/ASTBuilder.h (266116 => 266117)
--- trunk/Source/_javascript_Core/parser/ASTBuilder.h 2020-08-25 15:48:30 UTC (rev 266116)
+++ trunk/Source/_javascript_Core/parser/ASTBuilder.h 2020-08-25 15:58:40 UTC (rev 266117)
@@ -481,7 +481,7 @@
ArgumentListNode* createArgumentsList(const JSTokenLocation& location, ExpressionNode* arg) { return new (m_parserArena) ArgumentListNode(location, arg); }
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,
+ NEVER_INLINE PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type,
const Identifier* name, const ParserFunctionInfo<ASTBuilder>& functionInfo, ClassElementTag tag)
{
ASSERT(name);
@@ -492,7 +492,7 @@
return new (m_parserArena) PropertyNode(*name, methodDef, type, PropertyNode::Unknown, SuperBinding::Needed, tag);
}
- NEVER_INLINE PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type, bool,
+ NEVER_INLINE PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type,
ExpressionNode* name, const ParserFunctionInfo<ASTBuilder>& functionInfo, ClassElementTag tag)
{
ASSERT(name);
@@ -502,7 +502,7 @@
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,
+ NEVER_INLINE PropertyNode* createGetterOrSetterProperty(VM& vm, ParserArena& parserArena, const JSTokenLocation& location, PropertyNode::Type type,
double name, const ParserFunctionInfo<ASTBuilder>& functionInfo, ClassElementTag tag)
{
functionInfo.body->setLoc(functionInfo.startLine, functionInfo.endLine, location.startOffset, location.lineStartOffset);
@@ -512,7 +512,7 @@
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, ClassElementTag tag)
+ PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, SuperBinding superBinding, InferName inferName, ClassElementTag tag)
{
if (inferName == InferName::Allowed) {
if (node->isBaseFuncExprNode()) {
@@ -523,16 +523,16 @@
}
return new (m_parserArena) PropertyNode(*propertyName, node, type, putType, superBinding, tag);
}
- PropertyNode* createProperty(ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, ClassElementTag tag)
+ PropertyNode* createProperty(ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, SuperBinding superBinding, ClassElementTag tag)
{
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, ClassElementTag tag)
+ PropertyNode* createProperty(VM& vm, ParserArena& parserArena, double propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, SuperBinding superBinding, ClassElementTag tag)
{
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, ClassElementTag tag) { return new (m_parserArena) PropertyNode(propertyName, node, type, putType, superBinding, tag); }
- PropertyNode* createProperty(const Identifier* identifier, ExpressionNode* propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, ClassElementTag tag) { return new (m_parserArena) PropertyNode(*identifier, propertyName, node, type, putType, superBinding, tag); }
+ PropertyNode* createProperty(ExpressionNode* propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, SuperBinding superBinding, ClassElementTag tag) { return new (m_parserArena) PropertyNode(propertyName, node, type, putType, superBinding, tag); }
+ PropertyNode* createProperty(const Identifier* identifier, ExpressionNode* propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, SuperBinding superBinding, ClassElementTag tag) { return new (m_parserArena) PropertyNode(*identifier, 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); }
@@ -959,8 +959,11 @@
return result;
}
- const Identifier* getName(const Property& property) const { return property->name(); }
PropertyNode::Type getType(const Property& property) const { return property->type(); }
+ bool isUnderscoreProtoSetter(const Property& property) const
+ {
+ return PropertyNode::isUnderscoreProtoSetter(m_vm, property->name(), property->type(), property->needsSuperBinding());
+ }
bool isResolve(ExpressionNode* expr) const { return expr->isResolveNode(); }
Modified: trunk/Source/_javascript_Core/parser/Nodes.h (266116 => 266117)
--- trunk/Source/_javascript_Core/parser/Nodes.h 2020-08-25 15:48:30 UTC (rev 266116)
+++ trunk/Source/_javascript_Core/parser/Nodes.h 2020-08-25 15:58:40 UTC (rev 266117)
@@ -746,6 +746,11 @@
void setIsOverriddenByDuplicate() { m_isOverriddenByDuplicate = true; }
PutType putType() const { return static_cast<PutType>(m_putType); }
+ ALWAYS_INLINE static bool isUnderscoreProtoSetter(VM& vm, const Identifier* name, Type type, bool needsSuperBinding)
+ {
+ return name && *name == vm.propertyNames->underscoreProto && type == Type::Constant && !needsSuperBinding;
+ }
+
private:
friend class PropertyListNode;
const Identifier* m_name;
Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (266116 => 266117)
--- trunk/Source/_javascript_Core/parser/Parser.cpp 2020-08-25 15:48:30 UTC (rev 266116)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp 2020-08-25 15:58:40 UTC (rev 266117)
@@ -2977,11 +2977,10 @@
}
TreeProperty property;
- const bool alwaysStrictInsideClass = true;
if (isGetter || isSetter) {
type = static_cast<PropertyNode::Type>(type & ~PropertyNode::Constant);
type = static_cast<PropertyNode::Type>(type | (isGetter ? PropertyNode::Getter : PropertyNode::Setter));
- property = parseGetterSetter(context, alwaysStrictInsideClass, type, methodStart, ConstructorKind::None, tag);
+ property = parseGetterSetter(context, type, methodStart, ConstructorKind::None, tag);
failIfFalse(property, "Cannot parse this method");
} else if (Options::usePublicClassFields() && !match(OPENPAREN) && tag == ClassElementTag::Instance && parseMode == SourceParseMode::MethodMode) {
ASSERT(!isGetter && !isSetter);
@@ -3010,9 +3009,9 @@
failIfFalse(autoSemiColon(), "Expected a ';' following a class field");
auto inferName = initializer ? InferName::Allowed : InferName::Disallowed;
if (computedPropertyName)
- property = context.createProperty(ident, computedPropertyName, initializer, type, PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::NotNeeded, tag);
+ property = context.createProperty(ident, computedPropertyName, initializer, type, PropertyNode::Unknown, SuperBinding::NotNeeded, tag);
else
- property = context.createProperty(ident, initializer, type, PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::NotNeeded, inferName, tag);
+ property = context.createProperty(ident, initializer, type, PropertyNode::Unknown, SuperBinding::NotNeeded, inferName, tag);
} else {
ParserFunctionInfo<TreeBuilder> methodInfo;
bool isConstructor = tag == ClassElementTag::Instance && *ident == propertyNames.constructor;
@@ -3033,9 +3032,9 @@
"Cannot declare a static method named 'prototype'");
if (computedPropertyName) {
- property = context.createProperty(computedPropertyName, method, type, PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed, tag);
+ property = context.createProperty(computedPropertyName, method, type, PropertyNode::Unknown, SuperBinding::Needed, tag);
} else {
- property = context.createProperty(methodInfo.name, method, type, PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed, InferName::Allowed, tag);
+ property = context.createProperty(methodInfo.name, method, type, PropertyNode::Unknown, SuperBinding::Needed, InferName::Allowed, tag);
}
}
@@ -4104,7 +4103,7 @@
}
template <typename LexerType>
-template <class TreeBuilder> TreeProperty Parser<LexerType>::parseProperty(TreeBuilder& context, bool complete)
+template <class TreeBuilder> TreeProperty Parser<LexerType>::parseProperty(TreeBuilder& context)
{
SourceParseMode parseMode = SourceParseMode::MethodMode;
bool wasIdent = false;
@@ -4145,7 +4144,7 @@
unsigned getterOrSetterStartOffset = tokenStart();
JSToken identToken = m_token;
- if (complete || (wasIdent && !isGeneratorMethodParseMode(parseMode) && (*ident == m_vm.propertyNames->get || *ident == m_vm.propertyNames->set)))
+ if (wasIdent && !isGeneratorMethodParseMode(parseMode) && (*ident == m_vm.propertyNames->get || *ident == m_vm.propertyNames->set))
nextExpectIdentifier(LexerFlags::IgnoreReservedWords);
else
nextExpectIdentifier(TreeBuilder::DontBuildKeywords | LexerFlags::IgnoreReservedWords);
@@ -4156,13 +4155,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, ClassElementTag::No);
+ return context.createProperty(ident, node, PropertyNode::Constant, PropertyNode::Unknown, 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, ClassElementTag::No);
+ return context.createProperty(ident, method, PropertyNode::Constant, PropertyNode::KnownDirect, SuperBinding::Needed, InferName::Allowed, ClassElementTag::No);
}
failIfTrue(parseMode != SourceParseMode::MethodMode, "Expected a parenthesis for argument list");
@@ -4176,7 +4175,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, ClassElementTag::No);
+ return context.createProperty(ident, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Shorthand), PropertyNode::KnownDirect, SuperBinding::NotNeeded, InferName::Allowed, ClassElementTag::No);
}
if (match(EQUAL)) // CoverInitializedName is exclusive to BindingPattern and AssignmentPattern
@@ -4189,7 +4188,7 @@
type = PropertyNode::Setter;
else
failWithMessage("Expected a ':' following the property name '", ident->impl(), "'");
- return parseGetterSetter(context, complete, type, getterOrSetterStartOffset, ConstructorKind::None, ClassElementTag::No);
+ return parseGetterSetter(context, type, getterOrSetterStartOffset, ConstructorKind::None, ClassElementTag::No);
}
case DOUBLE:
case INTEGER: {
@@ -4200,7 +4199,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, ClassElementTag::No);
+ return context.createProperty(&ident, method, PropertyNode::Constant, PropertyNode::Unknown, SuperBinding::Needed, InferName::Allowed, ClassElementTag::No);
}
failIfTrue(parseMode != SourceParseMode::MethodMode, "Expected a parenthesis for argument list");
@@ -4208,7 +4207,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, ClassElementTag::No);
+ return context.createProperty(const_cast<VM&>(m_vm), m_parserArena, propertyName, node, PropertyNode::Constant, PropertyNode::Unknown, SuperBinding::NotNeeded, ClassElementTag::No);
}
case BIGINT: {
const Identifier* ident = &m_parserArena.identifierArena().makeBigIntDecimalIdentifier(const_cast<VM&>(m_vm), *m_token.m_data.bigIntString, m_token.m_data.radix);
@@ -4217,7 +4216,7 @@
if (match(OPENPAREN)) {
auto method = parsePropertyMethod(context, ident, parseMode);
propagateError();
- return context.createProperty(ident, method, PropertyNode::Constant, PropertyNode::Unknown, complete, SuperBinding::Needed, InferName::Allowed, ClassElementTag::No);
+ return context.createProperty(ident, method, PropertyNode::Constant, PropertyNode::Unknown, SuperBinding::Needed, InferName::Allowed, ClassElementTag::No);
}
failIfTrue(parseMode != SourceParseMode::MethodMode, "Expected a parenthesis for argument list");
@@ -4225,7 +4224,7 @@
TreeExpression node = parseAssignmentExpression(context);
failIfFalse(node, "Cannot parse _expression_ for property declaration");
context.setEndOffset(node, m_lexer->currentOffset());
- return context.createProperty(ident, node, PropertyNode::Constant, PropertyNode::Unknown, complete, SuperBinding::NotNeeded, InferName::Allowed, ClassElementTag::No);
+ return context.createProperty(ident, node, PropertyNode::Constant, PropertyNode::Unknown, SuperBinding::NotNeeded, InferName::Allowed, ClassElementTag::No);
}
case OPENBRACKET: {
next();
@@ -4236,7 +4235,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, ClassElementTag::No);
+ return context.createProperty(propertyName, method, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::KnownDirect, SuperBinding::Needed, ClassElementTag::No);
}
failIfTrue(parseMode != SourceParseMode::MethodMode, "Expected a parenthesis for argument list");
@@ -4244,7 +4243,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, ClassElementTag::No);
+ return context.createProperty(propertyName, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::Unknown, SuperBinding::NotNeeded, ClassElementTag::No);
}
case DOTDOTDOT: {
auto spreadLocation = m_token.m_location;
@@ -4254,7 +4253,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, ClassElementTag::No);
+ return context.createProperty(node, PropertyNode::Spread, PropertyNode::Unknown, SuperBinding::NotNeeded, ClassElementTag::No);
}
default:
failIfFalse(m_token.m_type & KeywordTokenFlag, "Expected a property name");
@@ -4276,7 +4275,7 @@
}
template <typename LexerType>
-template <class TreeBuilder> TreeProperty Parser<LexerType>::parseGetterSetter(TreeBuilder& context, bool strict, PropertyNode::Type type, unsigned getterOrSetterStartOffset,
+template <class TreeBuilder> TreeProperty Parser<LexerType>::parseGetterSetter(TreeBuilder& context, PropertyNode::Type type, unsigned getterOrSetterStartOffset,
ConstructorKind constructorKind, ClassElementTag tag)
{
const Identifier* stringPropertyName = nullptr;
@@ -4316,25 +4315,15 @@
}
if (stringPropertyName)
- return context.createGetterOrSetterProperty(location, type, strict, stringPropertyName, info, tag);
+ return context.createGetterOrSetterProperty(location, type, stringPropertyName, info, tag);
if (computedPropertyName)
- return context.createGetterOrSetterProperty(location, static_cast<PropertyNode::Type>(type | PropertyNode::Computed), strict, computedPropertyName, info, tag);
+ return context.createGetterOrSetterProperty(location, static_cast<PropertyNode::Type>(type | PropertyNode::Computed), computedPropertyName, info, tag);
- return context.createGetterOrSetterProperty(const_cast<VM&>(m_vm), m_parserArena, location, type, strict, numericPropertyName, info, tag);
+ return context.createGetterOrSetterProperty(const_cast<VM&>(m_vm), m_parserArena, location, type, numericPropertyName, info, tag);
}
template <typename LexerType>
-template <class TreeBuilder> bool Parser<LexerType>::shouldCheckPropertyForUnderscoreProtoDuplicate(TreeBuilder& context, const TreeProperty& property)
-{
- if (!context.getName(property))
- return false;
-
- // A Constant property that is not a Computed or Shorthand Constant property.
- return context.getType(property) == PropertyNode::Constant;
-}
-
-template <typename LexerType>
void Parser<LexerType>::recordPauseLocation(const JSTextPosition& position)
{
if (LIKELY(!m_debuggerParseData))
@@ -4377,12 +4366,10 @@
return context.createObjectLiteral(location);
}
- TreeProperty property = parseProperty(context, true);
+ TreeProperty property = parseProperty(context);
failIfFalse(property, "Cannot parse object literal property");
- bool seenUnderscoreProto = false;
- if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property))
- seenUnderscoreProto = *context.getName(property) == m_vm.propertyNames->underscoreProto;
+ bool seenProtoSetter = context.isUnderscoreProtoSetter(property);
TreePropertyList propertyList = context.createPropertyList(location, property);
TreePropertyList tail = propertyList;
@@ -4391,13 +4378,12 @@
if (match(CLOSEBRACE))
break;
JSTokenLocation propertyLocation(tokenLocation());
- property = parseProperty(context, true);
+ property = parseProperty(context);
failIfFalse(property, "Cannot parse object literal property");
- if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property)) {
- if (*context.getName(property) == m_vm.propertyNames->underscoreProto) {
- semanticFailIfTrue(seenUnderscoreProto, "Attempted to redefine __proto__ property");
- seenUnderscoreProto = true;
- }
+ if (context.isUnderscoreProtoSetter(property)) {
+ // https://tc39.es/ecma262/#sec-__proto__-property-names-in-object-initializers
+ semanticFailIfTrue(seenProtoSetter, "Attempted to redefine __proto__ property");
+ seenProtoSetter = true;
}
tail = context.createPropertyList(propertyLocation, property, tail);
}
Modified: trunk/Source/_javascript_Core/parser/Parser.h (266116 => 266117)
--- trunk/Source/_javascript_Core/parser/Parser.h 2020-08-25 15:48:30 UTC (rev 266116)
+++ trunk/Source/_javascript_Core/parser/Parser.h 2020-08-25 15:58:40 UTC (rev 266117)
@@ -1760,9 +1760,9 @@
template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseAsyncFunctionExpression(TreeBuilder&);
template <class TreeBuilder> ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&);
template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseArgument(TreeBuilder&, ArgumentType&);
- template <class TreeBuilder> TreeProperty parseProperty(TreeBuilder&, bool strict);
+ template <class TreeBuilder> TreeProperty parseProperty(TreeBuilder&);
template <class TreeBuilder> TreeExpression parsePropertyMethod(TreeBuilder& context, const Identifier* methodName, SourceParseMode);
- template <class TreeBuilder> TreeProperty parseGetterSetter(TreeBuilder&, bool strict, PropertyNode::Type, unsigned getterOrSetterStartOffset, ConstructorKind, ClassElementTag);
+ template <class TreeBuilder> TreeProperty parseGetterSetter(TreeBuilder&, 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 };
@@ -1802,8 +1802,6 @@
template <class TreeBuilder> NEVER_INLINE typename TreeBuilder::TemplateString parseTemplateString(TreeBuilder& context, bool isTemplateHead, typename LexerType::RawStringsBuildMode, bool& elementIsTail);
template <class TreeBuilder> NEVER_INLINE typename TreeBuilder::TemplateLiteral parseTemplateLiteral(TreeBuilder&, typename LexerType::RawStringsBuildMode);
- template <class TreeBuilder> ALWAYS_INLINE bool shouldCheckPropertyForUnderscoreProtoDuplicate(TreeBuilder&, const TreeProperty&);
-
template <class TreeBuilder> NEVER_INLINE const char* metaPropertyName(TreeBuilder&, TreeExpression);
template <class TreeBuilder> ALWAYS_INLINE bool isSimpleAssignmentTarget(TreeBuilder&, TreeExpression);
Modified: trunk/Source/_javascript_Core/parser/SyntaxChecker.h (266116 => 266117)
--- trunk/Source/_javascript_Core/parser/SyntaxChecker.h 2020-08-25 15:48:30 UTC (rev 266116)
+++ trunk/Source/_javascript_Core/parser/SyntaxChecker.h 2020-08-25 15:58:40 UTC (rev 266117)
@@ -64,7 +64,8 @@
SyntaxChecker* m_context;
};
- SyntaxChecker(VM& , void*)
+ SyntaxChecker(VM& vm, void*)
+ : m_vm(vm)
{
}
@@ -99,22 +100,20 @@
typedef ExpressionType Comma;
struct Property {
ALWAYS_INLINE Property(void* = nullptr)
- : type((PropertyNode::Type)0)
{
}
- ALWAYS_INLINE Property(const Identifier* ident, PropertyNode::Type ty)
- : name(ident)
- , type(ty)
+ ALWAYS_INLINE Property(PropertyNode::Type type)
+ : type(type)
{
}
- ALWAYS_INLINE Property(PropertyNode::Type ty)
- : name(nullptr)
- , type(ty)
+ ALWAYS_INLINE Property(PropertyNode::Type type, bool isUnderscoreProtoSetter)
+ : type(type)
+ , isUnderscoreProtoSetter(isUnderscoreProtoSetter)
{
}
ALWAYS_INLINE bool operator!() { return !type; }
- const Identifier* name;
- PropertyNode::Type type;
+ PropertyNode::Type type { static_cast<PropertyNode::Type>(0) };
+ bool isUnderscoreProtoSetter { false };
};
typedef int PropertyList;
typedef int ElementList;
@@ -215,28 +214,23 @@
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, ClassElementTag)
+ Property createProperty(const Identifier* name, int, PropertyNode::Type type, PropertyNode::PutType, SuperBinding superBinding, InferName, ClassElementTag)
{
- if (!complete)
- return Property(type);
- ASSERT(name);
- return Property(name, type);
+ return Property(type, PropertyNode::isUnderscoreProtoSetter(m_vm, name, type, superBinding == SuperBinding::Needed));
}
- Property createProperty(int, PropertyNode::Type type, PropertyNode::PutType, bool, SuperBinding, ClassElementTag)
+ Property createProperty(int, PropertyNode::Type type, PropertyNode::PutType, SuperBinding, ClassElementTag)
{
return Property(type);
}
- Property createProperty(VM& vm, ParserArena& parserArena, double name, int, PropertyNode::Type type, PropertyNode::PutType, bool complete, SuperBinding, ClassElementTag)
+ Property createProperty(VM&, ParserArena&, double, int, PropertyNode::Type type, PropertyNode::PutType, SuperBinding, ClassElementTag)
{
- if (!complete)
- return Property(type);
- return Property(&parserArena.identifierArena().makeNumericIdentifier(vm, name), type);
+ return Property(type);
}
- Property createProperty(int, int, PropertyNode::Type type, PropertyNode::PutType, bool, SuperBinding, ClassElementTag)
+ Property createProperty(int, int, PropertyNode::Type type, PropertyNode::PutType, SuperBinding, ClassElementTag)
{
return Property(type);
}
- Property createProperty(const Identifier*, int, int, PropertyNode::Type type, PropertyNode::PutType, bool, SuperBinding, ClassElementTag)
+ Property createProperty(const Identifier*, int, int, PropertyNode::Type type, PropertyNode::PutType, SuperBinding, ClassElementTag)
{
return Property(type);
}
@@ -291,22 +285,17 @@
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>&, ClassElementTag)
+ Property createGetterOrSetterProperty(const JSTokenLocation&, PropertyNode::Type type, const Identifier*, const ParserFunctionInfo<SyntaxChecker>&, ClassElementTag)
{
- ASSERT(name);
- if (!strict)
- return Property(type);
- return Property(name, type);
+ return Property(type);
}
- Property createGetterOrSetterProperty(const JSTokenLocation&, PropertyNode::Type type, bool, int, const ParserFunctionInfo<SyntaxChecker>&, ClassElementTag)
+ Property createGetterOrSetterProperty(const JSTokenLocation&, PropertyNode::Type type, 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>&, ClassElementTag)
+ Property createGetterOrSetterProperty(VM&, ParserArena&, const JSTokenLocation&, PropertyNode::Type type, double, const ParserFunctionInfo<SyntaxChecker>&, ClassElementTag)
{
- if (!strict)
- return Property(type);
- return Property(&parserArena.identifierArena().makeNumericIdentifier(vm, name), type);
+ return Property(type);
}
void appendStatement(int, int) { }
@@ -339,8 +328,8 @@
void assignmentStackAppend(int& assignmentStackDepth, int, int, int, int, Operator) { assignmentStackDepth = 1; }
int createAssignment(const JSTokenLocation&, int& assignmentStackDepth, int, int, int, int) { assignmentStackDepth = 0; return AssignmentExpr; }
- const Identifier* getName(const Property& property) const { return property.name; }
PropertyNode::Type getType(const Property& property) const { return property.type; }
+ bool isUnderscoreProtoSetter(const Property& property) const { return property.isUnderscoreProtoSetter; }
bool isResolve(ExpressionType expr) const { return expr == ResolveExpr || expr == ResolveEvalExpr; }
ExpressionType createDestructuringAssignment(const JSTokenLocation&, int, ExpressionType)
{
@@ -447,6 +436,7 @@
void propagateArgumentsUse() { }
private:
+ VM& m_vm;
int m_topBinaryExpr;
int m_topUnaryToken;
};