Title: [266264] trunk
Revision
266264
Author
[email protected]
Date
2020-08-27 17:27:19 -0700 (Thu, 27 Aug 2020)

Log Message

__proto__ in object literal should perform [[SetPrototypeOf]] directly
https://bugs.webkit.org/show_bug.cgi?id=215769

Reviewed by Ross Kirsling.

JSTests:

* microbenchmarks/object-literal-underscore-proto-setter.js: Added.
* stress/syntax-checker-duplicate-underscore-proto.js:
Rewrite the test to ensure each eval() call throws a SyntaxError.

Source/_javascript_Core:

To fix __proto__ usage in object literals if Object.prototype.__proto__ is overridden
or removed, this patch sets the [[Prototype]] directly, aligning JSC with V8 and
SpiderMonkey. We are safe to skip method table lookups and cycle checks, as the
spec [1] calls [[SetPrototypeOf]] on newly created (unreferenced) ordinary objects.

This change removes PropertyNode::PutType because its only purpose was to accomodate
__proto__ in object literals. Since emitPutConstantProperty() handles static public
class fields, which don't need `super` binding, PropertyNode::isUnderscoreProtoSetter()
is extended to reject class properties.

This patch speeds up creating object literals with __proto__ by 25%.

[1]: https://tc39.es/ecma262/#sec-__proto__-property-names-in-object-initializers (step 7.a)

* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitDirectPutById):
(JSC::BytecodeGenerator::emitDirectSetPrototypeOf):
1. Remove unused `dst` parameter to align with other `put` methods.
2. Remove `divot*` parameters as it's cumbersome to pass them through,
   and globalFuncSetPrototypeDirect() never throws anyway.

* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::PropertyListNode::emitPutConstantProperty):
(JSC::BytecodeIntrinsicNode::emit_intrinsic_putByIdDirect):
(JSC::BytecodeIntrinsicNode::emit_intrinsic_putByIdDirectPrivate):
(JSC::ClassExprNode::emitBytecode):
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createGetterOrSetterProperty):
(JSC::ASTBuilder::createProperty):
(JSC::ASTBuilder::isUnderscoreProtoSetter const):
* parser/NodeConstructors.h:
(JSC::PropertyNode::PropertyNode):
* parser/Nodes.h:
* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseClass):
(JSC::Parser<LexerType>::parseProperty):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createProperty):
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::globalFuncSetPrototypeDirect):
1. Ignore a prototype value of incorrect type as per spec [1],
   which is unobservable for call sites in ClassExprNode::emitBytecode().
2. Assert that JSObject::setPrototypeDirect() doesn't throw.

LayoutTests:

* js/script-tests/object-literal-direct-put.js:

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (266263 => 266264)


--- trunk/JSTests/ChangeLog	2020-08-27 23:48:31 UTC (rev 266263)
+++ trunk/JSTests/ChangeLog	2020-08-28 00:27:19 UTC (rev 266264)
@@ -1,3 +1,14 @@
+2020-08-27  Alexey Shvayka  <[email protected]>
+
+        __proto__ in object literal should perform [[SetPrototypeOf]] directly
+        https://bugs.webkit.org/show_bug.cgi?id=215769
+
+        Reviewed by Ross Kirsling.
+
+        * microbenchmarks/object-literal-underscore-proto-setter.js: Added.
+        * stress/syntax-checker-duplicate-underscore-proto.js:
+        Rewrite the test to ensure each eval() call throws a SyntaxError.
+
 2020-08-27  Yusuke Suzuki  <[email protected]>
 
         [JSC] setLength in Array#push could get very large length

Added: trunk/JSTests/microbenchmarks/object-literal-underscore-proto-setter.js (0 => 266264)


--- trunk/JSTests/microbenchmarks/object-literal-underscore-proto-setter.js	                        (rev 0)
+++ trunk/JSTests/microbenchmarks/object-literal-underscore-proto-setter.js	2020-08-28 00:27:19 UTC (rev 266264)
@@ -0,0 +1,6 @@
+var obj, arr = [];
+for (var i = 0; i < 1e5; ++i) {
+    obj = {__proto__: null};
+    obj = {__proto__: arr};
+    obj = {__proto__: obj};
+}

Modified: trunk/JSTests/stress/syntax-checker-duplicate-underscore-proto.js (266263 => 266264)


