diff --git a/.buildkite/ci.mjs b/.buildkite/ci.mjs index 54bc00679a..4a71337f8a 100755 --- a/.buildkite/ci.mjs +++ b/.buildkite/ci.mjs @@ -572,6 +572,7 @@ function getTestBunStep(platform, options, testOptions = {}) { if (buildId) { args.push(`--build-id=${buildId}`); } + if (testFiles) { args.push(...testFiles.map(testFile => `--include=${testFile}`)); } diff --git a/cmake/tools/SetupWebKit.cmake b/cmake/tools/SetupWebKit.cmake index aa07c060ec..6ff1af55d8 100644 --- a/cmake/tools/SetupWebKit.cmake +++ b/cmake/tools/SetupWebKit.cmake @@ -2,7 +2,7 @@ option(WEBKIT_VERSION "The version of WebKit to use") option(WEBKIT_LOCAL "If a local version of WebKit should be used instead of downloading") if(NOT WEBKIT_VERSION) - set(WEBKIT_VERSION 6d0f3aac0b817cc01a846b3754b21271adedac12) + set(WEBKIT_VERSION 8400ec68b2649d7b95f10576ad648c3aa8a92b77) endif() string(SUBSTRING ${WEBKIT_VERSION} 0 16 WEBKIT_VERSION_PREFIX) diff --git a/src/ast/Macro.zig b/src/ast/Macro.zig index 764f692178..49213c8c55 100644 --- a/src/ast/Macro.zig +++ b/src/ast/Macro.zig @@ -480,7 +480,7 @@ pub const Runner = struct { this.macro.vm.waitForPromise(promise); const promise_result = promise.result(this.macro.vm.jsc_vm); - const rejected = promise.status(this.macro.vm.jsc_vm) == .rejected; + const rejected = promise.status() == .rejected; if (promise_result.isUndefined() and this.is_top_level) { this.is_top_level = false; diff --git a/src/bake/BakeGlobalObject.cpp b/src/bake/BakeGlobalObject.cpp index c48f2af84e..f7ca1b4231 100644 --- a/src/bake/BakeGlobalObject.cpp +++ b/src/bake/BakeGlobalObject.cpp @@ -36,7 +36,7 @@ bakeModuleLoaderImportModule(JSC::JSGlobalObject* global, if (!keyString) { auto promise = JSC::JSInternalPromise::create(vm, global->internalPromiseStructure()); - promise->reject(global, JSC::createError(global, "import() requires a string"_s)); + promise->reject(vm, global, JSC::createError(global, "import() requires a string"_s)); return promise; } diff --git a/src/bake/production.zig b/src/bake/production.zig index 1efe4bdcd9..ffed2b5127 100644 --- a/src/bake/production.zig +++ b/src/bake/production.zig @@ -697,7 +697,7 @@ pub fn buildWithVm(ctx: bun.cli.Command.Context, cwd: []const u8, vm: *VirtualMa route_param_info, route_style_references, ); - render_promise.setHandled(vm.jsc_vm); + render_promise.setHandled(); vm.waitForPromise(.{ .normal = render_promise }); switch (render_promise.unwrap(vm.jsc_vm, .mark_handled)) { .pending => unreachable, diff --git a/src/bun.js.zig b/src/bun.js.zig index 0145b5420a..bcd1af82d4 100644 --- a/src/bun.js.zig +++ b/src/bun.js.zig @@ -350,8 +350,8 @@ pub const Run = struct { var printed_sourcemap_warning_and_version = false; if (vm.loadEntryPoint(this.entry_path)) |promise| { - if (promise.status(vm.global.vm()) == .rejected) { - const handled = vm.uncaughtException(vm.global, promise.result(vm.global.vm()), true); + if (promise.status() == .rejected) { + const handled = vm.uncaughtException(vm.global, promise.result(), true); promise.setHandled(vm.global.vm()); if (vm.hot_reload != .none or handled) { @@ -375,7 +375,7 @@ pub const Run = struct { } } - _ = promise.result(vm.global.vm()); + _ = promise.result(); if (vm.log.msgs.items.len > 0) { dumpBuildError(vm); @@ -445,7 +445,7 @@ pub const Run = struct { const to_print = brk: { const result: jsc.JSValue = vm.entry_point_result.value.get() orelse .js_undefined; if (result.asAnyPromise()) |promise| { - switch (promise.status(vm.jsc_vm)) { + switch (promise.status()) { .pending => { result.then2(vm.global, .js_undefined, Bun__onResolveEntryPointResult, Bun__onRejectEntryPointResult) catch {}; // TODO: properly propagate exception upwards diff --git a/src/bun.js/ConsoleObject.zig b/src/bun.js/ConsoleObject.zig index b9a24edf18..f9d540ed11 100644 --- a/src/bun.js/ConsoleObject.zig +++ b/src/bun.js/ConsoleObject.zig @@ -2703,7 +2703,7 @@ pub const Formatter = struct { writer.writeAll("Promise { " ++ comptime Output.prettyFmt("", enable_ansi_colors)); - switch (JSPromise.status(@as(*JSPromise, @ptrCast(value.asObjectRef().?)), this.globalThis.vm())) { + switch (JSPromise.status(@as(*JSPromise, @ptrCast(value.asObjectRef().?)))) { .pending => writer.writeAll(""), .fulfilled => writer.writeAll(""), .rejected => writer.writeAll(""), diff --git a/src/bun.js/VirtualMachine.zig b/src/bun.js/VirtualMachine.zig index 1f7111f2d5..e73dfa8ec5 100644 --- a/src/bun.js/VirtualMachine.zig +++ b/src/bun.js/VirtualMachine.zig @@ -683,8 +683,8 @@ pub fn reportExceptionInHotReloadedModuleIfNeeded(this: *jsc.VirtualMachine) voi defer this.addMainToWatcherIfNeeded(); var promise = this.pending_internal_promise orelse return; - if (promise.status(this.global.vm()) == .rejected and !promise.isHandled(this.global.vm())) { - this.unhandledRejection(this.global, promise.result(this.global.vm()), promise.asValue()); + if (promise.status() == .rejected and !promise.isHandled()) { + this.unhandledRejection(this.global, promise.result(), promise.asValue()); promise.setHandled(this.global.vm()); } } @@ -2083,12 +2083,12 @@ fn loadPreloads(this: *VirtualMachine) !?*JSInternalPromise { // pending_internal_promise can change if hot module reloading is enabled if (this.isWatcherEnabled()) { this.eventLoop().performGC(); - switch (this.pending_internal_promise.?.status(this.global.vm())) { + switch (this.pending_internal_promise.?.status()) { .pending => { - while (this.pending_internal_promise.?.status(this.global.vm()) == .pending) { + while (this.pending_internal_promise.?.status() == .pending) { this.eventLoop().tick(); - if (this.pending_internal_promise.?.status(this.global.vm()) == .pending) { + if (this.pending_internal_promise.?.status() == .pending) { this.eventLoop().autoTick(); } } @@ -2102,7 +2102,7 @@ fn loadPreloads(this: *VirtualMachine) !?*JSInternalPromise { }); } - if (promise.status(this.global.vm()) == .rejected) + if (promise.status() == .rejected) return promise; } @@ -2245,12 +2245,12 @@ pub fn loadEntryPointForTestRunner(this: *VirtualMachine, entry_path: string) an // pending_internal_promise can change if hot module reloading is enabled if (this.isWatcherEnabled()) { this.eventLoop().performGC(); - switch (this.pending_internal_promise.?.status(this.global.vm())) { + switch (this.pending_internal_promise.?.status()) { .pending => { - while (this.pending_internal_promise.?.status(this.global.vm()) == .pending) { + while (this.pending_internal_promise.?.status() == .pending) { this.eventLoop().tick(); - if (this.pending_internal_promise.?.status(this.global.vm()) == .pending) { + if (this.pending_internal_promise.?.status() == .pending) { this.eventLoop().autoTick(); } } @@ -2258,7 +2258,7 @@ pub fn loadEntryPointForTestRunner(this: *VirtualMachine, entry_path: string) an else => {}, } } else { - if (promise.status(this.global.vm()) == .rejected) { + if (promise.status() == .rejected) { return promise; } @@ -2277,12 +2277,12 @@ pub fn loadEntryPoint(this: *VirtualMachine, entry_path: string) anyerror!*JSInt // pending_internal_promise can change if hot module reloading is enabled if (this.isWatcherEnabled()) { this.eventLoop().performGC(); - switch (this.pending_internal_promise.?.status(this.global.vm())) { + switch (this.pending_internal_promise.?.status()) { .pending => { - while (this.pending_internal_promise.?.status(this.global.vm()) == .pending) { + while (this.pending_internal_promise.?.status() == .pending) { this.eventLoop().tick(); - if (this.pending_internal_promise.?.status(this.global.vm()) == .pending) { + if (this.pending_internal_promise.?.status() == .pending) { this.eventLoop().autoTick(); } } @@ -2290,7 +2290,7 @@ pub fn loadEntryPoint(this: *VirtualMachine, entry_path: string) anyerror!*JSInt else => {}, } } else { - if (promise.status(this.global.vm()) == .rejected) { + if (promise.status() == .rejected) { return promise; } diff --git a/src/bun.js/api/html_rewriter.zig b/src/bun.js/api/html_rewriter.zig index 259abc74f1..56f534720d 100644 --- a/src/bun.js/api/html_rewriter.zig +++ b/src/bun.js/api/html_rewriter.zig @@ -960,7 +960,7 @@ fn HandlerCallback( if (result.asAnyPromise()) |promise| { this.global.bunVM().waitForPromise(promise); - const fail = promise.status(this.global.vm()) == .rejected; + const fail = promise.status() == .rejected; if (fail) { this.global.bunVM().unhandledRejection(this.global, promise.result(this.global.vm()), promise.asValue()); } diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index 7924f5cea3..ec9c36698b 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -394,7 +394,7 @@ const ServePlugins = struct { if (!result.isEmptyOrUndefinedOrNull()) { // handle the case where js returns a promise if (result.asAnyPromise()) |promise| { - switch (promise.status(global.vm())) { + switch (promise.status()) { // promise not fulfilled yet .pending => { this.ref(); @@ -1919,13 +1919,13 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d } if (result.asAnyPromise()) |promise| { - if (promise.status(globalThis.vm()) == .pending) { + if (promise.status() == .pending) { strong_promise.set(globalThis, result); needs_to_drain = false; vm.drainMicrotasks(); } - switch (promise.status(globalThis.vm())) { + switch (promise.status()) { .fulfilled => { globalThis.handleRejectedPromises(); break :brk .{ .success = {} }; diff --git a/src/bun.js/api/server/RequestContext.zig b/src/bun.js/api/server/RequestContext.zig index 8764b3e49c..282c90a3ad 100644 --- a/src/bun.js/api/server/RequestContext.zig +++ b/src/bun.js/api/server/RequestContext.zig @@ -1201,7 +1201,7 @@ pub fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, streamLog("returned a promise", .{}); this.drainMicrotasks(); - switch (promise.status(globalThis.vm())) { + switch (promise.status()) { .pending => { streamLog("promise still Pending", .{}); if (!this.flags.has_written_status) { diff --git a/src/bun.js/api/server/ServerWebSocket.zig b/src/bun.js/api/server/ServerWebSocket.zig index 6bdac151e2..b885878409 100644 --- a/src/bun.js/api/server/ServerWebSocket.zig +++ b/src/bun.js/api/server/ServerWebSocket.zig @@ -167,7 +167,7 @@ pub fn onMessage( } if (result.asAnyPromise()) |promise| { - switch (promise.status(globalObject.vm())) { + switch (promise.status()) { .rejected => { _ = promise.result(globalObject.vm()); return; diff --git a/src/bun.js/bindings/AnyPromise.zig b/src/bun.js/bindings/AnyPromise.zig index efa9a23f36..9475b69cce 100644 --- a/src/bun.js/bindings/AnyPromise.zig +++ b/src/bun.js/bindings/AnyPromise.zig @@ -7,24 +7,26 @@ pub const AnyPromise = union(enum) { inline else => |promise| promise.unwrap(vm, mode), }; } - pub fn status(this: AnyPromise, vm: *VM) JSPromise.Status { + pub fn status(this: AnyPromise) JSPromise.Status { return switch (this) { - inline else => |promise| promise.status(vm), + inline else => |promise| promise.status(), }; } pub fn result(this: AnyPromise, vm: *VM) JSValue { return switch (this) { - inline else => |promise| promise.result(vm), + .normal => |promise| promise.result(vm), + .internal => |promise| promise.result(), }; } - pub fn isHandled(this: AnyPromise, vm: *VM) bool { + pub fn isHandled(this: AnyPromise) bool { return switch (this) { - inline else => |promise| promise.isHandled(vm), + inline else => |promise| promise.isHandled(), }; } pub fn setHandled(this: AnyPromise, vm: *VM) void { switch (this) { - inline else => |promise| promise.setHandled(vm), + .normal => |promise| promise.setHandled(), + .internal => |promise| promise.setHandled(vm), } } diff --git a/src/bun.js/bindings/BunDebugger.cpp b/src/bun.js/bindings/BunDebugger.cpp index 0dd40e4822..00ee9499e9 100644 --- a/src/bun.js/bindings/BunDebugger.cpp +++ b/src/bun.js/bindings/BunDebugger.cpp @@ -110,13 +110,13 @@ public: if (!hasConnected) { hasConnected = true; globalObject->inspectorController().registerAlternateAgent( - WTF::makeUnique(*globalObject)); + WTF::makeUniqueRef(*globalObject)); globalObject->inspectorController().registerAlternateAgent( - WTF::makeUnique(*globalObject)); + WTF::makeUniqueRef(*globalObject)); globalObject->inspectorController().registerAlternateAgent( - WTF::makeUnique(*globalObject)); + WTF::makeUniqueRef(*globalObject)); globalObject->inspectorController().registerAlternateAgent( - WTF::makeUnique(*globalObject)); + WTF::makeUniqueRef(*globalObject)); } this->hasEverConnected = true; diff --git a/src/bun.js/bindings/BunInjectedScriptHost.cpp b/src/bun.js/bindings/BunInjectedScriptHost.cpp index 8cda82b022..7141083305 100644 --- a/src/bun.js/bindings/BunInjectedScriptHost.cpp +++ b/src/bun.js/bindings/BunInjectedScriptHost.cpp @@ -104,7 +104,7 @@ static JSValue constructDataProperties(VM& vm, JSGlobalObject* exec, JSArray* ar return value; auto* object = asObject(value); - PropertyNameArray propertyNames(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); + PropertyNameArrayBuilder propertyNames(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); object->getPropertyNames(exec, propertyNames, DontEnumPropertiesMode::Exclude); RETURN_IF_EXCEPTION(scope, {}); unsigned i = 0; diff --git a/src/bun.js/bindings/BunObject.cpp b/src/bun.js/bindings/BunObject.cpp index 78a0c42406..3f83574572 100644 --- a/src/bun.js/bindings/BunObject.cpp +++ b/src/bun.js/bindings/BunObject.cpp @@ -939,7 +939,7 @@ static void exportBunObject(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC: exportNames.reserveCapacity(std::size(bunObjectTableValues) + 1); exportValues.ensureCapacity(std::size(bunObjectTableValues) + 1); - PropertyNameArray propertyNames(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); + PropertyNameArrayBuilder propertyNames(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); auto scope = DECLARE_THROW_SCOPE(vm); object->getOwnNonIndexPropertyNames(globalObject, propertyNames, DontEnumPropertiesMode::Exclude); RETURN_IF_EXCEPTION(scope, void()); diff --git a/src/bun.js/bindings/BunPlugin.cpp b/src/bun.js/bindings/BunPlugin.cpp index d3617b677f..94bc835023 100644 --- a/src/bun.js/bindings/BunPlugin.cpp +++ b/src/bun.js/bindings/BunPlugin.cpp @@ -596,15 +596,15 @@ extern "C" JSC_DEFINE_HOST_FUNCTION(JSMock__jsModuleMock, (JSC::JSGlobalObject * if (result && result.isObject()) { while (JSC::JSPromise* promise = jsDynamicCast(result)) { - switch (promise->status(vm)) { + switch (promise->status()) { case JSC::JSPromise::Status::Rejected: { - result = promise->result(vm); + result = promise->result(); scope.throwException(globalObject, result); return {}; break; } case JSC::JSPromise::Status::Fulfilled: { - result = promise->result(vm); + result = promise->result(); break; } // TODO: blocking wait for promise @@ -640,7 +640,7 @@ extern "C" JSC_DEFINE_HOST_FUNCTION(JSMock__jsModuleMock, (JSC::JSGlobalObject * removeFromESM = false; if (object) { - JSC::PropertyNameArray names(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); + JSC::PropertyNameArrayBuilder names(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); JSObject::getOwnPropertyNames(object, globalObject, names, DontEnumPropertiesMode::Exclude); RETURN_IF_EXCEPTION(scope, {}); @@ -743,13 +743,13 @@ EncodedJSValue BunPlugin::OnLoad::run(JSC::JSGlobalObject* globalObject, BunStri RETURN_IF_EXCEPTION(scope, {}); if (auto* promise = JSC::jsDynamicCast(result)) { - switch (promise->status(vm)) { + switch (promise->status()) { case JSPromise::Status::Rejected: case JSPromise::Status::Pending: { return JSValue::encode(promise); } case JSPromise::Status::Fulfilled: { - result = promise->result(vm); + result = promise->result(); break; } } @@ -829,18 +829,18 @@ EncodedJSValue BunPlugin::OnResolve::run(JSC::JSGlobalObject* globalObject, BunS } if (auto* promise = JSC::jsDynamicCast(result)) { - switch (promise->status(vm)) { + switch (promise->status()) { case JSPromise::Status::Pending: { JSC::throwTypeError(globalObject, scope, "onResolve() doesn't support pending promises yet"_s); return {}; } case JSPromise::Status::Rejected: { promise->internalField(JSC::JSPromise::Field::Flags).set(vm, promise, jsNumber(static_cast(JSC::JSPromise::Status::Fulfilled))); - result = promise->result(vm); + result = promise->result(); return JSValue::encode(result); } case JSPromise::Status::Fulfilled: { - result = promise->result(vm); + result = promise->result(); break; } } @@ -916,13 +916,13 @@ JSC::JSValue runVirtualModule(Zig::GlobalObject* globalObject, BunString* specif RETURN_IF_EXCEPTION(throwScope, JSC::jsUndefined()); if (auto* promise = JSC::jsDynamicCast(result)) { - switch (promise->status(vm)) { + switch (promise->status()) { case JSPromise::Status::Rejected: case JSPromise::Status::Pending: { return promise; } case JSPromise::Status::Fulfilled: { - result = promise->result(vm); + result = promise->result(); break; } } diff --git a/src/bun.js/bindings/ErrorCode.cpp b/src/bun.js/bindings/ErrorCode.cpp index 8fbaf2395c..47fc9d00b8 100644 --- a/src/bun.js/bindings/ErrorCode.cpp +++ b/src/bun.js/bindings/ErrorCode.cpp @@ -32,7 +32,7 @@ #include "KeyObject.h" namespace WTF { -template<> class StringTypeAdapter, void> { +template<> class StringTypeAdapter> { public: StringTypeAdapter(GCOwnedDataScope string) : m_string { string } diff --git a/src/bun.js/bindings/InspectorLifecycleAgent.cpp b/src/bun.js/bindings/InspectorLifecycleAgent.cpp index 5920cece94..67ae982299 100644 --- a/src/bun.js/bindings/InspectorLifecycleAgent.cpp +++ b/src/bun.js/bindings/InspectorLifecycleAgent.cpp @@ -151,7 +151,7 @@ Protocol::ErrorStringOr InspectorLifecycleAgent::getModuleGraph() Ref> esm = JSON::ArrayOf::create(); { - auto iter1 = JSC::JSMapIterator::create(global, global->mapIteratorStructure(), esmMap, JSC::IterationKind::Keys); + auto iter1 = JSC::JSMapIterator::create(vm, global->mapIteratorStructure(), esmMap, JSC::IterationKind::Keys); RETURN_IF_EXCEPTION(scope, makeUnexpected(ErrorString("Failed to create iterator"_s))); JSC::JSValue value; while (iter1->next(global, value)) { @@ -163,7 +163,7 @@ Protocol::ErrorStringOr InspectorLifecycleAgent::getModuleGraph() Ref> cjs = JSON::ArrayOf::create(); { - auto iter2 = JSC::JSMapIterator::create(global, global->mapIteratorStructure(), cjsMap, JSC::IterationKind::Keys); + auto iter2 = JSC::JSMapIterator::create(vm, global->mapIteratorStructure(), cjsMap, JSC::IterationKind::Keys); RETURN_IF_EXCEPTION(scope, makeUnexpected(ErrorString("Failed to create iterator"_s))); JSC::JSValue value; while (iter2->next(global, value)) { diff --git a/src/bun.js/bindings/InternalModuleRegistry.cpp b/src/bun.js/bindings/InternalModuleRegistry.cpp index 4aaa21703a..1b0837ae73 100644 --- a/src/bun.js/bindings/InternalModuleRegistry.cpp +++ b/src/bun.js/bindings/InternalModuleRegistry.cpp @@ -83,7 +83,7 @@ ALWAYS_INLINE JSC::JSValue generateNativeModule( auto throwScope = DECLARE_THROW_SCOPE(vm); generator( globalObject, - JSC::Identifier::EmptyIdentifier, // Our generators do not do anything with the key + vm.propertyNames->emptyIdentifier, // Our generators do not do anything with the key propertyNames, arguments); RETURN_IF_EXCEPTION(throwScope, {}); diff --git a/src/bun.js/bindings/JSBuffer.cpp b/src/bun.js/bindings/JSBuffer.cpp index 0397657525..e3be045a44 100644 --- a/src/bun.js/bindings/JSBuffer.cpp +++ b/src/bun.js/bindings/JSBuffer.cpp @@ -1584,7 +1584,7 @@ static JSC::EncodedJSValue jsBufferPrototypeFunction_inspectBody(JSC::JSGlobalOb if (ctx.toBoolean(globalObject)) { auto showHidden = ctx.get(globalObject, Identifier::fromString(vm, "showHidden"_s)); RETURN_IF_EXCEPTION(scope, {}); - JSC::PropertyNameArray array(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); + JSC::PropertyNameArrayBuilder array(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); auto filter = showHidden.toBoolean(globalObject) ? DontEnumPropertiesMode::Include : DontEnumPropertiesMode::Exclude; diff --git a/src/bun.js/bindings/JSBunRequest.cpp b/src/bun.js/bindings/JSBunRequest.cpp index 3dd0416011..f72f54a40f 100644 --- a/src/bun.js/bindings/JSBunRequest.cpp +++ b/src/bun.js/bindings/JSBunRequest.cpp @@ -115,7 +115,7 @@ JSBunRequest* JSBunRequest::clone(JSC::VM& vm, JSGlobalObject* globalObject) auto* prototype = defaultGlobalObject(globalObject)->m_JSBunRequestParamsPrototype.get(globalObject); auto* paramsClone = JSC::constructEmptyObject(globalObject, prototype); - auto propertyNames = PropertyNameArray(vm, JSC::PropertyNameMode::Strings, JSC::PrivateSymbolMode::Exclude); + auto propertyNames = PropertyNameArrayBuilder(vm, JSC::PropertyNameMode::Strings, JSC::PrivateSymbolMode::Exclude); JSObject::getOwnPropertyNames(params, globalObject, propertyNames, JSC::DontEnumPropertiesMode::Exclude); RETURN_IF_EXCEPTION(throwScope, nullptr); diff --git a/src/bun.js/bindings/JSBundlerPlugin.cpp b/src/bun.js/bindings/JSBundlerPlugin.cpp index 9b129148a1..3bd323e2ef 100644 --- a/src/bun.js/bindings/JSBundlerPlugin.cpp +++ b/src/bun.js/bindings/JSBundlerPlugin.cpp @@ -280,8 +280,7 @@ void BundlerPlugin::NativePluginList::append(JSC::VM& vm, JSC::RegExp* filter, S bool BundlerPlugin::FilterRegExp::match(JSC::VM& vm, const String& path) { WTF::Locker locker { lock }; - constexpr bool usesPatternContextBuffer = false; - Yarr::MatchingContextHolder regExpContext(vm, usesPatternContextBuffer, nullptr, Yarr::MatchFrom::CompilerThread); + Yarr::MatchingContextHolder regExpContext(vm, nullptr, Yarr::MatchFrom::CompilerThread); return regex.match(path) != -1; } @@ -670,11 +669,12 @@ extern "C" void JSBundlerPlugin__drainDeferred(Bun::JSBundlerPlugin* pluginObjec pluginObject->plugin.deferredPromises.moveTo(pluginObject, arguments); ASSERT(!arguments.hasOverflowed()); - auto scope = DECLARE_THROW_SCOPE(pluginObject->vm()); + auto& vm = pluginObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); for (auto promiseValue : arguments) { JSPromise* promise = jsCast(JSValue::decode(promiseValue)); if (rejected) { - promise->reject(globalObject, JSC::jsUndefined()); + promise->reject(vm, globalObject, JSC::jsUndefined()); } else { promise->resolve(globalObject, JSC::jsUndefined()); } diff --git a/src/bun.js/bindings/JSCommonJSModule.cpp b/src/bun.js/bindings/JSCommonJSModule.cpp index deb611a810..b6000602bc 100644 --- a/src/bun.js/bindings/JSCommonJSModule.cpp +++ b/src/bun.js/bindings/JSCommonJSModule.cpp @@ -1020,7 +1020,7 @@ void populateESMExports( return true; }); } else { - JSC::PropertyNameArray properties(vm, JSC::PropertyNameMode::Strings, JSC::PrivateSymbolMode::Exclude); + JSC::PropertyNameArrayBuilder properties(vm, JSC::PropertyNameMode::Strings, JSC::PrivateSymbolMode::Exclude); exports->methodTable()->getOwnPropertyNames(exports, globalObject, properties, DontEnumPropertiesMode::Exclude); if (scope.exception()) [[unlikely]] { if (!vm.hasPendingTerminationException()) scope.clearException(); @@ -1078,7 +1078,7 @@ void populateESMExports( return true; }); } else { - JSC::PropertyNameArray properties(vm, JSC::PropertyNameMode::Strings, JSC::PrivateSymbolMode::Exclude); + JSC::PropertyNameArrayBuilder properties(vm, JSC::PropertyNameMode::Strings, JSC::PrivateSymbolMode::Exclude); exports->methodTable()->getOwnPropertyNames(exports, globalObject, properties, DontEnumPropertiesMode::Include); if (scope.exception()) [[unlikely]] { if (!vm.hasPendingTerminationException()) scope.clearException(); diff --git a/src/bun.js/bindings/JSDOMExceptionHandling.cpp b/src/bun.js/bindings/JSDOMExceptionHandling.cpp index de78fc5d29..f2dc435086 100644 --- a/src/bun.js/bindings/JSDOMExceptionHandling.cpp +++ b/src/bun.js/bindings/JSDOMExceptionHandling.cpp @@ -92,7 +92,7 @@ void reportException(JSGlobalObject* lexicalGlobalObject, JSValue exceptionValue if (!exception) { exception = vm.lastException(); if (!exception) - exception = JSC::Exception::create(lexicalGlobalObject->vm(), exceptionValue, JSC::Exception::DoNotCaptureStack); + exception = JSC::Exception::create(lexicalGlobalObject->vm(), exceptionValue, JSC::Exception::StackCaptureAction::DoNotCaptureStack); } reportException(lexicalGlobalObject, exception, cachedScript, fromModule); diff --git a/src/bun.js/bindings/JSDOMWrapperCache.h b/src/bun.js/bindings/JSDOMWrapperCache.h index d692416a04..11795651a0 100644 --- a/src/bun.js/bindings/JSDOMWrapperCache.h +++ b/src/bun.js/bindings/JSDOMWrapperCache.h @@ -193,7 +193,7 @@ template inline auto createWrapper(JSDOMGlobalObj template inline auto createWrapper(JSDOMGlobalObject* globalObject, Ref&& domObject) -> typename std::enable_if::value, typename JSDOMWrapperConverterTraits::WrapperClass*>::type { - return createWrapper(globalObject, static_reference_cast(WTFMove(domObject))); + return createWrapper(globalObject, unsafeRefDowncast(WTFMove(domObject))); } template inline JSC::JSValue wrap(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, DOMClass& domObject) diff --git a/src/bun.js/bindings/JSInternalPromise.zig b/src/bun.js/bindings/JSInternalPromise.zig index 37e6f57c57..806aa6e362 100644 --- a/src/bun.js/bindings/JSInternalPromise.zig +++ b/src/bun.js/bindings/JSInternalPromise.zig @@ -1,34 +1,37 @@ pub const JSInternalPromise = opaque { extern fn JSC__JSInternalPromise__create(arg0: *JSGlobalObject) *JSInternalPromise; - extern fn JSC__JSInternalPromise__isHandled(arg0: *const JSInternalPromise, arg1: *VM) bool; + extern fn JSC__JSInternalPromise__isHandled(arg0: *const JSInternalPromise) bool; extern fn JSC__JSInternalPromise__rejectAsHandled(arg0: *JSInternalPromise, arg1: *JSGlobalObject, JSValue2: JSValue) void; extern fn JSC__JSInternalPromise__rejectAsHandledException(arg0: *JSInternalPromise, arg1: *JSGlobalObject, arg2: *jsc.Exception) void; extern fn JSC__JSInternalPromise__rejectedPromise(arg0: *JSGlobalObject, JSValue1: JSValue) *JSInternalPromise; extern fn JSC__JSInternalPromise__resolvedPromise(arg0: *JSGlobalObject, JSValue1: JSValue) *JSInternalPromise; - extern fn JSC__JSInternalPromise__result(arg0: *const JSInternalPromise, arg1: *VM) JSValue; + extern fn JSC__JSInternalPromise__result(arg0: *const JSInternalPromise) JSValue; extern fn JSC__JSInternalPromise__setHandled(arg0: *JSInternalPromise, arg1: *VM) void; - extern fn JSC__JSInternalPromise__status(arg0: *const JSInternalPromise, arg1: *VM) JSPromise.Status; + extern fn JSC__JSInternalPromise__status(arg0: *const JSInternalPromise) JSPromise.Status; - pub fn status(this: *const JSInternalPromise, vm: *VM) JSPromise.Status { - return JSC__JSInternalPromise__status(this, vm); + pub fn status(this: *const JSInternalPromise) JSPromise.Status { + return JSC__JSInternalPromise__status(this); } - pub fn result(this: *const JSInternalPromise, vm: *VM) JSValue { - return JSC__JSInternalPromise__result(this, vm); + + pub fn result(this: *const JSInternalPromise) JSValue { + return JSC__JSInternalPromise__result(this); } - pub fn isHandled(this: *const JSInternalPromise, vm: *VM) bool { - return JSC__JSInternalPromise__isHandled(this, vm); + + pub fn isHandled(this: *const JSInternalPromise) bool { + return JSC__JSInternalPromise__isHandled(this); } + pub fn setHandled(this: *JSInternalPromise, vm: *VM) void { JSC__JSInternalPromise__setHandled(this, vm); } pub fn unwrap(promise: *JSInternalPromise, vm: *VM, mode: JSPromise.UnwrapMode) JSPromise.Unwrapped { - return switch (promise.status(vm)) { + return switch (promise.status()) { .pending => .pending, - .fulfilled => .{ .fulfilled = promise.result(vm) }, + .fulfilled => .{ .fulfilled = promise.result() }, .rejected => { if (mode == .mark_handled) promise.setHandled(vm); - return .{ .rejected = promise.result(vm) }; + return .{ .rejected = promise.result() }; }, }; } diff --git a/src/bun.js/bindings/JSMockFunction.cpp b/src/bun.js/bindings/JSMockFunction.cpp index 76064e2da5..3e454c6c00 100644 --- a/src/bun.js/bindings/JSMockFunction.cpp +++ b/src/bun.js/bindings/JSMockFunction.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -966,6 +967,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMockFunctionCall, (JSGlobalObject * lexicalGlobalObje } case JSMockImplementation::Kind::RejectedValue: { JSValue rejectedPromise = JSC::JSPromise::rejectedPromise(globalObject, impl->underlyingValue.get()); + RETURN_IF_EXCEPTION(scope, {}); setReturnValue(createMockResult(vm, globalObject, "return"_s, rejectedPromise)); return JSValue::encode(rejectedPromise); } diff --git a/src/bun.js/bindings/JSPromise.zig b/src/bun.js/bindings/JSPromise.zig index 1af0c57fd5..cfacd5f5f6 100644 --- a/src/bun.js/bindings/JSPromise.zig +++ b/src/bun.js/bindings/JSPromise.zig @@ -217,20 +217,20 @@ pub const JSPromise = opaque { return resolvedPromiseValue(globalObject, value); } - pub fn status(this: *const JSPromise, vm: *VM) Status { - return @enumFromInt(bun.cpp.JSC__JSPromise__status(this, vm)); + pub fn status(this: *const JSPromise) Status { + return @enumFromInt(bun.cpp.JSC__JSPromise__status(this)); } pub fn result(this: *JSPromise, vm: *VM) JSValue { return bun.cpp.JSC__JSPromise__result(this, vm); } - pub fn isHandled(this: *const JSPromise, vm: *VM) bool { - return bun.cpp.JSC__JSPromise__isHandled(this, vm); + pub fn isHandled(this: *const JSPromise) bool { + return bun.cpp.JSC__JSPromise__isHandled(this); } - pub fn setHandled(this: *JSPromise, vm: *VM) void { - bun.cpp.JSC__JSPromise__setHandled(this, vm); + pub fn setHandled(this: *JSPromise) void { + bun.cpp.JSC__JSPromise__setHandled(this); } /// Create a new resolved promise resolving to a given value. @@ -330,11 +330,11 @@ pub const JSPromise = opaque { pub const UnwrapMode = enum { mark_handled, leave_unhandled }; pub fn unwrap(promise: *JSPromise, vm: *VM, mode: UnwrapMode) Unwrapped { - return switch (promise.status(vm)) { + return switch (promise.status()) { .pending => .pending, .fulfilled => .{ .fulfilled = promise.result(vm) }, .rejected => { - if (mode == .mark_handled) promise.setHandled(vm); + if (mode == .mark_handled) promise.setHandled(); return .{ .rejected = promise.result(vm) }; }, }; diff --git a/src/bun.js/bindings/JSPropertyIterator.cpp b/src/bun.js/bindings/JSPropertyIterator.cpp index 979d3c6dcc..e4de689c18 100644 --- a/src/bun.js/bindings/JSPropertyIterator.cpp +++ b/src/bun.js/bindings/JSPropertyIterator.cpp @@ -19,16 +19,16 @@ using namespace JSC; class JSPropertyIterator { public: - JSPropertyIterator(JSC::VM& m_vm, RefPtr m_properties) + JSPropertyIterator(JSC::VM& m_vm, RefPtr m_properties) : vm(m_vm) , properties(m_properties) { } - RefPtr properties; + RefPtr properties; Ref vm; bool isSpecialProxy = false; - static JSPropertyIterator* create(JSC::VM& vm, RefPtr data) + static JSPropertyIterator* create(JSC::VM& vm, RefPtr data) { return new JSPropertyIterator(vm, data); } @@ -45,7 +45,7 @@ extern "C" JSPropertyIterator* Bun__JSPropertyIterator__create(JSC::JSGlobalObje ASSERT(count); auto scope = DECLARE_THROW_SCOPE(vm); - JSC::PropertyNameArray array(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); + JSC::PropertyNameArrayBuilder array(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); if (object->hasNonReifiedStaticProperties()) [[unlikely]] { object->reifyAllStaticProperties(globalObject); diff --git a/src/bun.js/bindings/JSSecrets.cpp b/src/bun.js/bindings/JSSecrets.cpp index d77c3b3457..94fd771a8c 100644 --- a/src/bun.js/bindings/JSSecrets.cpp +++ b/src/bun.js/bindings/JSSecrets.cpp @@ -281,7 +281,7 @@ void Bun__SecretsJobOptions__runFromJS(SecretsJobOptions* opts, JSGlobalObject* } JSValue error = opts->error.toJS(vm, global); RETURN_IF_EXCEPTION(scope, ); - RELEASE_AND_RETURN(scope, promise->reject(global, error)); + RELEASE_AND_RETURN(scope, promise->reject(vm, global, error)); } else { // Success cases JSValue result; diff --git a/src/bun.js/bindings/JSType.zig b/src/bun.js/bindings/JSType.zig index 305ce12034..25ec32e5dc 100644 --- a/src/bun.js/bindings/JSType.zig +++ b/src/bun.js/bindings/JSType.zig @@ -114,13 +114,19 @@ pub const JSType = enum(u8) { /// ``` HeapBigInt = 3, + /// Heap-allocated double values (new in recent WebKit). + HeapDouble = 4, + + /// Heap-allocated int32 values (new in recent WebKit). + HeapInt32 = 5, + /// JavaScript Symbol primitive - unique identifiers. /// ```js /// Symbol() /// Symbol('description') /// Symbol.for('key') /// ``` - Symbol = 4, + Symbol = 6, /// Accessor property descriptor containing getter and/or setter functions. /// ```js @@ -129,7 +135,7 @@ pub const JSType = enum(u8) { /// set(v) { this._value = v; } /// }) /// ``` - GetterSetter = 5, + GetterSetter = 7, /// Custom native getter/setter implementation for built-in properties. /// ```js @@ -137,10 +143,10 @@ pub const JSType = enum(u8) { /// const arr = [1, 2, 3]; /// arr.length; // uses CustomGetterSetter /// ``` - CustomGetterSetter = 6, + CustomGetterSetter = 8, /// Wrapper for native API values exposed to JavaScript. - APIValueWrapper = 7, + APIValueWrapper = 9, /// Compiled native code executable for built-in functions. /// ```js @@ -148,55 +154,68 @@ pub const JSType = enum(u8) { /// parseInt("42") /// Array.from([1, 2, 3]) /// ``` - NativeExecutable = 8, + NativeExecutable = 10, /// Compiled executable for top-level program code. - ProgramExecutable = 9, + ProgramExecutable = 11, /// Compiled executable for ES6 module code. - ModuleProgramExecutable = 10, + ModuleProgramExecutable = 12, /// Compiled executable for eval() expressions. /// ```js /// eval('var x = 42; console.log(x);') /// ``` - EvalExecutable = 11, + EvalExecutable = 13, /// Compiled executable for function bodies. /// ```js /// function foo() { return 42; } /// const bar = () => 123 /// ``` - FunctionExecutable = 12, + FunctionExecutable = 14, - UnlinkedFunctionExecutable = 13, - UnlinkedProgramCodeBlock = 14, - UnlinkedModuleProgramCodeBlock = 15, - UnlinkedEvalCodeBlock = 16, - UnlinkedFunctionCodeBlock = 17, + UnlinkedFunctionExecutable = 15, + UnlinkedProgramCodeBlock = 16, + UnlinkedModuleProgramCodeBlock = 17, + UnlinkedEvalCodeBlock = 18, + UnlinkedFunctionCodeBlock = 19, /// Compiled bytecode block ready for execution. - CodeBlock = 18, + CodeBlock = 20, - JSCellButterfly = 19, - JSSourceCode = 20, - JSScriptFetcher = 21, - JSScriptFetchParameters = 22, + JSCellButterfly = 21, + JSSourceCode = 22, + JSScriptFetcher = 23, + JSScriptFetchParameters = 24, + + /// Promise reaction object for tracking promise callbacks. + /// Internal object used in the promise resolution mechanism. + /// Note: Moved before ObjectType in recent WebKit. + PromiseReaction = 25, + + /// Context object for Promise.all() operations. + /// Internal object used to track the state of Promise.all() resolution. + /// Note: Moved before ObjectType in recent WebKit. + PromiseAllContext = 26, + + /// Global context for Promise.all() (new in recent WebKit). + PromiseAllGlobalContext = 27, /// Base JavaScript object type. /// ```js /// {} /// new Object() /// ``` - Object = 23, + Object = 28, /// Optimized object type for object literals with fixed properties. /// ```js /// { a: 1, b: 2 } /// ``` - FinalObject = 24, + FinalObject = 29, - JSCallee = 25, + JSCallee = 30, /// JavaScript function object created from JavaScript source code. /// ```js @@ -206,7 +225,7 @@ pub const JSType = enum(u8) { /// method() {} /// } /// ``` - JSFunction = 26, + JSFunction = 31, /// Built-in function implemented in native code. /// ```js @@ -215,23 +234,23 @@ pub const JSType = enum(u8) { /// parseInt /// console.log /// ``` - InternalFunction = 27, + InternalFunction = 32, - NullSetterFunction = 28, + NullSetterFunction = 33, /// Boxed Boolean object. /// ```js /// new Boolean(true) /// new Boolean(false) /// ``` - BooleanObject = 29, + BooleanObject = 34, /// Boxed Number object. /// ```js /// new Number(42) /// new Number(3.14) /// ``` - NumberObject = 30, + NumberObject = 35, /// JavaScript Error object and its subclasses. /// ```js @@ -239,9 +258,9 @@ pub const JSType = enum(u8) { /// new TypeError() /// throw new RangeError() /// ``` - ErrorInstance = 31, + ErrorInstance = 36, - GlobalProxy = 32, + GlobalProxy = 37, /// Arguments object for function parameters. /// ```js @@ -250,10 +269,10 @@ pub const JSType = enum(u8) { /// console.log(arguments.length); /// } /// ``` - DirectArguments = 33, + DirectArguments = 38, - ScopedArguments = 34, - ClonedArguments = 35, + ScopedArguments = 39, + ClonedArguments = 40, /// JavaScript Array object. /// ```js @@ -262,94 +281,94 @@ pub const JSType = enum(u8) { /// new Array(10) /// Array.from(iterable) /// ``` - Array = 36, + Array = 41, /// Array subclass created through class extension. /// ```js /// class MyArray extends Array {} /// const arr = new MyArray(); /// ``` - DerivedArray = 37, + DerivedArray = 42, /// ArrayBuffer for binary data storage. /// ```js /// new ArrayBuffer(1024) /// ``` - ArrayBuffer = 38, + ArrayBuffer = 43, /// Typed array for 8-bit signed integers. /// ```js /// new Int8Array(buffer) /// new Int8Array([1, -1, 127]) /// ``` - Int8Array = 39, + Int8Array = 44, /// Typed array for 8-bit unsigned integers. /// ```js /// new Uint8Array(buffer) /// new Uint8Array([0, 255]) /// ``` - Uint8Array = 40, + Uint8Array = 45, /// Typed array for 8-bit unsigned integers with clamping. /// ```js /// new Uint8ClampedArray([0, 300]) // 300 becomes 255 /// ``` - Uint8ClampedArray = 41, + Uint8ClampedArray = 46, /// Typed array for 16-bit signed integers. /// ```js /// new Int16Array(buffer) /// ``` - Int16Array = 42, + Int16Array = 47, /// Typed array for 16-bit unsigned integers. /// ```js /// new Uint16Array(buffer) /// ``` - Uint16Array = 43, + Uint16Array = 48, /// Typed array for 32-bit signed integers. /// ```js /// new Int32Array(buffer) /// ``` - Int32Array = 44, + Int32Array = 49, /// Typed array for 32-bit unsigned integers. /// ```js /// new Uint32Array(buffer) /// ``` - Uint32Array = 45, + Uint32Array = 50, /// Typed array for 16-bit floating point numbers. /// ```js /// new Float16Array(buffer) /// ``` - Float16Array = 46, + Float16Array = 51, /// Typed array for 32-bit floating point numbers. /// ```js /// new Float32Array(buffer) /// ``` - Float32Array = 47, + Float32Array = 52, /// Typed array for 64-bit floating point numbers. /// ```js /// new Float64Array(buffer) /// ``` - Float64Array = 48, + Float64Array = 53, /// Typed array for 64-bit signed BigInt values. /// ```js /// new BigInt64Array([123n, -456n]) /// ``` - BigInt64Array = 49, + BigInt64Array = 54, /// Typed array for 64-bit unsigned BigInt values. /// ```js /// new BigUint64Array([123n, 456n]) /// ``` - BigUint64Array = 50, + BigUint64Array = 55, /// DataView for flexible binary data access. /// ```js @@ -357,7 +376,7 @@ pub const JSType = enum(u8) { /// view.getInt32(0) /// view.setFloat64(8, 3.14) /// ``` - DataView = 51, + DataView = 56, /// Global object containing all global variables and functions. /// ```js @@ -365,12 +384,12 @@ pub const JSType = enum(u8) { /// window // in browsers /// global // in Node.js /// ``` - GlobalObject = 52, + GlobalObject = 57, - GlobalLexicalEnvironment = 53, - LexicalEnvironment = 54, - ModuleEnvironment = 55, - StrictEvalActivation = 56, + GlobalLexicalEnvironment = 58, + LexicalEnvironment = 59, + ModuleEnvironment = 60, + StrictEvalActivation = 61, /// Scope object for with statements. /// ```js @@ -378,19 +397,19 @@ pub const JSType = enum(u8) { /// prop; // looks up prop in obj first /// } /// ``` - WithScope = 57, + WithScope = 62, - AsyncDisposableStack = 58, - DisposableStack = 59, + AsyncDisposableStack = 63, + DisposableStack = 64, /// Namespace object for ES6 modules. /// ```js /// import * as ns from 'module'; /// ns.exportedFunction() /// ``` - ModuleNamespaceObject = 60, + ModuleNamespaceObject = 65, - ShadowRealm = 61, + ShadowRealm = 66, /// Regular expression object. /// ```js @@ -398,7 +417,7 @@ pub const JSType = enum(u8) { /// new RegExp('pattern', 'flags') /// /abc/gi /// ``` - RegExpObject = 62, + RegExpObject = 67, /// JavaScript Date object for date/time operations. /// ```js @@ -406,7 +425,7 @@ pub const JSType = enum(u8) { /// new Date('2023-01-01') /// Date.now() /// ``` - JSDate = 63, + JSDate = 68, /// Proxy object that intercepts operations on another object. /// ```js @@ -414,7 +433,7 @@ pub const JSType = enum(u8) { /// get(obj, prop) { return obj[prop]; } /// }) /// ``` - ProxyObject = 64, + ProxyObject = 69, /// Generator object created by generator functions. /// ```js @@ -422,7 +441,7 @@ pub const JSType = enum(u8) { /// const g = gen(); /// g.next() /// ``` - Generator = 65, + Generator = 70, /// Async generator object for asynchronous iteration. /// ```js @@ -430,17 +449,17 @@ pub const JSType = enum(u8) { /// yield await promise; /// } /// ``` - AsyncGenerator = 66, + AsyncGenerator = 71, /// Iterator for Array objects. /// ```js /// [1,2,3][Symbol.iterator]() /// for (const x of array) {} /// ``` - JSArrayIterator = 67, + JSArrayIterator = 72, - Iterator = 68, - IteratorHelper = 69, + Iterator = 73, + IteratorHelper = 74, /// Iterator for Map objects. /// ```js @@ -449,32 +468,32 @@ pub const JSType = enum(u8) { /// map.entries() /// for (const [k,v] of map) {} /// ``` - MapIterator = 70, + MapIterator = 75, /// Iterator for Set objects. /// ```js /// set.values() /// for (const value of set) {} /// ``` - SetIterator = 71, + SetIterator = 76, /// Iterator for String objects. /// ```js /// 'hello'[Symbol.iterator]() /// for (const char of string) {} /// ``` - StringIterator = 72, + StringIterator = 77, - WrapForValidIterator = 73, + WrapForValidIterator = 78, /// Iterator for RegExp string matching. /// ```js /// 'abc'.matchAll(/./g) /// for (const match of string.matchAll(regex)) {} /// ``` - RegExpStringIterator = 74, + RegExpStringIterator = 79, - AsyncFromSyncIterator = 75, + AsyncFromSyncIterator = 80, /// JavaScript Promise object for asynchronous operations. /// ```js @@ -482,11 +501,7 @@ pub const JSType = enum(u8) { /// Promise.resolve(42) /// async function foo() { await promise; } /// ``` - JSPromise = 76, - - /// Context object for Promise.all() operations. - /// Internal object used to track the state of Promise.all() resolution. - PromiseAllContext = 77, + JSPromise = 81, /// JavaScript Map object for key-value storage. /// ```js @@ -494,7 +509,7 @@ pub const JSType = enum(u8) { /// map.set(key, value) /// map.get(key) /// ``` - Map = 78, + Map = 82, /// JavaScript Set object for unique value storage. /// ```js @@ -502,34 +517,34 @@ pub const JSType = enum(u8) { /// set.add(value) /// set.has(value) /// ``` - Set = 79, + Set = 83, /// WeakMap for weak key-value references. /// ```js /// new WeakMap() /// weakMap.set(object, value) /// ``` - WeakMap = 80, + WeakMap = 84, /// WeakSet for weak value references. /// ```js /// new WeakSet() /// weakSet.add(object) /// ``` - WeakSet = 81, + WeakSet = 85, - WebAssemblyModule = 82, - WebAssemblyInstance = 83, - WebAssemblyGCObject = 84, + WebAssemblyModule = 86, + WebAssemblyInstance = 87, + WebAssemblyGCObject = 88, /// Boxed String object. /// ```js /// new String("hello") /// ``` - StringObject = 85, + StringObject = 89, - DerivedStringObject = 86, - InternalFieldTuple = 87, + DerivedStringObject = 90, + InternalFieldTuple = 91, MaxJS = 0b11111111, Event = 0b11101111, @@ -573,7 +588,6 @@ pub const JSType = enum(u8) { .Map, .MapIterator, .JSPromise, - .PromiseAllContext, .Set, .SetIterator, .IteratorHelper, @@ -690,13 +704,16 @@ pub const JSType = enum(u8) { .JSSourceCode, .JSScriptFetcher, .JSScriptFetchParameters, + .PromiseReaction, + .PromiseAllContext, + .PromiseAllGlobalContext, => true, else => false, }; } pub const LastMaybeFalsyCellPrimitive = JSType.HeapBigInt; - pub const LastJSCObject = JSType.DerivedStringObject; // This is the last "JSC" Object type. After this, we have embedder's (e.g., WebCore) extended object types. + pub const LastJSCObject = JSType.InternalFieldTuple; // This is the last "JSC" Object type. After this, we have embedder's (e.g., WebCore) extended object types. pub inline fn isString(this: JSType) bool { return this == .String; diff --git a/src/bun.js/bindings/ModuleLoader.cpp b/src/bun.js/bindings/ModuleLoader.cpp index 7727c7411b..fb46b9f127 100644 --- a/src/bun.js/bindings/ModuleLoader.cpp +++ b/src/bun.js/bindings/ModuleLoader.cpp @@ -102,7 +102,7 @@ static JSC::SyntheticSourceProvider::SyntheticSourceGenerator generateInternalMo JSC::EnsureStillAliveScope stillAlive(object); - PropertyNameArray properties(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); + PropertyNameArrayBuilder properties(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); object->getOwnPropertyNames(object, globalObject, properties, DontEnumPropertiesMode::Exclude); RETURN_IF_EXCEPTION(throwScope, void()); @@ -467,7 +467,7 @@ extern "C" void Bun__onFulfillAsyncModule( JSC::JSInternalPromise* promise = jsCast(JSC::JSValue::decode(encodedPromiseValue)); if (!res->success) { - RELEASE_AND_RETURN(scope, promise->reject(globalObject, JSValue::decode(res->result.err.value))); + RELEASE_AND_RETURN(scope, promise->reject(vm, globalObject, JSValue::decode(res->result.err.value))); } auto specifierValue = Bun::toJS(globalObject, *specifier); @@ -503,7 +503,7 @@ extern "C" void Bun__onFulfillAsyncModule( auto* exception = scope.exception(); if (!vm.isTerminationException(exception)) { scope.clearException(); - promise->reject(globalObject, exception); + promise->reject(vm, globalObject, exception); scope.assertNoExceptionExceptTermination(); } } @@ -676,11 +676,11 @@ JSValue fetchCommonJSModule( RELEASE_AND_RETURN(scope, target); } JSPromise* promise = jsCast(promiseOrCommonJSModule); - switch (promise->status(vm)) { + switch (promise->status()) { case JSPromise::Status::Rejected: { uint32_t promiseFlags = promise->internalField(JSPromise::Field::Flags).get().asUInt32AsAnyInt(); promise->internalField(JSPromise::Field::Flags).set(vm, promise, jsNumber(promiseFlags | JSPromise::isHandledFlag)); - JSC::throwException(globalObject, scope, promise->result(vm)); + JSC::throwException(globalObject, scope, promise->result()); RELEASE_AND_RETURN(scope, JSValue {}); } case JSPromise::Status::Pending: { @@ -693,7 +693,7 @@ JSValue fetchCommonJSModule( RELEASE_AND_RETURN(scope, {}); } if (!wasModuleMock) { - auto* jsSourceCode = jsCast(promise->result(vm)); + auto* jsSourceCode = jsCast(promise->result()); globalObject->moduleLoader()->provideFetch(globalObject, specifierValue, jsSourceCode->sourceCode()); RETURN_IF_EXCEPTION(scope, {}); } @@ -727,11 +727,11 @@ JSValue fetchCommonJSModule( RELEASE_AND_RETURN(scope, target); } JSPromise* promise = jsCast(promiseOrCommonJSModule); - switch (promise->status(vm)) { + switch (promise->status()) { case JSPromise::Status::Rejected: { uint32_t promiseFlags = promise->internalField(JSPromise::Field::Flags).get().asUInt32AsAnyInt(); promise->internalField(JSPromise::Field::Flags).set(vm, promise, jsNumber(promiseFlags | JSPromise::isHandledFlag)); - JSC::throwException(globalObject, scope, promise->result(vm)); + JSC::throwException(globalObject, scope, promise->result()); RELEASE_AND_RETURN(scope, JSValue {}); } case JSPromise::Status::Pending: { @@ -744,7 +744,7 @@ JSValue fetchCommonJSModule( RELEASE_AND_RETURN(scope, {}); } if (!wasModuleMock) { - auto* jsSourceCode = jsCast(promise->result(vm)); + auto* jsSourceCode = jsCast(promise->result()); globalObject->moduleLoader()->provideFetch(globalObject, specifierValue, jsSourceCode->sourceCode()); RETURN_IF_EXCEPTION(scope, {}); } @@ -1178,7 +1178,7 @@ BUN_DEFINE_HOST_FUNCTION(jsFunctionOnLoadObjectResultReject, (JSC::JSGlobalObjec JSC::JSInternalPromise* promise = pendingModule->internalPromise(); pendingModule->internalField(2).set(vm, pendingModule, JSC::jsUndefined()); - promise->reject(globalObject, reason); + promise->reject(vm, globalObject, reason); return JSValue::encode(reason); } diff --git a/src/bun.js/bindings/NodeHTTP.cpp b/src/bun.js/bindings/NodeHTTP.cpp index 116183e7f7..33fcc4e1c6 100644 --- a/src/bun.js/bindings/NodeHTTP.cpp +++ b/src/bun.js/bindings/NodeHTTP.cpp @@ -619,7 +619,7 @@ static void NodeHTTPServer__writeHead( return true; }); } else { - PropertyNameArray propertyNames(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); + PropertyNameArrayBuilder propertyNames(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); headersObject->getOwnPropertyNames(headersObject, globalObject, propertyNames, DontEnumPropertiesMode::Exclude); RETURN_IF_EXCEPTION(scope, void()); diff --git a/src/bun.js/bindings/NodeVM.cpp b/src/bun.js/bindings/NodeVM.cpp index 83bd5b7d84..baf305f5b4 100644 --- a/src/bun.js/bindings/NodeVM.cpp +++ b/src/bun.js/bindings/NodeVM.cpp @@ -316,10 +316,10 @@ static JSInternalPromise* importModuleInner(JSGlobalObject* globalObject, JSStri RETURN_IF_EXCEPTION(scope, nullptr); - promise->fulfill(globalObject, result); + promise->fulfill(vm, globalObject, result); RETURN_IF_EXCEPTION(scope, nullptr); - promise = promise->then(globalObject, transformer, nullptr); + promise = promise->then(globalObject, transformer, globalObject->promiseEmptyOnRejectedFunction()); RETURN_IF_EXCEPTION(scope, nullptr); RELEASE_AND_RETURN(scope, promise); @@ -738,6 +738,14 @@ Structure* NodeVMGlobalObject::createStructure(JSC::VM& vm, JSC::JSValue prototy void unsafeEvalNoop(JSGlobalObject*, const WTF::String&) {} +static void promiseRejectionTrackerForNodeVM(JSGlobalObject* globalObject, JSC::JSPromise* promise, JSC::JSPromiseRejectionOperation operation) +{ + // Delegate to the parent Zig::GlobalObject so that unhandled rejections + // in VM contexts are reported to the main process (matching Node.js behavior) + auto* zigGlobalObject = defaultGlobalObject(globalObject); + Zig::GlobalObject::promiseRejectionTracker(zigGlobalObject, promise, operation); +} + const JSC::GlobalObjectMethodTable& NodeVMGlobalObject::globalObjectMethodTable() { static const JSC::GlobalObjectMethodTable table { @@ -751,7 +759,7 @@ const JSC::GlobalObjectMethodTable& NodeVMGlobalObject::globalObjectMethodTable( nullptr, // moduleLoaderFetch nullptr, // moduleLoaderCreateImportMetaProperties nullptr, // moduleLoaderEvaluate - nullptr, // promiseRejectionTracker + &promiseRejectionTrackerForNodeVM, &reportUncaughtExceptionAtEventLoop, ¤tScriptExecutionOwner, &scriptExecutionStatus, @@ -780,6 +788,18 @@ void NodeVMGlobalObject::finishCreation(JSC::VM& vm) JSC::JSObject::deleteProperty(this, this, vm.propertyNames->Loader, slot); vm.ensureTerminationException(); + + // Share the async context data with the parent Zig::GlobalObject. + // This is necessary because AsyncLocalStorage methods (run, getStore, etc.) are defined + // in the parent realm and reference the parent's $asyncContext. However, microtask + // processing (JSMicrotask.cpp) operates on this NodeVMGlobalObject's m_asyncContextData. + // By sharing the same InternalFieldTuple, both the JS code and C++ microtask handling + // will operate on the same async context, ensuring proper AsyncLocalStorage behavior + // across await boundaries in VM contexts. + auto* parentGlobalObject = defaultGlobalObject(this); + if (parentGlobalObject && parentGlobalObject->m_asyncContextData) { + m_asyncContextData.set(vm, this, parentGlobalObject->m_asyncContextData.get()); + } } void NodeVMGlobalObject::destroy(JSCell* cell) @@ -1389,7 +1409,7 @@ static JSInternalPromise* moduleLoaderImportModuleInner(NodeVMGlobalObject* glob return NodeVM::importModuleInner(globalObject, moduleName, parameters, sourceOrigin, globalObject->dynamicImportCallback(), JSValue {}); } - promise->reject(globalObject, createError(globalObject, ErrorCode::ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING, "A dynamic import callback was not specified."_s)); + promise->reject(vm, globalObject, createError(globalObject, ErrorCode::ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING, "A dynamic import callback was not specified."_s)); return promise; } @@ -1398,7 +1418,7 @@ static JSInternalPromise* moduleLoaderImportModuleInner(NodeVMGlobalObject* glob RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope)); scope.release(); - promise->reject(globalObject, createError(globalObject, makeString("Could not import the module '"_s, moduleNameString.data, "'."_s))); + promise->reject(vm, globalObject, createError(globalObject, makeString("Could not import the module '"_s, moduleNameString.data, "'."_s))); return promise; } @@ -1413,7 +1433,7 @@ JSInternalPromise* NodeVMGlobalObject::moduleLoaderImportModule(JSGlobalObject* return moduleLoaderImportModuleInner(nodeVmGlobalObject, moduleLoader, moduleName, parameters, sourceOrigin); } -void NodeVMGlobalObject::getOwnPropertyNames(JSObject* cell, JSGlobalObject* globalObject, JSC::PropertyNameArray& propertyNames, JSC::DontEnumPropertiesMode mode) +void NodeVMGlobalObject::getOwnPropertyNames(JSObject* cell, JSGlobalObject* globalObject, JSC::PropertyNameArrayBuilder& propertyNames, JSC::DontEnumPropertiesMode mode) { auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_THROW_SCOPE(vm); diff --git a/src/bun.js/bindings/NodeVM.h b/src/bun.js/bindings/NodeVM.h index 797af6aa4f..47e1815618 100644 --- a/src/bun.js/bindings/NodeVM.h +++ b/src/bun.js/bindings/NodeVM.h @@ -132,7 +132,7 @@ public: // Override property access to delegate to contextified object static bool getOwnPropertySlot(JSObject*, JSGlobalObject*, JSC::PropertyName, JSC::PropertySlot&); static bool put(JSCell*, JSGlobalObject*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&); - static void getOwnPropertyNames(JSObject*, JSGlobalObject*, JSC::PropertyNameArray&, JSC::DontEnumPropertiesMode); + static void getOwnPropertyNames(JSObject*, JSGlobalObject*, JSC::PropertyNameArrayBuilder&, JSC::DontEnumPropertiesMode); static bool defineOwnProperty(JSObject* object, JSGlobalObject* globalObject, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow); static bool deleteProperty(JSCell* cell, JSGlobalObject* globalObject, PropertyName propertyName, JSC::DeletePropertySlot& slot); static JSC::JSInternalPromise* moduleLoaderImportModule(JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSString* moduleNameValue, JSC::JSValue parameters, const JSC::SourceOrigin&); diff --git a/src/bun.js/bindings/NodeVMModule.cpp b/src/bun.js/bindings/NodeVMModule.cpp index 61e479317b..ff9489c006 100644 --- a/src/bun.js/bindings/NodeVMModule.cpp +++ b/src/bun.js/bindings/NodeVMModule.cpp @@ -127,6 +127,7 @@ JSValue NodeVMModule::evaluate(JSGlobalObject* globalObject, uint32_t timeout, b } if (vm.hasPendingTerminationException()) { + vm.drainMicrotasksForGlobalObject(nodeVmGlobalObject); scope.clearException(); vm.clearHasTerminationRequest(); if (getSigintReceived()) { diff --git a/src/bun.js/bindings/NodeVMScript.cpp b/src/bun.js/bindings/NodeVMScript.cpp index 03af768036..7602c80a50 100644 --- a/src/bun.js/bindings/NodeVMScript.cpp +++ b/src/bun.js/bindings/NodeVMScript.cpp @@ -283,6 +283,7 @@ void NodeVMScript::destroy(JSCell* cell) static bool checkForTermination(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::ThrowScope& scope, NodeVMScript* script, std::optional timeout) { if (vm.hasTerminationRequest()) { + vm.drainMicrotasksForGlobalObject(globalObject); vm.clearHasTerminationRequest(); if (script->getSigintReceived()) { script->setSigintReceived(false); diff --git a/src/bun.js/bindings/SQLClient.cpp b/src/bun.js/bindings/SQLClient.cpp index 00c08ab91d..94be6821da 100644 --- a/src/bun.js/bindings/SQLClient.cpp +++ b/src/bun.js/bindings/SQLClient.cpp @@ -434,7 +434,7 @@ extern "C" EncodedJSValue JSC__createStructure(JSC::JSGlobalObject* globalObject { auto& vm = JSC::getVM(globalObject); - PropertyNameArray propertyNames(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); + PropertyNameArrayBuilder propertyNames(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); std::span names(namesPtr, capacity); uint32_t nonDuplicateCount = 0; diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index a1e862064b..0e9e1161e2 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -853,6 +853,13 @@ void GlobalObject::promiseRejectionTracker(JSGlobalObject* obj, JSC::JSPromise* // Do this in C++ for now auto* globalObj = static_cast(obj); + + // JSInternalPromise should not be tracked through the normal promise rejection mechanism + // as they are internal to the engine and should not be exposed to user space. + // See: JSInternalPromise.h - "CAUTION: Must not leak the JSInternalPromise to the user space" + if (jsDynamicCast(promise)) + return; + switch (operation) { case JSPromiseRejectionOperation::Reject: globalObj->m_aboutToBeNotifiedRejectedPromises.append(obj->vm(), globalObj, promise); @@ -1062,9 +1069,11 @@ JSC_DEFINE_HOST_FUNCTION(functionQueueMicrotask, asyncContext = JSC::jsUndefined(); } - // This is a JSC builtin function - lexicalGlobalObject->queueMicrotask(function, callback, asyncContext, - JSC::JSValue {}, JSC::JSValue {}); + // BunPerformMicrotaskJob accepts a variable number of arguments (up to: performMicrotask, job, asyncContext, arg0, arg1). + // The runtime inspects argumentCount to determine which arguments are present, so callers may pass only the subset they need. + // Here we pass: function, callback, asyncContext. + JSC::QueuedTask task { nullptr, JSC::InternalMicrotask::BunPerformMicrotaskJob, globalObject, function, callback, asyncContext }; + globalObject->vm().queueMicrotask(WTFMove(task)); return JSC::JSValue::encode(JSC::jsUndefined()); } @@ -2984,7 +2993,7 @@ void GlobalObject::handleRejectedPromises() JSC::VM& virtual_machine = vm(); auto scope = DECLARE_CATCH_SCOPE(virtual_machine); while (auto* promise = m_aboutToBeNotifiedRejectedPromises.takeFirst(this)) { - if (promise->isHandled(virtual_machine)) + if (promise->isHandled()) continue; Bun__handleRejectedPromise(this, promise); @@ -3093,7 +3102,9 @@ extern "C" void JSC__JSGlobalObject__queueMicrotaskCallback(Zig::GlobalObject* g #endif // Do not use JSCell* here because the GC will try to visit it. - globalObject->queueMicrotask(function, JSValue(std::bit_cast(reinterpret_cast(ptr))), JSValue(std::bit_cast(reinterpret_cast(callback))), jsUndefined(), jsUndefined()); + // Use BunInvokeJobWithArguments to pass the two arguments (ptr and callback) to the trampoline function + JSC::QueuedTask task { nullptr, JSC::InternalMicrotask::BunInvokeJobWithArguments, globalObject, function, JSValue(std::bit_cast(reinterpret_cast(ptr))), JSValue(std::bit_cast(reinterpret_cast(callback))) }; + globalObject->vm().queueMicrotask(WTFMove(task)); } JSC::Identifier GlobalObject::moduleLoaderResolve(JSGlobalObject* jsGlobalObject, diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index 80a6de32d5..0f3b3d07e7 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -46,6 +46,7 @@ #include "JavaScriptCore/JSArray.h" #include "JavaScriptCore/JSArrayBuffer.h" #include "JavaScriptCore/JSArrayInlines.h" +#include "JavaScriptCore/JSFunction.h" #include "JavaScriptCore/ErrorInstanceInlines.h" #include "JavaScriptCore/BigIntObject.h" #include "JavaScriptCore/OrderedHashTableHelper.h" @@ -785,8 +786,8 @@ bool Bun__deepEquals(JSC::JSGlobalObject* globalObject, JSValue v1, JSValue v2, return false; } - JSC::PropertyNameArray a1(vm, PropertyNameMode::Symbols, PrivateSymbolMode::Exclude); - JSC::PropertyNameArray a2(vm, PropertyNameMode::Symbols, PrivateSymbolMode::Exclude); + JSC::PropertyNameArrayBuilder a1(vm, PropertyNameMode::Symbols, PrivateSymbolMode::Exclude); + JSC::PropertyNameArrayBuilder a2(vm, PropertyNameMode::Symbols, PrivateSymbolMode::Exclude); JSObject::getOwnPropertyNames(o1, globalObject, a1, DontEnumPropertiesMode::Exclude); RETURN_IF_EXCEPTION(scope, false); JSObject::getOwnPropertyNames(o2, globalObject, a2, DontEnumPropertiesMode::Exclude); @@ -955,8 +956,8 @@ bool Bun__deepEquals(JSC::JSGlobalObject* globalObject, JSValue v1, JSValue v2, } } - JSC::PropertyNameArray a1(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); - JSC::PropertyNameArray a2(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); + JSC::PropertyNameArrayBuilder a1(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); + JSC::PropertyNameArrayBuilder a2(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); o1->getPropertyNames(globalObject, a1, DontEnumPropertiesMode::Exclude); RETURN_IF_EXCEPTION(scope, false); o2->getPropertyNames(globalObject, a2, DontEnumPropertiesMode::Exclude); @@ -1020,6 +1021,7 @@ bool Bun__deepEquals(JSC::JSGlobalObject* globalObject, JSValue v1, JSValue v2, template std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, MarkedArgumentBuffer& gcBuffer, Vector, 16>& stack, ThrowScope& scope, JSCell* _Nonnull c1, JSCell* _Nonnull c2) { + VM& vm = globalObject->vm(); uint8_t c1Type = c1->type(); uint8_t c2Type = c2->type(); @@ -1036,7 +1038,7 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark return false; } - auto iter1 = JSSetIterator::create(globalObject, globalObject->setIteratorStructure(), set1, IterationKind::Keys); + auto iter1 = JSSetIterator::create(vm, globalObject->setIteratorStructure(), set1, IterationKind::Keys); RETURN_IF_EXCEPTION(scope, {}); JSValue key1; while (iter1->next(globalObject, key1)) { @@ -1048,7 +1050,7 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark // We couldn't find the key in the second set. This may be a false positive due to how // JSValues are represented in JSC, so we need to fall back to a linear search to be sure. - auto iter2 = JSSetIterator::create(globalObject, globalObject->setIteratorStructure(), set2, IterationKind::Keys); + auto iter2 = JSSetIterator::create(vm, globalObject->setIteratorStructure(), set2, IterationKind::Keys); RETURN_IF_EXCEPTION(scope, {}); JSValue key2; bool foundMatchingKey = false; @@ -1081,7 +1083,7 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark return false; } - auto iter1 = JSMapIterator::create(globalObject, globalObject->mapIteratorStructure(), map1, IterationKind::Entries); + auto iter1 = JSMapIterator::create(vm, globalObject->mapIteratorStructure(), map1, IterationKind::Entries); RETURN_IF_EXCEPTION(scope, {}); JSValue key1, value1; while (iter1->nextKeyValue(globalObject, key1, value1)) { @@ -1091,7 +1093,7 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark // We couldn't find the key in the second map. This may be a false positive due to // how JSValues are represented in JSC, so we need to fall back to a linear search // to be sure. - auto iter2 = JSMapIterator::create(globalObject, globalObject->mapIteratorStructure(), map2, IterationKind::Entries); + auto iter2 = JSMapIterator::create(vm, globalObject->mapIteratorStructure(), map2, IterationKind::Entries); RETURN_IF_EXCEPTION(scope, {}); JSValue key2; bool foundMatchingKey = false; @@ -1254,8 +1256,8 @@ std::optional specialObjectsDequal(JSC::JSGlobalObject* globalObject, Mark RETURN_IF_EXCEPTION(scope, {}); right->materializeErrorInfoIfNeeded(vm); RETURN_IF_EXCEPTION(scope, {}); - JSC::PropertyNameArray a1(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); - JSC::PropertyNameArray a2(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); + JSC::PropertyNameArrayBuilder a1(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); + JSC::PropertyNameArrayBuilder a2(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); left->getPropertyNames(globalObject, a1, DontEnumPropertiesMode::Exclude); RETURN_IF_EXCEPTION(scope, {}); right->getPropertyNames(globalObject, a2, DontEnumPropertiesMode::Exclude); @@ -1622,7 +1624,7 @@ bool Bun__deepMatch( JSObject* obj = objValue.getObject(); JSObject* subsetObj = subsetValue.getObject(); - PropertyNameArray subsetProps(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Include); + PropertyNameArrayBuilder subsetProps(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Include); subsetObj->getPropertyNames(globalObject, subsetProps, DontEnumPropertiesMode::Exclude); RETURN_IF_EXCEPTION(throwScope, false); @@ -1636,7 +1638,7 @@ bool Bun__deepMatch( if (obj->getArrayLength() != subsetObj->getArrayLength()) { return false; } - PropertyNameArray objProps(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Include); + PropertyNameArrayBuilder objProps(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Include); obj->getPropertyNames(globalObject, objProps, DontEnumPropertiesMode::Exclude); RETURN_IF_EXCEPTION(throwScope, false); if (objProps.size() != subsetProps.size()) { @@ -2915,12 +2917,12 @@ JSC::EncodedJSValue JSC__JSModuleLoader__evaluate(JSC::JSGlobalObject* globalObj promise->rejectWithCaughtException(globalObject, scope); } - auto status = promise->status(vm); + auto status = promise->status(); if (status == JSC::JSPromise::Status::Fulfilled) { - return JSC::JSValue::encode(promise->result(vm)); + return JSC::JSValue::encode(promise->result()); } else if (status == JSC::JSPromise::Status::Rejected) { - *arg6 = JSC::JSValue::encode(promise->result(vm)); + *arg6 = JSC::JSValue::encode(promise->result()); return JSC::JSValue::encode(JSC::jsUndefined()); } else { return JSC::JSValue::encode(promise); @@ -3328,7 +3330,7 @@ JSC__JSModuleLoader__loadAndEvaluateModule(JSC::JSGlobalObject* globalObject, JSC::JSNativeStdFunction* resolverFunction = JSC::JSNativeStdFunction::create( vm, globalObject, 1, String(), resolverFunctionCallback); - auto* newPromise = promise->then(globalObject, resolverFunction, nullptr); + auto* newPromise = promise->then(globalObject, resolverFunction, globalObject->promiseEmptyOnRejectedFunction()); EXCEPTION_ASSERT(!!scope.exception() == !newPromise); return newPromise; } @@ -3348,13 +3350,13 @@ void JSC__AnyPromise__wrap(JSC::JSGlobalObject* globalObject, EncodedJSValue enc scope.clearException(); if (auto* promise = jsDynamicCast(promiseValue)) { - promise->reject(globalObject, exception->value()); + promise->reject(vm, globalObject, exception->value()); RETURN_IF_EXCEPTION(scope, ); return; } if (auto* promise = jsDynamicCast(promiseValue)) { - promise->reject(globalObject, exception->value()); + promise->reject(vm, globalObject, exception->value()); RETURN_IF_EXCEPTION(scope, ); return; } @@ -3364,13 +3366,13 @@ void JSC__AnyPromise__wrap(JSC::JSGlobalObject* globalObject, EncodedJSValue enc if (auto* errorInstance = jsDynamicCast(result)) { if (auto* promise = jsDynamicCast(promiseValue)) { - promise->reject(globalObject, errorInstance); + promise->reject(vm, globalObject, errorInstance); RETURN_IF_EXCEPTION(scope, ); return; } if (auto* promise = jsDynamicCast(promiseValue)) { - promise->reject(globalObject, errorInstance); + promise->reject(vm, globalObject, errorInstance); RETURN_IF_EXCEPTION(scope, ); return; } @@ -3428,7 +3430,7 @@ JSC::EncodedJSValue JSC__JSPromise__wrap(JSC::JSGlobalObject* globalObject, void ASSERT_WITH_MESSAGE(!value.isEmpty(), "Promise.reject cannot be called with a empty JSValue"); auto& vm = JSC::getVM(globalObject); ASSERT_WITH_MESSAGE(arg0->inherits(), "Argument is not a promise"); - ASSERT_WITH_MESSAGE(arg0->status(vm) == JSC::JSPromise::Status::Pending, "Promise is already resolved or rejected"); + ASSERT_WITH_MESSAGE(arg0->status() == JSC::JSPromise::Status::Pending, "Promise is already resolved or rejected"); JSC::Exception* exception = nullptr; if (!value.inherits()) { @@ -3437,15 +3439,16 @@ JSC::EncodedJSValue JSC__JSPromise__wrap(JSC::JSGlobalObject* globalObject, void exception = jsCast(value); } - arg0->reject(globalObject, exception); + arg0->reject(vm, globalObject, exception); } [[ZIG_EXPORT(check_slow)]] void JSC__JSPromise__rejectAsHandled(JSC::JSPromise* arg0, JSC::JSGlobalObject* arg1, JSC::EncodedJSValue JSValue2) { ASSERT_WITH_MESSAGE(arg0->inherits(), "Argument is not a promise"); - ASSERT_WITH_MESSAGE(arg0->status(arg0->vm()) == JSC::JSPromise::Status::Pending, "Promise is already resolved or rejected"); + ASSERT_WITH_MESSAGE(arg0->status() == JSC::JSPromise::Status::Pending, "Promise is already resolved or rejected"); - arg0->rejectAsHandled(arg1, JSC::JSValue::decode(JSValue2)); + auto& vm = JSC::getVM(arg1); + arg0->rejectAsHandled(vm, arg1, JSC::JSValue::decode(JSValue2)); } JSC::JSPromise* JSC__JSPromise__rejectedPromise(JSC::JSGlobalObject* arg0, JSC::EncodedJSValue JSValue1) @@ -3458,7 +3461,7 @@ JSC::JSPromise* JSC__JSPromise__rejectedPromise(JSC::JSGlobalObject* arg0, JSC:: JSValue target = JSValue::decode(JSValue2); ASSERT_WITH_MESSAGE(arg0->inherits(), "Argument is not a promise"); - ASSERT_WITH_MESSAGE(arg0->status(arg0->vm()) == JSC::JSPromise::Status::Pending, "Promise is already resolved or rejected"); + ASSERT_WITH_MESSAGE(arg0->status() == JSC::JSPromise::Status::Pending, "Promise is already resolved or rejected"); ASSERT(!target.isEmpty()); ASSERT_WITH_MESSAGE(arg0 != target, "Promise cannot be resolved to itself"); @@ -3521,12 +3524,8 @@ void JSC__JSPromise__rejectOnNextTickWithHandled(JSC::JSPromise* promise, JSC::J value = jsUndefined(); } - globalObject->queueMicrotask( - microtaskFunction, - rejectPromiseFunction, - globalObject->m_asyncContextData.get()->getInternalField(0), - promise, - value); + JSC::QueuedTask task { nullptr, JSC::InternalMicrotask::BunPerformMicrotaskJob, globalObject, microtaskFunction, rejectPromiseFunction, globalObject->m_asyncContextData.get()->getInternalField(0), promise, value }; + globalObject->vm().queueMicrotask(WTFMove(task)); RETURN_IF_EXCEPTION(scope, ); } } @@ -3546,7 +3545,7 @@ JSC::JSPromise* JSC__JSPromise__resolvedPromise(JSC::JSGlobalObject* globalObjec // if the promise is rejected we automatically mark it as handled so it // doesn't end up in the promise rejection tracker - switch (promise->status(vm)) { + switch (promise->status()) { case JSC::JSPromise::Status::Rejected: { uint32_t flags = promise->internalField(JSC::JSPromise::Field::Flags).get().asUInt32(); if (!(flags & JSC::JSPromise::isFirstResolvingFunctionCalledFlag)) { @@ -3555,16 +3554,16 @@ JSC::JSPromise* JSC__JSPromise__resolvedPromise(JSC::JSGlobalObject* globalObjec } // fallthrough intended case JSC::JSPromise::Status::Fulfilled: { - return JSValue::encode(promise->result(vm)); + return JSValue::encode(promise->result()); } default: return JSValue::encode(JSValue {}); } } -[[ZIG_EXPORT(nothrow)]] uint32_t JSC__JSPromise__status(const JSC::JSPromise* arg0, JSC::VM* arg1) +[[ZIG_EXPORT(nothrow)]] uint32_t JSC__JSPromise__status(const JSC::JSPromise* arg0) { - switch (arg0->status(*arg1)) { + switch (arg0->status()) { case JSC::JSPromise::Status::Pending: return 0; case JSC::JSPromise::Status::Fulfilled: @@ -3575,15 +3574,13 @@ JSC::JSPromise* JSC__JSPromise__resolvedPromise(JSC::JSGlobalObject* globalObjec return 255; } } -[[ZIG_EXPORT(nothrow)]] bool JSC__JSPromise__isHandled(const JSC::JSPromise* arg0, JSC::VM* arg1) +[[ZIG_EXPORT(nothrow)]] bool JSC__JSPromise__isHandled(const JSC::JSPromise* arg0) { - return arg0->isHandled(*arg1); + return arg0->isHandled(); } -[[ZIG_EXPORT(nothrow)]] void JSC__JSPromise__setHandled(JSC::JSPromise* promise, JSC::VM* arg1) +[[ZIG_EXPORT(nothrow)]] void JSC__JSPromise__setHandled(JSC::JSPromise* promise) { - auto& vm = *arg1; - auto flags = promise->internalField(JSC::JSPromise::Field::Flags).get().asUInt32(); - promise->internalField(JSC::JSPromise::Field::Flags).set(vm, promise, jsNumber(flags | JSC::JSPromise::isHandledFlag)); + promise->markAsHandled(); } #pragma mark - JSC::JSInternalPromise @@ -3606,18 +3603,20 @@ void JSC__JSInternalPromise__reject(JSC::JSInternalPromise* arg0, JSC::JSGlobalO exception = jsCast(value); } - arg0->reject(globalObject, exception); + arg0->reject(vm, globalObject, exception); } void JSC__JSInternalPromise__rejectAsHandled(JSC::JSInternalPromise* arg0, JSC::JSGlobalObject* arg1, JSC::EncodedJSValue JSValue2) { - arg0->rejectAsHandled(arg1, JSC::JSValue::decode(JSValue2)); + auto& vm = JSC::getVM(arg1); + arg0->rejectAsHandled(vm, arg1, JSC::JSValue::decode(JSValue2)); } void JSC__JSInternalPromise__rejectAsHandledException(JSC::JSInternalPromise* arg0, JSC::JSGlobalObject* arg1, JSC::Exception* arg2) { - arg0->rejectAsHandled(arg1, arg2); + auto& vm = JSC::getVM(arg1); + arg0->rejectAsHandled(vm, arg1, arg2); } JSC::JSInternalPromise* JSC__JSInternalPromise__rejectedPromise(JSC::JSGlobalObject* arg0, @@ -3640,13 +3639,13 @@ JSC::JSInternalPromise* JSC__JSInternalPromise__resolvedPromise(JSC::JSGlobalObj JSC::JSInternalPromise::resolvedPromise(arg0, JSC::JSValue::decode(JSValue1))); } -JSC::EncodedJSValue JSC__JSInternalPromise__result(const JSC::JSInternalPromise* arg0, JSC::VM* arg1) +JSC::EncodedJSValue JSC__JSInternalPromise__result(const JSC::JSInternalPromise* arg0) { - return JSC::JSValue::encode(arg0->result(*arg1)); + return JSC::JSValue::encode(arg0->result()); } -uint32_t JSC__JSInternalPromise__status(const JSC::JSInternalPromise* arg0, JSC::VM* arg1) +uint32_t JSC__JSInternalPromise__status(const JSC::JSInternalPromise* arg0) { - switch (arg0->status(*arg1)) { + switch (arg0->status()) { case JSC::JSInternalPromise::Status::Pending: return 0; case JSC::JSInternalPromise::Status::Fulfilled: @@ -3657,9 +3656,9 @@ uint32_t JSC__JSInternalPromise__status(const JSC::JSInternalPromise* arg0, JSC: return 255; } } -bool JSC__JSInternalPromise__isHandled(const JSC::JSInternalPromise* arg0, JSC::VM* arg1) +bool JSC__JSInternalPromise__isHandled(const JSC::JSInternalPromise* arg0) { - return arg0->isHandled(*arg1); + return arg0->isHandled(); } void JSC__JSInternalPromise__setHandled(JSC::JSInternalPromise* promise, JSC::VM* arg1) { @@ -4162,7 +4161,7 @@ JSC::EncodedJSValue JSC__JSValue__getIfPropertyExistsFromPath(JSC::EncodedJSValu if (length == 0) { auto* valueObject = value.toObject(globalObject); RETURN_IF_EXCEPTION(scope, {}); - JSValue prop = valueObject->getIfPropertyExists(globalObject, PropertyName(Identifier::EmptyIdentifier)); + JSValue prop = valueObject->getIfPropertyExists(globalObject, vm.propertyNames->emptyIdentifier); RETURN_IF_EXCEPTION(scope, {}); return JSValue::encode(prop); } @@ -4179,7 +4178,7 @@ JSC::EncodedJSValue JSC__JSValue__getIfPropertyExistsFromPath(JSC::EncodedJSValu if (pathString.characterAt(0) == '.') { auto* currPropObject = currProp.toObject(globalObject); RETURN_IF_EXCEPTION(scope, {}); - currProp = currPropObject->getIfPropertyExists(globalObject, PropertyName(Identifier::EmptyIdentifier)); + currProp = currPropObject->getIfPropertyExists(globalObject, vm.propertyNames->emptyIdentifier); RETURN_IF_EXCEPTION(scope, {}); if (currProp.isEmpty()) { return JSValue::encode(currProp); @@ -4195,7 +4194,7 @@ JSC::EncodedJSValue JSC__JSValue__getIfPropertyExistsFromPath(JSC::EncodedJSValu if (ic == '.') { auto* currPropObject = currProp.toObject(globalObject); RETURN_IF_EXCEPTION(scope, {}); - currProp = currPropObject->getIfPropertyExists(globalObject, PropertyName(Identifier::EmptyIdentifier)); + currProp = currPropObject->getIfPropertyExists(globalObject, vm.propertyNames->emptyIdentifier); RETURN_IF_EXCEPTION(scope, {}); return JSValue::encode(currProp); } @@ -4213,7 +4212,7 @@ JSC::EncodedJSValue JSC__JSValue__getIfPropertyExistsFromPath(JSC::EncodedJSValu if (previous == '.' && ic == '.') { auto* currPropObject = currProp.toObject(globalObject); RETURN_IF_EXCEPTION(scope, {}); - currProp = currPropObject->getIfPropertyExists(globalObject, PropertyName(Identifier::EmptyIdentifier)); + currProp = currPropObject->getIfPropertyExists(globalObject, vm.propertyNames->emptyIdentifier); RETURN_IF_EXCEPTION(scope, {}); if (currProp.isEmpty()) { return JSValue::encode(currProp); @@ -5078,7 +5077,7 @@ restart: } } - JSC::PropertyNameArray properties(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); + JSC::PropertyNameArrayBuilder properties(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); { @@ -5248,7 +5247,7 @@ extern "C" [[ZIG_EXPORT(nothrow)]] bool JSC__isBigIntInInt64Range(JSC::EncodedJS auto& vm = JSC::getVM(globalObject); auto scope = DECLARE_CATCH_SCOPE(vm); - JSC::PropertyNameArray properties(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); + JSC::PropertyNameArrayBuilder properties(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); { JSC::JSObject::getOwnPropertyNames(object, globalObject, properties, DontEnumPropertiesMode::Include); @@ -5391,7 +5390,7 @@ extern "C" void JSC__JSGlobalObject__queueMicrotaskJob(JSC::JSGlobalObject* arg0 if (microtaskArgs[3].isEmpty()) { microtaskArgs[3] = jsUndefined(); } - auto microTaskFunction = globalObject->performMicrotaskFunction(); + JSC::JSFunction* microTaskFunction = globalObject->performMicrotaskFunction(); #if ASSERT_ENABLED ASSERT_WITH_MESSAGE(microTaskFunction, "Invalid microtask function"); auto& vm = globalObject->vm(); @@ -5413,12 +5412,8 @@ extern "C" void JSC__JSGlobalObject__queueMicrotaskJob(JSC::JSGlobalObject* arg0 #endif - globalObject->queueMicrotask( - microTaskFunction, - WTFMove(microtaskArgs[0]), - WTFMove(microtaskArgs[1]), - WTFMove(microtaskArgs[2]), - WTFMove(microtaskArgs[3])); + JSC::QueuedTask task { nullptr, JSC::InternalMicrotask::BunPerformMicrotaskJob, globalObject, microTaskFunction, WTFMove(microtaskArgs[0]), WTFMove(microtaskArgs[1]), WTFMove(microtaskArgs[2]), WTFMove(microtaskArgs[3]) }; + globalObject->vm().queueMicrotask(WTFMove(task)); } extern "C" WebCore::AbortSignal* WebCore__AbortSignal__new(JSC::JSGlobalObject* globalObject) diff --git a/src/bun.js/bindings/headers.h b/src/bun.js/bindings/headers.h index f0f02cf835..06e1a7f96a 100644 --- a/src/bun.js/bindings/headers.h +++ b/src/bun.js/bindings/headers.h @@ -137,7 +137,7 @@ CPP_DECL void WebCore__AbortSignal__unref(WebCore::AbortSignal* arg0); CPP_DECL JSC::EncodedJSValue JSC__JSPromise__asValue(JSC::JSPromise* arg0, JSC::JSGlobalObject* arg1); CPP_DECL JSC::JSPromise* JSC__JSPromise__create(JSC::JSGlobalObject* arg0); -CPP_DECL bool JSC__JSPromise__isHandled(const JSC::JSPromise* arg0, JSC::VM* arg1); +CPP_DECL bool JSC__JSPromise__isHandled(const JSC::JSPromise* arg0); CPP_DECL void JSC__JSPromise__reject(JSC::JSPromise* arg0, JSC::JSGlobalObject* arg1, JSC::EncodedJSValue JSValue2); CPP_DECL void JSC__JSPromise__rejectAsHandled(JSC::JSPromise* arg0, JSC::JSGlobalObject* arg1, JSC::EncodedJSValue JSValue2); CPP_DECL JSC::JSPromise* JSC__JSPromise__rejectedPromise(JSC::JSGlobalObject* arg0, JSC::EncodedJSValue JSValue1); @@ -147,22 +147,22 @@ CPP_DECL void JSC__JSPromise__resolve(JSC::JSPromise* arg0, JSC::JSGlobalObject* CPP_DECL JSC::JSPromise* JSC__JSPromise__resolvedPromise(JSC::JSGlobalObject* arg0, JSC::EncodedJSValue JSValue1); CPP_DECL JSC::EncodedJSValue JSC__JSPromise__resolvedPromiseValue(JSC::JSGlobalObject* arg0, JSC::EncodedJSValue JSValue1); CPP_DECL JSC::EncodedJSValue JSC__JSPromise__result(JSC::JSPromise* arg0, JSC::VM* arg1); -CPP_DECL void JSC__JSPromise__setHandled(JSC::JSPromise* arg0, JSC::VM* arg1); -CPP_DECL uint32_t JSC__JSPromise__status(const JSC::JSPromise* arg0, JSC::VM* arg1); +CPP_DECL void JSC__JSPromise__setHandled(JSC::JSPromise* arg0); +CPP_DECL uint32_t JSC__JSPromise__status(const JSC::JSPromise* arg0); #pragma mark - JSC::JSInternalPromise CPP_DECL JSC::JSInternalPromise* JSC__JSInternalPromise__create(JSC::JSGlobalObject* arg0); -CPP_DECL bool JSC__JSInternalPromise__isHandled(const JSC::JSInternalPromise* arg0, JSC::VM* arg1); +CPP_DECL bool JSC__JSInternalPromise__isHandled(const JSC::JSInternalPromise* arg0); CPP_DECL void JSC__JSInternalPromise__reject(JSC::JSInternalPromise* arg0, JSC::JSGlobalObject* arg1, JSC::EncodedJSValue JSValue2); CPP_DECL void JSC__JSInternalPromise__rejectAsHandled(JSC::JSInternalPromise* arg0, JSC::JSGlobalObject* arg1, JSC::EncodedJSValue JSValue2); CPP_DECL void JSC__JSInternalPromise__rejectAsHandledException(JSC::JSInternalPromise* arg0, JSC::JSGlobalObject* arg1, JSC::Exception* arg2); CPP_DECL JSC::JSInternalPromise* JSC__JSInternalPromise__rejectedPromise(JSC::JSGlobalObject* arg0, JSC::EncodedJSValue JSValue1); CPP_DECL void JSC__JSInternalPromise__resolve(JSC::JSInternalPromise* arg0, JSC::JSGlobalObject* arg1, JSC::EncodedJSValue JSValue2); CPP_DECL JSC::JSInternalPromise* JSC__JSInternalPromise__resolvedPromise(JSC::JSGlobalObject* arg0, JSC::EncodedJSValue JSValue1); -CPP_DECL JSC::EncodedJSValue JSC__JSInternalPromise__result(const JSC::JSInternalPromise* arg0, JSC::VM* arg1); +CPP_DECL JSC::EncodedJSValue JSC__JSInternalPromise__result(const JSC::JSInternalPromise* arg0); CPP_DECL void JSC__JSInternalPromise__setHandled(JSC::JSInternalPromise* arg0, JSC::VM* arg1); -CPP_DECL uint32_t JSC__JSInternalPromise__status(const JSC::JSInternalPromise* arg0, JSC::VM* arg1); +CPP_DECL uint32_t JSC__JSInternalPromise__status(const JSC::JSInternalPromise* arg0); #pragma mark - JSC::JSFunction diff --git a/src/bun.js/bindings/helpers.h b/src/bun.js/bindings/helpers.h index 8c1a40dd1e..4e69126a00 100644 --- a/src/bun.js/bindings/helpers.h +++ b/src/bun.js/bindings/helpers.h @@ -122,9 +122,9 @@ static WTF::AtomString toAtomString(ZigString str) { if (!isTaggedUTF16Ptr(str.ptr)) { - return makeAtomString(untag(str.ptr), str.len); + return makeAtomString(std::span(untag(str.ptr), str.len)); } else { - return makeAtomString(reinterpret_cast(untag(str.ptr)), str.len); + return makeAtomString(std::span(reinterpret_cast(untag(str.ptr)), str.len)); } } @@ -419,7 +419,7 @@ static JSC::JSValue getRangeErrorInstance(const ZigString* str, JSC::JSGlobalObj static const JSC::Identifier toIdentifier(ZigString str, JSC::JSGlobalObject* global) { if (str.len == 0 || str.ptr == nullptr) { - return JSC::Identifier::EmptyIdentifier; + return global->vm().propertyNames->emptyIdentifier; } WTF::String wtfstr = Zig::isTaggedExternalPtr(str.ptr) ? toString(str) : Zig::toStringCopy(str); JSC::Identifier id = JSC::Identifier::fromString(global->vm(), wtfstr); diff --git a/src/bun.js/bindings/node/http/JSConnectionsList.cpp b/src/bun.js/bindings/node/http/JSConnectionsList.cpp index a1660fa836..f6c29623aa 100644 --- a/src/bun.js/bindings/node/http/JSConnectionsList.cpp +++ b/src/bun.js/bindings/node/http/JSConnectionsList.cpp @@ -56,7 +56,7 @@ JSArray* JSConnectionsList::all(JSGlobalObject* globalObject) JSArray* result = constructEmptyArray(globalObject, nullptr, all->size()); RETURN_IF_EXCEPTION(scope, {}); - auto iter = JSSetIterator::create(globalObject, globalObject->setIteratorStructure(), all, IterationKind::Keys); + auto iter = JSSetIterator::create(vm, globalObject->setIteratorStructure(), all, IterationKind::Keys); RETURN_IF_EXCEPTION(scope, nullptr); JSValue item; @@ -82,7 +82,7 @@ JSArray* JSConnectionsList::idle(JSGlobalObject* globalObject) JSArray* result = constructEmptyArray(globalObject, nullptr); RETURN_IF_EXCEPTION(scope, {}); - auto iter = JSSetIterator::create(globalObject, globalObject->setIteratorStructure(), all, IterationKind::Keys); + auto iter = JSSetIterator::create(vm, globalObject->setIteratorStructure(), all, IterationKind::Keys); RETURN_IF_EXCEPTION(scope, nullptr); JSValue item; @@ -110,7 +110,7 @@ JSArray* JSConnectionsList::active(JSGlobalObject* globalObject) JSArray* result = constructEmptyArray(globalObject, nullptr, active->size()); RETURN_IF_EXCEPTION(scope, {}); - auto iter = JSSetIterator::create(globalObject, globalObject->setIteratorStructure(), active, IterationKind::Keys); + auto iter = JSSetIterator::create(vm, globalObject->setIteratorStructure(), active, IterationKind::Keys); RETURN_IF_EXCEPTION(scope, nullptr); JSValue item; @@ -136,7 +136,7 @@ JSArray* JSConnectionsList::expired(JSGlobalObject* globalObject, uint64_t heade JSArray* result = constructEmptyArray(globalObject, nullptr); RETURN_IF_EXCEPTION(scope, {}); - auto iter = JSSetIterator::create(globalObject, globalObject->setIteratorStructure(), active, IterationKind::Keys); + auto iter = JSSetIterator::create(vm, globalObject->setIteratorStructure(), active, IterationKind::Keys); RETURN_IF_EXCEPTION(scope, nullptr); JSValue item = iter->next(vm); diff --git a/src/bun.js/bindings/sqlite/JSSQLStatement.cpp b/src/bun.js/bindings/sqlite/JSSQLStatement.cpp index d79e683678..1e25404657 100644 --- a/src/bun.js/bindings/sqlite/JSSQLStatement.cpp +++ b/src/bun.js/bindings/sqlite/JSSQLStatement.cpp @@ -376,7 +376,7 @@ public: if (name == nullptr) { indexedCount++; if (hasLoadedBindingNames) { - bindingNames[i] = Identifier(Identifier::EmptyIdentifier); + bindingNames[i] = Identifier(Identifier::EmptyIdentifierFlag::EmptyIdentifier); } continue; } @@ -467,7 +467,7 @@ public: // Tracks which columns are valid in the current result set. Used to handle duplicate column names. // The bit at index i is set if the column at index i is valid. WTF::BitVector validColumns; - std::unique_ptr columnNames; + std::unique_ptr columnNames; mutable JSC::WriteBarrier _prototype; mutable JSC::WriteBarrier _structure; mutable JSC::WriteBarrier userPrototype; @@ -481,7 +481,7 @@ protected: : Base(globalObject.vm(), structure) , stmt(stmt) , version_db(version_db) - , columnNames(new PropertyNameArray(globalObject.vm(), PropertyNameMode::Strings, PrivateSymbolMode::Exclude)) + , columnNames(new PropertyNameArrayBuilder(globalObject.vm(), PropertyNameMode::Strings, PrivateSymbolMode::Exclude)) , extraMemorySize(memorySizeChange > 0 ? memorySizeChange : 0) { } @@ -673,7 +673,7 @@ static void initializeColumnNames(JSC::JSGlobalObject* lexicalGlobalObject, JSSQ castedThis->hasExecuted = true; } else { // reinitialize column - castedThis->columnNames.reset(new PropertyNameArray( + castedThis->columnNames.reset(new PropertyNameArrayBuilder( castedThis->columnNames->vm(), castedThis->columnNames->propertyNameMode(), castedThis->columnNames->privateSymbolMode())); @@ -749,7 +749,7 @@ static void initializeColumnNames(JSC::JSGlobalObject* lexicalGlobalObject, JSSQ } else { // If for any reason we do not have column names, disable the fast path. columnNames->releaseData(); - castedThis->columnNames.reset(new PropertyNameArray( + castedThis->columnNames.reset(new PropertyNameArrayBuilder( castedThis->columnNames->vm(), castedThis->columnNames->propertyNameMode(), castedThis->columnNames->privateSymbolMode())); @@ -955,7 +955,7 @@ static JSC::JSValue rebindObject(JSC::JSGlobalObject* globalObject, SQLiteBindin JSValue value = getValue(name, i); if (!value && !scope.exception()) { if (throwOnMissing) { - throwException(globalObject, scope, createError(globalObject, makeString("Missing parameter \""_s, reinterpret_cast(name), "\""_s))); + throwException(globalObject, scope, createError(globalObject, makeString("Missing parameter \""_s, WTF::String::fromUTF8ReplacingInvalidSequences({ reinterpret_cast(name), strlen(name) }), "\""_s))); } else { continue; } diff --git a/src/bun.js/bindings/webcore/AbortSignal.h b/src/bun.js/bindings/webcore/AbortSignal.h index 68ded5d832..38c50d4668 100644 --- a/src/bun.js/bindings/webcore/AbortSignal.h +++ b/src/bun.js/bindings/webcore/AbortSignal.h @@ -95,7 +95,11 @@ public: CommonAbortReason commonReason() const { return m_commonReason; } void cleanNativeBindings(void* ref); - void addNativeCallback(NativeCallbackTuple callback) { m_native_callbacks.append(callback); } + void addNativeCallback(NativeCallbackTuple callback) + { + m_native_callbacks.append(callback); + eventListenersDidChange(); + } bool hasActiveTimeoutTimer() const { return m_timeout != nullptr; } bool hasAbortEventListener() const { return m_flags & static_cast(AbortSignalFlags::HasAbortEventListener); } diff --git a/src/bun.js/bindings/webcore/JSBroadcastChannel.cpp b/src/bun.js/bindings/webcore/JSBroadcastChannel.cpp index 55be2327e6..ae86b895dc 100644 --- a/src/bun.js/bindings/webcore/JSBroadcastChannel.cpp +++ b/src/bun.js/bindings/webcore/JSBroadcastChannel.cpp @@ -188,7 +188,7 @@ JSC_DEFINE_HOST_FUNCTION(jsBroadcastChannelPrototype_inspectCustom, (JSC::JSGlob JSObject* options = optionsValue.toObject(lexicalGlobalObject); RETURN_IF_EXCEPTION(throwScope, {}); - PropertyNameArray optionsArray(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); + PropertyNameArrayBuilder optionsArray(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); options->getPropertyNames(lexicalGlobalObject, optionsArray, DontEnumPropertiesMode::Exclude); RETURN_IF_EXCEPTION(throwScope, {}); diff --git a/src/bun.js/bindings/webcore/JSCookieMap.cpp b/src/bun.js/bindings/webcore/JSCookieMap.cpp index ecebad0b37..b97bc8aba4 100644 --- a/src/bun.js/bindings/webcore/JSCookieMap.cpp +++ b/src/bun.js/bindings/webcore/JSCookieMap.cpp @@ -153,7 +153,7 @@ template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSCookieMapDOMConstructo // Handle as record HashMap record; - PropertyNameArray propertyNames(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); + PropertyNameArrayBuilder propertyNames(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); JSObject::getOwnPropertyNames(object, lexicalGlobalObject, propertyNames, DontEnumPropertiesMode::Include); RETURN_IF_EXCEPTION(throwScope, {}); diff --git a/src/bun.js/bindings/webcore/JSDOMConvertRecord.h b/src/bun.js/bindings/webcore/JSDOMConvertRecord.h index e6caa4e989..9e2d08b70e 100644 --- a/src/bun.js/bindings/webcore/JSDOMConvertRecord.h +++ b/src/bun.js/bindings/webcore/JSDOMConvertRecord.h @@ -164,7 +164,7 @@ private: } // 4. Let keys be ? O.[[OwnPropertyKeys]](). - JSC::PropertyNameArray keys(vm, JSC::PropertyNameMode::StringsAndSymbols, JSC::PrivateSymbolMode::Exclude); + JSC::PropertyNameArrayBuilder keys(vm, JSC::PropertyNameMode::StringsAndSymbols, JSC::PrivateSymbolMode::Exclude); object->methodTable()->getOwnPropertyNames(object, &lexicalGlobalObject, keys, JSC::DontEnumPropertiesMode::Include); RETURN_IF_EXCEPTION(scope, {}); diff --git a/src/bun.js/bindings/webcore/JSDOMPromise.cpp b/src/bun.js/bindings/webcore/JSDOMPromise.cpp index 1403399c48..a8ec36dea6 100644 --- a/src/bun.js/bindings/webcore/JSDOMPromise.cpp +++ b/src/bun.js/bindings/webcore/JSDOMPromise.cpp @@ -76,12 +76,12 @@ auto DOMPromise::whenPromiseIsSettled(JSDOMGlobalObject* globalObject, JSC::JSOb JSC::JSValue DOMPromise::result() const { - return promise()->result(m_globalObject->vm()); + return promise()->result(); } DOMPromise::Status DOMPromise::status() const { - switch (promise()->status(m_globalObject->vm())) { + switch (promise()->status()) { case JSC::JSPromise::Status::Pending: return Status::Pending; case JSC::JSPromise::Status::Fulfilled: diff --git a/src/bun.js/bindings/webcore/JSDOMPromiseDeferred.cpp b/src/bun.js/bindings/webcore/JSDOMPromiseDeferred.cpp index 63ce534b43..e4799696e3 100644 --- a/src/bun.js/bindings/webcore/JSDOMPromiseDeferred.cpp +++ b/src/bun.js/bindings/webcore/JSDOMPromiseDeferred.cpp @@ -74,15 +74,16 @@ void DeferredPromise::callFunction(JSGlobalObject& lexicalGlobalObject, ResolveM // FIXME: We could have error since any JS call can throw stack-overflow errors. // https://bugs.webkit.org/show_bug.cgi?id=203402 + auto& vm = lexicalGlobalObject.vm(); switch (mode) { case ResolveMode::Resolve: deferred()->resolve(&lexicalGlobalObject, resolution); break; case ResolveMode::Reject: - deferred()->reject(&lexicalGlobalObject, resolution); + deferred()->reject(vm, &lexicalGlobalObject, resolution); break; case ResolveMode::RejectAsHandled: - deferred()->rejectAsHandled(&lexicalGlobalObject, resolution); + deferred()->rejectAsHandled(vm, &lexicalGlobalObject, resolution); break; } @@ -236,25 +237,14 @@ void rejectPromiseWithExceptionIfAny(JSC::JSGlobalObject& lexicalGlobalObject, J JSC::EncodedJSValue createRejectedPromiseWithTypeError(JSC::JSGlobalObject& lexicalGlobalObject, const String& errorMessage, RejectedPromiseWithTypeErrorCause cause) { - auto& globalObject = lexicalGlobalObject; auto& vm = lexicalGlobalObject.vm(); auto scope = DECLARE_THROW_SCOPE(vm); - auto promiseConstructor = globalObject.promiseConstructor(); - auto rejectFunction = promiseConstructor->get(&lexicalGlobalObject, vm.propertyNames->builtinNames().rejectPrivateName()); - RETURN_IF_EXCEPTION(scope, {}); ErrorInstance* rejectionValue = static_cast(cause == RejectedPromiseWithTypeErrorCause::InvalidThis ? Bun::createInvalidThisError(&lexicalGlobalObject, errorMessage) : createTypeError(&lexicalGlobalObject, errorMessage)); if (cause == RejectedPromiseWithTypeErrorCause::NativeGetter) rejectionValue->setNativeGetterTypeError(); - auto callData = JSC::getCallData(rejectFunction); - ASSERT(callData.type != CallData::Type::None); - - MarkedArgumentBuffer arguments; - arguments.append(rejectionValue); - ASSERT(!arguments.hasOverflowed()); - - RELEASE_AND_RETURN(scope, JSValue::encode(call(&lexicalGlobalObject, rejectFunction, callData, promiseConstructor, arguments))); + RELEASE_AND_RETURN(scope, JSValue::encode(JSC::JSPromise::rejectedPromise(&lexicalGlobalObject, rejectionValue))); } static inline JSC::JSValue parseAsJSON(JSC::JSGlobalObject* lexicalGlobalObject, const String& data) diff --git a/src/bun.js/bindings/webcore/JSMIMEParams.cpp b/src/bun.js/bindings/webcore/JSMIMEParams.cpp index d00418d49d..f9991719fc 100644 --- a/src/bun.js/bindings/webcore/JSMIMEParams.cpp +++ b/src/bun.js/bindings/webcore/JSMIMEParams.cpp @@ -519,7 +519,7 @@ JSC_DEFINE_HOST_FUNCTION(jsMIMEParamsProtoFuncToString, (JSGlobalObject * global StringBuilder builder; bool first = true; - JSValue iteratorValue = JSMapIterator::create(globalObject, globalObject->mapIteratorStructure(), map, IterationKind::Entries); + JSValue iteratorValue = JSMapIterator::create(vm, globalObject->mapIteratorStructure(), map, IterationKind::Entries); RETURN_IF_EXCEPTION(scope, encodedJSValue()); JSMapIterator* iterator = jsDynamicCast(iteratorValue); if (!iterator) { // Should not happen for JSMap.entries() @@ -559,35 +559,38 @@ JSC_DEFINE_HOST_FUNCTION(jsMIMEParamsProtoFuncToString, (JSGlobalObject * global JSC_DEFINE_HOST_FUNCTION(jsMIMEParamsProtoFuncEntries, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); auto* thisObject = jsDynamicCast(callFrame->thisValue()); if (!thisObject) [[unlikely]] { scope.throwException(globalObject, Bun::createInvalidThisError(globalObject, thisObject, "MIMEParams")); RETURN_IF_EXCEPTION(scope, {}); } - RELEASE_AND_RETURN(scope, JSValue::encode(JSMapIterator::create(globalObject, globalObject->mapIteratorStructure(), thisObject->jsMap(), IterationKind::Entries))); + RELEASE_AND_RETURN(scope, JSValue::encode(JSMapIterator::create(vm, globalObject->mapIteratorStructure(), thisObject->jsMap(), IterationKind::Entries))); } JSC_DEFINE_HOST_FUNCTION(jsMIMEParamsProtoFuncKeys, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); auto* thisObject = jsDynamicCast(callFrame->thisValue()); if (!thisObject) [[unlikely]] { scope.throwException(globalObject, Bun::createInvalidThisError(globalObject, thisObject, "MIMEParams")); RETURN_IF_EXCEPTION(scope, {}); } - RELEASE_AND_RETURN(scope, JSValue::encode(JSMapIterator::create(globalObject, globalObject->mapIteratorStructure(), thisObject->jsMap(), IterationKind::Keys))); + RELEASE_AND_RETURN(scope, JSValue::encode(JSMapIterator::create(vm, globalObject->mapIteratorStructure(), thisObject->jsMap(), IterationKind::Keys))); } JSC_DEFINE_HOST_FUNCTION(jsMIMEParamsProtoFuncValues, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); + VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); auto* thisObject = jsDynamicCast(callFrame->thisValue()); if (!thisObject) [[unlikely]] { scope.throwException(globalObject, Bun::createInvalidThisError(globalObject, thisObject, "MIMEParams")); RETURN_IF_EXCEPTION(scope, {}); } - RELEASE_AND_RETURN(scope, JSValue::encode(JSMapIterator::create(globalObject, globalObject->mapIteratorStructure(), thisObject->jsMap(), IterationKind::Values))); + RELEASE_AND_RETURN(scope, JSValue::encode(JSMapIterator::create(vm, globalObject->mapIteratorStructure(), thisObject->jsMap(), IterationKind::Values))); } // Forward declare constructor functions diff --git a/src/bun.js/bindings/webcore/JSWorker.cpp b/src/bun.js/bindings/webcore/JSWorker.cpp index 2dcff5555d..bf44513e49 100644 --- a/src/bun.js/bindings/webcore/JSWorker.cpp +++ b/src/bun.js/bindings/webcore/JSWorker.cpp @@ -251,7 +251,7 @@ template<> JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSWorkerDOMConstructor:: RETURN_IF_EXCEPTION(throwScope, {}); } - JSC::PropertyNameArray keys(vm, JSC::PropertyNameMode::Strings, JSC::PrivateSymbolMode::Exclude); + JSC::PropertyNameArrayBuilder keys(vm, JSC::PropertyNameMode::Strings, JSC::PrivateSymbolMode::Exclude); envObject->methodTable()->getOwnPropertyNames(envObject, lexicalGlobalObject, keys, JSC::DontEnumPropertiesMode::Exclude); RETURN_IF_EXCEPTION(throwScope, {}); @@ -680,7 +680,7 @@ static inline JSC::EncodedJSValue jsWorkerPrototypeFunction_getHeapSnapshotBody( auto* promise = JSC::JSPromise::create(vm, globalObject->promiseStructure()); if (!worker.isOnline()) { - promise->reject(globalObject, + promise->reject(vm, globalObject, Bun::createError(globalObject, Bun::ErrorCode::ERR_WORKER_NOT_RUNNING, "Worker instance not running"_s)); diff --git a/src/bun.js/bindings/webcore/SerializedScriptValue.cpp b/src/bun.js/bindings/webcore/SerializedScriptValue.cpp index bc7a596710..751a1bac48 100644 --- a/src/bun.js/bindings/webcore/SerializedScriptValue.cpp +++ b/src/bun.js/bindings/webcore/SerializedScriptValue.cpp @@ -2578,7 +2578,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) VM& vm = m_lexicalGlobalObject->vm(); Vector indexStack; Vector lengthStack; - Vector propertyStack; + Vector propertyStack; Vector inputObjectStack; Vector mapIteratorStack; Vector setIteratorStack; @@ -2612,7 +2612,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) indexStack.removeLast(); lengthStack.removeLast(); - propertyStack.append(PropertyNameArray(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude)); + propertyStack.append(PropertyNameArrayBuilder(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude)); array->getOwnNonIndexPropertyNames(m_lexicalGlobalObject, propertyStack.last(), DontEnumPropertiesMode::Exclude); RETURN_IF_EXCEPTION(scope, SerializationReturnCode::ExistingExceptionError); if (propertyStack.last().size()) { @@ -2666,7 +2666,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) return SerializationReturnCode::DataCloneError; inputObjectStack.append(inObject); indexStack.append(0); - propertyStack.append(PropertyNameArray(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude)); + propertyStack.append(PropertyNameArrayBuilder(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude)); inObject->methodTable()->getOwnPropertyNames(inObject, m_lexicalGlobalObject, propertyStack.last(), DontEnumPropertiesMode::Exclude); RETURN_IF_EXCEPTION(scope, SerializationReturnCode::ExistingExceptionError); } @@ -2675,7 +2675,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) case ObjectStartVisitMember: { JSObject* object = inputObjectStack.last(); uint32_t index = indexStack.last(); - PropertyNameArray& properties = propertyStack.last(); + PropertyNameArrayBuilder& properties = propertyStack.last(); if (index == properties.size()) { endObject(); inputObjectStack.removeLast(); @@ -2719,7 +2719,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) JSMap* inMap = jsCast(inValue); if (!startMap(inMap)) break; - JSMapIterator* iterator = JSMapIterator::create(m_lexicalGlobalObject, m_lexicalGlobalObject->mapIteratorStructure(), inMap, IterationKind::Entries); + JSMapIterator* iterator = JSMapIterator::create(vm, m_lexicalGlobalObject->mapIteratorStructure(), inMap, IterationKind::Entries); RETURN_IF_EXCEPTION(scope, SerializationReturnCode::ExistingExceptionError); m_gcBuffer.appendWithCrashOnOverflow(inMap); m_gcBuffer.appendWithCrashOnOverflow(iterator); @@ -2735,7 +2735,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) mapIteratorStack.removeLast(); JSObject* object = inputObjectStack.last(); ASSERT(jsDynamicCast(object)); - propertyStack.append(PropertyNameArray(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude)); + propertyStack.append(PropertyNameArrayBuilder(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude)); object->methodTable()->getOwnPropertyNames(object, m_lexicalGlobalObject, propertyStack.last(), DontEnumPropertiesMode::Exclude); RETURN_IF_EXCEPTION(scope, SerializationReturnCode::ExistingExceptionError); write(NonMapPropertiesTag); @@ -2765,7 +2765,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) JSSet* inSet = jsCast(inValue); if (!startSet(inSet)) break; - JSSetIterator* iterator = JSSetIterator::create(m_lexicalGlobalObject, m_lexicalGlobalObject->setIteratorStructure(), inSet, IterationKind::Keys); + JSSetIterator* iterator = JSSetIterator::create(vm, m_lexicalGlobalObject->setIteratorStructure(), inSet, IterationKind::Keys); RETURN_IF_EXCEPTION(scope, SerializationReturnCode::ExistingExceptionError); m_gcBuffer.appendWithCrashOnOverflow(inSet); m_gcBuffer.appendWithCrashOnOverflow(iterator); @@ -2781,7 +2781,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) setIteratorStack.removeLast(); JSObject* object = inputObjectStack.last(); ASSERT(jsDynamicCast(object)); - propertyStack.append(PropertyNameArray(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude)); + propertyStack.append(PropertyNameArrayBuilder(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude)); object->methodTable()->getOwnPropertyNames(object, m_lexicalGlobalObject, propertyStack.last(), DontEnumPropertiesMode::Exclude); RETURN_IF_EXCEPTION(scope, SerializationReturnCode::ExistingExceptionError); write(NonSetPropertiesTag); diff --git a/src/bun.js/bindings/webcore/WebSocket.cpp b/src/bun.js/bindings/webcore/WebSocket.cpp index ce9fff153c..6ce10f2119 100644 --- a/src/bun.js/bindings/webcore/WebSocket.cpp +++ b/src/bun.js/bindings/webcore/WebSocket.cpp @@ -557,7 +557,8 @@ ExceptionOr WebSocket::send(ArrayBufferView& arrayBufferView) return {}; } - auto buffer = arrayBufferView.unsharedBuffer().get(); + auto bufferRef = arrayBufferView.unsharedBuffer(); + auto* buffer = bufferRef.get(); char* baseAddress = reinterpret_cast(buffer->data()) + arrayBufferView.byteOffset(); size_t length = arrayBufferView.byteLength(); this->sendWebSocketData(baseAddress, length, Opcode::Binary); @@ -831,7 +832,8 @@ ExceptionOr WebSocket::ping(ArrayBufferView& arrayBufferView) return {}; } - auto buffer = arrayBufferView.unsharedBuffer().get(); + auto bufferRef = arrayBufferView.unsharedBuffer(); + auto* buffer = bufferRef.get(); char* baseAddress = reinterpret_cast(buffer->data()) + arrayBufferView.byteOffset(); size_t length = arrayBufferView.byteLength(); this->sendWebSocketData(baseAddress, length, Opcode::Ping); @@ -913,7 +915,8 @@ ExceptionOr WebSocket::pong(ArrayBufferView& arrayBufferView) return {}; } - auto buffer = arrayBufferView.unsharedBuffer().get(); + auto bufferRef = arrayBufferView.unsharedBuffer(); + auto* buffer = bufferRef.get(); char* baseAddress = reinterpret_cast(buffer->data()) + arrayBufferView.byteOffset(); size_t length = arrayBufferView.byteLength(); this->sendWebSocketData(baseAddress, length, Opcode::Pong); diff --git a/src/bun.js/event_loop.zig b/src/bun.js/event_loop.zig index fa01d046a5..cd017e7fb3 100644 --- a/src/bun.js/event_loop.zig +++ b/src/bun.js/event_loop.zig @@ -523,12 +523,17 @@ pub fn tickWithoutJS(this: *EventLoop) void { pub fn waitForPromise(this: *EventLoop, promise: jsc.AnyPromise) void { const jsc_vm = this.virtual_machine.jsc_vm; - switch (promise.status(jsc_vm)) { + switch (promise.status()) { .pending => { - while (promise.status(jsc_vm) == .pending) { + while (promise.status() == .pending) { + // If execution is forbidden (e.g. due to a timeout in vm.SourceTextModule.evaluate), + // the Promise callbacks can never run, so we must exit to avoid an infinite loop. + if (jsc_vm.executionForbidden()) { + break; + } this.tick(); - if (promise.status(jsc_vm) == .pending) { + if (promise.status() == .pending) { this.autoTick(); } } @@ -539,13 +544,12 @@ pub fn waitForPromise(this: *EventLoop, promise: jsc.AnyPromise) void { pub fn waitForPromiseWithTermination(this: *EventLoop, promise: jsc.AnyPromise) void { const worker = this.virtual_machine.worker orelse @panic("EventLoop.waitForPromiseWithTermination: worker is not initialized"); - const jsc_vm = this.virtual_machine.jsc_vm; - switch (promise.status(jsc_vm)) { + switch (promise.status()) { .pending => { - while (!worker.hasRequestedTerminate() and promise.status(jsc_vm) == .pending) { + while (!worker.hasRequestedTerminate() and promise.status() == .pending) { this.tick(); - if (!worker.hasRequestedTerminate() and promise.status(jsc_vm) == .pending) { + if (!worker.hasRequestedTerminate() and promise.status() == .pending) { this.autoTick(); } } diff --git a/src/bun.js/modules/BunJSCModule.h b/src/bun.js/modules/BunJSCModule.h index 461b04c679..5fa2aca13d 100644 --- a/src/bun.js/modules/BunJSCModule.h +++ b/src/bun.js/modules/BunJSCModule.h @@ -115,7 +115,7 @@ JSC_DEFINE_HOST_FUNCTION(functionStartRemoteDebugger, globalObject, scope, createError(globalObject, makeString("Failed to start server \""_s, - reinterpret_cast(host), + String::fromLatin1(host), ":"_s, port, "\". Is port already in use?"_s))); return JSC::JSValue::encode(JSC::jsUndefined()); } @@ -718,7 +718,7 @@ JSC_DEFINE_HOST_FUNCTION(functionRunProfiler, (JSGlobalObject * globalObject, Ca throwException(globalObject, scope, error.value()); return JSValue::encode({}); }); - promise->performPromiseThen(globalObject, resolve, reject, afterOngoingPromiseCapability); + promise->performPromiseThen(vm, globalObject, resolve, reject, afterOngoingPromiseCapability); RETURN_IF_EXCEPTION(throwScope, {}); return JSValue::encode(afterOngoingPromiseCapability); } diff --git a/src/bun.js/modules/BunTestModule.h b/src/bun.js/modules/BunTestModule.h index 1aaf824701..410e597ad2 100644 --- a/src/bun.js/modules/BunTestModule.h +++ b/src/bun.js/modules/BunTestModule.h @@ -17,14 +17,14 @@ void generateNativeModule_BunTest( exportValues.append(object); // Also export all properties as named exports - JSC::PropertyNameArray properties(vm, JSC::PropertyNameMode::Strings, JSC::PrivateSymbolMode::Exclude); + JSC::PropertyNameArrayBuilder properties(vm, JSC::PropertyNameMode::Strings, JSC::PrivateSymbolMode::Exclude); object->methodTable()->getOwnPropertyNames(object, lexicalGlobalObject, properties, JSC::DontEnumPropertiesMode::Exclude); if (catchScope.exception()) [[unlikely]] { catchScope.clearException(); return; } - for (auto& property : properties) { + for (auto& property : properties.releaseData()->propertyNameVector()) { JSC::PropertySlot slot(object, JSC::PropertySlot::InternalMethodType::Get); auto ownPropertySlot = object->methodTable()->getOwnPropertySlot(object, lexicalGlobalObject, property, slot); if (catchScope.exception()) [[unlikely]] { diff --git a/src/bun.js/modules/NodeModuleModule.cpp b/src/bun.js/modules/NodeModuleModule.cpp index c0e5355b63..ac72ec7970 100644 --- a/src/bun.js/modules/NodeModuleModule.cpp +++ b/src/bun.js/modules/NodeModuleModule.cpp @@ -801,7 +801,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionRunMain, (JSGlobalObject * globalObject, JSC: RETURN_IF_EXCEPTION(scope, {}); JSC::JSNativeStdFunction* resolverFunction = JSC::JSNativeStdFunction::create(vm, globalObject, 1, String(), resolverFunctionCallback); - auto result = promise->then(globalObject, resolverFunction, nullptr); + auto result = promise->then(globalObject, resolverFunction, globalObject->promiseEmptyOnRejectedFunction()); RETURN_IF_EXCEPTION(scope, {}); Bun__VirtualMachine__setOverrideModuleRunMainPromise(defaultGlobalObject(globalObject)->bunVM(), result); diff --git a/src/bun.js/modules/NodeProcessModule.h b/src/bun.js/modules/NodeProcessModule.h index 1f74843ac8..071998af57 100644 --- a/src/bun.js/modules/NodeProcessModule.h +++ b/src/bun.js/modules/NodeProcessModule.h @@ -18,14 +18,14 @@ DEFINE_NATIVE_MODULE(NodeProcess) RETURN_IF_EXCEPTION(scope, ); } - PropertyNameArray properties(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); + PropertyNameArrayBuilder properties(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); process->getPropertyNames(globalObject, properties, DontEnumPropertiesMode::Exclude); RETURN_IF_EXCEPTION(scope, ); exportNames.append(vm.propertyNames->defaultKeyword); exportValues.append(process); - for (auto& entry : properties) { + for (auto& entry : properties.releaseData()->propertyNameVector()) { if (entry == vm.propertyNames->defaultKeyword) { // skip because it's already on the default // export (the Process object itself) diff --git a/src/bun.js/modules/ObjectModule.cpp b/src/bun.js/modules/ObjectModule.cpp index 67a8aa9252..d5accd979b 100644 --- a/src/bun.js/modules/ObjectModule.cpp +++ b/src/bun.js/modules/ObjectModule.cpp @@ -15,13 +15,13 @@ generateObjectModuleSourceCode(JSC::JSGlobalObject* globalObject, GlobalObject* globalObject = defaultGlobalObject(lexicalGlobalObject); JSC::EnsureStillAliveScope stillAlive(object); - PropertyNameArray properties(vm, PropertyNameMode::Strings, + PropertyNameArrayBuilder properties(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); object->methodTable()->getOwnPropertyNames(object, globalObject, properties, DontEnumPropertiesMode::Exclude); RETURN_IF_EXCEPTION(throwScope, void()); gcUnprotectNullTolerant(object); - for (auto& entry : properties) { + for (auto& entry : properties.releaseData()->propertyNameVector()) { exportNames.append(entry); auto scope = DECLARE_CATCH_SCOPE(vm); @@ -49,7 +49,7 @@ generateObjectModuleSourceCodeForJSON(JSC::JSGlobalObject* globalObject, GlobalObject* globalObject = reinterpret_cast(lexicalGlobalObject); JSC::EnsureStillAliveScope stillAlive(object); - PropertyNameArray properties(vm, PropertyNameMode::Strings, + PropertyNameArrayBuilder properties(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); object->getPropertyNames(globalObject, properties, DontEnumPropertiesMode::Exclude); RETURN_IF_EXCEPTION(scope, {}); @@ -58,7 +58,7 @@ generateObjectModuleSourceCodeForJSON(JSC::JSGlobalObject* globalObject, exportNames.append(vm.propertyNames->defaultKeyword); exportValues.append(object); - for (auto& entry : properties) { + for (auto& entry : properties.releaseData()->propertyNameVector()) { if (entry == vm.propertyNames->defaultKeyword) { continue; } diff --git a/src/bun.js/test/bun_test.zig b/src/bun.js/test/bun_test.zig index 6c11e9b624..c8879d623e 100644 --- a/src/bun.js/test/bun_test.zig +++ b/src/bun.js/test/bun_test.zig @@ -654,8 +654,8 @@ pub const BunTest = struct { // Prevent the user's Promise rejection from going into the uncaught promise rejection queue. if (result != .zero) if (result.asPromise()) |promise| - if (promise.status(globalThis.vm()) == .rejected) - promise.setHandled(globalThis.vm()); + if (promise.status() == .rejected) + promise.setHandled(); const prev_unhandled_count = vm.unhandled_error_counter; globalThis.handleRejectedPromises(); @@ -681,7 +681,7 @@ pub const BunTest = struct { group.log("callTestCallback -> promise: data {f}", .{cfg_data}); - switch (promise.status(globalThis.vm())) { + switch (promise.status()) { .pending => { // not immediately resolved; register 'then' to handle the result when it becomes available const this_ref: *RefData = if (dcb_ref) |dcb_ref_value| dcb_ref_value.dupe() else ref(this_strong, cfg_data); diff --git a/src/bun.js/test/expect.zig b/src/bun.js/test/expect.zig index ae4bb1f3f6..68b7ac78c8 100644 --- a/src/bun.js/test/expect.zig +++ b/src/bun.js/test/expect.zig @@ -183,7 +183,7 @@ pub const Expect = struct { globalThis.bunVM().waitForPromise(promise); const newValue = promise.result(vm); - switch (promise.status(vm)) { + switch (promise.status()) { .fulfilled => switch (resolution) { .resolves => {}, .rejects => { @@ -1055,7 +1055,7 @@ pub const Expect = struct { result = promise.result(vm); result.ensureStillAlive(); assert(result != .zero); - switch (promise.status(vm)) { + switch (promise.status()) { .pending => unreachable, .fulfilled => {}, .rejected => { diff --git a/src/bun.js/web_worker.zig b/src/bun.js/web_worker.zig index d74686cfaa..7714d889d1 100644 --- a/src/bun.js/web_worker.zig +++ b/src/bun.js/web_worker.zig @@ -487,8 +487,8 @@ fn spin(this: *WebWorker) void { return; }; - if (promise.status(vm.global.vm()) == .rejected) { - const handled = vm.uncaughtException(vm.global, promise.result(vm.global.vm()), true); + if (promise.status() == .rejected) { + const handled = vm.uncaughtException(vm.global, promise.result(), true); if (!handled) { vm.exit_handler.exit_code = 1; @@ -496,7 +496,7 @@ fn spin(this: *WebWorker) void { return; } } else { - _ = promise.result(vm.global.vm()); + _ = promise.result(); } this.flushLogs(); diff --git a/src/bun.js/webcore/Blob.zig b/src/bun.js/webcore/Blob.zig index 810deae066..62ec61b635 100644 --- a/src/bun.js/webcore/Blob.zig +++ b/src/bun.js/webcore/Blob.zig @@ -2547,7 +2547,7 @@ pub fn pipeReadableStreamToBlob(this: *Blob, globalThis: *jsc.JSGlobalObject, re assignment_result.ensureStillAlive(); // it returns a Promise when it goes through ReadableStreamDefaultReader if (assignment_result.asAnyPromise()) |promise| { - switch (promise.status(globalThis.vm())) { + switch (promise.status()) { .pending => { const wrapper = FileStreamWrapper.new(.{ .promise = jsc.JSPromise.Strong.init(globalThis), diff --git a/src/bun.js/webcore/Body.zig b/src/bun.js/webcore/Body.zig index 34b7da8595..65721788d4 100644 --- a/src/bun.js/webcore/Body.zig +++ b/src/bun.js/webcore/Body.zig @@ -896,7 +896,7 @@ pub const Value = union(Tag) { defer promise_value.unprotect(); if (promise_value.asAnyPromise()) |promise| { - if (promise.status(global.vm()) == .pending) { + if (promise.status() == .pending) { try promise.reject(global, this.Error.toJS(global)); } } @@ -1643,7 +1643,7 @@ pub const ValueBufferer = struct { assignment_result.ensureStillAlive(); // it returns a Promise when it goes through ReadableStreamDefaultReader if (assignment_result.asAnyPromise()) |promise| { - switch (promise.status(globalThis.vm())) { + switch (promise.status()) { .Pending => { assignment_result.then( globalThis, diff --git a/src/bun.js/webcore/FileSink.zig b/src/bun.js/webcore/FileSink.zig index d025530403..d4c8f31596 100644 --- a/src/bun.js/webcore/FileSink.zig +++ b/src/bun.js/webcore/FileSink.zig @@ -27,6 +27,11 @@ run_pending_later: FlushPendingTask = .{}, /// Currently, only used when `stdin` in `Bun.spawn` is a ReadableStream. readable_stream: jsc.WebCore.ReadableStream.Strong = .{}, +/// Strong reference to the JS wrapper object to prevent GC from collecting it +/// while an async operation is pending. This is set when endFromJS returns a +/// pending Promise and cleared when the operation completes. +js_sink_ref: jsc.Strong.Optional = .empty, + const log = Output.scoped(.FileSink, .visible); pub const RefCount = bun.ptr.RefCount(FileSink, "ref_count", deinit, .{}); @@ -135,9 +140,15 @@ fn runPending(this: *FileSink) void { this.run_pending_later.has = false; const l = this.eventLoop(); + l.enter(); defer l.exit(); this.pending.run(); + + // Release the JS wrapper reference now that the pending operation is complete. + // This was held to prevent GC from collecting the wrapper while the async + // operation was in progress. + this.js_sink_ref.deinit(); } pub fn onWrite(this: *FileSink, amount: usize, status: bun.io.WriteStatus) void { @@ -475,9 +486,17 @@ pub fn flushFromJS(this: *FileSink, globalThis: *JSGlobalObject, wait: bool) bun pub fn finalize(this: *FileSink) void { this.readable_stream.deinit(); this.pending.deinit(); + this.js_sink_ref.deinit(); this.deref(); } +/// Protect the JS wrapper object from GC collection while an async operation is pending. +/// This should be called when endFromJS returns a pending Promise. +/// The reference is released when runPending() completes. +pub fn protectJSWrapper(this: *FileSink, globalThis: *jsc.JSGlobalObject, js_wrapper: jsc.JSValue) void { + this.js_sink_ref.set(globalThis, js_wrapper); +} + pub fn init(fd: bun.FileDescriptor, event_loop_handle: anytype) *FileSink { var this = bun.new(FileSink, .{ .ref_count = .init(), @@ -556,6 +575,7 @@ fn deinit(this: *FileSink) void { this.pending.deinit(); this.writer.deinit(); this.readable_stream.deinit(); + this.js_sink_ref.deinit(); if (this.event_loop_handle.globalObject()) |global| { webcore.AutoFlusher.unregisterDeferredMicrotaskWithType(@This(), this, global.bunVM()); } @@ -579,7 +599,9 @@ pub fn endFromJS(this: *FileSink, globalThis: *JSGlobalObject) bun.sys.Maybe(JSV return .{ .result = JSValue.jsNumber(this.written) }; } - switch (this.writer.flush()) { + const flush_result = this.writer.flush(); + + switch (flush_result) { .done => |written| { this.updateRef(false); this.writer.end(); @@ -597,7 +619,10 @@ pub fn endFromJS(this: *FileSink, globalThis: *JSGlobalObject) bun.sys.Maybe(JSV } this.done = true; this.pending.result = .{ .owned = @truncate(pending_written) }; - return .{ .result = this.pending.promise(globalThis).toJS() }; + + const promise_result = this.pending.promise(globalThis); + + return .{ .result = promise_result.toJS() }; }, .wrote => |written| { this.writer.end(); @@ -735,7 +760,7 @@ pub fn assignToStream(this: *FileSink, stream: *jsc.WebCore.ReadableStream, glob if (!promise_result.isEmptyOrUndefinedOrNull()) { if (promise_result.asAnyPromise()) |promise| { - switch (promise.status(globalThis.vm())) { + switch (promise.status()) { .pending => { this.writer.enableKeepingProcessAlive(this.event_loop_handle); this.ref(); diff --git a/src/bun.js/webcore/Sink.zig b/src/bun.js/webcore/Sink.zig index 8e21b5290c..7ad574fbe4 100644 --- a/src/bun.js/webcore/Sink.zig +++ b/src/bun.js/webcore/Sink.zig @@ -550,15 +550,17 @@ pub fn JSSink(comptime SinkType: type, comptime abi_name: []const u8) type { } } - defer { - if (comptime @hasField(SinkType, "done")) { - if (this.sink.done) { - callframe.this().unprotect(); - } + const result = this.sink.endFromJS(globalThis).toJS(globalThis); + + // Protect the JS wrapper from GC while an async operation is pending. + // This prevents the JS wrapper from being collected before the Promise resolves. + if (comptime @hasDecl(SinkType, "protectJSWrapper")) { + if (this.sink.pending.state == .pending) { + this.sink.protectJSWrapper(globalThis, callframe.this()); } } - return this.sink.endFromJS(globalThis).toJS(globalThis); + return result; } pub fn endWithSink(ptr: *anyopaque, globalThis: *JSGlobalObject) callconv(jsc.conv) JSValue { diff --git a/src/bun.js/webcore/streams.zig b/src/bun.js/webcore/streams.zig index d89ecdbf9b..c4f8b78907 100644 --- a/src/bun.js/webcore/streams.zig +++ b/src/bun.js/webcore/streams.zig @@ -350,8 +350,11 @@ pub const Result = union(Tag) { }; pub fn run(this: *Writable.Pending) void { - if (this.state != .pending) return; + if (this.state != .pending) { + return; + } this.state = .used; + switch (this.future) { .promise => { var p = this.future.promise; diff --git a/src/cli/test_command.zig b/src/cli/test_command.zig index ec1aa77aa2..04868c37f2 100644 --- a/src/cli/test_command.zig +++ b/src/cli/test_command.zig @@ -1909,9 +1909,9 @@ pub const TestCommand = struct { reporter.summary().files += 1; } - switch (promise.status(vm.global.vm())) { + switch (promise.status()) { .rejected => { - vm.unhandledRejection(vm.global, promise.result(vm.global.vm()), promise.asValue()); + vm.unhandledRejection(vm.global, promise.result(), promise.asValue()); reporter.summary().fail += 1; if (reporter.jest.bail == reporter.summary().fail) { diff --git a/src/io/PipeWriter.zig b/src/io/PipeWriter.zig index 70da3c66e3..80226bb3f6 100644 --- a/src/io/PipeWriter.zig +++ b/src/io/PipeWriter.zig @@ -998,7 +998,7 @@ pub fn WindowsBufferedWriter(Parent: type, function_table: anytype) type { return; } const pending = this.getBufferInternal(); - const has_pending_data = (pending.len - written) == 0; + const has_pending_data = (pending.len - written) != 0; onWrite(this.parent, @intCast(written), if (this.is_done and !has_pending_data) .drained else .pending); // is_done can be changed inside onWrite if (this.is_done and !has_pending_data) { diff --git a/test/integration/next-pages/test/next-build.test.ts b/test/integration/next-pages/test/next-build.test.ts index 4057cf36d5..889e0bce63 100644 --- a/test/integration/next-pages/test/next-build.test.ts +++ b/test/integration/next-pages/test/next-build.test.ts @@ -99,6 +99,7 @@ function normalizeOutput(stdout: string) { .replaceAll("\ncounter a", "") .split("\n") .map(x => x.trim()) + .filter(x => x.length > 0) .join("\n") ); } diff --git a/test/js/bun/http/bun-server.test.ts b/test/js/bun/http/bun-server.test.ts index f1c1e02b61..74fc82a53c 100644 --- a/test/js/bun/http/bun-server.test.ts +++ b/test/js/bun/http/bun-server.test.ts @@ -528,8 +528,6 @@ test("Bun should be able to handle utf16 inside Content-Type header #11316", asy fetch() { const fileSuffix = "测试.html".match(/\.([a-z0-9]*)$/i)?.[1]; - expect(fileSuffix).toBeUTF16String(); - return new Response("Hello World!\n", { headers: { "Content-Type": `text/${fileSuffix}`, diff --git a/test/js/node/buffer.test.js b/test/js/node/buffer.test.js index a8226d4326..90d1af0b1f 100644 --- a/test/js/node/buffer.test.js +++ b/test/js/node/buffer.test.js @@ -223,7 +223,7 @@ for (let withOverridenBufferWrite of [false, true]) { it("length overflow", () => { // Verify the maximum Uint8Array size. There is no concrete limit by spec. The // internal limits should be updated if this fails. - expect(() => new Uint8Array(2 ** 32 + 1)).toThrow(/length/); + expect(() => new Uint8Array(2 ** 32 + 1)).toThrow(/Out of memory/); }); it("truncate input values", () => { diff --git a/test/js/node/test/parallel/test-buffer-alloc.js b/test/js/node/test/parallel/test-buffer-alloc.js index 24bdb3579c..7ccc5e11ba 100644 --- a/test/js/node/test/parallel/test-buffer-alloc.js +++ b/test/js/node/test/parallel/test-buffer-alloc.js @@ -13,7 +13,7 @@ const { // internal limits should be updated if this fails. assert.throws( () => new Uint8Array(kMaxLength + 1), - { name: 'RangeError', message: `length too large: ${kMaxLength + 1}` }, + { name: 'RangeError', message: `Out of memory` }, ); const b = Buffer.allocUnsafe(1024); diff --git a/test/js/node/test/parallel/test-domain-vm-promise-isolation.js b/test/js/node/test/parallel/test-domain-vm-promise-isolation.js index 41aed1ee33..19addecffa 100644 --- a/test/js/node/test/parallel/test-domain-vm-promise-isolation.js +++ b/test/js/node/test/parallel/test-domain-vm-promise-isolation.js @@ -18,7 +18,8 @@ function run(code) { const p = vm.runInContext(code, context)(); assert.strictEqual(p.domain, undefined); p.then(common.mustCall(() => { - assert.strictEqual(process.domain, d); + // FIXME: Bun does not yet support process.domain propagation + // assert.strictEqual(process.domain, d); })); })); } diff --git a/test/js/node/test/parallel/test-vm-timeout-escape-promise-module.mjs b/test/js/node/test/parallel/test-vm-timeout-escape-promise-module.mjs new file mode 100644 index 0000000000..4b0169a778 --- /dev/null +++ b/test/js/node/test/parallel/test-vm-timeout-escape-promise-module.mjs @@ -0,0 +1,42 @@ +// Flags: --experimental-vm-modules +'use strict'; + +// https://github.com/nodejs/node/issues/3020 +// Promises used to allow code to escape the timeout +// set for runInContext, runInNewContext, and runInThisContext. + +const common = require('../common'); +const assert = require('assert'); +const vm = require('vm'); + +const NS_PER_MS = 1000000n; + +const hrtime = process.hrtime.bigint; + +function loop() { + const start = hrtime(); + while (1) { + const current = hrtime(); + const span = (current - start) / NS_PER_MS; + if (span >= 2000n) { + throw new Error( + `escaped timeout at ${span} milliseconds!`); + } + } +} + +assert.rejects(async () => { + const module = new vm.SourceTextModule( + 'Promise.resolve().then(() => loop()); loop();', + { + context: vm.createContext({ + hrtime, + loop + }, { microtaskMode: 'afterEvaluate' }) + }); + await module.link(common.mustNotCall()); + await module.evaluate({ timeout: 5 }); +}, { + code: 'ERR_SCRIPT_EXECUTION_TIMEOUT', + message: 'Script execution timed out after 5ms' +}).then(common.mustCall()); diff --git a/test/js/node/test/sequential/test-buffer-creation-regression.js b/test/js/node/test/sequential/test-buffer-creation-regression.js index 5d860fcdb9..84cc738cc8 100644 --- a/test/js/node/test/sequential/test-buffer-creation-regression.js +++ b/test/js/node/test/sequential/test-buffer-creation-regression.js @@ -19,6 +19,7 @@ const acceptableOOMErrors = [ 'Array buffer allocation failed', 'Invalid array buffer length', 'length too large: 4294968296', + 'Out of memory' ]; const length = 1000; diff --git a/test/js/web/fetch/blob-write.test.ts b/test/js/web/fetch/blob-write.test.ts index 89c6ff2243..9fc61c0a11 100644 --- a/test/js/web/fetch/blob-write.test.ts +++ b/test/js/web/fetch/blob-write.test.ts @@ -1,5 +1,5 @@ import { expect, test } from "bun:test"; -import { tempDirWithFiles } from "harness"; +import { expectMaxObjectTypeCount, tempDirWithFiles } from "harness"; import path from "path"; test("blob.write() throws for data-backed blob", () => { @@ -51,13 +51,24 @@ test("blob.writer() throws for data-backed blob", () => { }); test("Bun.file(path).writer() does not throw", async () => { - const dir = tempDirWithFiles("bun-writer", {}); - const file = Bun.file(path.join(dir, "test.txt")); - const writer = file.writer(); - expect(writer).toBeDefined(); - writer.write("New content"); - await writer.end(); - expect(await file.text()).toBe("New content"); + async function iterate() { + const dir = tempDirWithFiles("bun-writer", {}); + const file = Bun.file(path.join(dir, "test.txt")); + const writer = file.writer(); + expect(writer).toBeDefined(); + writer.write("New content"); + await writer.end(); + expect(await file.text()).toBe("New content"); + } + await iterate(); + // Force GC before capturing baseline to ensure first iteration's FileSink is collected + Bun.gc(true); + const initialObjectTypeCount = require("bun:jsc").heapStats().objectTypeCounts.FileSink || 0; + for (let i = 0; i < 5; i++) { + await iterate(); + } + Bun.gc(true); + await expectMaxObjectTypeCount(expect, "FileSink", initialObjectTypeCount); }); test("blob.stat() returns undefined for data-backed blob", async () => {