mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
add [Symbol.dispose] in some bun apis (#10818)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com> Co-authored-by: Jarred-Sumner <Jarred-Sumner@users.noreply.github.com>
This commit is contained in:
Submodule src/bun.js/WebKit updated: 590f9c4019...ce4af76c27
@@ -96,6 +96,10 @@ export default [
|
||||
fn: "kill",
|
||||
length: 1,
|
||||
},
|
||||
"@@asyncDispose": {
|
||||
fn: "asyncDispose",
|
||||
length: 1,
|
||||
},
|
||||
|
||||
killed: {
|
||||
getter: "getKilled",
|
||||
|
||||
@@ -574,6 +574,34 @@ pub const Subprocess = struct {
|
||||
return this.stdout.toJS(globalThis, this.hasExited());
|
||||
}
|
||||
|
||||
pub fn asyncDispose(
|
||||
this: *Subprocess,
|
||||
global: *JSGlobalObject,
|
||||
_: *JSC.CallFrame,
|
||||
) callconv(.C) JSValue {
|
||||
if (this.process.hasExited()) {
|
||||
// rely on GC to clean everything up in this case
|
||||
return .undefined;
|
||||
}
|
||||
|
||||
// unref streams so that this disposed process will not prevent
|
||||
// the process from exiting causing a hang
|
||||
this.stdin.unref();
|
||||
this.stdout.unref();
|
||||
this.stderr.unref();
|
||||
|
||||
switch (this.tryKill(SignalCode.default)) {
|
||||
.result => {},
|
||||
.err => |err| {
|
||||
// Signal 9 should always be fine, but just in case that somehow fails.
|
||||
global.throwValue(err.toJSC(global));
|
||||
return .zero;
|
||||
},
|
||||
}
|
||||
|
||||
return this.getExited(global);
|
||||
}
|
||||
|
||||
pub fn kill(
|
||||
this: *Subprocess,
|
||||
globalThis: *JSGlobalObject,
|
||||
|
||||
@@ -20,6 +20,10 @@ function generate(name) {
|
||||
fn: "doReload",
|
||||
length: 2,
|
||||
},
|
||||
"@@dispose": {
|
||||
fn: "dispose",
|
||||
length: 0,
|
||||
},
|
||||
stop: {
|
||||
fn: "doStop",
|
||||
length: 1,
|
||||
|
||||
@@ -5122,6 +5122,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
|
||||
} = .{},
|
||||
|
||||
pub const doStop = JSC.wrapInstanceMethod(ThisServer, "stopFromJS", false);
|
||||
pub const dispose = JSC.wrapInstanceMethod(ThisServer, "disposeFromJS", false);
|
||||
pub const doUpgrade = JSC.wrapInstanceMethod(ThisServer, "onUpgrade", false);
|
||||
pub const doPublish = JSC.wrapInstanceMethod(ThisServer, "publish", false);
|
||||
pub const doReload = onReload;
|
||||
@@ -5547,6 +5548,16 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
|
||||
return JSC.JSValue.jsUndefined();
|
||||
}
|
||||
|
||||
pub fn disposeFromJS(this: *ThisServer) JSC.JSValue {
|
||||
if (this.listener != null) {
|
||||
JSC.C.JSValueUnprotect(this.globalThis, this.thisObject.asObjectRef());
|
||||
this.thisObject = JSC.JSValue.jsUndefined();
|
||||
this.stop(true);
|
||||
}
|
||||
|
||||
return JSC.JSValue.jsUndefined();
|
||||
}
|
||||
|
||||
pub fn getPort(
|
||||
this: *ThisServer,
|
||||
_: *JSC.JSGlobalObject,
|
||||
|
||||
@@ -111,6 +111,11 @@ function generate(ssl) {
|
||||
length: 0,
|
||||
},
|
||||
|
||||
"@@dispose": {
|
||||
fn: "shutdown",
|
||||
length: 0,
|
||||
},
|
||||
|
||||
shutdown: {
|
||||
fn: "shutdown",
|
||||
length: 1,
|
||||
@@ -181,6 +186,10 @@ export default [
|
||||
fn: "stop",
|
||||
length: 1,
|
||||
},
|
||||
"@@dispose": {
|
||||
fn: "stop",
|
||||
length: 0,
|
||||
},
|
||||
|
||||
ref: {
|
||||
fn: "ref",
|
||||
@@ -239,6 +248,10 @@ export default [
|
||||
fn: "close",
|
||||
length: 0,
|
||||
},
|
||||
"@@dispose": {
|
||||
fn: "close",
|
||||
length: 0,
|
||||
},
|
||||
reload: {
|
||||
fn: "reload",
|
||||
length: 1,
|
||||
|
||||
@@ -106,6 +106,10 @@ class JSCallback {
|
||||
closeCallback(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
[Symbol.dispose]() {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
class CString extends String {
|
||||
|
||||
@@ -995,6 +995,12 @@ class ChildProcess extends EventEmitter {
|
||||
pid;
|
||||
channel;
|
||||
|
||||
[Symbol.dispose]() {
|
||||
if (!this.killed) {
|
||||
this.kill();
|
||||
}
|
||||
}
|
||||
|
||||
get killed() {
|
||||
if (this.#handle == null) return false;
|
||||
}
|
||||
@@ -1310,7 +1316,7 @@ class ChildProcess extends EventEmitter {
|
||||
this.#handle.disconnect();
|
||||
}
|
||||
|
||||
kill(sig) {
|
||||
kill(sig?) {
|
||||
const signal = sig === 0 ? sig : convertToValidSignal(sig === undefined ? "SIGTERM" : sig);
|
||||
|
||||
if (this.#handle) {
|
||||
|
||||
@@ -1513,3 +1513,18 @@ it("should resolve pending promise if requested ended with pending read", async
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it("should work with dispose keyword", async () => {
|
||||
let url: string;
|
||||
{
|
||||
using server = Bun.serve({
|
||||
port: 0,
|
||||
fetch() {
|
||||
return new Response("OK");
|
||||
},
|
||||
});
|
||||
url = server.url;
|
||||
expect((await fetch(url)).status).toBe(200);
|
||||
}
|
||||
expect(fetch(url)).rejects.toThrow();
|
||||
});
|
||||
|
||||
@@ -782,3 +782,18 @@ describe("close handling", () => {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("dispose keyword works", async () => {
|
||||
let captured;
|
||||
{
|
||||
await using proc = spawn({
|
||||
cmd: [bunExe(), "-e", "await Bun.sleep(100000)"],
|
||||
});
|
||||
captured = proc;
|
||||
await Bun.sleep(100);
|
||||
}
|
||||
await Bun.sleep(0);
|
||||
expect(captured.killed).toBe(true);
|
||||
expect(captured.exitCode).toBe(null);
|
||||
expect(captured.signalCode).toBe("SIGTERM");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user