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