--- trunk/JSTests/stress/syntax-checker-duplicate-underscore-proto.js	2020-08-27 23:48:31 UTC (rev 266263)
+++ trunk/JSTests/stress/syntax-checker-duplicate-underscore-proto.js	2020-08-28 00:27:19 UTC (rev 266264)
@@ -1,8 +1,16 @@
-try {
-    eval("(function() { ({ x: 1, y: 1, z: 1, __proto__: 1, __proto__: 1 }) })");
-    eval("(function() { ({ x: 1, y: 1, z: 1, '__proto__': 1, '__proto__': 1 }) })");
-    throw new Error('Should have thrown a SyntaxError');
-} catch (error) {
-    if (!(error instanceof SyntaxError) && error.message !== 'Attempted to redefine __proto__ property.')
-        throw new Error(`Unexpected error: ${error.message}`);
+function shouldThrowSyntaxError(str, message) {
+    try {
+        eval(str);
+        throw new Error("Expected `" + str + "` to throw a SyntaxError, but did not throw.")
+    } catch (e) {
+        if (e.constructor !== SyntaxError)
+            throw new Error("Expected `" + str + "` to throw a SyntaxError, but threw '" + e + "'");
+        if (message !== void 0 && e.message !== message)
+            throw new Error("Expected `" + str + "` to throw SyntaxError: '" + message + "', but threw '" + e + "'");
+    }
 }
+
+shouldThrowSyntaxError("(function() { ({ x: 1, y: 1, z: 1, __proto__: 1, __proto__: 1 }) })", 'Attempted to redefine __proto__ property.');
+shouldThrowSyntaxError("(function() { ({ x: 1, y: 1, __proto__: 1, '__proto__': 1, z: 1 }) })", 'Attempted to redefine __proto__ property.');
+shouldThrowSyntaxError('(function() { ({ x: 1, "__proto__": 1, "__proto__": 1, y: 1, z: 1 }) })', 'Attempted to redefine __proto__ property.');
+shouldThrowSyntaxError('(function() { ({ __proto__: 1, "__proto__": 1, x: 1, y: 1, z: 1 }) })', 'Attempted to redefine __proto__ property.');

Modified: trunk/LayoutTests/ChangeLog (266263 => 266264)


--- trunk/LayoutTests/ChangeLog	2020-08-27 23:48:31 UTC (rev 266263)
+++ trunk/LayoutTests/ChangeLog	2020-08-28 00:27:19 UTC (rev 266264)
@@ -1,3 +1,12 @@
+2020-08-27  Alexey Shvayka  <[email protected]>
+
+        __proto__ in object literal should perform [[SetPrototypeOf]] directly
+        https://bugs.webkit.org/show_bug.cgi?id=215769
+
+        Reviewed by Ross Kirsling.
+
+        * js/script-tests/object-literal-direct-put.js:
+
 2020-08-27  Simon Fraser  <[email protected]>
 
         Scrolling on select element doesn't work after scrolling the page

Modified: trunk/LayoutTests/js/script-tests/object-literal-direct-put.js (266263 => 266264)


--- trunk/LayoutTests/js/script-tests/object-literal-direct-put.js	2020-08-27 23:48:31 UTC (rev 266263)
+++ trunk/LayoutTests/js/script-tests/object-literal-direct-put.js	2020-08-28 00:27:19 UTC (rev 266264)
@@ -1,5 +1,7 @@
 description("This test ensures that properties on an object literal are put directly onto the created object, and don't call setters in the prototype chain.");
 
+delete Object.prototype.__proto__;
+
 shouldBeTrue("({a:true}).a");
 shouldBeTrue("({__proto__: {a:false}, a:true}).a");
 shouldBeTrue("({__proto__: {set a(x) {throw 'Should not call setter'; }}, a:true}).a");

Modified: trunk/Source/_javascript_Core/ChangeLog (266263 => 266264)


--- trunk/Source/_javascript_Core/ChangeLog	2020-08-27 23:48:31 UTC (rev 266263)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-08-28 00:27:19 UTC (rev 266264)
@@ -1,3 +1,55 @@
+2020-08-27  Alexey Shvayka  <[email protected]>
+
+        __proto__ in object literal should perform [[SetPrototypeOf]] directly
+        https://bugs.webkit.org/show_bug.cgi?id=215769
+
+        Reviewed by Ross Kirsling.
+
+        To fix __proto__ usage in object literals if Object.prototype.__proto__ is overridden
+        or removed, this patch sets the [[Prototype]] directly, aligning JSC with V8 and
+        SpiderMonkey. We are safe to skip method table lookups and cycle checks, as the
+        spec [1] calls [[SetPrototypeOf]] on newly created (unreferenced) ordinary objects.
+
+        This change removes PropertyNode::PutType because its only purpose was to accomodate
+        __proto__ in object literals. Since emitPutConstantProperty() handles static public
+        class fields, which don't need `super` binding, PropertyNode::isUnderscoreProtoSetter()
+        is extended to reject class properties.
+
+        This patch speeds up creating object literals with __proto__ by 25%.
+
+        [1]: https://tc39.es/ecma262/#sec-__proto__-property-names-in-object-initializers (step 7.a)
+
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitDirectPutById):
+        (JSC::BytecodeGenerator::emitDirectSetPrototypeOf):
+        1. Remove unused `dst` parameter to align with other `put` methods.
+        2. Remove `divot*` parameters as it's cumbersome to pass them through,
+           and globalFuncSetPrototypeDirect() never throws anyway.
+
+        * bytecompiler/BytecodeGenerator.h:
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::PropertyListNode::emitPutConstantProperty):
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_putByIdDirect):
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_putByIdDirectPrivate):
+        (JSC::ClassExprNode::emitBytecode):
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createGetterOrSetterProperty):
+        (JSC::ASTBuilder::createProperty):
+        (JSC::ASTBuilder::isUnderscoreProtoSetter const):
+        * parser/NodeConstructors.h:
+        (JSC::PropertyNode::PropertyNode):
+        * parser/Nodes.h:
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseClass):
+        (JSC::Parser<LexerType>::parseProperty):
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::createProperty):
+        * runtime/JSGlobalObjectFunctions.cpp:
+        (JSC::globalFuncSetPrototypeDirect):
+        1. Ignore a prototype value of incorrect type as per spec [1],
+           which is unobservable for call sites in ClassExprNode::emitBytecode().
+        2. Assert that JSObject::setPrototypeDirect() doesn't throw.
+
 2020-08-27  Yusuke Suzuki  <[email protected]>
 
         [JSC] setLength in Array#push could get very large length

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (266263 => 266264)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2020-08-27 23:48:31 UTC (rev 266263)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2020-08-28 00:27:19 UTC (rev 266264)
@@ -2576,7 +2576,7 @@
     return value;
 }
 
