mirror of
https://github.com/denoland/deno.git
synced 2025-01-12 00:54:02 -05:00
feat(runtime): add op_set_exit_code (#12911)
Set the exit code to use if none is provided to Deno.exit(), or when Deno exits naturally. Needed for process.exitCode Node compat. Paves the way for #12888.
This commit is contained in:
parent
1d3f734e18
commit
993a1dd41a
9 changed files with 57 additions and 3 deletions
|
@ -93,6 +93,7 @@ use std::iter::once;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::atomic::Ordering::Relaxed;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
fn create_web_worker_callback(ps: ProcState) -> Arc<CreateWebWorkerCb> {
|
fn create_web_worker_callback(ps: ProcState) -> Arc<CreateWebWorkerCb> {
|
||||||
|
@ -1475,4 +1476,7 @@ pub fn main() {
|
||||||
logger::init(flags.log_level);
|
logger::init(flags.log_level);
|
||||||
|
|
||||||
unwrap_or_exit(run_basic(get_subcommand(flags)));
|
unwrap_or_exit(run_basic(get_subcommand(flags)));
|
||||||
|
|
||||||
|
let code = deno_runtime::EXIT_CODE.load(Relaxed);
|
||||||
|
std::process::exit(code);
|
||||||
}
|
}
|
||||||
|
|
|
@ -859,6 +859,24 @@ itest!(exit_error42 {
|
||||||
output: "exit_error42.ts.out",
|
output: "exit_error42.ts.out",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
itest!(set_exit_code_0 {
|
||||||
|
args: "run --no-check --unstable set_exit_code_0.ts",
|
||||||
|
output: "empty.out",
|
||||||
|
exit_code: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
itest!(set_exit_code_1 {
|
||||||
|
args: "run --no-check --unstable set_exit_code_1.ts",
|
||||||
|
output: "empty.out",
|
||||||
|
exit_code: 42,
|
||||||
|
});
|
||||||
|
|
||||||
|
itest!(set_exit_code_2 {
|
||||||
|
args: "run --no-check --unstable set_exit_code_2.ts",
|
||||||
|
output: "empty.out",
|
||||||
|
exit_code: 42,
|
||||||
|
});
|
||||||
|
|
||||||
itest!(heapstats {
|
itest!(heapstats {
|
||||||
args: "run --quiet --unstable --v8-flags=--expose-gc heapstats.js",
|
args: "run --quiet --unstable --v8-flags=--expose-gc heapstats.js",
|
||||||
output: "heapstats.js.out",
|
output: "heapstats.js.out",
|
||||||
|
|
0
cli/tests/testdata/empty.out
vendored
Normal file
0
cli/tests/testdata/empty.out
vendored
Normal file
2
cli/tests/testdata/set_exit_code_0.ts
vendored
Normal file
2
cli/tests/testdata/set_exit_code_0.ts
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Deno.core.opSync("op_set_exit_code", 42);
|
||||||
|
Deno.exit(0); // Takes precedence.
|
2
cli/tests/testdata/set_exit_code_1.ts
vendored
Normal file
2
cli/tests/testdata/set_exit_code_1.ts
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Deno.core.opSync("op_set_exit_code", 42);
|
||||||
|
Deno.exit();
|
2
cli/tests/testdata/set_exit_code_2.ts
vendored
Normal file
2
cli/tests/testdata/set_exit_code_2.ts
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Deno.core.opSync("op_set_exit_code", 42);
|
||||||
|
// Exits naturally.
|
|
@ -31,7 +31,14 @@
|
||||||
exitHandler = fn;
|
exitHandler = fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
function exit(code = 0) {
|
function exit(code) {
|
||||||
|
// Set exit code first so unload event listeners can override it.
|
||||||
|
if (typeof code === "number") {
|
||||||
|
core.opSync("op_set_exit_code", code);
|
||||||
|
} else {
|
||||||
|
code = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Dispatches `unload` only when it's not dispatched yet.
|
// Dispatches `unload` only when it's not dispatched yet.
|
||||||
if (!window[SymbolFor("isUnloadDispatched")]) {
|
if (!window[SymbolFor("isUnloadDispatched")]) {
|
||||||
// Invokes the `unload` hooks before exiting
|
// Invokes the `unload` hooks before exiting
|
||||||
|
@ -44,7 +51,7 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
core.opSync("op_exit", code);
|
core.opSync("op_exit");
|
||||||
throw new Error("Code not reachable");
|
throw new Error("Code not reachable");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use std::sync::atomic::AtomicI32;
|
||||||
|
|
||||||
pub use deno_broadcast_channel;
|
pub use deno_broadcast_channel;
|
||||||
pub use deno_console;
|
pub use deno_console;
|
||||||
pub use deno_crypto;
|
pub use deno_crypto;
|
||||||
|
@ -29,3 +31,12 @@ pub mod worker;
|
||||||
|
|
||||||
mod worker_bootstrap;
|
mod worker_bootstrap;
|
||||||
pub use worker_bootstrap::BootstrapOptions;
|
pub use worker_bootstrap::BootstrapOptions;
|
||||||
|
|
||||||
|
// The global may not be very elegant but:
|
||||||
|
//
|
||||||
|
// 1. op_exit() calls std::process::exit() so there is not much point storing
|
||||||
|
// the exit code in runtime state
|
||||||
|
//
|
||||||
|
// 2. storing it in runtime state makes retrieving it again in cli/main.rs
|
||||||
|
// unduly complicated
|
||||||
|
pub static EXIT_CODE: AtomicI32 = AtomicI32::new(0);
|
||||||
|
|
|
@ -10,6 +10,7 @@ use deno_core::OpState;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::env;
|
use std::env;
|
||||||
|
use std::sync::atomic::Ordering::Relaxed;
|
||||||
|
|
||||||
pub fn init() -> Extension {
|
pub fn init() -> Extension {
|
||||||
Extension::builder()
|
Extension::builder()
|
||||||
|
@ -23,6 +24,7 @@ pub fn init() -> Extension {
|
||||||
("op_hostname", op_sync(op_hostname)),
|
("op_hostname", op_sync(op_hostname)),
|
||||||
("op_loadavg", op_sync(op_loadavg)),
|
("op_loadavg", op_sync(op_loadavg)),
|
||||||
("op_os_release", op_sync(op_os_release)),
|
("op_os_release", op_sync(op_os_release)),
|
||||||
|
("op_set_exit_code", op_sync(op_set_exit_code)),
|
||||||
("op_system_memory_info", op_sync(op_system_memory_info)),
|
("op_system_memory_info", op_sync(op_system_memory_info)),
|
||||||
])
|
])
|
||||||
.build()
|
.build()
|
||||||
|
@ -95,7 +97,13 @@ fn op_delete_env(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_exit(_state: &mut OpState, code: i32, _: ()) -> Result<(), AnyError> {
|
fn op_set_exit_code(_: &mut OpState, code: i32, _: ()) -> Result<(), AnyError> {
|
||||||
|
crate::EXIT_CODE.store(code, Relaxed);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn op_exit(_: &mut OpState, _: (), _: ()) -> Result<(), AnyError> {
|
||||||
|
let code = crate::EXIT_CODE.load(Relaxed);
|
||||||
std::process::exit(code)
|
std::process::exit(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue