From 32f1ebbd26f3f4d1a01081bb37f64c2c9bc7f66b Mon Sep 17 00:00:00 2001 From: Seonghyun Kim Date: Thu, 19 Sep 2024 13:22:17 +0900 Subject: [PATCH] Fix bug in callConstructor with class Signed-off-by: Seonghyun Kim --- src/interpreter/ByteCodeInterpreter.cpp | 12 ++++++++---- test/cctest/testapi.cpp | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/interpreter/ByteCodeInterpreter.cpp b/src/interpreter/ByteCodeInterpreter.cpp index 3b9347d3b..8e02eb768 100644 --- a/src/interpreter/ByteCodeInterpreter.cpp +++ b/src/interpreter/ByteCodeInterpreter.cpp @@ -4165,10 +4165,14 @@ NEVER_INLINE void InterpreterSlowPath::callFunctionComplexCase(ExecutionState& s // using this value on stack is trick for callConstructor util if (stackStorage[0].isPointerValue() && stackStorage[0].asPointerValue()) { result = stackStorage[0].asObject(); - Object* proto = Object::getPrototypeFromConstructor(state, newTarget, [](ExecutionState& state, Context* constructorRealm) -> Object* { - return constructorRealm->globalObject()->objectPrototype(); - }); - result.asObject()->setPrototype(state, proto); + if (registerFile[code->m_calleeIndex].isObject() && registerFile[code->m_calleeIndex].asObject()->isScriptClassConstructorFunctionObject()) { + Object::callConstructor(state, registerFile[code->m_calleeIndex], result.asObject(), argc, argv, newTarget); + } else { + Object* proto = Object::getPrototypeFromConstructor(state, newTarget, [](ExecutionState& state, Context* constructorRealm) -> Object* { + return constructorRealm->globalObject()->objectPrototype(); + }); + result.asObject()->setPrototype(state, proto); + } } else { result = Object::construct(state, registerFile[code->m_calleeIndex], argc, argv, newTarget); } diff --git a/test/cctest/testapi.cpp b/test/cctest/testapi.cpp index 6e68fc0fb..2d48dd13f 100644 --- a/test/cctest/testapi.cpp +++ b/test/cctest/testapi.cpp @@ -693,6 +693,20 @@ TEST(FunctionObject, CallConsturctor) return ValueRef::createUndefined(); }); + + eval(g_context.get(), StringRef::createFromASCII("class callconstructortest3 extends Number { constructor() { super(); this.baseProperty = 123 } };")); + eval(g_context.get(), StringRef::createFromASCII("class callconstructortest4 extends callconstructortest3{ #pri; constructor() { super(); this.#pri = 123; } read() { return this.#pri + this.baseProperty; } }; this.testClass = callconstructortest4;")); + + Evaluator::execute(g_context.get(), [](ExecutionStateRef* state) -> ValueRef* { + auto testClass = state->context()->globalObject()->get(state, StringRef::createFromASCII("testClass")); + ObjectRef* obj = ObjectRef::create(state); + testClass->callConstructor(state, obj, 0, nullptr); + EXPECT_TRUE(obj->get(state, StringRef::createFromASCII("read"))->call(state, obj, 0, nullptr)->asNumber() == 123 * 2); + EXPECT_TRUE(obj->instanceOf(state, testClass)); + EXPECT_TRUE(obj->instanceOf(state, state->context()->globalObject()->number())); + + return ValueRef::createUndefined(); + }); } TEST(ObjectTemplate, Basic1)