0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 17:34:47 -05:00

refactor: Use ES modules for internal runtime code (#17648)

This PR refactors all internal js files (except core) to be written as
ES modules.
`__bootstrap`has been mostly replaced with static imports in form in
`internal:[path to file from repo root]`.
To specify if files are ESM, an `esm` method has been added to
`Extension`, similar to the `js` method.
A new ModuleLoader called `InternalModuleLoader` has been added to
enable the loading of internal specifiers, which is used in all
situations except when a snapshot is only loaded, and not a new one is
created from it.

---------

Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
This commit is contained in:
Leo Kettmeir 2023-02-07 20:22:46 +01:00 committed by GitHub
parent 65500f36e8
commit b4aa153097
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
123 changed files with 41574 additions and 41713 deletions

View file

@ -10,6 +10,9 @@ use crate::profiling::is_profiling;
pub fn create_js_runtime(setup: impl FnOnce() -> Vec<Extension>) -> JsRuntime {
JsRuntime::new(RuntimeOptions {
extensions_with_js: setup(),
module_loader: Some(std::rc::Rc::new(
deno_core::InternalModuleLoader::new(None),
)),
..Default::default()
})
}

View file

@ -275,6 +275,7 @@ mod ts {
.build()],
extensions_with_js: vec![],
additional_files: files,
additional_esm_files: vec![],
compression_cb: Some(Box::new(|vec, snapshot_slice| {
vec.extend_from_slice(
&zstd::bulk::compress(snapshot_slice, 22)
@ -306,7 +307,7 @@ mod ts {
}
}
fn create_cli_snapshot(snapshot_path: PathBuf, files: Vec<PathBuf>) {
fn create_cli_snapshot(snapshot_path: PathBuf, esm_files: Vec<PathBuf>) {
let extensions: Vec<Extension> = vec![
deno_webidl::init(),
deno_console::init(),
@ -343,7 +344,8 @@ fn create_cli_snapshot(snapshot_path: PathBuf, files: Vec<PathBuf>) {
startup_snapshot: Some(deno_runtime::js::deno_isolate_init()),
extensions,
extensions_with_js: vec![],
additional_files: files,
additional_files: vec![],
additional_esm_files: esm_files,
compression_cb: Some(Box::new(|vec, snapshot_slice| {
lzzzz::lz4_hc::compress_to_vec(
snapshot_slice,
@ -448,13 +450,13 @@ fn main() {
let o = PathBuf::from(env::var_os("OUT_DIR").unwrap());
let compiler_snapshot_path = o.join("COMPILER_SNAPSHOT.bin");
let js_files = get_js_files(env!("CARGO_MANIFEST_DIR"), "tsc");
let js_files = get_js_files(env!("CARGO_MANIFEST_DIR"), "tsc", None);
ts::create_compiler_snapshot(compiler_snapshot_path, js_files, &c);
let cli_snapshot_path = o.join("CLI_SNAPSHOT.bin");
let mut js_files = get_js_files(env!("CARGO_MANIFEST_DIR"), "js");
js_files.push(deno_runtime::js::get_99_main());
create_cli_snapshot(cli_snapshot_path, js_files);
let mut esm_files = get_js_files(env!("CARGO_MANIFEST_DIR"), "js", None);
esm_files.push(deno_runtime::js::get_99_main());
create_cli_snapshot(cli_snapshot_path, esm_files);
#[cfg(target_os = "windows")]
{

View file

@ -1,14 +1,14 @@
// Copyright 2018-2023 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 {
const core = globalThis.Deno.core;
const ops = core.ops;
const internals = globalThis.__bootstrap.internals;
import { setExitHandler } from "internal:runtime/js/30_os.js";
import { Console } from "internal:ext/console/02_console.js";
import { serializePermissions } from "internal:runtime/js/10_permissions.js";
import { assert } from "internal:ext/web/00_infra.js";
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayFrom,
ArrayPrototypeFilter,
ArrayPrototypeJoin,
@ -33,36 +33,36 @@
Set,
SymbolToStringTag,
TypeError,
} = window.__bootstrap.primordials;
} = primordials;
const opSanitizerDelayResolveQueue = [];
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() {
// 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() {
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 = {
// 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"],
@ -132,14 +132,14 @@
"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) {
// 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();
@ -232,9 +232,9 @@
throw assert(false, msg);
};
}
}
function prettyResourceNames(name) {
function prettyResourceNames(name) {
switch (name) {
case "fsFile":
return ["A file", "opened", "closed"];
@ -299,9 +299,9 @@
default:
return [`A "${name}" resource`, "created", "cleaned up"];
}
}
}
function resourceCloseHint(name) {
function resourceCloseHint(name) {
switch (name) {
case "fsFile":
return "Close the file handle by calling `file.close()`.";
@ -366,12 +366,12 @@
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) {
// 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();
@ -416,11 +416,11 @@
`;
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) {
// 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(
@ -439,9 +439,9 @@
setExitHandler(null);
}
};
}
}
function assertTestStepScopes(fn) {
function assertTestStepScopes(fn) {
/** @param desc {TestDescription | TestStepDescription} */
return async function testStepSanitizer(desc) {
preValidation();
@ -495,9 +495,9 @@
}
}
};
}
}
function testStepPostValidation(desc) {
function testStepPostValidation(desc) {
// check for any running steps
for (const childDesc of MapPrototypeGet(testStates, desc.id).children) {
if (MapPrototypeGet(testStates, childDesc.id).status == "pending") {
@ -517,19 +517,19 @@
}
currentDesc = currentDesc.parent;
}
}
}
function pledgePermissions(permissions) {
function pledgePermissions(permissions) {
return ops.op_pledge_test_permissions(
serializePermissions(permissions),
);
}
}
function restorePermissions(token) {
function restorePermissions(token) {
ops.op_restore_test_permissions(token);
}
}
function withPermissions(fn, permissions) {
function withPermissions(fn, permissions) {
return async function applyPermissions(...params) {
const token = pledgePermissions(permissions);
@ -539,9 +539,9 @@
restorePermissions(token);
}
};
}
}
/**
/**
* @typedef {{
* id: number,
* name: string,
@ -603,21 +603,21 @@
* }} BenchDescription
*/
/** @type {TestDescription[]} */
const testDescs = [];
/** @type {Map<number, TestState | TestStepState>} */
const testStates = new Map();
/** @type {BenchDescription[]} */
const benchDescs = [];
let isTestSubcommand = false;
let isBenchSubcommand = false;
/** @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(
// Main test function provided by Deno.
function test(
nameOrFnOrOptions,
optionsOrFn,
maybeFn,
) {
) {
if (!isTestSubcommand) {
return;
}
@ -729,14 +729,14 @@
children: [],
finalized: false,
});
}
}
// Main bench function provided by Deno.
function bench(
// Main bench function provided by Deno.
function bench(
nameOrFnOrOptions,
optionsOrFn,
maybeFn,
) {
) {
if (!isBenchSubcommand) {
return;
}
@ -829,9 +829,9 @@
benchDesc.filteredOut = filteredOut;
ArrayPrototypePush(benchDescs, benchDesc);
}
}
async function runTest(desc) {
async function runTest(desc) {
if (desc.ignore) {
return "ignored";
}
@ -858,16 +858,16 @@
stepReportResult(childDesc);
}
}
}
}
function compareMeasurements(a, b) {
function compareMeasurements(a, b) {
if (a > b) return 1;
if (a < b) return -1;
return 0;
}
}
function benchStats(n, highPrecision, avg, min, max, all) {
function benchStats(n, highPrecision, avg, min, max, all) {
return {
n,
min,
@ -878,9 +878,9 @@
p999: all[MathCeil(n * (99.9 / 100)) - 1],
avg: !highPrecision ? (avg / n) : MathCeil(avg / n),
};
}
}
async function benchMeasure(timeBudget, desc) {
async function benchMeasure(timeBudget, desc) {
const fn = desc.fn;
let n = 0;
let avg = 0;
@ -990,9 +990,9 @@
all.sort(compareMeasurements);
return benchStats(n, wavg > lowPrecisionThresholdInNs, avg, min, max, all);
}
}
async function runBench(desc) {
async function runBench(desc) {
let token = null;
try {
@ -1019,39 +1019,39 @@
if (bench.sanitizeExit) setExitHandler(null);
if (token !== null) restorePermissions(token);
}
}
}
let origin = null;
let origin = null;
function getTestOrigin() {
function getTestOrigin() {
if (origin == null) {
origin = ops.op_get_test_origin();
}
return origin;
}
}
function getBenchOrigin() {
function getBenchOrigin() {
if (origin == null) {
origin = ops.op_get_bench_origin();
}
return origin;
}
}
function benchNow() {
function benchNow() {
return ops.op_bench_now();
}
}
function enableTest() {
function enableTest() {
isTestSubcommand = true;
}
}
function enableBench() {
function enableBench() {
isBenchSubcommand = true;
}
}
async function runTests({
async function runTests({
shuffle = null,
} = {}) {
} = {}) {
core.setMacrotaskCallback(handleOpSanitizerDelayMacrotask);
const origin = getTestOrigin();
@ -1101,9 +1101,9 @@
result: [desc.id, result, elapsed],
});
}
}
}
async function runBenchmarks() {
async function runBenchmarks() {
core.setMacrotaskCallback(handleOpSanitizerDelayMacrotask);
const origin = getBenchOrigin();
@ -1152,20 +1152,20 @@
}
globalThis.console = originalConsole;
}
}
function getFullName(desc) {
function getFullName(desc) {
if ("parent" in desc) {
return `${desc.parent.name} > ${desc.name}`;
}
return desc.name;
}
}
function usesSanitizer(desc) {
function usesSanitizer(desc) {
return desc.sanitizeResources || desc.sanitizeOps || desc.sanitizeExit;
}
}
function canStreamReporting(desc) {
function canStreamReporting(desc) {
let currentDesc = desc;
while (currentDesc != null) {
if (!usesSanitizer(currentDesc)) {
@ -1180,18 +1180,18 @@
}
}
return true;
}
}
function stepReportWait(desc) {
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) {
function stepReportResult(desc) {
const state = MapPrototypeGet(testStates, desc.id);
if (state.reportedResult) {
return;
@ -1212,29 +1212,29 @@
stepResult: [desc.id, result, state.elapsed],
});
state.reportedResult = true;
}
}
function failedChildStepsCount(desc) {
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
/** If a test validation error already occurred then don't bother checking
* the sanitizers as that will create extra noise.
*/
function shouldSkipSanitizers(desc) {
function shouldSkipSanitizers(desc) {
try {
testStepPostValidation(desc);
return false;
} catch {
return true;
}
}
}
/** @param desc {TestDescription | TestStepDescription} */
function createTestContext(desc) {
/** @param desc {TestDescription | TestStepDescription} */
function createTestContext(desc) {
let parent;
let level;
let rootId;
@ -1390,9 +1390,9 @@
}
},
};
}
}
/**
/**
* @template T {Function}
* @param testFn {T}
* @param opts {{
@ -1402,7 +1402,7 @@
* }}
* @returns {T}
*/
function wrapTestFnWithSanitizers(testFn, opts) {
function wrapTestFnWithSanitizers(testFn, opts) {
testFn = assertTestStepScopes(testFn);
if (opts.sanitizeOps) {
@ -1415,18 +1415,15 @@
testFn = assertExit(testFn, true);
}
return testFn;
}
}
window.__bootstrap.internals = {
...window.__bootstrap.internals ?? {},
testing: {
internals.testing = {
runTests,
runBenchmarks,
enableTest,
enableBench,
},
};
};
window.__bootstrap.denoNs.bench = bench;
window.__bootstrap.denoNs.test = test;
})(this);
import { denoNs } from "internal:runtime/js/90_deno_ns.js";
denoNs.bench = bench;
denoNs.test = test;

View file

@ -3844,3 +3844,15 @@ itest!(node_prefix_missing {
envs: env_vars_for_npm_tests_no_sync_download(),
exit_code: 1,
});
itest!(internal_import {
args: "run run/internal_import.ts",
output: "run/internal_import.ts.out",
exit_code: 1,
});
itest!(internal_dynamic_import {
args: "run run/internal_dynamic_import.ts",
output: "run/internal_dynamic_import.ts.out",
exit_code: 1,
});

View file

@ -1,5 +1,4 @@
1
queueMicrotask
error: Uncaught Error: bar
throw new Error("bar");
^

View file

@ -0,0 +1 @@
await import("internal:runtime/js/01_build.js");

View file

@ -0,0 +1,4 @@
error: Uncaught TypeError: Cannot load internal module from external code
await import("internal:runtime/js/01_build.js");
^
at [WILDCARD]/internal_dynamic_import.ts:1:1

View file

@ -0,0 +1 @@
import "internal:runtime/js/01_build.js";

View file

@ -0,0 +1,8 @@
error: Unsupported scheme "internal" for module "internal:runtime/js/01_build.js". Supported schemes: [
"data",
"blob",
"file",
"http",
"https",
]
at [WILDCARD]

View file

@ -427,6 +427,8 @@
});
ObjectAssign(globalThis.__bootstrap, { core });
const internals = {};
ObjectAssign(globalThis.__bootstrap, { internals });
ObjectAssign(globalThis.Deno, { core });
// Direct bindings on `globalThis`

View file

@ -267,9 +267,11 @@ pub fn host_import_module_dynamically_callback<'s>(
.unwrap()
.to_rust_string_lossy(scope);
let is_internal_module = specifier_str.starts_with("internal:");
let resolver = v8::PromiseResolver::new(scope).unwrap();
let promise = resolver.get_promise(scope);
if !is_internal_module {
let assertions = parse_import_assertions(
scope,
import_assertions,
@ -305,7 +307,7 @@ pub fn host_import_module_dynamically_callback<'s>(
);
state_rc.borrow_mut().notify_new_dynamic_import();
}
}
// Map errors from module resolution (not JS errors from module execution) to
// ones rethrown from this scope, so they include the call stack of the
// dynamic import site. Error objects without any stack frames are assumed to
@ -317,6 +319,14 @@ pub fn host_import_module_dynamically_callback<'s>(
let promise = promise.catch(scope, map_err).unwrap();
if is_internal_module {
let message =
v8::String::new(scope, "Cannot load internal module from external code")
.unwrap();
let exception = v8::Exception::type_error(scope, message);
resolver.reject(scope, exception);
}
Some(promise)
}

View file

@ -38,6 +38,7 @@ impl OpDecl {
#[derive(Default)]
pub struct Extension {
js_files: Option<Vec<SourcePair>>,
esm_files: Option<Vec<SourcePair>>,
ops: Option<Vec<OpDecl>>,
opstate_fn: Option<Box<OpStateFn>>,
middleware_fn: Option<Box<OpMiddlewareFn>>,
@ -81,13 +82,20 @@ impl Extension {
/// returns JS source code to be loaded into the isolate (either at snapshotting,
/// or at startup). as a vector of a tuple of the file name, and the source code.
pub fn init_js(&self) -> &[SourcePair] {
pub fn get_js_sources(&self) -> &[SourcePair] {
match &self.js_files {
Some(files) => files,
None => &[],
}
}
pub fn get_esm_sources(&self) -> &[SourcePair] {
match &self.esm_files {
Some(files) => files,
None => &[],
}
}
/// Called at JsRuntime startup to initialize ops in the isolate.
pub fn init_ops(&mut self) -> Option<Vec<OpDecl>> {
// TODO(@AaronO): maybe make op registration idempotent
@ -145,6 +153,7 @@ impl Extension {
#[derive(Default)]
pub struct ExtensionBuilder {
js: Vec<SourcePair>,
esm: Vec<SourcePair>,
ops: Vec<OpDecl>,
state: Option<Box<OpStateFn>>,
middleware: Option<Box<OpMiddlewareFn>>,
@ -164,6 +173,11 @@ impl ExtensionBuilder {
self
}
pub fn esm(&mut self, js_files: Vec<SourcePair>) -> &mut Self {
self.esm.extend(js_files);
self
}
pub fn ops(&mut self, ops: Vec<OpDecl>) -> &mut Self {
self.ops.extend(ops);
self
@ -195,10 +209,12 @@ impl ExtensionBuilder {
pub fn build(&mut self) -> Extension {
let js_files = Some(std::mem::take(&mut self.js));
let esm_files = Some(std::mem::take(&mut self.esm));
let ops = Some(std::mem::take(&mut self.ops));
let deps = Some(std::mem::take(&mut self.deps));
Extension {
js_files,
esm_files,
ops,
opstate_fn: self.state.take(),
middleware_fn: self.middleware.take(),

View file

@ -73,6 +73,7 @@ pub use crate::module_specifier::ModuleResolutionError;
pub use crate::module_specifier::ModuleSpecifier;
pub use crate::module_specifier::DUMMY_SPECIFIER;
pub use crate::modules::FsModuleLoader;
pub use crate::modules::InternalModuleLoader;
pub use crate::modules::ModuleId;
pub use crate::modules::ModuleLoader;
pub use crate::modules::ModuleSource;

View file

@ -292,6 +292,69 @@ impl ModuleLoader for NoopModuleLoader {
}
}
pub struct InternalModuleLoader(Rc<dyn ModuleLoader>);
impl InternalModuleLoader {
pub fn new(module_loader: Option<Rc<dyn ModuleLoader>>) -> Self {
InternalModuleLoader(
module_loader.unwrap_or_else(|| Rc::new(NoopModuleLoader)),
)
}
}
impl ModuleLoader for InternalModuleLoader {
fn resolve(
&self,
specifier: &str,
referrer: &str,
kind: ResolutionKind,
) -> Result<ModuleSpecifier, Error> {
if let Ok(url_specifier) = ModuleSpecifier::parse(specifier) {
if url_specifier.scheme() == "internal" {
let referrer_specifier = ModuleSpecifier::parse(referrer).ok();
if referrer == "." || referrer_specifier.unwrap().scheme() == "internal"
{
return Ok(url_specifier);
} else {
return Err(generic_error(
"Cannot load internal module from external code",
));
};
}
}
self.0.resolve(specifier, referrer, kind)
}
fn load(
&self,
module_specifier: &ModuleSpecifier,
maybe_referrer: Option<ModuleSpecifier>,
is_dyn_import: bool,
) -> Pin<Box<ModuleSourceFuture>> {
self.0.load(module_specifier, maybe_referrer, is_dyn_import)
}
fn prepare_load(
&self,
op_state: Rc<RefCell<OpState>>,
module_specifier: &ModuleSpecifier,
maybe_referrer: Option<String>,
is_dyn_import: bool,
) -> Pin<Box<dyn Future<Output = Result<(), Error>>>> {
if module_specifier.scheme() == "internal" {
return async { Ok(()) }.boxed_local();
}
self.0.prepare_load(
op_state,
module_specifier,
maybe_referrer,
is_dyn_import,
)
}
}
/// Basic file system module loader.
///
/// Note that this loader will **block** event loop
@ -2508,4 +2571,33 @@ if (import.meta.url != 'file:///main_with_code.js') throw Error();
)
.unwrap();
}
#[test]
fn internal_module_loader() {
let loader = InternalModuleLoader::new(None);
assert!(loader
.resolve("internal:foo", "internal:bar", ResolutionKind::Import)
.is_ok());
assert_eq!(
loader
.resolve("internal:foo", "file://bar", ResolutionKind::Import)
.err()
.map(|e| e.to_string()),
Some("Cannot load internal module from external code".to_string())
);
assert_eq!(
loader
.resolve("file://foo", "file://bar", ResolutionKind::Import)
.err()
.map(|e| e.to_string()),
Some("Module loading is not supported".to_string())
);
assert_eq!(
loader
.resolve("file://foo", "internal:bar", ResolutionKind::Import)
.err()
.map(|e| e.to_string()),
Some("Module loading is not supported".to_string())
);
}
}

View file

@ -13,17 +13,18 @@ use crate::modules::ModuleId;
use crate::modules::ModuleLoadId;
use crate::modules::ModuleLoader;
use crate::modules::ModuleMap;
use crate::modules::NoopModuleLoader;
use crate::op_void_async;
use crate::op_void_sync;
use crate::ops::*;
use crate::source_map::SourceMapCache;
use crate::source_map::SourceMapGetter;
use crate::Extension;
use crate::NoopModuleLoader;
use crate::OpMiddlewareFn;
use crate::OpResult;
use crate::OpState;
use crate::PromiseId;
use anyhow::Context as AnyhowContext;
use anyhow::Error;
use futures::channel::oneshot;
use futures::future::poll_fn;
@ -605,9 +606,16 @@ impl JsRuntime {
None
};
let loader = options
let loader = if snapshot_options != SnapshotOptions::Load {
Rc::new(crate::modules::InternalModuleLoader::new(
options.module_loader,
))
} else {
options
.module_loader
.unwrap_or_else(|| Rc::new(NoopModuleLoader));
.unwrap_or_else(|| Rc::new(NoopModuleLoader))
};
{
let mut state = state_rc.borrow_mut();
state.global_realm = Some(JsRealm(global_context.clone()));
@ -805,12 +813,32 @@ impl JsRuntime {
// Take extensions to avoid double-borrow
let extensions = std::mem::take(&mut self.extensions_with_js);
for ext in &extensions {
let js_files = ext.init_js();
{
let js_files = ext.get_esm_sources();
for (filename, source) in js_files {
futures::executor::block_on(async {
let id = self
.load_side_module(
&ModuleSpecifier::parse(filename)?,
Some(source.to_string()),
)
.await?;
let receiver = self.mod_evaluate(id);
self.run_event_loop(false).await?;
receiver.await?
})
.with_context(|| format!("Couldn't execute '{filename}'"))?;
}
}
{
let js_files = ext.get_js_sources();
for (filename, source) in js_files {
// TODO(@AaronO): use JsRuntime::execute_static() here to move src off heap
realm.execute_script(self.v8_isolate(), filename, source)?;
}
}
}
// Restore extensions
self.extensions_with_js = extensions;

View file

@ -1,10 +1,12 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use anyhow::Context;
use std::path::Path;
use std::path::PathBuf;
use crate::Extension;
use crate::JsRuntime;
use crate::ModuleSpecifier;
use crate::RuntimeOptions;
use crate::Snapshot;
@ -17,6 +19,7 @@ pub struct CreateSnapshotOptions {
pub extensions: Vec<Extension>,
pub extensions_with_js: Vec<Extension>,
pub additional_files: Vec<PathBuf>,
pub additional_esm_files: Vec<PathBuf>,
pub compression_cb: Option<Box<CompressionCb>>,
}
@ -44,6 +47,27 @@ pub fn create_snapshot(create_snapshot_options: CreateSnapshotOptions) {
)
.unwrap();
}
for file in create_snapshot_options.additional_esm_files {
let display_path = file.strip_prefix(display_root).unwrap_or(&file);
let display_path_str = display_path.display().to_string();
let filename =
&("internal:".to_string() + &display_path_str.replace('\\', "/"));
futures::executor::block_on(async {
let id = js_runtime
.load_side_module(
&ModuleSpecifier::parse(filename)?,
Some(std::fs::read_to_string(&file)?),
)
.await?;
let receiver = js_runtime.mod_evaluate(id);
js_runtime.run_event_loop(false).await?;
receiver.await?
})
.with_context(|| format!("Couldn't execute '{}'", file.display()))
.unwrap();
}
let snapshot = js_runtime.snapshot();
let snapshot_slice: &[u8] = &snapshot;
@ -79,9 +103,12 @@ pub fn create_snapshot(create_snapshot_options: CreateSnapshotOptions) {
);
}
pub type FilterFn = Box<dyn Fn(&PathBuf) -> bool>;
pub fn get_js_files(
cargo_manifest_dir: &'static str,
directory: &str,
filter: Option<FilterFn>,
) -> Vec<PathBuf> {
let manifest_dir = Path::new(cargo_manifest_dir);
let mut js_files = std::fs::read_dir(directory)
@ -92,7 +119,7 @@ pub fn get_js_files(
})
.filter(|path| {
path.extension().unwrap_or_default() == "js"
&& !path.ends_with("99_main.js")
&& filter.as_ref().map(|filter| filter(path)).unwrap_or(true)
})
.collect::<Vec<PathBuf>>();
js_files.sort();

View file

@ -2,31 +2,31 @@
/// <reference path="../../core/internal.d.ts" />
"use strict";
((window) => {
const core = window.Deno.core;
const ops = core.ops;
const webidl = window.__bootstrap.webidl;
const { MessageEvent, defineEventHandler, setTarget } =
window.__bootstrap.event;
const { EventTarget } = window.__bootstrap.eventTarget;
const { DOMException } = window.__bootstrap.domException;
const {
const core = globalThis.Deno.core;
const ops = core.ops;
import * as webidl from "internal:ext/webidl/00_webidl.js";
import {
defineEventHandler,
EventTarget,
setTarget,
} from "internal:ext/web/02_event.js";
import DOMException from "internal:ext/web/01_dom_exception.js";
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayPrototypeIndexOf,
ArrayPrototypeSplice,
ArrayPrototypePush,
Symbol,
Uint8Array,
} = window.__bootstrap.primordials;
} = primordials;
const _name = Symbol("[[name]]");
const _closed = Symbol("[[closed]]");
const _name = Symbol("[[name]]");
const _closed = Symbol("[[closed]]");
const channels = [];
let rid = null;
const channels = [];
let rid = null;
async function recv() {
async function recv() {
while (channels.length > 0) {
const message = await core.opAsync("op_broadcast_recv", rid);
@ -40,9 +40,9 @@
core.close(rid);
rid = null;
}
}
function dispatch(source, name, data) {
function dispatch(source, name, data) {
for (let i = 0; i < channels.length; ++i) {
const channel = channels[i];
@ -62,16 +62,16 @@
defer(go);
}
}
}
// Defer to avoid starving the event loop. Not using queueMicrotask()
// for that reason: it lets promises make forward progress but can
// still starve other parts of the event loop.
function defer(go) {
// Defer to avoid starving the event loop. Not using queueMicrotask()
// for that reason: it lets promises make forward progress but can
// still starve other parts of the event loop.
function defer(go) {
setTimeout(go, 1);
}
}
class BroadcastChannel extends EventTarget {
class BroadcastChannel extends EventTarget {
[_name];
[_closed] = false;
@ -141,11 +141,10 @@
ops.op_broadcast_unsubscribe(rid);
}
}
}
}
defineEventHandler(BroadcastChannel.prototype, "message");
defineEventHandler(BroadcastChannel.prototype, "messageerror");
const BroadcastChannelPrototype = BroadcastChannel.prototype;
defineEventHandler(BroadcastChannel.prototype, "message");
defineEventHandler(BroadcastChannel.prototype, "messageerror");
const BroadcastChannelPrototype = BroadcastChannel.prototype;
window.__bootstrap.broadcastChannel = { BroadcastChannel };
})(this);
export { BroadcastChannel };

View file

@ -112,7 +112,7 @@ pub fn init<BC: BroadcastChannel + 'static>(
) -> Extension {
Extension::builder(env!("CARGO_PKG_NAME"))
.dependencies(vec!["deno_webidl", "deno_web"])
.js(include_js_files!(
.esm(include_js_files!(
prefix "internal:ext/broadcast_channel",
"01_broadcast_channel.js",
))

64
ext/cache/01_cache.js vendored
View file

@ -1,25 +1,24 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
"use strict";
((window) => {
const core = window.__bootstrap.core;
const webidl = window.__bootstrap.webidl;
const {
const core = globalThis.Deno.core;
import * as webidl from "internal:ext/webidl/00_webidl.js";
const primordials = globalThis.__bootstrap.primordials;
const {
Symbol,
TypeError,
ObjectPrototypeIsPrototypeOf,
} = window.__bootstrap.primordials;
const {
} = primordials;
import {
Request,
toInnerResponse,
RequestPrototype,
toInnerRequest,
} = window.__bootstrap.fetch;
const { URLPrototype } = window.__bootstrap.url;
const RequestPrototype = Request.prototype;
const { getHeader } = window.__bootstrap.headers;
const { readableStreamForRid } = window.__bootstrap.streams;
} from "internal:ext/fetch/23_request.js";
import { toInnerResponse } from "internal:ext/fetch/23_response.js";
import { URLPrototype } from "internal:ext/url/00_url.js";
import { getHeader } from "internal:ext/fetch/20_headers.js";
import { readableStreamForRid } from "internal:ext/web/06_streams.js";
class CacheStorage {
class CacheStorage {
constructor() {
webidl.illegalConstructor();
}
@ -59,12 +58,12 @@
});
return await core.opAsync("op_cache_storage_delete", cacheName);
}
}
}
const _matchAll = Symbol("[[matchAll]]");
const _id = Symbol("id");
const _matchAll = Symbol("[[matchAll]]");
const _id = Symbol("id");
class Cache {
class Cache {
/** @type {number} */
[_id];
@ -275,22 +274,19 @@
return responses;
}
}
}
webidl.configurePrototype(CacheStorage);
webidl.configurePrototype(Cache);
const CacheStoragePrototype = CacheStorage.prototype;
const CachePrototype = Cache.prototype;
webidl.configurePrototype(CacheStorage);
webidl.configurePrototype(Cache);
const CacheStoragePrototype = CacheStorage.prototype;
const CachePrototype = Cache.prototype;
let cacheStorage;
window.__bootstrap.caches = {
CacheStorage,
Cache,
cacheStorage() {
if (!cacheStorage) {
cacheStorage = webidl.createBranded(CacheStorage);
let cacheStorageStorage;
function cacheStorage() {
if (!cacheStorageStorage) {
cacheStorageStorage = webidl.createBranded(CacheStorage);
}
return cacheStorage;
},
};
})(this);
return cacheStorageStorage;
}
export { Cache, CacheStorage, cacheStorage };

2
ext/cache/lib.rs vendored
View file

@ -27,7 +27,7 @@ pub fn init<CA: Cache + 'static>(
) -> Extension {
Extension::builder(env!("CARGO_PKG_NAME"))
.dependencies(vec!["deno_webidl", "deno_web", "deno_url", "deno_fetch"])
.js(include_js_files!(
.esm(include_js_files!(
prefix "internal:ext/cache",
"01_cache.js",
))

View file

@ -2,110 +2,107 @@
/// <reference path="../../core/internal.d.ts" />
"use strict";
((window) => {
const {
const primordials = globalThis.__bootstrap.primordials;
const {
RegExp,
StringPrototypeReplace,
ArrayPrototypeJoin,
} = window.__bootstrap.primordials;
} = primordials;
let noColor = false;
let noColor = false;
function setNoColor(value) {
function setNoColor(value) {
noColor = value;
}
}
function getNoColor() {
function getNoColor() {
return noColor;
}
}
function code(open, close) {
function code(open, close) {
return {
open: `\x1b[${open}m`,
close: `\x1b[${close}m`,
regexp: new RegExp(`\\x1b\\[${close}m`, "g"),
};
}
}
function run(str, code) {
function run(str, code) {
return `${code.open}${
StringPrototypeReplace(str, code.regexp, code.open)
}${code.close}`;
}
}
function bold(str) {
function bold(str) {
return run(str, code(1, 22));
}
}
function italic(str) {
function italic(str) {
return run(str, code(3, 23));
}
}
function yellow(str) {
function yellow(str) {
return run(str, code(33, 39));
}
}
function cyan(str) {
function cyan(str) {
return run(str, code(36, 39));
}
}
function red(str) {
function red(str) {
return run(str, code(31, 39));
}
}
function green(str) {
function green(str) {
return run(str, code(32, 39));
}
}
function bgRed(str) {
function bgRed(str) {
return run(str, code(41, 49));
}
}
function white(str) {
function white(str) {
return run(str, code(37, 39));
}
}
function gray(str) {
function gray(str) {
return run(str, code(90, 39));
}
}
function magenta(str) {
function magenta(str) {
return run(str, code(35, 39));
}
}
// https://github.com/chalk/ansi-regex/blob/02fa893d619d3da85411acc8fd4e2eea0e95a9d9/index.js
const ANSI_PATTERN = new RegExp(
// https://github.com/chalk/ansi-regex/blob/02fa893d619d3da85411acc8fd4e2eea0e95a9d9/index.js
const ANSI_PATTERN = new RegExp(
ArrayPrototypeJoin([
"[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)",
"(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))",
], "|"),
"g",
);
);
function stripColor(string) {
function stripColor(string) {
return StringPrototypeReplace(string, ANSI_PATTERN, "");
}
}
function maybeColor(fn) {
function maybeColor(fn) {
return !noColor ? fn : (s) => s;
}
}
window.__bootstrap.colors = {
bold,
italic,
yellow,
cyan,
red,
green,
export {
bgRed,
white,
gray,
magenta,
stripColor,
maybeColor,
setNoColor,
bold,
cyan,
getNoColor,
};
})(this);
gray,
green,
italic,
magenta,
maybeColor,
red,
setNoColor,
stripColor,
white,
yellow,
};

View file

@ -2,12 +2,10 @@
/// <reference path="../../core/internal.d.ts" />
"use strict";
((window) => {
const core = window.Deno.core;
const colors = window.__bootstrap.colors;
const {
const core = globalThis.Deno.core;
const internals = globalThis.__bootstrap.internals;
const primordials = globalThis.__bootstrap.primordials;
const {
AggregateErrorPrototype,
ArrayPrototypeUnshift,
isNaN,
@ -117,20 +115,21 @@
TypedArrayPrototypeGetSymbolToStringTag,
WeakMapPrototype,
WeakSetPrototype,
} = window.__bootstrap.primordials;
} = primordials;
import * as colors from "internal:ext/console/01_colors.js";
function isInvalidDate(x) {
function isInvalidDate(x) {
return isNaN(DatePrototypeGetTime(x));
}
}
function hasOwnProperty(obj, v) {
function hasOwnProperty(obj, v) {
if (obj == null) {
return false;
}
return ObjectPrototypeHasOwnProperty(obj, v);
}
}
function propertyIsEnumerable(obj, prop) {
function propertyIsEnumerable(obj, prop) {
if (
obj == null ||
typeof obj.propertyIsEnumerable !== "function"
@ -139,16 +138,16 @@
}
return ObjectPrototypePropertyIsEnumerable(obj, prop);
}
}
// Copyright Joyent, Inc. and other Node contributors. MIT license.
// Forked from Node's lib/internal/cli_table.js
// Copyright Joyent, Inc. and other Node contributors. MIT license.
// Forked from Node's lib/internal/cli_table.js
function isTypedArray(x) {
function isTypedArray(x) {
return TypedArrayPrototypeGetSymbolToStringTag(x) !== undefined;
}
}
const tableChars = {
const tableChars = {
middleMiddle: "─",
rowMiddle: "┼",
topRight: "┐",
@ -162,9 +161,9 @@
left: "│ ",
right: " │",
middle: " │ ",
};
};
function isFullWidthCodePoint(code) {
function isFullWidthCodePoint(code) {
// Code points are partially derived from:
// http://www.unicode.org/Public/UNIDATA/EastAsianWidth.txt
return (
@ -201,9 +200,9 @@
// CJK Unified Ideographs Extension B .. Tertiary Ideographic Plane
(code >= 0x20000 && code <= 0x3fffd))
);
}
}
function getStringWidth(str) {
function getStringWidth(str) {
str = StringPrototypeNormalize(colors.stripColor(str), "NFC");
let width = 0;
@ -212,9 +211,9 @@
}
return width;
}
}
function renderRow(row, columnWidths, columnRightAlign) {
function renderRow(row, columnWidths, columnRightAlign) {
let out = tableChars.left;
for (let i = 0; i < row.length; i++) {
const cell = row[i];
@ -231,14 +230,14 @@
}
out += tableChars.right;
return out;
}
}
function canRightAlign(value) {
function canRightAlign(value) {
const isNumber = !isNaN(value);
return isNumber;
}
}
function cliTable(head, columns) {
function cliTable(head, columns) {
const rows = [];
const columnWidths = ArrayPrototypeMap(head, (h) => getStringWidth(h));
const longestColumn = ArrayPrototypeReduce(
@ -289,10 +288,10 @@
tableChars.bottomRight;
return result;
}
/* End of forked part */
}
/* End of forked part */
const DEFAULT_INSPECT_OPTIONS = {
const DEFAULT_INSPECT_OPTIONS = {
depth: 4,
indentLevel: 0,
sorted: false,
@ -304,22 +303,22 @@
getters: false,
showHidden: false,
strAbbreviateSize: 100,
};
};
const DEFAULT_INDENT = " "; // Default indent string
const DEFAULT_INDENT = " "; // Default indent string
const LINE_BREAKING_LENGTH = 80;
const MIN_GROUP_LENGTH = 6;
const STR_ABBREVIATE_SIZE = 100;
const LINE_BREAKING_LENGTH = 80;
const MIN_GROUP_LENGTH = 6;
const STR_ABBREVIATE_SIZE = 100;
const PROMISE_STRING_BASE_LENGTH = 12;
const PROMISE_STRING_BASE_LENGTH = 12;
class CSI {
class CSI {
static kClear = "\x1b[1;1H";
static kClearScreenDown = "\x1b[0J";
}
}
function getClassInstanceName(instance) {
function getClassInstanceName(instance) {
if (typeof instance != "object") {
return "";
}
@ -328,13 +327,13 @@
return constructor.name ?? "";
}
return "";
}
}
function maybeColor(fn, inspectOptions) {
function maybeColor(fn, inspectOptions) {
return inspectOptions.colors ? fn : (s) => s;
}
}
function inspectFunction(value, inspectOptions) {
function inspectFunction(value, inspectOptions) {
const cyan = maybeColor(colors.cyan, inspectOptions);
if (
ReflectHas(value, customInspect) &&
@ -385,13 +384,13 @@
return cyan(`${refStr}[${cstrName}: ${value.name}]`) + suffix;
}
return cyan(`${refStr}[${cstrName}]`) + suffix;
}
}
function inspectIterable(
function inspectIterable(
value,
options,
inspectOptions,
) {
) {
const cyan = maybeColor(colors.cyan, inspectOptions);
if (inspectOptions.indentLevel >= inspectOptions.depth) {
return cyan(`[${options.typeName}]`);
@ -532,16 +531,16 @@
}
return `${iPrefix}${options.delims[0]}${iContent}${options.delims[1]}`;
}
}
// Ported from Node.js
// Copyright Node.js contributors. All rights reserved.
function groupEntries(
// Ported from Node.js
// Copyright Node.js contributors. All rights reserved.
function groupEntries(
entries,
level,
value,
iterableLimit = 100,
) {
) {
let totalLength = 0;
let maxLength = 0;
let entriesLength = entries.length;
@ -645,10 +644,10 @@
entries = tmp;
}
return entries;
}
}
let circular;
function handleCircular(value, cyan) {
let circular;
function handleCircular(value, cyan) {
let index = 1;
if (circular === undefined) {
circular = new Map();
@ -662,12 +661,12 @@
}
// Circular string is cyan
return cyan(`[Circular *${index}]`);
}
}
function _inspectValue(
function _inspectValue(
value,
inspectOptions,
) {
) {
const proxyDetails = core.getProxyDetails(value);
if (proxyDetails != null && inspectOptions.showProxy) {
return inspectProxy(proxyDetails, inspectOptions);
@ -719,12 +718,12 @@
// Not implemented is red
return red("[Not Implemented]");
}
}
}
function inspectValue(
function inspectValue(
value,
inspectOptions,
) {
) {
ArrayPrototypePush(CTX_STACK, value);
let x;
try {
@ -733,14 +732,14 @@
ArrayPrototypePop(CTX_STACK);
}
return x;
}
}
// We can match Node's quoting behavior exactly by swapping the double quote and
// single quote in this array. That would give preference to single quotes.
// However, we prefer double quotes as the default.
const QUOTES = ['"', "'", "`"];
// We can match Node's quoting behavior exactly by swapping the double quote and
// single quote in this array. That would give preference to single quotes.
// However, we prefer double quotes as the default.
const QUOTES = ['"', "'", "`"];
/** Surround the string in quotes.
/** Surround the string in quotes.
*
* The quote symbol is chosen by taking the first of the `QUOTES` array which
* does not occur in the string. If they all occur, settle with `QUOTES[0]`.
@ -748,7 +747,7 @@
* Insert a backslash before any occurrence of the chosen quote symbol and
* before any backslash.
*/
function quoteString(string) {
function quoteString(string) {
const quote =
ArrayPrototypeFind(QUOTES, (c) => !StringPrototypeIncludes(string, c)) ??
QUOTES[0];
@ -756,10 +755,10 @@
string = StringPrototypeReplace(string, escapePattern, "\\");
string = replaceEscapeSequences(string);
return `${quote}${string}${quote}`;
}
}
// Replace escape sequences that can modify output.
function replaceEscapeSequences(string) {
// Replace escape sequences that can modify output.
function replaceEscapeSequences(string) {
const escapeMap = {
"\b": "\\b",
"\f": "\\f",
@ -785,19 +784,19 @@
"0",
),
);
}
}
// Surround a string with quotes when it is required (e.g the string not a valid identifier).
function maybeQuoteString(string) {
// Surround a string with quotes when it is required (e.g the string not a valid identifier).
function maybeQuoteString(string) {
if (RegExpPrototypeTest(/^[a-zA-Z_][a-zA-Z_0-9]*$/, string)) {
return replaceEscapeSequences(string);
}
return quoteString(string);
}
}
// Surround a symbol's description in quotes when it is required (e.g the description has non printable characters).
function maybeQuoteSymbol(symbol) {
// Surround a symbol's description in quotes when it is required (e.g the description has non printable characters).
function maybeQuoteSymbol(symbol) {
if (symbol.description === undefined) {
return SymbolPrototypeToString(symbol);
}
@ -807,24 +806,23 @@
}
return `Symbol(${quoteString(symbol.description)})`;
}
}
const CTX_STACK = [];
function ctxHas(x) {
const CTX_STACK = [];
function ctxHas(x) {
// Only check parent contexts
return ArrayPrototypeIncludes(
ArrayPrototypeSlice(CTX_STACK, 0, CTX_STACK.length - 1),
x,
);
}
}
// Print strings when they are inside of arrays or objects with quotes
function inspectValueWithQuotes(
// Print strings when they are inside of arrays or objects with quotes
function inspectValueWithQuotes(
value,
inspectOptions,
) {
const abbreviateSize =
typeof inspectOptions.strAbbreviateSize === "undefined"
) {
const abbreviateSize = typeof inspectOptions.strAbbreviateSize === "undefined"
? STR_ABBREVIATE_SIZE
: inspectOptions.strAbbreviateSize;
const green = maybeColor(colors.green, inspectOptions);
@ -838,12 +836,12 @@
default:
return inspectValue(value, inspectOptions);
}
}
}
function inspectArray(
function inspectArray(
value,
inspectOptions,
) {
) {
const gray = maybeColor(colors.gray, inspectOptions);
let lastValidIndex = 0;
let keys;
@ -890,13 +888,13 @@
sort: false,
};
return inspectIterable(value, options, inspectOptions);
}
}
function inspectTypedArray(
function inspectTypedArray(
typedArrayName,
value,
inspectOptions,
) {
) {
const valueLength = value.length;
const options = {
typeName: typedArrayName,
@ -913,12 +911,12 @@
sort: false,
};
return inspectIterable(value, options, inspectOptions);
}
}
function inspectSet(
function inspectSet(
value,
inspectOptions,
) {
) {
const options = {
typeName: "Set",
displayName: "Set",
@ -934,12 +932,12 @@
sort: inspectOptions.sorted,
};
return inspectIterable(value, options, inspectOptions);
}
}
function inspectMap(
function inspectMap(
value,
inspectOptions,
) {
) {
const options = {
typeName: "Map",
displayName: "Map",
@ -961,32 +959,32 @@
options,
inspectOptions,
);
}
}
function inspectWeakSet(inspectOptions) {
function inspectWeakSet(inspectOptions) {
const cyan = maybeColor(colors.cyan, inspectOptions);
return `WeakSet { ${cyan("[items unknown]")} }`; // as seen in Node, with cyan color
}
}
function inspectWeakMap(inspectOptions) {
function inspectWeakMap(inspectOptions) {
const cyan = maybeColor(colors.cyan, inspectOptions);
return `WeakMap { ${cyan("[items unknown]")} }`; // as seen in Node, with cyan color
}
}
function inspectDate(value, inspectOptions) {
function inspectDate(value, inspectOptions) {
// without quotes, ISO format, in magenta like before
const magenta = maybeColor(colors.magenta, inspectOptions);
return magenta(
isInvalidDate(value) ? "Invalid Date" : DatePrototypeToISOString(value),
);
}
}
function inspectRegExp(value, inspectOptions) {
function inspectRegExp(value, inspectOptions) {
const red = maybeColor(colors.red, inspectOptions);
return red(RegExpPrototypeToString(value)); // RegExps are red
}
}
function inspectError(value, cyan) {
function inspectError(value, cyan) {
const causes = [value];
let err = value;
@ -1058,19 +1056,19 @@
);
return finalMessage;
}
}
function inspectStringObject(value, inspectOptions) {
function inspectStringObject(value, inspectOptions) {
const cyan = maybeColor(colors.cyan, inspectOptions);
return cyan(`[String: "${StringPrototypeToString(value)}"]`); // wrappers are in cyan
}
}
function inspectBooleanObject(value, inspectOptions) {
function inspectBooleanObject(value, inspectOptions) {
const cyan = maybeColor(colors.cyan, inspectOptions);
return cyan(`[Boolean: ${BooleanPrototypeToString(value)}]`); // wrappers are in cyan
}
}
function inspectNumberObject(value, inspectOptions) {
function inspectNumberObject(value, inspectOptions) {
const cyan = maybeColor(colors.cyan, inspectOptions);
// Special handling of -0
return cyan(
@ -1080,28 +1078,28 @@
: NumberPrototypeToString(value)
}]`,
); // wrappers are in cyan
}
}
function inspectBigIntObject(value, inspectOptions) {
function inspectBigIntObject(value, inspectOptions) {
const cyan = maybeColor(colors.cyan, inspectOptions);
return cyan(`[BigInt: ${BigIntPrototypeToString(value)}n]`); // wrappers are in cyan
}
}
function inspectSymbolObject(value, inspectOptions) {
function inspectSymbolObject(value, inspectOptions) {
const cyan = maybeColor(colors.cyan, inspectOptions);
return cyan(`[Symbol: ${maybeQuoteSymbol(SymbolPrototypeValueOf(value))}]`); // wrappers are in cyan
}
}
const PromiseState = {
const PromiseState = {
Pending: 0,
Fulfilled: 1,
Rejected: 2,
};
};
function inspectPromise(
function inspectPromise(
value,
inspectOptions,
) {
) {
const cyan = maybeColor(colors.cyan, inspectOptions);
const red = maybeColor(colors.red, inspectOptions);
@ -1126,19 +1124,19 @@
}
return `Promise { ${str} }`;
}
}
function inspectProxy(
function inspectProxy(
targetAndHandler,
inspectOptions,
) {
) {
return `Proxy ${inspectArray(targetAndHandler, inspectOptions)}`;
}
}
function inspectRawObject(
function inspectRawObject(
value,
inspectOptions,
) {
) {
const cyan = maybeColor(colors.cyan, inspectOptions);
if (inspectOptions.indentLevel >= inspectOptions.depth) {
@ -1297,9 +1295,9 @@
}
return [baseString, refIndex];
}
}
function inspectObject(value, inspectOptions, proxyDetails) {
function inspectObject(value, inspectOptions, proxyDetails) {
if (
ReflectHas(value, customInspect) &&
typeof value[customInspect] === "function"
@ -1372,9 +1370,9 @@
insp = refIndex + insp;
return insp;
}
}
}
const colorKeywords = new Map([
const colorKeywords = new Map([
["black", "#000000"],
["silver", "#c0c0c0"],
["gray", "#808080"],
@ -1523,9 +1521,9 @@
["whitesmoke", "#f5f5f5"],
["yellowgreen", "#9acd32"],
["rebeccapurple", "#663399"],
]);
]);
function parseCssColor(colorString) {
function parseCssColor(colorString) {
if (MapPrototypeHas(colorKeywords, colorString)) {
colorString = MapPrototypeGet(colorKeywords, colorString);
}
@ -1592,9 +1590,9 @@
];
}
return null;
}
}
function getDefaultCss() {
function getDefaultCss() {
return {
backgroundColor: null,
color: null,
@ -1603,9 +1601,9 @@
textDecorationColor: null,
textDecorationLine: [],
};
}
}
function parseCss(cssString) {
function parseCss(cssString) {
const css = getDefaultCss();
const rawEntries = [];
@ -1710,14 +1708,14 @@
}
return css;
}
}
function colorEquals(color1, color2) {
function colorEquals(color1, color2) {
return color1?.[0] == color2?.[0] && color1?.[1] == color2?.[1] &&
color1?.[2] == color2?.[2];
}
}
function cssToAnsi(css, prevCss = null) {
function cssToAnsi(css, prevCss = null) {
prevCss = prevCss ?? getDefaultCss();
let ansi = "";
if (!colorEquals(css.backgroundColor, prevCss.backgroundColor)) {
@ -1841,9 +1839,9 @@
}
}
return ansi;
}
}
function inspectArgs(args, inspectOptions = {}) {
function inspectArgs(args, inspectOptions = {}) {
circular = undefined;
const noColor = colors.getNoColor();
@ -1942,20 +1940,20 @@
}
return string;
}
}
const countMap = new Map();
const timerMap = new Map();
const isConsoleInstance = Symbol("isConsoleInstance");
const countMap = new Map();
const timerMap = new Map();
const isConsoleInstance = Symbol("isConsoleInstance");
function getConsoleInspectOptions() {
function getConsoleInspectOptions() {
return {
...DEFAULT_INSPECT_OPTIONS,
colors: !colors.getNoColor(),
};
}
}
class Console {
class Console {
#printFunc = null;
[isConsoleInstance] = false;
@ -2264,25 +2262,25 @@
static [SymbolHasInstance](instance) {
return instance[isConsoleInstance];
}
}
}
const customInspect = SymbolFor("Deno.customInspect");
const customInspect = SymbolFor("Deno.customInspect");
function inspect(
function inspect(
value,
inspectOptions = {},
) {
) {
circular = undefined;
return inspectValue(value, {
...DEFAULT_INSPECT_OPTIONS,
...inspectOptions,
});
}
}
/** Creates a proxy that represents a subset of the properties
/** Creates a proxy that represents a subset of the properties
* of the original object optionally without evaluating the properties
* in order to get the values. */
function createFilteredInspectProxy({ object, keys, evaluate }) {
function createFilteredInspectProxy({ object, keys, evaluate }) {
return new Proxy({}, {
get(_target, key) {
if (key === SymbolToStringTag) {
@ -2329,21 +2327,21 @@
value: object[key],
};
}
}
}
// A helper function that will bind our own console implementation
// with default implementation of Console from V8. This will cause
// console messages to be piped to inspector console.
//
// We are using `Deno.core.callConsole` binding to preserve proper stack
// frames in inspector console. This has to be done because V8 considers
// the last JS stack frame as gospel for the inspector. In our case we
// specifically want the latest user stack frame to be the one that matters
// though.
//
// Inspired by:
// https://github.com/nodejs/node/blob/1317252dfe8824fd9cfee125d2aaa94004db2f3b/lib/internal/util/inspector.js#L39-L61
function wrapConsole(consoleFromDeno, consoleFromV8) {
// A helper function that will bind our own console implementation
// with default implementation of Console from V8. This will cause
// console messages to be piped to inspector console.
//
// We are using `Deno.core.callConsole` binding to preserve proper stack
// frames in inspector console. This has to be done because V8 considers
// the last JS stack frame as gospel for the inspector. In our case we
// specifically want the latest user stack frame to be the one that matters
// though.
//
// Inspired by:
// https://github.com/nodejs/node/blob/1317252dfe8824fd9cfee125d2aaa94004db2f3b/lib/internal/util/inspector.js#L39-L61
function wrapConsole(consoleFromDeno, consoleFromV8) {
const callConsole = core.callConsole;
const keys = ObjectKeys(consoleFromV8);
@ -2361,26 +2359,22 @@
consoleFromDeno[key] = consoleFromV8[key];
}
}
}
}
// Expose these fields to internalObject for tests.
window.__bootstrap.internals = {
...window.__bootstrap.internals ?? {},
// Expose these fields to internalObject for tests.
internals.Console = Console;
internals.cssToAnsi = cssToAnsi;
internals.inspectArgs = inspectArgs;
internals.parseCss = parseCss;
internals.parseCssColor = parseCssColor;
export {
Console,
cssToAnsi,
inspectArgs,
parseCss,
parseCssColor,
};
window.__bootstrap.console = {
createFilteredInspectProxy,
CSI,
inspectArgs,
Console,
customInspect,
inspect,
wrapConsole,
createFilteredInspectProxy,
inspectArgs,
quoteString,
};
})(this);
wrapConsole,
};

View file

@ -3,14 +3,10 @@
/// <reference no-default-lib="true" />
/// <reference lib="esnext" />
declare namespace globalThis {
declare namespace __bootstrap {
declare namespace console {
declare function createFilteredInspectProxy<TObject>(params: {
declare module "internal:ext/console/02_console.js" {
function createFilteredInspectProxy<TObject>(params: {
object: TObject;
keys: (keyof TObject)[];
evaluate: boolean;
}): Record<string, unknown>;
}
}
}

View file

@ -6,7 +6,7 @@ use std::path::PathBuf;
pub fn init() -> Extension {
Extension::builder(env!("CARGO_PKG_NAME"))
.js(include_js_files!(
.esm(include_js_files!(
prefix "internal:ext/console",
"01_colors.js",
"02_console.js",

View file

@ -6,15 +6,12 @@
/// <reference path="../webidl/internal.d.ts" />
/// <reference path="../web/lib.deno_web.d.ts" />
"use strict";
((window) => {
const core = window.Deno.core;
const ops = core.ops;
const webidl = window.__bootstrap.webidl;
const { DOMException } = window.__bootstrap.domException;
const {
const core = globalThis.Deno.core;
const ops = core.ops;
const primordials = globalThis.__bootstrap.primordials;
import * as webidl from "internal:ext/webidl/00_webidl.js";
import DOMException from "internal:ext/web/01_dom_exception.js";
const {
ArrayBufferPrototype,
ArrayBufferIsView,
ArrayPrototypeEvery,
@ -49,11 +46,11 @@
WeakMap,
WeakMapPrototypeGet,
WeakMapPrototypeSet,
} = window.__bootstrap.primordials;
} = primordials;
// P-521 is not yet supported.
const supportedNamedCurves = ["P-256", "P-384"];
const recognisedUsages = [
// P-521 is not yet supported.
const supportedNamedCurves = ["P-256", "P-384"];
const recognisedUsages = [
"encrypt",
"decrypt",
"sign",
@ -62,9 +59,9 @@
"deriveBits",
"wrapKey",
"unwrapKey",
];
];
const simpleAlgorithmDictionaries = {
const simpleAlgorithmDictionaries = {
AesGcmParams: { iv: "BufferSource", additionalData: "BufferSource" },
RsaHashedKeyGenParams: { hash: "HashAlgorithmIdentifier" },
EcKeyGenParams: {},
@ -81,9 +78,9 @@
RsaOaepParams: { label: "BufferSource" },
RsaHashedImportParams: { hash: "HashAlgorithmIdentifier" },
EcKeyImportParams: {},
};
};
const supportedAlgorithms = {
const supportedAlgorithms = {
"digest": {
"SHA-1": null,
"SHA-256": null,
@ -167,9 +164,9 @@
"unwrapKey": {
"AES-KW": null,
},
};
};
const aesJwkAlg = {
const aesJwkAlg = {
"AES-CTR": {
128: "A128CTR",
192: "A192CTR",
@ -190,11 +187,11 @@
192: "A192KW",
256: "A256KW",
},
};
};
// See https://www.w3.org/TR/WebCryptoAPI/#dfn-normalize-an-algorithm
// 18.4.4
function normalizeAlgorithm(algorithm, op) {
// See https://www.w3.org/TR/WebCryptoAPI/#dfn-normalize-an-algorithm
// 18.4.4
function normalizeAlgorithm(algorithm, op) {
if (typeof algorithm == "string") {
return normalizeAlgorithm({ name: algorithm }, op);
}
@ -269,27 +266,27 @@
}
return normalizedAlgorithm;
}
}
/**
/**
* @param {ArrayBufferView | ArrayBuffer} input
* @returns {Uint8Array}
*/
function copyBuffer(input) {
function copyBuffer(input) {
return TypedArrayPrototypeSlice(
ArrayBufferIsView(input)
? new Uint8Array(input.buffer, input.byteOffset, input.byteLength)
: new Uint8Array(input),
);
}
}
const _handle = Symbol("[[handle]]");
const _algorithm = Symbol("[[algorithm]]");
const _extractable = Symbol("[[extractable]]");
const _usages = Symbol("[[usages]]");
const _type = Symbol("[[type]]");
const _handle = Symbol("[[handle]]");
const _algorithm = Symbol("[[algorithm]]");
const _extractable = Symbol("[[extractable]]");
const _usages = Symbol("[[usages]]");
const _type = Symbol("[[type]]");
class CryptoKey {
class CryptoKey {
/** @type {string} */
[_type];
/** @type {boolean} */
@ -341,12 +338,12 @@
})
}`;
}
}
}
webidl.configurePrototype(CryptoKey);
const CryptoKeyPrototype = CryptoKey.prototype;
webidl.configurePrototype(CryptoKey);
const CryptoKeyPrototype = CryptoKey.prototype;
/**
/**
* @param {string} type
* @param {boolean} extractable
* @param {string[]} usages
@ -354,7 +351,7 @@
* @param {object} handle
* @returns
*/
function constructKey(type, extractable, usages, algorithm, handle) {
function constructKey(type, extractable, usages, algorithm, handle) {
const key = webidl.createBranded(CryptoKey);
key[_type] = type;
key[_extractable] = extractable;
@ -362,23 +359,23 @@
key[_algorithm] = algorithm;
key[_handle] = handle;
return key;
}
}
// https://w3c.github.io/webcrypto/#concept-usage-intersection
/**
// https://w3c.github.io/webcrypto/#concept-usage-intersection
/**
* @param {string[]} a
* @param {string[]} b
* @returns
*/
function usageIntersection(a, b) {
function usageIntersection(a, b) {
return a.filter((i) => b.includes(i));
}
}
// TODO(lucacasonato): this should be moved to rust
/** @type {WeakMap<object, object>} */
const KEY_STORE = new WeakMap();
// TODO(lucacasonato): this should be moved to rust
/** @type {WeakMap<object, object>} */
const KEY_STORE = new WeakMap();
function getKeyLength(algorithm) {
function getKeyLength(algorithm) {
switch (algorithm.name) {
case "AES-CBC":
case "AES-CTR":
@ -438,9 +435,9 @@
default:
throw new TypeError("unreachable");
}
}
}
class SubtleCrypto {
class SubtleCrypto {
constructor() {
webidl.illegalConstructor();
}
@ -1703,10 +1700,10 @@
return result;
}
}
const SubtleCryptoPrototype = SubtleCrypto.prototype;
}
const SubtleCryptoPrototype = SubtleCrypto.prototype;
async function generateKey(normalizedAlgorithm, extractable, usages) {
async function generateKey(normalizedAlgorithm, extractable, usages) {
const algorithmName = normalizedAlgorithm.name;
switch (algorithmName) {
@ -2124,14 +2121,14 @@
return key;
}
}
}
}
function importKeyEd25519(
function importKeyEd25519(
format,
keyData,
extractable,
keyUsages,
) {
) {
switch (format) {
case "raw": {
// 1.
@ -2352,14 +2349,14 @@
default:
throw new DOMException("Not implemented", "NotSupportedError");
}
}
}
function importKeyX25519(
function importKeyX25519(
format,
keyData,
extractable,
keyUsages,
) {
) {
switch (format) {
case "raw": {
// 1.
@ -2557,13 +2554,13 @@
default:
throw new DOMException("Not implemented", "NotSupportedError");
}
}
}
function exportKeyAES(
function exportKeyAES(
format,
key,
innerKey,
) {
) {
switch (format) {
// 2.
case "raw": {
@ -2616,16 +2613,16 @@
default:
throw new DOMException("Not implemented", "NotSupportedError");
}
}
}
function importKeyAES(
function importKeyAES(
format,
normalizedAlgorithm,
keyData,
extractable,
keyUsages,
supportedKeyUsages,
) {
) {
// 1.
if (
ArrayPrototypeFind(
@ -2783,15 +2780,15 @@
// 8.
return key;
}
}
function importKeyHMAC(
function importKeyHMAC(
format,
normalizedAlgorithm,
keyData,
extractable,
keyUsages,
) {
) {
// 2.
if (
ArrayPrototypeFind(
@ -2977,15 +2974,15 @@
);
return key;
}
}
function importKeyEC(
function importKeyEC(
format,
normalizedAlgorithm,
keyData,
extractable,
keyUsages,
) {
) {
const supportedUsages = SUPPORTED_KEY_USAGES[normalizedAlgorithm.name];
switch (format) {
@ -3296,9 +3293,9 @@
default:
throw new DOMException("Not implemented", "NotSupportedError");
}
}
}
const SUPPORTED_KEY_USAGES = {
const SUPPORTED_KEY_USAGES = {
"RSASSA-PKCS1-v1_5": {
public: ["verify"],
private: ["sign"],
@ -3324,15 +3321,15 @@
private: ["deriveKey", "deriveBits"],
jwkUse: "enc",
},
};
};
function importKeyRSA(
function importKeyRSA(
format,
normalizedAlgorithm,
keyData,
extractable,
keyUsages,
) {
) {
switch (format) {
case "pkcs8": {
// 1.
@ -3722,14 +3719,14 @@
default:
throw new DOMException("Not implemented", "NotSupportedError");
}
}
}
function importKeyHKDF(
function importKeyHKDF(
format,
keyData,
extractable,
keyUsages,
) {
) {
if (format !== "raw") {
throw new DOMException("Format not supported", "NotSupportedError");
}
@ -3773,14 +3770,14 @@
// 9.
return key;
}
}
function importKeyPBKDF2(
function importKeyPBKDF2(
format,
keyData,
extractable,
keyUsages,
) {
) {
// 1.
if (format !== "raw") {
throw new DOMException("Format not supported", "NotSupportedError");
@ -3825,9 +3822,9 @@
// 10.
return key;
}
}
function exportKeyHMAC(format, key, innerKey) {
function exportKeyHMAC(format, key, innerKey) {
// 1.
if (innerKey == null) {
throw new DOMException("Key is not available", "OperationError");
@ -3890,9 +3887,9 @@
default:
throw new DOMException("Not implemented", "NotSupportedError");
}
}
}
function exportKeyRSA(format, key, innerKey) {
function exportKeyRSA(format, key, innerKey) {
switch (format) {
case "pkcs8": {
// 1.
@ -4020,9 +4017,9 @@
default:
throw new DOMException("Not implemented", "NotSupportedError");
}
}
}
function exportKeyEd25519(format, key, innerKey) {
function exportKeyEd25519(format, key, innerKey) {
switch (format) {
case "raw": {
// 1.
@ -4083,9 +4080,9 @@
default:
throw new DOMException("Not implemented", "NotSupportedError");
}
}
}
function exportKeyX25519(format, key, innerKey) {
function exportKeyX25519(format, key, innerKey) {
switch (format) {
case "raw": {
// 1.
@ -4143,9 +4140,9 @@
default:
throw new DOMException("Not implemented", "NotSupportedError");
}
}
}
function exportKeyEC(format, key, innerKey) {
function exportKeyEC(format, key, innerKey) {
switch (format) {
case "raw": {
// 1.
@ -4283,9 +4280,9 @@
default:
throw new DOMException("Not implemented", "NotSupportedError");
}
}
}
async function generateKeyAES(normalizedAlgorithm, extractable, usages) {
async function generateKeyAES(normalizedAlgorithm, extractable, usages) {
const algorithmName = normalizedAlgorithm.name;
// 2.
@ -4321,9 +4318,9 @@
// 12.
return key;
}
}
async function deriveBits(normalizedAlgorithm, baseKey, length) {
async function deriveBits(normalizedAlgorithm, baseKey, length) {
switch (normalizedAlgorithm.name) {
case "PBKDF2": {
// 1.
@ -4483,9 +4480,9 @@
default:
throw new DOMException("Not implemented", "NotSupportedError");
}
}
}
async function encrypt(normalizedAlgorithm, key, data) {
async function encrypt(normalizedAlgorithm, key, data) {
const handle = key[_handle];
const keyData = WeakMapPrototypeGet(KEY_STORE, handle);
@ -4644,12 +4641,12 @@
default:
throw new DOMException("Not implemented", "NotSupportedError");
}
}
}
webidl.configurePrototype(SubtleCrypto);
const subtle = webidl.createBranded(SubtleCrypto);
webidl.configurePrototype(SubtleCrypto);
const subtle = webidl.createBranded(SubtleCrypto);
class Crypto {
class Crypto {
constructor() {
webidl.illegalConstructor();
}
@ -4713,15 +4710,10 @@
[SymbolFor("Deno.customInspect")](inspect) {
return `${this.constructor.name} ${inspect({})}`;
}
}
}
webidl.configurePrototype(Crypto);
const CryptoPrototype = Crypto.prototype;
webidl.configurePrototype(Crypto);
const CryptoPrototype = Crypto.prototype;
window.__bootstrap.crypto = {
SubtleCrypto,
crypto: webidl.createBranded(Crypto),
Crypto,
CryptoKey,
};
})(this);
const crypto = webidl.createBranded(Crypto);
export { Crypto, crypto, CryptoKey, SubtleCrypto };

View file

@ -4,27 +4,25 @@
/// <reference path="../../core/lib.deno_core.d.ts" />
/// <reference path="../webidl/internal.d.ts" />
"use strict";
((window) => {
const webidl = window.__bootstrap.webidl;
const { CryptoKey } = window.__bootstrap.crypto;
const {
const primordials = globalThis.__bootstrap.primordials;
import * as webidl from "internal:ext/webidl/00_webidl.js";
import { CryptoKey } from "internal:ext/crypto/00_crypto.js";
const {
ArrayBufferIsView,
ArrayBufferPrototype,
ObjectPrototypeIsPrototypeOf,
SafeArrayIterator,
} = window.__bootstrap.primordials;
} = primordials;
webidl.converters.AlgorithmIdentifier = (V, opts) => {
webidl.converters.AlgorithmIdentifier = (V, opts) => {
// Union for (object or DOMString)
if (webidl.type(V) == "Object") {
return webidl.converters.object(V, opts);
}
return webidl.converters.DOMString(V, opts);
};
};
webidl.converters["BufferSource or JsonWebKey"] = (V, opts) => {
webidl.converters["BufferSource or JsonWebKey"] = (V, opts) => {
// Union for (BufferSource or JsonWebKey)
if (
ArrayBufferIsView(V) ||
@ -33,22 +31,22 @@
return webidl.converters.BufferSource(V, opts);
}
return webidl.converters.JsonWebKey(V, opts);
};
};
webidl.converters.KeyType = webidl.createEnumConverter("KeyType", [
webidl.converters.KeyType = webidl.createEnumConverter("KeyType", [
"public",
"private",
"secret",
]);
]);
webidl.converters.KeyFormat = webidl.createEnumConverter("KeyFormat", [
webidl.converters.KeyFormat = webidl.createEnumConverter("KeyFormat", [
"raw",
"pkcs8",
"spki",
"jwk",
]);
]);
webidl.converters.KeyUsage = webidl.createEnumConverter("KeyUsage", [
webidl.converters.KeyUsage = webidl.createEnumConverter("KeyUsage", [
"encrypt",
"decrypt",
"sign",
@ -57,29 +55,29 @@
"deriveBits",
"wrapKey",
"unwrapKey",
]);
]);
webidl.converters["sequence<KeyUsage>"] = webidl.createSequenceConverter(
webidl.converters["sequence<KeyUsage>"] = webidl.createSequenceConverter(
webidl.converters.KeyUsage,
);
);
webidl.converters.HashAlgorithmIdentifier =
webidl.converters.HashAlgorithmIdentifier =
webidl.converters.AlgorithmIdentifier;
/** @type {__bootstrap.webidl.Dictionary} */
const dictAlgorithm = [{
/** @type {webidl.Dictionary} */
const dictAlgorithm = [{
key: "name",
converter: webidl.converters.DOMString,
required: true,
}];
}];
webidl.converters.Algorithm = webidl
webidl.converters.Algorithm = webidl
.createDictionaryConverter("Algorithm", dictAlgorithm);
webidl.converters.BigInteger = webidl.converters.Uint8Array;
webidl.converters.BigInteger = webidl.converters.Uint8Array;
/** @type {__bootstrap.webidl.Dictionary} */
const dictRsaKeyGenParams = [
/** @type {webidl.Dictionary} */
const dictRsaKeyGenParams = [
...new SafeArrayIterator(dictAlgorithm),
{
key: "modulusLength",
@ -92,68 +90,68 @@
converter: webidl.converters.BigInteger,
required: true,
},
];
];
webidl.converters.RsaKeyGenParams = webidl
webidl.converters.RsaKeyGenParams = webidl
.createDictionaryConverter("RsaKeyGenParams", dictRsaKeyGenParams);
const dictRsaHashedKeyGenParams = [
const dictRsaHashedKeyGenParams = [
...new SafeArrayIterator(dictRsaKeyGenParams),
{
key: "hash",
converter: webidl.converters.HashAlgorithmIdentifier,
required: true,
},
];
];
webidl.converters.RsaHashedKeyGenParams = webidl.createDictionaryConverter(
webidl.converters.RsaHashedKeyGenParams = webidl.createDictionaryConverter(
"RsaHashedKeyGenParams",
dictRsaHashedKeyGenParams,
);
);
const dictRsaHashedImportParams = [
const dictRsaHashedImportParams = [
...new SafeArrayIterator(dictAlgorithm),
{
key: "hash",
converter: webidl.converters.HashAlgorithmIdentifier,
required: true,
},
];
];
webidl.converters.RsaHashedImportParams = webidl.createDictionaryConverter(
webidl.converters.RsaHashedImportParams = webidl.createDictionaryConverter(
"RsaHashedImportParams",
dictRsaHashedImportParams,
);
);
webidl.converters.NamedCurve = webidl.converters.DOMString;
webidl.converters.NamedCurve = webidl.converters.DOMString;
const dictEcKeyImportParams = [
const dictEcKeyImportParams = [
...new SafeArrayIterator(dictAlgorithm),
{
key: "namedCurve",
converter: webidl.converters.NamedCurve,
required: true,
},
];
];
webidl.converters.EcKeyImportParams = webidl.createDictionaryConverter(
webidl.converters.EcKeyImportParams = webidl.createDictionaryConverter(
"EcKeyImportParams",
dictEcKeyImportParams,
);
);
const dictEcKeyGenParams = [
const dictEcKeyGenParams = [
...new SafeArrayIterator(dictAlgorithm),
{
key: "namedCurve",
converter: webidl.converters.NamedCurve,
required: true,
},
];
];
webidl.converters.EcKeyGenParams = webidl
webidl.converters.EcKeyGenParams = webidl
.createDictionaryConverter("EcKeyGenParams", dictEcKeyGenParams);
const dictAesKeyGenParams = [
const dictAesKeyGenParams = [
...new SafeArrayIterator(dictAlgorithm),
{
key: "length",
@ -161,12 +159,12 @@
webidl.converters["unsigned short"](V, { ...opts, enforceRange: true }),
required: true,
},
];
];
webidl.converters.AesKeyGenParams = webidl
webidl.converters.AesKeyGenParams = webidl
.createDictionaryConverter("AesKeyGenParams", dictAesKeyGenParams);
const dictHmacKeyGenParams = [
const dictHmacKeyGenParams = [
...new SafeArrayIterator(dictAlgorithm),
{
key: "hash",
@ -178,12 +176,12 @@
converter: (V, opts) =>
webidl.converters["unsigned long"](V, { ...opts, enforceRange: true }),
},
];
];
webidl.converters.HmacKeyGenParams = webidl
webidl.converters.HmacKeyGenParams = webidl
.createDictionaryConverter("HmacKeyGenParams", dictHmacKeyGenParams);
const dictRsaPssParams = [
const dictRsaPssParams = [
...new SafeArrayIterator(dictAlgorithm),
{
key: "saltLength",
@ -191,35 +189,35 @@
webidl.converters["unsigned long"](V, { ...opts, enforceRange: true }),
required: true,
},
];
];
webidl.converters.RsaPssParams = webidl
webidl.converters.RsaPssParams = webidl
.createDictionaryConverter("RsaPssParams", dictRsaPssParams);
const dictRsaOaepParams = [
const dictRsaOaepParams = [
...new SafeArrayIterator(dictAlgorithm),
{
key: "label",
converter: webidl.converters["BufferSource"],
},
];
];
webidl.converters.RsaOaepParams = webidl
webidl.converters.RsaOaepParams = webidl
.createDictionaryConverter("RsaOaepParams", dictRsaOaepParams);
const dictEcdsaParams = [
const dictEcdsaParams = [
...new SafeArrayIterator(dictAlgorithm),
{
key: "hash",
converter: webidl.converters.HashAlgorithmIdentifier,
required: true,
},
];
];
webidl.converters["EcdsaParams"] = webidl
webidl.converters["EcdsaParams"] = webidl
.createDictionaryConverter("EcdsaParams", dictEcdsaParams);
const dictHmacImportParams = [
const dictHmacImportParams = [
...new SafeArrayIterator(dictAlgorithm),
{
key: "hash",
@ -231,12 +229,12 @@
converter: (V, opts) =>
webidl.converters["unsigned long"](V, { ...opts, enforceRange: true }),
},
];
];
webidl.converters.HmacImportParams = webidl
webidl.converters.HmacImportParams = webidl
.createDictionaryConverter("HmacImportParams", dictHmacImportParams);
const dictRsaOtherPrimesInfo = [
const dictRsaOtherPrimesInfo = [
{
key: "r",
converter: webidl.converters["DOMString"],
@ -249,18 +247,18 @@
key: "t",
converter: webidl.converters["DOMString"],
},
];
];
webidl.converters.RsaOtherPrimesInfo = webidl.createDictionaryConverter(
webidl.converters.RsaOtherPrimesInfo = webidl.createDictionaryConverter(
"RsaOtherPrimesInfo",
dictRsaOtherPrimesInfo,
);
webidl.converters["sequence<RsaOtherPrimesInfo>"] = webidl
);
webidl.converters["sequence<RsaOtherPrimesInfo>"] = webidl
.createSequenceConverter(
webidl.converters.RsaOtherPrimesInfo,
);
const dictJsonWebKey = [
const dictJsonWebKey = [
// Sections 4.2 and 4.3 of RFC7517.
// https://datatracker.ietf.org/doc/html/rfc7517#section-4
{
@ -338,14 +336,14 @@
key: "k",
converter: webidl.converters["DOMString"],
},
];
];
webidl.converters.JsonWebKey = webidl.createDictionaryConverter(
webidl.converters.JsonWebKey = webidl.createDictionaryConverter(
"JsonWebKey",
dictJsonWebKey,
);
);
const dictHkdfParams = [
const dictHkdfParams = [
...new SafeArrayIterator(dictAlgorithm),
{
key: "hash",
@ -362,12 +360,12 @@
converter: webidl.converters["BufferSource"],
required: true,
},
];
];
webidl.converters.HkdfParams = webidl
webidl.converters.HkdfParams = webidl
.createDictionaryConverter("HkdfParams", dictHkdfParams);
const dictPbkdf2Params = [
const dictPbkdf2Params = [
...new SafeArrayIterator(dictAlgorithm),
{
key: "hash",
@ -385,12 +383,12 @@
converter: webidl.converters["BufferSource"],
required: true,
},
];
];
webidl.converters.Pbkdf2Params = webidl
webidl.converters.Pbkdf2Params = webidl
.createDictionaryConverter("Pbkdf2Params", dictPbkdf2Params);
const dictAesDerivedKeyParams = [
const dictAesDerivedKeyParams = [
...new SafeArrayIterator(dictAlgorithm),
{
key: "length",
@ -398,18 +396,18 @@
webidl.converters["unsigned long"](V, { ...opts, enforceRange: true }),
required: true,
},
];
];
const dictAesCbcParams = [
const dictAesCbcParams = [
...new SafeArrayIterator(dictAlgorithm),
{
key: "iv",
converter: webidl.converters["BufferSource"],
required: true,
},
];
];
const dictAesGcmParams = [
const dictAesGcmParams = [
...new SafeArrayIterator(dictAlgorithm),
{
key: "iv",
@ -425,9 +423,9 @@
key: "additionalData",
converter: webidl.converters["BufferSource"],
},
];
];
const dictAesCtrParams = [
const dictAesCtrParams = [
...new SafeArrayIterator(dictAlgorithm),
{
key: "counter",
@ -440,26 +438,26 @@
webidl.converters["unsigned short"](V, { ...opts, enforceRange: true }),
required: true,
},
];
];
webidl.converters.AesDerivedKeyParams = webidl
webidl.converters.AesDerivedKeyParams = webidl
.createDictionaryConverter("AesDerivedKeyParams", dictAesDerivedKeyParams);
webidl.converters.AesCbcParams = webidl
webidl.converters.AesCbcParams = webidl
.createDictionaryConverter("AesCbcParams", dictAesCbcParams);
webidl.converters.AesGcmParams = webidl
webidl.converters.AesGcmParams = webidl
.createDictionaryConverter("AesGcmParams", dictAesGcmParams);
webidl.converters.AesCtrParams = webidl
webidl.converters.AesCtrParams = webidl
.createDictionaryConverter("AesCtrParams", dictAesCtrParams);
webidl.converters.CryptoKey = webidl.createInterfaceConverter(
webidl.converters.CryptoKey = webidl.createInterfaceConverter(
"CryptoKey",
CryptoKey.prototype,
);
);
const dictCryptoKeyPair = [
const dictCryptoKeyPair = [
{
key: "publicKey",
converter: webidl.converters.CryptoKey,
@ -468,20 +466,19 @@
key: "privateKey",
converter: webidl.converters.CryptoKey,
},
];
];
webidl.converters.CryptoKeyPair = webidl
webidl.converters.CryptoKeyPair = webidl
.createDictionaryConverter("CryptoKeyPair", dictCryptoKeyPair);
const dictEcdhKeyDeriveParams = [
const dictEcdhKeyDeriveParams = [
...new SafeArrayIterator(dictAlgorithm),
{
key: "public",
converter: webidl.converters.CryptoKey,
required: true,
},
];
];
webidl.converters.EcdhKeyDeriveParams = webidl
webidl.converters.EcdhKeyDeriveParams = webidl
.createDictionaryConverter("EcdhKeyDeriveParams", dictEcdhKeyDeriveParams);
})(this);

View file

@ -75,7 +75,7 @@ use crate::shared::RawKeyData;
pub fn init(maybe_seed: Option<u64>) -> Extension {
Extension::builder(env!("CARGO_PKG_NAME"))
.dependencies(vec!["deno_webidl", "deno_web"])
.js(include_js_files!(
.esm(include_js_files!(
prefix "internal:ext/crypto",
"00_crypto.js",
"01_webidl.js",

View file

@ -1,22 +0,0 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
"use strict";
((window) => {
const { TypeError } = window.__bootstrap.primordials;
function requiredArguments(
name,
length,
required,
) {
if (length < required) {
const errMsg = `${name} requires at least ${required} argument${
required === 1 ? "" : "s"
}, but only ${length} present`;
throw new TypeError(errMsg);
}
}
window.__bootstrap.fetchUtil = {
requiredArguments,
};
})(this);

View file

@ -8,20 +8,19 @@
/// <reference path="../web/06_streams_types.d.ts" />
/// <reference path="./lib.deno_fetch.d.ts" />
/// <reference lib="esnext" />
"use strict";
((window) => {
const webidl = window.__bootstrap.webidl;
const {
import * as webidl from "internal:ext/webidl/00_webidl.js";
import {
byteLowerCase,
collectHttpQuotedString,
collectSequenceOfCodepoints,
HTTP_TAB_OR_SPACE_PREFIX_RE,
HTTP_TAB_OR_SPACE_SUFFIX_RE,
HTTP_TOKEN_CODE_POINT_RE,
byteLowerCase,
collectSequenceOfCodepoints,
collectHttpQuotedString,
httpTrim,
} = window.__bootstrap.infra;
const {
} from "internal:ext/web/00_infra.js";
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayIsArray,
ArrayPrototypeMap,
ArrayPrototypePush,
@ -38,35 +37,35 @@
SymbolIterator,
StringPrototypeReplaceAll,
TypeError,
} = window.__bootstrap.primordials;
} = primordials;
const _headerList = Symbol("header list");
const _iterableHeaders = Symbol("iterable headers");
const _guard = Symbol("guard");
const _headerList = Symbol("header list");
const _iterableHeaders = Symbol("iterable headers");
const _guard = Symbol("guard");
/**
/**
* @typedef Header
* @type {[string, string]}
*/
/**
/**
* @typedef HeaderList
* @type {Header[]}
*/
/**
/**
* @param {string} potentialValue
* @returns {string}
*/
function normalizeHeaderValue(potentialValue) {
function normalizeHeaderValue(potentialValue) {
return httpTrim(potentialValue);
}
}
/**
/**
* @param {Headers} headers
* @param {HeadersInit} object
*/
function fillHeaders(headers, object) {
function fillHeaders(headers, object) {
if (ArrayIsArray(object)) {
for (let i = 0; i < object.length; ++i) {
const header = object[i];
@ -85,19 +84,19 @@
appendHeader(headers, key, object[key]);
}
}
}
}
// Regex matching illegal chars in a header value
// deno-lint-ignore no-control-regex
const ILLEGAL_VALUE_CHARS = /[\x00\x0A\x0D]/;
// Regex matching illegal chars in a header value
// deno-lint-ignore no-control-regex
const ILLEGAL_VALUE_CHARS = /[\x00\x0A\x0D]/;
/**
/**
* https://fetch.spec.whatwg.org/#concept-headers-append
* @param {Headers} headers
* @param {string} name
* @param {string} value
*/
function appendHeader(headers, name, value) {
function appendHeader(headers, name, value) {
// 1.
value = normalizeHeaderValue(value);
@ -124,14 +123,14 @@
}
}
ArrayPrototypePush(list, [name, value]);
}
}
/**
/**
* https://fetch.spec.whatwg.org/#concept-header-list-get
* @param {HeaderList} list
* @param {string} name
*/
function getHeader(list, name) {
function getHeader(list, name) {
const lowercaseName = byteLowerCase(name);
const entries = ArrayPrototypeMap(
ArrayPrototypeFilter(
@ -145,15 +144,15 @@
} else {
return ArrayPrototypeJoin(entries, "\x2C\x20");
}
}
}
/**
/**
* https://fetch.spec.whatwg.org/#concept-header-list-get-decode-split
* @param {HeaderList} list
* @param {string} name
* @returns {string[] | null}
*/
function getDecodeSplitHeader(list, name) {
function getDecodeSplitHeader(list, name) {
const initialValue = getHeader(list, name);
if (initialValue === null) return null;
const input = initialValue;
@ -191,9 +190,9 @@
value = "";
}
return values;
}
}
class Headers {
class Headers {
/** @type {HeaderList} */
[_headerList] = [];
/** @type {"immutable" | "request" | "request-no-cors" | "response" | "none"} */
@ -413,14 +412,14 @@
}
return `Headers ${inspect(headers)}`;
}
}
}
webidl.mixinPairIterable("Headers", Headers, _iterableHeaders, 0, 1);
webidl.mixinPairIterable("Headers", Headers, _iterableHeaders, 0, 1);
webidl.configurePrototype(Headers);
const HeadersPrototype = Headers.prototype;
webidl.configurePrototype(Headers);
const HeadersPrototype = Headers.prototype;
webidl.converters["HeadersInit"] = (V, opts) => {
webidl.converters["HeadersInit"] = (V, opts) => {
// Union for (sequence<sequence<ByteString>> or record<ByteString, ByteString>)
if (webidl.type(V) === "Object" && V !== null) {
if (V[SymbolIterator] !== undefined) {
@ -433,47 +432,46 @@
"The provided value is not of type '(sequence<sequence<ByteString>> or record<ByteString, ByteString>)'",
opts,
);
};
webidl.converters["Headers"] = webidl.createInterfaceConverter(
};
webidl.converters["Headers"] = webidl.createInterfaceConverter(
"Headers",
Headers.prototype,
);
);
/**
/**
* @param {HeaderList} list
* @param {"immutable" | "request" | "request-no-cors" | "response" | "none"} guard
* @returns {Headers}
*/
function headersFromHeaderList(list, guard) {
function headersFromHeaderList(list, guard) {
const headers = webidl.createBranded(Headers);
headers[_headerList] = list;
headers[_guard] = guard;
return headers;
}
}
/**
* @param {Headers}
/**
* @param {Headers} headers
* @returns {HeaderList}
*/
function headerListFromHeaders(headers) {
function headerListFromHeaders(headers) {
return headers[_headerList];
}
}
/**
* @param {Headers}
/**
* @param {Headers} headers
* @returns {"immutable" | "request" | "request-no-cors" | "response" | "none"}
*/
function guardFromHeaders(headers) {
function guardFromHeaders(headers) {
return headers[_guard];
}
}
window.__bootstrap.headers = {
headersFromHeaderList,
headerListFromHeaders,
getDecodeSplitHeader,
guardFromHeaders,
export {
fillHeaders,
getDecodeSplitHeader,
getHeader,
guardFromHeaders,
headerListFromHeaders,
Headers,
};
})(this);
headersFromHeaderList,
};

View file

@ -8,14 +8,17 @@
/// <reference path="../web/06_streams_types.d.ts" />
/// <reference path="./lib.deno_fetch.d.ts" />
/// <reference lib="esnext" />
"use strict";
((window) => {
const core = window.Deno.core;
const webidl = globalThis.__bootstrap.webidl;
const { Blob, BlobPrototype, File, FilePrototype } =
globalThis.__bootstrap.file;
const {
const core = globalThis.Deno.core;
import * as webidl from "internal:ext/webidl/00_webidl.js";
import {
Blob,
BlobPrototype,
File,
FilePrototype,
} from "internal:ext/web/09_file.js";
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayPrototypePush,
ArrayPrototypeSlice,
ArrayPrototypeSplice,
@ -36,17 +39,17 @@
StringPrototypeReplaceAll,
TypeError,
TypedArrayPrototypeSubarray,
} = window.__bootstrap.primordials;
} = primordials;
const entryList = Symbol("entry list");
const entryList = Symbol("entry list");
/**
/**
* @param {string} name
* @param {string | Blob} value
* @param {string | undefined} filename
* @returns {FormDataEntry}
*/
function createEntry(name, value, filename) {
function createEntry(name, value, filename) {
if (
ObjectPrototypeIsPrototypeOf(BlobPrototype, value) &&
!ObjectPrototypeIsPrototypeOf(FilePrototype, value)
@ -67,15 +70,15 @@
// @ts-expect-error because TS is not smart enough
value,
};
}
}
/**
/**
* @typedef FormDataEntry
* @property {string} name
* @property {FormDataEntryValue} value
*/
class FormData {
class FormData {
/** @type {FormDataEntry[]} */
[entryList] = [];
@ -267,14 +270,14 @@
ArrayPrototypePush(list, entry);
}
}
}
}
webidl.mixinPairIterable("FormData", FormData, entryList, "name", "value");
webidl.mixinPairIterable("FormData", FormData, entryList, "name", "value");
webidl.configurePrototype(FormData);
const FormDataPrototype = FormData.prototype;
webidl.configurePrototype(FormData);
const FormDataPrototype = FormData.prototype;
const escape = (str, isFilename) => {
const escape = (str, isFilename) => {
const escapeMap = {
"\n": "%0A",
"\r": "%0D",
@ -286,13 +289,13 @@
/([\n\r"])/g,
(c) => escapeMap[c],
);
};
};
/**
/**
* convert FormData to a Blob synchronous without reading all of the files
* @param {globalThis.FormData} formData
*/
function formDataToBlob(formData) {
function formDataToBlob(formData) {
const boundary = StringPrototypePadStart(
StringPrototypeSlice(
StringPrototypeReplaceAll(`${MathRandom()}${MathRandom()}`, ".", ""),
@ -329,13 +332,13 @@
return new Blob(chunks, {
type: "multipart/form-data; boundary=" + boundary,
});
}
}
/**
/**
* @param {string} value
* @returns {Map<string, string>}
*/
function parseContentDisposition(value) {
function parseContentDisposition(value) {
/** @type {Map<string, string>} */
const params = new Map();
// Forced to do so for some Map constructor param mismatch
@ -351,13 +354,13 @@
}
}
return params;
}
}
const CRLF = "\r\n";
const LF = StringPrototypeCodePointAt(CRLF, 1);
const CR = StringPrototypeCodePointAt(CRLF, 0);
const CRLF = "\r\n";
const LF = StringPrototypeCodePointAt(CRLF, 1);
const CR = StringPrototypeCodePointAt(CRLF, 0);
class MultipartParser {
class MultipartParser {
/**
* @param {Uint8Array} body
* @param {string | undefined} boundary
@ -488,36 +491,35 @@
return formData;
}
}
}
/**
/**
* @param {Uint8Array} body
* @param {string | undefined} boundary
* @returns {FormData}
*/
function parseFormData(body, boundary) {
function parseFormData(body, boundary) {
const parser = new MultipartParser(body, boundary);
return parser.parse();
}
}
/**
/**
* @param {FormDataEntry[]} entries
* @returns {FormData}
*/
function formDataFromEntries(entries) {
function formDataFromEntries(entries) {
const fd = new FormData();
fd[entryList] = entries;
return fd;
}
}
webidl.converters["FormData"] = webidl
webidl.converters["FormData"] = webidl
.createInterfaceConverter("FormData", FormDataPrototype);
globalThis.__bootstrap.formData = {
export {
FormData,
formDataFromEntries,
FormDataPrototype,
formDataToBlob,
parseFormData,
formDataFromEntries,
};
})(globalThis);
};

View file

@ -10,32 +10,33 @@
/// <reference path="../web/06_streams_types.d.ts" />
/// <reference path="./lib.deno_fetch.d.ts" />
/// <reference lib="esnext" />
"use strict";
((window) => {
const core = window.Deno.core;
const webidl = globalThis.__bootstrap.webidl;
const { parseUrlEncoded } = globalThis.__bootstrap.url;
const { URLSearchParamsPrototype } = globalThis.__bootstrap.url;
const {
parseFormData,
const core = globalThis.Deno.core;
import * as webidl from "internal:ext/webidl/00_webidl.js";
import {
parseUrlEncoded,
URLSearchParamsPrototype,
} from "internal:ext/url/00_url.js";
import {
formDataFromEntries,
formDataToBlob,
FormDataPrototype,
} = globalThis.__bootstrap.formData;
const mimesniff = globalThis.__bootstrap.mimesniff;
const { BlobPrototype } = globalThis.__bootstrap.file;
const {
isReadableStreamDisturbed,
errorReadableStream,
readableStreamClose,
readableStreamDisturb,
readableStreamCollectIntoUint8Array,
readableStreamThrowIfErrored,
formDataToBlob,
parseFormData,
} from "internal:ext/fetch/21_formdata.js";
import * as mimesniff from "internal:ext/web/01_mimesniff.js";
import { BlobPrototype } from "internal:ext/web/09_file.js";
import {
createProxy,
errorReadableStream,
isReadableStreamDisturbed,
readableStreamClose,
readableStreamCollectIntoUint8Array,
readableStreamDisturb,
ReadableStreamPrototype,
} = globalThis.__bootstrap.streams;
const {
readableStreamThrowIfErrored,
} from "internal:ext/web/06_streams.js";
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayBufferPrototype,
ArrayBufferIsView,
ArrayPrototypeMap,
@ -48,25 +49,25 @@
TypeError,
Uint8Array,
Uint8ArrayPrototype,
} = window.__bootstrap.primordials;
} = primordials;
/**
/**
* @param {Uint8Array | string} chunk
* @returns {Uint8Array}
*/
function chunkToU8(chunk) {
function chunkToU8(chunk) {
return typeof chunk === "string" ? core.encode(chunk) : chunk;
}
}
/**
/**
* @param {Uint8Array | string} chunk
* @returns {string}
*/
function chunkToString(chunk) {
function chunkToString(chunk) {
return typeof chunk === "string" ? chunk : core.decode(chunk);
}
}
class InnerBody {
class InnerBody {
/**
* @param {ReadableStream<Uint8Array> | { body: Uint8Array | string, consumed: boolean }} stream
*/
@ -216,15 +217,15 @@
proxy.length = this.length;
return proxy;
}
}
}
/**
/**
* @param {any} prototype
* @param {symbol} bodySymbol
* @param {symbol} mimeTypeSymbol
* @returns {void}
*/
function mixinBody(prototype, bodySymbol, mimeTypeSymbol) {
function mixinBody(prototype, bodySymbol, mimeTypeSymbol) {
async function consumeBody(object, type) {
webidl.assertBranded(object, prototype);
@ -316,15 +317,15 @@
},
};
return ObjectDefineProperties(prototype, mixin);
}
}
/**
/**
* https://fetch.spec.whatwg.org/#concept-body-package-data
* @param {Uint8Array | string} bytes
* @param {"ArrayBuffer" | "Blob" | "FormData" | "JSON" | "text"} type
* @param {MimeType | null} [mimeType]
*/
function packageData(bytes, type, mimeType) {
function packageData(bytes, type, mimeType) {
switch (type) {
case "ArrayBuffer":
return chunkToU8(bytes).buffer;
@ -362,13 +363,13 @@
case "text":
return chunkToString(bytes);
}
}
}
/**
/**
* @param {BodyInit} object
* @returns {{body: InnerBody, contentType: string | null}}
*/
function extractBody(object) {
function extractBody(object) {
/** @type {ReadableStream<Uint8Array> | { body: Uint8Array | string, consumed: boolean }} */
let stream;
let source = null;
@ -433,9 +434,9 @@
body.source = source;
body.length = length;
return { body, contentType };
}
}
webidl.converters["BodyInit_DOMString"] = (V, opts) => {
webidl.converters["BodyInit_DOMString"] = (V, opts) => {
// Union for (ReadableStream or Blob or ArrayBufferView or ArrayBuffer or FormData or URLSearchParams or USVString)
if (ObjectPrototypeIsPrototypeOf(ReadableStreamPrototype, V)) {
return webidl.converters["ReadableStream"](V, opts);
@ -462,10 +463,9 @@
// core.encode() will UTF-8 encode strings with replacement, being equivalent to the USV normalization.
// Therefore we can convert to DOMString instead of USVString and avoid a costly redundant conversion.
return webidl.converters["DOMString"](V, opts);
};
webidl.converters["BodyInit_DOMString?"] = webidl.createNullableConverter(
};
webidl.converters["BodyInit_DOMString?"] = webidl.createNullableConverter(
webidl.converters["BodyInit_DOMString"],
);
);
window.__bootstrap.fetchBody = { mixinBody, InnerBody, extractBody };
})(globalThis);
export { extractBody, InnerBody, mixinBody };

View file

@ -9,26 +9,24 @@
/// <reference path="../web/06_streams_types.d.ts" />
/// <reference path="./lib.deno_fetch.d.ts" />
/// <reference lib="esnext" />
"use strict";
((window) => {
const core = window.Deno.core;
const ops = core.ops;
const core = globalThis.Deno.core;
const ops = core.ops;
/**
/**
* @param {Deno.CreateHttpClientOptions} options
* @returns {HttpClient}
*/
function createHttpClient(options) {
function createHttpClient(options) {
options.caCerts ??= [];
return new HttpClient(
ops.op_fetch_custom_client(
options,
),
);
}
}
class HttpClient {
class HttpClient {
/**
* @param {number} rid
*/
@ -38,11 +36,7 @@
close() {
core.close(this.rid);
}
}
const HttpClientPrototype = HttpClient.prototype;
}
const HttpClientPrototype = HttpClient.prototype;
window.__bootstrap.fetch ??= {};
window.__bootstrap.fetch.createHttpClient = createHttpClient;
window.__bootstrap.fetch.HttpClient = HttpClient;
window.__bootstrap.fetch.HttpClientPrototype = HttpClientPrototype;
})(globalThis);
export { createHttpClient, HttpClient, HttpClientPrototype };

View file

@ -8,27 +8,33 @@
/// <reference path="../web/06_streams_types.d.ts" />
/// <reference path="./lib.deno_fetch.d.ts" />
/// <reference lib="esnext" />
"use strict";
((window) => {
const webidl = window.__bootstrap.webidl;
const consoleInternal = window.__bootstrap.console;
const { HTTP_TOKEN_CODE_POINT_RE, byteUpperCase } = window.__bootstrap.infra;
const { URL } = window.__bootstrap.url;
const { guardFromHeaders } = window.__bootstrap.headers;
const { mixinBody, extractBody, InnerBody } = window.__bootstrap.fetchBody;
const { getLocationHref } = window.__bootstrap.location;
const { extractMimeType } = window.__bootstrap.mimesniff;
const { blobFromObjectUrl } = window.__bootstrap.file;
const {
headersFromHeaderList,
headerListFromHeaders,
import * as webidl from "internal:ext/webidl/00_webidl.js";
import { createFilteredInspectProxy } from "internal:ext/console/02_console.js";
import {
byteUpperCase,
HTTP_TOKEN_CODE_POINT_RE,
} from "internal:ext/web/00_infra.js";
import { URL } from "internal:ext/url/00_url.js";
import {
extractBody,
InnerBody,
mixinBody,
} from "internal:ext/fetch/22_body.js";
import { getLocationHref } from "internal:ext/web/12_location.js";
import { extractMimeType } from "internal:ext/web/01_mimesniff.js";
import { blobFromObjectUrl } from "internal:ext/web/09_file.js";
import {
fillHeaders,
getDecodeSplitHeader,
} = window.__bootstrap.headers;
const { HttpClientPrototype } = window.__bootstrap.fetch;
const abortSignal = window.__bootstrap.abortSignal;
const {
guardFromHeaders,
headerListFromHeaders,
headersFromHeaderList,
} from "internal:ext/fetch/20_headers.js";
import { HttpClientPrototype } from "internal:ext/fetch/22_http_client.js";
import * as abortSignal from "internal:ext/web/03_abort_signal.js";
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayPrototypeMap,
ArrayPrototypeSlice,
ArrayPrototypeSplice,
@ -38,33 +44,33 @@
Symbol,
SymbolFor,
TypeError,
} = window.__bootstrap.primordials;
} = primordials;
const _request = Symbol("request");
const _headers = Symbol("headers");
const _getHeaders = Symbol("get headers");
const _headersCache = Symbol("headers cache");
const _signal = Symbol("signal");
const _mimeType = Symbol("mime type");
const _body = Symbol("body");
const _flash = Symbol("flash");
const _url = Symbol("url");
const _method = Symbol("method");
const _request = Symbol("request");
const _headers = Symbol("headers");
const _getHeaders = Symbol("get headers");
const _headersCache = Symbol("headers cache");
const _signal = Symbol("signal");
const _mimeType = Symbol("mime type");
const _body = Symbol("body");
const _flash = Symbol("flash");
const _url = Symbol("url");
const _method = Symbol("method");
/**
/**
* @param {(() => string)[]} urlList
* @param {string[]} urlListProcessed
*/
function processUrlList(urlList, urlListProcessed) {
function processUrlList(urlList, urlListProcessed) {
for (let i = 0; i < urlList.length; i++) {
if (urlListProcessed[i] === undefined) {
urlListProcessed[i] = urlList[i]();
}
}
return urlListProcessed;
}
}
/**
/**
* @typedef InnerRequest
* @property {() => string} method
* @property {() => string} url
@ -79,7 +85,7 @@
* @property {Blob | null} blobUrlEntry
*/
/**
/**
* @param {() => string} method
* @param {string | () => string} url
* @param {() => [string, string][]} headerList
@ -87,7 +93,7 @@
* @param {boolean} maybeBlob
* @returns {InnerRequest}
*/
function newInnerRequest(method, url, headerList, body, maybeBlob) {
function newInnerRequest(method, url, headerList, body, maybeBlob) {
let blobUrlEntry = null;
if (maybeBlob && typeof url === "string" && url.startsWith("blob:")) {
blobUrlEntry = blobFromObjectUrl(url);
@ -150,16 +156,16 @@
return this.urlListProcessed[currentIndex];
},
};
}
}
/**
/**
* https://fetch.spec.whatwg.org/#concept-request-clone
* @param {InnerRequest} request
* @param {boolean} skipBody
* @param {boolean} flash
* @returns {InnerRequest}
*/
function cloneInnerRequest(request, skipBody = false, flash = false) {
function cloneInnerRequest(request, skipBody = false, flash = false) {
const headerList = ArrayPrototypeMap(
request.headerList,
(x) => [x[0], x[1]],
@ -215,13 +221,13 @@
return this.urlListProcessed[currentIndex];
},
};
}
}
/**
/**
* @param {string} m
* @returns {boolean}
*/
function isKnownMethod(m) {
function isKnownMethod(m) {
return (
m === "DELETE" ||
m === "GET" ||
@ -230,12 +236,12 @@
m === "POST" ||
m === "PUT"
);
}
/**
}
/**
* @param {string} m
* @returns {string}
*/
function validateAndNormalizeMethod(m) {
function validateAndNormalizeMethod(m) {
// Fast path for well-known methods
if (isKnownMethod(m)) {
return m;
@ -252,9 +258,9 @@
throw new TypeError("Method is forbidden.");
}
return upperCase;
}
}
class Request {
class Request {
/** @type {InnerRequest} */
[_request];
/** @type {Headers} */
@ -530,7 +536,7 @@
}
[SymbolFor("Deno.customInspect")](inspect) {
return inspect(consoleInternal.createFilteredInspectProxy({
return inspect(createFilteredInspectProxy({
object: this,
evaluate: ObjectPrototypeIsPrototypeOf(RequestPrototype, this),
keys: [
@ -542,17 +548,17 @@
],
}));
}
}
}
webidl.configurePrototype(Request);
const RequestPrototype = Request.prototype;
mixinBody(RequestPrototype, _body, _mimeType);
webidl.configurePrototype(Request);
const RequestPrototype = Request.prototype;
mixinBody(RequestPrototype, _body, _mimeType);
webidl.converters["Request"] = webidl.createInterfaceConverter(
webidl.converters["Request"] = webidl.createInterfaceConverter(
"Request",
RequestPrototype,
);
webidl.converters["RequestInfo_DOMString"] = (V, opts) => {
);
webidl.converters["RequestInfo_DOMString"] = (V, opts) => {
// Union for (Request or USVString)
if (typeof V == "object") {
if (ObjectPrototypeIsPrototypeOf(RequestPrototype, V)) {
@ -561,16 +567,16 @@
}
// Passed to new URL(...) which implicitly converts DOMString -> USVString
return webidl.converters["DOMString"](V, opts);
};
webidl.converters["RequestRedirect"] = webidl.createEnumConverter(
};
webidl.converters["RequestRedirect"] = webidl.createEnumConverter(
"RequestRedirect",
[
"follow",
"error",
"manual",
],
);
webidl.converters["RequestInit"] = webidl.createDictionaryConverter(
);
webidl.converters["RequestInit"] = webidl.createDictionaryConverter(
"RequestInit",
[
{ key: "method", converter: webidl.converters["ByteString"] },
@ -590,24 +596,24 @@
},
{ key: "client", converter: webidl.converters.any },
],
);
);
/**
/**
* @param {Request} request
* @returns {InnerRequest}
*/
function toInnerRequest(request) {
function toInnerRequest(request) {
return request[_request];
}
}
/**
/**
* @param {InnerRequest} inner
* @param {AbortSignal} signal
* @param {"request" | "immutable" | "request-no-cors" | "response" | "none"} guard
* @param {boolean} flash
* @returns {Request}
*/
function fromInnerRequest(inner, signal, guard, flash) {
function fromInnerRequest(inner, signal, guard, flash) {
const request = webidl.createBranded(Request);
if (flash) {
request[_flash] = inner;
@ -619,9 +625,9 @@
? () => headersFromHeaderList(inner.headerList(), guard)
: () => headersFromHeaderList(inner.headerList, guard);
return request;
}
}
/**
/**
* @param {number} serverId
* @param {number} streamRid
* @param {ReadableStream} body
@ -630,14 +636,14 @@
* @param {() => [string, string][]} headersCb
* @returns {Request}
*/
function fromFlashRequest(
function fromFlashRequest(
serverId,
streamRid,
body,
methodCb,
urlCb,
headersCb,
) {
) {
const request = webidl.createBranded(Request);
request[_flash] = {
body: body !== null ? new InnerBody(body) : null,
@ -651,14 +657,15 @@
};
request[_getHeaders] = () => headersFromHeaderList(headersCb(), "request");
return request;
}
}
window.__bootstrap.fetch ??= {};
window.__bootstrap.fetch.Request = Request;
window.__bootstrap.fetch.toInnerRequest = toInnerRequest;
window.__bootstrap.fetch.fromFlashRequest = fromFlashRequest;
window.__bootstrap.fetch.fromInnerRequest = fromInnerRequest;
window.__bootstrap.fetch.newInnerRequest = newInnerRequest;
window.__bootstrap.fetch.processUrlList = processUrlList;
window.__bootstrap.fetch._flash = _flash;
})(globalThis);
export {
_flash,
fromFlashRequest,
fromInnerRequest,
newInnerRequest,
processUrlList,
Request,
RequestPrototype,
toInnerRequest,
};

View file

@ -9,29 +9,29 @@
/// <reference path="../web/06_streams_types.d.ts" />
/// <reference path="./lib.deno_fetch.d.ts" />
/// <reference lib="esnext" />
"use strict";
((window) => {
const { isProxy } = Deno.core;
const webidl = window.__bootstrap.webidl;
const consoleInternal = window.__bootstrap.console;
const {
const core = globalThis.Deno.core;
import * as webidl from "internal:ext/webidl/00_webidl.js";
import { createFilteredInspectProxy } from "internal:ext/console/02_console.js";
import {
byteLowerCase,
} = window.__bootstrap.infra;
const { HTTP_TAB_OR_SPACE, regexMatcher, serializeJSValueToJSONString } =
window.__bootstrap.infra;
const { extractBody, mixinBody } = window.__bootstrap.fetchBody;
const { getLocationHref } = window.__bootstrap.location;
const { extractMimeType } = window.__bootstrap.mimesniff;
const { URL } = window.__bootstrap.url;
const {
HTTP_TAB_OR_SPACE,
regexMatcher,
serializeJSValueToJSONString,
} from "internal:ext/web/00_infra.js";
import { extractBody, mixinBody } from "internal:ext/fetch/22_body.js";
import { getLocationHref } from "internal:ext/web/12_location.js";
import { extractMimeType } from "internal:ext/web/01_mimesniff.js";
import { URL } from "internal:ext/url/00_url.js";
import {
fillHeaders,
getDecodeSplitHeader,
guardFromHeaders,
headerListFromHeaders,
headersFromHeaderList,
guardFromHeaders,
fillHeaders,
} = window.__bootstrap.headers;
const {
} from "internal:ext/fetch/20_headers.js";
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayPrototypeMap,
ArrayPrototypePush,
ObjectDefineProperties,
@ -43,25 +43,25 @@
Symbol,
SymbolFor,
TypeError,
} = window.__bootstrap.primordials;
} = primordials;
const VCHAR = ["\x21-\x7E"];
const OBS_TEXT = ["\x80-\xFF"];
const VCHAR = ["\x21-\x7E"];
const OBS_TEXT = ["\x80-\xFF"];
const REASON_PHRASE = [
const REASON_PHRASE = [
...new SafeArrayIterator(HTTP_TAB_OR_SPACE),
...new SafeArrayIterator(VCHAR),
...new SafeArrayIterator(OBS_TEXT),
];
const REASON_PHRASE_MATCHER = regexMatcher(REASON_PHRASE);
const REASON_PHRASE_RE = new RegExp(`^[${REASON_PHRASE_MATCHER}]*$`);
];
const REASON_PHRASE_MATCHER = regexMatcher(REASON_PHRASE);
const REASON_PHRASE_RE = new RegExp(`^[${REASON_PHRASE_MATCHER}]*$`);
const _response = Symbol("response");
const _headers = Symbol("headers");
const _mimeType = Symbol("mime type");
const _body = Symbol("body");
const _response = Symbol("response");
const _headers = Symbol("headers");
const _mimeType = Symbol("mime type");
const _body = Symbol("body");
/**
/**
* @typedef InnerResponse
* @property {"basic" | "cors" | "default" | "error" | "opaque" | "opaqueredirect"} type
* @property {() => string | null} url
@ -74,29 +74,29 @@
* @property {string} [error]
*/
/**
/**
* @param {number} status
* @returns {boolean}
*/
function nullBodyStatus(status) {
function nullBodyStatus(status) {
return status === 101 || status === 204 || status === 205 || status === 304;
}
}
/**
/**
* @param {number} status
* @returns {boolean}
*/
function redirectStatus(status) {
function redirectStatus(status) {
return status === 301 || status === 302 || status === 303 ||
status === 307 || status === 308;
}
}
/**
/**
* https://fetch.spec.whatwg.org/#concept-response-clone
* @param {InnerResponse} response
* @returns {InnerResponse}
*/
function cloneInnerResponse(response) {
function cloneInnerResponse(response) {
const urlList = [...new SafeArrayIterator(response.urlList)];
const headerList = ArrayPrototypeMap(
response.headerList,
@ -121,12 +121,12 @@
return this.urlList[this.urlList.length - 1];
},
};
}
}
/**
/**
* @returns {InnerResponse}
*/
function newInnerResponse(status = 200, statusMessage = "") {
function newInnerResponse(status = 200, statusMessage = "") {
return {
type: "default",
body: null,
@ -140,35 +140,35 @@
return this.urlList[this.urlList.length - 1];
},
};
}
}
/**
/**
* @param {string} error
* @returns {InnerResponse}
*/
function networkError(error) {
function networkError(error) {
const resp = newInnerResponse(0);
resp.type = "error";
resp.error = error;
return resp;
}
}
/**
/**
* @returns {InnerResponse}
*/
function abortedNetworkError() {
function abortedNetworkError() {
const resp = networkError("aborted");
resp.aborted = true;
return resp;
}
}
/**
/**
* https://fetch.spec.whatwg.org#initialize-a-response
* @param {Response} response
* @param {ResponseInit} init
* @param {{ body: __bootstrap.fetchBody.InnerBody, contentType: string | null } | null} bodyWithType
* @param {{ body: fetchBody.InnerBody, contentType: string | null } | null} bodyWithType
*/
function initializeAResponse(response, init, bodyWithType) {
function initializeAResponse(response, init, bodyWithType) {
// 1.
if ((init.status < 200 || init.status > 599) && init.status != 101) {
throw new RangeError(
@ -190,7 +190,7 @@
// 4.
response[_response].statusMessage = init.statusText;
// 5.
/** @type {__bootstrap.headers.Headers} */
/** @type {headers.Headers} */
const headers = response[_headers];
if (init.headers) {
fillHeaders(headers, init.headers);
@ -221,9 +221,9 @@
}
}
}
}
}
class Response {
class Response {
get [_mimeType]() {
const values = getDecodeSplitHeader(
headerListFromHeaders(this[_headers]),
@ -418,7 +418,7 @@
}
[SymbolFor("Deno.customInspect")](inspect) {
return inspect(consoleInternal.createFilteredInspectProxy({
return inspect(createFilteredInspectProxy({
object: this,
evaluate: ObjectPrototypeIsPrototypeOf(ResponsePrototype, this),
keys: [
@ -433,22 +433,22 @@
],
}));
}
}
}
webidl.configurePrototype(Response);
ObjectDefineProperties(Response, {
webidl.configurePrototype(Response);
ObjectDefineProperties(Response, {
json: { enumerable: true },
redirect: { enumerable: true },
error: { enumerable: true },
});
const ResponsePrototype = Response.prototype;
mixinBody(ResponsePrototype, _body, _mimeType);
});
const ResponsePrototype = Response.prototype;
mixinBody(ResponsePrototype, _body, _mimeType);
webidl.converters["Response"] = webidl.createInterfaceConverter(
webidl.converters["Response"] = webidl.createInterfaceConverter(
"Response",
ResponsePrototype,
);
webidl.converters["ResponseInit"] = webidl.createDictionaryConverter(
);
webidl.converters["ResponseInit"] = webidl.createDictionaryConverter(
"ResponseInit",
[{
key: "status",
@ -462,13 +462,13 @@
key: "headers",
converter: webidl.converters["HeadersInit"],
}],
);
webidl.converters["ResponseInit_fast"] = function (init, opts) {
);
webidl.converters["ResponseInit_fast"] = function (init, opts) {
if (init === undefined || init === null) {
return { status: 200, statusText: "", headers: undefined };
}
// Fast path, if not a proxy
if (typeof init === "object" && !isProxy(init)) {
if (typeof init === "object" && !core.isProxy(init)) {
// Not a proxy fast path
const status = init.status !== undefined
? webidl.converters["unsigned short"](init.status)
@ -483,36 +483,36 @@
}
// Slow default path
return webidl.converters["ResponseInit"](init, opts);
};
};
/**
/**
* @param {Response} response
* @returns {InnerResponse}
*/
function toInnerResponse(response) {
function toInnerResponse(response) {
return response[_response];
}
}
/**
/**
* @param {InnerResponse} inner
* @param {"request" | "immutable" | "request-no-cors" | "response" | "none"} guard
* @returns {Response}
*/
function fromInnerResponse(inner, guard) {
function fromInnerResponse(inner, guard) {
const response = webidl.createBranded(Response);
response[_response] = inner;
response[_headers] = headersFromHeaderList(inner.headerList, guard);
return response;
}
}
window.__bootstrap.fetch ??= {};
window.__bootstrap.fetch.Response = Response;
window.__bootstrap.fetch.ResponsePrototype = ResponsePrototype;
window.__bootstrap.fetch.newInnerResponse = newInnerResponse;
window.__bootstrap.fetch.toInnerResponse = toInnerResponse;
window.__bootstrap.fetch.fromInnerResponse = fromInnerResponse;
window.__bootstrap.fetch.redirectStatus = redirectStatus;
window.__bootstrap.fetch.nullBodyStatus = nullBodyStatus;
window.__bootstrap.fetch.networkError = networkError;
window.__bootstrap.fetch.abortedNetworkError = abortedNetworkError;
})(globalThis);
export {
abortedNetworkError,
fromInnerResponse,
networkError,
newInnerResponse,
nullBodyStatus,
redirectStatus,
Response,
ResponsePrototype,
toInnerResponse,
};

View file

@ -9,29 +9,33 @@
/// <reference path="./internal.d.ts" />
/// <reference path="./lib.deno_fetch.d.ts" />
/// <reference lib="esnext" />
"use strict";
((window) => {
const core = window.Deno.core;
const ops = core.ops;
const webidl = window.__bootstrap.webidl;
const { byteLowerCase } = window.__bootstrap.infra;
const { BlobPrototype } = window.__bootstrap.file;
const { errorReadableStream, ReadableStreamPrototype, readableStreamForRid } =
window.__bootstrap.streams;
const { InnerBody, extractBody } = window.__bootstrap.fetchBody;
const {
toInnerRequest,
toInnerResponse,
fromInnerResponse,
redirectStatus,
nullBodyStatus,
networkError,
abortedNetworkError,
const core = globalThis.Deno.core;
const ops = core.ops;
import * as webidl from "internal:ext/webidl/00_webidl.js";
import { byteLowerCase } from "internal:ext/web/00_infra.js";
import { BlobPrototype } from "internal:ext/web/09_file.js";
import {
errorReadableStream,
readableStreamForRid,
ReadableStreamPrototype,
} from "internal:ext/web/06_streams.js";
import { extractBody, InnerBody } from "internal:ext/fetch/22_body.js";
import {
processUrlList,
} = window.__bootstrap.fetch;
const abortSignal = window.__bootstrap.abortSignal;
const {
toInnerRequest,
} from "internal:ext/fetch/23_request.js";
import {
abortedNetworkError,
fromInnerResponse,
networkError,
nullBodyStatus,
redirectStatus,
toInnerResponse,
} from "internal:ext/fetch/23_response.js";
import * as abortSignal from "internal:ext/web/03_abort_signal.js";
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayPrototypePush,
ArrayPrototypeSplice,
ArrayPrototypeFilter,
@ -52,23 +56,23 @@
WeakMapPrototypeGet,
WeakMapPrototypeHas,
WeakMapPrototypeSet,
} = window.__bootstrap.primordials;
} = primordials;
const REQUEST_BODY_HEADER_NAMES = [
const REQUEST_BODY_HEADER_NAMES = [
"content-encoding",
"content-language",
"content-location",
"content-type",
];
];
const requestBodyReaders = new WeakMap();
const requestBodyReaders = new WeakMap();
/**
/**
* @param {{ method: string, url: string, headers: [string, string][], clientRid: number | null, hasBody: boolean }} args
* @param {Uint8Array | null} body
* @returns {{ requestRid: number, requestBodyRid: number | null }}
*/
function opFetch(method, url, headers, clientRid, hasBody, bodyLength, body) {
function opFetch(method, url, headers, clientRid, hasBody, bodyLength, body) {
return ops.op_fetch(
method,
url,
@ -78,22 +82,22 @@
bodyLength,
body,
);
}
}
/**
/**
* @param {number} rid
* @returns {Promise<{ status: number, statusText: string, headers: [string, string][], url: string, responseRid: number }>}
*/
function opFetchSend(rid) {
function opFetchSend(rid) {
return core.opAsync("op_fetch_send", rid);
}
}
/**
/**
* @param {number} responseBodyRid
* @param {AbortSignal} [terminator]
* @returns {ReadableStream<Uint8Array>}
*/
function createResponseBodyStream(responseBodyRid, terminator) {
function createResponseBodyStream(responseBodyRid, terminator) {
const readable = readableStreamForRid(responseBodyRid);
function onAbort() {
@ -105,15 +109,15 @@
terminator[abortSignal.add](onAbort);
return readable;
}
}
/**
/**
* @param {InnerRequest} req
* @param {boolean} recursive
* @param {AbortSignal} terminator
* @returns {Promise<InnerResponse>}
*/
async function mainFetch(req, recursive, terminator) {
async function mainFetch(req, recursive, terminator) {
if (req.blobUrlEntry !== null) {
if (req.method !== "GET") {
throw new TypeError("Blob URL fetch only supports GET method.");
@ -185,9 +189,7 @@
req.clientRid,
reqBody !== null,
req.body?.length,
ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, reqBody)
? reqBody
: null,
ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, reqBody) ? reqBody : null,
);
function onAbort() {
@ -333,15 +335,15 @@
}
return response;
}
}
/**
/**
* @param {InnerRequest} request
* @param {InnerResponse} response
* @param {AbortSignal} terminator
* @returns {Promise<InnerResponse>}
*/
function httpRedirectFetch(request, response, terminator) {
function httpRedirectFetch(request, response, terminator) {
const locationHeaders = ArrayPrototypeFilter(
response.headerList,
(entry) => byteLowerCase(entry[0]) === "location",
@ -399,13 +401,13 @@
}
ArrayPrototypePush(request.urlList, () => locationURL.href);
return mainFetch(request, true, terminator);
}
}
/**
/**
* @param {RequestInfo} input
* @param {RequestInit} init
*/
function fetch(input, init = {}) {
function fetch(input, init = {}) {
// There is an async dispatch later that causes a stack trace disconnect.
// We reconnect it by assigning the result of that dispatch to `opPromise`,
// awaiting `opPromise` in an inner function also named `fetch()` and
@ -493,9 +495,9 @@
})();
}
return result;
}
}
function abortFetch(request, responseObject, error) {
function abortFetch(request, responseObject, error) {
if (request.body !== null) {
if (WeakMapPrototypeHas(requestBodyReaders, request)) {
WeakMapPrototypeGet(requestBodyReaders, request).cancel(error);
@ -508,9 +510,9 @@
if (response.body !== null) response.body.error(error);
}
return error;
}
}
/**
/**
* Handle the Response argument to the WebAssembly streaming APIs, after
* resolving if it was passed as a promise. This function should be registered
* through `Deno.core.setWasmStreamingCallback`.
@ -520,7 +522,7 @@
* value of that promise.
* @param {number} rid An rid that represents the wasm streaming resource.
*/
function handleWasmStreaming(source, rid) {
function handleWasmStreaming(source, rid) {
// This implements part of
// https://webassembly.github.io/spec/web-api/#compile-a-potential-webassembly-response
try {
@ -578,9 +580,6 @@
// 2.8
core.abortWasmStreaming(rid, err);
}
}
}
window.__bootstrap.fetch ??= {};
window.__bootstrap.fetch.fetch = fetch;
window.__bootstrap.fetch.handleWasmStreaming = handleWasmStreaming;
})(this);
export { fetch, handleWasmStreaming };

View file

@ -5,17 +5,11 @@
/// <reference no-default-lib="true" />
/// <reference lib="esnext" />
declare namespace globalThis {
declare namespace __bootstrap {
declare var fetchUtil: {
requiredArguments(name: string, length: number, required: number): void;
};
declare var domIterable: {
declare var domIterable: {
DomIterableMixin(base: any, dataSymbol: symbol): any;
};
};
declare namespace headers {
declare module "internal:ext/fetch/20_headers.js" {
class Headers {
}
type HeaderList = [string, string][];
@ -37,21 +31,21 @@ declare namespace globalThis {
function guardFromHeaders(
headers: Headers,
): "immutable" | "request" | "request-no-cors" | "response" | "none";
}
}
declare namespace formData {
declare type FormData = typeof FormData;
declare function formDataToBlob(
formData: globalThis.FormData,
declare module "internal:ext/fetch/21_formdata.js" {
type FormData = typeof FormData;
function formDataToBlob(
formData: FormData,
): Blob;
declare function parseFormData(
function parseFormData(
body: Uint8Array,
boundary: string | undefined,
): FormData;
declare function formDataFromEntries(entries: FormDataEntry[]): FormData;
}
function formDataFromEntries(entries: FormDataEntry[]): FormData;
}
declare namespace fetchBody {
declare module "internal:ext/fetch/22_body.js" {
function mixinBody(
prototype: any,
bodySymbol: symbol,
@ -70,9 +64,9 @@ declare namespace globalThis {
body: InnerBody;
contentType: string | null;
};
}
}
declare namespace fetch {
declare module "internal:ext/fetch/26_fetch.js" {
function toInnerRequest(request: Request): InnerRequest;
function fromInnerRequest(
inner: InnerRequest,
@ -92,7 +86,7 @@ declare namespace globalThis {
method: string,
url: any,
headerList?: [string, string][],
body?: globalThis.__bootstrap.fetchBody.InnerBody,
body?: fetchBody.InnerBody,
): InnerResponse;
function toInnerResponse(response: Response): InnerResponse;
function fromInnerResponse(
@ -105,6 +99,4 @@ declare namespace globalThis {
| "none",
): Response;
function networkError(error: string): InnerResponse;
}
}
}

View file

@ -97,9 +97,8 @@ where
{
Extension::builder(env!("CARGO_PKG_NAME"))
.dependencies(vec!["deno_webidl", "deno_web", "deno_url", "deno_console"])
.js(include_js_files!(
.esm(include_js_files!(
prefix "internal:ext/fetch",
"01_fetch_util.js",
"20_headers.js",
"21_formdata.js",
"22_body.js",

View file

@ -1,11 +1,10 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
"use strict";
((window) => {
const core = window.Deno.core;
const ops = core.ops;
const __bootstrap = window.__bootstrap;
const {
const core = globalThis.Deno.core;
const ops = core.ops;
const internals = globalThis.__bootstrap.internals;
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayPrototypeMap,
ArrayPrototypeJoin,
ObjectDefineProperty,
@ -26,12 +25,12 @@
MathCeil,
SafeMap,
SafeArrayIterator,
} = window.__bootstrap.primordials;
} = primordials;
const U32_BUFFER = new Uint32Array(2);
const U64_BUFFER = new BigUint64Array(U32_BUFFER.buffer);
const I64_BUFFER = new BigInt64Array(U32_BUFFER.buffer);
class UnsafePointerView {
const U32_BUFFER = new Uint32Array(2);
const U64_BUFFER = new BigUint64Array(U32_BUFFER.buffer);
const I64_BUFFER = new BigInt64Array(U32_BUFFER.buffer);
class UnsafePointerView {
pointer;
constructor(pointer) {
@ -166,11 +165,11 @@
destination.byteLength,
);
}
}
}
const OUT_BUFFER = new Uint32Array(2);
const OUT_BUFFER_64 = new BigInt64Array(OUT_BUFFER.buffer);
class UnsafePointer {
const OUT_BUFFER = new Uint32Array(2);
const OUT_BUFFER_64 = new BigInt64Array(OUT_BUFFER.buffer);
class UnsafePointer {
static of(value) {
if (ObjectPrototypeIsPrototypeOf(UnsafeCallbackPrototype, value)) {
return value.pointer;
@ -182,9 +181,9 @@
}
return OUT_BUFFER_64[0];
}
}
}
class UnsafeFnPointer {
class UnsafeFnPointer {
pointer;
definition;
#structSize;
@ -238,24 +237,24 @@
}
}
}
}
}
function isReturnedAsBigInt(type) {
function isReturnedAsBigInt(type) {
return type === "buffer" || type === "pointer" || type === "function" ||
type === "u64" || type === "i64" ||
type === "usize" || type === "isize";
}
}
function isI64(type) {
function isI64(type) {
return type === "i64" || type === "isize";
}
}
function isStruct(type) {
function isStruct(type) {
return typeof type === "object" && type !== null &&
typeof type.struct === "object";
}
}
function getTypeSizeAndAlignment(type, cache = new SafeMap()) {
function getTypeSizeAndAlignment(type, cache = new SafeMap()) {
if (isStruct(type)) {
const cached = cache.get(type);
if (cached !== undefined) {
@ -305,9 +304,9 @@
default:
throw new TypeError(`Unsupported type: ${type}`);
}
}
}
class UnsafeCallback {
class UnsafeCallback {
#refcount;
// Internal promise only meant to keep Deno from exiting
#refpromise;
@ -356,11 +355,11 @@
this.#refcount = 0;
core.close(this.#rid);
}
}
}
const UnsafeCallbackPrototype = UnsafeCallback.prototype;
const UnsafeCallbackPrototype = UnsafeCallback.prototype;
class DynamicLibrary {
class DynamicLibrary {
#rid;
symbols = {};
@ -492,19 +491,19 @@
close() {
core.close(this.#rid);
}
}
}
function dlopen(path, symbols) {
function dlopen(path, symbols) {
// TODO(@crowlKats): remove me
// URL support is progressively enhanced by util in `runtime/js`.
const pathFromURL = __bootstrap.util.pathFromURL ?? ((p) => p);
const pathFromURL = internals.pathFromURL ?? ((p) => p);
return new DynamicLibrary(pathFromURL(path), symbols);
}
}
window.__bootstrap.ffi = {
export {
dlopen,
UnsafeCallback,
UnsafeFnPointer,
UnsafePointer,
UnsafePointerView,
UnsafeFnPointer,
};
})(this);
};

View file

@ -84,7 +84,7 @@ pub(crate) struct FfiState {
pub fn init<P: FfiPermissions + 'static>(unstable: bool) -> Extension {
Extension::builder(env!("CARGO_PKG_NAME"))
.js(include_js_files!(
.esm(include_js_files!(
prefix "internal:ext/ffi",
"00_ffi.js",
))

View file

@ -1,32 +1,31 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
"use strict";
((window) => {
const { BlobPrototype } = window.__bootstrap.file;
const { TcpConn } = window.__bootstrap.net;
const { fromFlashRequest, toInnerResponse, _flash } =
window.__bootstrap.fetch;
const core = window.Deno.core;
const { Event } = window.__bootstrap.event;
const {
ReadableStream,
ReadableStreamPrototype,
getReadableStreamResourceBacking,
readableStreamClose,
const core = globalThis.Deno.core;
const ops = core.ops;
const primordials = globalThis.__bootstrap.primordials;
import { BlobPrototype } from "internal:ext/web/09_file.js";
import { TcpConn } from "internal:ext/net/01_net.js";
import { toInnerResponse } from "internal:ext/fetch/23_response.js";
import { _flash, fromFlashRequest } from "internal:ext/fetch/23_request.js";
import { Event } from "internal:ext/web/02_event.js";
import {
_state,
} = window.__bootstrap.streams;
const {
WebSocket,
_rid,
_readyState,
getReadableStreamResourceBacking,
ReadableStream,
readableStreamClose,
ReadableStreamPrototype,
} from "internal:ext/web/06_streams.js";
import {
_eventLoop,
_protocol,
_idleTimeoutDuration,
_idleTimeoutTimeout,
_protocol,
_readyState,
_rid,
_serverHandleIdleTimeout,
} = window.__bootstrap.webSocket;
const { _ws } = window.__bootstrap.http;
const {
WebSocket,
} from "internal:ext/websocket/01_websocket.js";
import { _ws } from "internal:ext/http/01_http.js";
const {
ObjectPrototypeIsPrototypeOf,
PromisePrototype,
PromisePrototypeCatch,
@ -36,9 +35,9 @@
TypeError,
Uint8Array,
Uint8ArrayPrototype,
} = window.__bootstrap.primordials;
} = primordials;
const statusCodes = {
const statusCodes = {
100: "Continue",
101: "Switching Protocols",
102: "Processing",
@ -98,9 +97,9 @@
508: "Loop Detected",
510: "Not Extended",
511: "Network Authentication Required",
};
};
const methods = {
const methods = {
0: "GET",
1: "HEAD",
2: "CONNECT",
@ -110,28 +109,28 @@
6: "TRACE",
7: "POST",
8: "PATCH",
};
};
let dateInterval;
let date;
let dateInterval;
let date;
// Construct an HTTP response message.
// All HTTP/1.1 messages consist of a start-line followed by a sequence
// of octets.
//
// HTTP-message = start-line
// *( header-field CRLF )
// CRLF
// [ message-body ]
//
function http1Response(
// Construct an HTTP response message.
// All HTTP/1.1 messages consist of a start-line followed by a sequence
// of octets.
//
// HTTP-message = start-line
// *( header-field CRLF )
// CRLF
// [ message-body ]
//
function http1Response(
method,
status,
headerList,
body,
bodyLen,
earlyEnd = false,
) {
) {
// HTTP uses a "<major>.<minor>" numbering scheme
// HTTP-version = HTTP-name "/" DIGIT "." DIGIT
// HTTP-name = %x48.54.54.50 ; "HTTP", case-sensitive
@ -186,34 +185,34 @@
}
return str;
}
}
function prepareFastCalls() {
return core.ops.op_flash_make_request();
}
function prepareFastCalls() {
return ops.op_flash_make_request();
}
function hostnameForDisplay(hostname) {
function hostnameForDisplay(hostname) {
// If the hostname is "0.0.0.0", we display "localhost" in console
// because browsers in Windows don't resolve "0.0.0.0".
// See the discussion in https://github.com/denoland/deno_std/issues/1165
return hostname === "0.0.0.0" ? "localhost" : hostname;
}
}
function writeFixedResponse(
function writeFixedResponse(
server,
requestId,
response,
responseLen,
end,
respondFast,
) {
) {
let nwritten = 0;
// TypedArray
if (typeof response !== "string") {
nwritten = respondFast(requestId, response, end);
} else {
// string
nwritten = core.ops.op_flash_respond(
nwritten = ops.op_flash_respond(
server,
requestId,
response,
@ -230,10 +229,10 @@
end,
);
}
}
}
// TODO(@littledivy): Woah woah, cut down the number of arguments.
async function handleResponse(
// TODO(@littledivy): Woah woah, cut down the number of arguments.
async function handleResponse(
req,
resp,
body,
@ -244,7 +243,7 @@
respondFast,
respondChunked,
tryRespondChunked,
) {
) {
// there might've been an HTTP upgrade.
if (resp === undefined) {
return;
@ -433,9 +432,9 @@
ws[_serverHandleIdleTimeout]();
}
})();
}
}
function createServe(opFn) {
function createServe(opFn) {
return async function serve(arg1, arg2) {
let options = undefined;
let handler = undefined;
@ -560,11 +559,11 @@
() => methods[method],
/* urlCb */
() => {
const path = core.ops.op_flash_path(serverId, i);
const path = ops.op_flash_path(serverId, i);
return `${server.transport}://${server.hostname}:${server.port}${path}`;
},
/* headersCb */
() => core.ops.op_flash_headers(serverId, i),
() => ops.op_flash_headers(serverId, i),
);
let resp;
@ -638,7 +637,7 @@
});
function tryRespondChunked(token, chunk, shutdown) {
const nwritten = core.ops.op_try_flash_respond_chunked(
const nwritten = ops.op_try_flash_respond_chunked(
serverId,
token,
chunk ?? new Uint8Array(),
@ -672,10 +671,10 @@
let respondFast = (token, response, shutdown) =>
fastOp.respond(token, response, shutdown);
if (serverId > 0) {
nextRequestSync = () => core.ops.op_flash_next_server(serverId);
getMethodSync = (token) => core.ops.op_flash_method(serverId, token);
nextRequestSync = () => ops.op_flash_next_server(serverId);
getMethodSync = (token) => ops.op_flash_method(serverId, token);
respondFast = (token, response, shutdown) =>
core.ops.op_flash_respond(serverId, token, response, null, shutdown);
ops.op_flash_respond(serverId, token, response, null, shutdown);
}
if (!dateInterval) {
@ -690,11 +689,11 @@
serverPromise,
]);
};
}
}
function createRequestBodyStream(serverId, token) {
function createRequestBodyStream(serverId, token) {
// The first packet is left over bytes after parsing the request
const firstRead = core.ops.op_flash_first_packet(
const firstRead = ops.op_flash_first_packet(
serverId,
token,
);
@ -734,9 +733,9 @@
}
},
});
}
}
function upgradeHttpRaw(req) {
function upgradeHttpRaw(req) {
if (!req[_flash]) {
throw new TypeError(
"Non-flash requests can not be upgraded with `upgradeHttpRaw`. Use `upgradeHttp` instead.",
@ -751,13 +750,9 @@
req.headers;
const { serverId, streamRid } = req[_flash];
const connRid = core.ops.op_flash_upgrade_http(streamRid, serverId);
const connRid = ops.op_flash_upgrade_http(streamRid, serverId);
// TODO(@littledivy): return already read first packet too.
return [new TcpConn(connRid), new Uint8Array()];
}
}
window.__bootstrap.flash = {
createServe,
upgradeHttpRaw,
};
})(this);
export { createServe, upgradeHttpRaw };

View file

@ -1514,7 +1514,7 @@ pub fn init<P: FlashPermissions + 'static>(unstable: bool) -> Extension {
"deno_websocket",
"deno_http",
])
.js(deno_core::include_js_files!(
.esm(deno_core::include_js_files!(
prefix "internal:ext/flash",
"01_http.js",
))

View file

@ -1,45 +1,44 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
"use strict";
((window) => {
const webidl = window.__bootstrap.webidl;
const { InnerBody } = window.__bootstrap.fetchBody;
const { Event } = window.__bootstrap.event;
const { setEventTargetData } = window.__bootstrap.eventTarget;
const { BlobPrototype } = window.__bootstrap.file;
const {
ResponsePrototype,
fromInnerRequest,
toInnerResponse,
newInnerRequest,
newInnerResponse,
const core = globalThis.Deno.core;
const primordials = globalThis.__bootstrap.primordials;
const { BadResourcePrototype, InterruptedPrototype, ops } = core;
import * as webidl from "internal:ext/webidl/00_webidl.js";
import { InnerBody } from "internal:ext/fetch/22_body.js";
import { Event, setEventTargetData } from "internal:ext/web/02_event.js";
import { BlobPrototype } from "internal:ext/web/09_file.js";
import {
fromInnerResponse,
newInnerResponse,
ResponsePrototype,
toInnerResponse,
} from "internal:ext/fetch/23_response.js";
import {
_flash,
} = window.__bootstrap.fetch;
const core = window.Deno.core;
const { BadResourcePrototype, InterruptedPrototype, ops } = core;
const { ReadableStreamPrototype } = window.__bootstrap.streams;
const abortSignal = window.__bootstrap.abortSignal;
const {
WebSocket,
_rid,
_readyState,
fromInnerRequest,
newInnerRequest,
} from "internal:ext/fetch/23_request.js";
import * as abortSignal from "internal:ext/web/03_abort_signal.js";
import {
_eventLoop,
_protocol,
_server,
_idleTimeoutDuration,
_idleTimeoutTimeout,
_protocol,
_readyState,
_rid,
_server,
_serverHandleIdleTimeout,
} = window.__bootstrap.webSocket;
const { TcpConn, UnixConn } = window.__bootstrap.net;
const { TlsConn } = window.__bootstrap.tls;
const {
WebSocket,
} from "internal:ext/websocket/01_websocket.js";
import { TcpConn, UnixConn } from "internal:ext/net/01_net.js";
import { TlsConn } from "internal:ext/net/02_tls.js";
import {
Deferred,
getReadableStreamResourceBacking,
readableStreamForRid,
readableStreamClose,
} = window.__bootstrap.streams;
const {
readableStreamForRid,
ReadableStreamPrototype,
} from "internal:ext/web/06_streams.js";
const {
ArrayPrototypeIncludes,
ArrayPrototypePush,
ArrayPrototypeSome,
@ -57,12 +56,12 @@
TypeError,
Uint8Array,
Uint8ArrayPrototype,
} = window.__bootstrap.primordials;
} = primordials;
const connErrorSymbol = Symbol("connError");
const _deferred = Symbol("upgradeHttpDeferred");
const connErrorSymbol = Symbol("connError");
const _deferred = Symbol("upgradeHttpDeferred");
class HttpConn {
class HttpConn {
#rid = 0;
#closed = false;
#remoteAddr;
@ -176,15 +175,15 @@
},
};
}
}
}
function createRespondWith(
function createRespondWith(
httpConn,
streamRid,
request,
remoteAddr,
localAddr,
) {
) {
return async function respondWith(resp) {
try {
resp = await resp;
@ -386,11 +385,11 @@
}
}
};
}
}
const _ws = Symbol("[[associated_ws]]");
const _ws = Symbol("[[associated_ws]]");
function upgradeWebSocket(request, options = {}) {
function upgradeWebSocket(request, options = {}) {
const upgrade = request.headers.get("upgrade");
const upgradeHasWebSocketOption = upgrade !== null &&
ArrayPrototypeSome(
@ -456,9 +455,9 @@
socket[_idleTimeoutTimeout] = null;
return { response, socket };
}
}
function upgradeHttp(req) {
function upgradeHttp(req) {
if (req[_flash]) {
throw new TypeError(
"Flash requests can not be upgraded with `upgradeHttp`. Use `upgradeHttpRaw` instead.",
@ -467,12 +466,6 @@
req[_deferred] = new Deferred();
return req[_deferred].promise;
}
}
window.__bootstrap.http = {
HttpConn,
upgradeWebSocket,
upgradeHttp,
_ws,
};
})(this);
export { _ws, HttpConn, upgradeHttp, upgradeWebSocket };

View file

@ -80,7 +80,7 @@ mod reader_stream;
pub fn init() -> Extension {
Extension::builder(env!("CARGO_PKG_NAME"))
.dependencies(vec!["deno_web", "deno_net", "deno_fetch", "deno_websocket"])
.js(include_js_files!(
.esm(include_js_files!(
prefix "internal:ext/http",
"01_http.js",
))

View file

@ -1,16 +1,15 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
"use strict";
((window) => {
const core = window.Deno.core;
const { BadResourcePrototype, InterruptedPrototype, ops } = core;
const {
const core = globalThis.Deno.core;
const { BadResourcePrototype, InterruptedPrototype, ops } = core;
import {
readableStreamForRidUnrefable,
readableStreamForRidUnrefableRef,
readableStreamForRidUnrefableUnref,
writableStreamForRid,
} = window.__bootstrap.streams;
const {
} from "internal:ext/web/06_streams.js";
const primordials = globalThis.__bootstrap.primordials;
const {
Error,
ObjectPrototypeIsPrototypeOf,
PromiseResolve,
@ -19,23 +18,23 @@
TypedArrayPrototypeSubarray,
TypeError,
Uint8Array,
} = window.__bootstrap.primordials;
} = primordials;
const promiseIdSymbol = SymbolFor("Deno.core.internalPromiseId");
const promiseIdSymbol = SymbolFor("Deno.core.internalPromiseId");
async function write(rid, data) {
async function write(rid, data) {
return await core.write(rid, data);
}
}
function shutdown(rid) {
function shutdown(rid) {
return core.shutdown(rid);
}
}
function resolveDns(query, recordType, options) {
function resolveDns(query, recordType, options) {
return core.opAsync("op_dns_resolve", { query, recordType, options });
}
}
class Conn {
class Conn {
#rid = 0;
#remoteAddr = null;
#localAddr = null;
@ -128,9 +127,9 @@
}
this.#pendingReadPromiseIds.forEach((id) => core.unrefOp(id));
}
}
}
class TcpConn extends Conn {
class TcpConn extends Conn {
setNoDelay(noDelay = true) {
return ops.op_set_nodelay(this.rid, noDelay);
}
@ -138,11 +137,11 @@
setKeepAlive(keepAlive = true) {
return ops.op_set_keepalive(this.rid, keepAlive);
}
}
}
class UnixConn extends Conn {}
class UnixConn extends Conn {}
class Listener {
class Listener {
#rid = 0;
#addr = null;
#unref = false;
@ -234,9 +233,9 @@
core.unrefOp(this.#promiseId);
}
}
}
}
class Datagram {
class Datagram {
#rid = 0;
#addr = null;
@ -325,9 +324,9 @@
}
}
}
}
}
function listen(args) {
function listen(args) {
switch (args.transport ?? "tcp") {
case "tcp": {
const { 0: rid, 1: addr } = ops.op_net_listen_tcp({
@ -348,9 +347,9 @@
default:
throw new TypeError(`Unsupported transport: '${transport}'`);
}
}
}
function createListenDatagram(udpOpFn, unixOpFn) {
function createListenDatagram(udpOpFn, unixOpFn) {
return function listenDatagram(args) {
switch (args.transport) {
case "udp": {
@ -376,9 +375,9 @@
throw new TypeError(`Unsupported transport: '${transport}'`);
}
};
}
}
async function connect(args) {
async function connect(args) {
switch (args.transport ?? "tcp") {
case "tcp": {
const { 0: rid, 1: localAddr, 2: remoteAddr } = await core.opAsync(
@ -406,18 +405,17 @@
default:
throw new TypeError(`Unsupported transport: '${transport}'`);
}
}
}
window.__bootstrap.net = {
connect,
export {
Conn,
connect,
createListenDatagram,
Datagram,
listen,
Listener,
resolveDns,
shutdown,
TcpConn,
UnixConn,
listen,
createListenDatagram,
Listener,
shutdown,
Datagram,
resolveDns,
};
})(this);
};

View file

@ -1,27 +1,26 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
"use strict";
((window) => {
const core = window.Deno.core;
const ops = core.ops;
const { Listener, Conn } = window.__bootstrap.net;
const { TypeError } = window.__bootstrap.primordials;
const core = globalThis.Deno.core;
const ops = core.ops;
import { Conn, Listener } from "internal:ext/net/01_net.js";
const primordials = globalThis.__bootstrap.primordials;
const { TypeError } = primordials;
function opStartTls(args) {
function opStartTls(args) {
return core.opAsync("op_tls_start", args);
}
}
function opTlsHandshake(rid) {
function opTlsHandshake(rid) {
return core.opAsync("op_tls_handshake", rid);
}
}
class TlsConn extends Conn {
class TlsConn extends Conn {
handshake() {
return opTlsHandshake(this.rid);
}
}
}
async function connectTls({
async function connectTls({
port,
hostname = "127.0.0.1",
transport = "tcp",
@ -30,7 +29,7 @@
certChain = undefined,
privateKey = undefined,
alpnProtocols = undefined,
}) {
}) {
if (transport !== "tcp") {
throw new TypeError(`Unsupported transport: '${transport}'`);
}
@ -42,9 +41,9 @@
localAddr.transport = "tcp";
remoteAddr.transport = "tcp";
return new TlsConn(rid, remoteAddr, localAddr);
}
}
class TlsListener extends Listener {
class TlsListener extends Listener {
async accept() {
const { 0: rid, 1: localAddr, 2: remoteAddr } = await core.opAsync(
"op_net_accept_tls",
@ -54,9 +53,9 @@
remoteAddr.transport = "tcp";
return new TlsConn(rid, remoteAddr, localAddr);
}
}
}
function listenTls({
function listenTls({
port,
cert,
certFile,
@ -66,7 +65,7 @@
transport = "tcp",
alpnProtocols = undefined,
reusePort = false,
}) {
}) {
if (transport !== "tcp") {
throw new TypeError(`Unsupported transport: '${transport}'`);
}
@ -75,9 +74,9 @@
{ cert, certFile, key, keyFile, alpnProtocols, reusePort },
);
return new TlsListener(rid, localAddr);
}
}
async function startTls(
async function startTls(
conn,
{
hostname = "127.0.0.1",
@ -85,7 +84,7 @@
caCerts = [],
alpnProtocols = undefined,
} = {},
) {
) {
const { 0: rid, 1: localAddr, 2: remoteAddr } = await opStartTls({
rid: conn.rid,
hostname,
@ -94,13 +93,6 @@
alpnProtocols,
});
return new TlsConn(rid, remoteAddr, localAddr);
}
}
window.__bootstrap.tls = {
startTls,
listenTls,
connectTls,
TlsConn,
TlsListener,
};
})(this);
export { connectTls, listenTls, startTls, TlsConn, TlsListener };

View file

@ -86,7 +86,7 @@ pub fn init<P: NetPermissions + 'static>(
ops.extend(ops_tls::init::<P>());
Extension::builder(env!("CARGO_PKG_NAME"))
.dependencies(vec!["deno_web"])
.js(include_js_files!(
.esm(include_js_files!(
prefix "internal:ext/net",
"01_net.js",
"02_tls.js",

View file

@ -2,10 +2,9 @@
// deno-lint-ignore-file
"use strict";
((window) => {
const {
const internals = globalThis.__bootstrap.internals;
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayPrototypePush,
ArrayPrototypeFilter,
ObjectEntries,
@ -17,17 +16,17 @@
ReflectOwnKeys,
Set,
SetPrototypeHas,
} = window.__bootstrap.primordials;
} = primordials;
function assert(cond) {
function assert(cond) {
if (!cond) {
throw Error("assert");
}
}
}
let initialized = false;
const nodeGlobals = {};
const nodeGlobalThis = new Proxy(globalThis, {
let initialized = false;
const nodeGlobals = {};
const nodeGlobalThis = new Proxy(globalThis, {
get(_target, prop, _receiver) {
if (prop in nodeGlobals) {
return nodeGlobals[prop];
@ -84,12 +83,12 @@
has(_target, prop) {
return prop in nodeGlobals || prop in globalThis;
},
});
});
const nativeModuleExports = ObjectCreate(null);
const builtinModules = [];
const nativeModuleExports = ObjectCreate(null);
const builtinModules = [];
function initialize(nodeModules, nodeGlobalThisName) {
function initialize(nodeModules, nodeGlobalThisName) {
assert(!initialized);
initialized = true;
for (const [name, exports] of ObjectEntries(nodeModules)) {
@ -114,15 +113,11 @@
writable: false,
value: nodeGlobalThis,
});
}
}
window.__bootstrap.internals = {
...window.__bootstrap.internals ?? {},
node: {
internals.node = {
globalThis: nodeGlobalThis,
initialize,
nativeModuleExports,
builtinModules,
},
};
})(globalThis);
};

View file

@ -2,10 +2,11 @@
// deno-lint-ignore-file
"use strict";
((window) => {
const {
const core = globalThis.Deno.core;
const ops = core.ops;
const internals = globalThis.__bootstrap.internals;
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayIsArray,
ArrayPrototypeIncludes,
ArrayPrototypeIndexOf,
@ -37,44 +38,42 @@
RegExpPrototypeTest,
Error,
TypeError,
} = window.__bootstrap.primordials;
const core = window.Deno.core;
const ops = core.ops;
const { node } = window.__bootstrap.internals;
} = primordials;
const node = internals.node;
// Map used to store CJS parsing data.
const cjsParseCache = new SafeWeakMap();
// Map used to store CJS parsing data.
const cjsParseCache = new SafeWeakMap();
function pathDirname(filepath) {
function pathDirname(filepath) {
if (filepath == null || filepath === "") {
throw new Error("Empty filepath.");
}
return ops.op_require_path_dirname(filepath);
}
}
function pathResolve(...args) {
function pathResolve(...args) {
return ops.op_require_path_resolve(args);
}
}
function assert(cond) {
function assert(cond) {
if (!cond) {
throw Error("assert");
}
}
}
const nativeModulePolyfill = new SafeMap();
const nativeModulePolyfill = new SafeMap();
const relativeResolveCache = ObjectCreate(null);
let requireDepth = 0;
let statCache = null;
let isPreloading = false;
let mainModule = null;
let hasBrokenOnInspectBrk = false;
let hasInspectBrk = false;
// Are we running with --node-modules-dir flag?
let usesLocalNodeModulesDir = false;
const relativeResolveCache = ObjectCreate(null);
let requireDepth = 0;
let statCache = null;
let isPreloading = false;
let mainModule = null;
let hasBrokenOnInspectBrk = false;
let hasInspectBrk = false;
// Are we running with --node-modules-dir flag?
let usesLocalNodeModulesDir = false;
function stat(filename) {
function stat(filename) {
// TODO: required only on windows
// filename = path.toNamespacedPath(filename);
if (statCache !== null) {
@ -89,9 +88,9 @@
}
return result;
}
}
function updateChildren(parent, child, scan) {
function updateChildren(parent, child, scan) {
if (!parent) {
return;
}
@ -100,20 +99,20 @@
if (children && !(scan && ArrayPrototypeIncludes(children, child))) {
ArrayPrototypePush(children, child);
}
}
}
function tryFile(requestPath, _isMain) {
function tryFile(requestPath, _isMain) {
const rc = stat(requestPath);
if (rc !== 0) return;
return toRealPath(requestPath);
}
}
function tryPackage(requestPath, exts, isMain, originalPath) {
function tryPackage(requestPath, exts, isMain, originalPath) {
const packageJsonPath = pathResolve(
requestPath,
"package.json",
);
const pkg = core.ops.op_require_read_package_scope(packageJsonPath)?.main;
const pkg = ops.op_require_read_package_scope(packageJsonPath)?.main;
if (!pkg) {
return tryExtensions(
pathResolve(requestPath, "index"),
@ -159,10 +158,10 @@
}
}
return actual;
}
}
const realpathCache = new SafeMap();
function toRealPath(requestPath) {
const realpathCache = new SafeMap();
function toRealPath(requestPath) {
const maybeCached = realpathCache.get(requestPath);
if (maybeCached) {
return maybeCached;
@ -170,9 +169,9 @@
const rp = ops.op_require_real_path(requestPath);
realpathCache.set(requestPath, rp);
return rp;
}
}
function tryExtensions(p, exts, isMain) {
function tryExtensions(p, exts, isMain) {
for (let i = 0; i < exts.length; i++) {
const filename = tryFile(p + exts[i], isMain);
@ -181,11 +180,11 @@
}
}
return false;
}
}
// Find the longest (possibly multi-dot) extension registered in
// Module._extensions
function findLongestRegisteredExtension(filename) {
// Find the longest (possibly multi-dot) extension registered in
// Module._extensions
function findLongestRegisteredExtension(filename) {
const name = ops.op_require_path_basename(filename);
let currentExtension;
let index;
@ -199,9 +198,9 @@
}
}
return ".js";
}
}
function getExportsForCircularRequire(module) {
function getExportsForCircularRequire(module) {
if (
module.exports &&
ObjectGetPrototypeOf(module.exports) === ObjectPrototype &&
@ -219,18 +218,18 @@
}
return module.exports;
}
}
function emitCircularRequireWarning(prop) {
function emitCircularRequireWarning(prop) {
node.globalThis.process.emitWarning(
`Accessing non-existent property '${String(prop)}' of module exports ` +
"inside circular dependency",
);
}
}
// A Proxy that can be used as the prototype of a module.exports object and
// warns when non-existent properties are accessed.
const CircularRequirePrototypeWarningProxy = new Proxy({}, {
// A Proxy that can be used as the prototype of a module.exports object and
// warns when non-existent properties are accessed.
const CircularRequirePrototypeWarningProxy = new Proxy({}, {
get(target, prop) {
// Allow __esModule access in any case because it is used in the output
// of transpiled code to determine whether something comes from an
@ -249,10 +248,10 @@
emitCircularRequireWarning(prop);
return undefined;
},
});
});
const moduleParentCache = new SafeWeakMap();
function Module(id = "", parent) {
const moduleParentCache = new SafeWeakMap();
function Module(id = "", parent) {
this.id = id;
this.path = pathDirname(id);
this.exports = {};
@ -261,25 +260,25 @@
this.filename = null;
this.loaded = false;
this.children = [];
}
}
Module.builtinModules = node.builtinModules;
Module.builtinModules = node.builtinModules;
Module._extensions = ObjectCreate(null);
Module._cache = ObjectCreate(null);
Module._pathCache = ObjectCreate(null);
let modulePaths = [];
Module.globalPaths = modulePaths;
Module._extensions = ObjectCreate(null);
Module._cache = ObjectCreate(null);
Module._pathCache = ObjectCreate(null);
let modulePaths = [];
Module.globalPaths = modulePaths;
const CHAR_FORWARD_SLASH = 47;
const TRAILING_SLASH_REGEX = /(?:^|\/)\.?\.$/;
const encodedSepRegEx = /%2F|%2C/i;
const CHAR_FORWARD_SLASH = 47;
const TRAILING_SLASH_REGEX = /(?:^|\/)\.?\.$/;
const encodedSepRegEx = /%2F|%2C/i;
function finalizeEsmResolution(
function finalizeEsmResolution(
resolved,
parentPath,
pkgPath,
) {
) {
if (RegExpPrototypeTest(encodedSepRegEx, resolved)) {
throw new ERR_INVALID_MODULE_SPECIFIER(
resolved,
@ -297,18 +296,18 @@
filename,
path.resolve(pkgPath, "package.json"),
);
}
}
// This only applies to requests of a specific form:
// 1. name/.*
// 2. @scope/name/.*
const EXPORTS_PATTERN = /^((?:@[^/\\%]+\/)?[^./\\%][^/\\%]*)(\/.*)?$/;
function resolveExports(
// This only applies to requests of a specific form:
// 1. name/.*
// 2. @scope/name/.*
const EXPORTS_PATTERN = /^((?:@[^/\\%]+\/)?[^./\\%][^/\\%]*)(\/.*)?$/;
function resolveExports(
modulesPath,
request,
parentPath,
usesLocalNodeModulesDir,
) {
) {
// The implementation's behavior is meant to mirror resolution in ESM.
const [, name, expansion = ""] =
StringPrototypeMatch(request, EXPORTS_PATTERN) || [];
@ -316,7 +315,7 @@
return;
}
return core.ops.op_require_resolve_exports(
return ops.op_require_resolve_exports(
usesLocalNodeModulesDir,
modulesPath,
request,
@ -324,9 +323,9 @@
expansion,
parentPath,
) ?? false;
}
}
Module._findPath = function (request, paths, isMain, parentPath) {
Module._findPath = function (request, paths, isMain, parentPath) {
const absoluteRequest = ops.op_require_path_is_absolute(request);
if (absoluteRequest) {
paths = [""];
@ -366,7 +365,7 @@
}
}
const isDenoDirPackage = core.ops.op_require_is_deno_dir_package(
const isDenoDirPackage = ops.op_require_is_deno_dir_package(
curPath,
);
const isRelative = ops.op_require_is_request_relative(
@ -408,25 +407,25 @@
}
return false;
};
};
Module._nodeModulePaths = function (fromPath) {
Module._nodeModulePaths = function (fromPath) {
return ops.op_require_node_module_paths(fromPath);
};
};
Module._resolveLookupPaths = function (request, parent) {
Module._resolveLookupPaths = function (request, parent) {
const paths = [];
if (core.ops.op_require_is_request_relative(request) && parent?.filename) {
if (ops.op_require_is_request_relative(request) && parent?.filename) {
ArrayPrototypePush(
paths,
core.ops.op_require_path_dirname(parent.filename),
ops.op_require_path_dirname(parent.filename),
);
return paths;
}
if (parent?.filename && parent.filename.length > 0) {
const denoDirPath = core.ops.op_require_resolve_deno_dir(
const denoDirPath = ops.op_require_resolve_deno_dir(
request,
parent.filename,
);
@ -443,9 +442,9 @@
ArrayPrototypePush(paths, ...new SafeArrayIterator(lookupPathsResult));
}
return paths;
};
};
Module._load = function (request, parent, isMain) {
Module._load = function (request, parent, isMain) {
let relResolveCacheIdentifier;
if (parent) {
// Fast path for (lazy loaded) modules in the same directory. The indirect
@ -537,14 +536,14 @@
}
return module.exports;
};
};
Module._resolveFilename = function (
Module._resolveFilename = function (
request,
parent,
isMain,
options,
) {
) {
if (
StringPrototypeStartsWith(request, "node:") ||
nativeModuleCanBeRequiredByUsers(request)
@ -592,7 +591,7 @@
if (parent?.filename) {
if (request[0] === "#") {
const maybeResolved = core.ops.op_require_package_imports_resolve(
const maybeResolved = ops.op_require_package_imports_resolve(
parent.filename,
request,
);
@ -638,9 +637,9 @@
err.code = "MODULE_NOT_FOUND";
err.requireStack = requireStack;
throw err;
};
};
Module.prototype.load = function (filename) {
Module.prototype.load = function (filename) {
assert(!this.loaded);
this.filename = filename;
this.paths = Module._nodeModulePaths(
@ -659,11 +658,11 @@
this.loaded = true;
// TODO: do caching
};
};
// Loads a module at the given file path. Returns that module's
// `exports` property.
Module.prototype.require = function (id) {
// Loads a module at the given file path. Returns that module's
// `exports` property.
Module.prototype.require = function (id) {
if (typeof id !== "string") {
// TODO(bartlomieju): it should use different error type
// ("ERR_INVALID_ARG_VALUE")
@ -681,20 +680,20 @@
} finally {
requireDepth--;
}
};
};
Module.wrapper = [
Module.wrapper = [
// We provide the non-standard APIs in the CommonJS wrapper
// to avoid exposing them in global namespace.
"(function (exports, require, module, __filename, __dirname, globalThis) { const { Buffer, clearImmediate, clearInterval, clearTimeout, console, global, process, setImmediate, setInterval, setTimeout} = globalThis; var window = undefined; (function () {",
"\n}).call(this); })",
];
Module.wrap = function (script) {
];
Module.wrap = function (script) {
script = script.replace(/^#!.*?\n/, "");
return `${Module.wrapper[0]}${script}${Module.wrapper[1]}`;
};
};
function enrichCJSError(error) {
function enrichCJSError(error) {
if (error instanceof SyntaxError) {
if (
StringPrototypeIncludes(
@ -709,13 +708,13 @@
);
}
}
}
}
function wrapSafe(
function wrapSafe(
filename,
content,
cjsModuleInstance,
) {
) {
const wrapper = Module.wrap(content);
const [f, err] = core.evalContext(wrapper, filename);
if (err) {
@ -725,9 +724,9 @@
throw err.thrown;
}
return f;
}
}
Module.prototype._compile = function (content, filename) {
Module.prototype._compile = function (content, filename) {
const compiledWrapper = wrapSafe(filename, content, this);
const dirname = pathDirname(filename);
@ -741,7 +740,7 @@
if (hasInspectBrk && !hasBrokenOnInspectBrk) {
hasBrokenOnInspectBrk = true;
core.ops.op_require_break_on_next_statement();
ops.op_require_break_on_next_statement();
}
const result = compiledWrapper.call(
@ -757,13 +756,13 @@
statCache = null;
}
return result;
};
};
Module._extensions[".js"] = function (module, filename) {
Module._extensions[".js"] = function (module, filename) {
const content = ops.op_require_read_file(filename);
if (StringPrototypeEndsWith(filename, ".js")) {
const pkg = core.ops.op_require_read_closest_package_json(filename);
const pkg = ops.op_require_read_closest_package_json(filename);
if (pkg && pkg.exists && pkg.typ == "module") {
let message = `Trying to import ESM module: ${filename}`;
@ -778,17 +777,17 @@
}
module._compile(content, filename);
};
};
function stripBOM(content) {
function stripBOM(content) {
if (StringPrototypeCharCodeAt(content, 0) === 0xfeff) {
content = StringPrototypeSlice(content, 1);
}
return content;
}
}
// Native extension for .json
Module._extensions[".json"] = function (module, filename) {
// Native extension for .json
Module._extensions[".json"] = function (module, filename) {
const content = ops.op_require_read_file(filename);
try {
@ -797,25 +796,25 @@
err.message = filename + ": " + err.message;
throw err;
}
};
};
// Native extension for .node
Module._extensions[".node"] = function (module, filename) {
// Native extension for .node
Module._extensions[".node"] = function (module, filename) {
if (filename.endsWith("fsevents.node")) {
throw new Error("Using fsevents module is currently not supported");
}
module.exports = ops.op_napi_open(filename, node.globalThis);
};
};
function createRequireFromPath(filename) {
function createRequireFromPath(filename) {
const proxyPath = ops.op_require_proxy_path(filename);
const mod = new Module(proxyPath);
mod.filename = proxyPath;
mod.paths = Module._nodeModulePaths(mod.path);
return makeRequireFunction(mod);
}
}
function makeRequireFunction(mod) {
function makeRequireFunction(mod) {
const require = function require(path) {
return mod.require(path);
};
@ -837,20 +836,20 @@
require.cache = Module._cache;
return require;
}
}
// Matches to:
// - /foo/...
// - \foo\...
// - C:/foo/...
// - C:\foo\...
const RE_START_OF_ABS_PATH = /^([/\\]|[a-zA-Z]:[/\\])/;
// Matches to:
// - /foo/...
// - \foo\...
// - C:/foo/...
// - C:\foo\...
const RE_START_OF_ABS_PATH = /^([/\\]|[a-zA-Z]:[/\\])/;
function isAbsolute(filenameOrUrl) {
function isAbsolute(filenameOrUrl) {
return RE_START_OF_ABS_PATH.test(filenameOrUrl);
}
}
function createRequire(filenameOrUrl) {
function createRequire(filenameOrUrl) {
let fileUrlStr;
if (filenameOrUrl instanceof URL) {
if (filenameOrUrl.protocol !== "file:") {
@ -871,27 +870,27 @@
`The argument 'filename' must be a file URL object, file URL string, or absolute path string. Received ${filenameOrUrl}`,
);
}
const filename = core.ops.op_require_as_file_path(fileUrlStr);
const filename = ops.op_require_as_file_path(fileUrlStr);
return createRequireFromPath(filename);
}
}
Module.createRequire = createRequire;
Module.createRequire = createRequire;
Module._initPaths = function () {
Module._initPaths = function () {
const paths = ops.op_require_init_paths();
modulePaths = paths;
Module.globalPaths = ArrayPrototypeSlice(modulePaths);
};
};
Module.syncBuiltinESMExports = function syncBuiltinESMExports() {
Module.syncBuiltinESMExports = function syncBuiltinESMExports() {
throw new Error("not implemented");
};
};
Module.Module = Module;
Module.Module = Module;
node.nativeModuleExports.module = Module;
node.nativeModuleExports.module = Module;
function loadNativeModule(_id, request) {
function loadNativeModule(_id, request) {
if (nativeModulePolyfill.has(request)) {
return nativeModulePolyfill.get(request);
}
@ -904,18 +903,18 @@
return nodeMod;
}
return undefined;
}
}
function nativeModuleCanBeRequiredByUsers(request) {
function nativeModuleCanBeRequiredByUsers(request) {
return !!node.nativeModuleExports[request];
}
}
function readPackageScope() {
function readPackageScope() {
throw new Error("not implemented");
}
}
/** @param specifier {string} */
function packageSpecifierSubPath(specifier) {
/** @param specifier {string} */
function packageSpecifierSubPath(specifier) {
let parts = StringPrototypeSplit(specifier, "/");
if (StringPrototypeStartsWith(parts[0], "@")) {
parts = ArrayPrototypeSlice(parts, 2);
@ -923,11 +922,9 @@
parts = ArrayPrototypeSlice(parts, 1);
}
return ArrayPrototypeJoin(parts, "/");
}
}
window.__bootstrap.internals = {
...window.__bootstrap.internals ?? {},
require: {
internals.require = {
setUsesLocalNodeModulesDir() {
usesLocalNodeModulesDir = true;
},
@ -939,6 +936,4 @@
toRealPath,
cjsParseCache,
readPackageScope,
},
};
})(globalThis);
};

View file

@ -85,7 +85,7 @@ pub fn init<P: NodePermissions + 'static>(
maybe_npm_resolver: Option<Rc<dyn RequireNpmResolver>>,
) -> Extension {
Extension::builder(env!("CARGO_PKG_NAME"))
.js(include_js_files!(
.esm(include_js_files!(
prefix "internal:ext/node",
"01_node.js",
"02_require.js",

View file

@ -5,13 +5,11 @@
/// <reference path="../../core/lib.deno_core.d.ts" />
/// <reference path="../webidl/internal.d.ts" />
"use strict";
((window) => {
const core = window.Deno.core;
const ops = core.ops;
const webidl = window.__bootstrap.webidl;
const {
const core = globalThis.Deno.core;
const ops = core.ops;
import * as webidl from "internal:ext/webidl/00_webidl.js";
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayIsArray,
ArrayPrototypeMap,
ArrayPrototypePush,
@ -26,24 +24,24 @@
SymbolFor,
SymbolIterator,
TypeError,
} = window.__bootstrap.primordials;
} = primordials;
const _list = Symbol("list");
const _urlObject = Symbol("url object");
const _list = Symbol("list");
const _urlObject = Symbol("url object");
// WARNING: must match rust code's UrlSetter::*
const SET_HASH = 0;
const SET_HOST = 1;
const SET_HOSTNAME = 2;
const SET_PASSWORD = 3;
const SET_PATHNAME = 4;
const SET_PORT = 5;
const SET_PROTOCOL = 6;
const SET_SEARCH = 7;
const SET_USERNAME = 8;
// WARNING: must match rust code's UrlSetter::*
const SET_HASH = 0;
const SET_HOST = 1;
const SET_HOSTNAME = 2;
const SET_PASSWORD = 3;
const SET_PATHNAME = 4;
const SET_PORT = 5;
const SET_PROTOCOL = 6;
const SET_SEARCH = 7;
const SET_USERNAME = 8;
// Helper functions
function opUrlReparse(href, setter, value) {
// Helper functions
function opUrlReparse(href, setter, value) {
const status = ops.op_url_reparse(
href,
setter,
@ -51,36 +49,36 @@
componentsBuf.buffer,
);
return getSerialization(status, href);
}
}
function opUrlParse(href, maybeBase) {
function opUrlParse(href, maybeBase) {
let status;
if (maybeBase === undefined) {
status = ops.op_url_parse(href, componentsBuf.buffer);
} else {
status = core.ops.op_url_parse_with_base(
status = ops.op_url_parse_with_base(
href,
maybeBase,
componentsBuf.buffer,
);
}
return getSerialization(status, href, maybeBase);
}
}
function getSerialization(status, href, maybeBase) {
function getSerialization(status, href, maybeBase) {
if (status === 0) {
return href;
} else if (status === 1) {
return core.ops.op_url_get_serialization();
return ops.op_url_get_serialization();
} else {
throw new TypeError(
`Invalid URL: '${href}'` +
(maybeBase ? ` with base '${maybeBase}'` : ""),
);
}
}
}
class URLSearchParams {
class URLSearchParams {
[_list];
[_urlObject] = null;
@ -304,30 +302,30 @@
webidl.assertBranded(this, URLSearchParamsPrototype);
return ops.op_url_stringify_search_params(this[_list]);
}
}
}
webidl.mixinPairIterable("URLSearchParams", URLSearchParams, _list, 0, 1);
webidl.mixinPairIterable("URLSearchParams", URLSearchParams, _list, 0, 1);
webidl.configurePrototype(URLSearchParams);
const URLSearchParamsPrototype = URLSearchParams.prototype;
webidl.configurePrototype(URLSearchParams);
const URLSearchParamsPrototype = URLSearchParams.prototype;
webidl.converters["URLSearchParams"] = webidl.createInterfaceConverter(
webidl.converters["URLSearchParams"] = webidl.createInterfaceConverter(
"URLSearchParams",
URLSearchParamsPrototype,
);
);
const _updateUrlSearch = Symbol("updateUrlSearch");
const _updateUrlSearch = Symbol("updateUrlSearch");
function trim(s) {
function trim(s) {
if (s.length === 1) return "";
return s;
}
}
// Represents a "no port" value. A port in URL cannot be greater than 2^16 1
const NO_PORT = 65536;
// Represents a "no port" value. A port in URL cannot be greater than 2^16 1
const NO_PORT = 65536;
const componentsBuf = new Uint32Array(8);
class URL {
const componentsBuf = new Uint32Array(8);
class URL {
#queryObject = null;
#serialization;
#schemeEnd;
@ -771,22 +769,22 @@
webidl.assertBranded(this, URLPrototype);
return this.#serialization;
}
}
}
webidl.configurePrototype(URL);
const URLPrototype = URL.prototype;
webidl.configurePrototype(URL);
const URLPrototype = URL.prototype;
/**
/**
* This function implements application/x-www-form-urlencoded parsing.
* https://url.spec.whatwg.org/#concept-urlencoded-parser
* @param {Uint8Array} bytes
* @returns {[string, string][]}
*/
function parseUrlEncoded(bytes) {
function parseUrlEncoded(bytes) {
return ops.op_url_parse_search_params(null, bytes);
}
}
webidl
webidl
.converters[
"sequence<sequence<USVString>> or record<USVString, USVString> or USVString"
] = (V, opts) => {
@ -800,11 +798,10 @@
return webidl.converters.USVString(V, opts);
};
window.__bootstrap.url = {
export {
parseUrlEncoded,
URL,
URLPrototype,
URLSearchParams,
URLSearchParamsPrototype,
parseUrlEncoded,
};
})(this);
};

View file

@ -7,13 +7,11 @@
/// <reference path="./internal.d.ts" />
/// <reference path="./lib.deno_url.d.ts" />
"use strict";
((window) => {
const core = window.Deno.core;
const ops = core.ops;
const webidl = window.__bootstrap.webidl;
const {
const core = globalThis.Deno.core;
const ops = core.ops;
import * as webidl from "internal:ext/webidl/00_webidl.js";
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayPrototypeMap,
ObjectKeys,
ObjectFromEntries,
@ -23,11 +21,11 @@
Symbol,
SymbolFor,
TypeError,
} = window.__bootstrap.primordials;
} = primordials;
const _components = Symbol("components");
const _components = Symbol("components");
/**
/**
* @typedef Components
* @property {Component} protocol
* @property {Component} username
@ -39,14 +37,14 @@
* @property {Component} hash
*/
/**
/**
* @typedef Component
* @property {string} patternString
* @property {RegExp} regexp
* @property {string[]} groupNameList
*/
class URLPattern {
class URLPattern {
/** @type {Components} */
[_components];
@ -242,12 +240,12 @@
})
}`;
}
}
}
webidl.configurePrototype(URLPattern);
const URLPatternPrototype = URLPattern.prototype;
webidl.configurePrototype(URLPattern);
const URLPatternPrototype = URLPattern.prototype;
webidl.converters.URLPatternInit = webidl
webidl.converters.URLPatternInit = webidl
.createDictionaryConverter("URLPatternInit", [
{ key: "protocol", converter: webidl.converters.USVString },
{ key: "username", converter: webidl.converters.USVString },
@ -260,15 +258,12 @@
{ key: "baseURL", converter: webidl.converters.USVString },
]);
webidl.converters["URLPatternInput"] = (V, opts) => {
webidl.converters["URLPatternInput"] = (V, opts) => {
// Union for (URLPatternInit or USVString)
if (typeof V == "object") {
return webidl.converters.URLPatternInit(V, opts);
}
return webidl.converters.USVString(V, opts);
};
};
window.__bootstrap.urlPattern = {
URLPattern,
};
})(globalThis);
export { URLPattern };

View file

@ -12,9 +12,11 @@ fn setup() -> Vec<Extension> {
deno_webidl::init(),
deno_url::init(),
Extension::builder("bench_setup")
.js(vec![(
"setup",
"const { URL } = globalThis.__bootstrap.url;",
.esm(vec![(
"internal:setup",
r#"import { URL } from "internal:ext/url/00_url.js";
globalThis.URL = URL;
"#,
)])
.build(),
]

22
ext/url/internal.d.ts vendored
View file

@ -1,20 +1,14 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
// deno-lint-ignore-file no-var
/// <reference no-default-lib="true" />
/// <reference lib="esnext" />
declare namespace globalThis {
declare namespace __bootstrap {
declare var url: {
URL: typeof URL;
URLSearchParams: typeof URLSearchParams;
parseUrlEncoded(bytes: Uint8Array): [string, string][];
};
declare var urlPattern: {
URLPattern: typeof URLPattern;
};
}
declare module "internal:ext/url/00_url.js" {
const URL: typeof URL;
const URLSearchParams: typeof URLSearchParams;
function parseUrlEncoded(bytes: Uint8Array): [string, string][];
}
declare module "internal:ext/url/01_urlpattern.js" {
const URLPattern: typeof URLPattern;
}

View file

@ -20,7 +20,7 @@ use crate::urlpattern::op_urlpattern_process_match_input;
pub fn init() -> Extension {
Extension::builder(env!("CARGO_PKG_NAME"))
.dependencies(vec!["deno_webidl"])
.js(include_js_files!(
.esm(include_js_files!(
prefix "internal:ext/url",
"00_url.js",
"01_urlpattern.js",

View file

@ -6,12 +6,10 @@
/// <reference path="../web/internal.d.ts" />
/// <reference path="../web/lib.deno_web.d.ts" />
"use strict";
((window) => {
const core = Deno.core;
const ops = core.ops;
const {
const core = globalThis.Deno.core;
const ops = core.ops;
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayPrototypeJoin,
ArrayPrototypeMap,
Error,
@ -30,28 +28,28 @@
StringPrototypeToLowerCase,
StringPrototypeToUpperCase,
TypeError,
} = window.__bootstrap.primordials;
} = primordials;
const ASCII_DIGIT = ["\u0030-\u0039"];
const ASCII_UPPER_ALPHA = ["\u0041-\u005A"];
const ASCII_LOWER_ALPHA = ["\u0061-\u007A"];
const ASCII_ALPHA = [
const ASCII_DIGIT = ["\u0030-\u0039"];
const ASCII_UPPER_ALPHA = ["\u0041-\u005A"];
const ASCII_LOWER_ALPHA = ["\u0061-\u007A"];
const ASCII_ALPHA = [
...new SafeArrayIterator(ASCII_UPPER_ALPHA),
...new SafeArrayIterator(ASCII_LOWER_ALPHA),
];
const ASCII_ALPHANUMERIC = [
];
const ASCII_ALPHANUMERIC = [
...new SafeArrayIterator(ASCII_DIGIT),
...new SafeArrayIterator(ASCII_ALPHA),
];
];
const HTTP_TAB_OR_SPACE = ["\u0009", "\u0020"];
const HTTP_WHITESPACE = [
const HTTP_TAB_OR_SPACE = ["\u0009", "\u0020"];
const HTTP_WHITESPACE = [
"\u000A",
"\u000D",
...new SafeArrayIterator(HTTP_TAB_OR_SPACE),
];
];
const HTTP_TOKEN_CODE_POINT = [
const HTTP_TOKEN_CODE_POINT = [
"\u0021",
"\u0023",
"\u0024",
@ -68,46 +66,46 @@
"\u007C",
"\u007E",
...new SafeArrayIterator(ASCII_ALPHANUMERIC),
];
const HTTP_TOKEN_CODE_POINT_RE = new RegExp(
];
const HTTP_TOKEN_CODE_POINT_RE = new RegExp(
`^[${regexMatcher(HTTP_TOKEN_CODE_POINT)}]+$`,
);
const HTTP_QUOTED_STRING_TOKEN_POINT = [
);
const HTTP_QUOTED_STRING_TOKEN_POINT = [
"\u0009",
"\u0020-\u007E",
"\u0080-\u00FF",
];
const HTTP_QUOTED_STRING_TOKEN_POINT_RE = new RegExp(
];
const HTTP_QUOTED_STRING_TOKEN_POINT_RE = new RegExp(
`^[${regexMatcher(HTTP_QUOTED_STRING_TOKEN_POINT)}]+$`,
);
const HTTP_TAB_OR_SPACE_MATCHER = regexMatcher(HTTP_TAB_OR_SPACE);
const HTTP_TAB_OR_SPACE_PREFIX_RE = new RegExp(
);
const HTTP_TAB_OR_SPACE_MATCHER = regexMatcher(HTTP_TAB_OR_SPACE);
const HTTP_TAB_OR_SPACE_PREFIX_RE = new RegExp(
`^[${HTTP_TAB_OR_SPACE_MATCHER}]+`,
"g",
);
const HTTP_TAB_OR_SPACE_SUFFIX_RE = new RegExp(
);
const HTTP_TAB_OR_SPACE_SUFFIX_RE = new RegExp(
`[${HTTP_TAB_OR_SPACE_MATCHER}]+$`,
"g",
);
const HTTP_WHITESPACE_MATCHER = regexMatcher(HTTP_WHITESPACE);
const HTTP_BETWEEN_WHITESPACE = new RegExp(
);
const HTTP_WHITESPACE_MATCHER = regexMatcher(HTTP_WHITESPACE);
const HTTP_BETWEEN_WHITESPACE = new RegExp(
`^[${HTTP_WHITESPACE_MATCHER}]*(.*?)[${HTTP_WHITESPACE_MATCHER}]*$`,
);
const HTTP_WHITESPACE_PREFIX_RE = new RegExp(
);
const HTTP_WHITESPACE_PREFIX_RE = new RegExp(
`^[${HTTP_WHITESPACE_MATCHER}]+`,
"g",
);
const HTTP_WHITESPACE_SUFFIX_RE = new RegExp(
);
const HTTP_WHITESPACE_SUFFIX_RE = new RegExp(
`[${HTTP_WHITESPACE_MATCHER}]+$`,
"g",
);
);
/**
/**
* Turn a string of chars into a regex safe matcher.
* @param {string[]} chars
* @returns {string}
*/
function regexMatcher(chars) {
function regexMatcher(chars) {
const matchers = ArrayPrototypeMap(chars, (char) => {
if (char.length === 1) {
const a = StringPrototypePadStart(
@ -133,16 +131,16 @@
}
});
return ArrayPrototypeJoin(matchers, "");
}
}
/**
/**
* https://infra.spec.whatwg.org/#collect-a-sequence-of-code-points
* @param {string} input
* @param {number} position
* @param {(char: string) => boolean} condition
* @returns {{result: string, position: number}}
*/
function collectSequenceOfCodepoints(input, position, condition) {
function collectSequenceOfCodepoints(input, position, condition) {
const start = position;
for (
let c = StringPrototypeCharAt(input, position);
@ -150,13 +148,13 @@
c = StringPrototypeCharAt(input, ++position)
);
return { result: StringPrototypeSlice(input, start, position), position };
}
}
/**
/**
* @param {string} s
* @returns {string}
*/
function byteUpperCase(s) {
function byteUpperCase(s) {
return StringPrototypeReplace(
String(s),
/[a-z]/g,
@ -164,26 +162,26 @@
return StringPrototypeToUpperCase(c);
},
);
}
}
/**
/**
* @param {string} s
* @returns {string}
*/
function byteLowerCase(s) {
function byteLowerCase(s) {
// NOTE: correct since all callers convert to ByteString first
// TODO(@AaronO): maybe prefer a ByteString_Lower webidl converter
return StringPrototypeToLowerCase(s);
}
}
/**
/**
* https://fetch.spec.whatwg.org/#collect-an-http-quoted-string
* @param {string} input
* @param {number} position
* @param {boolean} extractValue
* @returns {{result: string, position: number}}
*/
function collectHttpQuotedString(input, position, extractValue) {
function collectHttpQuotedString(input, position, extractValue) {
// 1.
const positionStart = position;
// 2.
@ -233,29 +231,29 @@
result: StringPrototypeSubstring(input, positionStart, position + 1),
position,
};
}
}
/**
/**
* @param {Uint8Array} data
* @returns {string}
*/
function forgivingBase64Encode(data) {
function forgivingBase64Encode(data) {
return ops.op_base64_encode(data);
}
}
/**
/**
* @param {string} data
* @returns {Uint8Array}
*/
function forgivingBase64Decode(data) {
function forgivingBase64Decode(data) {
return ops.op_base64_decode(data);
}
}
/**
/**
* @param {string} char
* @returns {boolean}
*/
function isHttpWhitespace(char) {
function isHttpWhitespace(char) {
switch (char) {
case "\u0009":
case "\u000A":
@ -265,75 +263,74 @@
default:
return false;
}
}
}
/**
/**
* @param {string} s
* @returns {string}
*/
function httpTrim(s) {
function httpTrim(s) {
if (!isHttpWhitespace(s[0]) && !isHttpWhitespace(s[s.length - 1])) {
return s;
}
return StringPrototypeMatch(s, HTTP_BETWEEN_WHITESPACE)?.[1] ?? "";
}
}
class AssertionError extends Error {
class AssertionError extends Error {
constructor(msg) {
super(msg);
this.name = "AssertionError";
}
}
}
/**
/**
* @param {unknown} cond
* @param {string=} msg
* @returns {asserts cond}
*/
function assert(cond, msg = "Assertion failed.") {
function assert(cond, msg = "Assertion failed.") {
if (!cond) {
throw new AssertionError(msg);
}
}
}
/**
/**
* @param {unknown} value
* @returns {string}
*/
function serializeJSValueToJSONString(value) {
function serializeJSValueToJSONString(value) {
const result = JSONStringify(value);
if (result === undefined) {
throw new TypeError("Value is not JSON serializable.");
}
return result;
}
}
window.__bootstrap.infra = {
collectSequenceOfCodepoints,
ASCII_DIGIT,
ASCII_UPPER_ALPHA,
ASCII_LOWER_ALPHA,
export {
ASCII_ALPHA,
ASCII_ALPHANUMERIC,
HTTP_TAB_OR_SPACE,
HTTP_WHITESPACE,
HTTP_TOKEN_CODE_POINT,
HTTP_TOKEN_CODE_POINT_RE,
ASCII_DIGIT,
ASCII_LOWER_ALPHA,
ASCII_UPPER_ALPHA,
assert,
AssertionError,
byteLowerCase,
byteUpperCase,
collectHttpQuotedString,
collectSequenceOfCodepoints,
forgivingBase64Decode,
forgivingBase64Encode,
HTTP_QUOTED_STRING_TOKEN_POINT,
HTTP_QUOTED_STRING_TOKEN_POINT_RE,
HTTP_TAB_OR_SPACE,
HTTP_TAB_OR_SPACE_PREFIX_RE,
HTTP_TAB_OR_SPACE_SUFFIX_RE,
HTTP_TOKEN_CODE_POINT,
HTTP_TOKEN_CODE_POINT_RE,
HTTP_WHITESPACE,
HTTP_WHITESPACE_PREFIX_RE,
HTTP_WHITESPACE_SUFFIX_RE,
httpTrim,
regexMatcher,
byteUpperCase,
byteLowerCase,
collectHttpQuotedString,
forgivingBase64Encode,
forgivingBase64Decode,
AssertionError,
assert,
serializeJSValueToJSONString,
};
})(globalThis);
};

View file

@ -7,10 +7,8 @@
/// <reference path="../web/internal.d.ts" />
/// <reference path="../web/lib.deno_web.d.ts" />
"use strict";
((window) => {
const {
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayPrototypeSlice,
Error,
ErrorPrototype,
@ -21,48 +19,48 @@
ObjectSetPrototypeOf,
Symbol,
SymbolFor,
} = window.__bootstrap.primordials;
const webidl = window.__bootstrap.webidl;
const consoleInternal = window.__bootstrap.console;
} = primordials;
import * as webidl from "internal:ext/webidl/00_webidl.js";
import { createFilteredInspectProxy } from "internal:ext/console/02_console.js";
const _name = Symbol("name");
const _message = Symbol("message");
const _code = Symbol("code");
const _name = Symbol("name");
const _message = Symbol("message");
const _code = Symbol("code");
// Defined in WebIDL 4.3.
// https://webidl.spec.whatwg.org/#idl-DOMException
const INDEX_SIZE_ERR = 1;
const DOMSTRING_SIZE_ERR = 2;
const HIERARCHY_REQUEST_ERR = 3;
const WRONG_DOCUMENT_ERR = 4;
const INVALID_CHARACTER_ERR = 5;
const NO_DATA_ALLOWED_ERR = 6;
const NO_MODIFICATION_ALLOWED_ERR = 7;
const NOT_FOUND_ERR = 8;
const NOT_SUPPORTED_ERR = 9;
const INUSE_ATTRIBUTE_ERR = 10;
const INVALID_STATE_ERR = 11;
const SYNTAX_ERR = 12;
const INVALID_MODIFICATION_ERR = 13;
const NAMESPACE_ERR = 14;
const INVALID_ACCESS_ERR = 15;
const VALIDATION_ERR = 16;
const TYPE_MISMATCH_ERR = 17;
const SECURITY_ERR = 18;
const NETWORK_ERR = 19;
const ABORT_ERR = 20;
const URL_MISMATCH_ERR = 21;
const QUOTA_EXCEEDED_ERR = 22;
const TIMEOUT_ERR = 23;
const INVALID_NODE_TYPE_ERR = 24;
const DATA_CLONE_ERR = 25;
// Defined in WebIDL 4.3.
// https://webidl.spec.whatwg.org/#idl-DOMException
const INDEX_SIZE_ERR = 1;
const DOMSTRING_SIZE_ERR = 2;
const HIERARCHY_REQUEST_ERR = 3;
const WRONG_DOCUMENT_ERR = 4;
const INVALID_CHARACTER_ERR = 5;
const NO_DATA_ALLOWED_ERR = 6;
const NO_MODIFICATION_ALLOWED_ERR = 7;
const NOT_FOUND_ERR = 8;
const NOT_SUPPORTED_ERR = 9;
const INUSE_ATTRIBUTE_ERR = 10;
const INVALID_STATE_ERR = 11;
const SYNTAX_ERR = 12;
const INVALID_MODIFICATION_ERR = 13;
const NAMESPACE_ERR = 14;
const INVALID_ACCESS_ERR = 15;
const VALIDATION_ERR = 16;
const TYPE_MISMATCH_ERR = 17;
const SECURITY_ERR = 18;
const NETWORK_ERR = 19;
const ABORT_ERR = 20;
const URL_MISMATCH_ERR = 21;
const QUOTA_EXCEEDED_ERR = 22;
const TIMEOUT_ERR = 23;
const INVALID_NODE_TYPE_ERR = 24;
const DATA_CLONE_ERR = 25;
// Defined in WebIDL 2.8.1.
// https://webidl.spec.whatwg.org/#dfn-error-names-table
/** @type {Record<string, number>} */
// the prototype should be null, to prevent user code from looking
// up Object.prototype properties, such as "toString"
const nameToCodeMapping = ObjectCreate(null, {
// Defined in WebIDL 2.8.1.
// https://webidl.spec.whatwg.org/#dfn-error-names-table
/** @type {Record<string, number>} */
// the prototype should be null, to prevent user code from looking
// up Object.prototype properties, such as "toString"
const nameToCodeMapping = ObjectCreate(null, {
IndexSizeError: { value: INDEX_SIZE_ERR },
HierarchyRequestError: { value: HIERARCHY_REQUEST_ERR },
WrongDocumentError: { value: WRONG_DOCUMENT_ERR },
@ -85,11 +83,11 @@
TimeoutError: { value: TIMEOUT_ERR },
InvalidNodeTypeError: { value: INVALID_NODE_TYPE_ERR },
DataCloneError: { value: DATA_CLONE_ERR },
});
});
// Defined in WebIDL 4.3.
// https://webidl.spec.whatwg.org/#idl-DOMException
class DOMException {
// Defined in WebIDL 4.3.
// https://webidl.spec.whatwg.org/#idl-DOMException
class DOMException {
[_message];
[_name];
[_code];
@ -147,7 +145,7 @@
if (ObjectPrototypeIsPrototypeOf(DOMExceptionPrototype, this)) {
return `DOMException: ${this[_message]}`;
} else {
return inspect(consoleInternal.createFilteredInspectProxy({
return inspect(createFilteredInspectProxy({
object: this,
evaluate: false,
keys: [
@ -158,14 +156,14 @@
}));
}
}
}
}
ObjectSetPrototypeOf(DOMException.prototype, ErrorPrototype);
ObjectSetPrototypeOf(DOMException.prototype, ErrorPrototype);
webidl.configurePrototype(DOMException);
const DOMExceptionPrototype = DOMException.prototype;
webidl.configurePrototype(DOMException);
const DOMExceptionPrototype = DOMException.prototype;
const entries = ObjectEntries({
const entries = ObjectEntries({
INDEX_SIZE_ERR,
DOMSTRING_SIZE_ERR,
HIERARCHY_REQUEST_ERR,
@ -191,13 +189,12 @@
TIMEOUT_ERR,
INVALID_NODE_TYPE_ERR,
DATA_CLONE_ERR,
});
for (let i = 0; i < entries.length; ++i) {
});
for (let i = 0; i < entries.length; ++i) {
const { 0: key, 1: value } = entries[i];
const desc = { value, enumerable: true };
ObjectDefineProperty(DOMException, key, desc);
ObjectDefineProperty(DOMException.prototype, key, desc);
}
}
window.__bootstrap.domException = { DOMException };
})(this);
export default DOMException;

View file

@ -6,10 +6,8 @@
/// <reference path="../web/internal.d.ts" />
/// <reference path="../web/lib.deno_web.d.ts" />
"use strict";
((window) => {
const {
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayPrototypeIncludes,
Map,
MapPrototypeGet,
@ -19,29 +17,29 @@
SafeMapIterator,
StringPrototypeReplaceAll,
StringPrototypeToLowerCase,
} = window.__bootstrap.primordials;
const {
} = primordials;
import {
collectHttpQuotedString,
collectSequenceOfCodepoints,
HTTP_QUOTED_STRING_TOKEN_POINT_RE,
HTTP_TOKEN_CODE_POINT_RE,
HTTP_WHITESPACE,
HTTP_WHITESPACE_PREFIX_RE,
HTTP_WHITESPACE_SUFFIX_RE,
HTTP_QUOTED_STRING_TOKEN_POINT_RE,
HTTP_TOKEN_CODE_POINT_RE,
collectHttpQuotedString,
} = window.__bootstrap.infra;
} from "internal:ext/web/00_infra.js";
/**
/**
* @typedef MimeType
* @property {string} type
* @property {string} subtype
* @property {Map<string,string>} parameters
*/
/**
/**
* @param {string} input
* @returns {MimeType | null}
*/
function parseMimeType(input) {
function parseMimeType(input) {
// 1.
input = StringPrototypeReplaceAll(input, HTTP_WHITESPACE_PREFIX_RE, "");
input = StringPrototypeReplaceAll(input, HTTP_WHITESPACE_SUFFIX_RE, "");
@ -180,21 +178,21 @@
// 12.
return mimeType;
}
}
/**
/**
* @param {MimeType} mimeType
* @returns {string}
*/
function essence(mimeType) {
function essence(mimeType) {
return `${mimeType.type}/${mimeType.subtype}`;
}
}
/**
/**
* @param {MimeType} mimeType
* @returns {string}
*/
function serializeMimeType(mimeType) {
function serializeMimeType(mimeType) {
let serialization = essence(mimeType);
for (const param of new SafeMapIterator(mimeType.parameters)) {
serialization += `;${param[0]}=`;
@ -207,16 +205,16 @@
serialization += value;
}
return serialization;
}
}
/**
/**
* Part of the Fetch spec's "extract a MIME type" algorithm
* (https://fetch.spec.whatwg.org/#concept-header-extract-mime-type).
* @param {string[] | null} headerValues The result of getting, decoding and
* splitting the "Content-Type" header.
* @returns {MimeType | null}
*/
function extractMimeType(headerValues) {
function extractMimeType(headerValues) {
if (headerValues === null) return null;
let charset = null;
@ -249,12 +247,6 @@
}
}
return mimeType;
}
}
window.__bootstrap.mimesniff = {
parseMimeType,
essence,
serializeMimeType,
extractMimeType,
};
})(this);
export { essence, extractMimeType, parseMimeType, serializeMimeType };

View file

@ -4,15 +4,14 @@
// Many parts of the DOM are not implemented in Deno, but the logic for those
// parts still exists. This means you will observe a lot of strange structures
// and impossible logic branches based on what Deno currently supports.
"use strict";
((window) => {
const core = window.Deno.core;
const ops = core.ops;
const webidl = window.__bootstrap.webidl;
const { DOMException } = window.__bootstrap.domException;
const consoleInternal = window.__bootstrap.console;
const {
const core = globalThis.Deno.core;
const ops = core.ops;
import * as webidl from "internal:ext/webidl/00_webidl.js";
import DOMException from "internal:ext/web/01_dom_exception.js";
import { createFilteredInspectProxy } from "internal:ext/console/02_console.js";
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayPrototypeFilter,
ArrayPrototypeIncludes,
ArrayPrototypeIndexOf,
@ -40,109 +39,117 @@
SymbolFor,
SymbolToStringTag,
TypeError,
} = window.__bootstrap.primordials;
} = primordials;
// accessors for non runtime visible data
// This should be set via setGlobalThis this is required so that if even
// user deletes globalThis it is still usable
let globalThis_;
function getDispatched(event) {
function saveGlobalThisReference(val) {
globalThis_ = val;
}
// accessors for non runtime visible data
function getDispatched(event) {
return Boolean(event[_dispatched]);
}
}
function getPath(event) {
function getPath(event) {
return event[_path] ?? [];
}
}
function getStopImmediatePropagation(event) {
function getStopImmediatePropagation(event) {
return Boolean(event[_stopImmediatePropagationFlag]);
}
}
function setCurrentTarget(
function setCurrentTarget(
event,
value,
) {
) {
event[_attributes].currentTarget = value;
}
}
function setIsTrusted(event, value) {
function setIsTrusted(event, value) {
event[_isTrusted] = value;
}
}
function setDispatched(event, value) {
function setDispatched(event, value) {
event[_dispatched] = value;
}
}
function setEventPhase(event, value) {
function setEventPhase(event, value) {
event[_attributes].eventPhase = value;
}
}
function setInPassiveListener(event, value) {
function setInPassiveListener(event, value) {
event[_inPassiveListener] = value;
}
}
function setPath(event, value) {
function setPath(event, value) {
event[_path] = value;
}
}
function setRelatedTarget(
function setRelatedTarget(
event,
value,
) {
) {
event[_attributes].relatedTarget = value;
}
}
function setTarget(event, value) {
function setTarget(event, value) {
event[_attributes].target = value;
}
}
function setStopImmediatePropagation(
function setStopImmediatePropagation(
event,
value,
) {
) {
event[_stopImmediatePropagationFlag] = value;
}
}
// Type guards that widen the event type
// Type guards that widen the event type
function hasRelatedTarget(
function hasRelatedTarget(
event,
) {
) {
return ReflectHas(event, "relatedTarget");
}
}
const isTrusted = ObjectGetOwnPropertyDescriptor({
const isTrusted = ObjectGetOwnPropertyDescriptor({
get isTrusted() {
return this[_isTrusted];
},
}, "isTrusted").get;
}, "isTrusted").get;
const eventInitConverter = webidl.createDictionaryConverter("EventInit", [{
const eventInitConverter = webidl.createDictionaryConverter("EventInit", [{
key: "bubbles",
defaultValue: false,
converter: webidl.converters.boolean,
}, {
}, {
key: "cancelable",
defaultValue: false,
converter: webidl.converters.boolean,
}, {
}, {
key: "composed",
defaultValue: false,
converter: webidl.converters.boolean,
}]);
}]);
const _attributes = Symbol("[[attributes]]");
const _canceledFlag = Symbol("[[canceledFlag]]");
const _stopPropagationFlag = Symbol("[[stopPropagationFlag]]");
const _stopImmediatePropagationFlag = Symbol(
const _attributes = Symbol("[[attributes]]");
const _canceledFlag = Symbol("[[canceledFlag]]");
const _stopPropagationFlag = Symbol("[[stopPropagationFlag]]");
const _stopImmediatePropagationFlag = Symbol(
"[[stopImmediatePropagationFlag]]",
);
const _inPassiveListener = Symbol("[[inPassiveListener]]");
const _dispatched = Symbol("[[dispatched]]");
const _isTrusted = Symbol("[[isTrusted]]");
const _path = Symbol("[[path]]");
// internal.
const _skipInternalInit = Symbol("[[skipSlowInit]]");
);
const _inPassiveListener = Symbol("[[inPassiveListener]]");
const _dispatched = Symbol("[[dispatched]]");
const _isTrusted = Symbol("[[isTrusted]]");
const _path = Symbol("[[path]]");
// internal.
const _skipInternalInit = Symbol("[[skipSlowInit]]");
class Event {
class Event {
constructor(type, eventInitDict = {}) {
// TODO(lucacasonato): remove when this interface is spec aligned
this[SymbolToStringTag] = "Event";
@ -198,7 +205,7 @@
}
[SymbolFor("Deno.privateCustomInspect")](inspect) {
return inspect(consoleInternal.createFilteredInspectProxy({
return inspect(createFilteredInspectProxy({
object: this,
evaluate: ObjectPrototypeIsPrototypeOf(Event.prototype, this),
keys: EVENT_PROPS,
@ -422,19 +429,19 @@
get timeStamp() {
return this[_attributes].timeStamp;
}
}
}
function defineEnumerableProps(
function defineEnumerableProps(
Ctor,
props,
) {
) {
for (let i = 0; i < props.length; ++i) {
const prop = props[i];
ReflectDefineProperty(Ctor.prototype, prop, { enumerable: true });
}
}
}
const EVENT_PROPS = [
const EVENT_PROPS = [
"bubbles",
"cancelable",
"composed",
@ -446,41 +453,41 @@
"returnValue",
"timeStamp",
"type",
];
];
defineEnumerableProps(Event, EVENT_PROPS);
defineEnumerableProps(Event, EVENT_PROPS);
// This is currently the only node type we are using, so instead of implementing
// the whole of the Node interface at the moment, this just gives us the one
// value to power the standards based logic
const DOCUMENT_FRAGMENT_NODE = 11;
// This is currently the only node type we are using, so instead of implementing
// the whole of the Node interface at the moment, this just gives us the one
// value to power the standards based logic
const DOCUMENT_FRAGMENT_NODE = 11;
// DOM Logic Helper functions and type guards
// DOM Logic Helper functions and type guards
/** Get the parent node, for event targets that have a parent.
/** Get the parent node, for event targets that have a parent.
*
* Ref: https://dom.spec.whatwg.org/#get-the-parent */
function getParent(eventTarget) {
function getParent(eventTarget) {
return isNode(eventTarget) ? eventTarget.parentNode : null;
}
}
function getRoot(eventTarget) {
function getRoot(eventTarget) {
return isNode(eventTarget)
? eventTarget.getRootNode({ composed: true })
: null;
}
}
function isNode(
function isNode(
eventTarget,
) {
) {
return Boolean(eventTarget && ReflectHas(eventTarget, "nodeType"));
}
}
// https://dom.spec.whatwg.org/#concept-shadow-including-inclusive-ancestor
function isShadowInclusiveAncestor(
// https://dom.spec.whatwg.org/#concept-shadow-including-inclusive-ancestor
function isShadowInclusiveAncestor(
ancestor,
node,
) {
) {
while (isNode(node)) {
if (node === ancestor) {
return true;
@ -494,37 +501,37 @@
}
return false;
}
}
function isShadowRoot(nodeImpl) {
function isShadowRoot(nodeImpl) {
return Boolean(
nodeImpl &&
isNode(nodeImpl) &&
nodeImpl.nodeType === DOCUMENT_FRAGMENT_NODE &&
getHost(nodeImpl) != null,
);
}
}
function isSlotable(
function isSlotable(
nodeImpl,
) {
) {
return Boolean(isNode(nodeImpl) && ReflectHas(nodeImpl, "assignedSlot"));
}
}
// DOM Logic functions
// DOM Logic functions
/** Append a path item to an event's path.
/** Append a path item to an event's path.
*
* Ref: https://dom.spec.whatwg.org/#concept-event-path-append
*/
function appendToEventPath(
function appendToEventPath(
eventImpl,
target,
targetOverride,
relatedTarget,
touchTargets,
slotInClosedTree,
) {
) {
const itemInShadowTree = isNode(target) && isShadowRoot(getRoot(target));
const rootOfClosedTree = isShadowRoot(target) &&
getMode(target) === "closed";
@ -538,13 +545,13 @@
rootOfClosedTree,
slotInClosedTree,
});
}
}
function dispatch(
function dispatch(
targetImpl,
eventImpl,
targetOverride,
) {
) {
let clearTargets = false;
let activationTarget = null;
@ -707,16 +714,16 @@
// }
return !eventImpl.defaultPrevented;
}
}
/** Inner invoking of the event listeners where the resolved listeners are
/** Inner invoking of the event listeners where the resolved listeners are
* called.
*
* Ref: https://dom.spec.whatwg.org/#concept-event-listener-inner-invoke */
function innerInvokeEventListeners(
function innerInvokeEventListeners(
eventImpl,
targetListeners,
) {
) {
let found = false;
const { type } = eventImpl;
@ -788,12 +795,12 @@
}
return found;
}
}
/** Invokes the listeners on a given event path with the supplied event.
/** Invokes the listeners on a given event path with the supplied event.
*
* Ref: https://dom.spec.whatwg.org/#concept-event-listener-invoke */
function invokeEventListeners(tuple, eventImpl) {
function invokeEventListeners(tuple, eventImpl) {
const path = getPath(eventImpl);
const tupleIndex = ArrayPrototypeIndexOf(path, tuple);
for (let i = tupleIndex; i >= 0; i--) {
@ -817,11 +824,11 @@
} catch (error) {
reportException(error);
}
}
}
function normalizeEventHandlerOptions(
function normalizeEventHandlerOptions(
options,
) {
) {
if (typeof options === "boolean" || typeof options === "undefined") {
return {
capture: Boolean(options),
@ -829,12 +836,12 @@
} else {
return options;
}
}
}
/** Retarget the target following the spec logic.
/** Retarget the target following the spec logic.
*
* Ref: https://dom.spec.whatwg.org/#retarget */
function retarget(a, b) {
function retarget(a, b) {
while (true) {
if (!isNode(a)) {
return a;
@ -853,41 +860,41 @@
a = getHost(aRoot);
}
}
}
}
// Accessors for non-public data
// Accessors for non-public data
const eventTargetData = Symbol();
const eventTargetData = Symbol();
function setEventTargetData(target) {
function setEventTargetData(target) {
target[eventTargetData] = getDefaultTargetData();
}
}
function getAssignedSlot(target) {
function getAssignedSlot(target) {
return Boolean(target?.[eventTargetData]?.assignedSlot);
}
}
function getHasActivationBehavior(target) {
function getHasActivationBehavior(target) {
return Boolean(target?.[eventTargetData]?.hasActivationBehavior);
}
}
function getHost(target) {
function getHost(target) {
return target?.[eventTargetData]?.host ?? null;
}
}
function getListeners(target) {
function getListeners(target) {
return target?.[eventTargetData]?.listeners ?? {};
}
}
function getMode(target) {
function getMode(target) {
return target?.[eventTargetData]?.mode ?? null;
}
}
function listenerCount(target, type) {
function listenerCount(target, type) {
return getListeners(target)?.[type]?.length ?? 0;
}
}
function getDefaultTargetData() {
function getDefaultTargetData() {
return {
assignedSlot: false,
hasActivationBehavior: false,
@ -895,12 +902,12 @@
listeners: ObjectCreate(null),
mode: "",
};
}
}
// This is lazy loaded because there is a circular dependency with AbortSignal.
let addEventListenerOptionsConverter;
// This is lazy loaded because there is a circular dependency with AbortSignal.
let addEventListenerOptionsConverter;
function lazyAddEventListenerOptionsConverter() {
function lazyAddEventListenerOptionsConverter() {
addEventListenerOptionsConverter ??= webidl.createDictionaryConverter(
"AddEventListenerOptions",
[
@ -925,18 +932,18 @@
},
],
);
}
}
webidl.converters.AddEventListenerOptions = (V, opts) => {
webidl.converters.AddEventListenerOptions = (V, opts) => {
if (webidl.type(V) !== "Object" || V === null) {
V = { capture: Boolean(V) };
}
lazyAddEventListenerOptionsConverter();
return addEventListenerOptionsConverter(V, opts);
};
};
class EventTarget {
class EventTarget {
constructor() {
this[eventTargetData] = getDefaultTargetData();
this[webidl.brand] = webidl.brand;
@ -947,7 +954,7 @@
callback,
options,
) {
const self = this ?? globalThis;
const self = this ?? globalThis_;
webidl.assertBranded(self, EventTargetPrototype);
const prefix = "Failed to execute 'addEventListener' on 'EventTarget'";
@ -1005,7 +1012,7 @@
callback,
options,
) {
const self = this ?? globalThis;
const self = this ?? globalThis_;
webidl.assertBranded(self, EventTargetPrototype);
webidl.requiredArguments(arguments.length, 2, {
prefix: "Failed to execute 'removeEventListener' on 'EventTarget'",
@ -1043,7 +1050,7 @@
// `globalThis` directly here, because it could be deleted by user.
// Instead use saved reference to global scope when the script was
// executed.
const self = this ?? window;
const self = this ?? globalThis_;
webidl.assertBranded(self, EventTargetPrototype);
webidl.requiredArguments(arguments.length, 1, {
prefix: "Failed to execute 'dispatchEvent' on 'EventTarget'",
@ -1069,18 +1076,18 @@
getParent(_event) {
return null;
}
}
}
webidl.configurePrototype(EventTarget);
const EventTargetPrototype = EventTarget.prototype;
webidl.configurePrototype(EventTarget);
const EventTargetPrototype = EventTarget.prototype;
defineEnumerableProps(EventTarget, [
defineEnumerableProps(EventTarget, [
"addEventListener",
"removeEventListener",
"dispatchEvent",
]);
]);
class ErrorEvent extends Event {
class ErrorEvent extends Event {
#message = "";
#filename = "";
#lineno = "";
@ -1130,7 +1137,7 @@
}
[SymbolFor("Deno.privateCustomInspect")](inspect) {
return inspect(consoleInternal.createFilteredInspectProxy({
return inspect(createFilteredInspectProxy({
object: this,
evaluate: ObjectPrototypeIsPrototypeOf(ErrorEvent.prototype, this),
keys: [
@ -1146,17 +1153,17 @@
// TODO(lucacasonato): remove when this interface is spec aligned
[SymbolToStringTag] = "ErrorEvent";
}
}
defineEnumerableProps(ErrorEvent, [
defineEnumerableProps(ErrorEvent, [
"message",
"filename",
"lineno",
"colno",
"error",
]);
]);
class CloseEvent extends Event {
class CloseEvent extends Event {
#wasClean = "";
#code = "";
#reason = "";
@ -1191,7 +1198,7 @@
}
[SymbolFor("Deno.privateCustomInspect")](inspect) {
return inspect(consoleInternal.createFilteredInspectProxy({
return inspect(createFilteredInspectProxy({
object: this,
evaluate: ObjectPrototypeIsPrototypeOf(CloseEvent.prototype, this),
keys: [
@ -1202,9 +1209,9 @@
],
}));
}
}
}
class MessageEvent extends Event {
class MessageEvent extends Event {
get source() {
return null;
}
@ -1224,7 +1231,7 @@
}
[SymbolFor("Deno.privateCustomInspect")](inspect) {
return inspect(consoleInternal.createFilteredInspectProxy({
return inspect(createFilteredInspectProxy({
object: this,
evaluate: ObjectPrototypeIsPrototypeOf(MessageEvent.prototype, this),
keys: [
@ -1238,9 +1245,9 @@
// TODO(lucacasonato): remove when this interface is spec aligned
[SymbolToStringTag] = "CloseEvent";
}
}
class CustomEvent extends Event {
class CustomEvent extends Event {
#detail = null;
constructor(type, eventInitDict = {}) {
@ -1257,7 +1264,7 @@
}
[SymbolFor("Deno.privateCustomInspect")](inspect) {
return inspect(consoleInternal.createFilteredInspectProxy({
return inspect(createFilteredInspectProxy({
object: this,
evaluate: ObjectPrototypeIsPrototypeOf(CustomEvent.prototype, this),
keys: [
@ -1269,15 +1276,15 @@
// TODO(lucacasonato): remove when this interface is spec aligned
[SymbolToStringTag] = "CustomEvent";
}
}
ReflectDefineProperty(CustomEvent.prototype, "detail", {
ReflectDefineProperty(CustomEvent.prototype, "detail", {
enumerable: true,
});
});
// ProgressEvent could also be used in other DOM progress event emits.
// Current use is for FileReader.
class ProgressEvent extends Event {
// ProgressEvent could also be used in other DOM progress event emits.
// Current use is for FileReader.
class ProgressEvent extends Event {
constructor(type, eventInitDict = {}) {
super(type, eventInitDict);
@ -1287,7 +1294,7 @@
}
[SymbolFor("Deno.privateCustomInspect")](inspect) {
return inspect(consoleInternal.createFilteredInspectProxy({
return inspect(createFilteredInspectProxy({
object: this,
evaluate: ObjectPrototypeIsPrototypeOf(ProgressEvent.prototype, this),
keys: [
@ -1301,9 +1308,9 @@
// TODO(lucacasonato): remove when this interface is spec aligned
[SymbolToStringTag] = "ProgressEvent";
}
}
class PromiseRejectionEvent extends Event {
class PromiseRejectionEvent extends Event {
#promise = null;
#reason = null;
@ -1335,7 +1342,7 @@
}
[SymbolFor("Deno.privateCustomInspect")](inspect) {
return inspect(consoleInternal.createFilteredInspectProxy({
return inspect(createFilteredInspectProxy({
object: this,
evaluate: ObjectPrototypeIsPrototypeOf(
PromiseRejectionEvent.prototype,
@ -1351,16 +1358,16 @@
// TODO(lucacasonato): remove when this interface is spec aligned
[SymbolToStringTag] = "PromiseRejectionEvent";
}
}
defineEnumerableProps(PromiseRejectionEvent, [
defineEnumerableProps(PromiseRejectionEvent, [
"promise",
"reason",
]);
]);
const _eventHandlers = Symbol("eventHandlers");
const _eventHandlers = Symbol("eventHandlers");
function makeWrappedHandler(handler, isSpecialErrorEventHandler) {
function makeWrappedHandler(handler, isSpecialErrorEventHandler) {
function wrappedHandler(evt) {
if (typeof wrappedHandler.handler !== "function") {
return;
@ -1390,19 +1397,19 @@
}
wrappedHandler.handler = handler;
return wrappedHandler;
}
}
// `init` is an optional function that will be called the first time that the
// event handler property is set. It will be called with the object on which
// the property is set as its argument.
// `isSpecialErrorEventHandler` can be set to true to opt into the special
// behavior of event handlers for the "error" event in a global scope.
function defineEventHandler(
// `init` is an optional function that will be called the first time that the
// event handler property is set. It will be called with the object on which
// the property is set as its argument.
// `isSpecialErrorEventHandler` can be set to true to opt into the special
// behavior of event handlers for the "error" event in a global scope.
function defineEventHandler(
emitter,
name,
init = undefined,
isSpecialErrorEventHandler = false,
) {
) {
// HTML specification section 8.1.7.1
ObjectDefineProperty(emitter, `on${name}`, {
get() {
@ -1439,12 +1446,12 @@
configurable: true,
enumerable: true,
});
}
}
let reportExceptionStackedCalls = 0;
let reportExceptionStackedCalls = 0;
// https://html.spec.whatwg.org/#report-the-exception
function reportException(error) {
// https://html.spec.whatwg.org/#report-the-exception
function reportException(error) {
reportExceptionStackedCalls++;
const jsError = core.destructureError(error);
const message = jsError.exceptionMessage;
@ -1480,44 +1487,42 @@
error,
});
// Avoid recursing `reportException()` via error handlers more than once.
if (reportExceptionStackedCalls > 1 || window.dispatchEvent(event)) {
if (reportExceptionStackedCalls > 1 || globalThis_.dispatchEvent(event)) {
ops.op_dispatch_exception(error);
}
reportExceptionStackedCalls--;
}
}
function checkThis(thisArg) {
if (thisArg !== null && thisArg !== undefined && thisArg !== globalThis) {
function checkThis(thisArg) {
if (thisArg !== null && thisArg !== undefined && thisArg !== globalThis_) {
throw new TypeError("Illegal invocation");
}
}
}
// https://html.spec.whatwg.org/#dom-reporterror
function reportError(error) {
// https://html.spec.whatwg.org/#dom-reporterror
function reportError(error) {
checkThis(this);
const prefix = "Failed to call 'reportError'";
webidl.requiredArguments(arguments.length, 1, { prefix });
reportException(error);
}
}
window.__bootstrap.eventTarget = {
EventTarget,
setEventTargetData,
listenerCount,
};
window.__bootstrap.event = {
reportException,
setIsTrusted,
setTarget,
defineEventHandler,
export {
_skipInternalInit,
Event,
ErrorEvent,
CloseEvent,
MessageEvent,
CustomEvent,
defineEventHandler,
ErrorEvent,
Event,
EventTarget,
listenerCount,
MessageEvent,
ProgressEvent,
PromiseRejectionEvent,
reportError,
};
})(this);
reportException,
saveGlobalThisReference,
setEventTargetData,
setIsTrusted,
setTarget,
};

View file

@ -6,12 +6,10 @@
/// <reference path="../web/internal.d.ts" />
/// <reference path="../web/lib.deno_web.d.ts" />
"use strict";
((window) => {
const core = window.Deno.core;
const { DOMException } = window.__bootstrap.domException;
const {
const core = globalThis.Deno.core;
import DOMException from "internal:ext/web/01_dom_exception.js";
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayBuffer,
ArrayBufferPrototype,
ArrayBufferPrototypeGetByteLength,
@ -40,28 +38,28 @@
BigUint64Array,
Float32Array,
Float64Array,
} = window.__bootstrap.primordials;
} = primordials;
const objectCloneMemo = new WeakMap();
const objectCloneMemo = new WeakMap();
function cloneArrayBuffer(
function cloneArrayBuffer(
srcBuffer,
srcByteOffset,
srcLength,
_cloneConstructor,
) {
) {
// this function fudges the return type but SharedArrayBuffer is disabled for a while anyway
return ArrayBufferPrototypeSlice(
srcBuffer,
srcByteOffset,
srcByteOffset + srcLength,
);
}
}
// TODO(petamoriken): Resizable ArrayBuffer support in the future
/** Clone a value in a similar way to structured cloning. It is similar to a
// TODO(petamoriken): Resizable ArrayBuffer support in the future
/** Clone a value in a similar way to structured cloning. It is similar to a
* StructureDeserialize(StructuredSerialize(...)). */
function structuredClone(value) {
function structuredClone(value) {
// Performance optimization for buffers, otherwise
// `serialize/deserialize` will allocate new buffer.
if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, value)) {
@ -137,7 +135,6 @@
}
throw e;
}
}
}
window.__bootstrap.structuredClone = structuredClone;
})(globalThis);
export { structuredClone };

View file

@ -1,10 +1,9 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
"use strict";
((window) => {
const core = window.Deno.core;
const ops = core.ops;
const {
const core = globalThis.Deno.core;
const ops = core.ops;
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayPrototypePush,
ArrayPrototypeShift,
FunctionPrototypeCall,
@ -22,36 +21,36 @@
SymbolFor,
TypeError,
indirectEval,
} = window.__bootstrap.primordials;
const { webidl } = window.__bootstrap;
const { reportException } = window.__bootstrap.event;
const { assert } = window.__bootstrap.infra;
} = primordials;
import * as webidl from "internal:ext/webidl/00_webidl.js";
import { reportException } from "internal:ext/web/02_event.js";
import { assert } from "internal:ext/web/00_infra.js";
const hrU8 = new Uint8Array(8);
const hr = new Uint32Array(hrU8.buffer);
function opNow() {
const hrU8 = new Uint8Array(8);
const hr = new Uint32Array(hrU8.buffer);
function opNow() {
ops.op_now(hrU8);
return (hr[0] * 1000 + hr[1] / 1e6);
}
}
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
/**
/**
* The task queue corresponding to the timer task source.
*
* @type { {action: () => void, nestingLevel: number}[] }
*/
const timerTasks = [];
const timerTasks = [];
/**
/**
* The current task's timer nesting level, or zero if we're not currently
* running a timer task (since the minimum nesting level is 1).
*
* @type {number}
*/
let timerNestingLevel = 0;
let timerNestingLevel = 0;
function handleTimerMacrotask() {
function handleTimerMacrotask() {
if (timerTasks.length === 0) {
return true;
}
@ -66,21 +65,21 @@
timerNestingLevel = 0;
}
return timerTasks.length === 0;
}
}
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
/**
/**
* The keys in this map correspond to the key ID's in the spec's map of active
* timers. The values are the timeout's cancel rid.
*
* @type {Map<number, { cancelRid: number, isRef: boolean, promiseId: number }>}
*/
const activeTimers = new Map();
const activeTimers = new Map();
let nextId = 1;
let nextId = 1;
/**
/**
* @param {Function | string} callback
* @param {number} timeout
* @param {Array<any>} args
@ -88,13 +87,13 @@
* @param {number | undefined} prevId
* @returns {number} The timer ID
*/
function initializeTimer(
function initializeTimer(
callback,
timeout,
args,
repeat,
prevId,
) {
) {
// 2. If previousId was given, let id be previousId; otherwise, let
// previousId be an implementation-defined integer than is greater than zero
// and does not already exist in global's map of active timers.
@ -189,11 +188,11 @@
);
return id;
}
}
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
/**
/**
* @typedef ScheduledTimer
* @property {number} millis
* @property {() => void} cb
@ -202,23 +201,22 @@
* @property {ScheduledTimer | null} next
*/
/**
/**
* A doubly linked list of timers.
* @type { { head: ScheduledTimer | null, tail: ScheduledTimer | null } }
*/
const scheduledTimers = { head: null, tail: null };
const scheduledTimers = { head: null, tail: null };
/**
/**
* @param {() => void} cb Will be run after the timeout, if it hasn't been
* cancelled.
* @param {number} millis
* @param {{ cancelRid: number, isRef: boolean, promiseId: number }} timerInfo
*/
function runAfterTimeout(cb, millis, timerInfo) {
function runAfterTimeout(cb, millis, timerInfo) {
const cancelRid = timerInfo.cancelRid;
const sleepPromise = core.opAsync("op_sleep", millis, cancelRid);
timerInfo.promiseId =
sleepPromise[SymbolFor("Deno.core.internalPromiseId")];
timerInfo.promiseId = sleepPromise[SymbolFor("Deno.core.internalPromiseId")];
if (!timerInfo.isRef) {
core.unrefOp(timerInfo.promiseId);
}
@ -283,10 +281,10 @@
}
},
);
}
}
/** @param {ScheduledTimer} timerObj */
function removeFromScheduledTimers(timerObj) {
/** @param {ScheduledTimer} timerObj */
function removeFromScheduledTimers(timerObj) {
if (timerObj.prev !== null) {
timerObj.prev.next = timerObj.next;
} else {
@ -299,17 +297,17 @@
assert(scheduledTimers.tail === timerObj);
scheduledTimers.tail = timerObj.prev;
}
}
}
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
function checkThis(thisArg) {
function checkThis(thisArg) {
if (thisArg !== null && thisArg !== undefined && thisArg !== globalThis) {
throw new TypeError("Illegal invocation");
}
}
}
function setTimeout(callback, timeout = 0, ...args) {
function setTimeout(callback, timeout = 0, ...args) {
checkThis(this);
if (typeof callback !== "function") {
callback = webidl.converters.DOMString(callback);
@ -317,9 +315,9 @@
timeout = webidl.converters.long(timeout);
return initializeTimer(callback, timeout, args, false);
}
}
function setInterval(callback, timeout = 0, ...args) {
function setInterval(callback, timeout = 0, ...args) {
checkThis(this);
if (typeof callback !== "function") {
callback = webidl.converters.DOMString(callback);
@ -327,9 +325,9 @@
timeout = webidl.converters.long(timeout);
return initializeTimer(callback, timeout, args, true);
}
}
function clearTimeout(id = 0) {
function clearTimeout(id = 0) {
checkThis(this);
id = webidl.converters.long(id);
const timerInfo = MapPrototypeGet(activeTimers, id);
@ -337,39 +335,38 @@
core.tryClose(timerInfo.cancelRid);
MapPrototypeDelete(activeTimers, id);
}
}
}
function clearInterval(id = 0) {
function clearInterval(id = 0) {
checkThis(this);
clearTimeout(id);
}
}
function refTimer(id) {
function refTimer(id) {
const timerInfo = MapPrototypeGet(activeTimers, id);
if (timerInfo === undefined || timerInfo.isRef) {
return;
}
timerInfo.isRef = true;
core.refOp(timerInfo.promiseId);
}
}
function unrefTimer(id) {
function unrefTimer(id) {
const timerInfo = MapPrototypeGet(activeTimers, id);
if (timerInfo === undefined || !timerInfo.isRef) {
return;
}
timerInfo.isRef = false;
core.unrefOp(timerInfo.promiseId);
}
}
window.__bootstrap.timers = {
setTimeout,
setInterval,
clearTimeout,
export {
clearInterval,
clearTimeout,
handleTimerMacrotask,
opNow,
refTimer,
setInterval,
setTimeout,
unrefTimer,
};
})(this);
};

View file

@ -1,14 +1,18 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
"use strict";
// @ts-check
/// <reference path="../../core/internal.d.ts" />
((window) => {
const webidl = window.__bootstrap.webidl;
const { Event, setIsTrusted, defineEventHandler } = window.__bootstrap.event;
const { EventTarget, listenerCount } = window.__bootstrap.eventTarget;
const {
import * as webidl from "internal:ext/webidl/00_webidl.js";
import {
defineEventHandler,
Event,
EventTarget,
listenerCount,
setIsTrusted,
} from "internal:ext/web/02_event.js";
const primordials = globalThis.__bootstrap.primordials;
const {
SafeArrayIterator,
SafeSetIterator,
Set,
@ -16,20 +20,24 @@
SetPrototypeDelete,
Symbol,
TypeError,
} = window.__bootstrap.primordials;
const { setTimeout, refTimer, unrefTimer } = window.__bootstrap.timers;
} = primordials;
import {
refTimer,
setTimeout,
unrefTimer,
} from "internal:ext/web/02_timers.js";
const add = Symbol("[[add]]");
const signalAbort = Symbol("[[signalAbort]]");
const remove = Symbol("[[remove]]");
const abortReason = Symbol("[[abortReason]]");
const abortAlgos = Symbol("[[abortAlgos]]");
const signal = Symbol("[[signal]]");
const timerId = Symbol("[[timerId]]");
const add = Symbol("[[add]]");
const signalAbort = Symbol("[[signalAbort]]");
const remove = Symbol("[[remove]]");
const abortReason = Symbol("[[abortReason]]");
const abortAlgos = Symbol("[[abortAlgos]]");
const signal = Symbol("[[signal]]");
const timerId = Symbol("[[timerId]]");
const illegalConstructorKey = Symbol("illegalConstructorKey");
const illegalConstructorKey = Symbol("illegalConstructorKey");
class AbortSignal extends EventTarget {
class AbortSignal extends EventTarget {
static abort(reason = undefined) {
if (reason !== undefined) {
reason = webidl.converters.any(reason);
@ -138,13 +146,13 @@
unrefTimer(this[timerId]);
}
}
}
defineEventHandler(AbortSignal.prototype, "abort");
}
defineEventHandler(AbortSignal.prototype, "abort");
webidl.configurePrototype(AbortSignal);
const AbortSignalPrototype = AbortSignal.prototype;
webidl.configurePrototype(AbortSignal);
const AbortSignalPrototype = AbortSignal.prototype;
class AbortController {
class AbortController {
[signal] = new AbortSignal(illegalConstructorKey);
constructor() {
@ -160,41 +168,38 @@
webidl.assertBranded(this, AbortControllerPrototype);
this[signal][signalAbort](reason);
}
}
}
webidl.configurePrototype(AbortController);
const AbortControllerPrototype = AbortController.prototype;
webidl.configurePrototype(AbortController);
const AbortControllerPrototype = AbortController.prototype;
webidl.converters["AbortSignal"] = webidl.createInterfaceConverter(
webidl.converters["AbortSignal"] = webidl.createInterfaceConverter(
"AbortSignal",
AbortSignal.prototype,
);
);
function newSignal() {
function newSignal() {
return new AbortSignal(illegalConstructorKey);
}
}
function follow(followingSignal, parentSignal) {
function follow(followingSignal, parentSignal) {
if (followingSignal.aborted) {
return;
}
if (parentSignal.aborted) {
followingSignal[signalAbort](parentSignal.reason);
} else {
parentSignal[add](() =>
followingSignal[signalAbort](parentSignal.reason)
);
}
parentSignal[add](() => followingSignal[signalAbort](parentSignal.reason));
}
}
window.__bootstrap.abortSignal = {
AbortSignal,
export {
AbortController,
AbortSignal,
AbortSignalPrototype,
add,
signalAbort,
remove,
follow,
newSignal,
};
})(this);
remove,
signalAbort,
};

View file

@ -1,20 +1,19 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
"use strict";
// @ts-check
/// <reference path="../../core/internal.d.ts" />
((window) => {
const { EventTarget } = window.__bootstrap.eventTarget;
const {
import { EventTarget } from "internal:ext/web/02_event.js";
const primordials = globalThis.__bootstrap.primordials;
const {
Symbol,
SymbolToStringTag,
TypeError,
} = window.__bootstrap.primordials;
} = primordials;
const illegalConstructorKey = Symbol("illegalConstructorKey");
const illegalConstructorKey = Symbol("illegalConstructorKey");
class Window extends EventTarget {
class Window extends EventTarget {
constructor(key = null) {
if (key !== illegalConstructorKey) {
throw new TypeError("Illegal constructor.");
@ -25,9 +24,9 @@
get [SymbolToStringTag]() {
return "Window";
}
}
}
class WorkerGlobalScope extends EventTarget {
class WorkerGlobalScope extends EventTarget {
constructor(key = null) {
if (key != illegalConstructorKey) {
throw new TypeError("Illegal constructor.");
@ -38,9 +37,9 @@
get [SymbolToStringTag]() {
return "WorkerGlobalScope";
}
}
}
class DedicatedWorkerGlobalScope extends WorkerGlobalScope {
class DedicatedWorkerGlobalScope extends WorkerGlobalScope {
constructor(key = null) {
if (key != illegalConstructorKey) {
throw new TypeError("Illegal constructor.");
@ -51,29 +50,34 @@
get [SymbolToStringTag]() {
return "DedicatedWorkerGlobalScope";
}
}
}
window.__bootstrap.globalInterfaces = {
DedicatedWorkerGlobalScope,
Window,
WorkerGlobalScope,
dedicatedWorkerGlobalScopeConstructorDescriptor: {
const dedicatedWorkerGlobalScopeConstructorDescriptor = {
configurable: true,
enumerable: false,
value: DedicatedWorkerGlobalScope,
writable: true,
},
windowConstructorDescriptor: {
};
const windowConstructorDescriptor = {
configurable: true,
enumerable: false,
value: Window,
writable: true,
},
workerGlobalScopeConstructorDescriptor: {
};
const workerGlobalScopeConstructorDescriptor = {
configurable: true,
enumerable: false,
value: WorkerGlobalScope,
writable: true,
},
};
})(this);
};
export {
DedicatedWorkerGlobalScope,
dedicatedWorkerGlobalScopeConstructorDescriptor,
Window,
windowConstructorDescriptor,
WorkerGlobalScope,
workerGlobalScopeConstructorDescriptor,
};

View file

@ -6,23 +6,21 @@
/// <reference path="../web/internal.d.ts" />
/// <reference lib="esnext" />
"use strict";
((window) => {
const core = Deno.core;
const ops = core.ops;
const webidl = window.__bootstrap.webidl;
const { DOMException } = window.__bootstrap.domException;
const {
const core = globalThis.Deno.core;
const ops = core.ops;
import * as webidl from "internal:ext/webidl/00_webidl.js";
import DOMException from "internal:ext/web/01_dom_exception.js";
const primordials = globalThis.__bootstrap.primordials;
const {
ObjectPrototypeIsPrototypeOf,
TypeErrorPrototype,
} = window.__bootstrap.primordials;
} = primordials;
/**
/**
* @param {string} data
* @returns {string}
*/
function atob(data) {
function atob(data) {
const prefix = "Failed to execute 'atob'";
webidl.requiredArguments(arguments.length, 1, { prefix });
data = webidl.converters.DOMString(data, {
@ -40,13 +38,13 @@
}
throw e;
}
}
}
/**
/**
* @param {string} data
* @returns {string}
*/
function btoa(data) {
function btoa(data) {
const prefix = "Failed to execute 'btoa'";
webidl.requiredArguments(arguments.length, 1, { prefix });
data = webidl.converters.DOMString(data, {
@ -64,10 +62,6 @@
}
throw e;
}
}
}
window.__bootstrap.base64 = {
atob,
btoa,
};
})(globalThis);
export { atob, btoa };

File diff suppressed because it is too large Load diff

View file

@ -9,13 +9,11 @@
/// <reference path="../web/lib.deno_web.d.ts" />
/// <reference lib="esnext" />
"use strict";
((window) => {
const core = Deno.core;
const ops = core.ops;
const webidl = window.__bootstrap.webidl;
const {
const core = globalThis.Deno.core;
const ops = core.ops;
import * as webidl from "internal:ext/webidl/00_webidl.js";
const primordials = globalThis.__bootstrap.primordials;
const {
PromiseReject,
PromiseResolve,
// TODO(lucacasonato): add SharedArrayBuffer to primordials
@ -27,9 +25,9 @@
ObjectPrototypeIsPrototypeOf,
ArrayBufferIsView,
Uint32Array,
} = window.__bootstrap.primordials;
} = primordials;
class TextDecoder {
class TextDecoder {
/** @type {string} */
#encoding;
/** @type {boolean} */
@ -160,12 +158,12 @@
}
}
}
}
}
webidl.configurePrototype(TextDecoder);
const TextDecoderPrototype = TextDecoder.prototype;
webidl.configurePrototype(TextDecoder);
const TextDecoderPrototype = TextDecoder.prototype;
class TextEncoder {
class TextEncoder {
constructor() {
this[webidl.brand] = webidl.brand;
}
@ -217,14 +215,14 @@
written: encodeIntoBuf[1],
};
}
}
}
const encodeIntoBuf = new Uint32Array(2);
const encodeIntoBuf = new Uint32Array(2);
webidl.configurePrototype(TextEncoder);
const TextEncoderPrototype = TextEncoder.prototype;
webidl.configurePrototype(TextEncoder);
const TextEncoderPrototype = TextEncoder.prototype;
class TextDecoderStream {
class TextDecoderStream {
/** @type {TextDecoder} */
#decoder;
/** @type {TransformStream<BufferSource, string>} */
@ -306,12 +304,12 @@
webidl.assertBranded(this, TextDecoderStreamPrototype);
return this.#transform.writable;
}
}
}
webidl.configurePrototype(TextDecoderStream);
const TextDecoderStreamPrototype = TextDecoderStream.prototype;
webidl.configurePrototype(TextDecoderStream);
const TextDecoderStreamPrototype = TextDecoderStream.prototype;
class TextEncoderStream {
class TextEncoderStream {
/** @type {string | null} */
#pendingHighSurrogate = null;
/** @type {TransformStream<string, Uint8Array>} */
@ -379,12 +377,12 @@
webidl.assertBranded(this, TextEncoderStreamPrototype);
return this.#transform.writable;
}
}
}
webidl.configurePrototype(TextEncoderStream);
const TextEncoderStreamPrototype = TextEncoderStream.prototype;
webidl.configurePrototype(TextEncoderStream);
const TextEncoderStreamPrototype = TextEncoderStream.prototype;
webidl.converters.TextDecoderOptions = webidl.createDictionaryConverter(
webidl.converters.TextDecoderOptions = webidl.createDictionaryConverter(
"TextDecoderOptions",
[
{
@ -398,8 +396,8 @@
defaultValue: false,
},
],
);
webidl.converters.TextDecodeOptions = webidl.createDictionaryConverter(
);
webidl.converters.TextDecodeOptions = webidl.createDictionaryConverter(
"TextDecodeOptions",
[
{
@ -408,12 +406,12 @@
defaultValue: false,
},
],
);
);
/**
/**
* @param {Uint8Array} bytes
*/
function decode(bytes, encoding) {
function decode(bytes, encoding) {
const BOMEncoding = BOMSniff(bytes);
if (BOMEncoding !== null) {
encoding = BOMEncoding;
@ -421,25 +419,24 @@
bytes = TypedArrayPrototypeSubarray(bytes, start);
}
return new TextDecoder(encoding).decode(bytes);
}
}
/**
/**
* @param {Uint8Array} bytes
*/
function BOMSniff(bytes) {
function BOMSniff(bytes) {
if (bytes[0] === 0xEF && bytes[1] === 0xBB && bytes[2] === 0xBF) {
return "UTF-8";
}
if (bytes[0] === 0xFE && bytes[1] === 0xFF) return "UTF-16BE";
if (bytes[0] === 0xFF && bytes[1] === 0xFE) return "UTF-16LE";
return null;
}
}
window.__bootstrap.encoding = {
TextEncoder,
TextDecoder,
TextEncoderStream,
TextDecoderStream,
export {
decode,
};
})(this);
TextDecoder,
TextDecoderStream,
TextEncoder,
TextEncoderStream,
};

View file

@ -9,13 +9,12 @@
/// <reference path="../web/lib.deno_web.d.ts" />
/// <reference path="./internal.d.ts" />
/// <reference lib="esnext" />
"use strict";
((window) => {
const core = window.Deno.core;
const ops = core.ops;
const webidl = window.__bootstrap.webidl;
const {
const core = globalThis.Deno.core;
const ops = core.ops;
import * as webidl from "internal:ext/webidl/00_webidl.js";
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayBufferPrototype,
ArrayBufferPrototypeSlice,
ArrayBufferIsView,
@ -38,19 +37,19 @@
TypedArrayPrototypeSet,
TypeError,
Uint8Array,
} = window.__bootstrap.primordials;
const consoleInternal = window.__bootstrap.console;
} = primordials;
import { createFilteredInspectProxy } from "internal:ext/console/02_console.js";
// TODO(lucacasonato): this needs to not be hardcoded and instead depend on
// host os.
const isWindows = false;
// TODO(lucacasonato): this needs to not be hardcoded and instead depend on
// host os.
const isWindows = false;
/**
/**
* @param {string} input
* @param {number} position
* @returns {{result: string, position: number}}
*/
function collectCodepointsNotCRLF(input, position) {
function collectCodepointsNotCRLF(input, position) {
// See https://w3c.github.io/FileAPI/#convert-line-endings-to-native and
// https://infra.spec.whatwg.org/#collect-a-sequence-of-code-points
const start = position;
@ -60,13 +59,13 @@
c = StringPrototypeCharAt(input, ++position)
);
return { result: StringPrototypeSlice(input, start, position), position };
}
}
/**
/**
* @param {string} s
* @returns {string}
*/
function convertLineEndingsToNative(s) {
function convertLineEndingsToNative(s) {
const nativeLineEnding = isWindows ? "\r\n" : "\n";
let { result, position } = collectCodepointsNotCRLF(s, 0);
@ -94,23 +93,23 @@
}
return result;
}
}
/** @param {(BlobReference | Blob)[]} parts */
async function* toIterator(parts) {
/** @param {(BlobReference | Blob)[]} parts */
async function* toIterator(parts) {
for (let i = 0; i < parts.length; ++i) {
yield* parts[i].stream();
}
}
}
/** @typedef {BufferSource | Blob | string} BlobPart */
/** @typedef {BufferSource | Blob | string} BlobPart */
/**
/**
* @param {BlobPart[]} parts
* @param {string} endings
* @returns {{ parts: (BlobReference|Blob)[], size: number }}
*/
function processBlobParts(parts, endings) {
function processBlobParts(parts, endings) {
/** @type {(BlobReference|Blob)[]} */
const processedParts = [];
let size = 0;
@ -142,27 +141,27 @@
}
}
return { parts: processedParts, size };
}
}
/**
/**
* @param {string} str
* @returns {string}
*/
function normalizeType(str) {
function normalizeType(str) {
let normalizedType = str;
if (!RegExpPrototypeTest(/^[\x20-\x7E]*$/, str)) {
normalizedType = "";
}
return StringPrototypeToLowerCase(normalizedType);
}
}
/**
/**
* Get all Parts as a flat array containing all references
* @param {Blob} blob
* @param {string[]} bag
* @returns {string[]}
*/
function getParts(blob, bag = []) {
function getParts(blob, bag = []) {
const parts = blob[_parts];
for (let i = 0; i < parts.length; ++i) {
const part = parts[i];
@ -173,13 +172,13 @@
}
}
return bag;
}
}
const _type = Symbol("Type");
const _size = Symbol("Size");
const _parts = Symbol("Parts");
const _type = Symbol("Type");
const _size = Symbol("Size");
const _parts = Symbol("Parts");
class Blob {
class Blob {
[_type] = "";
[_size] = 0;
[_parts];
@ -384,7 +383,7 @@
}
[SymbolFor("Deno.customInspect")](inspect) {
return inspect(consoleInternal.createFilteredInspectProxy({
return inspect(createFilteredInspectProxy({
object: this,
evaluate: ObjectPrototypeIsPrototypeOf(BlobPrototype, this),
keys: [
@ -393,16 +392,16 @@
],
}));
}
}
}
webidl.configurePrototype(Blob);
const BlobPrototype = Blob.prototype;
webidl.configurePrototype(Blob);
const BlobPrototype = Blob.prototype;
webidl.converters["Blob"] = webidl.createInterfaceConverter(
webidl.converters["Blob"] = webidl.createInterfaceConverter(
"Blob",
Blob.prototype,
);
webidl.converters["BlobPart"] = (V, opts) => {
);
webidl.converters["BlobPart"] = (V, opts) => {
// Union for ((ArrayBuffer or ArrayBufferView) or Blob or USVString)
if (typeof V == "object") {
if (ObjectPrototypeIsPrototypeOf(BlobPrototype, V)) {
@ -423,15 +422,15 @@
// on the string.
// core.encode() is equivalent to USVString normalization.
return webidl.converters["DOMString"](V, opts);
};
webidl.converters["sequence<BlobPart>"] = webidl.createSequenceConverter(
};
webidl.converters["sequence<BlobPart>"] = webidl.createSequenceConverter(
webidl.converters["BlobPart"],
);
webidl.converters["EndingType"] = webidl.createEnumConverter("EndingType", [
);
webidl.converters["EndingType"] = webidl.createEnumConverter("EndingType", [
"transparent",
"native",
]);
const blobPropertyBagDictionary = [
]);
const blobPropertyBagDictionary = [
{
key: "type",
converter: webidl.converters["DOMString"],
@ -442,16 +441,16 @@
converter: webidl.converters["EndingType"],
defaultValue: "transparent",
},
];
webidl.converters["BlobPropertyBag"] = webidl.createDictionaryConverter(
];
webidl.converters["BlobPropertyBag"] = webidl.createDictionaryConverter(
"BlobPropertyBag",
blobPropertyBagDictionary,
);
);
const _Name = Symbol("[[Name]]");
const _LastModified = Symbol("[[LastModified]]");
const _Name = Symbol("[[Name]]");
const _LastModified = Symbol("[[LastModified]]");
class File extends Blob {
class File extends Blob {
/** @type {string} */
[_Name];
/** @type {number} */
@ -503,12 +502,12 @@
webidl.assertBranded(this, FilePrototype);
return this[_LastModified];
}
}
}
webidl.configurePrototype(File);
const FilePrototype = File.prototype;
webidl.configurePrototype(File);
const FilePrototype = File.prototype;
webidl.converters["FilePropertyBag"] = webidl.createDictionaryConverter(
webidl.converters["FilePropertyBag"] = webidl.createDictionaryConverter(
"FilePropertyBag",
blobPropertyBagDictionary,
[
@ -517,21 +516,21 @@
converter: webidl.converters["long long"],
},
],
);
);
// A finalization registry to deallocate a blob part when its JS reference is
// garbage collected.
const registry = new FinalizationRegistry((uuid) => {
// A finalization registry to deallocate a blob part when its JS reference is
// garbage collected.
const registry = new FinalizationRegistry((uuid) => {
ops.op_blob_remove_part(uuid);
});
});
// TODO(lucacasonato): get a better stream from Rust in BlobReference#stream
// TODO(lucacasonato): get a better stream from Rust in BlobReference#stream
/**
/**
* An opaque reference to a blob part in Rust. This could be backed by a file,
* in memory storage, or something else.
*/
class BlobReference {
class BlobReference {
/**
* Don't use directly. Use `BlobReference.fromUint8Array`.
* @param {string} id
@ -588,9 +587,9 @@
// yield core.opAsync("op_blob_read_part", chunk._id);
// }
}
}
}
/**
/**
* Construct a new Blob object from an object URL.
*
* This new object will not duplicate data in memory with the original Blob
@ -604,7 +603,7 @@
* @param {string} url
* @returns {Blob | null}
*/
function blobFromObjectUrl(url) {
function blobFromObjectUrl(url) {
const blobData = ops.op_blob_from_object_url(url);
if (blobData === null) {
return null;
@ -625,14 +624,13 @@
blob[_size] = totalSize;
blob[_parts] = parts;
return blob;
}
}
window.__bootstrap.file = {
blobFromObjectUrl,
getParts,
export {
Blob,
blobFromObjectUrl,
BlobPrototype,
File,
FilePrototype,
};
})(this);
getParts,
};

View file

@ -10,18 +10,16 @@
/// <reference path="./internal.d.ts" />
/// <reference lib="esnext" />
"use strict";
((window) => {
const core = window.Deno.core;
const webidl = window.__bootstrap.webidl;
const { forgivingBase64Encode } = window.__bootstrap.infra;
const { ProgressEvent } = window.__bootstrap.event;
const { EventTarget } = window.__bootstrap.eventTarget;
const { decode, TextDecoder } = window.__bootstrap.encoding;
const { parseMimeType } = window.__bootstrap.mimesniff;
const { DOMException } = window.__bootstrap.domException;
const {
const core = globalThis.Deno.core;
const ops = core.ops;
import * as webidl from "internal:ext/webidl/00_webidl.js";
const primordials = globalThis.__bootstrap.primordials;
import { forgivingBase64Encode } from "internal:ext/web/00_infra.js";
import { EventTarget, ProgressEvent } from "internal:ext/web/02_event.js";
import { decode, TextDecoder } from "internal:ext/web/08_text_encoding.js";
import { parseMimeType } from "internal:ext/web/01_mimesniff.js";
import DOMException from "internal:ext/web/01_dom_exception.js";
const {
ArrayPrototypePush,
ArrayPrototypeReduce,
FunctionPrototypeCall,
@ -37,15 +35,15 @@
TypeError,
Uint8Array,
Uint8ArrayPrototype,
} = window.__bootstrap.primordials;
} = primordials;
const state = Symbol("[[state]]");
const result = Symbol("[[result]]");
const error = Symbol("[[error]]");
const aborted = Symbol("[[aborted]]");
const handlerSymbol = Symbol("eventHandlers");
const state = Symbol("[[state]]");
const result = Symbol("[[result]]");
const error = Symbol("[[error]]");
const aborted = Symbol("[[aborted]]");
const handlerSymbol = Symbol("eventHandlers");
class FileReader extends EventTarget {
class FileReader extends EventTarget {
/** @type {"empty" | "loading" | "done"} */
[state] = "empty";
/** @type {null | string | ArrayBuffer} */
@ -169,7 +167,7 @@
break;
}
case "BinaryString":
this[result] = core.ops.op_encode_binary_string(bytes);
this[result] = ops.op_encode_binary_string(bytes);
break;
case "Text": {
let decoder = undefined;
@ -433,49 +431,49 @@
set onabort(value) {
this.#setEventHandlerFor("abort", value);
}
}
}
webidl.configurePrototype(FileReader);
const FileReaderPrototype = FileReader.prototype;
webidl.configurePrototype(FileReader);
const FileReaderPrototype = FileReader.prototype;
ObjectDefineProperty(FileReader, "EMPTY", {
ObjectDefineProperty(FileReader, "EMPTY", {
writable: false,
enumerable: true,
configurable: false,
value: 0,
});
ObjectDefineProperty(FileReader, "LOADING", {
});
ObjectDefineProperty(FileReader, "LOADING", {
writable: false,
enumerable: true,
configurable: false,
value: 1,
});
ObjectDefineProperty(FileReader, "DONE", {
});
ObjectDefineProperty(FileReader, "DONE", {
writable: false,
enumerable: true,
configurable: false,
value: 2,
});
ObjectDefineProperty(FileReader.prototype, "EMPTY", {
});
ObjectDefineProperty(FileReader.prototype, "EMPTY", {
writable: false,
enumerable: true,
configurable: false,
value: 0,
});
ObjectDefineProperty(FileReader.prototype, "LOADING", {
});
ObjectDefineProperty(FileReader.prototype, "LOADING", {
writable: false,
enumerable: true,
configurable: false,
value: 1,
});
ObjectDefineProperty(FileReader.prototype, "DONE", {
});
ObjectDefineProperty(FileReader.prototype, "DONE", {
writable: false,
enumerable: true,
configurable: false,
value: 2,
});
});
function makeWrappedHandler(handler) {
function makeWrappedHandler(handler) {
function wrappedHandler(...args) {
if (typeof wrappedHandler.handler !== "function") {
return;
@ -488,9 +486,6 @@
}
wrappedHandler.handler = handler;
return wrappedHandler;
}
}
window.__bootstrap.fileReader = {
FileReader,
};
})(this);
export { FileReader };

View file

@ -10,20 +10,18 @@
/// <reference path="../url/lib.deno_url.d.ts" />
/// <reference path="./internal.d.ts" />
/// <reference lib="esnext" />
"use strict";
((window) => {
const core = Deno.core;
const ops = core.ops;
const webidl = window.__bootstrap.webidl;
const { getParts } = window.__bootstrap.file;
const { URL } = window.__bootstrap.url;
const core = globalThis.Deno.core;
const ops = core.ops;
import * as webidl from "internal:ext/webidl/00_webidl.js";
import { getParts } from "internal:ext/web/09_file.js";
import { URL } from "internal:ext/url/00_url.js";
/**
/**
* @param {Blob} blob
* @returns {string}
*/
function createObjectURL(blob) {
function createObjectURL(blob) {
const prefix = "Failed to execute 'createObjectURL' on 'URL'";
webidl.requiredArguments(arguments.length, 1, { prefix });
blob = webidl.converters["Blob"](blob, {
@ -31,19 +29,14 @@
prefix,
});
const url = ops.op_blob_create_object_url(
blob.type,
getParts(blob),
);
return ops.op_blob_create_object_url(blob.type, getParts(blob));
}
return url;
}
/**
/**
* @param {string} url
* @returns {void}
*/
function revokeObjectURL(url) {
function revokeObjectURL(url) {
const prefix = "Failed to execute 'revokeObjectURL' on 'URL'";
webidl.requiredArguments(arguments.length, 1, { prefix });
url = webidl.converters["DOMString"](url, {
@ -52,8 +45,7 @@
});
ops.op_blob_revoke_object_url(url);
}
}
URL.createObjectURL = createObjectURL;
URL.revokeObjectURL = revokeObjectURL;
})(globalThis);
URL.createObjectURL = createObjectURL;
URL.revokeObjectURL = revokeObjectURL;

View file

@ -1,12 +1,11 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
"use strict";
/// <reference path="../../core/internal.d.ts" />
((window) => {
const { URL } = window.__bootstrap.url;
const { DOMException } = window.__bootstrap.domException;
const {
import { URL } from "internal:ext/url/00_url.js";
import DOMException from "internal:ext/web/01_dom_exception.js";
const primordials = globalThis.__bootstrap.primordials;
const {
Error,
ObjectDefineProperties,
Symbol,
@ -16,16 +15,16 @@
WeakMap,
WeakMapPrototypeGet,
WeakMapPrototypeSet,
} = window.__bootstrap.primordials;
} = primordials;
const locationConstructorKey = Symbol("locationConstuctorKey");
const locationConstructorKey = Symbol("locationConstuctorKey");
// The differences between the definitions of `Location` and `WorkerLocation`
// are because of the `LegacyUnforgeable` attribute only specified upon
// `Location`'s properties. See:
// - https://html.spec.whatwg.org/multipage/history.html#the-location-interface
// - https://heycam.github.io/webidl/#LegacyUnforgeable
class Location {
// The differences between the definitions of `Location` and `WorkerLocation`
// are because of the `LegacyUnforgeable` attribute only specified upon
// `Location`'s properties. See:
// - https://html.spec.whatwg.org/multipage/history.html#the-location-interface
// - https://heycam.github.io/webidl/#LegacyUnforgeable
class Location {
constructor(href = null, key = null) {
if (key != locationConstructorKey) {
throw new TypeError("Illegal constructor.");
@ -198,18 +197,18 @@
},
});
}
}
}
ObjectDefineProperties(Location.prototype, {
ObjectDefineProperties(Location.prototype, {
[SymbolToStringTag]: {
value: "Location",
configurable: true,
},
});
});
const workerLocationUrls = new WeakMap();
const workerLocationUrls = new WeakMap();
class WorkerLocation {
class WorkerLocation {
constructor(href = null, key = null) {
if (key != locationConstructorKey) {
throw new TypeError("Illegal constructor.");
@ -219,9 +218,9 @@
url.password = "";
WeakMapPrototypeSet(workerLocationUrls, this, url);
}
}
}
ObjectDefineProperties(WorkerLocation.prototype, {
ObjectDefineProperties(WorkerLocation.prototype, {
hash: {
get() {
const url = WeakMapPrototypeGet(workerLocationUrls, this);
@ -353,28 +352,33 @@
return `${this.constructor.name} ${inspect(object)}`;
},
},
});
});
let location = undefined;
let workerLocation = undefined;
let location = undefined;
let workerLocation = undefined;
function setLocationHref(href) {
function setLocationHref(href) {
location = new Location(href, locationConstructorKey);
workerLocation = new WorkerLocation(href, locationConstructorKey);
}
}
window.__bootstrap.location = {
locationConstructorDescriptor: {
function getLocationHref() {
return location?.href;
}
const locationConstructorDescriptor = {
value: Location,
configurable: true,
writable: true,
},
workerLocationConstructorDescriptor: {
};
const workerLocationConstructorDescriptor = {
value: WorkerLocation,
configurable: true,
writable: true,
},
locationDescriptor: {
};
const locationDescriptor = {
get() {
return location;
},
@ -382,8 +386,8 @@
throw new DOMException(`Cannot set "location".`, "NotSupportedError");
},
enumerable: true,
},
workerLocationDescriptor: {
};
const workerLocationDescriptor = {
get() {
if (workerLocation == null) {
throw new Error(
@ -394,10 +398,13 @@
},
configurable: true,
enumerable: true,
},
};
export {
getLocationHref,
locationConstructorDescriptor,
locationDescriptor,
setLocationHref,
getLocationHref() {
return location?.href;
},
};
})(this);
workerLocationConstructorDescriptor,
workerLocationDescriptor,
};

View file

@ -6,16 +6,18 @@
/// <reference path="./internal.d.ts" />
/// <reference path="./lib.deno_web.d.ts" />
"use strict";
((window) => {
const core = window.Deno.core;
const { InterruptedPrototype, ops } = core;
const webidl = window.__bootstrap.webidl;
const { EventTarget, setEventTargetData } = window.__bootstrap.eventTarget;
const { MessageEvent, defineEventHandler } = window.__bootstrap.event;
const { DOMException } = window.__bootstrap.domException;
const {
const core = globalThis.Deno.core;
const { InterruptedPrototype, ops } = core;
import * as webidl from "internal:ext/webidl/00_webidl.js";
import {
defineEventHandler,
EventTarget,
MessageEvent,
setEventTargetData,
} from "internal:ext/web/02_event.js";
import DOMException from "internal:ext/web/01_dom_exception.js";
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayBufferPrototype,
ArrayPrototypeFilter,
ArrayPrototypeIncludes,
@ -26,9 +28,9 @@
SymbolFor,
SymbolIterator,
TypeError,
} = window.__bootstrap.primordials;
} = primordials;
class MessageChannel {
class MessageChannel {
/** @type {MessagePort} */
#port1;
/** @type {MessagePort} */
@ -58,28 +60,28 @@
inspect({ port1: this.port1, port2: this.port2 })
}`;
}
}
}
webidl.configurePrototype(MessageChannel);
const MessageChannelPrototype = MessageChannel.prototype;
webidl.configurePrototype(MessageChannel);
const MessageChannelPrototype = MessageChannel.prototype;
const _id = Symbol("id");
const _enabled = Symbol("enabled");
const _id = Symbol("id");
const _enabled = Symbol("enabled");
/**
/**
* @param {number} id
* @returns {MessagePort}
*/
function createMessagePort(id) {
function createMessagePort(id) {
const port = core.createHostObject();
ObjectSetPrototypeOf(port, MessagePortPrototype);
port[webidl.brand] = webidl.brand;
setEventTargetData(port);
port[_id] = id;
return port;
}
}
class MessagePort extends EventTarget {
class MessagePort extends EventTarget {
/** @type {number | null} */
[_id] = null;
/** @type {boolean} */
@ -176,28 +178,28 @@
this[_id] = null;
}
}
}
}
defineEventHandler(MessagePort.prototype, "message", function (self) {
defineEventHandler(MessagePort.prototype, "message", function (self) {
self.start();
});
defineEventHandler(MessagePort.prototype, "messageerror");
});
defineEventHandler(MessagePort.prototype, "messageerror");
webidl.configurePrototype(MessagePort);
const MessagePortPrototype = MessagePort.prototype;
webidl.configurePrototype(MessagePort);
const MessagePortPrototype = MessagePort.prototype;
/**
/**
* @returns {[number, number]}
*/
function opCreateEntangledMessagePort() {
function opCreateEntangledMessagePort() {
return ops.op_message_port_create_entangled();
}
}
/**
* @param {globalThis.__bootstrap.messagePort.MessageData} messageData
/**
* @param {messagePort.MessageData} messageData
* @returns {[any, object[]]}
*/
function deserializeJsMessageData(messageData) {
function deserializeJsMessageData(messageData) {
/** @type {object[]} */
const transferables = [];
const hostObjects = [];
@ -235,19 +237,19 @@
}
return [data, transferables];
}
}
/**
/**
* @param {any} data
* @param {object[]} transferables
* @returns {globalThis.__bootstrap.messagePort.MessageData}
* @returns {messagePort.MessageData}
*/
function serializeJsMessageData(data, transferables) {
function serializeJsMessageData(data, transferables) {
const transferredArrayBuffers = [];
for (let i = 0, j = 0; i < transferables.length; i++) {
const ab = transferables[i];
if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, ab)) {
if (ab.byteLength === 0 && core.ops.op_arraybuffer_was_detached(ab)) {
if (ab.byteLength === 0 && ops.op_arraybuffer_was_detached(ab)) {
throw new DOMException(
`ArrayBuffer at index ${j} is already detached`,
"DataCloneError",
@ -268,7 +270,7 @@
throw new DOMException(err, "DataCloneError");
});
/** @type {globalThis.__bootstrap.messagePort.Transferable[]} */
/** @type {messagePort.Transferable[]} */
const serializedTransferables = [];
let arrayBufferI = 0;
@ -305,9 +307,9 @@
data: serializedData,
transferables: serializedTransferables,
};
}
}
webidl.converters.StructuredSerializeOptions = webidl
webidl.converters.StructuredSerializeOptions = webidl
.createDictionaryConverter(
"StructuredSerializeOptions",
[
@ -321,7 +323,7 @@
],
);
function structuredClone(value, options) {
function structuredClone(value, options) {
const prefix = "Failed to execute 'structuredClone'";
webidl.requiredArguments(arguments.length, 1, { prefix });
options = webidl.converters.StructuredSerializeOptions(options, {
@ -330,14 +332,13 @@
});
const messageData = serializeJsMessageData(value, options.transfer);
return deserializeJsMessageData(messageData)[0];
}
}
window.__bootstrap.messagePort = {
export {
deserializeJsMessageData,
MessageChannel,
MessagePort,
MessagePortPrototype,
deserializeJsMessageData,
serializeJsMessageData,
structuredClone,
};
})(globalThis);
};

View file

@ -5,24 +5,21 @@
/// <reference path="./internal.d.ts" />
/// <reference path="./lib.deno_web.d.ts" />
"use strict";
const core = globalThis.Deno.core;
const ops = core.ops;
import * as webidl from "internal:ext/webidl/00_webidl.js";
import { TransformStream } from "internal:ext/web/06_streams.js";
((window) => {
const core = window.Deno.core;
const ops = core.ops;
const webidl = window.__bootstrap.webidl;
const { TransformStream } = window.__bootstrap.streams;
webidl.converters.CompressionFormat = webidl.createEnumConverter(
webidl.converters.CompressionFormat = webidl.createEnumConverter(
"CompressionFormat",
[
"deflate",
"deflate-raw",
"gzip",
],
);
);
class CompressionStream {
class CompressionStream {
#transform;
constructor(format) {
@ -65,12 +62,12 @@
webidl.assertBranded(this, CompressionStreamPrototype);
return this.#transform.writable;
}
}
}
webidl.configurePrototype(CompressionStream);
const CompressionStreamPrototype = CompressionStream.prototype;
webidl.configurePrototype(CompressionStream);
const CompressionStreamPrototype = CompressionStream.prototype;
class DecompressionStream {
class DecompressionStream {
#transform;
constructor(format) {
@ -113,19 +110,15 @@
webidl.assertBranded(this, DecompressionStreamPrototype);
return this.#transform.writable;
}
}
}
function maybeEnqueue(controller, output) {
function maybeEnqueue(controller, output) {
if (output && output.byteLength > 0) {
controller.enqueue(output);
}
}
}
webidl.configurePrototype(DecompressionStream);
const DecompressionStreamPrototype = DecompressionStream.prototype;
webidl.configurePrototype(DecompressionStream);
const DecompressionStreamPrototype = DecompressionStream.prototype;
window.__bootstrap.compression = {
CompressionStream,
DecompressionStream,
};
})(globalThis);
export { CompressionStream, DecompressionStream };

View file

@ -1,8 +1,7 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
"use strict";
((window) => {
const {
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayPrototypeFilter,
ArrayPrototypeFind,
ArrayPrototypePush,
@ -14,20 +13,20 @@
Symbol,
SymbolFor,
TypeError,
} = window.__bootstrap.primordials;
} = primordials;
import * as webidl from "internal:ext/webidl/00_webidl.js";
import { structuredClone } from "internal:ext/web/02_structured_clone.js";
import { createFilteredInspectProxy } from "internal:ext/console/02_console.js";
import { EventTarget } from "internal:ext/web/02_event.js";
import { opNow } from "internal:ext/web/02_timers.js";
import DOMException from "internal:ext/web/01_dom_exception.js";
const { webidl, structuredClone } = window.__bootstrap;
const consoleInternal = window.__bootstrap.console;
const { EventTarget } = window.__bootstrap.eventTarget;
const { opNow } = window.__bootstrap.timers;
const { DOMException } = window.__bootstrap.domException;
const illegalConstructorKey = Symbol("illegalConstructorKey");
const customInspect = SymbolFor("Deno.customInspect");
let performanceEntries = [];
let timeOrigin;
const illegalConstructorKey = Symbol("illegalConstructorKey");
const customInspect = SymbolFor("Deno.customInspect");
let performanceEntries = [];
let timeOrigin;
webidl.converters["PerformanceMarkOptions"] = webidl
webidl.converters["PerformanceMarkOptions"] = webidl
.createDictionaryConverter(
"PerformanceMarkOptions",
[
@ -42,14 +41,14 @@
],
);
webidl.converters["DOMString or DOMHighResTimeStamp"] = (V, opts) => {
webidl.converters["DOMString or DOMHighResTimeStamp"] = (V, opts) => {
if (webidl.type(V) === "Number" && V !== null) {
return webidl.converters.DOMHighResTimeStamp(V, opts);
}
return webidl.converters.DOMString(V, opts);
};
};
webidl.converters["PerformanceMeasureOptions"] = webidl
webidl.converters["PerformanceMeasureOptions"] = webidl
.createDictionaryConverter(
"PerformanceMeasureOptions",
[
@ -72,28 +71,28 @@
],
);
webidl.converters["DOMString or PerformanceMeasureOptions"] = (V, opts) => {
webidl.converters["DOMString or PerformanceMeasureOptions"] = (V, opts) => {
if (webidl.type(V) === "Object" && V !== null) {
return webidl.converters["PerformanceMeasureOptions"](V, opts);
}
return webidl.converters.DOMString(V, opts);
};
};
function setTimeOrigin(origin) {
function setTimeOrigin(origin) {
timeOrigin = origin;
}
}
function findMostRecent(
function findMostRecent(
name,
type,
) {
) {
return ArrayPrototypeFind(
ArrayPrototypeReverse(ArrayPrototypeSlice(performanceEntries)),
(entry) => entry.name === name && entry.entryType === type,
);
}
}
function convertMarkToTimestamp(mark) {
function convertMarkToTimestamp(mark) {
if (typeof mark === "string") {
const entry = findMostRecent(mark, "mark");
if (!entry) {
@ -108,27 +107,27 @@
throw new TypeError("Mark cannot be negative.");
}
return mark;
}
}
function filterByNameType(
function filterByNameType(
name,
type,
) {
) {
return ArrayPrototypeFilter(
performanceEntries,
(entry) =>
(name ? entry.name === name : true) &&
(type ? entry.entryType === type : true),
);
}
}
const now = opNow;
const now = opNow;
const _name = Symbol("[[name]]");
const _entryType = Symbol("[[entryType]]");
const _startTime = Symbol("[[startTime]]");
const _duration = Symbol("[[duration]]");
class PerformanceEntry {
const _name = Symbol("[[name]]");
const _entryType = Symbol("[[entryType]]");
const _startTime = Symbol("[[startTime]]");
const _duration = Symbol("[[duration]]");
class PerformanceEntry {
[_name] = "";
[_entryType] = "";
[_startTime] = 0;
@ -183,7 +182,7 @@
}
[customInspect](inspect) {
return inspect(consoleInternal.createFilteredInspectProxy({
return inspect(createFilteredInspectProxy({
object: this,
evaluate: ObjectPrototypeIsPrototypeOf(
PerformanceEntryPrototype,
@ -197,12 +196,12 @@
],
}));
}
}
webidl.configurePrototype(PerformanceEntry);
const PerformanceEntryPrototype = PerformanceEntry.prototype;
}
webidl.configurePrototype(PerformanceEntry);
const PerformanceEntryPrototype = PerformanceEntry.prototype;
const _detail = Symbol("[[detail]]");
class PerformanceMark extends PerformanceEntry {
const _detail = Symbol("[[detail]]");
class PerformanceMark extends PerformanceEntry {
[_detail] = null;
get detail() {
@ -254,7 +253,7 @@
}
[customInspect](inspect) {
return inspect(consoleInternal.createFilteredInspectProxy({
return inspect(createFilteredInspectProxy({
object: this,
evaluate: ObjectPrototypeIsPrototypeOf(PerformanceMarkPrototype, this),
keys: [
@ -266,10 +265,10 @@
],
}));
}
}
webidl.configurePrototype(PerformanceMark);
const PerformanceMarkPrototype = PerformanceMark.prototype;
class PerformanceMeasure extends PerformanceEntry {
}
webidl.configurePrototype(PerformanceMark);
const PerformanceMarkPrototype = PerformanceMark.prototype;
class PerformanceMeasure extends PerformanceEntry {
[_detail] = null;
get detail() {
@ -310,7 +309,7 @@
}
[customInspect](inspect) {
return inspect(consoleInternal.createFilteredInspectProxy({
return inspect(createFilteredInspectProxy({
object: this,
evaluate: ObjectPrototypeIsPrototypeOf(
PerformanceMeasurePrototype,
@ -325,10 +324,10 @@
],
}));
}
}
webidl.configurePrototype(PerformanceMeasure);
const PerformanceMeasurePrototype = PerformanceMeasure.prototype;
class Performance extends EventTarget {
}
webidl.configurePrototype(PerformanceMeasure);
const PerformanceMeasurePrototype = PerformanceMeasure.prototype;
class Performance extends EventTarget {
constructor(key = null) {
if (key != illegalConstructorKey) {
webidl.illegalConstructor();
@ -568,27 +567,28 @@
}
[customInspect](inspect) {
return inspect(consoleInternal.createFilteredInspectProxy({
return inspect(createFilteredInspectProxy({
object: this,
evaluate: ObjectPrototypeIsPrototypeOf(PerformancePrototype, this),
keys: [],
}));
}
}
webidl.configurePrototype(Performance);
const PerformancePrototype = Performance.prototype;
}
webidl.configurePrototype(Performance);
const PerformancePrototype = Performance.prototype;
webidl.converters["Performance"] = webidl.createInterfaceConverter(
webidl.converters["Performance"] = webidl.createInterfaceConverter(
"Performance",
PerformancePrototype,
);
);
window.__bootstrap.performance = {
const performance = new Performance(illegalConstructorKey);
export {
Performance,
performance,
PerformanceEntry,
PerformanceMark,
PerformanceMeasure,
Performance,
performance: new Performance(illegalConstructorKey),
setTimeOrigin,
};
})(this);
};

View file

@ -29,11 +29,12 @@ fn setup() -> Vec<Extension> {
deno_console::init(),
deno_web::init::<Permissions>(BlobStore::default(), None),
Extension::builder("bench_setup")
.js(vec![(
"setup",
.esm(vec![(
"internal:setup",
r#"
const { TextDecoder } = globalThis.__bootstrap.encoding;
const hello12k = Deno.core.encode("hello world\n".repeat(1e3));
import { TextDecoder } from "internal:ext/web/08_text_encoding.js";
globalThis.TextDecoder = TextDecoder;
globalThis.hello12k = Deno.core.encode("hello world\n".repeat(1e3));
"#,
)])
.state(|state| {

View file

@ -28,9 +28,10 @@ fn setup() -> Vec<Extension> {
deno_console::init(),
deno_web::init::<Permissions>(BlobStore::default(), None),
Extension::builder("bench_setup")
.js(vec![
("setup", r#"
const { setTimeout, handleTimerMacrotask } = globalThis.__bootstrap.timers;
.esm(vec![
("internal:setup", r#"
import { setTimeout, handleTimerMacrotask } from "internal:ext/web/02_timers.js";
globalThis.setTimeout = setTimeout;
Deno.core.setMacrotaskCallback(handleTimerMacrotask);
"#),
])

145
ext/web/internal.d.ts vendored
View file

@ -1,14 +1,10 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
// deno-lint-ignore-file no-var
/// <reference no-default-lib="true" />
/// <reference lib="esnext" />
declare namespace globalThis {
declare namespace __bootstrap {
declare var infra: {
collectSequenceOfCodepoints(
declare module "internal:ext/web/00_infra.js" {
function collectSequenceOfCodepoints(
input: string,
position: number,
condition: (char: string) => boolean,
@ -16,26 +12,26 @@ declare namespace globalThis {
result: string;
position: number;
};
ASCII_DIGIT: string[];
ASCII_UPPER_ALPHA: string[];
ASCII_LOWER_ALPHA: string[];
ASCII_ALPHA: string[];
ASCII_ALPHANUMERIC: string[];
HTTP_TAB_OR_SPACE: string[];
HTTP_WHITESPACE: string[];
HTTP_TOKEN_CODE_POINT: string[];
HTTP_TOKEN_CODE_POINT_RE: RegExp;
HTTP_QUOTED_STRING_TOKEN_POINT: string[];
HTTP_QUOTED_STRING_TOKEN_POINT_RE: RegExp;
HTTP_TAB_OR_SPACE_PREFIX_RE: RegExp;
HTTP_TAB_OR_SPACE_SUFFIX_RE: RegExp;
HTTP_WHITESPACE_PREFIX_RE: RegExp;
HTTP_WHITESPACE_SUFFIX_RE: RegExp;
httpTrim(s: string): string;
regexMatcher(chars: string[]): string;
byteUpperCase(s: string): string;
byteLowerCase(s: string): string;
collectHttpQuotedString(
const ASCII_DIGIT: string[];
const ASCII_UPPER_ALPHA: string[];
const ASCII_LOWER_ALPHA: string[];
const ASCII_ALPHA: string[];
const ASCII_ALPHANUMERIC: string[];
const HTTP_TAB_OR_SPACE: string[];
const HTTP_WHITESPACE: string[];
const HTTP_TOKEN_CODE_POINT: string[];
const HTTP_TOKEN_CODE_POINT_RE: RegExp;
const HTTP_QUOTED_STRING_TOKEN_POINT: string[];
const HTTP_QUOTED_STRING_TOKEN_POINT_RE: RegExp;
const HTTP_TAB_OR_SPACE_PREFIX_RE: RegExp;
const HTTP_TAB_OR_SPACE_SUFFIX_RE: RegExp;
const HTTP_WHITESPACE_PREFIX_RE: RegExp;
const HTTP_WHITESPACE_SUFFIX_RE: RegExp;
function httpTrim(s: string): string;
function regexMatcher(chars: string[]): string;
function byteUpperCase(s: string): string;
function byteLowerCase(s: string): string;
function collectHttpQuotedString(
input: string,
position: number,
extractValue: boolean,
@ -43,78 +39,73 @@ declare namespace globalThis {
result: string;
position: number;
};
forgivingBase64Encode(data: Uint8Array): string;
forgivingBase64Decode(data: string): Uint8Array;
serializeJSValueToJSONString(value: unknown): string;
};
function forgivingBase64Encode(data: Uint8Array): string;
function forgivingBase64Decode(data: string): Uint8Array;
function serializeJSValueToJSONString(value: unknown): string;
}
declare var domException: {
DOMException: typeof DOMException;
};
declare module "internal:ext/web/01_dom_exception.js" {
export = DOMException;
}
declare namespace mimesniff {
declare interface MimeType {
declare module "internal:ext/web/01_mimesniff.js" {
interface MimeType {
type: string;
subtype: string;
parameters: Map<string, string>;
}
declare function parseMimeType(input: string): MimeType | null;
declare function essence(mimeType: MimeType): string;
declare function serializeMimeType(mimeType: MimeType): string;
declare function extractMimeType(
function parseMimeType(input: string): MimeType | null;
function essence(mimeType: MimeType): string;
function serializeMimeType(mimeType: MimeType): string;
function extractMimeType(
headerValues: string[] | null,
): MimeType | null;
}
}
declare var eventTarget: {
EventTarget: typeof EventTarget;
};
declare module "internal:ext/web/02_event.js" {
const EventTarget: typeof EventTarget;
const Event: typeof event;
const ErrorEvent: typeof ErrorEvent;
const CloseEvent: typeof CloseEvent;
const MessageEvent: typeof MessageEvent;
const CustomEvent: typeof CustomEvent;
const ProgressEvent: typeof ProgressEvent;
const PromiseRejectionEvent: typeof PromiseRejectionEvent;
const reportError: typeof reportError;
}
declare var event: {
Event: typeof event;
ErrorEvent: typeof ErrorEvent;
CloseEvent: typeof CloseEvent;
MessageEvent: typeof MessageEvent;
CustomEvent: typeof CustomEvent;
ProgressEvent: typeof ProgressEvent;
PromiseRejectionEvent: typeof PromiseRejectionEvent;
reportError: typeof reportError;
};
declare module "internal:ext/web/12_location.js" {
function getLocationHref(): string | undefined;
}
declare var location: {
getLocationHref(): string | undefined;
};
declare module "internal:ext/web/05_base64.js" {
function atob(data: string): string;
function btoa(data: string): string;
}
declare var base64: {
atob(data: string): string;
btoa(data: string): string;
};
declare module "internal:ext/web/09_file.js" {
function blobFromObjectUrl(url: string): Blob | null;
function getParts(blob: Blob): string[];
const Blob: typeof Blob;
const File: typeof File;
}
declare var file: {
blobFromObjectUrl(url: string): Blob | null;
getParts(blob: Blob): string[];
Blob: typeof Blob;
File: typeof File;
};
declare module "internal:ext/web/06_streams.js" {
const ReadableStream: typeof ReadableStream;
function isReadableStreamDisturbed(stream: ReadableStream): boolean;
function createProxy<T>(stream: ReadableStream<T>): ReadableStream<T>;
}
declare var streams: {
ReadableStream: typeof ReadableStream;
isReadableStreamDisturbed(stream: ReadableStream): boolean;
createProxy<T>(stream: ReadableStream<T>): ReadableStream<T>;
};
declare namespace messagePort {
declare type Transferable = {
declare module "internal:ext/web/13_message_port.js" {
type Transferable = {
kind: "messagePort";
data: number;
} | {
kind: "arrayBuffer";
data: number;
};
declare interface MessageData {
interface MessageData {
data: Uint8Array;
transferables: Transferable[];
}
}
}
}

View file

@ -64,7 +64,7 @@ pub fn init<P: TimersPermission + 'static>(
) -> Extension {
Extension::builder(env!("CARGO_PKG_NAME"))
.dependencies(vec!["deno_webidl", "deno_console", "deno_url"])
.js(include_js_files!(
.esm(include_js_files!(
prefix "internal:ext/web",
"00_infra.js",
"01_dom_exception.js",

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -6,20 +6,22 @@
/// <reference path="../web/lib.deno_web.d.ts" />
/// <reference path="./lib.deno_webgpu.d.ts" />
"use strict";
const core = globalThis.Deno.core;
const ops = core.ops;
import * as webidl from "internal:ext/webidl/00_webidl.js";
const primordials = globalThis.__bootstrap.primordials;
const { Symbol } = primordials;
import {
_device,
assertDevice,
createGPUTexture,
} from "internal:ext/webgpu/01_webgpu.js";
((window) => {
const core = window.Deno.core;
const ops = core.ops;
const webidl = window.__bootstrap.webidl;
const { Symbol } = window.__bootstrap.primordials;
const { _device, assertDevice, createGPUTexture } = window.__bootstrap.webgpu;
const _surfaceRid = Symbol("[[surfaceRid]]");
const _configuration = Symbol("[[configuration]]");
const _canvas = Symbol("[[canvas]]");
const _currentTexture = Symbol("[[currentTexture]]");
class GPUCanvasContext {
const _surfaceRid = Symbol("[[surfaceRid]]");
const _configuration = Symbol("[[configuration]]");
const _canvas = Symbol("[[canvas]]");
const _currentTexture = Symbol("[[currentTexture]]");
class GPUCanvasContext {
/** @type {number} */
[_surfaceRid];
/** @type {InnerGPUDevice} */
@ -131,19 +133,14 @@
this[_currentTexture].destroy();
this[_currentTexture] = undefined;
}
}
const GPUCanvasContextPrototype = GPUCanvasContext.prototype;
}
const GPUCanvasContextPrototype = GPUCanvasContext.prototype;
function createCanvasContext(options) {
function createCanvasContext(options) {
const canvasContext = webidl.createBranded(GPUCanvasContext);
canvasContext[_surfaceRid] = options.surfaceRid;
canvasContext[_canvas] = options.canvas;
return canvasContext;
}
}
window.__bootstrap.webgpu = {
...window.__bootstrap.webgpu,
GPUCanvasContext,
createCanvasContext,
};
})(this);
export { createCanvasContext, GPUCanvasContext };

View file

@ -6,23 +6,20 @@
/// <reference path="../web/lib.deno_web.d.ts" />
/// <reference path="./lib.deno_webgpu.d.ts" />
"use strict";
import * as webidl from "internal:ext/webidl/00_webidl.js";
import { GPUTextureUsage } from "internal:ext/webgpu/01_webgpu.js";
((window) => {
const webidl = window.__bootstrap.webidl;
const { GPUTextureUsage } = window.__bootstrap.webgpu;
// ENUM: GPUCanvasAlphaMode
webidl.converters["GPUCanvasAlphaMode"] = webidl.createEnumConverter(
// ENUM: GPUCanvasAlphaMode
webidl.converters["GPUCanvasAlphaMode"] = webidl.createEnumConverter(
"GPUCanvasAlphaMode",
[
"opaque",
"premultiplied",
],
);
);
// NON-SPEC: ENUM: GPUPresentMode
webidl.converters["GPUPresentMode"] = webidl.createEnumConverter(
// NON-SPEC: ENUM: GPUPresentMode
webidl.converters["GPUPresentMode"] = webidl.createEnumConverter(
"GPUPresentMode",
[
"autoVsync",
@ -32,10 +29,10 @@
"immediate",
"mailbox",
],
);
);
// DICT: GPUCanvasConfiguration
const dictMembersGPUCanvasConfiguration = [
// DICT: GPUCanvasConfiguration
const dictMembersGPUCanvasConfiguration = [
{ key: "device", converter: webidl.converters.GPUDevice, required: true },
{
key: "format",
@ -77,10 +74,9 @@
return [];
},
},
];
webidl.converters["GPUCanvasConfiguration"] = webidl
];
webidl.converters["GPUCanvasConfiguration"] = webidl
.createDictionaryConverter(
"GPUCanvasConfiguration",
dictMembersGPUCanvasConfiguration,
);
})(this);

View file

@ -119,7 +119,7 @@ impl Resource for WebGpuQuerySet {
pub fn init(unstable: bool) -> Extension {
Extension::builder(env!("CARGO_PKG_NAME"))
.dependencies(vec!["deno_webidl", "deno_web"])
.js(include_js_files!(
.esm(include_js_files!(
prefix "internal:ext/webgpu",
"01_webgpu.js",
"02_idl_types.js",

View file

@ -15,8 +15,8 @@ use wgpu_types::SurfaceStatus;
pub fn init_surface(unstable: bool) -> Extension {
Extension::builder("deno_webgpu_surface")
.dependencies(vec!["deno_webidl", "deno_web", "deno_webgpu"])
.js(include_js_files!(
prefix "internal:deno_webgpu",
.esm(include_js_files!(
prefix "internal:ext/webgpu",
"03_surface.js",
"04_surface_idl_types.js",
))

View file

@ -6,11 +6,9 @@
/// <reference path="../../core/internal.d.ts" />
"use strict";
((window) => {
const core = window.Deno.core;
const {
const core = globalThis.Deno.core;
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayBufferPrototype,
ArrayBufferIsView,
ArrayPrototypeForEach,
@ -83,24 +81,24 @@
Uint32Array,
Uint8Array,
Uint8ClampedArray,
} = window.__bootstrap.primordials;
} = primordials;
function makeException(ErrorType, message, opts = {}) {
function makeException(ErrorType, message, opts = {}) {
return new ErrorType(
`${opts.prefix ? opts.prefix + ": " : ""}${
opts.context ? opts.context : "Value"
} ${message}`,
);
}
}
function toNumber(value) {
function toNumber(value) {
if (typeof value === "bigint") {
throw TypeError("Cannot convert a BigInt value to a number");
}
return Number(value);
}
}
function type(V) {
function type(V) {
if (V === null) {
return "Null";
}
@ -127,10 +125,10 @@
// such cases. So treat the default case as an object.
return "Object";
}
}
}
// Round x to the nearest integer, choosing the even integer if it lies halfway between two.
function evenRound(x) {
// Round x to the nearest integer, choosing the even integer if it lies halfway between two.
function evenRound(x) {
// There are four cases for numbers with fractional part being .5:
//
// case | x | floor(x) | round(x) | expected | x <> 0 | x % 1 | x & 1 | example
@ -149,17 +147,17 @@
}
return censorNegativeZero(MathRound(x));
}
}
function integerPart(n) {
function integerPart(n) {
return censorNegativeZero(MathTrunc(n));
}
}
function sign(x) {
function sign(x) {
return x < 0 ? -1 : 1;
}
}
function modulo(x, y) {
function modulo(x, y) {
// https://tc39.github.io/ecma262/#eqn-modulo
// Note that http://stackoverflow.com/a/4467559/3191 does NOT work for large modulos
const signMightNotMatch = x % y;
@ -167,13 +165,13 @@
return signMightNotMatch + y;
}
return signMightNotMatch;
}
}
function censorNegativeZero(x) {
function censorNegativeZero(x) {
return x === 0 ? 0 : x;
}
}
function createIntegerConversion(bitLength, typeOpts) {
function createIntegerConversion(bitLength, typeOpts) {
const isSigned = !typeOpts.unsigned;
let lowerBound;
@ -238,9 +236,9 @@
}
return x;
};
}
}
function createLongLongConversion(bitLength, { unsigned }) {
function createLongLongConversion(bitLength, { unsigned }) {
const upperBound = NumberMAX_SAFE_INTEGER;
const lowerBound = unsigned ? 0 : NumberMIN_SAFE_INTEGER;
const asBigIntN = unsigned ? BigIntAsUintN : BigIntAsIntN;
@ -281,35 +279,35 @@
xBigInt = asBigIntN(bitLength, xBigInt);
return Number(xBigInt);
};
}
}
const converters = [];
const converters = [];
converters.any = (V) => {
converters.any = (V) => {
return V;
};
};
converters.boolean = function (val) {
converters.boolean = function (val) {
return !!val;
};
};
converters.byte = createIntegerConversion(8, { unsigned: false });
converters.octet = createIntegerConversion(8, { unsigned: true });
converters.byte = createIntegerConversion(8, { unsigned: false });
converters.octet = createIntegerConversion(8, { unsigned: true });
converters.short = createIntegerConversion(16, { unsigned: false });
converters["unsigned short"] = createIntegerConversion(16, {
converters.short = createIntegerConversion(16, { unsigned: false });
converters["unsigned short"] = createIntegerConversion(16, {
unsigned: true,
});
});
converters.long = createIntegerConversion(32, { unsigned: false });
converters["unsigned long"] = createIntegerConversion(32, { unsigned: true });
converters.long = createIntegerConversion(32, { unsigned: false });
converters["unsigned long"] = createIntegerConversion(32, { unsigned: true });
converters["long long"] = createLongLongConversion(64, { unsigned: false });
converters["unsigned long long"] = createLongLongConversion(64, {
converters["long long"] = createLongLongConversion(64, { unsigned: false });
converters["unsigned long long"] = createLongLongConversion(64, {
unsigned: true,
});
});
converters.float = (V, opts) => {
converters.float = (V, opts) => {
const x = toNumber(V);
if (!NumberIsFinite(x)) {
@ -335,9 +333,9 @@
}
return y;
};
};
converters["unrestricted float"] = (V, _opts) => {
converters["unrestricted float"] = (V, _opts) => {
const x = toNumber(V);
if (isNaN(x)) {
@ -349,9 +347,9 @@
}
return MathFround(x);
};
};
converters.double = (V, opts) => {
converters.double = (V, opts) => {
const x = toNumber(V);
if (!NumberIsFinite(x)) {
@ -363,15 +361,15 @@
}
return x;
};
};
converters["unrestricted double"] = (V, _opts) => {
converters["unrestricted double"] = (V, _opts) => {
const x = toNumber(V);
return x;
};
};
converters.DOMString = function (V, opts = {}) {
converters.DOMString = function (V, opts = {}) {
if (typeof V === "string") {
return V;
} else if (V === null && opts.treatNullAsEmptyString) {
@ -385,19 +383,19 @@
}
return String(V);
};
};
// deno-lint-ignore no-control-regex
const IS_BYTE_STRING = /^[\x00-\xFF]*$/;
converters.ByteString = (V, opts) => {
// deno-lint-ignore no-control-regex
const IS_BYTE_STRING = /^[\x00-\xFF]*$/;
converters.ByteString = (V, opts) => {
const x = converters.DOMString(V, opts);
if (!RegExpPrototypeTest(IS_BYTE_STRING, x)) {
throw makeException(TypeError, "is not a valid ByteString", opts);
}
return x;
};
};
converters.USVString = (V, opts) => {
converters.USVString = (V, opts) => {
const S = converters.DOMString(V, opts);
const n = S.length;
let U = "";
@ -422,42 +420,42 @@
}
}
return U;
};
};
converters.object = (V, opts) => {
converters.object = (V, opts) => {
if (type(V) !== "Object") {
throw makeException(TypeError, "is not an object", opts);
}
return V;
};
};
// Not exported, but used in Function and VoidFunction.
// Not exported, but used in Function and VoidFunction.
// Neither Function nor VoidFunction is defined with [TreatNonObjectAsNull], so
// handling for that is omitted.
function convertCallbackFunction(V, opts) {
// Neither Function nor VoidFunction is defined with [TreatNonObjectAsNull], so
// handling for that is omitted.
function convertCallbackFunction(V, opts) {
if (typeof V !== "function") {
throw makeException(TypeError, "is not a function", opts);
}
return V;
}
}
function isDataView(V) {
function isDataView(V) {
return ArrayBufferIsView(V) &&
TypedArrayPrototypeGetSymbolToStringTag(V) === undefined;
}
}
function isNonSharedArrayBuffer(V) {
function isNonSharedArrayBuffer(V) {
return ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, V);
}
}
function isSharedArrayBuffer(V) {
function isSharedArrayBuffer(V) {
// deno-lint-ignore prefer-primordials
return ObjectPrototypeIsPrototypeOf(SharedArrayBuffer.prototype, V);
}
}
converters.ArrayBuffer = (V, opts = {}) => {
converters.ArrayBuffer = (V, opts = {}) => {
if (!isNonSharedArrayBuffer(V)) {
if (opts.allowShared && !isSharedArrayBuffer(V)) {
throw makeException(
@ -470,9 +468,9 @@
}
return V;
};
};
converters.DataView = (V, opts = {}) => {
converters.DataView = (V, opts = {}) => {
if (!isDataView(V)) {
throw makeException(TypeError, "is not a DataView", opts);
}
@ -486,17 +484,17 @@
}
return V;
};
};
// Returns the unforgeable `TypedArray` constructor name or `undefined`,
// if the `this` value isn't a valid `TypedArray` object.
//
// https://tc39.es/ecma262/#sec-get-%typedarray%.prototype-@@tostringtag
const typedArrayNameGetter = ObjectGetOwnPropertyDescriptor(
// Returns the unforgeable `TypedArray` constructor name or `undefined`,
// if the `this` value isn't a valid `TypedArray` object.
//
// https://tc39.es/ecma262/#sec-get-%typedarray%.prototype-@@tostringtag
const typedArrayNameGetter = ObjectGetOwnPropertyDescriptor(
ObjectGetPrototypeOf(Uint8Array).prototype,
SymbolToStringTag,
).get;
ArrayPrototypeForEach(
).get;
ArrayPrototypeForEach(
[
Int8Array,
Int16Array,
@ -530,11 +528,11 @@
return V;
};
},
);
);
// Common definitions
// Common definitions
converters.ArrayBufferView = (V, opts = {}) => {
converters.ArrayBufferView = (V, opts = {}) => {
if (!ArrayBufferIsView(V)) {
throw makeException(
TypeError,
@ -552,9 +550,9 @@
}
return V;
};
};
converters.BufferSource = (V, opts = {}) => {
converters.BufferSource = (V, opts = {}) => {
if (ArrayBufferIsView(V)) {
if (!opts.allowShared && isSharedArrayBuffer(V.buffer)) {
throw makeException(
@ -587,53 +585,53 @@
}
return V;
};
};
converters.DOMTimeStamp = converters["unsigned long long"];
converters.DOMHighResTimeStamp = converters["double"];
converters.DOMTimeStamp = converters["unsigned long long"];
converters.DOMHighResTimeStamp = converters["double"];
converters.Function = convertCallbackFunction;
converters.Function = convertCallbackFunction;
converters.VoidFunction = convertCallbackFunction;
converters.VoidFunction = convertCallbackFunction;
converters["UVString?"] = createNullableConverter(
converters["UVString?"] = createNullableConverter(
converters.USVString,
);
converters["sequence<double>"] = createSequenceConverter(
);
converters["sequence<double>"] = createSequenceConverter(
converters.double,
);
converters["sequence<object>"] = createSequenceConverter(
);
converters["sequence<object>"] = createSequenceConverter(
converters.object,
);
converters["Promise<undefined>"] = createPromiseConverter(() => undefined);
);
converters["Promise<undefined>"] = createPromiseConverter(() => undefined);
converters["sequence<ByteString>"] = createSequenceConverter(
converters["sequence<ByteString>"] = createSequenceConverter(
converters.ByteString,
);
converters["sequence<sequence<ByteString>>"] = createSequenceConverter(
);
converters["sequence<sequence<ByteString>>"] = createSequenceConverter(
converters["sequence<ByteString>"],
);
converters["record<ByteString, ByteString>"] = createRecordConverter(
);
converters["record<ByteString, ByteString>"] = createRecordConverter(
converters.ByteString,
converters.ByteString,
);
);
converters["sequence<USVString>"] = createSequenceConverter(
converters["sequence<USVString>"] = createSequenceConverter(
converters.USVString,
);
converters["sequence<sequence<USVString>>"] = createSequenceConverter(
);
converters["sequence<sequence<USVString>>"] = createSequenceConverter(
converters["sequence<USVString>"],
);
converters["record<USVString, USVString>"] = createRecordConverter(
);
converters["record<USVString, USVString>"] = createRecordConverter(
converters.USVString,
converters.USVString,
);
);
converters["sequence<DOMString>"] = createSequenceConverter(
converters["sequence<DOMString>"] = createSequenceConverter(
converters.DOMString,
);
);
function requiredArguments(length, required, opts = {}) {
function requiredArguments(length, required, opts = {}) {
if (length < required) {
const errMsg = `${
opts.prefix ? opts.prefix + ": " : ""
@ -642,9 +640,9 @@
} required, but only ${length} present.`;
throw new TypeError(errMsg);
}
}
}
function createDictionaryConverter(name, ...dictionaries) {
function createDictionaryConverter(name, ...dictionaries) {
let hasRequiredKey = false;
const allMembers = [];
for (let i = 0; i < dictionaries.length; ++i) {
@ -741,10 +739,10 @@
return idlDict;
};
}
}
// https://heycam.github.io/webidl/#es-enumeration
function createEnumConverter(name, values) {
// https://heycam.github.io/webidl/#es-enumeration
function createEnumConverter(name, values) {
const E = new Set(values);
return function (V, opts = {}) {
@ -760,9 +758,9 @@
return S;
};
}
}
function createNullableConverter(converter) {
function createNullableConverter(converter) {
return (V, opts = {}) => {
// FIXME: If Type(V) is not Object, and the conversion to an IDL value is
// being performed due to V being assigned to an attribute whose type is a
@ -773,10 +771,10 @@
if (V === null || V === undefined) return null;
return converter(V, opts);
};
}
}
// https://heycam.github.io/webidl/#es-sequence
function createSequenceConverter(converter) {
// https://heycam.github.io/webidl/#es-sequence
function createSequenceConverter(converter) {
return function (V, opts = {}) {
if (type(V) !== "Object") {
throw makeException(
@ -812,9 +810,9 @@
}
return array;
};
}
}
function createRecordConverter(keyConverter, valueConverter) {
function createRecordConverter(keyConverter, valueConverter) {
return (V, opts) => {
if (type(V) !== "Object") {
throw makeException(
@ -851,20 +849,20 @@
}
return result;
};
}
}
function createPromiseConverter(converter) {
function createPromiseConverter(converter) {
return (V, opts) =>
PromisePrototypeThen(PromiseResolve(V), (V) => converter(V, opts));
}
}
function invokeCallbackFunction(
function invokeCallbackFunction(
callable,
args,
thisArg,
returnValueConverter,
opts,
) {
) {
try {
const rv = ReflectApply(callable, thisArg, args);
return returnValueConverter(rv, {
@ -877,39 +875,39 @@
}
throw err;
}
}
}
const brand = Symbol("[[webidl.brand]]");
const brand = Symbol("[[webidl.brand]]");
function createInterfaceConverter(name, prototype) {
function createInterfaceConverter(name, prototype) {
return (V, opts) => {
if (!ObjectPrototypeIsPrototypeOf(prototype, V) || V[brand] !== brand) {
throw makeException(TypeError, `is not of type ${name}.`, opts);
}
return V;
};
}
}
// TODO(lucacasonato): have the user pass in the prototype, and not the type.
function createBranded(Type) {
// TODO(lucacasonato): have the user pass in the prototype, and not the type.
function createBranded(Type) {
const t = ObjectCreate(Type.prototype);
t[brand] = brand;
return t;
}
}
function assertBranded(self, prototype) {
function assertBranded(self, prototype) {
if (
!ObjectPrototypeIsPrototypeOf(prototype, self) || self[brand] !== brand
) {
throw new TypeError("Illegal invocation");
}
}
}
function illegalConstructor() {
function illegalConstructor() {
throw new TypeError("Illegal constructor");
}
}
function define(target, source) {
function define(target, source) {
const keys = ReflectOwnKeys(source);
for (let i = 0; i < keys.length; ++i) {
const key = keys[i];
@ -918,13 +916,13 @@
throw new TypeError(`Cannot redefine property: ${String(key)}`);
}
}
}
}
const _iteratorInternal = Symbol("iterator internal");
const _iteratorInternal = Symbol("iterator internal");
const globalIteratorPrototype = ObjectGetPrototypeOf(ArrayIteratorPrototype);
const globalIteratorPrototype = ObjectGetPrototypeOf(ArrayIteratorPrototype);
function mixinPairIterable(name, prototype, dataSymbol, keyKey, valueKey) {
function mixinPairIterable(name, prototype, dataSymbol, keyKey, valueKey) {
const iteratorPrototype = ObjectCreate(globalIteratorPrototype, {
[SymbolToStringTag]: { configurable: true, value: `${name} Iterator` },
});
@ -1029,9 +1027,9 @@
},
};
return ObjectDefineProperties(prototype.prototype, properties);
}
}
function configurePrototype(prototype) {
function configurePrototype(prototype) {
const descriptors = ObjectGetOwnPropertyDescriptors(prototype.prototype);
for (const key in descriptors) {
if (!ObjectPrototypeHasOwnProperty(descriptors, key)) {
@ -1061,12 +1059,12 @@
configurable: true,
writable: false,
});
}
}
const setlikeInner = Symbol("[[set]]");
const setlikeInner = Symbol("[[set]]");
// Ref: https://webidl.spec.whatwg.org/#es-setlike
function setlike(obj, objPrototype, readonly) {
// Ref: https://webidl.spec.whatwg.org/#es-setlike
function setlike(obj, objPrototype, readonly) {
ObjectDefineProperties(obj, {
size: {
configurable: true,
@ -1163,29 +1161,27 @@
},
});
}
}
}
window.__bootstrap ??= {};
window.__bootstrap.webidl = {
type,
makeException,
export {
assertBranded,
brand,
configurePrototype,
converters,
requiredArguments,
createBranded,
createDictionaryConverter,
createEnumConverter,
createNullableConverter,
createSequenceConverter,
createRecordConverter,
createPromiseConverter,
invokeCallbackFunction,
createInterfaceConverter,
brand,
createBranded,
assertBranded,
createNullableConverter,
createPromiseConverter,
createRecordConverter,
createSequenceConverter,
illegalConstructor,
invokeCallbackFunction,
makeException,
mixinPairIterable,
configurePrototype,
requiredArguments,
setlike,
setlikeInner,
};
})(this);
type,
};

View file

@ -2,7 +2,10 @@
// deno-lint-ignore-file
const { createDictionaryConverter, converters } = globalThis.__bootstrap.webidl;
import {
converters,
createDictionaryConverter,
} from "internal:ext/webidl/00_webidl.js";
const TextDecodeOptions = createDictionaryConverter(
"TextDecodeOptions",
@ -14,6 +17,7 @@ const TextDecodeOptions = createDictionaryConverter(
},
],
);
globalThis.TextDecodeOptions = TextDecodeOptions;
// Sanity check
{
@ -33,3 +37,4 @@ function handwrittenConverter(V) {
}
return defaultValue;
}
globalThis.handwrittenConverter = handwrittenConverter;

View file

@ -11,7 +11,7 @@ fn setup() -> Vec<Extension> {
vec![
deno_webidl::init(),
Extension::builder("deno_webidl_bench")
.js(vec![("setup", include_str!("dict.js"))])
.esm(vec![("internal:setup", include_str!("dict.js"))])
.build(),
]
}

View file

@ -4,10 +4,8 @@
/// <reference no-default-lib="true" />
/// <reference lib="esnext" />
declare namespace globalThis {
declare namespace __bootstrap {
declare namespace webidl {
declare interface ConverterOpts {
declare module "internal:ext/webidl/00_webidl.js" {
interface ConverterOpts {
/**
* The prefix for error messages created by this converter.
* Examples:
@ -16,7 +14,7 @@ declare namespace globalThis {
*/
prefix: string;
}
declare interface ValueConverterOpts extends ConverterOpts {
interface ValueConverterOpts extends ConverterOpts {
/**
* The context of this value error messages created by this converter.
* Examples:
@ -25,12 +23,12 @@ declare namespace globalThis {
*/
context: string;
}
declare function makeException(
function makeException(
ErrorType: any,
message: string,
opts: ValueConverterOpts,
): any;
declare interface IntConverterOpts extends ValueConverterOpts {
interface IntConverterOpts extends ValueConverterOpts {
/**
* Wether to throw if the number is outside of the acceptable values for
* this type.
@ -41,19 +39,19 @@ declare namespace globalThis {
*/
clamp?: boolean;
}
declare interface StringConverterOpts extends ValueConverterOpts {
interface StringConverterOpts extends ValueConverterOpts {
/**
* Wether to treat `null` value as an empty string.
*/
treatNullAsEmptyString?: boolean;
}
declare interface BufferConverterOpts extends ValueConverterOpts {
interface BufferConverterOpts extends ValueConverterOpts {
/**
* Wether to allow `SharedArrayBuffer` (not just `ArrayBuffer`).
*/
allowShared?: boolean;
}
declare const converters: {
const converters: {
any(v: any): any;
/**
* Convert a value into a `boolean` (bool).
@ -205,13 +203,13 @@ declare namespace globalThis {
/**
* Assert that the a function has at least a required amount of arguments.
*/
declare function requiredArguments(
function requiredArguments(
length: number,
required: number,
opts: ConverterOpts,
): void;
declare type Dictionary = DictionaryMember[];
declare interface DictionaryMember {
type Dictionary = DictionaryMember[];
interface DictionaryMember {
key: string;
converter: (v: any, opts: ValueConverterOpts) => any;
defaultValue?: any;
@ -221,7 +219,7 @@ declare namespace globalThis {
/**
* Create a converter for dictionaries.
*/
declare function createDictionaryConverter<T>(
function createDictionaryConverter<T>(
name: string,
...dictionaries: Dictionary[]
): (v: any, opts: ValueConverterOpts) => T;
@ -229,7 +227,7 @@ declare namespace globalThis {
/**
* Create a converter for enums.
*/
declare function createEnumConverter(
function createEnumConverter(
name: string,
values: string[],
): (v: any, opts: ValueConverterOpts) => string;
@ -237,28 +235,28 @@ declare namespace globalThis {
/**
* Create a converter that makes the contained type nullable.
*/
declare function createNullableConverter<T>(
function createNullableConverter<T>(
converter: (v: any, opts: ValueConverterOpts) => T,
): (v: any, opts: ValueConverterOpts) => T | null;
/**
* Create a converter that converts a sequence of the inner type.
*/
declare function createSequenceConverter<T>(
function createSequenceConverter<T>(
converter: (v: any, opts: ValueConverterOpts) => T,
): (v: any, opts: ValueConverterOpts) => T[];
/**
* Create a converter that converts a Promise of the inner type.
*/
declare function createPromiseConverter<T>(
function createPromiseConverter<T>(
converter: (v: any, opts: ValueConverterOpts) => T,
): (v: any, opts: ValueConverterOpts) => Promise<T>;
/**
* Invoke a callback function.
*/
declare function invokeCallbackFunction<T>(
function invokeCallbackFunction<T>(
callable: (...args: any) => any,
args: any[],
thisArg: any,
@ -269,32 +267,32 @@ declare namespace globalThis {
/**
* Throw an illegal constructor error.
*/
declare function illegalConstructor(): never;
function illegalConstructor(): never;
/**
* The branding symbol.
*/
declare const brand: unique symbol;
const brand: unique symbol;
/**
* Create a branded instance of an interface.
*/
declare function createBranded(self: any): any;
function createBranded(self: any): any;
/**
* Assert that self is branded.
*/
declare function assertBranded(self: any, type: any): void;
function assertBranded(self: any, type: any): void;
/**
* Create a converter for interfaces.
*/
declare function createInterfaceConverter(
function createInterfaceConverter(
name: string,
prototype: any,
): (v: any, opts: ValueConverterOpts) => any;
declare function createRecordConverter<
function createRecordConverter<
K extends string | number | symbol,
V,
>(
@ -309,7 +307,7 @@ declare namespace globalThis {
* Mix in the iterable declarations defined in WebIDL.
* https://heycam.github.io/webidl/#es-iterable
*/
declare function mixinPairIterable(
function mixinPairIterable(
name: string,
prototype: any,
dataSymbol: symbol,
@ -320,12 +318,12 @@ declare namespace globalThis {
/**
* Configure prototype properties enumerability / writability / configurability.
*/
declare function configurePrototype(prototype: any);
function configurePrototype(prototype: any);
/**
* Get the WebIDL / ES type of a value.
*/
declare function type(
function type(
v: any,
):
| "Null"
@ -336,6 +334,4 @@ declare namespace globalThis {
| "Symbol"
| "BigInt"
| "Object";
}
}
}

View file

@ -6,7 +6,7 @@ use deno_core::Extension;
/// Load and execute the javascript code.
pub fn init() -> Extension {
Extension::builder(env!("CARGO_PKG_NAME"))
.js(include_js_files!(
.esm(include_js_files!(
prefix "internal:ext/webidl",
"00_webidl.js",
))

View file

@ -1,26 +1,25 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
"use strict";
/// <reference path="../../core/internal.d.ts" />
((window) => {
const core = window.Deno.core;
const ops = core.ops;
const { URL } = window.__bootstrap.url;
const webidl = window.__bootstrap.webidl;
const { HTTP_TOKEN_CODE_POINT_RE } = window.__bootstrap.infra;
const { DOMException } = window.__bootstrap.domException;
const {
Event,
ErrorEvent,
CloseEvent,
MessageEvent,
defineEventHandler,
const core = globalThis.Deno.core;
const ops = core.ops;
import { URL } from "internal:ext/url/00_url.js";
import * as webidl from "internal:ext/webidl/00_webidl.js";
import { HTTP_TOKEN_CODE_POINT_RE } from "internal:ext/web/00_infra.js";
import DOMException from "internal:ext/web/01_dom_exception.js";
import {
_skipInternalInit,
} = window.__bootstrap.event;
const { EventTarget } = window.__bootstrap.eventTarget;
const { Blob, BlobPrototype } = globalThis.__bootstrap.file;
const {
CloseEvent,
defineEventHandler,
ErrorEvent,
Event,
EventTarget,
MessageEvent,
} from "internal:ext/web/02_event.js";
import { Blob, BlobPrototype } from "internal:ext/web/09_file.js";
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayBufferPrototype,
ArrayBufferIsView,
ArrayPrototypeJoin,
@ -42,9 +41,9 @@
SymbolIterator,
PromisePrototypeCatch,
SymbolFor,
} = window.__bootstrap.primordials;
} = primordials;
webidl.converters["sequence<DOMString> or DOMString"] = (V, opts) => {
webidl.converters["sequence<DOMString> or DOMString"] = (V, opts) => {
// Union for (sequence<DOMString> or DOMString)
if (webidl.type(V) === "Object" && V !== null) {
if (V[SymbolIterator] !== undefined) {
@ -52,9 +51,9 @@
}
}
return webidl.converters.DOMString(V, opts);
};
};
webidl.converters["WebSocketSend"] = (V, opts) => {
webidl.converters["WebSocketSend"] = (V, opts) => {
// Union for (Blob or ArrayBufferView or ArrayBuffer or USVString)
if (ObjectPrototypeIsPrototypeOf(BlobPrototype, V)) {
return webidl.converters["Blob"](V, opts);
@ -72,27 +71,27 @@
}
}
return webidl.converters["USVString"](V, opts);
};
};
const CONNECTING = 0;
const OPEN = 1;
const CLOSING = 2;
const CLOSED = 3;
const CONNECTING = 0;
const OPEN = 1;
const CLOSING = 2;
const CLOSED = 3;
const _readyState = Symbol("[[readyState]]");
const _url = Symbol("[[url]]");
const _rid = Symbol("[[rid]]");
const _extensions = Symbol("[[extensions]]");
const _protocol = Symbol("[[protocol]]");
const _binaryType = Symbol("[[binaryType]]");
const _bufferedAmount = Symbol("[[bufferedAmount]]");
const _eventLoop = Symbol("[[eventLoop]]");
const _readyState = Symbol("[[readyState]]");
const _url = Symbol("[[url]]");
const _rid = Symbol("[[rid]]");
const _extensions = Symbol("[[extensions]]");
const _protocol = Symbol("[[protocol]]");
const _binaryType = Symbol("[[binaryType]]");
const _bufferedAmount = Symbol("[[bufferedAmount]]");
const _eventLoop = Symbol("[[eventLoop]]");
const _server = Symbol("[[server]]");
const _idleTimeoutDuration = Symbol("[[idleTimeout]]");
const _idleTimeoutTimeout = Symbol("[[idleTimeoutTimeout]]");
const _serverHandleIdleTimeout = Symbol("[[serverHandleIdleTimeout]]");
class WebSocket extends EventTarget {
const _server = Symbol("[[server]]");
const _idleTimeoutDuration = Symbol("[[idleTimeout]]");
const _idleTimeoutTimeout = Symbol("[[idleTimeoutTimeout]]");
const _serverHandleIdleTimeout = Symbol("[[serverHandleIdleTimeout]]");
class WebSocket extends EventTarget {
[_rid];
[_readyState] = CONNECTING;
@ -225,8 +224,7 @@
if (
ArrayPrototypeSome(
protocols,
(protocol) =>
!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, protocol),
(protocol) => !RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, protocol),
)
) {
throw new DOMException(
@ -540,9 +538,9 @@
})
}`;
}
}
}
ObjectDefineProperties(WebSocket, {
ObjectDefineProperties(WebSocket, {
CONNECTING: {
value: 0,
},
@ -555,25 +553,24 @@
CLOSED: {
value: 3,
},
});
});
defineEventHandler(WebSocket.prototype, "message");
defineEventHandler(WebSocket.prototype, "error");
defineEventHandler(WebSocket.prototype, "close");
defineEventHandler(WebSocket.prototype, "open");
defineEventHandler(WebSocket.prototype, "message");
defineEventHandler(WebSocket.prototype, "error");
defineEventHandler(WebSocket.prototype, "close");
defineEventHandler(WebSocket.prototype, "open");
webidl.configurePrototype(WebSocket);
const WebSocketPrototype = WebSocket.prototype;
webidl.configurePrototype(WebSocket);
const WebSocketPrototype = WebSocket.prototype;
window.__bootstrap.webSocket = {
WebSocket,
_rid,
_readyState,
export {
_eventLoop,
_protocol,
_server,
_idleTimeoutDuration,
_idleTimeoutTimeout,
_protocol,
_readyState,
_rid,
_server,
_serverHandleIdleTimeout,
};
})(this);
WebSocket,
};

View file

@ -1,19 +1,20 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
"use strict";
/// <reference path="../../core/internal.d.ts" />
((window) => {
const core = window.Deno.core;
const ops = core.ops;
const webidl = window.__bootstrap.webidl;
const { writableStreamClose, Deferred } = window.__bootstrap.streams;
const { DOMException } = window.__bootstrap.domException;
const { add, remove } = window.__bootstrap.abortSignal;
const { headersFromHeaderList, headerListFromHeaders, fillHeaders } =
window.__bootstrap.headers;
const {
const core = globalThis.Deno.core;
const ops = core.ops;
import * as webidl from "internal:ext/webidl/00_webidl.js";
import { Deferred, writableStreamClose } from "internal:ext/web/06_streams.js";
import DOMException from "internal:ext/web/01_dom_exception.js";
import { add, remove } from "internal:ext/web/03_abort_signal.js";
import {
fillHeaders,
headerListFromHeaders,
headersFromHeaderList,
} from "internal:ext/fetch/20_headers.js";
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayPrototypeJoin,
ArrayPrototypeMap,
Error,
@ -27,9 +28,9 @@
SymbolFor,
TypeError,
Uint8ArrayPrototype,
} = window.__bootstrap.primordials;
} = primordials;
webidl.converters.WebSocketStreamOptions = webidl.createDictionaryConverter(
webidl.converters.WebSocketStreamOptions = webidl.createDictionaryConverter(
"WebSocketStreamOptions",
[
{
@ -48,8 +49,8 @@
converter: webidl.converters.HeadersInit,
},
],
);
webidl.converters.WebSocketCloseInfo = webidl.createDictionaryConverter(
);
webidl.converters.WebSocketCloseInfo = webidl.createDictionaryConverter(
"WebSocketCloseInfo",
[
{
@ -62,17 +63,17 @@
defaultValue: "",
},
],
);
);
const CLOSE_RESPONSE_TIMEOUT = 5000;
const CLOSE_RESPONSE_TIMEOUT = 5000;
const _rid = Symbol("[[rid]]");
const _url = Symbol("[[url]]");
const _connection = Symbol("[[connection]]");
const _closed = Symbol("[[closed]]");
const _earlyClose = Symbol("[[earlyClose]]");
const _closeSent = Symbol("[[closeSent]]");
class WebSocketStream {
const _rid = Symbol("[[rid]]");
const _url = Symbol("[[url]]");
const _connection = Symbol("[[connection]]");
const _closed = Symbol("[[closed]]");
const _earlyClose = Symbol("[[earlyClose]]");
const _closeSent = Symbol("[[closeSent]]");
class WebSocketStream {
[_rid];
[_url];
@ -153,9 +154,7 @@
"op_ws_create",
"new WebSocketStream()",
this[_url],
options.protocols
? ArrayPrototypeJoin(options.protocols, ", ")
: "",
options.protocols ? ArrayPrototypeJoin(options.protocols, ", ") : "",
cancelRid,
headerListFromHeaders(headers),
),
@ -418,9 +417,8 @@
})
}`;
}
}
}
const WebSocketStreamPrototype = WebSocketStream.prototype;
const WebSocketStreamPrototype = WebSocketStream.prototype;
window.__bootstrap.webSocket.WebSocketStream = WebSocketStream;
})(this);
export { WebSocketStream };

View file

@ -504,7 +504,7 @@ pub fn init<P: WebSocketPermissions + 'static>(
) -> Extension {
Extension::builder(env!("CARGO_PKG_NAME"))
.dependencies(vec!["deno_url", "deno_webidl"])
.js(include_js_files!(
.esm(include_js_files!(
prefix "internal:ext/websocket",
"01_websocket.js",
"02_websocketstream.js",

View file

@ -2,11 +2,11 @@
/// <reference path="../../core/internal.d.ts" />
((window) => {
const core = window.Deno.core;
const ops = core.ops;
const webidl = window.__bootstrap.webidl;
const {
const core = globalThis.Deno.core;
const ops = core.ops;
import * as webidl from "internal:ext/webidl/00_webidl.js";
const primordials = globalThis.__bootstrap.primordials;
const {
SafeArrayIterator,
Symbol,
SymbolFor,
@ -16,11 +16,11 @@
ReflectGet,
ReflectHas,
Proxy,
} = window.__bootstrap.primordials;
} = primordials;
const _persistent = Symbol("[[persistent]]");
const _persistent = Symbol("[[persistent]]");
class Storage {
class Storage {
[_persistent];
constructor() {
@ -88,11 +88,11 @@
webidl.assertBranded(this, StoragePrototype);
ops.op_webstorage_clear(this[_persistent]);
}
}
}
const StoragePrototype = Storage.prototype;
const StoragePrototype = Storage.prototype;
function createStorage(persistent) {
function createStorage(persistent) {
const storage = webidl.createBranded(Storage);
storage[_persistent] = persistent;
@ -169,24 +169,22 @@
};
return proxy;
}
}
let localStorage;
let sessionStorage;
let localStorageStorage;
function localStorage() {
if (!localStorageStorage) {
localStorageStorage = createStorage(true);
}
return localStorageStorage;
}
window.__bootstrap.webStorage = {
localStorage() {
if (!localStorage) {
localStorage = createStorage(true);
let sessionStorageStorage;
function sessionStorage() {
if (!sessionStorageStorage) {
sessionStorageStorage = createStorage(false);
}
return localStorage;
},
sessionStorage() {
if (!sessionStorage) {
sessionStorage = createStorage(false);
}
return sessionStorage;
},
Storage,
};
})(this);
return sessionStorageStorage;
}
export { localStorage, sessionStorage, Storage };

View file

@ -24,7 +24,7 @@ const MAX_STORAGE_BYTES: u32 = 10 * 1024 * 1024;
pub fn init(origin_storage_dir: Option<PathBuf>) -> Extension {
Extension::builder(env!("CARGO_PKG_NAME"))
.dependencies(vec!["deno_webidl"])
.js(include_js_files!(
.esm(include_js_files!(
prefix "internal:ext/webstorage",
"01_webstorage.js",
))

View file

@ -5,7 +5,6 @@ use std::env;
use std::path::PathBuf;
// This is a shim that allows to generate documentation on docs.rs
#[cfg(not(feature = "docsrs"))]
mod not_docs {
use std::path::Path;
@ -121,7 +120,7 @@ mod not_docs {
}
}
fn create_runtime_snapshot(snapshot_path: PathBuf, files: Vec<PathBuf>) {
fn create_runtime_snapshot(snapshot_path: PathBuf, esm_files: Vec<PathBuf>) {
let extensions_with_js: Vec<Extension> = vec![
deno_webidl::init(),
deno_console::init(),
@ -158,7 +157,8 @@ mod not_docs {
startup_snapshot: None,
extensions: vec![],
extensions_with_js,
additional_files: files,
additional_files: vec![],
additional_esm_files: esm_files,
compression_cb: Some(Box::new(|vec, snapshot_slice| {
lzzzz::lz4_hc::compress_to_vec(
snapshot_slice,
@ -172,14 +172,19 @@ mod not_docs {
pub fn build_snapshot(runtime_snapshot_path: PathBuf) {
#[allow(unused_mut)]
let mut js_files = get_js_files(env!("CARGO_MANIFEST_DIR"), "js");
let mut esm_files = get_js_files(
env!("CARGO_MANIFEST_DIR"),
"js",
Some(Box::new(|path| !path.ends_with("99_main.js"))),
);
#[cfg(not(feature = "snapshot_from_snapshot"))]
{
let manifest = env!("CARGO_MANIFEST_DIR");
let path = PathBuf::from(manifest);
js_files.push(path.join("js").join("99_main.js"));
esm_files.push(path.join("js").join("99_main.js"));
}
create_runtime_snapshot(runtime_snapshot_path, js_files);
create_runtime_snapshot(runtime_snapshot_path, esm_files);
}
}

View file

@ -1,18 +1,17 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
"use strict";
((window) => {
const { ObjectFreeze, StringPrototypeSplit } = window.__bootstrap.primordials;
const primordials = globalThis.__bootstrap.primordials;
const { ObjectFreeze, StringPrototypeSplit } = primordials;
const build = {
const build = {
target: "unknown",
arch: "unknown",
os: "unknown",
vendor: "unknown",
env: undefined,
};
};
function setBuildInfo(target) {
function setBuildInfo(target) {
const { 0: arch, 1: vendor, 2: os, 3: env } = StringPrototypeSplit(
target,
"-",
@ -24,10 +23,6 @@
build.os = os;
build.env = env;
ObjectFreeze(build);
}
}
window.__bootstrap.build = {
build,
setBuildInfo,
};
})(this);
export { build, setBuildInfo };

View file

@ -1,131 +1,130 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
"use strict";
((window) => {
const core = window.Deno.core;
const { Error } = window.__bootstrap.primordials;
const { BadResource, Interrupted } = core;
const core = globalThis.Deno.core;
const { BadResource, Interrupted } = core;
const primordials = globalThis.__bootstrap.primordials;
const { Error } = primordials;
class NotFound extends Error {
class NotFound extends Error {
constructor(msg) {
super(msg);
this.name = "NotFound";
}
}
}
class PermissionDenied extends Error {
class PermissionDenied extends Error {
constructor(msg) {
super(msg);
this.name = "PermissionDenied";
}
}
}
class ConnectionRefused extends Error {
class ConnectionRefused extends Error {
constructor(msg) {
super(msg);
this.name = "ConnectionRefused";
}
}
}
class ConnectionReset extends Error {
class ConnectionReset extends Error {
constructor(msg) {
super(msg);
this.name = "ConnectionReset";
}
}
}
class ConnectionAborted extends Error {
class ConnectionAborted extends Error {
constructor(msg) {
super(msg);
this.name = "ConnectionAborted";
}
}
}
class NotConnected extends Error {
class NotConnected extends Error {
constructor(msg) {
super(msg);
this.name = "NotConnected";
}
}
}
class AddrInUse extends Error {
class AddrInUse extends Error {
constructor(msg) {
super(msg);
this.name = "AddrInUse";
}
}
}
class AddrNotAvailable extends Error {
class AddrNotAvailable extends Error {
constructor(msg) {
super(msg);
this.name = "AddrNotAvailable";
}
}
}
class BrokenPipe extends Error {
class BrokenPipe extends Error {
constructor(msg) {
super(msg);
this.name = "BrokenPipe";
}
}
}
class AlreadyExists extends Error {
class AlreadyExists extends Error {
constructor(msg) {
super(msg);
this.name = "AlreadyExists";
}
}
}
class InvalidData extends Error {
class InvalidData extends Error {
constructor(msg) {
super(msg);
this.name = "InvalidData";
}
}
}
class TimedOut extends Error {
class TimedOut extends Error {
constructor(msg) {
super(msg);
this.name = "TimedOut";
}
}
}
class WriteZero extends Error {
class WriteZero extends Error {
constructor(msg) {
super(msg);
this.name = "WriteZero";
}
}
}
class UnexpectedEof extends Error {
class UnexpectedEof extends Error {
constructor(msg) {
super(msg);
this.name = "UnexpectedEof";
}
}
}
class Http extends Error {
class Http extends Error {
constructor(msg) {
super(msg);
this.name = "Http";
}
}
}
class Busy extends Error {
class Busy extends Error {
constructor(msg) {
super(msg);
this.name = "Busy";
}
}
}
class NotSupported extends Error {
class NotSupported extends Error {
constructor(msg) {
super(msg);
this.name = "NotSupported";
}
}
}
const errors = {
const errors = {
NotFound,
PermissionDenied,
ConnectionRefused,
@ -145,9 +144,6 @@
Http,
Busy,
NotSupported,
};
};
window.__bootstrap.errors = {
errors,
};
})(this);
export { errors };

View file

@ -1,29 +1,24 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
"use strict";
((window) => {
const { ObjectFreeze } = window.__bootstrap.primordials;
const primordials = globalThis.__bootstrap.primordials;
const { ObjectFreeze } = primordials;
const version = {
const version = {
deno: "",
v8: "",
typescript: "",
};
};
function setVersions(
function setVersions(
denoVersion,
v8Version,
tsVersion,
) {
) {
version.deno = denoVersion;
version.v8 = v8Version;
version.typescript = tsVersion;
ObjectFreeze(version);
}
}
window.__bootstrap.version = {
version,
setVersions,
};
})(this);
export { setVersions, version };

View file

@ -1,25 +0,0 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
"use strict";
((window) => {
const { TypeError, Symbol } = window.__bootstrap.primordials;
const illegalConstructorKey = Symbol("illegalConstructorKey");
function requiredArguments(
name,
length,
required,
) {
if (length < required) {
const errMsg = `${name} requires at least ${required} argument${
required === 1 ? "" : "s"
}, but only ${length} present`;
throw new TypeError(errMsg);
}
}
window.__bootstrap.webUtil = {
illegalConstructorKey,
requiredArguments,
};
})(this);

View file

@ -1,28 +1,28 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
"use strict";
((window) => {
const {
const internals = globalThis.__bootstrap.internals;
const primordials = globalThis.__bootstrap.primordials;
const {
decodeURIComponent,
ObjectPrototypeIsPrototypeOf,
Promise,
SafeArrayIterator,
StringPrototypeReplace,
TypeError,
} = window.__bootstrap.primordials;
const { build } = window.__bootstrap.build;
const { URLPrototype } = window.__bootstrap.url;
let logDebug = false;
let logSource = "JS";
} = primordials;
import { build } from "internal:runtime/js/01_build.js";
import { URLPrototype } from "internal:ext/url/00_url.js";
let logDebug = false;
let logSource = "JS";
function setLogDebug(debug, source) {
function setLogDebug(debug, source) {
logDebug = debug;
if (source) {
logSource = source;
}
}
}
function log(...args) {
function log(...args) {
if (logDebug) {
// if we destructure `console` off `globalThis` too early, we don't bind to
// the right console, therefore we don't log anything out.
@ -31,9 +31,9 @@
...new SafeArrayIterator(args),
);
}
}
}
function createResolvable() {
function createResolvable() {
let resolve;
let reject;
const promise = new Promise((res, rej) => {
@ -43,10 +43,10 @@
promise.resolve = resolve;
promise.reject = reject;
return promise;
}
}
// Keep in sync with `fromFileUrl()` in `std/path/win32.ts`.
function pathFromURLWin32(url) {
// Keep in sync with `fromFileUrl()` in `std/path/win32.ts`.
function pathFromURLWin32(url) {
let p = StringPrototypeReplace(
url.pathname,
/^\/*([A-Za-z]:)(\/|$)/,
@ -70,10 +70,10 @@
path = `\\\\${url.hostname}${path}`;
}
return path;
}
}
// Keep in sync with `fromFileUrl()` in `std/path/posix.ts`.
function pathFromURLPosix(url) {
// Keep in sync with `fromFileUrl()` in `std/path/posix.ts`.
function pathFromURLPosix(url) {
if (url.hostname !== "") {
throw new TypeError(`Host must be empty.`);
}
@ -81,9 +81,9 @@
return decodeURIComponent(
StringPrototypeReplace(url.pathname, /%(?![0-9A-Fa-f]{2})/g, "%25"),
);
}
}
function pathFromURL(pathOrUrl) {
function pathFromURL(pathOrUrl) {
if (ObjectPrototypeIsPrototypeOf(URLPrototype, pathOrUrl)) {
if (pathOrUrl.protocol != "file:") {
throw new TypeError("Must be a file URL.");
@ -94,57 +94,54 @@
: pathFromURLPosix(pathOrUrl);
}
return pathOrUrl;
}
}
window.__bootstrap.internals = {
...window.__bootstrap.internals ?? {},
pathFromURL,
};
// TODO(bartlomieju): remove
internals.pathFromURL = pathFromURL;
function writable(value) {
function writable(value) {
return {
value,
writable: true,
enumerable: true,
configurable: true,
};
}
}
function nonEnumerable(value) {
function nonEnumerable(value) {
return {
value,
writable: true,
enumerable: false,
configurable: true,
};
}
}
function readOnly(value) {
function readOnly(value) {
return {
value,
enumerable: true,
writable: false,
configurable: true,
};
}
}
function getterOnly(getter) {
function getterOnly(getter) {
return {
get: getter,
set() {},
enumerable: true,
configurable: true,
};
}
}
window.__bootstrap.util = {
log,
setLogDebug,
export {
createResolvable,
pathFromURL,
writable,
nonEnumerable,
readOnly,
getterOnly,
};
})(this);
log,
nonEnumerable,
pathFromURL,
readOnly,
setLogDebug,
writable,
};

View file

@ -1,13 +1,11 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
"use strict";
((window) => {
const { ops } = Deno.core;
const { Event } = window.__bootstrap.event;
const { EventTarget } = window.__bootstrap.eventTarget;
const { pathFromURL } = window.__bootstrap.util;
const { illegalConstructorKey } = window.__bootstrap.webUtil;
const {
const core = globalThis.Deno.core;
const ops = core.ops;
import { Event, EventTarget } from "internal:ext/web/02_event.js";
import { pathFromURL } from "internal:runtime/js/06_util.js";
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayIsArray,
ArrayPrototypeIncludes,
ArrayPrototypeMap,
@ -21,18 +19,21 @@
PromiseReject,
ReflectHas,
SafeArrayIterator,
Symbol,
SymbolFor,
TypeError,
} = window.__bootstrap.primordials;
} = primordials;
/**
const illegalConstructorKey = Symbol("illegalConstructorKey");
/**
* @typedef StatusCacheValue
* @property {PermissionState} state
* @property {PermissionStatus} status
*/
/** @type {ReadonlyArray<"read" | "write" | "net" | "env" | "sys" | "run" | "ffi" | "hrtime">} */
const permissionNames = [
/** @type {ReadonlyArray<"read" | "write" | "net" | "env" | "sys" | "run" | "ffi" | "hrtime">} */
const permissionNames = [
"read",
"write",
"net",
@ -41,33 +42,33 @@
"run",
"ffi",
"hrtime",
];
];
/**
/**
* @param {Deno.PermissionDescriptor} desc
* @returns {Deno.PermissionState}
*/
function opQuery(desc) {
function opQuery(desc) {
return ops.op_query_permission(desc);
}
}
/**
/**
* @param {Deno.PermissionDescriptor} desc
* @returns {Deno.PermissionState}
*/
function opRevoke(desc) {
function opRevoke(desc) {
return ops.op_revoke_permission(desc);
}
}
/**
/**
* @param {Deno.PermissionDescriptor} desc
* @returns {Deno.PermissionState}
*/
function opRequest(desc) {
function opRequest(desc) {
return ops.op_request_permission(desc);
}
}
class PermissionStatus extends EventTarget {
class PermissionStatus extends EventTarget {
/** @type {{ state: Deno.PermissionState }} */
#state;
@ -109,17 +110,17 @@
inspect({ state: this.state, onchange: this.onchange })
}`;
}
}
}
/** @type {Map<string, StatusCacheValue>} */
const statusCache = new Map();
/** @type {Map<string, StatusCacheValue>} */
const statusCache = new Map();
/**
/**
* @param {Deno.PermissionDescriptor} desc
* @param {Deno.PermissionState} state
* @returns {PermissionStatus}
*/
function cache(desc, state) {
function cache(desc, state) {
let { name: key } = desc;
if (
(desc.name === "read" || desc.name === "write" || desc.name === "ffi") &&
@ -150,22 +151,22 @@
status.status = new PermissionStatus(status, illegalConstructorKey);
MapPrototypeSet(statusCache, key, status);
return status.status;
}
}
/**
/**
* @param {unknown} desc
* @returns {desc is Deno.PermissionDescriptor}
*/
function isValidDescriptor(desc) {
function isValidDescriptor(desc) {
return typeof desc === "object" && desc !== null &&
ArrayPrototypeIncludes(permissionNames, desc.name);
}
}
/**
/**
* @param {Deno.PermissionDescriptor} desc
* @returns {desc is Deno.PermissionDescriptor}
*/
function formDescriptor(desc) {
function formDescriptor(desc) {
if (
desc.name === "read" || desc.name === "write" || desc.name === "ffi"
) {
@ -173,9 +174,9 @@
} else if (desc.name === "run") {
desc.command = pathFromURL(desc.command);
}
}
}
class Permissions {
class Permissions {
constructor(key = null) {
if (key != illegalConstructorKey) {
throw new TypeError("Illegal constructor.");
@ -244,12 +245,12 @@
const state = opRequest(desc);
return cache(desc, state);
}
}
}
const permissions = new Permissions(illegalConstructorKey);
const permissions = new Permissions(illegalConstructorKey);
/** Converts all file URLs in FS allowlists to paths. */
function serializePermissions(permissions) {
/** Converts all file URLs in FS allowlists to paths. */
function serializePermissions(permissions) {
if (typeof permissions == "object" && permissions != null) {
const serializedPermissions = {};
for (
@ -276,12 +277,6 @@
return serializedPermissions;
}
return permissions;
}
}
window.__bootstrap.permissions = {
serializePermissions,
permissions,
Permissions,
PermissionStatus,
};
})(this);
export { Permissions, permissions, PermissionStatus, serializePermissions };

View file

@ -1,39 +1,41 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
"use strict";
((window) => {
const core = window.Deno.core;
const ops = core.ops;
const {
const core = globalThis.Deno.core;
const ops = core.ops;
const primordials = globalThis.__bootstrap.primordials;
const {
Error,
ObjectPrototypeIsPrototypeOf,
StringPrototypeStartsWith,
String,
SymbolIterator,
SymbolToStringTag,
} = window.__bootstrap.primordials;
const webidl = window.__bootstrap.webidl;
const { URL } = window.__bootstrap.url;
const { getLocationHref } = window.__bootstrap.location;
const { serializePermissions } = window.__bootstrap.permissions;
const { log } = window.__bootstrap.util;
const { ErrorEvent, MessageEvent, defineEventHandler } =
window.__bootstrap.event;
const { EventTarget } = window.__bootstrap.eventTarget;
const {
} = primordials;
import * as webidl from "internal:ext/webidl/00_webidl.js";
import { URL } from "internal:ext/url/00_url.js";
import { getLocationHref } from "internal:ext/web/12_location.js";
import { serializePermissions } from "internal:runtime/js/10_permissions.js";
import { log } from "internal:runtime/js/06_util.js";
import {
defineEventHandler,
ErrorEvent,
EventTarget,
MessageEvent,
} from "internal:ext/web/02_event.js";
import {
deserializeJsMessageData,
serializeJsMessageData,
MessagePortPrototype,
} = window.__bootstrap.messagePort;
serializeJsMessageData,
} from "internal:ext/web/13_message_port.js";
function createWorker(
function createWorker(
specifier,
hasSourceCode,
sourceCode,
permissions,
name,
workerType,
) {
) {
return ops.op_create_worker({
hasSourceCode,
name,
@ -42,25 +44,25 @@
specifier,
workerType,
});
}
}
function hostTerminateWorker(id) {
function hostTerminateWorker(id) {
ops.op_host_terminate_worker(id);
}
}
function hostPostMessage(id, data) {
function hostPostMessage(id, data) {
ops.op_host_post_message(id, data);
}
}
function hostRecvCtrl(id) {
function hostRecvCtrl(id) {
return core.opAsync("op_host_recv_ctrl", id);
}
}
function hostRecvMessage(id) {
function hostRecvMessage(id) {
return core.opAsync("op_host_recv_message", id);
}
}
class Worker extends EventTarget {
class Worker extends EventTarget {
#id = 0;
#name = "";
@ -131,7 +133,7 @@
// TODO(nayeemrmn): It's not correct to use `e.fileName` to detect user
// errors. It won't be there for non-awaited async ops for example.
if (e.fileName && !event.defaultPrevented) {
window.dispatchEvent(event);
globalThis.dispatchEvent(event);
}
return event.defaultPrevented;
@ -237,18 +239,15 @@
}
[SymbolToStringTag] = "Worker";
}
}
defineEventHandler(Worker.prototype, "error");
defineEventHandler(Worker.prototype, "message");
defineEventHandler(Worker.prototype, "messageerror");
defineEventHandler(Worker.prototype, "error");
defineEventHandler(Worker.prototype, "message");
defineEventHandler(Worker.prototype, "messageerror");
webidl.converters["WorkerType"] = webidl.createEnumConverter("WorkerType", [
webidl.converters["WorkerType"] = webidl.createEnumConverter("WorkerType", [
"classic",
"module",
]);
]);
window.__bootstrap.worker = {
Worker,
};
})(this);
export { Worker };

Some files were not shown because too many files have changed in this diff Show more