diff options
author | 2023-09-27 19:17:05 -0700 | |
---|---|---|
committer | 2023-09-27 19:17:05 -0700 | |
commit | c692cbff21f442b6e10c5af5c1139d2e45d2e2a8 (patch) | |
tree | b5cb83c9cf64c6858cc4b822614c0427c9afad00 | |
parent | 7cd1dc2817158f9a27605ec5bac33575b9ef12f3 (diff) | |
download | bun-jarred/callable.tar.gz bun-jarred/callable.tar.zst bun-jarred/callable.zip |
`makeClassCallable`jarred/callable
-rw-r--r-- | src/bun.js/bindings/ZigGlobalObject.cpp | 109 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGlobalObject.h | 4 |
2 files changed, 112 insertions, 1 deletions
diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 54fb58776..1e4b08ef8 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -1579,6 +1579,98 @@ JSC_DEFINE_CUSTOM_SETTER(noop_setter, return true; } +JSC_DEFINE_HOST_FUNCTION(jsMakeClassCallableCall, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) +{ + auto& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto* constructor = callframe->thisValue().getObject(); + if (!constructor || !constructor->isConstructor()) { + throwTypeError(globalObject, scope, "call expects a constructor"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + JSValue newTarget = callframe->argument(0); + JSC::ArgList args = JSC::ArgList(callframe, 1); + RELEASE_AND_RETURN(scope, JSValue::encode(JSC::construct(globalObject, constructor, JSC::getCallData(constructor), args, newTarget))); +} + +JSC_DEFINE_HOST_FUNCTION(jsMakeClassCallableApply, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) +{ + auto& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto* constructor = callframe->thisValue().getObject(); + if (!constructor || !constructor->isConstructor()) { + throwTypeError(globalObject, scope, "apply expects a constructor"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + JSValue newTarget = callframe->argument(0); + + MarkedArgumentBuffer args; + JSValue argumentsObject = callframe->argument(1); + if (auto* array = jsDynamicCast<JSC::JSArray*>(argumentsObject)) { + JSValue thisValue = callframe->thisValue(); + + unsigned argCount = array->length(); + for (unsigned i = 0; i < argCount; i++) { + JSValue value = array->getIndex(globalObject, i); + if (UNLIKELY(scope.exception())) + return JSC::JSValue::encode(JSC::JSValue {}); + if (value.isEmpty()) + continue; + + args.append(value); + } + } + + RELEASE_AND_RETURN(scope, JSValue::encode(JSC::construct(globalObject, constructor, JSC::getCallData(constructor), args, newTarget))); +} + +JSC_DEFINE_HOST_FUNCTION(jsMakeClassCallable, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callframe)) +{ + auto* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (callframe->argumentCount() < 1) { + throwTypeError(globalObject, scope, "makeClassCallable needs 1 argument"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + auto* constructor = callframe->argument(0).getObject(); + if (!constructor || !constructor->isConstructor()) { + throwTypeError(globalObject, scope, "makeClassCallable needs a constructor"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + JSFunction* call = JSC::JSBoundFunction::create(vm, + globalObject, + globalObject->makeClassCallableCallUnbound(), + constructor, + ArgList(), 1, jsString(vm, String("call"_s))); + + JSFunction* apply = JSC::JSBoundFunction::create(vm, + globalObject, + globalObject->makeClassCallableApplyUnbound(), + constructor, + ArgList(), 1, jsString(vm, String("apply"_s))); + + constructor->putDirect( + vm, + vm.propertyNames->builtinNames().callPublicName(), + call, + JSC::PropertyAttribute::DontEnum | 0); + constructor->putDirect( + vm, + vm.propertyNames->builtinNames().applyPublicName(), + apply, + JSC::PropertyAttribute::DontEnum | 0); + + RELEASE_AND_RETURN(scope, JSC::JSValue::encode(constructor)); +} + static NeverDestroyed<const String> pathToFileURLString(MAKE_STATIC_STRING_IMPL("pathToFileURL")); static NeverDestroyed<const String> fileURLToPathString(MAKE_STATIC_STRING_IMPL("fileURLToPath")); @@ -1701,6 +1793,10 @@ JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, return JSC::JSValue::encode(obj); } + if (string == "makeClassCallable"_s) { + return JSC::JSValue::encode(JSC::JSFunction::create(vm, globalObject, 1, "makeClassCallable"_s, jsMakeClassCallable, ImplementationVisibility::Public, NoIntrinsic)); + } + if (string == "worker_threads"_s) { JSValue workerData = jsUndefined(); @@ -2766,6 +2862,16 @@ void GlobalObject::finishCreation(VM& vm) init.set(fileConstructor); }); + m_makeClassCallableCall.initLater( + [](const Initializer<JSFunction>& init) { + init.set(JSFunction::create(init.vm, init.owner, 2, "call"_s, jsMakeClassCallableCall, ImplementationVisibility::Private)); + }); + + m_makeClassCallableApply.initLater( + [](const Initializer<JSFunction>& init) { + init.set(JSFunction::create(init.vm, init.owner, 2, "apply"_s, jsMakeClassCallableApply, ImplementationVisibility::Private)); + }); + m_cryptoObject.initLater( [](const Initializer<JSObject>& init) { JSC::JSGlobalObject* globalObject = init.owner; @@ -3813,7 +3919,8 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor) thisObject->m_JSBufferSubclassStructure.visit(visitor); thisObject->m_cryptoObject.visit(visitor); thisObject->m_JSDOMFileConstructor.visit(visitor); - + thisObject->m_makeClassCallableCall.visit(visitor); + thisObject->m_makeClassCallableApply.visit(visitor); thisObject->m_requireFunctionUnbound.visit(visitor); thisObject->m_requireResolveFunctionUnbound.visit(visitor); thisObject->m_importMetaObjectStructure.visit(visitor); diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h index e27b3bffa..37e3ec1d2 100644 --- a/src/bun.js/bindings/ZigGlobalObject.h +++ b/src/bun.js/bindings/ZigGlobalObject.h @@ -353,6 +353,8 @@ public: mutable WriteBarrier<JSFunction> m_thenables[promiseFunctionsSize + 1]; mutable WriteBarrier<JSC::Unknown> m_errorConstructorPrepareStackTraceValue; + JSFunction* makeClassCallableCallUnbound() { return m_makeClassCallableCall.getInitializedOnMainThread(this); } + JSFunction* makeClassCallableApplyUnbound() { return m_makeClassCallableApply.getInitializedOnMainThread(this); } Structure* memoryFootprintStructure() { @@ -508,6 +510,8 @@ public: LazyProperty<JSGlobalObject, JSObject> m_navigatorObject; LazyProperty<JSGlobalObject, JSObject> m_performanceObject; LazyProperty<JSGlobalObject, JSObject> m_processObject; + LazyProperty<JSGlobalObject, JSFunction> m_makeClassCallableCall; + LazyProperty<JSGlobalObject, JSFunction> m_makeClassCallableApply; private: DOMGuardedObjectSet m_guardedObjects WTF_GUARDED_BY_LOCK(m_gcLock); |