This commit is contained in:
Dylan Conway
2025-04-29 23:34:38 -07:00
parent 56515dc678
commit 574ff328f5
10 changed files with 462 additions and 235 deletions

View File

@@ -16,68 +16,45 @@
namespace Bun {
using namespace JSC;
template<typename T>
void callInternal(T* timeout, JSGlobalObject* globalObject)
static void call(JSGlobalObject* globalObject, JSValue timerObject, JSValue callbackValue, JSValue argumentsValue)
{
static_assert(std::is_same_v<T, WebCore::JSTimeout> || std::is_same_v<T, WebCore::JSImmediate>,
"wrong type passed to callInternal");
auto& vm = JSC::getVM(globalObject);
auto scope = DECLARE_THROW_SCOPE(vm);
JSValue callbackValue = timeout->m_callback.get();
JSCell* callbackCell = callbackValue.isCell() ? callbackValue.asCell() : nullptr;
if (!callbackCell) {
Bun__reportUnhandledError(globalObject, JSValue::encode(createNotAFunctionError(globalObject, callbackValue)));
return;
}
JSValue restoreAsyncContext {};
JSC::InternalFieldTuple* asyncContextData = nullptr;
if (auto* wrapper = jsDynamicCast<AsyncContextFrame*>(callbackCell)) {
callbackCell = wrapper->callback.get().asCell();
if (auto* wrapper = jsDynamicCast<AsyncContextFrame*>(callbackValue)) {
callbackValue = wrapper->callback.get();
asyncContextData = globalObject->m_asyncContextData.get();
restoreAsyncContext = asyncContextData->getInternalField(0);
asyncContextData->putInternalField(vm, 0, wrapper->context.get());
}
switch (callbackCell->type()) {
case JSC::JSPromiseType: {
if (auto* promise = jsDynamicCast<JSPromise*>(callbackValue)) {
// This was a Bun.sleep() call
auto promise = jsCast<JSPromise*>(callbackCell);
promise->resolve(globalObject, jsUndefined());
break;
}
default: {
auto callData = JSC::getCallData(callbackCell);
} else {
auto callData = JSC::getCallData(callbackValue);
if (callData.type == CallData::Type::None) {
Bun__reportUnhandledError(globalObject, JSValue::encode(createNotAFunctionError(globalObject, callbackValue)));
return;
}
MarkedArgumentBuffer args;
if (timeout->m_arguments) {
JSValue argumentsValue = timeout->m_arguments.get();
auto* butterfly = jsDynamicCast<JSImmutableButterfly*>(argumentsValue);
if (auto* butterfly = jsDynamicCast<JSImmutableButterfly*>(argumentsValue)) {
// If it's a JSImmutableButterfly, there is more than 1 argument.
if (butterfly) {
unsigned length = butterfly->length();
args.ensureCapacity(length);
for (unsigned i = 0; i < length; ++i) {
args.append(butterfly->get(i));
}
} else {
// Otherwise, it's a single argument.
args.append(argumentsValue);
unsigned length = butterfly->length();
args.ensureCapacity(length);
for (unsigned i = 0; i < length; ++i) {
args.append(butterfly->get(i));
}
} else if (!argumentsValue.isUndefined()) {
// Otherwise, it's a single argument.
args.append(argumentsValue);
}
JSC::profiledCall(globalObject, ProfilingReason::API, JSValue(callbackCell), JSC::getCallData(callbackCell), timeout, ArgList(args));
break;
}
JSC::profiledCall(globalObject, ProfilingReason::API, callbackValue, callData, timerObject, args);
}
if (UNLIKELY(scope.exception())) {
@@ -91,21 +68,14 @@ void callInternal(T* timeout, JSGlobalObject* globalObject)
}
}
extern "C" void Bun__JSTimeout__call(JSC::EncodedJSValue encodedTimeoutValue, JSC::JSGlobalObject* globalObject)
extern "C" void Bun__JSTimeout__call(JSGlobalObject* globalObject, EncodedJSValue timerObject, EncodedJSValue callbackValue, EncodedJSValue argumentsValue)
{
auto& vm = globalObject->vm();
if (UNLIKELY(vm.hasPendingTerminationException())) {
return;
}
JSValue timeoutValue = JSValue::decode(encodedTimeoutValue);
if (auto* timeout = jsDynamicCast<WebCore::JSTimeout*>(timeoutValue)) {
return callInternal(timeout, globalObject);
} else if (auto* immediate = jsDynamicCast<WebCore::JSImmediate*>(timeoutValue)) {
return callInternal(immediate, globalObject);
}
ASSERT_NOT_REACHED_WITH_MESSAGE("Object passed to Bun__JSTimeout__call is not a JSTimeout or a JSImmediate");
return call(globalObject, JSValue::decode(timerObject), JSValue::decode(callbackValue), JSValue::decode(argumentsValue));
}
}