Title: [266117] trunk
Revision
266117
Author
[email protected]
Date
2020-08-25 08:58:40 -0700 (Tue, 25 Aug 2020)

Log Message

Invalid early error for object literal method named "__proto__"
https://bugs.webkit.org/show_bug.cgi?id=215760

Reviewed by Ross Kirsling.

JSTests:

* test262/expectations.yaml: Mark 2 test cases as passing.

Source/_javascript_Core:

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):

Modified Paths

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;
 };
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to