mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
### What does this PR do? Fixes #23177 ### How did you verify your code works?
This commit is contained in:
@@ -444,10 +444,10 @@ pub const Interpreter = struct {
|
||||
|
||||
if (comptime free_buffered_io) {
|
||||
if (this._buffered_stdout == .owned) {
|
||||
this._buffered_stdout.owned.deinit(bun.default_allocator);
|
||||
this._buffered_stdout.owned.clearAndFree(bun.default_allocator);
|
||||
}
|
||||
if (this._buffered_stderr == .owned) {
|
||||
this._buffered_stderr.owned.deinit(bun.default_allocator);
|
||||
this._buffered_stderr.owned.clearAndFree(bun.default_allocator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -994,7 +994,7 @@ pub const Interpreter = struct {
|
||||
interp.exit_code = exit_code;
|
||||
switch (try interp.run()) {
|
||||
.err => |e| {
|
||||
interp.deinitEverything();
|
||||
interp.#deinitFromExec();
|
||||
bun.Output.err(e, "Failed to run script <b>{s}<r>", .{std.fs.path.basename(path)});
|
||||
bun.Global.exit(1);
|
||||
return 1;
|
||||
@@ -1003,7 +1003,7 @@ pub const Interpreter = struct {
|
||||
}
|
||||
mini.tick(&is_done, @as(fn (*anyopaque) bool, IsDone.isDone));
|
||||
const code = interp.exit_code.?;
|
||||
interp.deinitEverything();
|
||||
interp.#deinitFromExec();
|
||||
return code;
|
||||
}
|
||||
|
||||
@@ -1061,7 +1061,7 @@ pub const Interpreter = struct {
|
||||
interp.exit_code = exit_code;
|
||||
switch (try interp.run()) {
|
||||
.err => |e| {
|
||||
interp.deinitEverything();
|
||||
interp.#deinitFromExec();
|
||||
bun.Output.err(e, "Failed to run script <b>{s}<r>", .{path_for_errors});
|
||||
bun.Global.exit(1);
|
||||
return 1;
|
||||
@@ -1070,7 +1070,7 @@ pub const Interpreter = struct {
|
||||
}
|
||||
mini.tick(&is_done, @as(fn (*anyopaque) bool, IsDone.isDone));
|
||||
const code = interp.exit_code.?;
|
||||
interp.deinitEverything();
|
||||
interp.#deinitFromExec();
|
||||
return code;
|
||||
}
|
||||
|
||||
@@ -1142,7 +1142,7 @@ pub const Interpreter = struct {
|
||||
_ = callframe; // autofix
|
||||
|
||||
if (this.setupIOBeforeRun().asErr()) |e| {
|
||||
defer this.deinitEverything();
|
||||
defer this.#deinitFromExec();
|
||||
const shellerr = bun.shell.ShellErr.newSys(e);
|
||||
return try throwShellErr(&shellerr, .{ .js = globalThis.bunVM().event_loop });
|
||||
}
|
||||
@@ -1191,20 +1191,21 @@ pub const Interpreter = struct {
|
||||
defer decrPendingActivityFlag(&this.has_pending_activity);
|
||||
|
||||
if (this.event_loop == .js) {
|
||||
defer this.deinitAfterJSRun();
|
||||
this.exit_code = exit_code;
|
||||
const this_jsvalue = this.this_jsvalue;
|
||||
if (this_jsvalue != .zero) {
|
||||
if (jsc.Codegen.JSShellInterpreter.resolveGetCached(this_jsvalue)) |resolve| {
|
||||
const loop = this.event_loop.js;
|
||||
const globalThis = this.globalThis;
|
||||
this.this_jsvalue = .zero;
|
||||
const buffered_stdout = this.getBufferedStdout(globalThis);
|
||||
const buffered_stderr = this.getBufferedStderr(globalThis);
|
||||
this.keep_alive.disable();
|
||||
this.#derefRootShellAndIOIfNeeded(true);
|
||||
loop.enter();
|
||||
_ = resolve.call(globalThis, .js_undefined, &.{
|
||||
JSValue.jsNumberFromU16(exit_code),
|
||||
this.getBufferedStdout(globalThis),
|
||||
this.getBufferedStderr(globalThis),
|
||||
buffered_stdout,
|
||||
buffered_stderr,
|
||||
}) catch |err| globalThis.reportActiveExceptionAsUnhandled(err);
|
||||
jsc.Codegen.JSShellInterpreter.resolveSetCached(this_jsvalue, globalThis, .js_undefined);
|
||||
jsc.Codegen.JSShellInterpreter.rejectSetCached(this_jsvalue, globalThis, .js_undefined);
|
||||
@@ -1219,35 +1220,45 @@ pub const Interpreter = struct {
|
||||
return .done;
|
||||
}
|
||||
|
||||
fn deinitAfterJSRun(this: *ThisInterpreter) void {
|
||||
log("Interpreter(0x{x}) deinitAfterJSRun", .{@intFromPtr(this)});
|
||||
this.root_io.deref();
|
||||
this.keep_alive.disable();
|
||||
this.root_shell.deinitImpl(false, false);
|
||||
fn #derefRootShellAndIOIfNeeded(this: *ThisInterpreter, free_buffered_io: bool) void {
|
||||
if (free_buffered_io) {
|
||||
// Can safely be called multiple times.
|
||||
if (this.root_shell._buffered_stderr == .owned) {
|
||||
this.root_shell._buffered_stderr.owned.clearAndFree(bun.default_allocator);
|
||||
}
|
||||
if (this.root_shell._buffered_stdout == .owned) {
|
||||
this.root_shell._buffered_stdout.owned.clearAndFree(bun.default_allocator);
|
||||
}
|
||||
}
|
||||
|
||||
// Has this already been finalized?
|
||||
if (this.this_jsvalue != .zero) {
|
||||
// Cannot be safely called multiple times.
|
||||
this.root_io.deref();
|
||||
this.root_shell.deinitImpl(false, false);
|
||||
}
|
||||
|
||||
this.this_jsvalue = .zero;
|
||||
}
|
||||
|
||||
fn deinitFromFinalizer(this: *ThisInterpreter) void {
|
||||
if (this.root_shell._buffered_stderr == .owned) {
|
||||
this.root_shell._buffered_stderr.owned.deinit(bun.default_allocator);
|
||||
}
|
||||
if (this.root_shell._buffered_stdout == .owned) {
|
||||
this.root_shell._buffered_stdout.owned.deinit(bun.default_allocator);
|
||||
}
|
||||
this.this_jsvalue = .zero;
|
||||
this.#derefRootShellAndIOIfNeeded(true);
|
||||
this.keep_alive.disable();
|
||||
this.args.deinit();
|
||||
this.allocator.destroy(this);
|
||||
}
|
||||
|
||||
fn deinitEverything(this: *ThisInterpreter) void {
|
||||
fn #deinitFromExec(this: *ThisInterpreter) void {
|
||||
log("deinit interpreter", .{});
|
||||
|
||||
this.this_jsvalue = .zero;
|
||||
this.root_io.deref();
|
||||
this.root_shell.deinitImpl(false, true);
|
||||
|
||||
for (this.vm_args_utf8.items[0..]) |str| {
|
||||
str.deinit();
|
||||
}
|
||||
this.vm_args_utf8.deinit();
|
||||
this.this_jsvalue = .zero;
|
||||
this.allocator.destroy(this);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user