-RegisterID* BytecodeGenerator::emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value, PropertyNode::PutType putType)
+RegisterID* BytecodeGenerator::emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value)
 {
     ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties should be handled with put_by_val(direct).");
 
@@ -2584,7 +2584,7 @@
 
     m_staticPropertyAnalyzer.putById(base, propertyIndex);
 
-    PutByIdFlags type = (putType == PropertyNode::KnownDirect || property != m_vm.propertyNames->underscoreProto) ? PutByIdFlags::createDirect(ecmaMode()) : PutByIdFlags::create(ecmaMode());
+    PutByIdFlags type = PutByIdFlags::createDirect(ecmaMode());
     OpPutById::emit(this, base, propertyIndex, value, type);
     return value;
 }
@@ -2692,7 +2692,7 @@
     return dst;
 }
 
-RegisterID* BytecodeGenerator::emitDirectSetPrototypeOf(RegisterID* dst, RegisterID* base, RegisterID* prototype, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
+RegisterID* BytecodeGenerator::emitDirectSetPrototypeOf(RegisterID* base, RegisterID* prototype)
 {
     RefPtr<RegisterID> setPrototypeDirect = moveLinkTimeConstant(nullptr, LinkTimeConstant::setPrototypeDirect);
 
@@ -2700,8 +2700,9 @@
     move(args.thisRegister(), base);
     move(args.argumentRegister(0), prototype);
 
-    emitCall(newTemporary(), setPrototypeDirect.get(), NoExpectedFunction, args, divot, divotStart, divotEnd, DebuggableCall::No);
-    return dst;
+    JSTextPosition position;
+    emitCall(newTemporary(), setPrototypeDirect.get(), NoExpectedFunction, args, position, position, position, DebuggableCall::No);
+    return base;
 }
 
 RegisterID* BytecodeGenerator::emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (266263 => 266264)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2020-08-27 23:48:31 UTC (rev 266263)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2020-08-28 00:27:19 UTC (rev 266264)
@@ -807,12 +807,12 @@
         RegisterID* emitDirectGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
         RegisterID* emitPutById(RegisterID* base, const Identifier& property, RegisterID* value);
         RegisterID* emitPutById(RegisterID* base, RegisterID* thisValue, const Identifier& property, RegisterID* value);
-        RegisterID* emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value, PropertyNode::PutType);
+        RegisterID* emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value);
         RegisterID* emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier&);
         RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
         RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* thisValue, RegisterID* property);
         RegisterID* emitGetPrototypeOf(RegisterID* dst, RegisterID* value);
