diff options
author | 2023-08-19 17:46:59 -0700 | |
---|---|---|
committer | 2023-08-19 17:46:59 -0700 | |
commit | 196620183fd20ca42b363c5f947af1dc979f888f (patch) | |
tree | 2413e721e515588eb743358df6a4a4f3750572d8 /src | |
parent | 86ad0151479c96314233c2d7dfbf7ed83b57feab (diff) | |
download | bun-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.cpp | 19 | ||||
-rw-r--r-- | src/bun.js/bindings/napi.h | 14 |
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; |