From ca64771257d23ceee97e882965269702c359f6aa Mon Sep 17 00:00:00 2001 From: Julien Cayzac Date: Fri, 8 Dec 2023 22:24:49 +0900 Subject: [PATCH] fix(unstable): Honor granular unstable flags in js runtime (#21466) This fixes #21434 for `BroadcastChannel` and `WebSocketStream`. `--unstable` still enable both, but granular unstable flags now also work: * `--unstable-net` now enables `WebSocketStream`. * `--unstable-broadcast-channel` now enables `BroadcastChannel`. * Additionally, there are now tests for all granular unstable flags. Since `unsafe-proto` already had tests, so I didn't add any for this one. It also introduces a map to keep track of granular unstable ids without having to sync multiple places. --- cli/tests/integration/run_tests.rs | 83 ++++++++++++ .../unstable_broadcast_channel.disabled.out | 2 + .../unstable_broadcast_channel.enabled.out | 2 + .../run/unstable_broadcast_channel.js | 10 ++ .../testdata/run/unstable_cron.disabled.out | 2 + .../testdata/run/unstable_cron.enabled.out | 2 + cli/tests/testdata/run/unstable_cron.js | 10 ++ .../testdata/run/unstable_ffi.disabled.out | 10 ++ .../testdata/run/unstable_ffi.enabled.out | 10 ++ cli/tests/testdata/run/unstable_ffi.js | 14 +++ .../testdata/run/unstable_fs.disabled.out | 10 ++ .../testdata/run/unstable_fs.enabled.out | 10 ++ cli/tests/testdata/run/unstable_fs.js | 14 +++ .../testdata/run/unstable_http.disabled.out | 16 +++ .../testdata/run/unstable_http.enabled.out | 16 +++ cli/tests/testdata/run/unstable_http.js | 17 +++ .../testdata/run/unstable_kv.disabled.out | 10 ++ .../testdata/run/unstable_kv.enabled.out | 10 ++ cli/tests/testdata/run/unstable_kv.js | 14 +++ .../testdata/run/unstable_net.disabled.out | 4 + .../testdata/run/unstable_net.enabled.out | 4 + cli/tests/testdata/run/unstable_net.js | 11 ++ .../run/unstable_worker_options.disabled.out | 1 + .../run/unstable_worker_options.enabled.out | 2 + .../testdata/run/unstable_worker_options.js | 19 +++ runtime/js/90_deno_ns.js | 119 +++++++++--------- runtime/js/98_global_scope.js | 8 +- runtime/js/99_main.js | 52 ++++++-- 28 files changed, 414 insertions(+), 68 deletions(-) create mode 100644 cli/tests/testdata/run/unstable_broadcast_channel.disabled.out create mode 100644 cli/tests/testdata/run/unstable_broadcast_channel.enabled.out create mode 100644 cli/tests/testdata/run/unstable_broadcast_channel.js create mode 100644 cli/tests/testdata/run/unstable_cron.disabled.out create mode 100644 cli/tests/testdata/run/unstable_cron.enabled.out create mode 100644 cli/tests/testdata/run/unstable_cron.js create mode 100644 cli/tests/testdata/run/unstable_ffi.disabled.out create mode 100644 cli/tests/testdata/run/unstable_ffi.enabled.out create mode 100644 cli/tests/testdata/run/unstable_ffi.js create mode 100644 cli/tests/testdata/run/unstable_fs.disabled.out create mode 100644 cli/tests/testdata/run/unstable_fs.enabled.out create mode 100644 cli/tests/testdata/run/unstable_fs.js create mode 100644 cli/tests/testdata/run/unstable_http.disabled.out create mode 100644 cli/tests/testdata/run/unstable_http.enabled.out create mode 100644 cli/tests/testdata/run/unstable_http.js create mode 100644 cli/tests/testdata/run/unstable_kv.disabled.out create mode 100644 cli/tests/testdata/run/unstable_kv.enabled.out create mode 100644 cli/tests/testdata/run/unstable_kv.js create mode 100644 cli/tests/testdata/run/unstable_net.disabled.out create mode 100644 cli/tests/testdata/run/unstable_net.enabled.out create mode 100644 cli/tests/testdata/run/unstable_net.js create mode 100644 cli/tests/testdata/run/unstable_worker_options.disabled.out create mode 100644 cli/tests/testdata/run/unstable_worker_options.enabled.out create mode 100644 cli/tests/testdata/run/unstable_worker_options.js diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs index 058f92572e..c96d68b937 100644 --- a/cli/tests/integration/run_tests.rs +++ b/cli/tests/integration/run_tests.rs @@ -1577,6 +1577,89 @@ itest!(unstable_worker { output: "run/unstable_worker.ts.out", }); +itest!(unstable_worker_options_disabled { + args: "run --quiet --reload --allow-read run/unstable_worker_options.js", + output: "run/unstable_worker_options.disabled.out", + exit_code: 70, +}); + +itest!(unstable_worker_options_enabled { + args: "run --quiet --reload --allow-read --unstable-worker-options run/unstable_worker_options.js", + output: "run/unstable_worker_options.enabled.out", +}); + +itest!(unstable_broadcast_channel_disabled { + args: "run --quiet --reload --allow-read run/unstable_broadcast_channel.js", + output: "run/unstable_broadcast_channel.disabled.out", +}); + +itest!(unstable_broadcast_channel_enabled { + args: "run --quiet --reload --allow-read --unstable-broadcast-channel run/unstable_broadcast_channel.js", + output: "run/unstable_broadcast_channel.enabled.out", +}); + +itest!(unstable_cron_disabled { + args: "run --quiet --reload --allow-read run/unstable_cron.js", + output: "run/unstable_cron.disabled.out", +}); + +itest!(unstable_cron_enabled { + args: + "run --quiet --reload --allow-read --unstable-cron run/unstable_cron.js", + output: "run/unstable_cron.enabled.out", +}); + +itest!(unstable_ffi_disabled { + args: "run --quiet --reload --allow-read run/unstable_ffi.js", + output: "run/unstable_ffi.disabled.out", +}); + +itest!(unstable_ffi_enabled { + args: "run --quiet --reload --allow-read --unstable-ffi run/unstable_ffi.js", + output: "run/unstable_ffi.enabled.out", +}); + +itest!(unstable_fs_disabled { + args: "run --quiet --reload --allow-read run/unstable_fs.js", + output: "run/unstable_fs.disabled.out", +}); + +itest!(unstable_fs_enabled { + args: "run --quiet --reload --allow-read --unstable-fs run/unstable_fs.js", + output: "run/unstable_fs.enabled.out", +}); + +itest!(unstable_http_disabled { + args: "run --quiet --reload --allow-read run/unstable_http.js", + output: "run/unstable_http.disabled.out", +}); + +itest!(unstable_http_enabled { + args: + "run --quiet --reload --allow-read --unstable-http run/unstable_http.js", + output: "run/unstable_http.enabled.out", +}); + +itest!(unstable_net_disabled { + args: "run --quiet --reload --allow-read run/unstable_net.js", + output: "run/unstable_net.disabled.out", +}); + +itest!(unstable_net_enabled { + args: "run --quiet --reload --allow-read --unstable-net run/unstable_net.js", + output: "run/unstable_net.enabled.out", +}); + +itest!(unstable_kv_disabled { + args: "run --quiet --reload --allow-read run/unstable_kv.js", + output: "run/unstable_kv.disabled.out", +}); + +itest!(unstable_kv_enabled { + args: "run --quiet --reload --allow-read --unstable-kv run/unstable_kv.js", + output: "run/unstable_kv.enabled.out", +}); + itest!(import_compression { args: "run --quiet --reload --allow-net run/import_compression/main.ts", output: "run/import_compression/main.out", diff --git a/cli/tests/testdata/run/unstable_broadcast_channel.disabled.out b/cli/tests/testdata/run/unstable_broadcast_channel.disabled.out new file mode 100644 index 0000000000..7758663527 --- /dev/null +++ b/cli/tests/testdata/run/unstable_broadcast_channel.disabled.out @@ -0,0 +1,2 @@ +main undefined +worker undefined diff --git a/cli/tests/testdata/run/unstable_broadcast_channel.enabled.out b/cli/tests/testdata/run/unstable_broadcast_channel.enabled.out new file mode 100644 index 0000000000..b3701ce443 --- /dev/null +++ b/cli/tests/testdata/run/unstable_broadcast_channel.enabled.out @@ -0,0 +1,2 @@ +main [class BroadcastChannel extends EventTarget] +worker [class BroadcastChannel extends EventTarget] diff --git a/cli/tests/testdata/run/unstable_broadcast_channel.js b/cli/tests/testdata/run/unstable_broadcast_channel.js new file mode 100644 index 0000000000..b8576aa22f --- /dev/null +++ b/cli/tests/testdata/run/unstable_broadcast_channel.js @@ -0,0 +1,10 @@ +const scope = import.meta.url.slice(-7) === "#worker" ? "worker" : "main"; + +console.log(scope, globalThis.BroadcastChannel); + +if (scope === "worker") { + postMessage("done"); +} else { + const worker = new Worker(`${import.meta.url}#worker`, { type: "module" }); + worker.onmessage = () => Deno.exit(0); +} diff --git a/cli/tests/testdata/run/unstable_cron.disabled.out b/cli/tests/testdata/run/unstable_cron.disabled.out new file mode 100644 index 0000000000..7758663527 --- /dev/null +++ b/cli/tests/testdata/run/unstable_cron.disabled.out @@ -0,0 +1,2 @@ +main undefined +worker undefined diff --git a/cli/tests/testdata/run/unstable_cron.enabled.out b/cli/tests/testdata/run/unstable_cron.enabled.out new file mode 100644 index 0000000000..d18304f1fd --- /dev/null +++ b/cli/tests/testdata/run/unstable_cron.enabled.out @@ -0,0 +1,2 @@ +main [Function: cron] +worker [Function: cron] diff --git a/cli/tests/testdata/run/unstable_cron.js b/cli/tests/testdata/run/unstable_cron.js new file mode 100644 index 0000000000..3114f6e555 --- /dev/null +++ b/cli/tests/testdata/run/unstable_cron.js @@ -0,0 +1,10 @@ +const scope = import.meta.url.slice(-7) === "#worker" ? "worker" : "main"; + +console.log(scope, Deno.cron); + +if (scope === "worker") { + postMessage("done"); +} else { + const worker = new Worker(`${import.meta.url}#worker`, { type: "module" }); + worker.onmessage = () => Deno.exit(0); +} diff --git a/cli/tests/testdata/run/unstable_ffi.disabled.out b/cli/tests/testdata/run/unstable_ffi.disabled.out new file mode 100644 index 0000000000..0d8ac4410f --- /dev/null +++ b/cli/tests/testdata/run/unstable_ffi.disabled.out @@ -0,0 +1,10 @@ +main undefined +main undefined +main undefined +main undefined +main undefined +worker undefined +worker undefined +worker undefined +worker undefined +worker undefined diff --git a/cli/tests/testdata/run/unstable_ffi.enabled.out b/cli/tests/testdata/run/unstable_ffi.enabled.out new file mode 100644 index 0000000000..672b2a2a23 --- /dev/null +++ b/cli/tests/testdata/run/unstable_ffi.enabled.out @@ -0,0 +1,10 @@ +main [class UnsafeCallback] +main [class UnsafeFnPointer] +main [class UnsafePointer] +main [class UnsafePointerView] +main [Function: dlopen] +worker [class UnsafeCallback] +worker [class UnsafeFnPointer] +worker [class UnsafePointer] +worker [class UnsafePointerView] +worker [Function: dlopen] diff --git a/cli/tests/testdata/run/unstable_ffi.js b/cli/tests/testdata/run/unstable_ffi.js new file mode 100644 index 0000000000..4809c5ffe4 --- /dev/null +++ b/cli/tests/testdata/run/unstable_ffi.js @@ -0,0 +1,14 @@ +const scope = import.meta.url.slice(-7) === "#worker" ? "worker" : "main"; + +console.log(scope, Deno.UnsafeCallback); +console.log(scope, Deno.UnsafeFnPointer); +console.log(scope, Deno.UnsafePointer); +console.log(scope, Deno.UnsafePointerView); +console.log(scope, Deno.dlopen); + +if (scope === "worker") { + postMessage("done"); +} else { + const worker = new Worker(`${import.meta.url}#worker`, { type: "module" }); + worker.onmessage = () => Deno.exit(0); +} diff --git a/cli/tests/testdata/run/unstable_fs.disabled.out b/cli/tests/testdata/run/unstable_fs.disabled.out new file mode 100644 index 0000000000..0d8ac4410f --- /dev/null +++ b/cli/tests/testdata/run/unstable_fs.disabled.out @@ -0,0 +1,10 @@ +main undefined +main undefined +main undefined +main undefined +main undefined +worker undefined +worker undefined +worker undefined +worker undefined +worker undefined diff --git a/cli/tests/testdata/run/unstable_fs.enabled.out b/cli/tests/testdata/run/unstable_fs.enabled.out new file mode 100644 index 0000000000..6938fa9c22 --- /dev/null +++ b/cli/tests/testdata/run/unstable_fs.enabled.out @@ -0,0 +1,10 @@ +main [AsyncFunction: flock] +main [Function: flockSync] +main [AsyncFunction: funlock] +main [Function: funlockSync] +main [Function: umask] +worker [AsyncFunction: flock] +worker [Function: flockSync] +worker [AsyncFunction: funlock] +worker [Function: funlockSync] +worker [Function: umask] diff --git a/cli/tests/testdata/run/unstable_fs.js b/cli/tests/testdata/run/unstable_fs.js new file mode 100644 index 0000000000..83f14f2fd7 --- /dev/null +++ b/cli/tests/testdata/run/unstable_fs.js @@ -0,0 +1,14 @@ +const scope = import.meta.url.slice(-7) === "#worker" ? "worker" : "main"; + +console.log(scope, Deno.flock); +console.log(scope, Deno.flockSync); +console.log(scope, Deno.funlock); +console.log(scope, Deno.funlockSync); +console.log(scope, Deno.umask); + +if (scope === "worker") { + postMessage("done"); +} else { + const worker = new Worker(`${import.meta.url}#worker`, { type: "module" }); + worker.onmessage = () => Deno.exit(0); +} diff --git a/cli/tests/testdata/run/unstable_http.disabled.out b/cli/tests/testdata/run/unstable_http.disabled.out new file mode 100644 index 0000000000..63a6c83c58 --- /dev/null +++ b/cli/tests/testdata/run/unstable_http.disabled.out @@ -0,0 +1,16 @@ +main undefined +main undefined +main undefined +main undefined +main undefined +main undefined +main undefined +main undefined +worker undefined +worker undefined +worker undefined +worker undefined +worker undefined +worker undefined +worker undefined +worker undefined diff --git a/cli/tests/testdata/run/unstable_http.enabled.out b/cli/tests/testdata/run/unstable_http.enabled.out new file mode 100644 index 0000000000..558f1f5427 --- /dev/null +++ b/cli/tests/testdata/run/unstable_http.enabled.out @@ -0,0 +1,16 @@ +main [class HttpClient] +main [Function: createHttpClient] +main [class HttpConn] +main Symbol("[[associated_ws]]") +main [Function: serve] +main [Function: upgradeHttp] +main [Function: upgradeWebSocket] +main [Function: upgradeHttp] +worker [class HttpClient] +worker [Function: createHttpClient] +worker [class HttpConn] +worker Symbol("[[associated_ws]]") +worker [Function: serve] +worker [Function: upgradeHttp] +worker [Function: upgradeWebSocket] +worker [Function: upgradeHttp] diff --git a/cli/tests/testdata/run/unstable_http.js b/cli/tests/testdata/run/unstable_http.js new file mode 100644 index 0000000000..0125196576 --- /dev/null +++ b/cli/tests/testdata/run/unstable_http.js @@ -0,0 +1,17 @@ +const scope = import.meta.url.slice(-7) === "#worker" ? "worker" : "main"; + +console.log(scope, Deno.HttpClient); +console.log(scope, Deno.createHttpClient); +console.log(scope, Deno.http?.HttpConn); +console.log(scope, Deno.http?._ws); +console.log(scope, Deno.http?.serve); +console.log(scope, Deno.http?.upgradeHttp); +console.log(scope, Deno.http?.upgradeWebSocket); +console.log(scope, Deno.upgradeHttp); + +if (scope === "worker") { + postMessage("done"); +} else { + const worker = new Worker(`${import.meta.url}#worker`, { type: "module" }); + worker.onmessage = () => Deno.exit(0); +} diff --git a/cli/tests/testdata/run/unstable_kv.disabled.out b/cli/tests/testdata/run/unstable_kv.disabled.out new file mode 100644 index 0000000000..0d8ac4410f --- /dev/null +++ b/cli/tests/testdata/run/unstable_kv.disabled.out @@ -0,0 +1,10 @@ +main undefined +main undefined +main undefined +main undefined +main undefined +worker undefined +worker undefined +worker undefined +worker undefined +worker undefined diff --git a/cli/tests/testdata/run/unstable_kv.enabled.out b/cli/tests/testdata/run/unstable_kv.enabled.out new file mode 100644 index 0000000000..a1356cefca --- /dev/null +++ b/cli/tests/testdata/run/unstable_kv.enabled.out @@ -0,0 +1,10 @@ +main [class AtomicOperation] +main [class Kv] +main [class KvListIterator extends Object] +main [class KvU64] +main [AsyncFunction: openKv] +worker [class AtomicOperation] +worker [class Kv] +worker [class KvListIterator extends Object] +worker [class KvU64] +worker [AsyncFunction: openKv] diff --git a/cli/tests/testdata/run/unstable_kv.js b/cli/tests/testdata/run/unstable_kv.js new file mode 100644 index 0000000000..17c0e05aa5 --- /dev/null +++ b/cli/tests/testdata/run/unstable_kv.js @@ -0,0 +1,14 @@ +const scope = import.meta.url.slice(-7) === "#worker" ? "worker" : "main"; + +console.log(scope, Deno.AtomicOperation); +console.log(scope, Deno.Kv); +console.log(scope, Deno.KvListIterator); +console.log(scope, Deno.KvU64); +console.log(scope, Deno.openKv); + +if (scope === "worker") { + postMessage("done"); +} else { + const worker = new Worker(`${import.meta.url}#worker`, { type: "module" }); + worker.onmessage = () => Deno.exit(0); +} diff --git a/cli/tests/testdata/run/unstable_net.disabled.out b/cli/tests/testdata/run/unstable_net.disabled.out new file mode 100644 index 0000000000..3562f72fdd --- /dev/null +++ b/cli/tests/testdata/run/unstable_net.disabled.out @@ -0,0 +1,4 @@ +main undefined +main undefined +worker undefined +worker undefined diff --git a/cli/tests/testdata/run/unstable_net.enabled.out b/cli/tests/testdata/run/unstable_net.enabled.out new file mode 100644 index 0000000000..8b86637f3c --- /dev/null +++ b/cli/tests/testdata/run/unstable_net.enabled.out @@ -0,0 +1,4 @@ +main [Function: listenDatagram] +main [class WebSocketStream] +worker [Function: listenDatagram] +worker [class WebSocketStream] diff --git a/cli/tests/testdata/run/unstable_net.js b/cli/tests/testdata/run/unstable_net.js new file mode 100644 index 0000000000..4492b202b1 --- /dev/null +++ b/cli/tests/testdata/run/unstable_net.js @@ -0,0 +1,11 @@ +const scope = import.meta.url.slice(-7) === "#worker" ? "worker" : "main"; + +console.log(scope, Deno.listenDatagram); +console.log(scope, globalThis.WebSocketStream); + +if (scope === "worker") { + postMessage("done"); +} else { + const worker = new Worker(`${import.meta.url}#worker`, { type: "module" }); + worker.onmessage = () => Deno.exit(0); +} diff --git a/cli/tests/testdata/run/unstable_worker_options.disabled.out b/cli/tests/testdata/run/unstable_worker_options.disabled.out new file mode 100644 index 0000000000..03f189c252 --- /dev/null +++ b/cli/tests/testdata/run/unstable_worker_options.disabled.out @@ -0,0 +1 @@ +Unstable API 'Worker.deno.permissions'. The --unstable flag must be provided. diff --git a/cli/tests/testdata/run/unstable_worker_options.enabled.out b/cli/tests/testdata/run/unstable_worker_options.enabled.out new file mode 100644 index 0000000000..57a52b019a --- /dev/null +++ b/cli/tests/testdata/run/unstable_worker_options.enabled.out @@ -0,0 +1,2 @@ +main ok +worker ok diff --git a/cli/tests/testdata/run/unstable_worker_options.js b/cli/tests/testdata/run/unstable_worker_options.js new file mode 100644 index 0000000000..213eb3ee67 --- /dev/null +++ b/cli/tests/testdata/run/unstable_worker_options.js @@ -0,0 +1,19 @@ +const scope = import.meta.url.slice(-7) === "#worker" ? "worker" : "main"; + +new Worker(`data:application/javascript;base64,${btoa(`postMessage("ok");`)}`, { + type: "module", + deno: { + permissions: { + read: true, + }, + }, +}).onmessage = ({ data }) => { + console.log(scope, data); + + if (scope === "main") { + const worker = new Worker(`${import.meta.url}#worker`, { type: "module" }); + worker.onmessage = () => Deno.exit(0); + } else { + postMessage("done"); + } +}; diff --git a/runtime/js/90_deno_ns.js b/runtime/js/90_deno_ns.js index 834e5d1a3b..83c4a4d03e 100644 --- a/runtime/js/90_deno_ns.js +++ b/runtime/js/90_deno_ns.js @@ -155,64 +155,69 @@ const denoNs = { }; // NOTE(bartlomieju): keep IDs in sync with `cli/main.rs` -const denoNsUnstableById = { - // BroadcastChannel is always available? - // 1: {}, - - 2: { - cron: cron.cron, - }, - - // FFI - 3: { - dlopen: ffi.dlopen, - UnsafeCallback: ffi.UnsafeCallback, - UnsafePointer: ffi.UnsafePointer, - UnsafePointerView: ffi.UnsafePointerView, - UnsafeFnPointer: ffi.UnsafeFnPointer, - }, - - // FS - 4: { - flock: fs.flock, - flockSync: fs.flockSync, - funlock: fs.funlock, - funlockSync: fs.funlockSync, - umask: fs.umask, - }, - - // HTTP - 5: { - HttpClient: httpClient.HttpClient, - createHttpClient: httpClient.createHttpClient, - // TODO(bartlomieju): why is it needed? - http, - upgradeHttp: http.upgradeHttp, - }, - - // KV - 6: { - openKv: kv.openKv, - AtomicOperation: kv.AtomicOperation, - Kv: kv.Kv, - KvU64: kv.KvU64, - KvListIterator: kv.KvListIterator, - }, - - // net - 7: { - listenDatagram: net.createListenDatagram( - ops.op_net_listen_udp, - ops.op_net_listen_unixpacket, - ), - }, - // Unsafe proto - // 8: {}, - - // Worker options - // 9: {} +const unstableIds = { + broadcastChannel: 1, + cron: 2, + ffi: 3, + fs: 4, + http: 5, + kv: 6, + net: 7, + unsafeProto: 8, + workerOptions: 9, }; +const denoNsUnstableById = {}; + +// denoNsUnstableById[unstableIds.broadcastChannel] = {} + +denoNsUnstableById[unstableIds.cron] = { + cron: cron.cron, +}; + +denoNsUnstableById[unstableIds.ffi] = { + dlopen: ffi.dlopen, + UnsafeCallback: ffi.UnsafeCallback, + UnsafePointer: ffi.UnsafePointer, + UnsafePointerView: ffi.UnsafePointerView, + UnsafeFnPointer: ffi.UnsafeFnPointer, +}; + +denoNsUnstableById[unstableIds.fs] = { + flock: fs.flock, + flockSync: fs.flockSync, + funlock: fs.funlock, + funlockSync: fs.funlockSync, + umask: fs.umask, +}; + +denoNsUnstableById[unstableIds.http] = { + HttpClient: httpClient.HttpClient, + createHttpClient: httpClient.createHttpClient, + // TODO(bartlomieju): why is it needed? + http, + upgradeHttp: http.upgradeHttp, +}; + +denoNsUnstableById[unstableIds.kv] = { + openKv: kv.openKv, + AtomicOperation: kv.AtomicOperation, + Kv: kv.Kv, + KvU64: kv.KvU64, + KvListIterator: kv.KvListIterator, +}; + +denoNsUnstableById[unstableIds.net] = { + listenDatagram: net.createListenDatagram( + ops.op_net_listen_udp, + ops.op_net_listen_unixpacket, + ), +}; + +// denoNsUnstableById[unstableIds.unsafeProto] = {} + +// denoNsUnstableById[unstableIds.workerOptions] = {} + // when editing this list, also update unstableDenoProps in cli/tsc/99_main_compiler.js const denoNsUnstable = { listenDatagram: net.createListenDatagram( @@ -242,4 +247,4 @@ const denoNsUnstable = { cron: cron.cron, }; -export { denoNs, denoNsUnstable, denoNsUnstableById }; +export { denoNs, denoNsUnstable, denoNsUnstableById, unstableIds }; diff --git a/runtime/js/98_global_scope.js b/runtime/js/98_global_scope.js index 56354948e5..65a9c69331 100644 --- a/runtime/js/98_global_scope.js +++ b/runtime/js/98_global_scope.js @@ -42,6 +42,7 @@ import * as globalInterfaces from "ext:deno_web/04_global_interfaces.js"; import * as webStorage from "ext:deno_webstorage/01_webstorage.js"; import * as prompt from "ext:runtime/41_prompt.js"; import * as imageData from "ext:deno_web/16_image_data.js"; +import { unstableIds } from "ext:runtime/90_deno_ns.js"; // https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope const windowOrWorkerGlobalScope = { @@ -143,8 +144,11 @@ const windowOrWorkerGlobalScope = { [webidl.brand]: util.nonEnumerable(webidl.brand), }; -const unstableWindowOrWorkerGlobalScope = { +const unstableForWindowOrWorkerGlobalScope = {}; +unstableForWindowOrWorkerGlobalScope[unstableIds.broadcastChannel] = { BroadcastChannel: util.nonEnumerable(broadcastChannel.BroadcastChannel), +}; +unstableForWindowOrWorkerGlobalScope[unstableIds.net] = { WebSocketStream: util.nonEnumerable(webSocketStream.WebSocketStream), }; @@ -312,7 +316,7 @@ const workerRuntimeGlobalProperties = { export { mainRuntimeGlobalProperties, memoizeLazy, - unstableWindowOrWorkerGlobalScope, + unstableForWindowOrWorkerGlobalScope, windowOrWorkerGlobalScope, workerRuntimeGlobalProperties, }; diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js index 22352bf292..0469b38bfc 100644 --- a/runtime/js/99_main.js +++ b/runtime/js/99_main.js @@ -17,8 +17,10 @@ const { ObjectAssign, ObjectDefineProperties, ObjectDefineProperty, + ObjectKeys, ObjectPrototypeIsPrototypeOf, ObjectSetPrototypeOf, + ObjectValues, PromisePrototypeThen, PromiseResolve, Symbol, @@ -47,6 +49,7 @@ import { denoNs, denoNsUnstable, denoNsUnstableById, + unstableIds, } from "ext:runtime/90_deno_ns.js"; import { errors } from "ext:runtime/01_errors.js"; import * as webidl from "ext:deno_webidl/00_webidl.js"; @@ -54,7 +57,7 @@ import DOMException from "ext:deno_web/01_dom_exception.js"; import { mainRuntimeGlobalProperties, memoizeLazy, - unstableWindowOrWorkerGlobalScope, + unstableForWindowOrWorkerGlobalScope, windowOrWorkerGlobalScope, workerRuntimeGlobalProperties, } from "ext:runtime/98_global_scope.js"; @@ -370,6 +373,35 @@ let hasBootstrapped = false; delete globalThis.console; // Set up global properties shared by main and worker runtime. ObjectDefineProperties(globalThis, windowOrWorkerGlobalScope); + +// Set up global properties shared by main and worker runtime that are exposed +// by unstable features if those are enabled. +function exposeUnstableFeaturesForWindowOrWorkerGlobalScope(options) { + const { unstableFlag, unstableFeatures } = options; + if (unstableFlag) { + const all = ObjectValues(unstableForWindowOrWorkerGlobalScope); + for (let i = 0; i <= all.length; i++) { + const props = all[i]; + ObjectDefineProperties(globalThis, { ...props }); + } + } else { + const featureIds = ArrayPrototypeMap( + ObjectKeys( + unstableForWindowOrWorkerGlobalScope, + ), + (k) => k | 0, + ); + + for (let i = 0; i <= featureIds.length; i++) { + const featureId = featureIds[i]; + if (ArrayPrototypeIncludes(unstableFeatures, featureId)) { + const props = unstableForWindowOrWorkerGlobalScope[featureId]; + ObjectDefineProperties(globalThis, { ...props }); + } + } + } +} + // FIXME(bartlomieju): temporarily add whole `Deno.core` to // `Deno[Deno.internal]` namespace. It should be removed and only necessary // methods should be left there. @@ -430,9 +462,10 @@ function bootstrapMainRuntime(runtimeOptions) { location.setLocationHref(location_); } - if (unstableFlag) { - ObjectDefineProperties(globalThis, unstableWindowOrWorkerGlobalScope); - } + exposeUnstableFeaturesForWindowOrWorkerGlobalScope({ + unstableFlag, + unstableFeatures, + }); ObjectDefineProperties(globalThis, mainRuntimeGlobalProperties); ObjectDefineProperties(globalThis, { // TODO(bartlomieju): in the future we might want to change the @@ -501,7 +534,7 @@ function bootstrapMainRuntime(runtimeOptions) { } } - if (!ArrayPrototypeIncludes(unstableFeatures, /* unsafe-proto */ 8)) { + if (!ArrayPrototypeIncludes(unstableFeatures, unstableIds.unsafeProto)) { // Removes the `__proto__` for security reasons. // https://tc39.es/ecma262/#sec-get-object.prototype.__proto__ delete Object.prototype.__proto__; @@ -547,9 +580,10 @@ function bootstrapWorkerRuntime( delete globalThis.nodeBootstrap; hasBootstrapped = true; - if (unstableFlag) { - ObjectDefineProperties(globalThis, unstableWindowOrWorkerGlobalScope); - } + exposeUnstableFeaturesForWindowOrWorkerGlobalScope({ + unstableFlag, + unstableFeatures, + }); ObjectDefineProperties(globalThis, workerRuntimeGlobalProperties); ObjectDefineProperties(globalThis, { name: util.writable(name), @@ -604,7 +638,7 @@ function bootstrapWorkerRuntime( } } - if (!ArrayPrototypeIncludes(unstableFeatures, /* unsafe-proto */ 8)) { + if (!ArrayPrototypeIncludes(unstableFeatures, unstableIds.unsafeProto)) { // Removes the `__proto__` for security reasons. // https://tc39.es/ecma262/#sec-get-object.prototype.__proto__ delete Object.prototype.__proto__;