-        RegisterID* emitDirectSetPrototypeOf(RegisterID* dst, RegisterID* base, RegisterID* prototype, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
+        RegisterID* emitDirectSetPrototypeOf(RegisterID* base, RegisterID* prototype);
         RegisterID* emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
         RegisterID* emitPutByVal(RegisterID* base, RegisterID* thisValue, RegisterID* property, RegisterID* value);
         RegisterID* emitDirectGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property);

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (266263 => 266264)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2020-08-27 23:48:31 UTC (rev 266263)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2020-08-28 00:27:19 UTC (rev 266264)
@@ -747,6 +747,12 @@
     // Private fields are handled in the synthetic instanceFieldInitializer function, not here.
     ASSERT(!(node.type() & PropertyNode::Private));
 
+    if (PropertyNode::isUnderscoreProtoSetter(generator.vm(), node)) {
+        RefPtr<RegisterID> prototype = generator.emitNode(node.m_assign);
+        generator.emitDirectSetPrototypeOf(newObj, prototype.get());
+        return;
+    }
+
     bool shouldSetFunctionName = generator.shouldSetFunctionName(node.m_assign);
 
     RefPtr<RegisterID> propertyName;
@@ -777,7 +783,7 @@
         ASSERT(!propertyName);
         Optional<uint32_t> optionalIndex = parseIndex(*identifier);
         if (!optionalIndex) {
-            generator.emitDirectPutById(newObj, *identifier, value.get(), node.putType());
+            generator.emitDirectPutById(newObj, *identifier, value.get());
             return;
         }
 
@@ -1394,7 +1400,7 @@
 
     ASSERT(!node->m_next);
 
-    return generator.move(dst, generator.emitDirectPutById(base.get(), ident, value.get(), PropertyNode::KnownDirect));
+    return generator.move(dst, generator.emitDirectPutById(base.get(), ident, value.get()));
 }
 
 RegisterID* BytecodeIntrinsicNode::emit_intrinsic_putByIdDirectPrivate(BytecodeGenerator& generator, RegisterID* dst)
@@ -1410,7 +1416,7 @@
 
     ASSERT(!node->m_next);
 
-    return generator.move(dst, generator.emitDirectPutById(base.get(), generator.parserArena().identifierArena().makeIdentifier(generator.vm(), symbol), value.get(), PropertyNode::KnownDirect));
+    return generator.move(dst, generator.emitDirectPutById(base.get(), generator.parserArena().identifierArena().makeIdentifier(generator.vm(), symbol), value.get()));
 }
 
 RegisterID* BytecodeIntrinsicNode::emit_intrinsic_putByValDirect(BytecodeGenerator& generator, RegisterID* dst)
@@ -4908,9 +4914,9 @@
         generator.emitThrowTypeError("The value of the superclass's prototype property is not an object or null."_s);
         generator.emitLabel(protoParentIsObjectOrNullLabel.get());
 
-        generator.emitDirectSetPrototypeOf(tempRegister.get(), constructor.get(), superclass.get(), divot(), divotStart(), divotEnd());
+        generator.emitDirectSetPrototypeOf(constructor.get(), superclass.get());
         generator.emitLabel(superclassIsNullLabel.get());
-        generator.emitDirectSetPrototypeOf(tempRegister.get(), prototype.get(), protoParent.get(), divot(), divotStart(), divotEnd());
+        generator.emitDirectSetPrototypeOf(prototype.get(), protoParent.get());
     }
 
     if (needsHomeObject)
@@ -4935,7 +4941,7 @@
             // https://bugs.webkit.org/show_bug.cgi?id=196867
             emitPutHomeObject(generator, instanceFieldInitializer.get(), prototype.get());
 
-            generator.emitDirectPutById(constructor.get(), generator.propertyNames().builtinNames().instanceFieldInitializerPrivateName(), instanceFieldInitializer.get(), PropertyNode::Unknown);
+            generator.emitDirectPutById(constructor.get(), generator.propertyNames().builtinNames().instanceFieldInitializerPrivateName(), instanceFieldInitializer.get());
         }
     }
 

Modified: trunk/Source/_javascript_Core/parser/ASTBuilder.h (266263 => 266264)


--- trunk/Source/_javascript_Core/parser/ASTBuilder.h	2020-08-27 23:48:31 UTC (rev 266263)
+++ trunk/Source/_javascript_Core/parser/ASTBuilder.h	2020-08-28 00:27:19 UTC (rev 266264)
@@ -489,7 +489,7 @@
         functionInfo.body->setEcmaName(*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, tag);
