aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2023-08-19 17:46:59 -0700
committerGravatar GitHub <noreply@github.com> 2023-08-19 17:46:59 -0700
commit196620183fd20ca42b363c5f947af1dc979f888f (patch)
tree2413e721e515588eb743358df6a4a4f3750572d8 /src
parent86ad0151479c96314233c2d7dfbf7ed83b57feab (diff)
downloadbun-196620183fd20ca42b363c5f947af1dc979f888f.tar.gz
bun-196620183fd20ca42b363c5f947af1dc979f888f.tar.zst
bun-196620183fd20ca42b363c5f947af1dc979f888f.zip
Fixes #172 (#4220)
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Diffstat (limited to 'src')
-rw-r--r--src/bun.js/bindings/napi.cpp19
-rw-r--r--src/bun.js/bindings/napi.h14
2 files changed, 24 insertions, 9 deletions
diff --git a/src/bun.js/bindings/napi.cpp b/src/bun.js/bindings/napi.cpp
index d532e5444..237f3d554 100644
--- a/src/bun.js/bindings/napi.cpp
+++ b/src/bun.js/bindings/napi.cpp
@@ -1244,18 +1244,30 @@ JSC_DEFINE_HOST_FUNCTION(NapiClass_ConstructorFunction,
{
JSC::VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
-
+ JSObject* constructorTarget = asObject(callFrame->jsCallee());
JSObject* newTarget = asObject(callFrame->newTarget());
+ NapiClass* napi = jsDynamicCast<NapiClass*>(constructorTarget);
+ while (!napi && constructorTarget) {
+ constructorTarget = constructorTarget->getPrototypeDirect().getObject();
+ napi = jsDynamicCast<NapiClass*>(constructorTarget);
+ }
- NapiClass* napi = jsDynamicCast<NapiClass*>(newTarget);
if (UNLIKELY(!napi)) {
JSC::throwVMError(globalObject, scope, JSC::createTypeError(globalObject, "NapiClass constructor called on an object that is not a NapiClass"_s));
return JSC::JSValue::encode(JSC::jsUndefined());
}
- NapiPrototype* prototype = JSC::jsDynamicCast<NapiPrototype*>(napi->getDirect(vm, vm.propertyNames->prototype));
+ NapiPrototype* prototype = JSC::jsDynamicCast<NapiPrototype*>(napi->getIfPropertyExists(globalObject, vm.propertyNames->prototype));
+ RETURN_IF_EXCEPTION(scope, {});
+
+ if (!prototype) {
+ JSC::throwVMError(globalObject, scope, JSC::createTypeError(globalObject, "NapiClass constructor is missing the prototype"_s));
+ return JSC::JSValue::encode(JSC::jsUndefined());
+ }
+ auto* subclass = prototype->subclass(globalObject, newTarget);
RETURN_IF_EXCEPTION(scope, {});
+ callFrame->setThisValue(subclass);
size_t count = callFrame->argumentCount();
MarkedArgumentBuffer args;
@@ -1266,7 +1278,6 @@ JSC_DEFINE_HOST_FUNCTION(NapiClass_ConstructorFunction,
}
}
- callFrame->setThisValue(prototype->subclass(newTarget));
napi->constructor()(globalObject, callFrame);
RETURN_IF_EXCEPTION(scope, {});
diff --git a/src/bun.js/bindings/napi.h b/src/bun.js/bindings/napi.h
index 550803963..b157c4367 100644
--- a/src/bun.js/bindings/napi.h
+++ b/src/bun.js/bindings/napi.h
@@ -213,15 +213,19 @@ public:
return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
}
- NapiPrototype* subclass(JSC::JSObject* newTarget)
+ NapiPrototype* subclass(JSC::JSGlobalObject* globalObject, JSC::JSObject* newTarget)
{
auto& vm = this->vm();
- auto* structure = InternalFunction::createSubclassStructure(globalObject(),
- newTarget,
- this->structure());
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ auto* targetFunction = jsCast<JSFunction*>(newTarget);
+ FunctionRareData* rareData = targetFunction->ensureRareData(vm);
+ auto* prototype = newTarget->get(globalObject, vm.propertyNames->prototype).getObject();
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ auto* structure = rareData->createInternalFunctionAllocationStructureFromBase(vm, globalObject, prototype, this->structure());
+ RETURN_IF_EXCEPTION(scope, nullptr);
NapiPrototype* footprint = new (NotNull, allocateCell<NapiPrototype>(vm)) NapiPrototype(vm, structure);
footprint->finishCreation(vm);
- return footprint;
+ RELEASE_AND_RETURN(scope, footprint);
}
NapiRef* napiRef = nullptr;