Title: [275439] trunk
Revision
275439
Author
[email protected]
Date
2021-04-02 14:20:45 -0700 (Fri, 02 Apr 2021)

Log Message

Reduce bytecode instruction count emitted for `class extends`
https://bugs.webkit.org/show_bug.cgi?id=223884

Reviewed by Yusuke Suzuki.

JSTests:

* ChakraCore/test/Error/validate_line_column.baseline-jsc:

Source/_javascript_Core:

This patch adds a variant of globalFuncSetPrototypeDirect() that throws on
invalid [[Prototype]] values (instead of ignoring them) and utilizes it in
ClassExprNode::emitBytecode(), removing equivalent checks.

Throwing for invalid `superclass.prototype` value after setting the [[Prototype]]
of `constructor` is unobservable because it's a newly created extensible object
and `superclass` is a proven object.

The fact that [[Prototype]] set can throw only in case of `superclass.prototype`
allows keeping descriptive error message via custom appender. To find "extends"
in a source code, ClassExprNode is made an instance of ThrowableExpressionData.

This change reduces the number of emitted bytecodes by 4, and fixes IsConstructor's
error [1] to point to correct source code location.

[1]: https://tc39.es/ecma262/#sec-runtime-semantics-classdefinitionevaluation (step 5.f)

* builtins/BuiltinNames.h:
* bytecode/LinkTimeConstant.h:
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitDirectSetPrototypeOf):
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::PropertyListNode::emitPutConstantProperty):
(JSC::ClassExprNode::emitBytecode):
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createClassExpr):
* parser/Nodes.h:
* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseClass):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createClassExpr):
* runtime/ExceptionHelpers.cpp:
(JSC::invalidPrototypeSourceAppender):
(JSC::createInvalidPrototypeError):
* runtime/ExceptionHelpers.h:
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
* runtime/JSGlobalObjectFunctions.h:

Modified Paths

Diff

Modified: trunk/JSTests/ChakraCore/test/Error/validate_line_column.baseline-jsc (275438 => 275439)


--- trunk/JSTests/ChakraCore/test/Error/validate_line_column.baseline-jsc	2021-04-02 21:10:28 UTC (rev 275438)
+++ trunk/JSTests/ChakraCore/test/Error/validate_line_column.baseline-jsc	2021-04-02 21:20:45 UTC (rev 275439)
@@ -4,7 +4,7 @@
 @validate_line_column.js:21:11
 foo@validate_line_column.js:10:17
 global code@validate_line_column.js:20:4
-@validate_line_column.js:26:7
+@validate_line_column.js:26:23
 foo@validate_line_column.js:10:17
 global code@validate_line_column.js:24:4
 @validate_line_column.js:30:14

Modified: trunk/JSTests/ChangeLog (275438 => 275439)


--- trunk/JSTests/ChangeLog	2021-04-02 21:10:28 UTC (rev 275438)
+++ trunk/JSTests/ChangeLog	2021-04-02 21:20:45 UTC (rev 275439)
@@ -1,3 +1,12 @@
+2021-04-02  Alexey Shvayka  <[email protected]>
+
+        Reduce bytecode instruction count emitted for `class extends`
+        https://bugs.webkit.org/show_bug.cgi?id=223884
+
+        Reviewed by Yusuke Suzuki.
+
+        * ChakraCore/test/Error/validate_line_column.baseline-jsc:
+
 2021-04-02  Jessica Tallon  <[email protected]>
 
         Add tests for the new type method on certain JS-API wasm objects.

Modified: trunk/Source/_javascript_Core/ChangeLog (275438 => 275439)


--- trunk/Source/_javascript_Core/ChangeLog	2021-04-02 21:10:28 UTC (rev 275438)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-04-02 21:20:45 UTC (rev 275439)
@@ -1,3 +1,52 @@
+2021-04-02  Alexey Shvayka  <[email protected]>
+
+        Reduce bytecode instruction count emitted for `class extends`
+        https://bugs.webkit.org/show_bug.cgi?id=223884
+
+        Reviewed by Yusuke Suzuki.
+
+        This patch adds a variant of globalFuncSetPrototypeDirect() that throws on
+        invalid [[Prototype]] values (instead of ignoring them) and utilizes it in
+        ClassExprNode::emitBytecode(), removing equivalent checks.
+
+        Throwing for invalid `superclass.prototype` value after setting the [[Prototype]]
+        of `constructor` is unobservable because it's a newly created extensible object
+        and `superclass` is a proven object.
+
+        The fact that [[Prototype]] set can throw only in case of `superclass.prototype`
+        allows keeping descriptive error message via custom appender. To find "extends"
+        in a source code, ClassExprNode is made an instance of ThrowableExpressionData.
+
+        This change reduces the number of emitted bytecodes by 4, and fixes IsConstructor's
+        error [1] to point to correct source code location.
+
+        [1]: https://tc39.es/ecma262/#sec-runtime-semantics-classdefinitionevaluation (step 5.f)
+
+        * builtins/BuiltinNames.h:
+        * bytecode/LinkTimeConstant.h:
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitDirectSetPrototypeOf):
+        * bytecompiler/BytecodeGenerator.h:
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::PropertyListNode::emitPutConstantProperty):
+        (JSC::ClassExprNode::emitBytecode):
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createClassExpr):
+        * parser/Nodes.h:
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseClass):
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::createClassExpr):
+        * runtime/ExceptionHelpers.cpp:
+        (JSC::invalidPrototypeSourceAppender):
+        (JSC::createInvalidPrototypeError):
+        * runtime/ExceptionHelpers.h:
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        * runtime/JSGlobalObjectFunctions.cpp:
+        (JSC::JSC_DEFINE_HOST_FUNCTION):
+        * runtime/JSGlobalObjectFunctions.h:
+
 2021-04-02  Jessica Tallon  <[email protected]>
 
         Add type method to WebAssembly.Memory, WebAssembly.Table & WebAssembly.Global objects

Modified: trunk/Source/_javascript_Core/builtins/BuiltinNames.h (275438 => 275439)


--- trunk/Source/_javascript_Core/builtins/BuiltinNames.h	2021-04-02 21:10:28 UTC (rev 275438)
+++ trunk/Source/_javascript_Core/builtins/BuiltinNames.h	2021-04-02 21:20:45 UTC (rev 275439)
@@ -144,6 +144,7 @@
     macro(setBucketNext) \
     macro(setBucketKey) \
     macro(setPrototypeDirect) \
+    macro(setPrototypeDirectOrThrow) \
     macro(regExpBuiltinExec) \
     macro(regExpMatchFast) \
     macro(regExpProtoFlagsGetter) \

Modified: trunk/Source/_javascript_Core/bytecode/LinkTimeConstant.h (275438 => 275439)


--- trunk/Source/_javascript_Core/bytecode/LinkTimeConstant.h	2021-04-02 21:10:28 UTC (rev 275438)
+++ trunk/Source/_javascript_Core/bytecode/LinkTimeConstant.h	2021-04-02 21:20:45 UTC (rev 275439)
@@ -44,6 +44,7 @@
     v(setBucketNext, nullptr) \
     v(setBucketKey, nullptr) \
     v(setPrototypeDirect, nullptr) \
+    v(setPrototypeDirectOrThrow, nullptr) \
     v(copyDataProperties, nullptr) \
     v(enqueueJob, nullptr) \
     v(makeTypeError, nullptr) \

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (275438 => 275439)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2021-04-02 21:10:28 UTC (rev 275438)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2021-04-02 21:20:45 UTC (rev 275439)
@@ -2706,16 +2706,16 @@
     return dst;
 }
 