+        return new (m_parserArena) PropertyNode(*name, methodDef, type, SuperBinding::Needed, tag);
     }
 
     NEVER_INLINE PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type,
@@ -499,7 +499,7 @@
         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, tag);
+        return new (m_parserArena) PropertyNode(name, methodDef, type, SuperBinding::Needed, tag);
     }
 
     NEVER_INLINE PropertyNode* createGetterOrSetterProperty(VM& vm, ParserArena& parserArena, const JSTokenLocation& location, PropertyNode::Type type,
@@ -509,10 +509,10 @@
         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, tag);
+        return new (m_parserArena) PropertyNode(ident, methodDef, type, SuperBinding::Needed, tag);
     }
 
-    PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, SuperBinding superBinding, InferName inferName, ClassElementTag tag)
+    PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type, SuperBinding superBinding, InferName inferName, ClassElementTag tag)
     {
         if (inferName == InferName::Allowed) {
             if (node->isBaseFuncExprNode()) {
@@ -521,18 +521,18 @@
             } else if (node->isClassExprNode())
                 static_cast<ClassExprNode*>(node)->setEcmaName(*propertyName);
         }
-        return new (m_parserArena) PropertyNode(*propertyName, node, type, putType, superBinding, tag);
+        return new (m_parserArena) PropertyNode(*propertyName, node, type, superBinding, tag);
     }
-    PropertyNode* createProperty(ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, SuperBinding superBinding, ClassElementTag tag)
+    PropertyNode* createProperty(ExpressionNode* node, PropertyNode::Type type, SuperBinding superBinding, ClassElementTag tag)
     {
-        return new (m_parserArena) PropertyNode(node, type, putType, superBinding, tag);
+        return new (m_parserArena) PropertyNode(node, type, superBinding, tag);
     }
-    PropertyNode* createProperty(VM& vm, ParserArena& parserArena, double propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, SuperBinding superBinding, ClassElementTag tag)
+    PropertyNode* createProperty(VM& vm, ParserArena& parserArena, double propertyName, ExpressionNode* node, PropertyNode::Type type, SuperBinding superBinding, ClassElementTag tag)
     {
-        return new (m_parserArena) PropertyNode(parserArena.identifierArena().makeNumericIdentifier(vm, propertyName), node, type, putType, superBinding, tag);
+        return new (m_parserArena) PropertyNode(parserArena.identifierArena().makeNumericIdentifier(vm, propertyName), node, type, 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); }
+    PropertyNode* createProperty(ExpressionNode* propertyName, ExpressionNode* node, PropertyNode::Type type, SuperBinding superBinding, ClassElementTag tag) { return new (m_parserArena) PropertyNode(propertyName, node, type, superBinding, tag); }
+    PropertyNode* createProperty(const Identifier* identifier, ExpressionNode* propertyName, ExpressionNode* node, PropertyNode::Type type, SuperBinding superBinding, ClassElementTag tag) { return new (m_parserArena) PropertyNode(*identifier, propertyName, node, type, 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); }
 
@@ -960,11 +960,7 @@
     }
 
     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 isUnderscoreProtoSetter(const Property& property) const { return PropertyNode::isUnderscoreProtoSetter(m_vm, *property); }
     bool isResolve(ExpressionNode* expr) const { return expr->isResolveNode(); }
 
     ExpressionNode* createDestructuringAssignment(const JSTokenLocation& location, DestructuringPattern pattern, ExpressionNode* initializer)

Modified: trunk/Source/_javascript_Core/parser/NodeConstructors.h (266263 => 266264)


--- trunk/Source/_javascript_Core/parser/NodeConstructors.h	2020-08-27 23:48:31 UTC (rev 266263)
+++ trunk/Source/_javascript_Core/parser/NodeConstructors.h	2020-08-28 00:27:19 UTC (rev 266264)
@@ -243,49 +243,45 @@
     {
     }
 
-    inline PropertyNode::PropertyNode(const Identifier& name, ExpressionNode* assign, Type type, PutType putType, SuperBinding superBinding, ClassElementTag tag)
+    inline PropertyNode::PropertyNode(const Identifier& name, ExpressionNode* assign, Type type, SuperBinding superBinding, ClassElementTag tag)
         : m_name(&name)
         , m_expression(nullptr)
         , m_assign(assign)
         , m_type(type)
         , m_needsSuperBinding(superBinding == SuperBinding::Needed)
