Ignore:
Timestamp:
Aug 27, 2020, 5:27:19 PM (5 years ago)
Author:
Alexey Shvayka
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/JavaScriptCore:

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:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp

    r266106 r266264  
    734734{
    735735    VM& vm = globalObject->vm();
     736    auto scope = DECLARE_THROW_SCOPE(vm);
    736737
    737738    JSValue value = callFrame->uncheckedArgument(0);
    738     ASSERT(value.isObject() || value.isNull());
    739 
    740     JSObject* object = asObject(callFrame->thisValue());
    741     object->setPrototypeDirect(vm, value);
    742 
     739    if (value.isObject() || value.isNull()) {
     740        JSObject* object = asObject(callFrame->thisValue());
     741        object->setPrototypeDirect(vm, value);
     742    }
     743
     744    scope.assertNoException();
    743745    return { };
    744746}
Note: See TracChangeset for help on using the changeset viewer.