diff options
-rw-r--r-- | cli/js/globals.ts | 8 | ||||
-rw-r--r-- | cli/js/lib.deno.window.d.ts | 2 | ||||
-rw-r--r-- | cli/js/runtime_main.ts | 27 | ||||
-rw-r--r-- | cli/tests/058_tasks_microtasks_close.ts | 18 | ||||
-rw-r--r-- | cli/tests/058_tasks_microtasks_close.ts.out | 6 | ||||
-rw-r--r-- | cli/tests/integration_tests.rs | 5 |
6 files changed, 65 insertions, 1 deletions
diff --git a/cli/js/globals.ts b/cli/js/globals.ts index ada491bde..d71a96d39 100644 --- a/cli/js/globals.ts +++ b/cli/js/globals.ts @@ -179,6 +179,14 @@ export function readOnly(value: unknown): PropertyDescriptor { }; } +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function getterOnly(getter: () => any): PropertyDescriptor { + return { + get: getter, + enumerable: true + }; +} + // https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope export const windowOrWorkerGlobalScopeMethods = { atob: writable(textEncoding.atob), diff --git a/cli/js/lib.deno.window.d.ts b/cli/js/lib.deno.window.d.ts index 737971d94..e4ab6b70d 100644 --- a/cli/js/lib.deno.window.d.ts +++ b/cli/js/lib.deno.window.d.ts @@ -13,6 +13,8 @@ declare interface Window extends WindowOrWorkerGlobalScope { onload: Function | undefined; onunload: Function | undefined; crypto: Crypto; + close: () => void; + closed: boolean; Deno: typeof Deno; } diff --git a/cli/js/runtime_main.ts b/cli/js/runtime_main.ts index a59e7513b..4c506e0ce 100644 --- a/cli/js/runtime_main.ts +++ b/cli/js/runtime_main.ts @@ -10,8 +10,10 @@ import * as Deno from "./deno.ts"; import * as domTypes from "./web/dom_types.ts"; import * as csprng from "./ops/get_random_values.ts"; +import { exit } from "./ops/os.ts"; import { readOnly, + getterOnly, writable, windowOrWorkerGlobalScopeMethods, windowOrWorkerGlobalScopeProperties, @@ -21,6 +23,7 @@ import { internalObject } from "./internals.ts"; import { setSignals } from "./signals.ts"; import { replLoop } from "./repl.ts"; import { LocationImpl } from "./web/location.ts"; +import { setTimeout } from "./web/timers.ts"; import * as runtime from "./runtime.ts"; import { symbols } from "./symbols.ts"; import { log, immutableDefine } from "./util.ts"; @@ -31,6 +34,26 @@ import { log, immutableDefine } from "./util.ts"; // @ts-ignore Deno[symbols.internal] = internalObject; +let windowIsClosing = false; + +function windowClose(): void { + if (!windowIsClosing) { + windowIsClosing = true; + // Push a macrotask to exit after a promise resolve. + // This is not perfect, but should be fine for first pass. + Promise.resolve().then(() => + setTimeout.call( + null, + () => { + // This should be fine, since only Window/MainWorker has .close() + exit(0); + }, + 0 + ) + ); + } +} + export const mainRuntimeGlobalProperties = { window: readOnly(globalThis), self: readOnly(globalThis), @@ -38,7 +61,9 @@ export const mainRuntimeGlobalProperties = { // TODO(bartlomieju): from MDN docs (https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope) // it seems those two properties should be availble to workers as well onload: writable(undefined), - onunload: writable(undefined) + onunload: writable(undefined), + close: writable(windowClose), + closed: getterOnly(() => windowIsClosing) }; let hasBootstrapped = false; diff --git a/cli/tests/058_tasks_microtasks_close.ts b/cli/tests/058_tasks_microtasks_close.ts new file mode 100644 index 000000000..11de55a38 --- /dev/null +++ b/cli/tests/058_tasks_microtasks_close.ts @@ -0,0 +1,18 @@ +console.log("sync 1"); +setTimeout(() => { + console.log("setTimeout 1"); + Promise.resolve().then(() => { + console.log("Promise resolve in setTimeout 1"); + }); +}); +Promise.resolve().then(() => { + console.log("promise 1"); +}); +window.close(); +console.log("sync 2"); +setTimeout(() => { + console.log("setTimeout 2"); +}); +setTimeout(() => { + console.log("setTimeout 3"); +}, 100); diff --git a/cli/tests/058_tasks_microtasks_close.ts.out b/cli/tests/058_tasks_microtasks_close.ts.out new file mode 100644 index 000000000..218273cab --- /dev/null +++ b/cli/tests/058_tasks_microtasks_close.ts.out @@ -0,0 +1,6 @@ +sync 1 +sync 2 +promise 1 +setTimeout 1 +Promise resolve in setTimeout 1 +setTimeout 2 diff --git a/cli/tests/integration_tests.rs b/cli/tests/integration_tests.rs index 02c46840e..f8651869b 100644 --- a/cli/tests/integration_tests.rs +++ b/cli/tests/integration_tests.rs @@ -1078,6 +1078,11 @@ itest!(_057_revoke_permissions { output: "057_revoke_permissions.out", }); +itest!(_058_tasks_microtasks_close { + args: "run 058_tasks_microtasks_close.ts", + output: "058_tasks_microtasks_close.ts.out", +}); + itest!(js_import_detect { args: "run --reload js_import_detect.ts", output: "js_import_detect.ts.out", |