-        , m_putType(putType)
         , m_classElementTag(static_cast<unsigned>(tag))
         , m_isOverriddenByDuplicate(false)
     {
     }
     
-    inline PropertyNode::PropertyNode(ExpressionNode* assign, Type type, PutType putType, SuperBinding superBinding, ClassElementTag tag)
+    inline PropertyNode::PropertyNode(ExpressionNode* assign, Type type, SuperBinding superBinding, ClassElementTag tag)
         : m_name(nullptr)
         , m_expression(nullptr)
         , m_assign(assign)
         , m_type(type)
         , m_needsSuperBinding(superBinding == SuperBinding::Needed)
-        , m_putType(putType)
         , m_classElementTag(static_cast<unsigned>(tag))
         , m_isOverriddenByDuplicate(false)
     {
     }
 
-    inline PropertyNode::PropertyNode(ExpressionNode* name, ExpressionNode* assign, Type type, PutType putType, SuperBinding superBinding, ClassElementTag tag)
+    inline PropertyNode::PropertyNode(ExpressionNode* name, ExpressionNode* assign, Type type, SuperBinding superBinding, ClassElementTag tag)
         : m_name(nullptr)
         , m_expression(name)
         , m_assign(assign)
         , m_type(type)
         , m_needsSuperBinding(superBinding == SuperBinding::Needed)
-        , m_putType(putType)
         , m_classElementTag(static_cast<unsigned>(tag))
         , m_isOverriddenByDuplicate(false)
     {
     }
 
-    inline PropertyNode::PropertyNode(const Identifier& ident, ExpressionNode* name, ExpressionNode* assign, Type type, PutType putType, SuperBinding superBinding, ClassElementTag tag)
+    inline PropertyNode::PropertyNode(const Identifier& ident, ExpressionNode* name, ExpressionNode* assign, Type type, SuperBinding superBinding, ClassElementTag tag)
         : m_name(&ident)
         , m_expression(name)
         , m_assign(assign)
         , m_type(type)
         , m_needsSuperBinding(superBinding == SuperBinding::Needed)
-        , m_putType(putType)
         , m_classElementTag(static_cast<unsigned>(tag))
         , m_isOverriddenByDuplicate(false)
     {

Modified: trunk/Source/_javascript_Core/parser/Nodes.h (266263 => 266264)


--- trunk/Source/_javascript_Core/parser/Nodes.h	2020-08-27 23:48:31 UTC (rev 266263)
+++ trunk/Source/_javascript_Core/parser/Nodes.h	2020-08-28 00:27:19 UTC (rev 266264)
@@ -722,12 +722,11 @@
     class PropertyNode final : public ParserArenaFreeable {
     public:
         enum Type : uint8_t { Constant = 1, Getter = 2, Setter = 4, Computed = 8, Shorthand = 16, Spread = 32, Private = 64 };
-        enum PutType : uint8_t { Unknown, KnownDirect };
 
-        PropertyNode(const Identifier&, ExpressionNode*, Type, PutType, SuperBinding, ClassElementTag);
-        PropertyNode(ExpressionNode*, Type, PutType, SuperBinding, ClassElementTag);
-        PropertyNode(ExpressionNode* propertyName, ExpressionNode*, Type, PutType, SuperBinding, ClassElementTag);
-        PropertyNode(const Identifier&, ExpressionNode* propertyName, ExpressionNode*, Type, PutType, SuperBinding, ClassElementTag);
+        PropertyNode(const Identifier&, ExpressionNode*, Type, SuperBinding, ClassElementTag);
+        PropertyNode(ExpressionNode*, Type, SuperBinding, ClassElementTag);
+        PropertyNode(ExpressionNode* propertyName, ExpressionNode*, Type, SuperBinding, ClassElementTag);
+        PropertyNode(const Identifier&, ExpressionNode* propertyName, ExpressionNode*, Type, SuperBinding, ClassElementTag);
 
         ExpressionNode* expressionName() const { return m_expression; }
         const Identifier* name() const { return m_name; }
@@ -744,13 +743,17 @@
         bool hasComputedName() const { return m_expression; }
         bool isComputedClassField() const { return isClassField() && hasComputedName(); }
         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)
+        ALWAYS_INLINE static bool isUnderscoreProtoSetter(VM& vm, const PropertyNode& node)
         {
-            return name && *name == vm.propertyNames->underscoreProto && type == Type::Constant && !needsSuperBinding;
+            return isUnderscoreProtoSetter(vm, node.name(), node.type(), node.needsSuperBinding(), node.isClassProperty());
         }
 
+        ALWAYS_INLINE static bool isUnderscoreProtoSetter(VM& vm, const Identifier* name, Type type, bool needsSuperBinding, bool isClassProperty)
+        {
+            return name && *name == vm.propertyNames->underscoreProto && type == Type::Constant && !needsSuperBinding && !isClassProperty;
+        }
+
     private:
         friend class PropertyListNode;
         const Identifier* m_name;
@@ -758,7 +761,6 @@
         ExpressionNode* m_assign;
         unsigned m_type : 7;
         unsigned m_needsSuperBinding : 1;
-        unsigned m_putType : 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;
@@ -2328,7 +2330,7 @@
         Type m_type;
     };
 
