summaryrefslogtreecommitdiff
path: root/runtime/js
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2022-11-21 14:36:26 +0100
committerGitHub <noreply@github.com>2022-11-21 14:36:26 +0100
commitd2327469284327c5ec9bbf72d5d16b9b9f8135d6 (patch)
tree598c7dde3ba436b27abf2f6be0c7a9770637e352 /runtime/js
parentfedeea6dde91874774f5a9eb518635427a88e86c (diff)
feat(core): Ability to create snapshots from existing snapshots (#16597)
Co-authored-by: crowlkats <crowlkats@toaxl.com>
Diffstat (limited to 'runtime/js')
-rw-r--r--runtime/js/40_testing.js1408
-rw-r--r--runtime/js/90_deno_ns.js2
-rw-r--r--runtime/js/98_global_scope.js352
-rw-r--r--runtime/js/99_main.js343
4 files changed, 377 insertions, 1728 deletions
diff --git a/runtime/js/40_testing.js b/runtime/js/40_testing.js
deleted file mode 100644
index e8590faf1..000000000
--- a/runtime/js/40_testing.js
+++ /dev/null
@@ -1,1408 +0,0 @@
-// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
-"use strict";
-
-((window) => {
- const core = window.Deno.core;
- const ops = core.ops;
- const { setExitHandler } = window.__bootstrap.os;
- const { Console } = window.__bootstrap.console;
- const { serializePermissions } = window.__bootstrap.permissions;
- const { assert } = window.__bootstrap.infra;
- const {
- ArrayFrom,
- ArrayPrototypeFilter,
- ArrayPrototypeJoin,
- ArrayPrototypeMap,
- ArrayPrototypePush,
- ArrayPrototypeShift,
- ArrayPrototypeSort,
- BigInt,
- DateNow,
- Error,
- FunctionPrototype,
- Map,
- MapPrototypeGet,
- MapPrototypeHas,
- MapPrototypeSet,
- MathCeil,
- ObjectKeys,
- ObjectPrototypeIsPrototypeOf,
- Promise,
- SafeArrayIterator,
- Set,
- SymbolToStringTag,
- TypeError,
- } = window.__bootstrap.primordials;
-
- const opSanitizerDelayResolveQueue = [];
-
- // Even if every resource is closed by the end of a test, there can be a delay
- // until the pending ops have all finished. This function returns a promise
- // that resolves when it's (probably) fine to run the op sanitizer.
- //
- // This is implemented by adding a macrotask callback that runs after the
- // timer macrotasks, so we can guarantee that a currently running interval
- // will have an associated op. An additional `setTimeout` of 0 is needed
- // before that, though, in order to give time for worker message ops to finish
- // (since timeouts of 0 don't queue tasks in the timer queue immediately).
- function opSanitizerDelay() {
- return new Promise((resolve) => {
- setTimeout(() => {
- ArrayPrototypePush(opSanitizerDelayResolveQueue, resolve);
- }, 0);
- });
- }
-
- function handleOpSanitizerDelayMacrotask() {
- ArrayPrototypeShift(opSanitizerDelayResolveQueue)?.();
- return opSanitizerDelayResolveQueue.length === 0;
- }
-
- // An async operation to $0 was started in this test, but never completed. This is often caused by not $1.
- // An async operation to $0 was started in this test, but never completed. Async operations should not complete in a test if they were not started in that test.
- // deno-fmt-ignore
- const OP_DETAILS = {
- "op_blob_read_part": ["read from a Blob or File", "awaiting the result of a Blob or File read"],
- "op_broadcast_recv": ["receive a message from a BroadcastChannel", "closing the BroadcastChannel"],
- "op_broadcast_send": ["send a message to a BroadcastChannel", "closing the BroadcastChannel"],
- "op_chmod_async": ["change the permissions of a file", "awaiting the result of a `Deno.chmod` call"],
- "op_chown_async": ["change the owner of a file", "awaiting the result of a `Deno.chown` call"],
- "op_copy_file_async": ["copy a file", "awaiting the result of a `Deno.copyFile` call"],
- "op_crypto_decrypt": ["decrypt data", "awaiting the result of a `crypto.subtle.decrypt` call"],
- "op_crypto_derive_bits": ["derive bits from a key", "awaiting the result of a `crypto.subtle.deriveBits` call"],
- "op_crypto_encrypt": ["encrypt data", "awaiting the result of a `crypto.subtle.encrypt` call"],
- "op_crypto_generate_key": ["generate a key", "awaiting the result of a `crypto.subtle.generateKey` call"],
- "op_crypto_sign_key": ["sign data", "awaiting the result of a `crypto.subtle.sign` call"],
- "op_crypto_subtle_digest": ["digest data", "awaiting the result of a `crypto.subtle.digest` call"],
- "op_crypto_verify_key": ["verify data", "awaiting the result of a `crypto.subtle.verify` call"],
- "op_net_recv_udp": ["receive a datagram message via UDP", "awaiting the result of `Deno.DatagramConn#receive` call, or not breaking out of a for await loop looping over a `Deno.DatagramConn`"],
- "op_net_recv_unixpacket": ["receive a datagram message via Unixpacket", "awaiting the result of `Deno.DatagramConn#receive` call, or not breaking out of a for await loop looping over a `Deno.DatagramConn`"],
- "op_net_send_udp": ["send a datagram message via UDP", "awaiting the result of `Deno.DatagramConn#send` call"],
- "op_net_send_unixpacket": ["send a datagram message via Unixpacket", "awaiting the result of `Deno.DatagramConn#send` call"],
- "op_dns_resolve": ["resolve a DNS name", "awaiting the result of a `Deno.resolveDns` call"],
- "op_fdatasync_async": ["flush pending data operations for a file to disk", "awaiting the result of a `Deno.fdatasync` call"],
- "op_fetch_send": ["send a HTTP request", "awaiting the result of a `fetch` call"],
- "op_ffi_call_nonblocking": ["do a non blocking ffi call", "awaiting the returned promise"] ,
- "op_ffi_call_ptr_nonblocking": ["do a non blocking ffi call", "awaiting the returned promise"],
- "op_flock_async": ["lock a file", "awaiting the result of a `Deno.flock` call"],
- "op_fs_events_poll": ["get the next file system event", "breaking out of a for await loop looping over `Deno.FsEvents`"],
- "op_fstat_async": ["get file metadata", "awaiting the result of a `Deno.File#fstat` call"],
- "op_fsync_async": ["flush pending data operations for a file to disk", "awaiting the result of a `Deno.fsync` call"],
- "op_ftruncate_async": ["truncate a file", "awaiting the result of a `Deno.ftruncate` call"],
- "op_funlock_async": ["unlock a file", "awaiting the result of a `Deno.funlock` call"],
- "op_futime_async": ["change file timestamps", "awaiting the result of a `Deno.futime` call"],
- "op_http_accept": ["accept a HTTP request", "closing a `Deno.HttpConn`"],
- "op_http_shutdown": ["shutdown a HTTP connection", "awaiting `Deno.HttpEvent#respondWith`"],
- "op_http_upgrade_websocket": ["upgrade a HTTP connection to a WebSocket", "awaiting `Deno.HttpEvent#respondWith`"],
- "op_http_write_headers": ["write HTTP response headers", "awaiting `Deno.HttpEvent#respondWith`"],
- "op_http_write": ["write HTTP response body", "awaiting `Deno.HttpEvent#respondWith`"],
- "op_link_async": ["create a hard link", "awaiting the result of a `Deno.link` call"],
- "op_make_temp_dir_async": ["create a temporary directory", "awaiting the result of a `Deno.makeTempDir` call"],
- "op_make_temp_file_async": ["create a temporary file", "awaiting the result of a `Deno.makeTempFile` call"],
- "op_message_port_recv_message": ["receive a message from a MessagePort", "awaiting the result of not closing a `MessagePort`"],
- "op_mkdir_async": ["create a directory", "awaiting the result of a `Deno.mkdir` call"],
- "op_net_accept_tcp": ["accept a TCP stream", "closing a `Deno.Listener`"],
- "op_net_accept_unix": ["accept a Unix stream", "closing a `Deno.Listener`"],
- "op_net_connect_tcp": ["connect to a TCP server", "awaiting a `Deno.connect` call"],
- "op_net_connect_unix": ["connect to a Unix server", "awaiting a `Deno.connect` call"],
- "op_open_async": ["open a file", "awaiting the result of a `Deno.open` call"],
- "op_read_dir_async": ["read a directory", "collecting all items in the async iterable returned from a `Deno.readDir` call"],
- "op_read_link_async": ["read a symlink", "awaiting the result of a `Deno.readLink` call"],
- "op_realpath_async": ["resolve a path", "awaiting the result of a `Deno.realpath` call"],
- "op_remove_async": ["remove a file or directory", "awaiting the result of a `Deno.remove` call"],
- "op_rename_async": ["rename a file or directory", "awaiting the result of a `Deno.rename` call"],
- "op_run_status": ["get the status of a subprocess", "awaiting the result of a `Deno.Process#status` call"],
- "op_seek_async": ["seek in a file", "awaiting the result of a `Deno.File#seek` call"],
- "op_signal_poll": ["get the next signal", "un-registering a OS signal handler"],
- "op_sleep": ["sleep for a duration", "cancelling a `setTimeout` or `setInterval` call"],
- "op_stat_async": ["get file metadata", "awaiting the result of a `Deno.stat` call"],
- "op_symlink_async": ["create a symlink", "awaiting the result of a `Deno.symlink` call"],
- "op_net_accept_tls": ["accept a TLS stream", "closing a `Deno.TlsListener`"],
- "op_net_connect_tls": ["connect to a TLS server", "awaiting a `Deno.connectTls` call"],
- "op_tls_handshake": ["perform a TLS handshake", "awaiting a `Deno.TlsConn#handshake` call"],
- "op_tls_start": ["start a TLS connection", "awaiting a `Deno.startTls` call"],
- "op_truncate_async": ["truncate a file", "awaiting the result of a `Deno.truncate` call"],
- "op_utime_async": ["change file timestamps", "awaiting the result of a `Deno.utime` call"],
- "op_webgpu_buffer_get_map_async": ["map a WebGPU buffer", "awaiting the result of a `GPUBuffer#mapAsync` call"],
- "op_webgpu_request_adapter": ["request a WebGPU adapter", "awaiting the result of a `navigator.gpu.requestAdapter` call"],
- "op_webgpu_request_device": ["request a WebGPU device", "awaiting the result of a `GPUAdapter#requestDevice` call"],
- "op_worker_recv_message": ["receive a message from a web worker", "terminating a `Worker`"],
- "op_ws_close": ["close a WebSocket", "awaiting until the `close` event is emitted on a `WebSocket`, or the `WebSocketStream#closed` promise resolves"],
- "op_ws_create": ["create a WebSocket", "awaiting until the `open` event is emitted on a `WebSocket`, or the result of a `WebSocketStream#connection` promise"],
- "op_ws_next_event": ["receive the next message on a WebSocket", "closing a `WebSocket` or `WebSocketStream`"],
- "op_ws_send": ["send a message on a WebSocket", "closing a `WebSocket` or `WebSocketStream`"],
- };
-
- // Wrap test function in additional assertion that makes sure
- // the test case does not leak async "ops" - ie. number of async
- // completed ops after the test is the same as number of dispatched
- // ops. Note that "unref" ops are ignored since in nature that are
- // optional.
- function assertOps(fn) {
- /** @param desc {TestDescription | TestStepDescription} */
- return async function asyncOpSanitizer(desc) {
- const pre = core.metrics();
- const preTraces = new Map(core.opCallTraces);
- try {
- await fn(desc);
- } finally {
- // Defer until next event loop turn - that way timeouts and intervals
- // cleared can actually be removed from resource table, otherwise
- // false positives may occur (https://github.com/denoland/deno/issues/4591)
- await opSanitizerDelay();
- await opSanitizerDelay();
- }
-
- if (shouldSkipSanitizers(desc)) return;
-
- const post = core.metrics();
- const postTraces = new Map(core.opCallTraces);
-
- // We're checking diff because one might spawn HTTP server in the background
- // that will be a pending async op before test starts.
- const dispatchedDiff = post.opsDispatchedAsync - pre.opsDispatchedAsync;
- const completedDiff = post.opsCompletedAsync - pre.opsCompletedAsync;
-
- if (dispatchedDiff === completedDiff) return;
-
- const details = [];
- for (const key in post.ops) {
- const preOp = pre.ops[key] ??
- { opsDispatchedAsync: 0, opsCompletedAsync: 0 };
- const postOp = post.ops[key];
- const dispatchedDiff = postOp.opsDispatchedAsync -
- preOp.opsDispatchedAsync;
- const completedDiff = postOp.opsCompletedAsync -
- preOp.opsCompletedAsync;
-
- if (dispatchedDiff > completedDiff) {
- const [name, hint] = OP_DETAILS[key] || [key, null];
- const count = dispatchedDiff - completedDiff;
- let message = `${count} async operation${
- count === 1 ? "" : "s"
- } to ${name} ${
- count === 1 ? "was" : "were"
- } started in this test, but never completed.`;
- if (hint) {
- message += ` This is often caused by not ${hint}.`;
- }
- const traces = [];
- for (const [id, { opName, stack }] of postTraces) {
- if (opName !== key) continue;
- if (MapPrototypeHas(preTraces, id)) continue;
- ArrayPrototypePush(traces, stack);
- }
- if (traces.length === 1) {
- message += " The operation was started here:\n";
- message += traces[0];
- } else if (traces.length > 1) {
- message += " The operations were started here:\n";
- message += ArrayPrototypeJoin(traces, "\n\n");
- }
- ArrayPrototypePush(details, message);
- } else if (dispatchedDiff < completedDiff) {
- const [name, hint] = OP_DETAILS[key] || [key, null];
- const count = completedDiff - dispatchedDiff;
- ArrayPrototypePush(
- details,
- `${count} async operation${count === 1 ? "" : "s"} to ${name} ${
- count === 1 ? "was" : "were"
- } started before this test, but ${
- count === 1 ? "was" : "were"
- } completed during the test. Async operations should not complete in a test if they were not started in that test.
- ${hint ? `This is often caused by not ${hint}.` : ""}`,
- );
- }
- }
-
- let msg = `Test case is leaking async ops.
-
- - ${ArrayPrototypeJoin(details, "\n - ")}`;
-
- if (!core.isOpCallTracingEnabled()) {
- msg +=
- `\n\nTo get more details where ops were leaked, run again with --trace-ops flag.`;
- } else {
- msg += "\n";
- }
-
- throw assert(false, msg);
- };
- }
-
- function prettyResourceNames(name) {
- switch (name) {
- case "fsFile":
- return ["A file", "opened", "closed"];
- case "fetchRequest":
- return ["A fetch request", "started", "finished"];
- case "fetchRequestBody":
- return ["A fetch request body", "created", "closed"];
- case "fetchResponseBody":
- return ["A fetch response body", "created", "consumed"];
- case "httpClient":
- return ["An HTTP client", "created", "closed"];
- case "dynamicLibrary":
- return ["A dynamic library", "loaded", "unloaded"];
- case "httpConn":
- return ["An inbound HTTP connection", "accepted", "closed"];
- case "httpStream":
- return ["An inbound HTTP request", "accepted", "closed"];
- case "tcpStream":
- return ["A TCP connection", "opened/accepted", "closed"];
- case "unixStream":
- return ["A Unix connection", "opened/accepted", "closed"];
- case "tlsStream":
- return ["A TLS connection", "opened/accepted", "closed"];
- case "tlsListener":
- return ["A TLS listener", "opened", "closed"];
- case "unixListener":
- return ["A Unix listener", "opened", "closed"];
- case "unixDatagram":
- return ["A Unix datagram", "opened", "closed"];
- case "tcpListener":
- return ["A TCP listener", "opened", "closed"];
- case "udpSocket":
- return ["A UDP socket", "opened", "closed"];
- case "timer":
- return ["A timer", "started", "fired/cleared"];
- case "textDecoder":
- return ["A text decoder", "created", "finished"];
- case "messagePort":
- return ["A message port", "created", "closed"];
- case "webSocketStream":
- return ["A WebSocket", "opened", "closed"];
- case "fsEvents":
- return ["A file system watcher", "created", "closed"];
- case "childStdin":
- return ["A child process stdin", "opened", "closed"];
- case "childStdout":
- return ["A child process stdout", "opened", "closed"];
- case "childStderr":
- return ["A child process stderr", "opened", "closed"];
- case "child":
- return ["A child process", "started", "closed"];
- case "signal":
- return ["A signal listener", "created", "fired/cleared"];
- case "stdin":
- return ["The stdin pipe", "opened", "closed"];
- case "stdout":
- return ["The stdout pipe", "opened", "closed"];
- case "stderr":
- return ["The stderr pipe", "opened", "closed"];
- case "compression":
- return ["A CompressionStream", "created", "closed"];
- default:
- return [`A "${name}" resource`, "created", "cleaned up"];
- }
- }
-
- function resourceCloseHint(name) {
- switch (name) {
- case "fsFile":
- return "Close the file handle by calling `file.close()`.";
- case "fetchRequest":
- return "Await the promise returned from `fetch()` or abort the fetch with an abort signal.";
- case "fetchRequestBody":
- return "Terminate the request body `ReadableStream` by closing or erroring it.";
- case "fetchResponseBody":
- return "Consume or close the response body `ReadableStream`, e.g `await resp.text()` or `await resp.body.cancel()`.";
- case "httpClient":
- return "Close the HTTP client by calling `httpClient.close()`.";
- case "dynamicLibrary":
- return "Unload the dynamic library by calling `dynamicLibrary.close()`.";
- case "httpConn":
- return "Close the inbound HTTP connection by calling `httpConn.close()`.";
- case "httpStream":
- return "Close the inbound HTTP request by responding with `e.respondWith().` or closing the HTTP connection.";
- case "tcpStream":
- return "Close the TCP connection by calling `tcpConn.close()`.";
- case "unixStream":
- return "Close the Unix socket connection by calling `unixConn.close()`.";
- case "tlsStream":
- return "Close the TLS connection by calling `tlsConn.close()`.";
- case "tlsListener":
- return "Close the TLS listener by calling `tlsListener.close()`.";
- case "unixListener":
- return "Close the Unix socket listener by calling `unixListener.close()`.";
- case "unixDatagram":
- return "Close the Unix datagram socket by calling `unixDatagram.close()`.";
- case "tcpListener":
- return "Close the TCP listener by calling `tcpListener.close()`.";
- case "udpSocket":
- return "Close the UDP socket by calling `udpSocket.close()`.";
- case "timer":
- return "Clear the timer by calling `clearInterval` or `clearTimeout`.";
- case "textDecoder":
- return "Close the text decoder by calling `textDecoder.decode('')` or `await textDecoderStream.readable.cancel()`.";
- case "messagePort":
- return "Close the message port by calling `messagePort.close()`.";
- case "webSocketStream":
- return "Close the WebSocket by calling `webSocket.close()`.";
- case "fsEvents":
- return "Close the file system watcher by calling `watcher.close()`.";
- case "childStdin":
- return "Close the child process stdin by calling `proc.stdin.close()`.";
- case "childStdout":
- return "Close the child process stdout by calling `proc.stdout.close()`.";
- case "childStderr":
- return "Close the child process stderr by calling `proc.stderr.close()`.";
- case "child":
- return "Close the child process by calling `proc.kill()` or `proc.close()`.";
- case "signal":
- return "Clear the signal listener by calling `Deno.removeSignalListener`.";
- case "stdin":
- return "Close the stdin pipe by calling `Deno.stdin.close()`.";
- case "stdout":
- return "Close the stdout pipe by calling `Deno.stdout.close()`.";
- case "stderr":
- return "Close the stderr pipe by calling `Deno.stderr.close()`.";
- case "compression":
- return "Close the compression stream by calling `await stream.writable.close()`.";
- default:
- return "Close the resource before the end of the test.";
- }
- }
-
- // Wrap test function in additional assertion that makes sure
- // the test case does not "leak" resources - ie. resource table after
- // the test has exactly the same contents as before the test.
- function assertResources(fn) {
- /** @param desc {TestDescription | TestStepDescription} */
- return async function resourceSanitizer(desc) {
- const pre = core.resources();
- await fn(desc);
-
- if (shouldSkipSanitizers(desc)) {
- return;
- }
-
- const post = core.resources();
-
- const allResources = new Set([
- ...new SafeArrayIterator(ObjectKeys(pre)),
- ...new SafeArrayIterator(ObjectKeys(post)),
- ]);
-
- const details = [];
- for (const resource of allResources) {
- const preResource = pre[resource];
- const postResource = post[resource];
- if (preResource === postResource) continue;
-
- if (preResource === undefined) {
- const [name, action1, action2] = prettyResourceNames(postResource);
- const hint = resourceCloseHint(postResource);
- const detail =
- `${name} (rid ${resource}) was ${action1} during the test, but not ${action2} during the test. ${hint}`;
- ArrayPrototypePush(details, detail);
- } else {
- const [name, action1, action2] = prettyResourceNames(preResource);
- const detail =
- `${name} (rid ${resource}) was ${action1} before the test started, but was ${action2} during the test. Do not close resources in a test that were not created during that test.`;
- ArrayPrototypePush(details, detail);
- }
- }
-
- const message = `Test case is leaking ${details.length} resource${
- details.length === 1 ? "" : "s"
- }:
-
- - ${details.join("\n - ")}
-`;
- assert(details.length === 0, message);
- };
- }
-
- // Wrap test function in additional assertion that makes sure
- // that the test case does not accidentally exit prematurely.
- function assertExit(fn, isTest) {
- return async function exitSanitizer(...params) {
- setExitHandler((exitCode) => {
- assert(
- false,
- `${
- isTest ? "Test case" : "Bench"
- } attempted to exit with exit code: ${exitCode}`,
- );
- });
-
- try {
- await fn(...new SafeArrayIterator(params));
- } catch (err) {
- throw err;
- } finally {
- setExitHandler(null);
- }
- };
- }
-
- function assertTestStepScopes(fn) {
- /** @param desc {TestDescription | TestStepDescription} */
- return async function testStepSanitizer(desc) {
- preValidation();
- // only report waiting after pre-validation
- if (canStreamReporting(desc) && "parent" in desc) {
- stepReportWait(desc);
- }
- await fn(MapPrototypeGet(testStates, desc.id).context);
- testStepPostValidation(desc);
-
- function preValidation() {
- const runningStepDescs = getRunningStepDescs();
- const runningStepDescsWithSanitizers = ArrayPrototypeFilter(
- runningStepDescs,
- (d) => usesSanitizer(d),
- );
-
- if (runningStepDescsWithSanitizers.length > 0) {
- throw new Error(
- "Cannot start test step while another test step with sanitizers is running.\n" +
- runningStepDescsWithSanitizers
- .map((d) => ` * ${getFullName(d)}`)
- .join("\n"),
- );
- }
-
- if (usesSanitizer(desc) && runningStepDescs.length > 0) {
- throw new Error(
- "Cannot start test step with sanitizers while another test step is running.\n" +
- runningStepDescs.map((d) => ` * ${getFullName(d)}`).join("\n"),
- );
- }
-
- function getRunningStepDescs() {
- const results = [];
- let childDesc = desc;
- while (childDesc.parent != null) {
- const state = MapPrototypeGet(testStates, childDesc.parent.id);
- for (const siblingDesc of state.children) {
- if (siblingDesc.id == childDesc.id) {
- continue;
- }
- const siblingState = MapPrototypeGet(testStates, siblingDesc.id);
- if (!siblingState.finalized) {
- ArrayPrototypePush(results, siblingDesc);
- }
- }
- childDesc = childDesc.parent;
- }
- return results;
- }
- }
- };
- }
-
- function testStepPostValidation(desc) {
- // check for any running steps
- for (const childDesc of MapPrototypeGet(testStates, desc.id).children) {
- if (MapPrototypeGet(testStates, childDesc.id).status == "pending") {
- throw new Error(
- "There were still test steps running after the current scope finished execution. Ensure all steps are awaited (ex. `await t.step(...)`).",
- );
- }
- }
-
- // check if an ancestor already completed
- let currentDesc = desc.parent;
- while (currentDesc != null) {
- if (MapPrototypeGet(testStates, currentDesc.id).finalized) {
- throw new Error(
- "Parent scope completed before test step finished execution. Ensure all steps are awaited (ex. `await t.step(...)`).",
- );
- }
- currentDesc = currentDesc.parent;
- }
- }
-
- function pledgePermissions(permissions) {
- return ops.op_pledge_test_permissions(
- serializePermissions(permissions),
- );
- }
-
- function restorePermissions(token) {
- ops.op_restore_test_permissions(token);
- }
-
- function withPermissions(fn, permissions) {
- return async function applyPermissions(...params) {
- const token = pledgePermissions(permissions);
-
- try {
- await fn(...new SafeArrayIterator(params));
- } finally {
- restorePermissions(token);
- }
- };
- }
-
- /**
- * @typedef {{
- * id: number,
- * name: string,
- * fn: TestFunction
- * origin: string,
- * location: TestLocation,
- * filteredOut: boolean,
- * ignore: boolean,
- * only: boolean.
- * sanitizeOps: boolean,
- * sanitizeResources: boolean,
- * sanitizeExit: boolean,
- * permissions: PermissionOptions,
- * }} TestDescription
- *
- * @typedef {{
- * id: number,
- * name: string,
- * fn: TestFunction
- * origin: string,
- * location: TestLocation,
- * ignore: boolean,
- * level: number,
- * parent: TestDescription | TestStepDescription,
- * rootId: number,
- * rootName: String,
- * sanitizeOps: boolean,
- * sanitizeResources: boolean,
- * sanitizeExit: boolean,
- * }} TestStepDescription
- *
- * @typedef {{
- * context: TestContext,
- * children: TestStepDescription[],
- * finalized: boolean,
- * }} TestState
- *
- * @typedef {{
- * context: TestContext,
- * children: TestStepDescription[],
- * finalized: boolean,
- * status: "pending" | "ok" | ""failed" | ignored",
- * error: unknown,
- * elapsed: number | null,
- * reportedWait: boolean,
- * reportedResult: boolean,
- * }} TestStepState
- *
- * @typedef {{
- * id: number,
- * name: string,
- * fn: BenchFunction
- * origin: string,
- * filteredOut: boolean,
- * ignore: boolean,
- * only: boolean.
- * sanitizeExit: boolean,
- * permissions: PermissionOptions,
- * }} BenchDescription
- */
-
- /** @type {TestDescription[]} */
- const testDescs = [];
- /** @type {Map<number, TestState | TestStepState>} */
- const testStates = new Map();
- /** @type {BenchDescription[]} */
- const benchDescs = [];
- let isTestSubcommand = false;
- let isBenchSubcommand = false;
-
- // Main test function provided by Deno.
- function test(
- nameOrFnOrOptions,
- optionsOrFn,
- maybeFn,
- ) {
- if (!isTestSubcommand) {
- return;
- }
-
- let testDesc;
- const defaults = {
- ignore: false,
- only: false,
- sanitizeOps: true,
- sanitizeResources: true,
- sanitizeExit: true,
- permissions: null,
- };
-
- if (typeof nameOrFnOrOptions === "string") {
- if (!nameOrFnOrOptions) {
- throw new TypeError("The test name can't be empty");
- }
- if (typeof optionsOrFn === "function") {
- testDesc = { fn: optionsOrFn, name: nameOrFnOrOptions, ...defaults };
- } else {
- if (!maybeFn || typeof maybeFn !== "function") {
- throw new TypeError("Missing test function");
- }
- if (optionsOrFn.fn != undefined) {
- throw new TypeError(
- "Unexpected 'fn' field in options, test function is already provided as the third argument.",
- );
- }
- if (optionsOrFn.name != undefined) {
- throw new TypeError(
- "Unexpected 'name' field in options, test name is already provided as the first argument.",
- );
- }
- testDesc = {
- ...defaults,
- ...optionsOrFn,
- fn: maybeFn,
- name: nameOrFnOrOptions,
- };
- }
- } else if (typeof nameOrFnOrOptions === "function") {
- if (!nameOrFnOrOptions.name) {
- throw new TypeError("The test function must have a name");
- }
- if (optionsOrFn != undefined) {
- throw new TypeError("Unexpected second argument to Deno.test()");
- }
- if (maybeFn != undefined) {
- throw new TypeError("Unexpected third argument to Deno.test()");
- }
- testDesc = {
- ...defaults,
- fn: nameOrFnOrOptions,
- name: nameOrFnOrOptions.name,
- };
- } else {
- let fn;
- let name;
- if (typeof optionsOrFn === "function") {
- fn = optionsOrFn;
- if (nameOrFnOrOptions.fn != undefined) {
- throw new TypeError(
- "Unexpected 'fn' field in options, test function is already provided as the second argument.",
- );
- }
- name = nameOrFnOrOptions.name ?? fn.name;
- } else {
- if (
- !nameOrFnOrOptions.fn || typeof nameOrFnOrOptions.fn !== "function"
- ) {
- throw new TypeError(
- "Expected 'fn' field in the first argument to be a test function.",
- );
- }
- fn = nameOrFnOrOptions.fn;
- name = nameOrFnOrOptions.name ?? fn.name;
- }
- if (!name) {
- throw new TypeError("The test name can't be empty");
- }
- testDesc = { ...defaults, ...nameOrFnOrOptions, fn, name };
- }
-
- // Delete this prop in case the user passed it. It's used to detect steps.
- delete testDesc.parent;
- testDesc.fn = wrapTestFnWithSanitizers(testDesc.fn, testDesc);
- if (testDesc.permissions) {
- testDesc.fn = withPermissions(
- testDesc.fn,
- testDesc.permissions,
- );
- }
- testDesc.origin = getTestOrigin();
- const jsError = Deno.core.destructureError(new Error());
- testDesc.location = {
- fileName: jsError.frames[1].fileName,
- lineNumber: jsError.frames[1].lineNumber,
- columnNumber: jsError.frames[1].columnNumber,
- };
-
- const { id, filteredOut } = ops.op_register_test(testDesc);
- testDesc.id = id;
- testDesc.filteredOut = filteredOut;
-
- ArrayPrototypePush(testDescs, testDesc);
- MapPrototypeSet(testStates, testDesc.id, {
- context: createTestContext(testDesc),
- children: [],
- finalized: false,
- });
- }
-
- // Main bench function provided by Deno.
- function bench(
- nameOrFnOrOptions,
- optionsOrFn,
- maybeFn,
- ) {
- if (!isBenchSubcommand) {
- return;
- }
-
- let benchDesc;
- const defaults = {
- ignore: false,
- baseline: false,
- only: false,
- sanitizeExit: true,
- permissions: null,
- };
-
- if (typeof nameOrFnOrOptions === "string") {
- if (!nameOrFnOrOptions) {
- throw new TypeError("The bench name can't be empty");
- }
- if (typeof optionsOrFn === "function") {
- benchDesc = { fn: optionsOrFn, name: nameOrFnOrOptions, ...defaults };
- } else {
- if (!maybeFn || typeof maybeFn !== "function") {
- throw new TypeError("Missing bench function");
- }
- if (optionsOrFn.fn != undefined) {
- throw new TypeError(
- "Unexpected 'fn' field in options, bench function is already provided as the third argument.",
- );
- }
- if (optionsOrFn.name != undefined) {
- throw new TypeError(
- "Unexpected 'name' field in options, bench name is already provided as the first argument.",
- );
- }
- benchDesc = {
- ...defaults,
- ...optionsOrFn,
- fn: maybeFn,
- name: nameOrFnOrOptions,
- };
- }
- } else if (typeof nameOrFnOrOptions === "function") {
- if (!nameOrFnOrOptions.name) {
- throw new TypeError("The bench function must have a name");
- }
- if (optionsOrFn != undefined) {
- throw new TypeError("Unexpected second argument to Deno.bench()");
- }
- if (maybeFn != undefined) {
- throw new TypeError("Unexpected third argument to Deno.bench()");
- }
- benchDesc = {
- ...defaults,
- fn: nameOrFnOrOptions,
- name: nameOrFnOrOptions.name,
- };
- } else {
- let fn;
- let name;
- if (typeof optionsOrFn === "function") {
- fn = optionsOrFn;
- if (nameOrFnOrOptions.fn != undefined) {
- throw new TypeError(
- "Unexpected 'fn' field in options, bench function is already provided as the second argument.",
- );
- }
- name = nameOrFnOrOptions.name ?? fn.name;
- } else {
- if (
- !nameOrFnOrOptions.fn || typeof nameOrFnOrOptions.fn !== "function"
- ) {
- throw new TypeError(
- "Expected 'fn' field in the first argument to be a bench function.",
- );
- }
- fn = nameOrFnOrOptions.fn;
- name = nameOrFnOrOptions.name ?? fn.name;
- }
- if (!name) {
- throw new TypeError("The bench name can't be empty");
- }
- benchDesc = { ...defaults, ...nameOrFnOrOptions, fn, name };
- }
-
- benchDesc.origin = getBenchOrigin();
- const AsyncFunction = (async () => {}).constructor;
- benchDesc.async = AsyncFunction === benchDesc.fn.constructor;
-
- const { id, filteredOut } = ops.op_register_bench(benchDesc);
- benchDesc.id = id;
- benchDesc.filteredOut = filteredOut;
-
- ArrayPrototypePush(benchDescs, benchDesc);
- }
-
- async function runTest(desc) {
- if (desc.ignore) {
- return "ignored";
- }
-
- try {
- await desc.fn(desc);
- const failCount = failedChildStepsCount(desc);
- return failCount === 0 ? "ok" : {
- "failed": core.destructureError(
- new Error(
- `${failCount} test step${failCount === 1 ? "" : "s"} failed.`,
- ),
- ),
- };
- } catch (error) {
- return {
- "failed": core.destructureError(error),
- };
- } finally {
- const state = MapPrototypeGet(testStates, desc.id);
- state.finalized = true;
- // ensure the children report their result
- for (const childDesc of state.children) {
- stepReportResult(childDesc);
- }
- }
- }
-
- function compareMeasurements(a, b) {
- if (a > b) return 1;
- if (a < b) return -1;
-
- return 0;
- }
-
- function benchStats(n, highPrecision, avg, min, max, all) {
- return {
- n,
- min,
- max,
- p75: all[MathCeil(n * (75 / 100)) - 1],
- p99: all[MathCeil(n * (99 / 100)) - 1],
- p995: all[MathCeil(n * (99.5 / 100)) - 1],
- p999: all[MathCeil(n * (99.9 / 100)) - 1],
- avg: !highPrecision ? (avg / n) : MathCeil(avg / n),
- };
- }
-
- async function benchMeasure(timeBudget, desc) {
- const fn = desc.fn;
- let n = 0;
- let avg = 0;
- let wavg = 0;
- const all = [];
- let min = Infinity;
- let max = -Infinity;
- const lowPrecisionThresholdInNs = 1e4;
-
- // warmup step
- let c = 0;
- let iterations = 20;
- let budget = 10 * 1e6;
-
- if (!desc.async) {
- while (budget > 0 || iterations-- > 0) {
- const t1 = benchNow();
-
- fn();
- const iterationTime = benchNow() - t1;
-
- c++;
- wavg += iterationTime;
- budget -= iterationTime;
- }
- } else {
- while (budget > 0 || iterations-- > 0) {
- const t1 = benchNow();
-
- await fn();
- const iterationTime = benchNow() - t1;
-
- c++;
- wavg += iterationTime;
- budget -= iterationTime;
- }
- }
-
- wavg /= c;
-
- // measure step
- if (wavg > lowPrecisionThresholdInNs) {
- let iterations = 10;
- let budget = timeBudget * 1e6;
-
- if (!desc.async) {
- while (budget > 0 || iterations-- > 0) {
- const t1 = benchNow();
-
- fn();
- const iterationTime = benchNow() - t1;
-
- n++;
- avg += iterationTime;
- budget -= iterationTime;
- ArrayPrototypePush(all, iterationTime);
- if (iterationTime < min) min = iterationTime;
- if (iterationTime > max) max = iterationTime;
- }
- } else {
- while (budget > 0 || iterations-- > 0) {
- const t1 = benchNow();
-
- await fn();
- const iterationTime = benchNow() - t1;
-
- n++;
- avg += iterationTime;
- budget -= iterationTime;
- ArrayPrototypePush(all, iterationTime);
- if (iterationTime < min) min = iterationTime;
- if (iterationTime > max) max = iterationTime;
- }
- }
- } else {
- let iterations = 10;
- let budget = timeBudget * 1e6;
-
- if (!desc.async) {
- while (budget > 0 || iterations-- > 0) {
- const t1 = benchNow();
- for (let c = 0; c < lowPrecisionThresholdInNs; c++) fn();
- const iterationTime = (benchNow() - t1) / lowPrecisionThresholdInNs;
-
- n++;
- avg += iterationTime;
- ArrayPrototypePush(all, iterationTime);
- if (iterationTime < min) min = iterationTime;
- if (iterationTime > max) max = iterationTime;
- budget -= iterationTime * lowPrecisionThresholdInNs;
- }
- } else {
- while (budget > 0 || iterations-- > 0) {
- const t1 = benchNow();
- for (let c = 0; c < lowPrecisionThresholdInNs; c++) await fn();
- const iterationTime = (benchNow() - t1) / lowPrecisionThresholdInNs;
-
- n++;
- avg += iterationTime;
- ArrayPrototypePush(all, iterationTime);
- if (iterationTime < min) min = iterationTime;
- if (iterationTime > max) max = iterationTime;
- budget -= iterationTime * lowPrecisionThresholdInNs;
- }
- }
- }
-
- all.sort(compareMeasurements);
- return benchStats(n, wavg > lowPrecisionThresholdInNs, avg, min, max, all);
- }
-
- async function runBench(desc) {
- let token = null;
-
- try {
- if (desc.permissions) {
- token = pledgePermissions(desc.permissions);
- }
-
- if (desc.sanitizeExit) {
- setExitHandler((exitCode) => {
- assert(
- false,
- `Bench attempted to exit with exit code: ${exitCode}`,
- );
- });
- }
-
- const benchTimeInMs = 500;
- const stats = await benchMeasure(benchTimeInMs, desc);
-
- return { ok: stats };
- } catch (error) {
- return { failed: core.destructureError(error) };
- } finally {
- if (bench.sanitizeExit) setExitHandler(null);
- if (token !== null) restorePermissions(token);
- }
- }
-
- let origin = null;
-
- function getTestOrigin() {
- if (origin == null) {
- origin = ops.op_get_test_origin();
- }
- return origin;
- }
-
- function getBenchOrigin() {
- if (origin == null) {
- origin = ops.op_get_bench_origin();
- }
- return origin;
- }
-
- function benchNow() {
- return ops.op_bench_now();
- }
-
- function enableTest() {
- isTestSubcommand = true;
- }
-
- function enableBench() {
- isBenchSubcommand = true;
- }
-
- async function runTests({
- shuffle = null,
- } = {}) {
- core.setMacrotaskCallback(handleOpSanitizerDelayMacrotask);
-
- const origin = getTestOrigin();
- const only = ArrayPrototypeFilter(testDescs, (test) => test.only);
- const filtered = ArrayPrototypeFilter(
- only.length > 0 ? only : testDescs,
- (desc) => !desc.filteredOut,
- );
-
- ops.op_dispatch_test_event({
- plan: {
- origin,
- total: filtered.length,
- filteredOut: testDescs.length - filtered.length,
- usedOnly: only.length > 0,
- },
- });
-
- if (shuffle !== null) {
- // http://en.wikipedia.org/wiki/Linear_congruential_generator
- // Use BigInt for everything because the random seed is u64.
- const nextInt = (function (state) {
- const m = 0x80000000n;
- const a = 1103515245n;
- const c = 12345n;
-
- return function (max) {
- return state = ((a * state + c) % m) % BigInt(max);
- };
- }(BigInt(shuffle)));
-
- for (let i = filtered.length - 1; i > 0; i--) {
- const j = nextInt(i);
- [filtered[i], filtered[j]] = [filtered[j], filtered[i]];
- }
- }
-
- for (const desc of filtered) {
- ops.op_dispatch_test_event({ wait: desc.id });
- const earlier = DateNow();
- const result = await runTest(desc);
- const elapsed = DateNow() - earlier;
- ops.op_dispatch_test_event({
- result: [desc.id, result, elapsed],
- });
- }
- }
-
- async function runBenchmarks() {
- core.setMacrotaskCallback(handleOpSanitizerDelayMacrotask);
-
- const origin = getBenchOrigin();
- const originalConsole = globalThis.console;
-
- globalThis.console = new Console((s) => {
- ops.op_dispatch_bench_event({ output: s });
- });
-
- const only = ArrayPrototypeFilter(benchDescs, (bench) => bench.only);
- const filtered = ArrayPrototypeFilter(
- only.length > 0 ? only : benchDescs,
- (desc) => !desc.filteredOut && !desc.ignore,
- );
-
- let groups = new Set();
- // make sure ungrouped benchmarks are placed above grouped
- groups.add(undefined);
-
- for (const desc of filtered) {
- desc.group ||= undefined;
- groups.add(desc.group);
- }
-
- groups = ArrayFrom(groups);
- ArrayPrototypeSort(
- filtered,
- (a, b) => groups.indexOf(a.group) - groups.indexOf(b.group),
- );
-
- ops.op_dispatch_bench_event({
- plan: {
- origin,
- total: filtered.length,
- usedOnly: only.length > 0,
- names: ArrayPrototypeMap(filtered, (desc) => desc.name),
- },
- });
-
- for (const desc of filtered) {
- desc.baseline = !!desc.baseline;
- ops.op_dispatch_bench_event({ wait: desc.id });
- ops.op_dispatch_bench_event({
- result: [desc.id, await runBench(desc)],
- });
- }
-
- globalThis.console = originalConsole;
- }
-
- function getFullName(desc) {
- if ("parent" in desc) {
- return `${desc.parent.name} > ${desc.name}`;
- }
- return desc.name;
- }
-
- function usesSanitizer(desc) {
- return desc.sanitizeResources || desc.sanitizeOps || desc.sanitizeExit;
- }
-
- function canStreamReporting(desc) {
- let currentDesc = desc;
- while (currentDesc != null) {
- if (!usesSanitizer(currentDesc)) {
- return false;
- }
- currentDesc = currentDesc.parent;
- }
- for (const childDesc of MapPrototypeGet(testStates, desc.id).children) {
- const state = MapPrototypeGet(testStates, childDesc.id);
- if (!usesSanitizer(childDesc) && !state.finalized) {
- return false;
- }
- }
- return true;
- }
-
- function stepReportWait(desc) {
- const state = MapPrototypeGet(testStates, desc.id);
- if (state.reportedWait) {
- return;
- }
- ops.op_dispatch_test_event({ stepWait: desc.id });
- state.reportedWait = true;
- }
-
- function stepReportResult(desc) {
- const state = MapPrototypeGet(testStates, desc.id);
- if (state.reportedResult) {
- return;
- }
- stepReportWait(desc);
- for (const childDesc of state.children) {
- stepReportResult(childDesc);
- }
- let result;
- if (state.status == "pending" || state.status == "failed") {
- result = {
- [state.status]: state.error && core.destructureError(state.error),
- };
- } else {
- result = state.status;
- }
- ops.op_dispatch_test_event({
- stepResult: [desc.id, result, state.elapsed],
- });
- state.reportedResult = true;
- }
-
- function failedChildStepsCount(desc) {
- return ArrayPrototypeFilter(
- MapPrototypeGet(testStates, desc.id).children,
- (d) => MapPrototypeGet(testStates, d.id).status === "failed",
- ).length;
- }
-
- /** If a test validation error already occurred then don't bother checking
- * the sanitizers as that will create extra noise.
- */
- function shouldSkipSanitizers(desc) {
- try {
- testStepPostValidation(desc);
- return false;
- } catch {
- return true;
- }
- }
-
- /** @param desc {TestDescription | TestStepDescription} */
- function createTestContext(desc) {
- let parent;
- let level;
- let rootId;
- let rootName;
- if ("parent" in desc) {
- parent = MapPrototypeGet(testStates, desc.parent.id).context;
- level = desc.level;
- rootId = desc.rootId;
- rootName = desc.rootName;
- } else {
- parent = undefined;
- level = 0;
- rootId = desc.id;
- rootName = desc.name;
- }
- return {
- [SymbolToStringTag]: "TestContext",
- /**
- * The current test name.
- */
- name: desc.name,
- /**
- * Parent test context.
- */
- parent,
- /**
- * File Uri of the test code.
- */
- origin: desc.origin,
- /**
- * @param nameOrTestDefinition {string | TestStepDefinition}
- * @param fn {(t: TestContext) => void | Promise<void>}
- */
- async step(nameOrTestDefinition, fn) {
- if (MapPrototypeGet(testStates, desc.id).finalized) {
- throw new Error(
- "Cannot run test step after parent scope has finished execution. " +
- "Ensure any `.step(...)` calls are executed before their parent scope completes execution.",
- );
- }
-
- let stepDesc;
- if (typeof nameOrTestDefinition === "string") {
- if (!(ObjectPrototypeIsPrototypeOf(FunctionPrototype, fn))) {
- throw new TypeError("Expected function for second argument.");
- }
- stepDesc = {
- name: nameOrTestDefinition,
- fn,
- };
- } else if (typeof nameOrTestDefinition === "object") {
- stepDesc = nameOrTestDefinition;
- } else {
- throw new TypeError(
- "Expected a test definition or name and function.",
- );
- }
- stepDesc.ignore ??= false;
- stepDesc.sanitizeOps ??= desc.sanitizeOps;
- stepDesc.sanitizeResources ??= desc.sanitizeResources;
- stepDesc.sanitizeExit ??= desc.sanitizeExit;
- stepDesc.origin = getTestOrigin();
- const jsError = Deno.core.destructureError(new Error());
- stepDesc.location = {
- fileName: jsError.frames[1].fileName,
- lineNumber: jsError.frames[1].lineNumber,
- columnNumber: jsError.frames[1].columnNumber,
- };
- stepDesc.level = level + 1;
- stepDesc.parent = desc;
- stepDesc.rootId = rootId;
- stepDesc.rootName = rootName;
- const { id } = ops.op_register_test_step(stepDesc);
- stepDesc.id = id;
- const state = {
- context: createTestContext(stepDesc),
- children: [],
- finalized: false,
- status: "pending",
- error: null,
- elapsed: null,
- reportedWait: false,
- reportedResult: false,
- };
- MapPrototypeSet(testStates, stepDesc.id, state);
- ArrayPrototypePush(
- MapPrototypeGet(testStates, stepDesc.parent.id).children,
- stepDesc,
- );
-
- try {
- if (stepDesc.ignore) {
- state.status = "ignored";
- state.finalized = true;
- if (canStreamReporting(stepDesc)) {
- stepReportResult(stepDesc);
- }
- return false;
- }
-
- const testFn = wrapTestFnWithSanitizers(stepDesc.fn, stepDesc);
- const start = DateNow();
-
- try {
- await testFn(stepDesc);
-
- if (failedChildStepsCount(stepDesc) > 0) {
- state.status = "failed";
- } else {
- state.status = "ok";
- }
- } catch (error) {
- state.error = error;
- state.status = "failed";
- }
-
- state.elapsed = DateNow() - start;
-
- if (MapPrototypeGet(testStates, stepDesc.parent.id).finalized) {
- // always point this test out as one that was still running
- // if the parent step finalized
- state.status = "pending";
- }
-
- state.finalized = true;
-
- if (state.reportedWait && canStreamReporting(stepDesc)) {
- stepReportResult(stepDesc);
- }
-
- return state.status === "ok";
- } finally {
- if (canStreamReporting(stepDesc.parent)) {
- const parentState = MapPrototypeGet(testStates, stepDesc.parent.id);
- // flush any buffered steps
- for (const childDesc of parentState.children) {
- stepReportResult(childDesc);
- }
- }
- }
- },
- };
- }
-
- /**
- * @template T {Function}
- * @param testFn {T}
- * @param opts {{
- * sanitizeOps: boolean,
- * sanitizeResources: boolean,
- * sanitizeExit: boolean,
- * }}
- * @returns {T}
- */
- function wrapTestFnWithSanitizers(testFn, opts) {
- testFn = assertTestStepScopes(testFn);
-
- if (opts.sanitizeOps) {
- testFn = assertOps(testFn);
- }
- if (opts.sanitizeResources) {
- testFn = assertResources(testFn);
- }
- if (opts.sanitizeExit) {
- testFn = assertExit(testFn, true);
- }
- return testFn;
- }
-
- window.__bootstrap.testing = {
- bench,
- enableBench,
- enableTest,
- runBenchmarks,
- runTests,
- test,
- };
-})(this);
diff --git a/runtime/js/90_deno_ns.js b/runtime/js/90_deno_ns.js
index 16dd5c72f..cd6c07464 100644
--- a/runtime/js/90_deno_ns.js
+++ b/runtime/js/90_deno_ns.js
@@ -7,8 +7,6 @@
__bootstrap.denoNs = {
metrics: core.metrics,
- test: __bootstrap.testing.test,
- bench: __bootstrap.testing.bench,
Process: __bootstrap.process.Process,
run: __bootstrap.process.run,
isatty: __bootstrap.tty.isatty,
diff --git a/runtime/js/98_global_scope.js b/runtime/js/98_global_scope.js
new file mode 100644
index 000000000..7afb4472c
--- /dev/null
+++ b/runtime/js/98_global_scope.js
@@ -0,0 +1,352 @@
+// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
+"use strict";
+
+((window) => {
+ const core = Deno.core;
+ const {
+ ObjectDefineProperties,
+ SymbolFor,
+ } = window.__bootstrap.primordials;
+
+ const util = window.__bootstrap.util;
+ const location = window.__bootstrap.location;
+ const event = window.__bootstrap.event;
+ const eventTarget = window.__bootstrap.eventTarget;
+ const timers = window.__bootstrap.timers;
+ const base64 = window.__bootstrap.base64;
+ const encoding = window.__bootstrap.encoding;
+ const Console = window.__bootstrap.console.Console;
+ const caches = window.__bootstrap.caches;
+ const compression = window.__bootstrap.compression;
+ const worker = window.__bootstrap.worker;
+ const performance = window.__bootstrap.performance;
+ const crypto = window.__bootstrap.crypto;
+ const url = window.__bootstrap.url;
+ const urlPattern = window.__bootstrap.urlPattern;
+ const headers = window.__bootstrap.headers;
+ const streams = window.__bootstrap.streams;
+ const fileReader = window.__bootstrap.fileReader;
+ const webgpu = window.__bootstrap.webgpu;
+ const webSocket = window.__bootstrap.webSocket;
+ const broadcastChannel = window.__bootstrap.broadcastChannel;
+ const file = window.__bootstrap.file;
+ const formData = window.__bootstrap.formData;
+ const fetch = window.__bootstrap.fetch;
+ const messagePort = window.__bootstrap.messagePort;
+ const webidl = window.__bootstrap.webidl;
+ const domException = window.__bootstrap.domException;
+ const abortSignal = window.__bootstrap.abortSignal;
+ const globalInterfaces = window.__bootstrap.globalInterfaces;
+ const webStorage = window.__bootstrap.webStorage;
+ const prompt = window.__bootstrap.prompt;
+
+ // https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope
+ const windowOrWorkerGlobalScope = {
+ AbortController: util.nonEnumerable(abortSignal.AbortController),
+ AbortSignal: util.nonEnumerable(abortSignal.AbortSignal),
+ Blob: util.nonEnumerable(file.Blob),
+ ByteLengthQueuingStrategy: util.nonEnumerable(
+ streams.ByteLengthQueuingStrategy,
+ ),
+ CloseEvent: util.nonEnumerable(event.CloseEvent),
+ CompressionStream: util.nonEnumerable(compression.CompressionStream),
+ CountQueuingStrategy: util.nonEnumerable(
+ streams.CountQueuingStrategy,
+ ),
+ CryptoKey: util.nonEnumerable(crypto.CryptoKey),
+ CustomEvent: util.nonEnumerable(event.CustomEvent),
+ DecompressionStream: util.nonEnumerable(compression.DecompressionStream),
+ DOMException: util.nonEnumerable(domException.DOMException),
+ ErrorEvent: util.nonEnumerable(event.ErrorEvent),
+ Event: util.nonEnumerable(event.Event),
+ EventTarget: util.nonEnumerable(eventTarget.EventTarget),
+ File: util.nonEnumerable(file.File),
+ FileReader: util.nonEnumerable(fileReader.FileReader),
+ FormData: util.nonEnumerable(formData.FormData),
+ Headers: util.nonEnumerable(headers.Headers),
+ MessageEvent: util.nonEnumerable(event.MessageEvent),
+ Performance: util.nonEnumerable(performance.Performance),
+ PerformanceEntry: util.nonEnumerable(performance.PerformanceEntry),
+ PerformanceMark: util.nonEnumerable(performance.PerformanceMark),
+ PerformanceMeasure: util.nonEnumerable(performance.PerformanceMeasure),
+ PromiseRejectionEvent: util.nonEnumerable(event.PromiseRejectionEvent),
+ ProgressEvent: util.nonEnumerable(event.ProgressEvent),
+ ReadableStream: util.nonEnumerable(streams.ReadableStream),
+ ReadableStreamDefaultReader: util.nonEnumerable(
+ streams.ReadableStreamDefaultReader,
+ ),
+ Request: util.nonEnumerable(fetch.Request),
+ Response: util.nonEnumerable(fetch.Response),
+ TextDecoder: util.nonEnumerable(encoding.TextDecoder),
+ TextEncoder: util.nonEnumerable(encoding.TextEncoder),
+ TextDecoderStream: util.nonEnumerable(encoding.TextDecoderStream),
+ TextEncoderStream: util.nonEnumerable(encoding.TextEncoderStream),
+ TransformStream: util.nonEnumerable(streams.TransformStream),
+ URL: util.nonEnumerable(url.URL),
+ URLPattern: util.nonEnumerable(urlPattern.URLPattern),
+ URLSearchParams: util.nonEnumerable(url.URLSearchParams),
+ WebSocket: util.nonEnumerable(webSocket.WebSocket),
+ MessageChannel: util.nonEnumerable(messagePort.MessageChannel),
+ MessagePort: util.nonEnumerable(messagePort.MessagePort),
+ Worker: util.nonEnumerable(worker.Worker),
+ WritableStream: util.nonEnumerable(streams.WritableStream),
+ WritableStreamDefaultWriter: util.nonEnumerable(
+ streams.WritableStreamDefaultWriter,
+ ),
+ WritableStreamDefaultController: util.nonEnumerable(
+ streams.WritableStreamDefaultController,
+ ),
+ ReadableByteStreamController: util.nonEnumerable(
+ streams.ReadableByteStreamController,
+ ),
+ ReadableStreamBYOBReader: util.nonEnumerable(
+ streams.ReadableStreamBYOBReader,
+ ),
+ ReadableStreamBYOBRequest: util.nonEnumerable(
+ streams.ReadableStreamBYOBRequest,
+ ),
+ ReadableStreamDefaultController: util.nonEnumerable(
+ streams.ReadableStreamDefaultController,
+ ),
+ TransformStreamDefaultController: util.nonEnumerable(
+ streams.TransformStreamDefaultController,
+ ),
+ atob: util.writable(base64.atob),
+ btoa: util.writable(base64.btoa),
+ clearInterval: util.writable(timers.clearInterval),
+ clearTimeout: util.writable(timers.clearTimeout),
+ caches: {
+ enumerable: true,
+ configurable: true,
+ get: caches.cacheStorage,
+ },
+ CacheStorage: util.nonEnumerable(caches.CacheStorage),
+ Cache: util.nonEnumerable(caches.Cache),
+ console: util.nonEnumerable(
+ new Console((msg, level) => core.print(msg, level > 1)),
+ ),
+ crypto: util.readOnly(crypto.crypto),
+ Crypto: util.nonEnumerable(crypto.Crypto),
+ SubtleCrypto: util.nonEnumerable(crypto.SubtleCrypto),
+ fetch: util.writable(fetch.fetch),
+ performance: util.writable(performance.performance),
+ reportError: util.writable(event.reportError),
+ setInterval: util.writable(timers.setInterval),
+ setTimeout: util.writable(timers.setTimeout),
+ structuredClone: util.writable(messagePort.structuredClone),
+ // Branding as a WebIDL object
+ [webidl.brand]: util.nonEnumerable(webidl.brand),
+ };
+
+ const unstableWindowOrWorkerGlobalScope = {
+ BroadcastChannel: util.nonEnumerable(broadcastChannel.BroadcastChannel),
+ WebSocketStream: util.nonEnumerable(webSocket.WebSocketStream),
+
+ GPU: util.nonEnumerable(webgpu.GPU),
+ GPUAdapter: util.nonEnumerable(webgpu.GPUAdapter),
+ GPUSupportedLimits: util.nonEnumerable(webgpu.GPUSupportedLimits),
+ GPUSupportedFeatures: util.nonEnumerable(webgpu.GPUSupportedFeatures),
+ GPUDevice: util.nonEnumerable(webgpu.GPUDevice),
+ GPUQueue: util.nonEnumerable(webgpu.GPUQueue),
+ GPUBuffer: util.nonEnumerable(webgpu.GPUBuffer),
+ GPUBufferUsage: util.nonEnumerable(webgpu.GPUBufferUsage),
+ GPUMapMode: util.nonEnumerable(webgpu.GPUMapMode),
+ GPUTexture: util.nonEnumerable(webgpu.GPUTexture),
+ GPUTextureUsage: util.nonEnumerable(webgpu.GPUTextureUsage),
+ GPUTextureView: util.nonEnumerable(webgpu.GPUTextureView),
+ GPUSampler: util.nonEnumerable(webgpu.GPUSampler),
+ GPUBindGroupLayout: util.nonEnumerable(webgpu.GPUBindGroupLayout),
+ GPUPipelineLayout: util.nonEnumerable(webgpu.GPUPipelineLayout),
+ GPUBindGroup: util.nonEnumerable(webgpu.GPUBindGroup),
+ GPUShaderModule: util.nonEnumerable(webgpu.GPUShaderModule),
+ GPUShaderStage: util.nonEnumerable(webgpu.GPUShaderStage),
+ GPUComputePipeline: util.nonEnumerable(webgpu.GPUComputePipeline),
+ GPURenderPipeline: util.nonEnumerable(webgpu.GPURenderPipeline),
+ GPUColorWrite: util.nonEnumerable(webgpu.GPUColorWrite),
+ GPUCommandEncoder: util.nonEnumerable(webgpu.GPUCommandEncoder),
+ GPURenderPassEncoder: util.nonEnumerable(webgpu.GPURenderPassEncoder),
+ GPUComputePassEncoder: util.nonEnumerable(webgpu.GPUComputePassEncoder),
+ GPUCommandBuffer: util.nonEnumerable(webgpu.GPUCommandBuffer),
+ GPURenderBundleEncoder: util.nonEnumerable(webgpu.GPURenderBundleEncoder),
+ GPURenderBundle: util.nonEnumerable(webgpu.GPURenderBundle),
+ GPUQuerySet: util.nonEnumerable(webgpu.GPUQuerySet),
+ GPUOutOfMemoryError: util.nonEnumerable(webgpu.GPUOutOfMemoryError),
+ GPUValidationError: util.nonEnumerable(webgpu.GPUValidationError),
+ };
+
+ class Navigator {
+ constructor() {
+ webidl.illegalConstructor();
+ }
+
+ [SymbolFor("Deno.privateCustomInspect")](inspect) {
+ return `${this.constructor.name} ${inspect({})}`;
+ }
+ }
+
+ const navigator = webidl.createBranded(Navigator);
+
+ let numCpus, userAgent, language;
+
+ function setNumCpus(val) {
+ numCpus = val;
+ }
+
+ function setUserAgent(val) {
+ userAgent = val;
+ }
+
+ function setLanguage(val) {
+ language = val;
+ }
+
+ ObjectDefineProperties(Navigator.prototype, {
+ gpu: {
+ configurable: true,
+ enumerable: true,
+ get() {
+ webidl.assertBranded(this, NavigatorPrototype);
+ return webgpu.gpu;
+ },
+ },
+ hardwareConcurrency: {
+ configurable: true,
+ enumerable: true,
+ get() {
+ webidl.assertBranded(this, NavigatorPrototype);
+ return numCpus;
+ },
+ },
+ userAgent: {
+ configurable: true,
+ enumerable: true,
+ get() {
+ webidl.assertBranded(this, NavigatorPrototype);
+ return userAgent;
+ },
+ },
+ language: {
+ configurable: true,
+ enumerable: true,
+ get() {
+ webidl.assertBranded(this, NavigatorPrototype);
+ return language;
+ },
+ },
+ languages: {
+ configurable: true,
+ enumerable: true,
+ get() {
+ webidl.assertBranded(this, NavigatorPrototype);
+ return [language];
+ },
+ },
+ });
+ const NavigatorPrototype = Navigator.prototype;
+
+ class WorkerNavigator {
+ constructor() {
+ webidl.illegalConstructor();
+ }
+
+ [SymbolFor("Deno.privateCustomInspect")](inspect) {
+ return `${this.constructor.name} ${inspect({})}`;
+ }
+ }
+
+ const workerNavigator = webidl.createBranded(WorkerNavigator);
+
+ ObjectDefineProperties(WorkerNavigator.prototype, {
+ gpu: {
+ configurable: true,
+ enumerable: true,
+ get() {
+ webidl.assertBranded(this, WorkerNavigatorPrototype);
+ return webgpu.gpu;
+ },
+ },
+ hardwareConcurrency: {
+ configurable: true,
+ enumerable: true,
+ get() {
+ webidl.assertBranded(this, WorkerNavigatorPrototype);
+ return numCpus;
+ },
+ language: {
+ configurable: true,
+ enumerable: true,
+ get() {
+ webidl.assertBranded(this, WorkerNavigatorPrototype);
+ return language;
+ },
+ },
+ languages: {
+ configurable: true,
+ enumerable: true,
+ get() {
+ webidl.assertBranded(this, WorkerNavigatorPrototype);
+ return [language];
+ },
+ },
+ },
+ });
+ const WorkerNavigatorPrototype = WorkerNavigator.prototype;
+
+ const mainRuntimeGlobalProperties = {
+ Location: location.locationConstructorDescriptor,
+ location: location.locationDescriptor,
+ Window: globalInterfaces.windowConstructorDescriptor,
+ window: util.readOnly(globalThis),
+ self: util.writable(globalThis),
+ Navigator: util.nonEnumerable(Navigator),
+ navigator: {
+ configurable: true,
+ enumerable: true,
+ get: () => navigator,
+ },
+ alert: util.writable(prompt.alert),
+ confirm: util.writable(prompt.confirm),
+ prompt: util.writable(prompt.prompt),
+ localStorage: {
+ configurable: true,
+ enumerable: true,
+ get: webStorage.localStorage,
+ // Makes this reassignable to make astro work
+ set: () => {},
+ },
+ sessionStorage: {
+ configurable: true,
+ enumerable: true,
+ get: webStorage.sessionStorage,
+ // Makes this reassignable to make astro work
+ set: () => {},
+ },
+ Storage: util.nonEnumerable(webStorage.Storage),
+ };
+
+ const workerRuntimeGlobalProperties = {
+ WorkerLocation: location.workerLocationConstructorDescriptor,
+ location: location.workerLocationDescriptor,
+ WorkerGlobalScope: globalInterfaces.workerGlobalScopeConstructorDescriptor,
+ DedicatedWorkerGlobalScope:
+ globalInterfaces.dedicatedWorkerGlobalScopeConstructorDescriptor,
+ WorkerNavigator: util.nonEnumerable(WorkerNavigator),
+ navigator: {
+ configurable: true,
+ enumerable: true,
+ get: () => workerNavigator,
+ },
+ self: util.readOnly(globalThis),
+ };
+
+ window.__bootstrap.globalScope = {
+ windowOrWorkerGlobalScope,
+ unstableWindowOrWorkerGlobalScope,
+ mainRuntimeGlobalProperties,
+ workerRuntimeGlobalProperties,
+
+ setNumCpus,
+ setUserAgent,
+ setLanguage,
+ };
+})(this);
diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js
index c7faefcdd..2ea3504e2 100644
--- a/runtime/js/99_main.js
+++ b/runtime/js/99_main.js
@@ -41,48 +41,37 @@ delete Intl.v8BreakIterator;
const util = window.__bootstrap.util;
const event = window.__bootstrap.event;
const eventTarget = window.__bootstrap.eventTarget;
- const globalInterfaces = window.__bootstrap.globalInterfaces;
const location = window.__bootstrap.location;
const build = window.__bootstrap.build;
const version = window.__bootstrap.version;
const os = window.__bootstrap.os;
const timers = window.__bootstrap.timers;
- const base64 = window.__bootstrap.base64;
- const encoding = window.__bootstrap.encoding;
const colors = window.__bootstrap.colors;
- const Console = window.__bootstrap.console.Console;
- const caches = window.__bootstrap.caches;
const inspectArgs = window.__bootstrap.console.inspectArgs;
const quoteString = window.__bootstrap.console.quoteString;
- const compression = window.__bootstrap.compression;
- const worker = window.__bootstrap.worker;
const internals = window.__bootstrap.internals;
const performance = window.__bootstrap.performance;
const net = window.__bootstrap.net;
- const crypto = window.__bootstrap.crypto;
const url = window.__bootstrap.url;
- const urlPattern = window.__bootstrap.urlPattern;
- const headers = window.__bootstrap.headers;
- const streams = window.__bootstrap.streams;
- const fileReader = window.__bootstrap.fileReader;
- const webgpu = window.__bootstrap.webgpu;
- const webSocket = window.__bootstrap.webSocket;
- const webStorage = window.__bootstrap.webStorage;
- const broadcastChannel = window.__bootstrap.broadcastChannel;
- const file = window.__bootstrap.file;
- const formData = window.__bootstrap.formData;
const fetch = window.__bootstrap.fetch;
- const prompt = window.__bootstrap.prompt;
const messagePort = window.__bootstrap.messagePort;
const denoNs = window.__bootstrap.denoNs;
const denoNsUnstable = window.__bootstrap.denoNsUnstable;
const errors = window.__bootstrap.errors.errors;
const webidl = window.__bootstrap.webidl;
const domException = window.__bootstrap.domException;
- const abortSignal = window.__bootstrap.abortSignal;
const { defineEventHandler, reportException } = window.__bootstrap.event;
const { deserializeJsMessageData, serializeJsMessageData } =
window.__bootstrap.messagePort;
+ const {
+ windowOrWorkerGlobalScope,
+ unstableWindowOrWorkerGlobalScope,
+ workerRuntimeGlobalProperties,
+ mainRuntimeGlobalProperties,
+ setNumCpus,
+ setUserAgent,
+ setLanguage,
+ } = window.__bootstrap.globalScope;
let windowIsClosing = false;
@@ -326,298 +315,6 @@ delete Intl.v8BreakIterator;
);
}
- class Navigator {
- constructor() {
- webidl.illegalConstructor();
- }
-
- [SymbolFor("Deno.privateCustomInspect")](inspect) {
- return `${this.constructor.name} ${inspect({})}`;
- }
- }
-
- const navigator = webidl.createBranded(Navigator);
-
- let numCpus, userAgent, language;
-
- ObjectDefineProperties(Navigator.prototype, {
- gpu: {
- configurable: true,
- enumerable: true,
- get() {
- webidl.assertBranded(this, NavigatorPrototype);
- return webgpu.gpu;
- },
- },
- hardwareConcurrency: {
- configurable: true,
- enumerable: true,
- get() {
- webidl.assertBranded(this, NavigatorPrototype);
- return numCpus;
- },
- },
- userAgent: {
- configurable: true,
- enumerable: true,
- get() {
- webidl.assertBranded(this, NavigatorPrototype);
- return userAgent;
- },
- },
- language: {
- configurable: true,
- enumerable: true,
- get() {
- webidl.assertBranded(this, NavigatorPrototype);
- return language;
- },
- },
- languages: {
- configurable: true,
- enumerable: true,
- get() {
- webidl.assertBranded(this, NavigatorPrototype);
- return [language];
- },
- },
- });
- const NavigatorPrototype = Navigator.prototype;
-
- class WorkerNavigator {
- constructor() {
- webidl.illegalConstructor();
- }
-
- [SymbolFor("Deno.privateCustomInspect")](inspect) {
- return `${this.constructor.name} ${inspect({})}`;
- }
- }
-
- const workerNavigator = webidl.createBranded(WorkerNavigator);
-
- ObjectDefineProperties(WorkerNavigator.prototype, {
- gpu: {
- configurable: true,
- enumerable: true,
- get() {
- webidl.assertBranded(this, WorkerNavigatorPrototype);
- return webgpu.gpu;
- },
- },
- hardwareConcurrency: {
- configurable: true,
- enumerable: true,
- get() {
- webidl.assertBranded(this, WorkerNavigatorPrototype);
- return numCpus;
- },
- language: {
- configurable: true,
- enumerable: true,
- get() {
- webidl.assertBranded(this, WorkerNavigatorPrototype);
- return language;
- },
- },
- languages: {
- configurable: true,
- enumerable: true,
- get() {
- webidl.assertBranded(this, WorkerNavigatorPrototype);
- return [language];
- },
- },
- },
- });
- const WorkerNavigatorPrototype = WorkerNavigator.prototype;
-
- // https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope
- const windowOrWorkerGlobalScope = {
- AbortController: util.nonEnumerable(abortSignal.AbortController),
- AbortSignal: util.nonEnumerable(abortSignal.AbortSignal),
- Blob: util.nonEnumerable(file.Blob),
- ByteLengthQueuingStrategy: util.nonEnumerable(
- streams.ByteLengthQueuingStrategy,
- ),
- CloseEvent: util.nonEnumerable(event.CloseEvent),
- CompressionStream: util.nonEnumerable(compression.CompressionStream),
- CountQueuingStrategy: util.nonEnumerable(
- streams.CountQueuingStrategy,
- ),
- CryptoKey: util.nonEnumerable(crypto.CryptoKey),
- CustomEvent: util.nonEnumerable(event.CustomEvent),
- DecompressionStream: util.nonEnumerable(compression.DecompressionStream),
- DOMException: util.nonEnumerable(domException.DOMException),
- ErrorEvent: util.nonEnumerable(event.ErrorEvent),
- Event: util.nonEnumerable(event.Event),
- EventTarget: util.nonEnumerable(eventTarget.EventTarget),
- File: util.nonEnumerable(file.File),
- FileReader: util.nonEnumerable(fileReader.FileReader),
- FormData: util.nonEnumerable(formData.FormData),
- Headers: util.nonEnumerable(headers.Headers),
- MessageEvent: util.nonEnumerable(event.MessageEvent),
- Performance: util.nonEnumerable(performance.Performance),
- PerformanceEntry: util.nonEnumerable(performance.PerformanceEntry),
- PerformanceMark: util.nonEnumerable(performance.PerformanceMark),
- PerformanceMeasure: util.nonEnumerable(performance.PerformanceMeasure),
- PromiseRejectionEvent: util.nonEnumerable(event.PromiseRejectionEvent),
- ProgressEvent: util.nonEnumerable(event.ProgressEvent),
- ReadableStream: util.nonEnumerable(streams.ReadableStream),
- ReadableStreamDefaultReader: util.nonEnumerable(
- streams.ReadableStreamDefaultReader,
- ),
- Request: util.nonEnumerable(fetch.Request),
- Response: util.nonEnumerable(fetch.Response),
- TextDecoder: util.nonEnumerable(encoding.TextDecoder),
- TextEncoder: util.nonEnumerable(encoding.TextEncoder),
- TextDecoderStream: util.nonEnumerable(encoding.TextDecoderStream),
- TextEncoderStream: util.nonEnumerable(encoding.TextEncoderStream),
- TransformStream: util.nonEnumerable(streams.TransformStream),
- URL: util.nonEnumerable(url.URL),
- URLPattern: util.nonEnumerable(urlPattern.URLPattern),
- URLSearchParams: util.nonEnumerable(url.URLSearchParams),
- WebSocket: util.nonEnumerable(webSocket.WebSocket),
- MessageChannel: util.nonEnumerable(messagePort.MessageChannel),
- MessagePort: util.nonEnumerable(messagePort.MessagePort),
- Worker: util.nonEnumerable(worker.Worker),
- WritableStream: util.nonEnumerable(streams.WritableStream),
- WritableStreamDefaultWriter: util.nonEnumerable(
- streams.WritableStreamDefaultWriter,
- ),
- WritableStreamDefaultController: util.nonEnumerable(
- streams.WritableStreamDefaultController,
- ),
- ReadableByteStreamController: util.nonEnumerable(
- streams.ReadableByteStreamController,
- ),
- ReadableStreamBYOBReader: util.nonEnumerable(
- streams.ReadableStreamBYOBReader,
- ),
- ReadableStreamBYOBRequest: util.nonEnumerable(
- streams.ReadableStreamBYOBRequest,
- ),
- ReadableStreamDefaultController: util.nonEnumerable(
- streams.ReadableStreamDefaultController,
- ),
- TransformStreamDefaultController: util.nonEnumerable(
- streams.TransformStreamDefaultController,
- ),
- atob: util.writable(base64.atob),
- btoa: util.writable(base64.btoa),
- clearInterval: util.writable(timers.clearInterval),
- clearTimeout: util.writable(timers.clearTimeout),
- caches: {
- enumerable: true,
- configurable: true,
- get: caches.cacheStorage,
- },
- CacheStorage: util.nonEnumerable(caches.CacheStorage),
- Cache: util.nonEnumerable(caches.Cache),
- console: util.nonEnumerable(
- new Console((msg, level) => core.print(msg, level > 1)),
- ),
- crypto: util.readOnly(crypto.crypto),
- Crypto: util.nonEnumerable(crypto.Crypto),
- SubtleCrypto: util.nonEnumerable(crypto.SubtleCrypto),
- fetch: util.writable(fetch.fetch),
- performance: util.writable(performance.performance),
- reportError: util.writable(event.reportError),
- setInterval: util.writable(timers.setInterval),
- setTimeout: util.writable(timers.setTimeout),
- structuredClone: util.writable(messagePort.structuredClone),
- // Branding as a WebIDL object
- [webidl.brand]: util.nonEnumerable(webidl.brand),
- };
-
- const unstableWindowOrWorkerGlobalScope = {
- BroadcastChannel: util.nonEnumerable(broadcastChannel.BroadcastChannel),
- WebSocketStream: util.nonEnumerable(webSocket.WebSocketStream),
-
- GPU: util.nonEnumerable(webgpu.GPU),
- GPUAdapter: util.nonEnumerable(webgpu.GPUAdapter),
- GPUSupportedLimits: util.nonEnumerable(webgpu.GPUSupportedLimits),
- GPUSupportedFeatures: util.nonEnumerable(webgpu.GPUSupportedFeatures),
- GPUDevice: util.nonEnumerable(webgpu.GPUDevice),
- GPUQueue: util.nonEnumerable(webgpu.GPUQueue),
- GPUBuffer: util.nonEnumerable(webgpu.GPUBuffer),
- GPUBufferUsage: util.nonEnumerable(webgpu.GPUBufferUsage),
- GPUMapMode: util.nonEnumerable(webgpu.GPUMapMode),
- GPUTexture: util.nonEnumerable(webgpu.GPUTexture),
- GPUTextureUsage: util.nonEnumerable(webgpu.GPUTextureUsage),
- GPUTextureView: util.nonEnumerable(webgpu.GPUTextureView),
- GPUSampler: util.nonEnumerable(webgpu.GPUSampler),
- GPUBindGroupLayout: util.nonEnumerable(webgpu.GPUBindGroupLayout),
- GPUPipelineLayout: util.nonEnumerable(webgpu.GPUPipelineLayout),
- GPUBindGroup: util.nonEnumerable(webgpu.GPUBindGroup),
- GPUShaderModule: util.nonEnumerable(webgpu.GPUShaderModule),
- GPUShaderStage: util.nonEnumerable(webgpu.GPUShaderStage),
- GPUComputePipeline: util.nonEnumerable(webgpu.GPUComputePipeline),
- GPURenderPipeline: util.nonEnumerable(webgpu.GPURenderPipeline),
- GPUColorWrite: util.nonEnumerable(webgpu.GPUColorWrite),
- GPUCommandEncoder: util.nonEnumerable(webgpu.GPUCommandEncoder),
- GPURenderPassEncoder: util.nonEnumerable(webgpu.GPURenderPassEncoder),
- GPUComputePassEncoder: util.nonEnumerable(webgpu.GPUComputePassEncoder),
- GPUCommandBuffer: util.nonEnumerable(webgpu.GPUCommandBuffer),
- GPURenderBundleEncoder: util.nonEnumerable(webgpu.GPURenderBundleEncoder),
- GPURenderBundle: util.nonEnumerable(webgpu.GPURenderBundle),
- GPUQuerySet: util.nonEnumerable(webgpu.GPUQuerySet),
- GPUOutOfMemoryError: util.nonEnumerable(webgpu.GPUOutOfMemoryError),
- GPUValidationError: util.nonEnumerable(webgpu.GPUValidationError),
- };
-
- const mainRuntimeGlobalProperties = {
- Location: location.locationConstructorDescriptor,
- location: location.locationDescriptor,
- Window: globalInterfaces.windowConstructorDescriptor,
- window: util.readOnly(globalThis),
- self: util.writable(globalThis),
- Navigator: util.nonEnumerable(Navigator),
- navigator: {
- configurable: true,
- enumerable: true,
- get: () => navigator,
- },
- close: util.writable(windowClose),
- closed: util.getterOnly(() => windowIsClosing),
- alert: util.writable(prompt.alert),
- confirm: util.writable(prompt.confirm),
- prompt: util.writable(prompt.prompt),
- localStorage: {
- configurable: true,
- enumerable: true,
- get: webStorage.localStorage,
- // Makes this reassignable to make astro work
- set: () => {},
- },
- sessionStorage: {
- configurable: true,
- enumerable: true,
- get: webStorage.sessionStorage,
- // Makes this reassignable to make astro work
- set: () => {},
- },
- Storage: util.nonEnumerable(webStorage.Storage),
- };
-
- const workerRuntimeGlobalProperties = {
- WorkerLocation: location.workerLocationConstructorDescriptor,
- location: location.workerLocationDescriptor,
- WorkerGlobalScope: globalInterfaces.workerGlobalScopeConstructorDescriptor,
- DedicatedWorkerGlobalScope:
- globalInterfaces.dedicatedWorkerGlobalScopeConstructorDescriptor,
- WorkerNavigator: util.nonEnumerable(WorkerNavigator),
- navigator: {
- configurable: true,
- enumerable: true,
- get: () => workerNavigator,
- },
- self: util.readOnly(globalThis),
- // TODO(bartlomieju): should be readonly?
- close: util.nonEnumerable(workerClose),
- postMessage: util.writable(postMessage),
- };
-
const pendingRejections = [];
const pendingRejectionsReasons = new SafeWeakMap();
@@ -726,6 +423,10 @@ delete Intl.v8BreakIterator;
ObjectDefineProperties(globalThis, unstableWindowOrWorkerGlobalScope);
}
ObjectDefineProperties(globalThis, mainRuntimeGlobalProperties);
+ ObjectDefineProperties(globalThis, {
+ close: util.writable(windowClose),
+ closed: util.getterOnly(() => windowIsClosing),
+ });
ObjectSetPrototypeOf(globalThis, Window.prototype);
if (runtimeOptions.inspectFlag) {
@@ -754,9 +455,9 @@ delete Intl.v8BreakIterator;
runtimeStart(runtimeOptions);
- numCpus = runtimeOptions.cpuCount;
- userAgent = runtimeOptions.userAgent;
- language = runtimeOptions.locale;
+ setNumCpus(runtimeOptions.cpuCount);
+ setUserAgent(runtimeOptions.userAgent);
+ setLanguage(runtimeOptions.locale);
const internalSymbol = Symbol("Deno.internal");
@@ -849,7 +550,12 @@ delete Intl.v8BreakIterator;
ObjectDefineProperties(globalThis, unstableWindowOrWorkerGlobalScope);
}
ObjectDefineProperties(globalThis, workerRuntimeGlobalProperties);
- ObjectDefineProperties(globalThis, { name: util.writable(name) });
+ ObjectDefineProperties(globalThis, {
+ name: util.writable(name),
+ // TODO(bartlomieju): should be readonly?
+ close: util.nonEnumerable(workerClose),
+ postMessage: util.writable(postMessage),
+ });
if (runtimeOptions.enableTestingFeaturesFlag) {
ObjectDefineProperty(
globalThis,
@@ -882,8 +588,9 @@ delete Intl.v8BreakIterator;
);
location.setLocationHref(runtimeOptions.location);
- numCpus = runtimeOptions.cpuCount;
- language = runtimeOptions.locale;
+
+ setNumCpus(runtimeOptions.cpuCount);
+ setLanguage(runtimeOptions.locale);
globalThis.pollForMessages = pollForMessages;