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 { };
}