-    class ClassExprNode final : public ExpressionNode, public ThrowableExpressionData, public VariableEnvironmentNode {
+    class ClassExprNode final : public ExpressionNode, public VariableEnvironmentNode {
         JSC_MAKE_PARSER_ARENA_DELETABLE_ALLOCATED(ClassExprNode);
     public:
         ClassExprNode(const JSTokenLocation&, const Identifier&, const SourceCode& classSource,

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (266263 => 266264)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2020-08-27 23:48:31 UTC (rev 266263)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2020-08-28 00:27:19 UTC (rev 266264)
@@ -3009,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, SuperBinding::NotNeeded, tag);
+                property = context.createProperty(ident, computedPropertyName, initializer, type, SuperBinding::NotNeeded, tag);
             else
-                property = context.createProperty(ident, initializer, type, PropertyNode::Unknown, SuperBinding::NotNeeded, inferName, tag);
+                property = context.createProperty(ident, initializer, type, SuperBinding::NotNeeded, inferName, tag);
         } else {
             ParserFunctionInfo<TreeBuilder> methodInfo;
             bool isConstructor = tag == ClassElementTag::Instance && *ident == propertyNames.constructor;
@@ -3032,9 +3032,9 @@
                 "Cannot declare a static method named 'prototype'");
 
             if (computedPropertyName) {
-                property = context.createProperty(computedPropertyName, method, type, PropertyNode::Unknown, SuperBinding::Needed, tag);
+                property = context.createProperty(computedPropertyName, method, type, SuperBinding::Needed, tag);
             } else {
-                property = context.createProperty(methodInfo.name, method, type, PropertyNode::Unknown, SuperBinding::Needed, InferName::Allowed, tag);
+                property = context.createProperty(methodInfo.name, method, type, SuperBinding::Needed, InferName::Allowed, tag);
             }
         }
 
@@ -4155,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, SuperBinding::NotNeeded, inferName, ClassElementTag::No);
+            return context.createProperty(ident, node, PropertyNode::Constant, SuperBinding::NotNeeded, inferName, ClassElementTag::No);
         }
 
         if (match(OPENPAREN)) {
             auto method = parsePropertyMethod(context, ident, parseMode);
             propagateError();
-            return context.createProperty(ident, method, PropertyNode::Constant, PropertyNode::KnownDirect, SuperBinding::Needed, InferName::Allowed, ClassElementTag::No);
+            return context.createProperty(ident, method, PropertyNode::Constant, SuperBinding::Needed, InferName::Allowed, ClassElementTag::No);
         }
         failIfTrue(parseMode != SourceParseMode::MethodMode, "Expected a parenthesis for argument list");
 
@@ -4175,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, SuperBinding::NotNeeded, InferName::Allowed, ClassElementTag::No);
+            return context.createProperty(ident, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Shorthand), SuperBinding::NotNeeded, InferName::Allowed, ClassElementTag::No);
         }
 
         if (match(EQUAL)) // CoverInitializedName is exclusive to BindingPattern and AssignmentPattern
@@ -4199,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, SuperBinding::Needed, InferName::Allowed, ClassElementTag::No);
+            return context.createProperty(&ident, method, PropertyNode::Constant, SuperBinding::Needed, InferName::Allowed, ClassElementTag::No);
         }
         failIfTrue(parseMode != SourceParseMode::MethodMode, "Expected a parenthesis for argument list");
 
@@ -4207,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, SuperBinding::NotNeeded, ClassElementTag::No);
+        return context.createProperty(const_cast<VM&>(m_vm), m_parserArena, propertyName, node, PropertyNode::Constant, 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);
@@ -4216,7 +4216,7 @@
         if (match(OPENPAREN)) {
             auto method = parsePropertyMethod(context, ident, parseMode);
             propagateError();
-            return context.createProperty(ident, method, PropertyNode::Constant, PropertyNode::Unknown, SuperBinding::Needed, InferName::Allowed, ClassElementTag::No);
+            return context.createProperty(ident, method, PropertyNode::Constant, SuperBinding::Needed, InferName::Allowed, ClassElementTag::No);
         }
         failIfTrue(parseMode != SourceParseMode::MethodMode, "Expected a parenthesis for argument list");
 
