1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-24 16:19:12 -05:00

test: add unit tests from std/node (#17794)

Adds two test files: "cli/tests/unit_node/process_test.ts" and
"cli/tests/unit_node/child_process_test.ts"

---------

Co-authored-by: Yoshiya Hinosawa <stibium121@gmail.com>
This commit is contained in:
Bartek Iwańczuk 2023-02-16 14:30:14 +01:00 committed by GitHub
parent 848e2c0d57
commit 4c2380af5c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 1471 additions and 80 deletions

View file

@ -70,6 +70,8 @@ mod js_unit_tests;
mod lint;
#[path = "lsp_tests.rs"]
mod lsp;
#[path = "node_unit_tests.rs"]
mod node_unit_tests;
#[path = "npm_tests.rs"]
mod npm;
#[path = "repl_tests.rs"]

View file

@ -0,0 +1,21 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use test_util as util;
#[test]
fn node_unit_tests() {
let _g = util::http_server();
let mut deno = util::deno_cmd()
.current_dir(util::root_path())
.arg("test")
.arg("--unstable")
.arg("-A")
.arg(util::tests_path().join("unit_node"))
.spawn()
.expect("failed to spawn script");
let status = deno.wait().expect("failed to wait for the child process");
assert_eq!(Some(0), status.code());
assert!(status.success());
}

View file

@ -0,0 +1,577 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
import CP from "node:child_process";
import { Buffer } from "node:buffer";
import {
assert,
assertEquals,
assertExists,
assertNotStrictEquals,
assertStrictEquals,
assertStringIncludes,
} from "../../../test_util/std/testing/asserts.ts";
import { Deferred, deferred } from "../../../test_util/std/async/deferred.ts";
import * as path from "../../../test_util/std/path/mod.ts";
const { spawn, execFile, execFileSync, ChildProcess } = CP;
function withTimeout<T>(timeoutInMS: number): Deferred<T> {
const promise = deferred<T>();
const timer = setTimeout(() => {
promise.reject("Timeout");
}, timeoutInMS);
promise.then(() => {
clearTimeout(timer);
});
return promise;
}
// TODO(uki00a): Once Node.js's `parallel/test-child-process-spawn-error.js` works, this test case should be removed.
Deno.test("[node/child_process spawn] The 'error' event is emitted when no binary is found", async () => {
const promise = withTimeout(1000);
const childProcess = spawn("no-such-cmd");
childProcess.on("error", (_err: Error) => {
// TODO(@bartlomieju) Assert an error message.
promise.resolve();
});
await promise;
});
Deno.test("[node/child_process spawn] The 'exit' event is emitted with an exit code after the child process ends", async () => {
const promise = withTimeout(3000);
const childProcess = spawn(Deno.execPath(), ["--help"], {
env: { NO_COLOR: "true" },
});
try {
let exitCode = null;
childProcess.on("exit", (code: number) => {
promise.resolve();
exitCode = code;
});
await promise;
assertStrictEquals(exitCode, 0);
assertStrictEquals(childProcess.exitCode, exitCode);
} finally {
childProcess.kill();
childProcess.stdout?.destroy();
childProcess.stderr?.destroy();
}
});
Deno.test("[node/child_process disconnect] the method exists", async () => {
const promise = withTimeout(1000);
const childProcess = spawn(Deno.execPath(), ["--help"], {
env: { NO_COLOR: "true" },
});
try {
childProcess.disconnect();
childProcess.on("exit", () => {
promise.resolve();
});
await promise;
} finally {
childProcess.kill();
childProcess.stdout?.destroy();
childProcess.stderr?.destroy();
}
});
Deno.test({
name: "[node/child_process spawn] Verify that stdin and stdout work",
fn: async () => {
const promise = withTimeout(3000);
const childProcess = spawn(Deno.execPath(), ["fmt", "-"], {
env: { NO_COLOR: "true" },
stdio: ["pipe", "pipe"],
});
try {
assert(childProcess.stdin, "stdin should be defined");
assert(childProcess.stdout, "stdout should be defined");
let data = "";
childProcess.stdout.on("data", (chunk) => {
data += chunk;
});
childProcess.stdin.write(" console.log('hello')", "utf-8");
childProcess.stdin.end();
childProcess.on("close", () => {
promise.resolve();
});
await promise;
assertStrictEquals(data, `console.log("hello");\n`);
} finally {
childProcess.kill();
}
},
});
Deno.test({
name: "[node/child_process spawn] stdin and stdout with binary data",
fn: async () => {
const promise = withTimeout(10000);
const p = path.join(
path.dirname(path.fromFileUrl(import.meta.url)),
"./testdata/binary_stdio.js",
);
const childProcess = spawn(Deno.execPath(), ["run", p], {
env: { NO_COLOR: "true" },
stdio: ["pipe", "pipe"],
});
try {
assert(childProcess.stdin, "stdin should be defined");
assert(childProcess.stdout, "stdout should be defined");
let data: Buffer;
childProcess.stdout.on("data", (chunk) => {
data = chunk;
});
const buffer = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
childProcess.stdin.write(buffer);
childProcess.stdin.end();
childProcess.on("close", () => {
promise.resolve();
});
await promise;
assertEquals(new Uint8Array(data!), buffer);
} finally {
childProcess.kill();
}
},
});
async function spawnAndGetEnvValue(
inputValue: string | number | boolean,
): Promise<string> {
const promise = withTimeout<string>(3000);
const env = spawn(
`"${Deno.execPath()}" eval -p "Deno.env.toObject().BAZ"`,
{
env: { BAZ: String(inputValue), NO_COLOR: "true" },
shell: true,
},
);
try {
let envOutput = "";
assert(env.stdout);
env.on("error", (err: Error) => promise.reject(err));
env.stdout.on("data", (data) => {
envOutput += data;
});
env.on("close", () => {
promise.resolve(envOutput.trim());
});
return await promise;
} finally {
env.kill();
}
}
Deno.test({
ignore: Deno.build.os === "windows",
name:
"[node/child_process spawn] Verify that environment values can be numbers",
async fn() {
const envOutputValue = await spawnAndGetEnvValue(42);
assertStrictEquals(envOutputValue, "42");
},
});
Deno.test({
ignore: Deno.build.os === "windows",
name:
"[node/child_process spawn] Verify that environment values can be booleans",
async fn() {
const envOutputValue = await spawnAndGetEnvValue(false);
assertStrictEquals(envOutputValue, "false");
},
});
/* Start of ported part */ 3;
// Copyright Joyent and Node contributors. All rights reserved. MIT license.
// Ported from Node 15.5.1
// TODO(uki00a): Remove this case once Node's `parallel/test-child-process-spawn-event.js` works.
Deno.test("[child_process spawn] 'spawn' event", async () => {
const timeout = withTimeout(3000);
const subprocess = spawn(Deno.execPath(), ["eval", "console.log('ok')"]);
let didSpawn = false;
subprocess.on("spawn", function () {
didSpawn = true;
});
function mustNotBeCalled() {
timeout.reject(new Error("function should not have been called"));
}
const promises = [] as Promise<void>[];
function mustBeCalledAfterSpawn() {
const promise = deferred<void>();
promises.push(promise);
return () => {
if (didSpawn) {
promise.resolve();
} else {
promise.reject(
new Error("function should be called after the 'spawn' event"),
);
}
};
}
subprocess.on("error", mustNotBeCalled);
subprocess.stdout!.on("data", mustBeCalledAfterSpawn());
subprocess.stdout!.on("end", mustBeCalledAfterSpawn());
subprocess.stdout!.on("close", mustBeCalledAfterSpawn());
subprocess.stderr!.on("data", mustNotBeCalled);
subprocess.stderr!.on("end", mustBeCalledAfterSpawn());
subprocess.stderr!.on("close", mustBeCalledAfterSpawn());
subprocess.on("exit", mustBeCalledAfterSpawn());
subprocess.on("close", mustBeCalledAfterSpawn());
try {
await Promise.race([Promise.all(promises), timeout]);
timeout.resolve();
} finally {
subprocess.kill();
}
});
// TODO(uki00a): Remove this case once Node's `parallel/test-child-process-spawn-shell.js` works.
Deno.test("[child_process spawn] Verify that a shell is executed", async () => {
const promise = withTimeout(3000);
const doesNotExist = spawn("does-not-exist", { shell: true });
try {
assertNotStrictEquals(doesNotExist.spawnfile, "does-not-exist");
doesNotExist.on("error", () => {
promise.reject("The 'error' event must not be emitted.");
});
doesNotExist.on("exit", (code: number, signal: null) => {
assertStrictEquals(signal, null);
if (Deno.build.os === "windows") {
assertStrictEquals(code, 1); // Exit code of cmd.exe
} else {
assertStrictEquals(code, 127); // Exit code of /bin/sh });
}
promise.resolve();
});
await promise;
} finally {
doesNotExist.kill();
doesNotExist.stdout?.destroy();
doesNotExist.stderr?.destroy();
}
});
// TODO(uki00a): Remove this case once Node's `parallel/test-child-process-spawn-shell.js` works.
Deno.test({
ignore: Deno.build.os === "windows",
name: "[node/child_process spawn] Verify that passing arguments works",
async fn() {
const promise = withTimeout(3000);
const echo = spawn("echo", ["foo"], {
shell: true,
});
let echoOutput = "";
try {
assertStrictEquals(
echo.spawnargs[echo.spawnargs.length - 1].replace(/"/g, ""),
"echo foo",
);
assert(echo.stdout);
echo.stdout.on("data", (data) => {
echoOutput += data;
});
echo.on("close", () => {
assertStrictEquals(echoOutput.trim(), "foo");
promise.resolve();
});
await promise;
} finally {
echo.kill();
}
},
});
// TODO(uki00a): Remove this case once Node's `parallel/test-child-process-spawn-shell.js` works.
Deno.test({
ignore: Deno.build.os === "windows",
name: "[node/child_process spawn] Verity that shell features can be used",
async fn() {
const promise = withTimeout(3000);
const cmd = "echo bar | cat";
const command = spawn(cmd, {
shell: true,
});
try {
let commandOutput = "";
assert(command.stdout);
command.stdout.on("data", (data) => {
commandOutput += data;
});
command.on("close", () => {
assertStrictEquals(commandOutput.trim(), "bar");
promise.resolve();
});
await promise;
} finally {
command.kill();
}
},
});
// TODO(uki00a): Remove this case once Node's `parallel/test-child-process-spawn-shell.js` works.
Deno.test({
ignore: Deno.build.os === "windows",
name:
"[node/child_process spawn] Verity that environment is properly inherited",
async fn() {
const promise = withTimeout(3000);
const env = spawn(
`"${Deno.execPath()}" eval -p "Deno.env.toObject().BAZ"`,
{
env: { BAZ: "buzz", NO_COLOR: "true" },
shell: true,
},
);
try {
let envOutput = "";
assert(env.stdout);
env.on("error", (err: Error) => promise.reject(err));
env.stdout.on("data", (data) => {
envOutput += data;
});
env.on("close", () => {
assertStrictEquals(envOutput.trim(), "buzz");
promise.resolve();
});
await promise;
} finally {
env.kill();
}
},
});
/* End of ported part */
Deno.test({
name: "[node/child_process execFile] Get stdout as a string",
async fn() {
let child: unknown;
const script = path.join(
path.dirname(path.fromFileUrl(import.meta.url)),
"./testdata/exec_file_text_output.js",
);
const promise = new Promise<string | null>((resolve, reject) => {
child = execFile(Deno.execPath(), ["run", script], (err, stdout) => {
if (err) reject(err);
else if (stdout) resolve(stdout as string);
else resolve(null);
});
});
try {
const stdout = await promise;
assertEquals(stdout, "Hello World!\n");
} finally {
if (child instanceof ChildProcess) {
child.kill();
}
}
},
});
Deno.test({
name: "[node/child_process execFile] Get stdout as a buffer",
async fn() {
let child: unknown;
const script = path.join(
path.dirname(path.fromFileUrl(import.meta.url)),
"./testdata/exec_file_text_output.js",
);
const promise = new Promise<Buffer | null>((resolve, reject) => {
child = execFile(
Deno.execPath(),
["run", script],
{ encoding: "buffer" },
(err, stdout) => {
if (err) reject(err);
else if (stdout) resolve(stdout as Buffer);
else resolve(null);
},
);
});
try {
const stdout = await promise;
assert(Buffer.isBuffer(stdout));
assertEquals(stdout.toString("utf8"), "Hello World!\n");
} finally {
if (child instanceof ChildProcess) {
child.kill();
}
}
},
});
Deno.test({
name: "[node/child_process execFile] Get stderr",
async fn() {
let child: unknown;
const script = path.join(
path.dirname(path.fromFileUrl(import.meta.url)),
"./testdata/exec_file_text_error.js",
);
const promise = new Promise<
{ err: Error | null; stderr?: string | Buffer }
>((resolve) => {
child = execFile(Deno.execPath(), ["run", script], (err, _, stderr) => {
resolve({ err, stderr });
});
});
try {
const { err, stderr } = await promise;
if (child instanceof ChildProcess) {
assertEquals(child.exitCode, 1);
assertEquals(stderr, "yikes!\n");
} else {
throw err;
}
} finally {
if (child instanceof ChildProcess) {
child.kill();
}
}
},
});
Deno.test({
name: "[node/child_process execFile] Exceed given maxBuffer limit",
async fn() {
let child: unknown;
const script = path.join(
path.dirname(path.fromFileUrl(import.meta.url)),
"./testdata/exec_file_text_error.js",
);
const promise = new Promise<
{ err: Error | null; stderr?: string | Buffer }
>((resolve) => {
child = execFile(Deno.execPath(), ["run", script], {
encoding: "buffer",
maxBuffer: 3,
}, (err, _, stderr) => {
resolve({ err, stderr });
});
});
try {
const { err, stderr } = await promise;
if (child instanceof ChildProcess) {
assert(err);
assertEquals(
// deno-lint-ignore no-explicit-any
(err as any).code,
"ERR_CHILD_PROCESS_STDIO_MAXBUFFER",
);
assertEquals(err.message, "stderr maxBuffer length exceeded");
assertEquals((stderr as Buffer).toString("utf8"), "yik");
} else {
throw err;
}
} finally {
if (child instanceof ChildProcess) {
child.kill();
}
}
},
});
Deno.test({
name: "[node/child_process] ChildProcess.kill()",
async fn() {
const script = path.join(
path.dirname(path.fromFileUrl(import.meta.url)),
"./testdata/infinite_loop.js",
);
const childProcess = spawn(Deno.execPath(), ["run", script]);
const p = withTimeout(3000);
childProcess.on("exit", () => p.resolve());
childProcess.kill("SIGKILL");
await p;
assert(childProcess.killed);
assertEquals(childProcess.signalCode, "SIGKILL");
assertExists(childProcess.exitCode);
},
});
Deno.test({
name: "[node/child_process] ChildProcess.unref()",
async fn() {
const script = path.join(
path.dirname(path.fromFileUrl(import.meta.url)),
"testdata",
"child_process_unref.js",
);
const childProcess = spawn(Deno.execPath(), [
"run",
"-A",
"--unstable",
script,
]);
const p = deferred();
childProcess.on("exit", () => p.resolve());
await p;
},
});
Deno.test({
name: "[node/child_process] child_process.fork",
async fn() {
const testdataDir = path.join(
path.dirname(path.fromFileUrl(import.meta.url)),
"testdata",
);
const script = path.join(
testdataDir,
"node_modules",
"foo",
"index.js",
);
const p = deferred();
const cp = CP.fork(script, [], { cwd: testdataDir, stdio: "pipe" });
let output = "";
cp.on("close", () => p.resolve());
cp.stdout?.on("data", (data) => {
output += data;
});
await p;
assertEquals(output, "foo\ntrue\ntrue\ntrue\n");
},
});
Deno.test("[node/child_process execFileSync] 'inherit' stdout and stderr", () => {
execFileSync(Deno.execPath(), ["--help"], { stdio: "inherit" });
});
Deno.test(
"[node/child_process spawn] supports windowsVerbatimArguments option",
{ ignore: Deno.build.os !== "windows" },
async () => {
const cmdFinished = deferred();
let output = "";
const cp = spawn("cmd", ["/d", "/s", "/c", '"deno ^"--version^""'], {
stdio: "pipe",
windowsVerbatimArguments: true,
});
cp.on("close", () => cmdFinished.resolve());
cp.stdout?.on("data", (data) => {
output += data;
});
await cmdFinished;
assertStringIncludes(output, "deno");
assertStringIncludes(output, "v8");
assertStringIncludes(output, "typescript");
},
);

View file

@ -0,0 +1,713 @@
// deno-lint-ignore-file no-undef
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
import process, { argv, env } from "node:process";
import {
assert,
assertEquals,
assertFalse,
assertObjectMatch,
assertStrictEquals,
assertThrows,
} from "../../../test_util/std/testing/asserts.ts";
import { stripColor } from "../../../test_util/std/fmt/colors.ts";
import { deferred } from "../../../test_util/std/async/deferred.ts";
import * as path from "../../../test_util/std/path/mod.ts";
import { delay } from "../../../test_util/std/async/delay.ts";
const testDir = new URL(".", import.meta.url);
Deno.test({
name: "process.cwd and process.chdir success",
fn() {
assertEquals(process.cwd(), Deno.cwd());
const currentDir = Deno.cwd();
const tempDir = Deno.makeTempDirSync();
process.chdir(tempDir);
assertEquals(
Deno.realPathSync(process.cwd()),
Deno.realPathSync(tempDir),
);
process.chdir(currentDir);
},
});
Deno.test({
name: "process.chdir failure",
fn() {
assertThrows(
() => {
process.chdir("non-existent-directory-name");
},
Deno.errors.NotFound,
"file",
// On every OS Deno returns: "No such file" except for Windows, where it's:
// "The system cannot find the file specified. (os error 2)" so "file" is
// the only common string here.
);
},
});
Deno.test({
name: "process.version",
fn() {
assertEquals(typeof process, "object");
assertEquals(typeof process.version, "string");
assertEquals(typeof process.versions, "object");
assertEquals(typeof process.versions.node, "string");
assertEquals(typeof process.versions.v8, "string");
assertEquals(typeof process.versions.uv, "string");
assertEquals(typeof process.versions.zlib, "string");
assertEquals(typeof process.versions.brotli, "string");
assertEquals(typeof process.versions.ares, "string");
assertEquals(typeof process.versions.modules, "string");
assertEquals(typeof process.versions.nghttp2, "string");
assertEquals(typeof process.versions.napi, "string");
assertEquals(typeof process.versions.llhttp, "string");
assertEquals(typeof process.versions.openssl, "string");
assertEquals(typeof process.versions.cldr, "string");
assertEquals(typeof process.versions.icu, "string");
assertEquals(typeof process.versions.tz, "string");
assertEquals(typeof process.versions.unicode, "string");
// These two are not present in `process.versions` in Node, but we
// add them anyway
assertEquals(typeof process.versions.deno, "string");
assertEquals(typeof process.versions.typescript, "string");
},
});
Deno.test({
name: "process.platform",
fn() {
assertEquals(typeof process.platform, "string");
},
});
Deno.test({
name: "process.mainModule",
fn() {
assertEquals(process.mainModule, undefined);
// Check that it is writable
// @ts-ignore these are deprecated now
process.mainModule = "foo";
// @ts-ignore these are deprecated now
assertEquals(process.mainModule, "foo");
},
});
Deno.test({
name: "process.arch",
fn() {
assertEquals(typeof process.arch, "string");
if (Deno.build.arch == "x86_64") {
assertEquals(process.arch, "x64");
} else if (Deno.build.arch == "aarch64") {
assertEquals(process.arch, "arm64");
} else {
throw new Error("unreachable");
}
},
});
Deno.test({
name: "process.pid",
fn() {
assertEquals(typeof process.pid, "number");
assertEquals(process.pid, Deno.pid);
},
});
Deno.test({
name: "process.on",
async fn() {
assertEquals(typeof process.on, "function");
let triggered = false;
process.on("exit", () => {
triggered = true;
});
// @ts-ignore fix the type here
process.emit("exit");
assert(triggered);
const cwd = path.dirname(path.fromFileUrl(import.meta.url));
const command = new Deno.Command(Deno.execPath(), {
args: [
"run",
"--quiet",
"--unstable",
"./testdata/process_exit.ts",
],
cwd,
});
const { stdout } = await command.output();
const decoder = new TextDecoder();
assertEquals(stripColor(decoder.decode(stdout).trim()), "1\n2");
},
});
Deno.test({
name: "process.on signal",
ignore: Deno.build.os == "windows",
async fn() {
const promise = deferred();
let c = 0;
const listener = () => {
c += 1;
};
process.on("SIGINT", listener);
setTimeout(async () => {
// Sends SIGINT 3 times.
for (const _ of Array(3)) {
await delay(20);
Deno.kill(Deno.pid, "SIGINT");
}
await delay(20);
Deno.removeSignalListener("SIGINT", listener);
promise.resolve();
});
await promise;
assertEquals(c, 3);
},
});
Deno.test({
name: "process.off signal",
ignore: Deno.build.os == "windows",
async fn() {
const promise = deferred();
let c = 0;
const listener = () => {
c += 1;
process.off("SIGINT", listener);
};
process.on("SIGINT", listener);
setTimeout(async () => {
// Sends SIGINT 3 times.
for (const _ of Array(3)) {
await delay(20);
Deno.kill(Deno.pid, "SIGINT");
}
await delay(20);
promise.resolve();
});
await promise;
assertEquals(c, 1);
},
});
Deno.test({
name: "process.on SIGBREAK doesn't throw",
fn() {
const listener = () => {};
process.on("SIGBREAK", listener);
process.off("SIGBREAK", listener);
},
});
Deno.test({
name: "process.on SIGTERM doesn't throw on windows",
ignore: Deno.build.os !== "windows",
fn() {
const listener = () => {};
process.on("SIGTERM", listener);
process.off("SIGTERM", listener);
},
});
Deno.test({
name: "process.argv",
fn() {
assert(Array.isArray(argv));
assert(Array.isArray(process.argv));
assert(
process.argv[0].match(/[^/\\]*deno[^/\\]*$/),
"deno included in the file name of argv[0]",
);
assertEquals(
process.argv[1],
path.fromFileUrl(Deno.mainModule),
);
// argv supports array methods.
assert(Array.isArray(process.argv.slice(2)));
assertEquals(process.argv.indexOf(Deno.execPath()), 0);
assertEquals(process.argv.indexOf(path.fromFileUrl(Deno.mainModule)), 1);
},
});
Deno.test({
name: "process.execArgv",
fn() {
assert(Array.isArray(process.execArgv));
assert(process.execArgv.length == 0);
// execArgv supports array methods.
assert(Array.isArray(process.argv.slice(0)));
assertEquals(process.argv.indexOf("foo"), -1);
},
});
Deno.test({
name: "process.env",
fn() {
Deno.env.set("HELLO", "WORLD");
assertObjectMatch(process.env, Deno.env.toObject());
assertEquals(typeof (process.env.HELLO), "string");
assertEquals(process.env.HELLO, "WORLD");
assertEquals(typeof env.HELLO, "string");
assertEquals(env.HELLO, "WORLD");
assert(Object.getOwnPropertyNames(process.env).includes("HELLO"));
assert(Object.keys(process.env).includes("HELLO"));
assert(Object.prototype.hasOwnProperty.call(process.env, "HELLO"));
assert(
!Object.prototype.hasOwnProperty.call(
process.env,
"SURELY_NON_EXISTENT_VAR",
),
);
// deno-lint-ignore no-prototype-builtins
assert(process.env.hasOwnProperty("HELLO"));
assert("HELLO" in process.env);
assert(Object.keys(process.env.valueOf()).includes("HELLO"));
assertEquals(process.env.toString(), "[object Object]");
assertEquals(process.env.toLocaleString(), "[object Object]");
// should not error when assigning false to an env var
process.env.HELLO = false as unknown as string;
assertEquals(process.env.HELLO, "false");
process.env.HELLO = "WORLD";
assertEquals(process.env.HELLO, "WORLD");
},
});
Deno.test({
name: "process.env requires scoped env permission",
permissions: { env: ["FOO"] },
fn() {
Deno.env.set("FOO", "1");
assert("FOO" in process.env);
assertFalse("BAR" in process.env);
assert(Object.hasOwn(process.env, "FOO"));
assertFalse(Object.hasOwn(process.env, "BAR"));
},
});
Deno.test({
name: "process.env doesn't throw with invalid env var names",
fn() {
assertEquals(process.env[""], undefined);
assertEquals(process.env["\0"], undefined);
assertEquals(process.env["=c:"], undefined);
assertFalse(Object.hasOwn(process.env, ""));
assertFalse(Object.hasOwn(process.env, "\0"));
assertFalse(Object.hasOwn(process.env, "=c:"));
assertFalse("" in process.env);
assertFalse("\0" in process.env);
assertFalse("=c:" in process.env);
},
});
Deno.test({
name: "process.stdin",
fn() {
assertEquals(process.stdin.fd, Deno.stdin.rid);
assertEquals(process.stdin.isTTY, Deno.isatty(Deno.stdin.rid));
},
});
Deno.test({
name: "process.stdin readable with a TTY",
// TODO(PolarETech): Run this test even in non tty environment
ignore: !Deno.isatty(Deno.stdin.rid),
async fn() {
const promise = deferred();
const expected = ["foo", "bar", null, "end"];
const data: (string | null)[] = [];
process.stdin.setEncoding("utf8");
process.stdin.on("readable", () => {
data.push(process.stdin.read());
});
process.stdin.on("end", () => {
data.push("end");
});
process.stdin.push("foo");
process.nextTick(() => {
process.stdin.push("bar");
process.nextTick(() => {
process.stdin.push(null);
promise.resolve();
});
});
await promise;
assertEquals(process.stdin.readableHighWaterMark, 0);
assertEquals(data, expected);
},
});
Deno.test({
name: "process.stdin readable with piping a file",
async fn() {
const expected = ["65536", "foo", "bar", "null", "end"];
const scriptPath = "./testdata/process_stdin.ts";
const filePath = "./testdata/process_stdin_dummy.txt";
const shell = Deno.build.os === "windows" ? "cmd.exe" : "/bin/sh";
const cmd = `"${Deno.execPath()}" run ${scriptPath} < ${filePath}`;
const args = Deno.build.os === "windows" ? ["/d", "/c", cmd] : ["-c", cmd];
const p = new Deno.Command(shell, {
args,
stdin: "null",
stdout: "piped",
stderr: "null",
windowsRawArguments: true,
cwd: testDir,
});
const { stdout } = await p.output();
const data = new TextDecoder().decode(stdout).trim().split("\n");
assertEquals(data, expected);
},
});
Deno.test({
name: "process.stdin readable with piping a stream",
async fn() {
const expected = ["16384", "foo", "bar", "null", "end"];
const scriptPath = "./testdata/process_stdin.ts";
const command = new Deno.Command(Deno.execPath(), {
args: ["run", scriptPath],
stdin: "piped",
stdout: "piped",
stderr: "null",
cwd: testDir,
});
const child = command.spawn();
const writer = await child.stdin.getWriter();
writer.ready
.then(() => writer.write(new TextEncoder().encode("foo\nbar")))
.then(() => writer.releaseLock())
.then(() => child.stdin.close());
const { stdout } = await child.output();
const data = new TextDecoder().decode(stdout).trim().split("\n");
assertEquals(data, expected);
},
});
Deno.test({
name: "process.stdin readable with piping a socket",
ignore: Deno.build.os === "windows",
async fn() {
const expected = ["16384", "foo", "bar", "null", "end"];
const scriptPath = "./testdata/process_stdin.ts";
const listener = Deno.listen({ hostname: "127.0.0.1", port: 9000 });
listener.accept().then(async (conn) => {
await conn.write(new TextEncoder().encode("foo\nbar"));
conn.close();
listener.close();
});
const shell = "/bin/bash";
const cmd =
`"${Deno.execPath()}" run ${scriptPath} < /dev/tcp/127.0.0.1/9000`;
const args = ["-c", cmd];
const p = new Deno.Command(shell, {
args,
stdin: "null",
stdout: "piped",
stderr: "null",
cwd: testDir,
});
const { stdout } = await p.output();
const data = new TextDecoder().decode(stdout).trim().split("\n");
assertEquals(data, expected);
},
});
Deno.test({
name: "process.stdin readable with null",
async fn() {
const expected = ["65536", "null", "end"];
const scriptPath = "./testdata/process_stdin.ts";
const command = new Deno.Command(Deno.execPath(), {
args: ["run", scriptPath],
stdin: "null",
stdout: "piped",
stderr: "null",
cwd: testDir,
});
const { stdout } = await command.output();
const data = new TextDecoder().decode(stdout).trim().split("\n");
assertEquals(data, expected);
},
});
// TODO(kt3k): Enable this test case. 'readable' event handler in
// `process_stdin.ts` doesn't work now
Deno.test({
name: "process.stdin readable with unsuitable stdin",
ignore: true,
// // TODO(PolarETech): Prepare a similar test that can be run on Windows
// ignore: Deno.build.os === "windows",
async fn() {
const expected = ["16384", "null", "end"];
const scriptPath = "./testdata/process_stdin.ts";
const directoryPath = "./testdata/";
const shell = "/bin/bash";
const cmd = `"${Deno.execPath()}" run ${scriptPath} < ${directoryPath}`;
const args = ["-c", cmd];
const p = new Deno.Command(shell, {
args,
stdin: "null",
stdout: "piped",
stderr: "null",
windowsRawArguments: true,
cwd: testDir,
});
const { stdout } = await p.output();
const data = new TextDecoder().decode(stdout).trim().split("\n");
assertEquals(data, expected);
},
});
Deno.test({
name: "process.stdout",
fn() {
assertEquals(process.stdout.fd, Deno.stdout.rid);
const isTTY = Deno.isatty(Deno.stdout.rid);
assertEquals(process.stdout.isTTY, isTTY);
const consoleSize = isTTY ? Deno.consoleSize() : undefined;
assertEquals(process.stdout.columns, consoleSize?.columns);
assertEquals(process.stdout.rows, consoleSize?.rows);
assertEquals(
`${process.stdout.getWindowSize()}`,
`${consoleSize && [consoleSize.columns, consoleSize.rows]}`,
);
if (isTTY) {
assertStrictEquals(process.stdout.cursorTo(1, 2, () => {}), true);
assertStrictEquals(process.stdout.moveCursor(3, 4, () => {}), true);
assertStrictEquals(process.stdout.clearLine(1, () => {}), true);
assertStrictEquals(process.stdout.clearScreenDown(() => {}), true);
} else {
assertStrictEquals(process.stdout.cursorTo, undefined);
assertStrictEquals(process.stdout.moveCursor, undefined);
assertStrictEquals(process.stdout.clearLine, undefined);
assertStrictEquals(process.stdout.clearScreenDown, undefined);
}
},
});
Deno.test({
name: "process.stderr",
fn() {
assertEquals(process.stderr.fd, Deno.stderr.rid);
const isTTY = Deno.isatty(Deno.stderr.rid);
assertEquals(process.stderr.isTTY, isTTY);
const consoleSize = isTTY ? Deno.consoleSize() : undefined;
assertEquals(process.stderr.columns, consoleSize?.columns);
assertEquals(process.stderr.rows, consoleSize?.rows);
assertEquals(
`${process.stderr.getWindowSize()}`,
`${consoleSize && [consoleSize.columns, consoleSize.rows]}`,
);
if (isTTY) {
assertStrictEquals(process.stderr.cursorTo(1, 2, () => {}), true);
assertStrictEquals(process.stderr.moveCursor(3, 4, () => {}), true);
assertStrictEquals(process.stderr.clearLine(1, () => {}), true);
assertStrictEquals(process.stderr.clearScreenDown(() => {}), true);
} else {
assertStrictEquals(process.stderr.cursorTo, undefined);
assertStrictEquals(process.stderr.moveCursor, undefined);
assertStrictEquals(process.stderr.clearLine, undefined);
assertStrictEquals(process.stderr.clearScreenDown, undefined);
}
},
});
Deno.test({
name: "process.nextTick",
async fn() {
let withoutArguments = false;
process.nextTick(() => {
withoutArguments = true;
});
const expected = 12;
let result;
process.nextTick((x: number) => {
result = x;
}, 12);
await delay(10);
assert(withoutArguments);
assertEquals(result, expected);
},
});
Deno.test({
name: "process.hrtime",
// TODO(kt3k): Enable this test
ignore: true,
fn() {
const [sec0, nano0] = process.hrtime();
// seconds and nano seconds are positive integers.
assert(sec0 > 0);
assert(Number.isInteger(sec0));
assert(nano0 > 0);
assert(Number.isInteger(nano0));
const [sec1, nano1] = process.hrtime();
// the later call returns bigger value
assert(sec1 >= sec0);
assert(nano1 > nano0);
const [sec2, nano2] = process.hrtime([sec1, nano1]);
// the difference of the 2 calls is a small positive value.
assertEquals(sec2, 0);
assert(nano2 > 0);
},
});
Deno.test({
name: "process.hrtime.bigint",
fn() {
const time = process.hrtime.bigint();
assertEquals(typeof time, "bigint");
assert(time > 0n);
},
});
Deno.test("process.on, process.off, process.removeListener doesn't throw on unimplemented events", () => {
const events = [
"beforeExit",
"disconnect",
"message",
"multipleResolves",
"rejectionHandled",
"uncaughtException",
"uncaughtExceptionMonitor",
"unhandledRejection",
"worker",
];
const handler = () => {};
events.forEach((ev) => {
process.on(ev, handler);
assertEquals(process.listenerCount(ev), 1);
process.off(ev, handler);
assertEquals(process.listenerCount(ev), 0);
process.on(ev, handler);
assertEquals(process.listenerCount(ev), 1);
process.removeListener(ev, handler);
assertEquals(process.listenerCount(ev), 0);
});
});
Deno.test("process.memoryUsage()", () => {
const mem = process.memoryUsage();
assert(typeof mem.rss === "number");
assert(typeof mem.heapTotal === "number");
assert(typeof mem.heapUsed === "number");
assert(typeof mem.external === "number");
assert(typeof mem.arrayBuffers === "number");
assertEquals(mem.arrayBuffers, 0);
});
Deno.test("process.memoryUsage.rss()", () => {
const rss = process.memoryUsage.rss();
assert(typeof rss === "number");
});
Deno.test("process.exitCode", () => {
assert(process.exitCode === undefined);
process.exitCode = 127;
assert(process.exitCode === 127);
});
Deno.test("process.config", () => {
assert(process.config !== undefined);
assert(process.config.target_defaults !== undefined);
assert(process.config.variables !== undefined);
});
Deno.test("process._exiting", () => {
// @ts-ignore fix the type here
assert(process._exiting === false);
});
Deno.test("process.execPath", () => {
assertEquals(process.execPath, process.argv[0]);
});
Deno.test("process.execPath is writable", () => {
// pnpm writes to process.execPath
// https://github.com/pnpm/pnpm/blob/67d8b65d2e8da1df3725034b8c5b1fcf3af4ad81/packages/config/src/index.ts#L175
const originalExecPath = process.execPath;
try {
process.execPath = "/path/to/node";
assertEquals(process.execPath, "/path/to/node");
} finally {
process.execPath = originalExecPath;
}
});
Deno.test("process.getgid", () => {
if (Deno.build.os === "windows") {
assertEquals(process.getgid, undefined);
} else {
assertEquals(process.getgid?.(), Deno.gid());
}
});
Deno.test("process.getuid", () => {
if (Deno.build.os === "windows") {
assertEquals(process.getuid, undefined);
} else {
assertEquals(process.getuid?.(), Deno.uid());
}
});
Deno.test({
name: "process.exit",
async fn() {
const command = new Deno.Command(Deno.execPath(), {
args: [
"run",
"--quiet",
"--unstable",
"./testdata/process_exit2.ts",
],
cwd: testDir,
});
const { stdout } = await command.output();
const decoder = new TextDecoder();
assertEquals(stripColor(decoder.decode(stdout).trim()), "exit");
},
});

View file

@ -0,0 +1,11 @@
const buffer = new Uint8Array(10);
const nread = await Deno.stdin.read(buffer);
if (nread != 10) {
throw new Error("Too little data read");
}
const nwritten = await Deno.stdout.write(buffer);
if (nwritten != 10) {
throw new Error("Too little data written");
}

View file

@ -0,0 +1,9 @@
import cp from "node:child_process";
import * as path from "node:path";
const script = path.join(
path.dirname(path.fromFileUrl(import.meta.url)),
"infinite_loop.js",
);
const childProcess = cp.spawn(Deno.execPath(), ["run", script]);
childProcess.unref();

View file

@ -0,0 +1,2 @@
console.error("yikes!");
Deno.exit(1);

View file

@ -0,0 +1 @@
console.log("Hello World!");

View file

@ -0,0 +1,3 @@
while (true) {
await new Promise((resolve) => setTimeout(resolve, 1000));
}

View file

@ -0,0 +1,4 @@
console.log("foo");
console.log(typeof require === "function");
console.log(typeof module === "object");
console.log(typeof exports === "object");

View file

@ -0,0 +1,3 @@
{
"name": "foo"
}

View file

@ -0,0 +1,19 @@
import process from "node:process";
//deno-lint-ignore no-undef
process.on("exit", () => {
console.log(1);
});
function unexpected() {
console.log(null);
}
//deno-lint-ignore no-undef
process.on("exit", unexpected);
//deno-lint-ignore no-undef
process.removeListener("exit", unexpected);
//deno-lint-ignore no-undef
process.on("exit", () => {
console.log(2);
});

View file

@ -0,0 +1,4 @@
import process from "node:process";
process.on("exit", () => console.log("exit"));
process.exit();

View file

@ -0,0 +1,11 @@
import process from "node:process";
console.log(process.stdin.readableHighWaterMark);
process.stdin.setEncoding("utf8");
process.stdin.on("readable", () => {
console.log(process.stdin.read());
});
process.stdin.on("end", () => {
console.log("end");
});

View file

@ -0,0 +1,2 @@
foo
bar

View file

@ -841,14 +841,7 @@ impl JsRuntime {
)
.await?;
let receiver = runtime.mod_evaluate(id);
poll_fn(|cx| {
let r = runtime.poll_event_loop(cx, false);
// TODO(bartlomieju): some code in readable-stream polyfill in `ext/node`
// is calling `nextTick()` during snapshotting, which causes infinite loop
runtime.state.borrow_mut().has_tick_scheduled = false;
r
})
.await?;
runtime.run_event_loop(false).await?;
receiver.await?
})
.with_context(|| format!("Couldn't execute '{}'", file_source.specifier))

View file

@ -110,7 +110,7 @@ function initialize(nodeModules, nodeGlobalThisName) {
value: nodeGlobalThis,
});
// FIXME(bartlomieju): not nice to depend on `Deno` namespace here
internals.__bootstrapNodeProcess(Deno.args);
internals.__bootstrapNodeProcess(Deno.args, Deno.version);
}
internals.node = {

View file

@ -11,6 +11,11 @@ interface Tock {
args: Array<unknown>;
}
let nextTickEnabled = false;
export function enableNextTick() {
nextTickEnabled = true;
}
const queue = new FixedQueue();
export function processTicksAndRejections() {
@ -71,8 +76,6 @@ export function runNextTicks() {
// return;
if (!core.hasTickScheduled()) {
core.runMicrotasks();
}
if (!core.hasTickScheduled()) {
return true;
}
@ -93,6 +96,12 @@ export function nextTick<T extends Array<unknown>>(
callback: (...args: T) => void,
...args: T
) {
// If we're snapshotting we don't want to push nextTick to be run. We'll
// enable next ticks in "__bootstrapNodeProcess()";
if (!nextTickEnabled) {
return;
}
validateFunction(callback, "callback");
if (_exiting) {

View file

@ -126,5 +126,8 @@ export const versions = {
unicode: "14.0",
ngtcp2: "0.8.1",
nghttp3: "0.7.0",
...Deno.version,
// Will be filled when calling "__bootstrapNodeProcess()",
deno: "",
v8: "",
typescript: "",
};

View file

@ -9,13 +9,12 @@ import {
moveCursor,
} from "internal:deno_node/polyfills/internal/readline/callbacks.mjs";
import { Duplex, Readable, Writable } from "internal:deno_node/polyfills/stream.ts";
import { stdio } from "internal:deno_node/polyfills/_process/stdio.mjs";
import { isWindows } from "internal:deno_node/polyfills/_util/os.ts";
import { fs as fsConstants } from "internal:deno_node/polyfills/internal_binding/constants.ts";
import * as files from "internal:runtime/js/40_files.js";
// https://github.com/nodejs/node/blob/00738314828074243c9a52a228ab4c68b04259ef/lib/internal/bootstrap/switches/is_main_thread.js#L41
function createWritableStdioStream(writer, name) {
export function createWritableStdioStream(writer, name) {
const stream = new Writable({
write(buf, enc, cb) {
if (!writer) {
@ -92,18 +91,6 @@ function createWritableStdioStream(writer, name) {
return stream;
}
/** https://nodejs.org/api/process.html#process_process_stderr */
export const stderr = stdio.stderr = createWritableStdioStream(
files.stderr,
"stderr",
);
/** https://nodejs.org/api/process.html#process_process_stdout */
export const stdout = stdio.stdout = createWritableStdioStream(
files.stdout,
"stdout",
);
// TODO(PolarETech): This function should be replaced by
// `guessHandleType()` in "../internal_binding/util.ts".
// https://github.com/nodejs/node/blob/v18.12.1/src/node_util.cc#L257
@ -162,9 +149,10 @@ const _read = function (size) {
/** https://nodejs.org/api/process.html#process_process_stdin */
// https://github.com/nodejs/node/blob/v18.12.1/lib/internal/bootstrap/switches/is_main_thread.js#L189
export const stdin = stdio.stdin = (() => {
/** Create process.stdin */
export const initStdin = () => {
const fd = files.stdin?.rid;
let _stdin;
let stdin;
const stdinType = _guessStdinType(fd);
switch (stdinType) {
@ -173,7 +161,7 @@ export const stdin = stdio.stdin = (() => {
// use `Readable` instead.
// https://github.com/nodejs/node/blob/v18.12.1/lib/internal/bootstrap/switches/is_main_thread.js#L200
// https://github.com/nodejs/node/blob/v18.12.1/lib/internal/fs/streams.js#L148
_stdin = new Readable({
stdin = new Readable({
highWaterMark: 64 * 1024,
autoDestroy: false,
read: _read,
@ -197,7 +185,7 @@ export const stdin = stdio.stdin = (() => {
// 2. Creating a net.Socket() from a fd is not currently supported.
// https://github.com/nodejs/node/blob/v18.12.1/lib/internal/bootstrap/switches/is_main_thread.js#L206
// https://github.com/nodejs/node/blob/v18.12.1/lib/net.js#L329
_stdin = new Duplex({
stdin = new Duplex({
readable: stdinType === "TTY" ? undefined : true,
writable: stdinType === "TTY" ? undefined : false,
readableHighWaterMark: stdinType === "TTY" ? 0 : undefined,
@ -210,39 +198,41 @@ export const stdin = stdio.stdin = (() => {
if (stdinType !== "TTY") {
// Make sure the stdin can't be `.end()`-ed
_stdin._writableState.ended = true;
stdin._writableState.ended = true;
}
break;
}
default: {
// Provide a dummy contentless input for e.g. non-console
// Windows applications.
_stdin = new Readable({ read() {} });
_stdin.push(null);
stdin = new Readable({ read() {} });
stdin.push(null);
}
}
return _stdin;
})();
stdin.on("close", () => files.stdin?.close());
stdin.fd = files.stdin?.rid ?? -1;
Object.defineProperty(stdin, "isTTY", {
enumerable: true,
configurable: true,
get() {
return Deno.isatty?.(Deno.stdin.rid);
},
});
stdin._isRawMode = false;
stdin.setRawMode = (enable) => {
files.stdin?.setRaw?.(enable);
stdin._isRawMode = enable;
stdin.on("close", () => files.stdin?.close());
stdin.fd = files.stdin?.rid ?? -1;
Object.defineProperty(stdin, "isTTY", {
enumerable: true,
configurable: true,
get() {
return Deno.isatty?.(Deno.stdin.rid);
},
});
stdin._isRawMode = false;
stdin.setRawMode = (enable) => {
files.stdin?.setRaw?.(enable);
stdin._isRawMode = enable;
return stdin;
};
Object.defineProperty(stdin, "isRaw", {
enumerable: true,
configurable: true,
get() {
return stdin._isRawMode;
},
});
return stdin;
};
Object.defineProperty(stdin, "isRaw", {
enumerable: true,
configurable: true,
get() {
return stdin._isRawMode;
},
});

View file

@ -33,7 +33,7 @@ import promises from "internal:deno_node/polyfills/readline/promises.ts";
import { validateAbortSignal } from "internal:deno_node/polyfills/internal/validators.mjs";
import { promisify } from "internal:deno_node/polyfills/internal/util.mjs";
import { AbortError } from "internal:deno_node/polyfills/internal/errors.ts";
import { process } from "internal:deno_node/polyfills/process.ts";
import process from "internal:deno_node/polyfills/process.ts";
import {
Interface as _Interface,

View file

@ -40,7 +40,7 @@ import {
promisify,
} from "internal:deno_node/polyfills/util.ts";
import { createDeferredPromise } from "internal:deno_node/polyfills/internal/util.mjs";
import { process } from "internal:deno_node/polyfills/process.ts";
import process from "internal:deno_node/polyfills/process.ts";
import { Buffer } from "internal:deno_node/polyfills/buffer.ts";
import {
convertToValidSignal,

View file

@ -29,15 +29,17 @@ import {
import { _exiting } from "internal:deno_node/polyfills/_process/exiting.ts";
export { _nextTick as nextTick, chdir, cwd, env, version, versions };
import {
stderr as stderr_,
stdin as stdin_,
stdout as stdout_,
createWritableStdioStream,
initStdin,
} from "internal:deno_node/polyfills/_process/streams.mjs";
import { stdio } from "internal:deno_node/polyfills/_process/stdio.mjs";
import {
enableNextTick,
processTicksAndRejections,
runNextTicks,
} from "internal:deno_node/polyfills/_next_tick.ts";
import { isWindows } from "internal:deno_node/polyfills/_util/os.ts";
import * as files from "internal:runtime/js/40_files.js";
// TODO(kt3k): This should be set at start up time
export let arch = "";
@ -50,11 +52,11 @@ export let pid = 0;
// TODO(kt3k): Give better types to stdio objects
// deno-lint-ignore no-explicit-any
const stderr = stderr_ as any;
let stderr = null as any;
// deno-lint-ignore no-explicit-any
const stdin = stdin_ as any;
let stdin = null as any;
// deno-lint-ignore no-explicit-any
const stdout = stdout_ as any;
let stdout = null as any;
export { stderr, stdin, stdout };
import { getBinding } from "internal:deno_node/polyfills/internal_binding/mod.ts";
@ -663,13 +665,10 @@ class Process extends EventEmitter {
noDeprecation = false;
}
// TODO(kt3k): Do the below at start up time.
/*
if (Deno.build.os === "windows") {
if (isWindows) {
delete Process.prototype.getgid;
delete Process.prototype.getuid;
}
*/
/** https://nodejs.org/api/process.html#process_process */
const process = new Process();
@ -689,13 +688,21 @@ export const removeAllListeners = process.removeAllListeners;
// Should be called only once, in `runtime/js/99_main.js` when the runtime is
// bootstrapped.
internals.__bootstrapNodeProcess = function (args: string[]) {
internals.__bootstrapNodeProcess = function (
args: string[],
denoVersions: Record<string, string>,
) {
for (let i = 0; i < args.length; i++) {
argv[i + 2] = args[i];
}
for (const [key, value] of Object.entries(denoVersions)) {
versions[key] = value;
}
core.setNextTickCallback(processTicksAndRejections);
core.setMacrotaskCallback(runNextTicks);
enableNextTick();
// TODO(bartlomieju): this is buggy, see https://github.com/denoland/deno/issues/16928
// We should use a specialized API in 99_main.js instead
@ -740,12 +747,22 @@ internals.__bootstrapNodeProcess = function (args: string[]) {
}
});
// Initializes stdin
stdin = stdio.stdin = process.stdin = initStdin();
/** https://nodejs.org/api/process.html#process_process_stderr */
stderr = stdio.stderr = process.stderr = createWritableStdioStream(
files.stderr,
"stderr",
);
/** https://nodejs.org/api/process.html#process_process_stdout */
stdout = stdio.stdout = process.stdout = createWritableStdioStream(
files.stdout,
"stdout",
);
delete internals.__bootstrapNodeProcess;
};
export default process;
//TODO(Soremwar)
//Remove on 1.0
//Kept for backwards compatibility with std
export { process };

View file

@ -7,9 +7,10 @@ import {
import { validateFunction } from "internal:deno_node/polyfills/internal/validators.mjs";
import { promisify } from "internal:deno_node/polyfills/internal/util.mjs";
export { setUnrefTimeout } from "internal:deno_node/polyfills/internal/timers.mjs";
import * as timers from "internal:deno_web/02_timers.js";
const clearTimeout_ = globalThis.clearTimeout;
const clearInterval_ = globalThis.clearInterval;
const clearTimeout_ = timers.clearTimeout;
const clearInterval_ = timers.clearInterval;
export function setTimeout(
callback: (...args: unknown[]) => void,

View file

@ -515,11 +515,6 @@ function bootstrapMainRuntime(runtimeOptions) {
ObjectDefineProperty(globalThis, "Deno", util.readOnly(finalDenoNs));
util.log("args", runtimeOptions.args);
// FIXME(bartlomieju): this should be a helper function that is placed in
// "internals" namespace
// Initialize Node polyfills
// internals.__bootstrapNodeProcess();
}
function bootstrapWorkerRuntime(

View file

@ -29,6 +29,7 @@ export async function checkCopyright() {
":!:cli/tsc/compiler.d.ts",
":!:test_util/wpt/**",
":!:cli/tools/init/templates/**",
":!:cli/tests/unit_node/testdata/**",
// rust
"*.rs",