-RegisterID* BytecodeGenerator::emitDirectSetPrototypeOf(RegisterID* base, RegisterID* prototype)
+template<InvalidPrototypeMode mode>
+RegisterID* BytecodeGenerator::emitDirectSetPrototypeOf(RegisterID* base, RegisterID* prototype, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
 {
-    RefPtr<RegisterID> setPrototypeDirect = moveLinkTimeConstant(nullptr, LinkTimeConstant::setPrototypeDirect);
+    RefPtr<RegisterID> setPrototypeDirect = moveLinkTimeConstant(nullptr, mode == InvalidPrototypeMode::Throw ? LinkTimeConstant::setPrototypeDirectOrThrow : LinkTimeConstant::setPrototypeDirect);
 
     CallArguments args(*this, nullptr, 1);
     move(args.thisRegister(), base);
     move(args.argumentRegister(0), prototype);
 
-    JSTextPosition position;
-    emitCall(newTemporary(), setPrototypeDirect.get(), NoExpectedFunction, args, position, position, position, DebuggableCall::No);
+    emitCall(newTemporary(), setPrototypeDirect.get(), NoExpectedFunction, args, divot, divotStart, divotEnd, DebuggableCall::No);
     return base;
 }
 

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (275438 => 275439)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2021-04-02 21:10:28 UTC (rev 275438)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2021-04-02 21:20:45 UTC (rev 275439)
@@ -74,6 +74,7 @@
 
     enum class DebuggableCall { Yes, No };
     enum class ThisResolutionType { Local, Scoped };
+    enum class InvalidPrototypeMode : uint8_t { Throw, Ignore };
     enum class LinkTimeConstant : int32_t;
     
     class CallArguments {
@@ -814,7 +815,9 @@
         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* base, RegisterID* prototype);
+
+        template<InvalidPrototypeMode>
+        RegisterID* emitDirectSetPrototypeOf(RegisterID* base, RegisterID* prototype, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
         RegisterID* emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
         RegisterID* emitPutByVal(RegisterID* base, RegisterID* thisValue, RegisterID* property, RegisterID* value);
         RegisterID* emitDirectPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (275438 => 275439)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2021-04-02 21:10:28 UTC (rev 275438)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2021-04-02 21:20:45 UTC (rev 275439)
@@ -817,7 +817,7 @@
 
     if (PropertyNode::isUnderscoreProtoSetter(generator.vm(), node)) {
         RefPtr<RegisterID> prototype = generator.emitNode(node.m_assign);
-        generator.emitDirectSetPrototypeOf(newObj, prototype.get());
+        generator.emitDirectSetPrototypeOf<InvalidPrototypeMode::Ignore>(newObj, prototype.get(), m_position, m_position, m_position);
         return;
     }
 
@@ -5211,19 +5211,14 @@
 
         Ref<Label> superclassIsConstructorLabel = generator.newLabel();
         generator.emitJumpIfTrue(generator.emitIsConstructor(generator.newTemporary(), superclass.get()), superclassIsConstructorLabel.get());
+        generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
         generator.emitThrowTypeError("The superclass is not a constructor."_s);
         generator.emitLabel(superclassIsConstructorLabel.get());
         generator.emitGetById(protoParent.get(), superclass.get(), generator.propertyNames().prototype);
 
-        Ref<Label> protoParentIsObjectOrNullLabel = generator.newLabel();
-        generator.emitJumpIfTrue(generator.emitIsObject(generator.newTemporary(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
-        generator.emitJumpIfTrue(generator.emitIsNull(generator.newTemporary(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
-        generator.emitThrowTypeError("The value of the superclass's prototype property is not an object or null."_s);
-        generator.emitLabel(protoParentIsObjectOrNullLabel.get());
-
-        generator.emitDirectSetPrototypeOf(constructor.get(), superclass.get());
+        generator.emitDirectSetPrototypeOf<InvalidPrototypeMode::Throw>(constructor.get(), superclass.get(), m_position, m_position, m_position); // never actually throws
         generator.emitLabel(superclassIsNullLabel.get());
-        generator.emitDirectSetPrototypeOf(prototype.get(), protoParent.get());
+        generator.emitDirectSetPrototypeOf<InvalidPrototypeMode::Throw>(prototype.get(), protoParent.get(), divot(), divotStart(), divotEnd());
     }
 
     if (needsHomeObject)

Modified: trunk/Source/_javascript_Core/parser/ASTBuilder.h (275438 => 275439)


--- trunk/Source/_javascript_Core/parser/ASTBuilder.h	2021-04-02 21:10:28 UTC (rev 275438)
+++ trunk/Source/_javascript_Core/parser/ASTBuilder.h	2021-04-02 21:20:45 UTC (rev 275439)
@@ -412,10 +412,12 @@
     }
 
     ClassExprNode* createClassExpr(const JSTokenLocation& location, const ParserClassInfo<ASTBuilder>& classInfo, VariableEnvironment& classEnvironment, ExpressionNode* constructor,
-        ExpressionNode* parentClass, PropertyListNode* classElements)
+        ExpressionNode* parentClass, PropertyListNode* classElements, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end)
     {
         SourceCode source = m_sourceCode->subExpression(classInfo.startOffset, classInfo.endOffset, classInfo.startLine, classInfo.startColumn);
-        return new (m_parserArena) ClassExprNode(location, *classInfo.className, source, classEnvironment, constructor, parentClass, classElements);
+        ClassExprNode* node = new (m_parserArena) ClassExprNode(location, *classInfo.className, source, classEnvironment, constructor, parentClass, classElements);
+        setExceptionLocation(node, start, divot, end);
+        return node;
     }
 
     ExpressionNode* createFunctionExpr(const JSTokenLocation& location, const ParserFunctionInfo<ASTBuilder>& functionInfo)

Modified: trunk/Source/_javascript_Core/parser/Nodes.h (275438 => 275439)


--- trunk/Source/_javascript_Core/parser/Nodes.h	2021-04-02 21:10:28 UTC (rev 275438)
+++ trunk/Source/_javascript_Core/parser/Nodes.h	2021-04-02 21:20:45 UTC (rev 275439)
@@ -2356,7 +2356,7 @@
         Type m_type;
     };
 
-    class ClassExprNode final : public ExpressionNode, public VariableEnvironmentNode {
+    class ClassExprNode final : public ExpressionNode, public ThrowableExpressionData, 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 (275438 => 275439)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2021-04-02 21:10:28 UTC (rev 275438)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2021-04-02 21:20:45 UTC (rev 275439)
@@ -2886,6 +2886,7 @@
 template <class TreeBuilder> TreeClassExpression Parser<LexerType>::parseClass(TreeBuilder& context, FunctionNameRequirements requirements, ParserClassInfo<TreeBuilder>& info)
 {
     ASSERT(match(CLASSTOKEN));
+    JSTextPosition start = tokenStartPosition();
     JSTokenLocation location(tokenLocation());
     info.startLine = location.line;
     info.startColumn = tokenColumn();
@@ -2915,8 +2916,10 @@
     }
     ASSERT(info.className);
 
+    JSTextPosition divot = start;
     TreeExpression parentClass = 0;
     if (consume(EXTENDS)) {
+        divot = tokenStartPosition();
         parentClass = parseMemberExpression(context);
         failIfFalse(parentClass, "Cannot parse the parent class name");
     }
@@ -2923,6 +2926,7 @@
     classScope->setIsClassScope();
     const ConstructorKind constructorKind = parentClass ? ConstructorKind::Extends : ConstructorKind::Base;
 
+    JSTextPosition classHeadEnd = lastTokenEndPosition();
     consumeOrFail(OPENBRACE, "Expected opening '{' at the start of a class body");
 
     TreeExpression constructor = 0;
@@ -3170,7 +3174,7 @@
         semanticFailIfFalse(copyUndeclaredPrivateNamesToOuterScope(), "Cannot reference undeclared private names");
     }
 
-    auto classExpression = context.createClassExpr(location, info, classScope->finalizeLexicalEnvironment(), constructor, parentClass, classElements);
+    auto classExpression = context.createClassExpr(location, info, classScope->finalizeLexicalEnvironment(), constructor, parentClass, classElements, start, divot, classHeadEnd);
     popScope(classScope, TreeBuilder::NeedsFreeVariableInfo);
     return classExpression;
 }

Modified: trunk/Source/_javascript_Core/parser/SyntaxChecker.h (275438 => 275439)


--- trunk/Source/_javascript_Core/parser/SyntaxChecker.h	2021-04-02 21:10:28 UTC (rev 275438)
+++ trunk/Source/_javascript_Core/parser/SyntaxChecker.h	2021-04-02 21:20:45 UTC (rev 275439)
@@ -191,7 +191,7 @@
     ExpressionType createYield(const JSTokenLocation&) { return YieldExpr; }
     ExpressionType createYield(const JSTokenLocation&, ExpressionType, bool, int, int, int) { return YieldExpr; }
     ExpressionType createAwait(const JSTokenLocation&, ExpressionType, int, int, int) { return AwaitExpr; }
-    ClassExpression createClassExpr(const JSTokenLocation&, const ParserClassInfo<SyntaxChecker>&, VariableEnvironment&, ExpressionType, ExpressionType, PropertyList) { return ClassExpr; }
+    ClassExpression createClassExpr(const JSTokenLocation&, const ParserClassInfo<SyntaxChecker>&, VariableEnvironment&, ExpressionType, ExpressionType, PropertyList, int, int, int) { return ClassExpr; }
     ExpressionType createFunctionExpr(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }
     ExpressionType createGeneratorFunctionBody(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&, const Identifier&) { return FunctionExpr; }
     ExpressionType createAsyncFunctionBody(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; }

Modified: trunk/Source/_javascript_Core/runtime/ExceptionHelpers.cpp (275438 => 275439)


--- trunk/Source/_javascript_Core/runtime/ExceptionHelpers.cpp	2021-04-02 21:10:28 UTC (rev 275438)
+++ trunk/Source/_javascript_Core/runtime/ExceptionHelpers.cpp	2021-04-02 21:20:45 UTC (rev 275439)
@@ -262,6 +262,18 @@
     return invalidParameterInstanceofSourceAppender("[Symbol.hasInstance] is not a function, undefined, or null"_s, originalMessage, sourceText, runtimeType, occurrence);
 }
 
+static String invalidPrototypeSourceAppender(const String& originalMessage, const String& sourceText, RuntimeType, ErrorInstance::SourceTextWhereErrorOccurred occurrence)
+{
+    if (occurrence == ErrorInstance::FoundApproximateSource)
+        return defaultApproximateSourceError(originalMessage, sourceText);
+
+    auto extendsIndex = sourceText.reverseFind("extends");
+    if (extendsIndex == notFound || sourceText.find("extends") != extendsIndex)
+        return makeString(originalMessage, " (evaluating '", sourceText, "')");
+
+    return "The value of the superclass's prototype property is not an object or null."_s;
+}
+
 JSObject* createError(JSGlobalObject* globalObject, JSValue value, const String& message, ErrorInstance::SourceAppender appender)
 {
     VM& vm = globalObject->vm();
@@ -321,6 +333,11 @@
     return createError(globalObject, value, "is not an object"_s, defaultSourceAppender);
 }
 
+JSObject* createInvalidPrototypeError(JSGlobalObject* globalObject, JSValue value)
+{
+    return createError(globalObject, value, "is not an object or null"_s, invalidPrototypeSourceAppender);
+}
+
 JSObject* createErrorForInvalidGlobalAssignment(JSGlobalObject* globalObject, const String& propertyName)
 {
     return createReferenceError(globalObject, makeString("Strict mode forbids implicit creation of global property '", propertyName, '\''));

Modified: trunk/Source/_javascript_Core/runtime/ExceptionHelpers.h (275438 => 275439)


--- trunk/Source/_javascript_Core/runtime/ExceptionHelpers.h	2021-04-02 21:10:28 UTC (rev 275438)
+++ trunk/Source/_javascript_Core/runtime/ExceptionHelpers.h	2021-04-02 21:20:45 UTC (rev 275439)
@@ -52,6 +52,7 @@
 JSObject* createInvalidInstanceofParameterErrorHasInstanceValueNotFunction(JSGlobalObject*, JSValue);
 JSObject* createNotAConstructorError(JSGlobalObject*, JSValue);
 JSObject* createNotAFunctionError(JSGlobalObject*, JSValue);
+JSObject* createInvalidPrototypeError(JSGlobalObject*, JSValue);
 JSObject* createErrorForInvalidGlobalAssignment(JSGlobalObject*, const String&);
 JSObject* createInvalidPrivateNameError(JSGlobalObject*);
 JSObject* createRedefinedPrivateNameError(JSGlobalObject*);

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (275438 => 275439)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2021-04-02 21:10:28 UTC (rev 275438)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2021-04-02 21:20:45 UTC (rev 275439)
@@ -1299,6 +1299,9 @@
     m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::setPrototypeDirect)].initLater([] (const Initializer<JSCell>& init) {
             init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 2, String(), globalFuncSetPrototypeDirect));
         });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::setPrototypeDirectOrThrow)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 2, String(), globalFuncSetPrototypeDirectOrThrow));
+        });
 
     // RegExp.prototype helpers.
     m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::regExpCreate)].initLater([] (const Initializer<JSCell>& init) {

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp (275438 => 275439)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp	2021-04-02 21:10:28 UTC (rev 275438)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp	2021-04-02 21:20:45 UTC (rev 275439)
@@ -734,7 +734,6 @@
 JSC_DEFINE_HOST_FUNCTION(globalFuncSetPrototypeDirect, (JSGlobalObject* globalObject, CallFrame* callFrame))
 {
     VM& vm = globalObject->vm();
-    auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSValue value = callFrame->uncheckedArgument(0);
     if (value.isObject() || value.isNull()) {
@@ -742,10 +741,24 @@
         object->setPrototypeDirect(vm, value);
     }
 
-    scope.assertNoException();
-    return { };
+    return JSValue::encode(jsUndefined());
 }
 
+JSC_DEFINE_HOST_FUNCTION(globalFuncSetPrototypeDirectOrThrow, (JSGlobalObject* globalObject, CallFrame* callFrame))
+{
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    JSValue value = callFrame->uncheckedArgument(0);
+    if (!value.isObject() && !value.isNull())
+        return throwVMError(globalObject, scope, createInvalidPrototypeError(globalObject, value));
+
+    JSObject* object = asObject(callFrame->thisValue());
+    object->setPrototypeDirect(vm, value);
+
+    return JSValue::encode(jsUndefined());
+}
+
 JSC_DEFINE_HOST_FUNCTION(globalFuncHostPromiseRejectionTracker, (JSGlobalObject* globalObject, CallFrame* callFrame))
 {
     VM& vm = globalObject->vm();

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.h (275438 => 275439)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.h	2021-04-02 21:10:28 UTC (rev 275438)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.h	2021-04-02 21:20:45 UTC (rev 275439)
@@ -52,6 +52,7 @@
 JSC_DECLARE_HOST_FUNCTION(globalFuncProtoGetter);
 JSC_DECLARE_HOST_FUNCTION(globalFuncProtoSetter);
 JSC_DECLARE_HOST_FUNCTION(globalFuncSetPrototypeDirect);
+JSC_DECLARE_HOST_FUNCTION(globalFuncSetPrototypeDirectOrThrow);
 JSC_DECLARE_HOST_FUNCTION(globalFuncHostPromiseRejectionTracker);
 JSC_DECLARE_HOST_FUNCTION(globalFuncBuiltinLog);
 JSC_DECLARE_HOST_FUNCTION(globalFuncBuiltinDescribe);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to