@@ -4224,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, SuperBinding::NotNeeded, InferName::Allowed, ClassElementTag::No);
+        return context.createProperty(ident, node, PropertyNode::Constant, SuperBinding::NotNeeded, InferName::Allowed, ClassElementTag::No);
     }
     case OPENBRACKET: {
         next();
@@ -4235,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, SuperBinding::Needed, ClassElementTag::No);
+            return context.createProperty(propertyName, method, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), SuperBinding::Needed, ClassElementTag::No);
         }
         failIfTrue(parseMode != SourceParseMode::MethodMode, "Expected a parenthesis for argument list");
 
@@ -4243,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, SuperBinding::NotNeeded, ClassElementTag::No);
+        return context.createProperty(propertyName, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), SuperBinding::NotNeeded, ClassElementTag::No);
     }
     case DOTDOTDOT: {
         auto spreadLocation = m_token.m_location;
@@ -4253,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, SuperBinding::NotNeeded, ClassElementTag::No);
+        return context.createProperty(node, PropertyNode::Spread, SuperBinding::NotNeeded, ClassElementTag::No);
     }
     default:
         failIfFalse(m_token.m_type & KeywordTokenFlag, "Expected a property name");

Modified: trunk/Source/_javascript_Core/parser/SyntaxChecker.h (266263 => 266264)


--- trunk/Source/_javascript_Core/parser/SyntaxChecker.h	2020-08-27 23:48:31 UTC (rev 266263)
+++ trunk/Source/_javascript_Core/parser/SyntaxChecker.h	2020-08-28 00:27:19 UTC (rev 266264)
@@ -214,23 +214,25 @@
 
     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, SuperBinding superBinding, InferName, ClassElementTag)
+    Property createProperty(const Identifier* name, int, PropertyNode::Type type, SuperBinding superBinding, InferName, ClassElementTag tag)
     {
-        return Property(type, PropertyNode::isUnderscoreProtoSetter(m_vm, name, type, superBinding == SuperBinding::Needed));
+        bool needsSuperBinding = superBinding == SuperBinding::Needed;
+        bool isClassProperty = tag != ClassElementTag::No;
+        return Property(type, PropertyNode::isUnderscoreProtoSetter(m_vm, name, type, needsSuperBinding, isClassProperty));
     }
-    Property createProperty(int, PropertyNode::Type type, PropertyNode::PutType, SuperBinding, ClassElementTag)
+    Property createProperty(int, PropertyNode::Type type, SuperBinding, ClassElementTag)
     {
         return Property(type);
     }
-    Property createProperty(VM&, ParserArena&, double, int, PropertyNode::Type type, PropertyNode::PutType, SuperBinding, ClassElementTag)
+    Property createProperty(VM&, ParserArena&, double, int, PropertyNode::Type type, SuperBinding, ClassElementTag)
     {
         return Property(type);
     }
-    Property createProperty(int, int, PropertyNode::Type type, PropertyNode::PutType, SuperBinding, ClassElementTag)
+    Property createProperty(int, int, PropertyNode::Type type, SuperBinding, ClassElementTag)
     {
         return Property(type);
     }
-    Property createProperty(const Identifier*, int, int, PropertyNode::Type type, PropertyNode::PutType, SuperBinding, ClassElementTag)
+    Property createProperty(const Identifier*, int, int, PropertyNode::Type type, SuperBinding, ClassElementTag)
     {
         return Property(type);
     }

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp (266263 => 266264)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp	2020-08-27 23:48:31 UTC (rev 266263)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp	2020-08-28 00:27:19 UTC (rev 266264)
@@ -733,13 +733,15 @@
 EncodedJSValue JSC_HOST_CALL globalFuncSetPrototypeDirect(JSGlobalObject* globalObject, CallFrame* callFrame)
 {
     VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSValue value = callFrame->uncheckedArgument(0);
-    ASSERT(value.isObject() || value.isNull());
+    if (value.isObject() || value.isNull()) {
+        JSObject* object = asObject(callFrame->thisValue());
+        object->setPrototypeDirect(vm, value);
+    }
 
-    JSObject* object = asObject(callFrame->thisValue());
-    object->setPrototypeDirect(vm, value);
-
+    scope.assertNoException();
     return { };
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to