mirror of
https://github.com/denoland/deno.git
synced 2024-11-25 15:29:32 -05:00
feat: Add Deno.exitCode
API (#23609)
This commits adds the ability to set a would-be exit code for the Deno process without forcing an immediate exit, through the new `Deno.exitCode` API. - **Implements `Deno.exitCode` getter and setter**: Adds support for setting and retrieving a would-be exit code via `Deno.exitCode`. This allows for asynchronous cleanup before process termination without immediately exiting. - **Ensures type safety**: The setter for `Deno.exitCode` validates that the provided value is a number, throwing a TypeError if not, to ensure that only valid exit codes are set. Closes to #23605 --------- Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
This commit is contained in:
parent
cf611fbf54
commit
13723f267e
20 changed files with 322 additions and 24 deletions
|
@ -28,6 +28,10 @@ const {
|
||||||
|
|
||||||
import { setExitHandler } from "ext:runtime/30_os.js";
|
import { setExitHandler } from "ext:runtime/30_os.js";
|
||||||
|
|
||||||
|
// Capture `Deno` global so that users deleting or mangling it, won't
|
||||||
|
// have impact on our sanitizers.
|
||||||
|
const DenoNs = globalThis.Deno;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {{
|
* @typedef {{
|
||||||
* id: number,
|
* id: number,
|
||||||
|
@ -101,7 +105,20 @@ function assertExit(fn, isTest) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const innerResult = await fn(...new SafeArrayIterator(params));
|
const innerResult = await fn(...new SafeArrayIterator(params));
|
||||||
if (innerResult) return innerResult;
|
const exitCode = DenoNs.exitCode;
|
||||||
|
if (exitCode !== 0) {
|
||||||
|
// Reset the code to allow other tests to run...
|
||||||
|
DenoNs.exitCode = 0;
|
||||||
|
// ...and fail the current test.
|
||||||
|
throw new Error(
|
||||||
|
`${
|
||||||
|
isTest ? "Test case" : "Bench"
|
||||||
|
} finished with exit code set to ${exitCode}.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (innerResult) {
|
||||||
|
return innerResult;
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
setExitHandler(null);
|
setExitHandler(null);
|
||||||
}
|
}
|
||||||
|
|
94
cli/tests/unit/os_test.ts
Normal file
94
cli/tests/unit/os_test.ts
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
import { assertEquals, assertThrows } from "../../testing/asserts.ts";
|
||||||
|
|
||||||
|
Deno.test("Deno.exitCode getter and setter", () => {
|
||||||
|
// Initial value is 0
|
||||||
|
assertEquals(Deno.exitCode, 0);
|
||||||
|
|
||||||
|
// Set a new value
|
||||||
|
Deno.exitCode = 5;
|
||||||
|
assertEquals(Deno.exitCode, 5);
|
||||||
|
|
||||||
|
// Reset to initial value
|
||||||
|
Deno.exitCode = 0;
|
||||||
|
assertEquals(Deno.exitCode, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("Setting Deno.exitCode to NaN throws TypeError", () => {
|
||||||
|
// @ts-expect-error;
|
||||||
|
Deno.exitCode = "123";
|
||||||
|
assertEquals(Deno.exitCode, 123);
|
||||||
|
|
||||||
|
// Reset
|
||||||
|
Deno.exitCode = 0;
|
||||||
|
assertEquals(Deno.exitCode, 0);
|
||||||
|
|
||||||
|
// Throws on non-number values
|
||||||
|
assertThrows(
|
||||||
|
() => {
|
||||||
|
// @ts-expect-error Testing for runtime error
|
||||||
|
Deno.exitCode = "not a number";
|
||||||
|
},
|
||||||
|
TypeError,
|
||||||
|
"Exit code must be a number.",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("Setting Deno.exitCode does not cause an immediate exit", () => {
|
||||||
|
let exited = false;
|
||||||
|
const originalExit = Deno.exit;
|
||||||
|
|
||||||
|
// @ts-expect-error; read-only
|
||||||
|
Deno.exit = () => {
|
||||||
|
exited = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
Deno.exitCode = 1;
|
||||||
|
assertEquals(exited, false);
|
||||||
|
|
||||||
|
// @ts-expect-error; read-only
|
||||||
|
Deno.exit = originalExit;
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("Running Deno.exit(value) overrides Deno.exitCode", () => {
|
||||||
|
let args: unknown[] | undefined;
|
||||||
|
|
||||||
|
const originalExit = Deno.exit;
|
||||||
|
// @ts-expect-error; read-only
|
||||||
|
Deno.exit = (...x) => {
|
||||||
|
args = x;
|
||||||
|
};
|
||||||
|
|
||||||
|
Deno.exitCode = 42;
|
||||||
|
Deno.exit(0);
|
||||||
|
|
||||||
|
assertEquals(args, [0]);
|
||||||
|
// @ts-expect-error; read-only
|
||||||
|
Deno.exit = originalExit;
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("Running Deno.exit() uses Deno.exitCode as fallback", () => {
|
||||||
|
let args: unknown[] | undefined;
|
||||||
|
|
||||||
|
const originalExit = Deno.exit;
|
||||||
|
// @ts-expect-error; read-only
|
||||||
|
Deno.exit = (...x) => {
|
||||||
|
args = x;
|
||||||
|
};
|
||||||
|
|
||||||
|
Deno.exitCode = 42;
|
||||||
|
Deno.exit();
|
||||||
|
|
||||||
|
assertEquals(args, [42]);
|
||||||
|
// @ts-expect-error; read-only
|
||||||
|
Deno.exit = originalExit;
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("Retrieving the set exit code before process termination", () => {
|
||||||
|
Deno.exitCode = 42;
|
||||||
|
assertEquals(Deno.exitCode, 42);
|
||||||
|
|
||||||
|
// Reset to initial value
|
||||||
|
Deno.exitCode = 0;
|
||||||
|
});
|
17
cli/tsc/dts/lib.deno.ns.d.ts
vendored
17
cli/tsc/dts/lib.deno.ns.d.ts
vendored
|
@ -1466,6 +1466,23 @@ declare namespace Deno {
|
||||||
*/
|
*/
|
||||||
export function exit(code?: number): never;
|
export function exit(code?: number): never;
|
||||||
|
|
||||||
|
/** The exit code for the Deno process.
|
||||||
|
*
|
||||||
|
* If no exit code has been supplied, then Deno will assume a return code of `0`.
|
||||||
|
*
|
||||||
|
* When setting an exit code value, a number or non-NaN string must be provided,
|
||||||
|
* otherwise a TypeError will be thrown.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* console.log(Deno.exitCode); //-> 0
|
||||||
|
* Deno.exitCode = 1;
|
||||||
|
* console.log(Deno.exitCode); //-> 1
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @category Runtime
|
||||||
|
*/
|
||||||
|
export var exitCode: number;
|
||||||
|
|
||||||
/** An interface containing methods to interact with the process environment
|
/** An interface containing methods to interact with the process environment
|
||||||
* variables.
|
* variables.
|
||||||
*
|
*
|
||||||
|
|
|
@ -10,7 +10,6 @@ import {
|
||||||
op_geteuid,
|
op_geteuid,
|
||||||
op_node_process_kill,
|
op_node_process_kill,
|
||||||
op_process_abort,
|
op_process_abort,
|
||||||
op_set_exit_code,
|
|
||||||
} from "ext:core/ops";
|
} from "ext:core/ops";
|
||||||
|
|
||||||
import { warnNotImplemented } from "ext:deno_node/_utils.ts";
|
import { warnNotImplemented } from "ext:deno_node/_utils.ts";
|
||||||
|
@ -49,6 +48,7 @@ import {
|
||||||
} from "ext:deno_node/_next_tick.ts";
|
} from "ext:deno_node/_next_tick.ts";
|
||||||
import { isWindows } from "ext:deno_node/_util/os.ts";
|
import { isWindows } from "ext:deno_node/_util/os.ts";
|
||||||
import * as io from "ext:deno_io/12_io.js";
|
import * as io from "ext:deno_io/12_io.js";
|
||||||
|
import * as denoOs from "ext:runtime/30_os.js";
|
||||||
|
|
||||||
export let argv0 = "";
|
export let argv0 = "";
|
||||||
|
|
||||||
|
@ -74,28 +74,31 @@ const notImplementedEvents = [
|
||||||
];
|
];
|
||||||
|
|
||||||
export const argv: string[] = ["", ""];
|
export const argv: string[] = ["", ""];
|
||||||
let globalProcessExitCode: number | undefined = undefined;
|
|
||||||
|
// In Node, `process.exitCode` is initially `undefined` until set.
|
||||||
|
// And retains any value as long as it's nullish or number-ish.
|
||||||
|
let ProcessExitCode: undefined | null | string | number;
|
||||||
|
|
||||||
/** https://nodejs.org/api/process.html#process_process_exit_code */
|
/** https://nodejs.org/api/process.html#process_process_exit_code */
|
||||||
export const exit = (code?: number | string) => {
|
export const exit = (code?: number | string) => {
|
||||||
if (code || code === 0) {
|
if (code || code === 0) {
|
||||||
if (typeof code === "string") {
|
denoOs.setExitCode(code);
|
||||||
const parsedCode = parseInt(code);
|
} else if (Number.isNaN(code)) {
|
||||||
globalProcessExitCode = isNaN(parsedCode) ? undefined : parsedCode;
|
denoOs.setExitCode(1);
|
||||||
} else {
|
|
||||||
globalProcessExitCode = code;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProcessExitCode = denoOs.getExitCode();
|
||||||
if (!process._exiting) {
|
if (!process._exiting) {
|
||||||
process._exiting = true;
|
process._exiting = true;
|
||||||
// FIXME(bartlomieju): this is wrong, we won't be using syscall to exit
|
// FIXME(bartlomieju): this is wrong, we won't be using syscall to exit
|
||||||
// and thus the `unload` event will not be emitted to properly trigger "emit"
|
// and thus the `unload` event will not be emitted to properly trigger "emit"
|
||||||
// event on `process`.
|
// event on `process`.
|
||||||
process.emit("exit", process.exitCode || 0);
|
process.emit("exit", ProcessExitCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
process.reallyExit(process.exitCode || 0);
|
// Any valid thing `process.exitCode` set is already held in Deno.exitCode.
|
||||||
|
// At this point, we don't have to pass around Node's raw/string exit value.
|
||||||
|
process.reallyExit(ProcessExitCode);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** https://nodejs.org/api/process.html#processumaskmask */
|
/** https://nodejs.org/api/process.html#processumaskmask */
|
||||||
|
@ -433,14 +436,42 @@ Process.prototype._exiting = _exiting;
|
||||||
/** https://nodejs.org/api/process.html#processexitcode_1 */
|
/** https://nodejs.org/api/process.html#processexitcode_1 */
|
||||||
Object.defineProperty(Process.prototype, "exitCode", {
|
Object.defineProperty(Process.prototype, "exitCode", {
|
||||||
get() {
|
get() {
|
||||||
return globalProcessExitCode;
|
return ProcessExitCode;
|
||||||
},
|
},
|
||||||
set(code: number | undefined) {
|
set(code: number | string | null | undefined) {
|
||||||
globalProcessExitCode = code;
|
let parsedCode;
|
||||||
code = parseInt(code) || 0;
|
|
||||||
if (!isNaN(code)) {
|
if (typeof code === "number") {
|
||||||
op_set_exit_code(code);
|
if (Number.isNaN(code)) {
|
||||||
|
parsedCode = 1;
|
||||||
|
denoOs.setExitCode(parsedCode);
|
||||||
|
ProcessExitCode = parsedCode;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is looser than `denoOs.setExitCode` which requires exit code
|
||||||
|
// to be decimal or string of a decimal, but Node accept eg. 0x10.
|
||||||
|
parsedCode = parseInt(code);
|
||||||
|
denoOs.setExitCode(parsedCode);
|
||||||
|
ProcessExitCode = parsedCode;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof code === "string") {
|
||||||
|
parsedCode = parseInt(code);
|
||||||
|
if (Number.isNaN(parsedCode)) {
|
||||||
|
throw new TypeError(
|
||||||
|
`The "code" argument must be of type number. Received type ${typeof code} (${code})`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
denoOs.setExitCode(parsedCode);
|
||||||
|
ProcessExitCode = parsedCode;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(bartlomieju): hope for the best here. This should be further tightened.
|
||||||
|
denoOs.setExitCode(code);
|
||||||
|
ProcessExitCode = code;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {
|
||||||
op_exec_path,
|
op_exec_path,
|
||||||
op_exit,
|
op_exit,
|
||||||
op_get_env,
|
op_get_env,
|
||||||
|
op_get_exit_code,
|
||||||
op_gid,
|
op_gid,
|
||||||
op_hostname,
|
op_hostname,
|
||||||
op_loadavg,
|
op_loadavg,
|
||||||
|
@ -21,7 +22,9 @@ import {
|
||||||
const {
|
const {
|
||||||
Error,
|
Error,
|
||||||
FunctionPrototypeBind,
|
FunctionPrototypeBind,
|
||||||
|
NumberParseInt,
|
||||||
SymbolFor,
|
SymbolFor,
|
||||||
|
TypeError,
|
||||||
} = primordials;
|
} = primordials;
|
||||||
|
|
||||||
import { Event, EventTarget } from "ext:deno_web/02_event.js";
|
import { Event, EventTarget } from "ext:deno_web/02_event.js";
|
||||||
|
@ -75,7 +78,7 @@ function exit(code) {
|
||||||
if (typeof code === "number") {
|
if (typeof code === "number") {
|
||||||
op_set_exit_code(code);
|
op_set_exit_code(code);
|
||||||
} else {
|
} else {
|
||||||
code = 0;
|
code = op_get_exit_code();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dispatches `unload` only when it's not dispatched yet.
|
// Dispatches `unload` only when it's not dispatched yet.
|
||||||
|
@ -94,6 +97,20 @@ function exit(code) {
|
||||||
throw new Error("Code not reachable");
|
throw new Error("Code not reachable");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getExitCode() {
|
||||||
|
return op_get_exit_code();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setExitCode(value) {
|
||||||
|
const code = NumberParseInt(value, 10);
|
||||||
|
if (typeof code !== "number") {
|
||||||
|
throw new TypeError(
|
||||||
|
`Exit code must be a number, got: ${code} (${typeof code}).`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
op_set_exit_code(code);
|
||||||
|
}
|
||||||
|
|
||||||
function setEnv(key, value) {
|
function setEnv(key, value) {
|
||||||
op_set_env(key, value);
|
op_set_env(key, value);
|
||||||
}
|
}
|
||||||
|
@ -126,12 +143,14 @@ export {
|
||||||
env,
|
env,
|
||||||
execPath,
|
execPath,
|
||||||
exit,
|
exit,
|
||||||
|
getExitCode,
|
||||||
gid,
|
gid,
|
||||||
hostname,
|
hostname,
|
||||||
loadavg,
|
loadavg,
|
||||||
networkInterfaces,
|
networkInterfaces,
|
||||||
osRelease,
|
osRelease,
|
||||||
osUptime,
|
osUptime,
|
||||||
|
setExitCode,
|
||||||
setExitHandler,
|
setExitHandler,
|
||||||
systemMemoryInfo,
|
systemMemoryInfo,
|
||||||
uid,
|
uid,
|
||||||
|
|
|
@ -674,6 +674,14 @@ ObjectDefineProperties(finalDenoNs, {
|
||||||
return internals.future ? undefined : customInspect;
|
return internals.future ? undefined : customInspect;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
exitCode: {
|
||||||
|
get() {
|
||||||
|
return os.getExitCode();
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
os.setExitCode(value);
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
|
|
@ -32,6 +32,7 @@ deno_core::extension!(
|
||||||
op_os_uptime,
|
op_os_uptime,
|
||||||
op_set_env,
|
op_set_env,
|
||||||
op_set_exit_code,
|
op_set_exit_code,
|
||||||
|
op_get_exit_code,
|
||||||
op_system_memory_info,
|
op_system_memory_info,
|
||||||
op_uid,
|
op_uid,
|
||||||
op_runtime_memory_usage,
|
op_runtime_memory_usage,
|
||||||
|
@ -60,12 +61,13 @@ deno_core::extension!(
|
||||||
op_os_uptime,
|
op_os_uptime,
|
||||||
op_set_env,
|
op_set_env,
|
||||||
op_set_exit_code,
|
op_set_exit_code,
|
||||||
|
op_get_exit_code,
|
||||||
op_system_memory_info,
|
op_system_memory_info,
|
||||||
op_uid,
|
op_uid,
|
||||||
op_runtime_memory_usage,
|
op_runtime_memory_usage,
|
||||||
],
|
],
|
||||||
middleware = |op| match op.name {
|
middleware = |op| match op.name {
|
||||||
"op_exit" | "op_set_exit_code" =>
|
"op_exit" | "op_set_exit_code" | "op_get_exit_code" =>
|
||||||
op.with_implementation_from(&deno_core::op_void_sync()),
|
op.with_implementation_from(&deno_core::op_void_sync()),
|
||||||
_ => op,
|
_ => op,
|
||||||
},
|
},
|
||||||
|
@ -164,6 +166,12 @@ fn op_set_exit_code(state: &mut OpState, #[smi] code: i32) {
|
||||||
state.borrow_mut::<ExitCode>().set(code);
|
state.borrow_mut::<ExitCode>().set(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[op2(fast)]
|
||||||
|
#[smi]
|
||||||
|
fn op_get_exit_code(state: &mut OpState) -> i32 {
|
||||||
|
state.borrow_mut::<ExitCode>().get()
|
||||||
|
}
|
||||||
|
|
||||||
#[op2(fast)]
|
#[op2(fast)]
|
||||||
fn op_exit(state: &mut OpState) {
|
fn op_exit(state: &mut OpState) {
|
||||||
let code = state.borrow::<ExitCode>().get();
|
let code = state.borrow::<ExitCode>().get();
|
||||||
|
|
5
tests/specs/run/exit_code/__test__.jsonc
Normal file
5
tests/specs/run/exit_code/__test__.jsonc
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"args": "run main.js",
|
||||||
|
"exitCode": 42,
|
||||||
|
"output": "main.out"
|
||||||
|
}
|
7
tests/specs/run/exit_code/main.js
Normal file
7
tests/specs/run/exit_code/main.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
if (Deno.exitCode != 0) {
|
||||||
|
throw new Error("boom!");
|
||||||
|
}
|
||||||
|
|
||||||
|
Deno.exitCode = 42;
|
||||||
|
|
||||||
|
console.log("Deno.exitCode", Deno.exitCode);
|
1
tests/specs/run/exit_code/main.out
Normal file
1
tests/specs/run/exit_code/main.out
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Deno.exitCode 42
|
5
tests/specs/test/exit_code/__test__.jsonc
Normal file
5
tests/specs/test/exit_code/__test__.jsonc
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"args": "test main.js",
|
||||||
|
"exitCode": 1,
|
||||||
|
"output": "main.out"
|
||||||
|
}
|
3
tests/specs/test/exit_code/main.js
Normal file
3
tests/specs/test/exit_code/main.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
Deno.test("Deno.exitCode", () => {
|
||||||
|
Deno.exitCode = 42;
|
||||||
|
});
|
17
tests/specs/test/exit_code/main.out
Normal file
17
tests/specs/test/exit_code/main.out
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
running 1 test from ./main.js
|
||||||
|
Deno.exitCode ... FAILED ([WILDCARD])
|
||||||
|
|
||||||
|
ERRORS
|
||||||
|
|
||||||
|
Deno.exitCode => ./main.js:1:6
|
||||||
|
error: Error: Test case finished with exit code set to 42.
|
||||||
|
at exitSanitizer (ext:cli/40_test.js:113:15)
|
||||||
|
at async outerWrapped (ext:cli/40_test.js:134:14)
|
||||||
|
|
||||||
|
FAILURES
|
||||||
|
|
||||||
|
Deno.exitCode => ./main.js:1:6
|
||||||
|
|
||||||
|
FAILED | 0 passed | 1 failed ([WILDCARD])
|
||||||
|
|
||||||
|
error: Test failed
|
5
tests/specs/test/exit_code2/__test__.jsonc
Normal file
5
tests/specs/test/exit_code2/__test__.jsonc
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"args": "test main.js",
|
||||||
|
"exitCode": 1,
|
||||||
|
"output": "main.out"
|
||||||
|
}
|
7
tests/specs/test/exit_code2/main.js
Normal file
7
tests/specs/test/exit_code2/main.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
Deno.test("Deno.exitCode", () => {
|
||||||
|
Deno.exitCode = 5;
|
||||||
|
throw new Error("");
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("success", () => {
|
||||||
|
});
|
25
tests/specs/test/exit_code2/main.out
Normal file
25
tests/specs/test/exit_code2/main.out
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
running 2 tests from ./main.js
|
||||||
|
Deno.exitCode ... FAILED ([WILDCARD])
|
||||||
|
success ... FAILED ([WILDCARD])
|
||||||
|
|
||||||
|
ERRORS
|
||||||
|
|
||||||
|
Deno.exitCode => ./main.js:1:6
|
||||||
|
error: Error
|
||||||
|
throw new Error("");
|
||||||
|
^
|
||||||
|
at [WILDCARD]/exit_code2/main.js:3:9
|
||||||
|
|
||||||
|
success => ./main.js:6:6
|
||||||
|
error: Error: Test case finished with exit code set to 5.
|
||||||
|
at exitSanitizer (ext:cli/40_test.js:113:15)
|
||||||
|
at async outerWrapped (ext:cli/40_test.js:134:14)
|
||||||
|
|
||||||
|
FAILURES
|
||||||
|
|
||||||
|
Deno.exitCode => ./main.js:1:6
|
||||||
|
success => ./main.js:6:6
|
||||||
|
|
||||||
|
FAILED | 0 passed | 2 failed ([WILDCARD])
|
||||||
|
|
||||||
|
error: Test failed
|
5
tests/specs/test/exit_code3/__test__.jsonc
Normal file
5
tests/specs/test/exit_code3/__test__.jsonc
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"args": "test main.js",
|
||||||
|
"exitCode": 1,
|
||||||
|
"output": "main.out"
|
||||||
|
}
|
6
tests/specs/test/exit_code3/main.js
Normal file
6
tests/specs/test/exit_code3/main.js
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
Deno.test("Deno.exitCode", () => {
|
||||||
|
Deno.exitCode = 42;
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("success", () => {
|
||||||
|
});
|
18
tests/specs/test/exit_code3/main.out
Normal file
18
tests/specs/test/exit_code3/main.out
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
running 2 tests from ./main.js
|
||||||
|
Deno.exitCode ... FAILED ([WILDCARD])
|
||||||
|
success ... ok ([WILDCARD])
|
||||||
|
|
||||||
|
ERRORS
|
||||||
|
|
||||||
|
Deno.exitCode => ./main.js:1:6
|
||||||
|
error: Error: Test case finished with exit code set to 42.
|
||||||
|
at exitSanitizer (ext:cli/40_test.js:113:15)
|
||||||
|
at async outerWrapped (ext:cli/40_test.js:134:14)
|
||||||
|
|
||||||
|
FAILURES
|
||||||
|
|
||||||
|
Deno.exitCode => ./main.js:1:6
|
||||||
|
|
||||||
|
FAILED | 1 passed | 1 failed ([WILDCARD])
|
||||||
|
|
||||||
|
error: Test failed
|
|
@ -787,10 +787,10 @@ Deno.test("process.exitCode", () => {
|
||||||
assertEquals(process.exitCode, undefined);
|
assertEquals(process.exitCode, undefined);
|
||||||
process.exitCode = 127;
|
process.exitCode = 127;
|
||||||
assertEquals(process.exitCode, 127);
|
assertEquals(process.exitCode, 127);
|
||||||
|
assertThrows(() => {
|
||||||
// deno-lint-ignore no-explicit-any
|
// deno-lint-ignore no-explicit-any
|
||||||
(process.exitCode as any) = "asdf";
|
(process.exitCode as any) = "asdf";
|
||||||
// deno-lint-ignore no-explicit-any
|
});
|
||||||
assertEquals(process.exitCode as any, "asdf");
|
|
||||||
// deno-lint-ignore no-explicit-any
|
// deno-lint-ignore no-explicit-any
|
||||||
(process.exitCode as any) = "10";
|
(process.exitCode as any) = "10";
|
||||||
process.exitCode = undefined; // reset
|
process.exitCode = undefined; // reset
|
||||||
|
@ -827,7 +827,7 @@ Deno.test("process.exitCode in should change exit code", async () => {
|
||||||
);
|
);
|
||||||
await exitCodeTest(
|
await exitCodeTest(
|
||||||
"import process from 'node:process'; process.exitCode = NaN;",
|
"import process from 'node:process'; process.exitCode = NaN;",
|
||||||
0,
|
1,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue