Ignore:
Timestamp:
Aug 25, 2020, 8:58:40 AM (5 years ago)
Author:
Alexey Shvayka
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/JavaScriptCore:

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/parser/ASTBuilder.h

    r264633 r266117  
    482482    ArgumentListNode* createArgumentsList(const JSTokenLocation& location, ArgumentListNode* args, ExpressionNode* arg) { return new (m_parserArena) ArgumentListNode(location, args, arg); }
    483483
    484     NEVER_INLINE PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type, bool,
     484    NEVER_INLINE PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type,
    485485        const Identifier* name, const ParserFunctionInfo<ASTBuilder>& functionInfo, ClassElementTag tag)
    486486    {
     
    493493    }
    494494
    495     NEVER_INLINE PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type, bool,
     495    NEVER_INLINE PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type,
    496496        ExpressionNode* name, const ParserFunctionInfo<ASTBuilder>& functionInfo, ClassElementTag tag)
    497497    {
     
    503503    }
    504504
    505     NEVER_INLINE PropertyNode* createGetterOrSetterProperty(VM& vm, ParserArena& parserArena, const JSTokenLocation& location, PropertyNode::Type type, bool,
     505    NEVER_INLINE PropertyNode* createGetterOrSetterProperty(VM& vm, ParserArena& parserArena, const JSTokenLocation& location, PropertyNode::Type type,
    506506        double name, const ParserFunctionInfo<ASTBuilder>& functionInfo, ClassElementTag tag)
    507507    {
     
    513513    }
    514514
    515     PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, InferName inferName, ClassElementTag tag)
     515    PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, SuperBinding superBinding, InferName inferName, ClassElementTag tag)
    516516    {
    517517        if (inferName == InferName::Allowed) {
     
    524524        return new (m_parserArena) PropertyNode(*propertyName, node, type, putType, superBinding, tag);
    525525    }
    526     PropertyNode* createProperty(ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, ClassElementTag tag)
     526    PropertyNode* createProperty(ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, SuperBinding superBinding, ClassElementTag tag)
    527527    {
    528528        return new (m_parserArena) PropertyNode(node, type, putType, superBinding, tag);
    529529    }
    530     PropertyNode* createProperty(VM& vm, ParserArena& parserArena, double propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, ClassElementTag tag)
     530    PropertyNode* createProperty(VM& vm, ParserArena& parserArena, double propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, SuperBinding superBinding, ClassElementTag tag)
    531531    {
    532532        return new (m_parserArena) PropertyNode(parserArena.identifierArena().makeNumericIdentifier(vm, propertyName), node, type, putType, superBinding, tag);
    533533    }
    534     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); }
    535     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); }
     534    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); }
     535    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); }
    536536    PropertyListNode* createPropertyList(const JSTokenLocation& location, PropertyNode* property) { return new (m_parserArena) PropertyListNode(location, property); }
    537537    PropertyListNode* createPropertyList(const JSTokenLocation& location, PropertyNode* property, PropertyListNode* tail) { return new (m_parserArena) PropertyListNode(location, property, tail); }
     
    960960    }
    961961
    962     const Identifier* getName(const Property& property) const { return property->name(); }
    963962    PropertyNode::Type getType(const Property& property) const { return property->type(); }
     963    bool isUnderscoreProtoSetter(const Property& property) const
     964    {
     965        return PropertyNode::isUnderscoreProtoSetter(m_vm, property->name(), property->type(), property->needsSuperBinding());
     966    }
    964967
    965968    bool isResolve(ExpressionNode* expr) const { return expr->isResolveNode(); }
Note: See TracChangeset for help on using the changeset viewer.