From ac244dd88b00f30471ab01f662325432f2462d0e Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Fri, 12 Mar 2021 14:24:52 +0100 Subject: [PATCH] chore: split web op crate This commit starts splitting out the deno_web op crate into multiple smaller crates. This commit splits out WebIDL and URL API, but in the future I want to split out each spec into its own crate. That means we will have (in rough order of loading): `webidl`, `dom`, `streams`, `console`, `encoding`, `url`, `file`, `fetch`, `websocket`, and `webgpu` crates. --- Cargo.lock | 19 +- Cargo.toml | 6 +- cli/build.rs | 6 + cli/dts/lib.deno.shared_globals.d.ts | 1 + cli/main.rs | 3 +- cli/tsc.rs | 1 + op_crates/crypto/Cargo.toml | 2 +- op_crates/crypto/README.md | 6 +- op_crates/fetch/Cargo.toml | 2 +- op_crates/fetch/README.md | 6 +- op_crates/{web/11_url.js => url/00_url.js} | 30 +-- op_crates/url/Cargo.toml | 19 ++ op_crates/url/README.md | 5 + op_crates/url/internal.d.ts | 13 + op_crates/url/lib.deno_url.d.ts | 175 +++++++++++++ op_crates/url/lib.rs | 155 +++++++++++ op_crates/web/01_dom_exception.js | 1 + op_crates/web/Cargo.toml | 1 - op_crates/web/internal.d.ts | 287 -------------------- op_crates/web/lib.deno_web.d.ts | 169 ------------ op_crates/web/lib.rs | 144 ---------- op_crates/webgpu/Cargo.toml | 2 +- op_crates/{web => webidl}/00_webidl.js | 0 op_crates/webidl/Cargo.toml | 17 ++ op_crates/webidl/README.md | 6 + op_crates/webidl/internal.d.ts | 291 +++++++++++++++++++++ op_crates/webidl/lib.rs | 14 + runtime/Cargo.toml | 4 + runtime/build.rs | 2 + runtime/lib.rs | 2 + runtime/ops/mod.rs | 1 + runtime/ops/url.rs | 18 ++ runtime/web_worker.rs | 12 +- runtime/worker.rs | 12 +- 34 files changed, 785 insertions(+), 647 deletions(-) rename op_crates/{web/11_url.js => url/00_url.js} (90%) create mode 100644 op_crates/url/Cargo.toml create mode 100644 op_crates/url/README.md create mode 100644 op_crates/url/internal.d.ts create mode 100644 op_crates/url/lib.deno_url.d.ts create mode 100644 op_crates/url/lib.rs rename op_crates/{web => webidl}/00_webidl.js (100%) create mode 100644 op_crates/webidl/Cargo.toml create mode 100644 op_crates/webidl/README.md create mode 100644 op_crates/webidl/internal.d.ts create mode 100644 op_crates/webidl/lib.rs create mode 100644 runtime/ops/url.rs diff --git a/Cargo.lock b/Cargo.lock index 928464fcf18b51..c199cf560f504f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -635,8 +635,10 @@ dependencies = [ "deno_core", "deno_crypto", "deno_fetch", + "deno_url", "deno_web", "deno_webgpu", + "deno_webidl", "deno_websocket", "dlopen", "encoding_rs", @@ -668,13 +670,21 @@ dependencies = [ "winres", ] +[[package]] +name = "deno_url" +version = "0.1.0" +dependencies = [ + "deno_core", + "idna", + "serde", +] + [[package]] name = "deno_web" version = "0.30.3" dependencies = [ "deno_core", "futures", - "serde", ] [[package]] @@ -688,6 +698,13 @@ dependencies = [ "wgpu-types", ] +[[package]] +name = "deno_webidl" +version = "0.1.0" +dependencies = [ + "deno_core", +] + [[package]] name = "deno_websocket" version = "0.5.3" diff --git a/Cargo.toml b/Cargo.toml index 8a5f1021c46476..e89ca19b7bee56 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,9 +7,13 @@ members = [ "runtime", "test_plugin", "test_util", + "op_crates/crypto", "op_crates/fetch", + "op_crates/url", "op_crates/web", - "op_crates/crypto" + "op_crates/webgpu", + "op_crates/webidl", + "op_crates/websocket", ] exclude = [ "std/hash/_wasm" diff --git a/cli/build.rs b/cli/build.rs index 236097cbf88c99..3f97a71b7465b9 100644 --- a/cli/build.rs +++ b/cli/build.rs @@ -10,6 +10,7 @@ use deno_core::JsRuntime; use deno_core::RuntimeOptions; use deno_runtime::deno_crypto; use deno_runtime::deno_fetch; +use deno_runtime::deno_url; use deno_runtime::deno_web; use deno_runtime::deno_webgpu; use deno_runtime::deno_websocket; @@ -61,6 +62,7 @@ fn create_compiler_snapshot( ) { // libs that are being provided by op crates. let mut op_crate_libs = HashMap::new(); + op_crate_libs.insert("deno.url", deno_url::get_declaration()); op_crate_libs.insert("deno.web", deno_web::get_declaration()); op_crate_libs.insert("deno.fetch", deno_fetch::get_declaration()); op_crate_libs.insert("deno.webgpu", deno_webgpu::get_declaration()); @@ -254,6 +256,10 @@ fn main() { println!("cargo:rustc-env=TS_VERSION={}", ts_version()); println!("cargo:rustc-env=GIT_COMMIT_HASH={}", git_commit_hash()); + println!( + "cargo:rustc-env=DENO_URL_LIB_PATH={}", + deno_url::get_declaration().display() + ); println!( "cargo:rustc-env=DENO_WEB_LIB_PATH={}", deno_web::get_declaration().display() diff --git a/cli/dts/lib.deno.shared_globals.d.ts b/cli/dts/lib.deno.shared_globals.d.ts index 4332b757b1a02b..206cafdc3002c9 100644 --- a/cli/dts/lib.deno.shared_globals.d.ts +++ b/cli/dts/lib.deno.shared_globals.d.ts @@ -5,6 +5,7 @@ /// /// +/// /// /// /// diff --git a/cli/main.rs b/cli/main.rs index 93639d34f7266e..8d685c6dbe8224 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -278,8 +278,9 @@ fn print_cache_info( pub fn get_types(unstable: bool) -> String { let mut types = format!( - "{}\n{}\n{}\n{}\n{}\n{}\n{}", + "{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}", crate::tsc::DENO_NS_LIB, + crate::tsc::DENO_URL_LIB, crate::tsc::DENO_WEB_LIB, crate::tsc::DENO_FETCH_LIB, crate::tsc::DENO_WEBGPU_LIB, diff --git a/cli/tsc.rs b/cli/tsc.rs index 8d28b959d37d41..6bf8546509f737 100644 --- a/cli/tsc.rs +++ b/cli/tsc.rs @@ -29,6 +29,7 @@ use std::sync::Mutex; // Declaration files pub static DENO_NS_LIB: &str = include_str!("dts/lib.deno.ns.d.ts"); +pub static DENO_URL_LIB: &str = include_str!(env!("DENO_URL_LIB_PATH")); pub static DENO_WEB_LIB: &str = include_str!(env!("DENO_WEB_LIB_PATH")); pub static DENO_FETCH_LIB: &str = include_str!(env!("DENO_FETCH_LIB_PATH")); pub static DENO_WEBGPU_LIB: &str = include_str!(env!("DENO_WEBGPU_LIB_PATH")); diff --git a/op_crates/crypto/Cargo.toml b/op_crates/crypto/Cargo.toml index 3d5af740e45699..8b0d2d3fa451c5 100644 --- a/op_crates/crypto/Cargo.toml +++ b/op_crates/crypto/Cargo.toml @@ -4,7 +4,7 @@ name = "deno_crypto" version = "0.14.1" edition = "2018" -description = "Collection of WebCrypto APIs" +description = "Web Cryptography API implementation for Deno" authors = ["the Deno authors"] license = "MIT" readme = "README.md" diff --git a/op_crates/crypto/README.md b/op_crates/crypto/README.md index 0e1c248e64ce46..be07244584e75b 100644 --- a/op_crates/crypto/README.md +++ b/op_crates/crypto/README.md @@ -1,3 +1,5 @@ -# deno crypto +# deno_crypto -Op crate that implements crypto functions. +This crate implements the Web Cryptography API. + +Spec: https://www.w3.org/TR/WebCryptoAPI/ diff --git a/op_crates/fetch/Cargo.toml b/op_crates/fetch/Cargo.toml index 9491b87a36b71f..57a56d7409c0f9 100644 --- a/op_crates/fetch/Cargo.toml +++ b/op_crates/fetch/Cargo.toml @@ -4,7 +4,7 @@ name = "deno_fetch" version = "0.22.3" edition = "2018" -description = "provides fetch Web API to deno_core" +description = "Fetch API implementation for Deno" authors = ["the Deno authors"] license = "MIT" readme = "README.md" diff --git a/op_crates/fetch/README.md b/op_crates/fetch/README.md index 1a6dcab1745c09..2c946197e053bc 100644 --- a/op_crates/fetch/README.md +++ b/op_crates/fetch/README.md @@ -1 +1,5 @@ -This crate provides the web standard fetch API to `deno_core`. +# deno_fetch + +This crate implements the Fetch API. + +Spec: https://fetch.spec.whatwg.org/ diff --git a/op_crates/web/11_url.js b/op_crates/url/00_url.js similarity index 90% rename from op_crates/web/11_url.js rename to op_crates/url/00_url.js index d8f5bd5f7a9e00..9dd2b78007c3b5 100644 --- a/op_crates/web/11_url.js +++ b/op_crates/url/00_url.js @@ -28,7 +28,7 @@ init = init.slice(1); } - this.#params = core.jsonOpSync("op_parse_url_search_params", init); + this.#params = core.jsonOpSync("op_url_parse_search_params", init); } else if ( Array.isArray(init) || typeof init?.[Symbol.iterator] == "function" @@ -64,7 +64,7 @@ return; } const parseArgs = { href: url.href, setSearch: this.toString() }; - parts.set(url, core.jsonOpSync("op_parse_url", parseArgs)); + parts.set(url, core.jsonOpSync("op_url_parse", parseArgs)); }; append(name, value) { @@ -189,7 +189,7 @@ } toString() { - return core.jsonOpSync("op_stringify_url_search_params", this.#params); + return core.jsonOpSync("op_url_stringify_search_params", this.#params); } } @@ -206,7 +206,7 @@ } else { base = base !== undefined ? String(base) : base; const parseArgs = { href: String(url), baseHref: base }; - parts.set(this, core.jsonOpSync("op_parse_url", parseArgs)); + parts.set(this, core.jsonOpSync("op_url_parse", parseArgs)); } } @@ -231,7 +231,7 @@ if (this.#searchParams != null) { const params = paramLists.get(this.#searchParams); const newParams = core.jsonOpSync( - "op_parse_url_search_params", + "op_url_parse_search_params", this.search.slice(1), ); params.splice(0, params.length, ...newParams); @@ -245,7 +245,7 @@ set hash(value) { try { const parseArgs = { href: this.href, setHash: String(value) }; - parts.set(this, core.jsonOpSync("op_parse_url", parseArgs)); + parts.set(this, core.jsonOpSync("op_url_parse", parseArgs)); } catch { /* pass */ } @@ -258,7 +258,7 @@ set host(value) { try { const parseArgs = { href: this.href, setHost: String(value) }; - parts.set(this, core.jsonOpSync("op_parse_url", parseArgs)); + parts.set(this, core.jsonOpSync("op_url_parse", parseArgs)); } catch { /* pass */ } @@ -271,7 +271,7 @@ set hostname(value) { try { const parseArgs = { href: this.href, setHostname: String(value) }; - parts.set(this, core.jsonOpSync("op_parse_url", parseArgs)); + parts.set(this, core.jsonOpSync("op_url_parse", parseArgs)); } catch { /* pass */ } @@ -284,7 +284,7 @@ set href(value) { try { const parseArgs = { href: String(value) }; - parts.set(this, core.jsonOpSync("op_parse_url", parseArgs)); + parts.set(this, core.jsonOpSync("op_url_parse", parseArgs)); } catch { throw new TypeError("Invalid URL"); } @@ -302,7 +302,7 @@ set password(value) { try { const parseArgs = { href: this.href, setPassword: String(value) }; - parts.set(this, core.jsonOpSync("op_parse_url", parseArgs)); + parts.set(this, core.jsonOpSync("op_url_parse", parseArgs)); } catch { /* pass */ } @@ -315,7 +315,7 @@ set pathname(value) { try { const parseArgs = { href: this.href, setPathname: String(value) }; - parts.set(this, core.jsonOpSync("op_parse_url", parseArgs)); + parts.set(this, core.jsonOpSync("op_url_parse", parseArgs)); } catch { /* pass */ } @@ -328,7 +328,7 @@ set port(value) { try { const parseArgs = { href: this.href, setPort: String(value) }; - parts.set(this, core.jsonOpSync("op_parse_url", parseArgs)); + parts.set(this, core.jsonOpSync("op_url_parse", parseArgs)); } catch { /* pass */ } @@ -341,7 +341,7 @@ set protocol(value) { try { const parseArgs = { href: this.href, setProtocol: String(value) }; - parts.set(this, core.jsonOpSync("op_parse_url", parseArgs)); + parts.set(this, core.jsonOpSync("op_url_parse", parseArgs)); } catch { /* pass */ } @@ -354,7 +354,7 @@ set search(value) { try { const parseArgs = { href: this.href, setSearch: String(value) }; - parts.set(this, core.jsonOpSync("op_parse_url", parseArgs)); + parts.set(this, core.jsonOpSync("op_url_parse", parseArgs)); this.#updateSearchParams(); } catch { /* pass */ @@ -368,7 +368,7 @@ set username(value) { try { const parseArgs = { href: this.href, setUsername: String(value) }; - parts.set(this, core.jsonOpSync("op_parse_url", parseArgs)); + parts.set(this, core.jsonOpSync("op_url_parse", parseArgs)); } catch { /* pass */ } diff --git a/op_crates/url/Cargo.toml b/op_crates/url/Cargo.toml new file mode 100644 index 00000000000000..a07bfc7d3aae1d --- /dev/null +++ b/op_crates/url/Cargo.toml @@ -0,0 +1,19 @@ +# Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +[package] +name = "deno_url" +version = "0.1.0" +edition = "2018" +description = "URL API implementation for Deno" +authors = ["the Deno authors"] +license = "MIT" +readme = "README.md" +repository = "https://github.com/denoland/deno" + +[lib] +path = "lib.rs" + +[dependencies] +deno_core = { version = "0.80.2", path = "../../core" } +idna = "0.2.1" +serde = { version = "1.0.123", features = ["derive"] } diff --git a/op_crates/url/README.md b/op_crates/url/README.md new file mode 100644 index 00000000000000..991dd8b20078ad --- /dev/null +++ b/op_crates/url/README.md @@ -0,0 +1,5 @@ +# deno_url + +This crate implements the URL API for Deno. + +Spec: https://url.spec.whatwg.org/ diff --git a/op_crates/url/internal.d.ts b/op_crates/url/internal.d.ts new file mode 100644 index 00000000000000..f852928d354e9b --- /dev/null +++ b/op_crates/url/internal.d.ts @@ -0,0 +1,13 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. + +/// +/// + +declare namespace globalThis { + declare namespace __bootstrap { + declare var url: { + URL: typeof URL; + URLSearchParams: typeof URLSearchParams; + }; + } +} diff --git a/op_crates/url/lib.deno_url.d.ts b/op_crates/url/lib.deno_url.d.ts new file mode 100644 index 00000000000000..2a27fe6933692e --- /dev/null +++ b/op_crates/url/lib.deno_url.d.ts @@ -0,0 +1,175 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. + +// deno-lint-ignore-file no-explicit-any + +/// +/// + +declare class URLSearchParams { + constructor( + init?: string[][] | Record | string | URLSearchParams, + ); + static toString(): string; + + /** Appends a specified key/value pair as a new search parameter. + * + * ```ts + * let searchParams = new URLSearchParams(); + * searchParams.append('name', 'first'); + * searchParams.append('name', 'second'); + * ``` + */ + append(name: string, value: string): void; + + /** Deletes the given search parameter and its associated value, + * from the list of all search parameters. + * + * ```ts + * let searchParams = new URLSearchParams([['name', 'value']]); + * searchParams.delete('name'); + * ``` + */ + delete(name: string): void; + + /** Returns all the values associated with a given search parameter + * as an array. + * + * ```ts + * searchParams.getAll('name'); + * ``` + */ + getAll(name: string): string[]; + + /** Returns the first value associated to the given search parameter. + * + * ```ts + * searchParams.get('name'); + * ``` + */ + get(name: string): string | null; + + /** Returns a Boolean that indicates whether a parameter with the + * specified name exists. + * + * ```ts + * searchParams.has('name'); + * ``` + */ + has(name: string): boolean; + + /** Sets the value associated with a given search parameter to the + * given value. If there were several matching values, this method + * deletes the others. If the search parameter doesn't exist, this + * method creates it. + * + * ```ts + * searchParams.set('name', 'value'); + * ``` + */ + set(name: string, value: string): void; + + /** Sort all key/value pairs contained in this object in place and + * return undefined. The sort order is according to Unicode code + * points of the keys. + * + * ```ts + * searchParams.sort(); + * ``` + */ + sort(): void; + + /** Calls a function for each element contained in this object in + * place and return undefined. Optionally accepts an object to use + * as this when executing callback as second argument. + * + * ```ts + * const params = new URLSearchParams([["a", "b"], ["c", "d"]]); + * params.forEach((value, key, parent) => { + * console.log(value, key, parent); + * }); + * ``` + * + */ + forEach( + callbackfn: (value: string, key: string, parent: this) => void, + thisArg?: any, + ): void; + + /** Returns an iterator allowing to go through all keys contained + * in this object. + * + * ```ts + * const params = new URLSearchParams([["a", "b"], ["c", "d"]]); + * for (const key of params.keys()) { + * console.log(key); + * } + * ``` + */ + keys(): IterableIterator; + + /** Returns an iterator allowing to go through all values contained + * in this object. + * + * ```ts + * const params = new URLSearchParams([["a", "b"], ["c", "d"]]); + * for (const value of params.values()) { + * console.log(value); + * } + * ``` + */ + values(): IterableIterator; + + /** Returns an iterator allowing to go through all key/value + * pairs contained in this object. + * + * ```ts + * const params = new URLSearchParams([["a", "b"], ["c", "d"]]); + * for (const [key, value] of params.entries()) { + * console.log(key, value); + * } + * ``` + */ + entries(): IterableIterator<[string, string]>; + + /** Returns an iterator allowing to go through all key/value + * pairs contained in this object. + * + * ```ts + * const params = new URLSearchParams([["a", "b"], ["c", "d"]]); + * for (const [key, value] of params) { + * console.log(key, value); + * } + * ``` + */ + [Symbol.iterator](): IterableIterator<[string, string]>; + + /** Returns a query string suitable for use in a URL. + * + * ```ts + * searchParams.toString(); + * ``` + */ + toString(): string; +} + +/** The URL interface represents an object providing static methods used for creating object URLs. */ +declare class URL { + constructor(url: string, base?: string | URL); + createObjectURL(object: any): string; + revokeObjectURL(url: string): void; + + hash: string; + host: string; + hostname: string; + href: string; + toString(): string; + readonly origin: string; + password: string; + pathname: string; + port: string; + protocol: string; + search: string; + readonly searchParams: URLSearchParams; + username: string; + toJSON(): string; +} diff --git a/op_crates/url/lib.rs b/op_crates/url/lib.rs new file mode 100644 index 00000000000000..a655d8c34be042 --- /dev/null +++ b/op_crates/url/lib.rs @@ -0,0 +1,155 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. + +use deno_core::error::generic_error; +use deno_core::error::type_error; +use deno_core::error::uri_error; +use deno_core::error::AnyError; +use deno_core::serde_json; +use deno_core::serde_json::json; +use deno_core::serde_json::Value; +use deno_core::url::form_urlencoded; +use deno_core::url::quirks; +use deno_core::url::Url; +use deno_core::JsRuntime; +use deno_core::ZeroCopyBuf; +use serde::Deserialize; +use serde::Serialize; +use std::panic::catch_unwind; +use std::path::PathBuf; + +/// Parse `UrlParseArgs::href` with an optional `UrlParseArgs::base_href`, or an +/// optional part to "set" after parsing. Return `UrlParts`. +pub fn op_url_parse( + _state: &mut deno_core::OpState, + args: Value, + _zero_copy: &mut [ZeroCopyBuf], +) -> Result { + #[derive(Deserialize)] + #[serde(rename_all = "camelCase")] + struct UrlParseArgs { + href: String, + base_href: Option, + // If one of the following are present, this is a setter call. Apply the + // proper `Url::set_*()` method after (re)parsing `href`. + set_hash: Option, + set_host: Option, + set_hostname: Option, + set_password: Option, + set_pathname: Option, + set_port: Option, + set_protocol: Option, + set_search: Option, + set_username: Option, + } + let args: UrlParseArgs = serde_json::from_value(args)?; + let base_url = args + .base_href + .as_ref() + .map(|b| Url::parse(b).map_err(|_| type_error("Invalid base URL"))) + .transpose()?; + let mut url = Url::options() + .base_url(base_url.as_ref()) + .parse(&args.href) + .map_err(|_| type_error("Invalid URL"))?; + + if let Some(hash) = args.set_hash.as_ref() { + quirks::set_hash(&mut url, hash); + } else if let Some(host) = args.set_host.as_ref() { + quirks::set_host(&mut url, host).map_err(|_| uri_error("Invalid host"))?; + } else if let Some(hostname) = args.set_hostname.as_ref() { + quirks::set_hostname(&mut url, hostname) + .map_err(|_| uri_error("Invalid hostname"))?; + } else if let Some(password) = args.set_password.as_ref() { + quirks::set_password(&mut url, password) + .map_err(|_| uri_error("Invalid password"))?; + } else if let Some(pathname) = args.set_pathname.as_ref() { + quirks::set_pathname(&mut url, pathname); + } else if let Some(port) = args.set_port.as_ref() { + quirks::set_port(&mut url, port).map_err(|_| uri_error("Invalid port"))?; + } else if let Some(protocol) = args.set_protocol.as_ref() { + quirks::set_protocol(&mut url, protocol) + .map_err(|_| uri_error("Invalid protocol"))?; + } else if let Some(search) = args.set_search.as_ref() { + quirks::set_search(&mut url, search); + } else if let Some(username) = args.set_username.as_ref() { + quirks::set_username(&mut url, username) + .map_err(|_| uri_error("Invalid username"))?; + } + + #[derive(Serialize)] + struct UrlParts<'a> { + href: &'a str, + hash: &'a str, + host: &'a str, + hostname: &'a str, + origin: &'a str, + password: &'a str, + pathname: &'a str, + port: &'a str, + protocol: &'a str, + search: &'a str, + username: &'a str, + } + // TODO(nayeemrmn): Panic that occurs in rust-url for the `non-spec:` + // url-constructor wpt tests: https://github.com/servo/rust-url/issues/670. + let username = catch_unwind(|| quirks::username(&url)).map_err(|_| { + generic_error(format!( + "Internal error while parsing \"{}\"{}, \ + see https://github.com/servo/rust-url/issues/670", + args.href, + args + .base_href + .map(|b| format!(" against \"{}\"", b)) + .unwrap_or_default() + )) + })?; + Ok(json!(UrlParts { + href: quirks::href(&url), + hash: quirks::hash(&url), + host: quirks::host(&url), + hostname: quirks::hostname(&url), + origin: &quirks::origin(&url), + password: quirks::password(&url), + pathname: quirks::pathname(&url), + port: quirks::port(&url), + protocol: quirks::protocol(&url), + search: quirks::search(&url), + username, + })) +} + +pub fn op_url_parse_search_params( + _state: &mut deno_core::OpState, + args: Value, + _zero_copy: &mut [ZeroCopyBuf], +) -> Result { + let search: String = serde_json::from_value(args)?; + let search_params: Vec<_> = form_urlencoded::parse(search.as_bytes()) + .into_iter() + .collect(); + Ok(json!(search_params)) +} + +pub fn op_url_stringify_search_params( + _state: &mut deno_core::OpState, + args: Value, + _zero_copy: &mut [ZeroCopyBuf], +) -> Result { + let search_params: Vec<(String, String)> = serde_json::from_value(args)?; + let search = form_urlencoded::Serializer::new(String::new()) + .extend_pairs(search_params) + .finish(); + Ok(json!(search)) +} + +/// Load and execute the javascript code. +pub fn init(isolate: &mut JsRuntime) { + let files = vec![("deno:op_crates/url/00_url.js", include_str!("00_url.js"))]; + for (url, source_code) in files { + isolate.execute(url, source_code).unwrap(); + } +} + +pub fn get_declaration() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_url.d.ts") +} diff --git a/op_crates/web/01_dom_exception.js b/op_crates/web/01_dom_exception.js index 14f4ca8e9346d0..f5bd3289bf43c6 100644 --- a/op_crates/web/01_dom_exception.js +++ b/op_crates/web/01_dom_exception.js @@ -2,6 +2,7 @@ // @ts-check /// +/// /// /// diff --git a/op_crates/web/Cargo.toml b/op_crates/web/Cargo.toml index d1d37c216d9d89..e8620788149de1 100644 --- a/op_crates/web/Cargo.toml +++ b/op_crates/web/Cargo.toml @@ -15,7 +15,6 @@ path = "lib.rs" [dependencies] deno_core = { version = "0.80.2", path = "../../core" } -serde = { version = "1.0.123", features = ["derive"] } [dev-dependencies] futures = "0.3.12" diff --git a/op_crates/web/internal.d.ts b/op_crates/web/internal.d.ts index efafee26cd96dd..458f4a173c5a33 100644 --- a/op_crates/web/internal.d.ts +++ b/op_crates/web/internal.d.ts @@ -1,301 +1,14 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -// deno-lint-ignore-file no-explicit-any ban-types /// /// declare namespace globalThis { declare namespace __bootstrap { - declare namespace webidl { - declare interface ConverterOpts { - /** - * The prefix for error messages created by this converter. - * Examples: - * - `Failed to construct 'Event'` - * - `Failed to execute 'removeEventListener' on 'EventTarget'` - */ - prefix: string; - } - declare interface ValueConverterOpts extends ConverterOpts { - /** - * The context of this value error messages created by this converter. - * Examples: - * - `Argument 1` - * - `Argument 3` - */ - context: string; - } - declare function makeException( - ErrorType: any, - message: string, - opts: ValueConverterOpts, - ): any; - declare interface IntConverterOpts extends ValueConverterOpts { - /** - * Wether to throw if the number is outside of the acceptable values for - * this type. - */ - enforceRange?: boolean; - /** - * Wether to clamp this number to the acceptable values for this type. - */ - clamp?: boolean; - } - declare interface StringConverterOpts extends ValueConverterOpts { - /** - * Wether to treat `null` value as an empty string. - */ - treatNullAsEmptyString?: boolean; - } - declare interface BufferConverterOpts extends ValueConverterOpts { - /** - * Wether to allow `SharedArrayBuffer` (not just `ArrayBuffer`). - */ - allowShared?: boolean; - } - declare const converters: { - any(v: any): any; - /** - * Convert a value into a `boolean` (bool). - */ - boolean(v: any, opts?: IntConverterOpts): boolean; - /** - * Convert a value into a `byte` (int8). - */ - byte(v: any, opts?: IntConverterOpts): number; - /** - * Convert a value into a `octet` (uint8). - */ - octet(v: any, opts?: IntConverterOpts): number; - /** - * Convert a value into a `short` (int16). - */ - short(v: any, opts?: IntConverterOpts): number; - /** - * Convert a value into a `unsigned short` (uint16). - */ - ["unsigned short"](v: any, opts?: IntConverterOpts): number; - /** - * Convert a value into a `long` (int32). - */ - long(v: any, opts?: IntConverterOpts): number; - /** - * Convert a value into a `unsigned long` (uint32). - */ - ["unsigned long"](v: any, opts?: IntConverterOpts): number; - /** - * Convert a value into a `long long` (int64). - * **Note this is truncated to a JS number (53 bit precision).** - */ - ["long long"](v: any, opts?: IntConverterOpts): number; - /** - * Convert a value into a `unsigned long long` (uint64). - * **Note this is truncated to a JS number (53 bit precision).** - */ - ["unsigned long long"](v: any, opts?: IntConverterOpts): number; - /** - * Convert a value into a `float` (f32). - */ - float(v: any, opts?: ValueConverterOpts): number; - /** - * Convert a value into a `unrestricted float` (f32, infinity, or NaN). - */ - ["unrestricted float"](v: any, opts?: ValueConverterOpts): number; - /** - * Convert a value into a `double` (f64). - */ - double(v: any, opts?: ValueConverterOpts): number; - /** - * Convert a value into a `unrestricted double` (f64, infinity, or NaN). - */ - ["unrestricted double"](v: any, opts?: ValueConverterOpts): number; - /** - * Convert a value into a `DOMString` (string). - */ - DOMString(v: any, opts?: StringConverterOpts): string; - /** - * Convert a value into a `ByteString` (string with only u8 codepoints). - */ - ByteString(v: any, opts?: StringConverterOpts): string; - /** - * Convert a value into a `USVString` (string with only valid non - * surrogate Unicode code points). - */ - USVString(v: any, opts?: StringConverterOpts): string; - /** - * Convert a value into an `object` (object). - */ - object(v: any, opts?: ValueConverterOpts): object; - /** - * Convert a value into an `ArrayBuffer` (ArrayBuffer). - */ - ArrayBuffer(v: any, opts?: BufferConverterOpts): ArrayBuffer; - /** - * Convert a value into a `DataView` (ArrayBuffer). - */ - DataView(v: any, opts?: BufferConverterOpts): DataView; - /** - * Convert a value into a `Int8Array` (Int8Array). - */ - Int8Array(v: any, opts?: BufferConverterOpts): Int8Array; - /** - * Convert a value into a `Int16Array` (Int16Array). - */ - Int16Array(v: any, opts?: BufferConverterOpts): Int16Array; - /** - * Convert a value into a `Int32Array` (Int32Array). - */ - Int32Array(v: any, opts?: BufferConverterOpts): Int32Array; - /** - * Convert a value into a `Uint8Array` (Uint8Array). - */ - Uint8Array(v: any, opts?: BufferConverterOpts): Uint8Array; - /** - * Convert a value into a `Uint16Array` (Uint16Array). - */ - Uint16Array(v: any, opts?: BufferConverterOpts): Uint16Array; - /** - * Convert a value into a `Uint32Array` (Uint32Array). - */ - Uint32Array(v: any, opts?: BufferConverterOpts): Uint32Array; - /** - * Convert a value into a `Uint8ClampedArray` (Uint8ClampedArray). - */ - Uint8ClampedArray( - v: any, - opts?: BufferConverterOpts, - ): Uint8ClampedArray; - /** - * Convert a value into a `Float32Array` (Float32Array). - */ - Float32Array(v: any, opts?: BufferConverterOpts): Float32Array; - /** - * Convert a value into a `Float64Array` (Float64Array). - */ - Float64Array(v: any, opts?: BufferConverterOpts): Float64Array; - /** - * Convert a value into an `ArrayBufferView` (ArrayBufferView). - */ - ArrayBufferView(v: any, opts?: BufferConverterOpts): ArrayBufferView; - /** - * Convert a value into a `BufferSource` (ArrayBuffer or ArrayBufferView). - */ - BufferSource( - v: any, - opts?: BufferConverterOpts, - ): ArrayBuffer | ArrayBufferView; - /** - * Convert a value into a `DOMTimeStamp` (u64). Alias for unsigned long long - */ - DOMTimeStamp(v: any, opts?: IntConverterOpts): number; - /** - * Convert a value into a `Function` ((...args: any[]) => any). - */ - Function(v: any, opts?: ValueConverterOpts): (...args: any) => any; - /** - * Convert a value into a `VoidFunction` (() => void). - */ - VoidFunction(v: any, opts?: ValueConverterOpts): () => void; - ["UVString?"](v: any, opts?: ValueConverterOpts): string | null; - ["sequence"](v: any, opts?: ValueConverterOpts): number[]; - - [type: string]: (v: any, opts: ValueConverterOpts) => any; - }; - - /** - * Assert that the a function has at least a required amount of arguments. - */ - declare function requiredArguments( - length: number, - required: number, - opts: ConverterOpts, - ): void; - declare type Dictionary = DictionaryMember[]; - declare interface DictionaryMember { - key: string; - converter: (v: any, opts: ValueConverterOpts) => any; - defaultValue?: any; - required?: boolean; - } - - /** - * Create a converter for dictionaries. - */ - declare function createDictionaryConverter( - name: string, - ...dictionaries: Dictionary[] - ): (v: any, opts: ValueConverterOpts) => T; - - /** - * Create a converter for enums. - */ - declare function createEnumConverter( - name: string, - values: string[], - ): (v: any, opts: ValueConverterOpts) => string; - - /** - * Create a converter that makes the contained type nullable. - */ - declare function createNullableConverter( - 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( - converter: (v: any, opts: ValueConverterOpts) => T, - ): (v: any, opts: ValueConverterOpts) => T[]; - - /** - * Throw an illegal constructor error. - */ - declare function illegalConstructor(): never; - - /** - * The branding symbol. - */ - declare const brand: unique symbol; - - /** - * Create a branded instance of an interface. - */ - declare function createBranded(self: any): any; - - /** - * Assert that self is branded. - */ - declare function assertBranded(self: any, type: any): void; - - /** - * Create a converter for interfaces. - */ - declare function createInterfaceConverter( - name: string, - prototype: any, - ): (v: any, opts: ValueConverterOpts) => any; - - declare function createRecordConverter< - K extends string | number | symbol, - V, - >( - keyConverter: (v: any, opts: ValueConverterOpts) => K, - valueConverter: (v: any, opts: ValueConverterOpts) => V, - ): ( - v: Record, - opts: ValueConverterOpts, - ) => any; - } - declare var eventTarget: { EventTarget: typeof EventTarget; }; - declare var url: { - URLSearchParams: typeof URLSearchParams; - }; - declare var location: { getLocationHref(): string | undefined; }; diff --git a/op_crates/web/lib.deno_web.d.ts b/op_crates/web/lib.deno_web.d.ts index 24a8f929d26996..79b56f68e28c42 100644 --- a/op_crates/web/lib.deno_web.d.ts +++ b/op_crates/web/lib.deno_web.d.ts @@ -313,172 +313,3 @@ declare var FileReader: { readonly EMPTY: number; readonly LOADING: number; }; - -declare class URLSearchParams { - constructor( - init?: string[][] | Record | string | URLSearchParams, - ); - static toString(): string; - - /** Appends a specified key/value pair as a new search parameter. - * - * ```ts - * let searchParams = new URLSearchParams(); - * searchParams.append('name', 'first'); - * searchParams.append('name', 'second'); - * ``` - */ - append(name: string, value: string): void; - - /** Deletes the given search parameter and its associated value, - * from the list of all search parameters. - * - * ```ts - * let searchParams = new URLSearchParams([['name', 'value']]); - * searchParams.delete('name'); - * ``` - */ - delete(name: string): void; - - /** Returns all the values associated with a given search parameter - * as an array. - * - * ```ts - * searchParams.getAll('name'); - * ``` - */ - getAll(name: string): string[]; - - /** Returns the first value associated to the given search parameter. - * - * ```ts - * searchParams.get('name'); - * ``` - */ - get(name: string): string | null; - - /** Returns a Boolean that indicates whether a parameter with the - * specified name exists. - * - * ```ts - * searchParams.has('name'); - * ``` - */ - has(name: string): boolean; - - /** Sets the value associated with a given search parameter to the - * given value. If there were several matching values, this method - * deletes the others. If the search parameter doesn't exist, this - * method creates it. - * - * ```ts - * searchParams.set('name', 'value'); - * ``` - */ - set(name: string, value: string): void; - - /** Sort all key/value pairs contained in this object in place and - * return undefined. The sort order is according to Unicode code - * points of the keys. - * - * ```ts - * searchParams.sort(); - * ``` - */ - sort(): void; - - /** Calls a function for each element contained in this object in - * place and return undefined. Optionally accepts an object to use - * as this when executing callback as second argument. - * - * ```ts - * const params = new URLSearchParams([["a", "b"], ["c", "d"]]); - * params.forEach((value, key, parent) => { - * console.log(value, key, parent); - * }); - * ``` - * - */ - forEach( - callbackfn: (value: string, key: string, parent: this) => void, - thisArg?: any, - ): void; - - /** Returns an iterator allowing to go through all keys contained - * in this object. - * - * ```ts - * const params = new URLSearchParams([["a", "b"], ["c", "d"]]); - * for (const key of params.keys()) { - * console.log(key); - * } - * ``` - */ - keys(): IterableIterator; - - /** Returns an iterator allowing to go through all values contained - * in this object. - * - * ```ts - * const params = new URLSearchParams([["a", "b"], ["c", "d"]]); - * for (const value of params.values()) { - * console.log(value); - * } - * ``` - */ - values(): IterableIterator; - - /** Returns an iterator allowing to go through all key/value - * pairs contained in this object. - * - * ```ts - * const params = new URLSearchParams([["a", "b"], ["c", "d"]]); - * for (const [key, value] of params.entries()) { - * console.log(key, value); - * } - * ``` - */ - entries(): IterableIterator<[string, string]>; - - /** Returns an iterator allowing to go through all key/value - * pairs contained in this object. - * - * ```ts - * const params = new URLSearchParams([["a", "b"], ["c", "d"]]); - * for (const [key, value] of params) { - * console.log(key, value); - * } - * ``` - */ - [Symbol.iterator](): IterableIterator<[string, string]>; - - /** Returns a query string suitable for use in a URL. - * - * ```ts - * searchParams.toString(); - * ``` - */ - toString(): string; -} - -/** The URL interface represents an object providing static methods used for creating object URLs. */ -declare class URL { - constructor(url: string, base?: string | URL); - createObjectURL(object: any): string; - revokeObjectURL(url: string): void; - - hash: string; - host: string; - hostname: string; - href: string; - toString(): string; - readonly origin: string; - password: string; - pathname: string; - port: string; - protocol: string; - search: string; - readonly searchParams: URLSearchParams; - username: string; - toJSON(): string; -} diff --git a/op_crates/web/lib.rs b/op_crates/web/lib.rs index f67fd81a116bf3..81b51c6aebcd81 100644 --- a/op_crates/web/lib.rs +++ b/op_crates/web/lib.rs @@ -1,29 +1,11 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use deno_core::error::generic_error; -use deno_core::error::type_error; -use deno_core::error::uri_error; -use deno_core::error::AnyError; -use deno_core::serde_json; -use deno_core::serde_json::json; -use deno_core::serde_json::Value; -use deno_core::url::form_urlencoded; -use deno_core::url::quirks; -use deno_core::url::Url; use deno_core::JsRuntime; -use deno_core::ZeroCopyBuf; -use serde::Deserialize; -use serde::Serialize; -use std::panic::catch_unwind; use std::path::PathBuf; /// Load and execute the javascript code. pub fn init(isolate: &mut JsRuntime) { let files = vec![ - ( - "deno:op_crates/web/00_webidl.js", - include_str!("00_webidl.js"), - ), ( "deno:op_crates/web/01_dom_exception.js", include_str!("01_dom_exception.js"), @@ -44,7 +26,6 @@ pub fn init(isolate: &mut JsRuntime) { "deno:op_crates/web/08_text_encoding.js", include_str!("08_text_encoding.js"), ), - ("deno:op_crates/web/11_url.js", include_str!("11_url.js")), ( "deno:op_crates/web/12_location.js", include_str!("12_location.js"), @@ -59,131 +40,6 @@ pub fn init(isolate: &mut JsRuntime) { } } -/// Parse `UrlParseArgs::href` with an optional `UrlParseArgs::base_href`, or an -/// optional part to "set" after parsing. Return `UrlParts`. -pub fn op_parse_url( - _state: &mut deno_core::OpState, - args: Value, - _zero_copy: &mut [ZeroCopyBuf], -) -> Result { - #[derive(Deserialize)] - #[serde(rename_all = "camelCase")] - struct UrlParseArgs { - href: String, - base_href: Option, - // If one of the following are present, this is a setter call. Apply the - // proper `Url::set_*()` method after (re)parsing `href`. - set_hash: Option, - set_host: Option, - set_hostname: Option, - set_password: Option, - set_pathname: Option, - set_port: Option, - set_protocol: Option, - set_search: Option, - set_username: Option, - } - let args: UrlParseArgs = serde_json::from_value(args)?; - let base_url = args - .base_href - .as_ref() - .map(|b| Url::parse(b).map_err(|_| type_error("Invalid base URL"))) - .transpose()?; - let mut url = Url::options() - .base_url(base_url.as_ref()) - .parse(&args.href) - .map_err(|_| type_error("Invalid URL"))?; - - if let Some(hash) = args.set_hash.as_ref() { - quirks::set_hash(&mut url, hash); - } else if let Some(host) = args.set_host.as_ref() { - quirks::set_host(&mut url, host).map_err(|_| uri_error("Invalid host"))?; - } else if let Some(hostname) = args.set_hostname.as_ref() { - quirks::set_hostname(&mut url, hostname) - .map_err(|_| uri_error("Invalid hostname"))?; - } else if let Some(password) = args.set_password.as_ref() { - quirks::set_password(&mut url, password) - .map_err(|_| uri_error("Invalid password"))?; - } else if let Some(pathname) = args.set_pathname.as_ref() { - quirks::set_pathname(&mut url, pathname); - } else if let Some(port) = args.set_port.as_ref() { - quirks::set_port(&mut url, port).map_err(|_| uri_error("Invalid port"))?; - } else if let Some(protocol) = args.set_protocol.as_ref() { - quirks::set_protocol(&mut url, protocol) - .map_err(|_| uri_error("Invalid protocol"))?; - } else if let Some(search) = args.set_search.as_ref() { - quirks::set_search(&mut url, search); - } else if let Some(username) = args.set_username.as_ref() { - quirks::set_username(&mut url, username) - .map_err(|_| uri_error("Invalid username"))?; - } - - #[derive(Serialize)] - struct UrlParts<'a> { - href: &'a str, - hash: &'a str, - host: &'a str, - hostname: &'a str, - origin: &'a str, - password: &'a str, - pathname: &'a str, - port: &'a str, - protocol: &'a str, - search: &'a str, - username: &'a str, - } - // TODO(nayeemrmn): Panic that occurs in rust-url for the `non-spec:` - // url-constructor wpt tests: https://github.com/servo/rust-url/issues/670. - let username = catch_unwind(|| quirks::username(&url)).map_err(|_| { - generic_error(format!( - "Internal error while parsing \"{}\"{}, \ - see https://github.com/servo/rust-url/issues/670", - args.href, - args - .base_href - .map(|b| format!(" against \"{}\"", b)) - .unwrap_or_default() - )) - })?; - Ok(json!(UrlParts { - href: quirks::href(&url), - hash: quirks::hash(&url), - host: quirks::host(&url), - hostname: quirks::hostname(&url), - origin: &quirks::origin(&url), - password: quirks::password(&url), - pathname: quirks::pathname(&url), - port: quirks::port(&url), - protocol: quirks::protocol(&url), - search: quirks::search(&url), - username, - })) -} - -pub fn op_parse_url_search_params( - _state: &mut deno_core::OpState, - args: Value, - _zero_copy: &mut [ZeroCopyBuf], -) -> Result { - let search: String = serde_json::from_value(args)?; - let search_params: Vec<_> = form_urlencoded::parse(search.as_bytes()) - .into_iter() - .collect(); - Ok(json!(search_params)) -} - -pub fn op_stringify_url_search_params( - _state: &mut deno_core::OpState, - args: Value, - _zero_copy: &mut [ZeroCopyBuf], -) -> Result { - let search_params: Vec<(String, String)> = serde_json::from_value(args)?; - let search = form_urlencoded::Serializer::new(String::new()) - .extend_pairs(search_params) - .finish(); - Ok(json!(search)) -} - pub fn get_declaration() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_web.d.ts") } diff --git a/op_crates/webgpu/Cargo.toml b/op_crates/webgpu/Cargo.toml index f420106d31d643..603d0ad1be926e 100644 --- a/op_crates/webgpu/Cargo.toml +++ b/op_crates/webgpu/Cargo.toml @@ -4,7 +4,7 @@ name = "deno_webgpu" version = "0.1.1" edition = "2018" -description = "provides webgpu Web API to deno_core" +description = "WebGPU implementation for Deno" authors = ["the Deno authors"] license = "MIT" readme = "README.md" diff --git a/op_crates/web/00_webidl.js b/op_crates/webidl/00_webidl.js similarity index 100% rename from op_crates/web/00_webidl.js rename to op_crates/webidl/00_webidl.js diff --git a/op_crates/webidl/Cargo.toml b/op_crates/webidl/Cargo.toml new file mode 100644 index 00000000000000..5d2b1799909f63 --- /dev/null +++ b/op_crates/webidl/Cargo.toml @@ -0,0 +1,17 @@ +# Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +[package] +name = "deno_webidl" +version = "0.1.0" +edition = "2018" +description = "WebIDL implementation for Deno" +authors = ["the Deno authors"] +license = "MIT" +readme = "README.md" +repository = "https://github.com/denoland/deno" + +[lib] +path = "lib.rs" + +[dependencies] +deno_core = { version = "0.80.2", path = "../../core" } diff --git a/op_crates/webidl/README.md b/op_crates/webidl/README.md new file mode 100644 index 00000000000000..ce2d661e360b65 --- /dev/null +++ b/op_crates/webidl/README.md @@ -0,0 +1,6 @@ +# deno_webidl + +This crate implements WebIDL for Deno. It consists of infrastructure to do ECMA +-> WebIDL conversions. + +Spec: https://heycam.github.io/webidl/ diff --git a/op_crates/webidl/internal.d.ts b/op_crates/webidl/internal.d.ts new file mode 100644 index 00000000000000..425ee674e518d8 --- /dev/null +++ b/op_crates/webidl/internal.d.ts @@ -0,0 +1,291 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. +// deno-lint-ignore-file no-explicit-any ban-types + +/// +/// + +declare namespace globalThis { + declare namespace __bootstrap { + declare namespace webidl { + declare interface ConverterOpts { + /** + * The prefix for error messages created by this converter. + * Examples: + * - `Failed to construct 'Event'` + * - `Failed to execute 'removeEventListener' on 'EventTarget'` + */ + prefix: string; + } + declare interface ValueConverterOpts extends ConverterOpts { + /** + * The context of this value error messages created by this converter. + * Examples: + * - `Argument 1` + * - `Argument 3` + */ + context: string; + } + declare function makeException( + ErrorType: any, + message: string, + opts: ValueConverterOpts, + ): any; + declare interface IntConverterOpts extends ValueConverterOpts { + /** + * Wether to throw if the number is outside of the acceptable values for + * this type. + */ + enforceRange?: boolean; + /** + * Wether to clamp this number to the acceptable values for this type. + */ + clamp?: boolean; + } + declare interface StringConverterOpts extends ValueConverterOpts { + /** + * Wether to treat `null` value as an empty string. + */ + treatNullAsEmptyString?: boolean; + } + declare interface BufferConverterOpts extends ValueConverterOpts { + /** + * Wether to allow `SharedArrayBuffer` (not just `ArrayBuffer`). + */ + allowShared?: boolean; + } + declare const converters: { + any(v: any): any; + /** + * Convert a value into a `boolean` (bool). + */ + boolean(v: any, opts?: IntConverterOpts): boolean; + /** + * Convert a value into a `byte` (int8). + */ + byte(v: any, opts?: IntConverterOpts): number; + /** + * Convert a value into a `octet` (uint8). + */ + octet(v: any, opts?: IntConverterOpts): number; + /** + * Convert a value into a `short` (int16). + */ + short(v: any, opts?: IntConverterOpts): number; + /** + * Convert a value into a `unsigned short` (uint16). + */ + ["unsigned short"](v: any, opts?: IntConverterOpts): number; + /** + * Convert a value into a `long` (int32). + */ + long(v: any, opts?: IntConverterOpts): number; + /** + * Convert a value into a `unsigned long` (uint32). + */ + ["unsigned long"](v: any, opts?: IntConverterOpts): number; + /** + * Convert a value into a `long long` (int64). + * **Note this is truncated to a JS number (53 bit precision).** + */ + ["long long"](v: any, opts?: IntConverterOpts): number; + /** + * Convert a value into a `unsigned long long` (uint64). + * **Note this is truncated to a JS number (53 bit precision).** + */ + ["unsigned long long"](v: any, opts?: IntConverterOpts): number; + /** + * Convert a value into a `float` (f32). + */ + float(v: any, opts?: ValueConverterOpts): number; + /** + * Convert a value into a `unrestricted float` (f32, infinity, or NaN). + */ + ["unrestricted float"](v: any, opts?: ValueConverterOpts): number; + /** + * Convert a value into a `double` (f64). + */ + double(v: any, opts?: ValueConverterOpts): number; + /** + * Convert a value into a `unrestricted double` (f64, infinity, or NaN). + */ + ["unrestricted double"](v: any, opts?: ValueConverterOpts): number; + /** + * Convert a value into a `DOMString` (string). + */ + DOMString(v: any, opts?: StringConverterOpts): string; + /** + * Convert a value into a `ByteString` (string with only u8 codepoints). + */ + ByteString(v: any, opts?: StringConverterOpts): string; + /** + * Convert a value into a `USVString` (string with only valid non + * surrogate Unicode code points). + */ + USVString(v: any, opts?: StringConverterOpts): string; + /** + * Convert a value into an `object` (object). + */ + object(v: any, opts?: ValueConverterOpts): object; + /** + * Convert a value into an `ArrayBuffer` (ArrayBuffer). + */ + ArrayBuffer(v: any, opts?: BufferConverterOpts): ArrayBuffer; + /** + * Convert a value into a `DataView` (ArrayBuffer). + */ + DataView(v: any, opts?: BufferConverterOpts): DataView; + /** + * Convert a value into a `Int8Array` (Int8Array). + */ + Int8Array(v: any, opts?: BufferConverterOpts): Int8Array; + /** + * Convert a value into a `Int16Array` (Int16Array). + */ + Int16Array(v: any, opts?: BufferConverterOpts): Int16Array; + /** + * Convert a value into a `Int32Array` (Int32Array). + */ + Int32Array(v: any, opts?: BufferConverterOpts): Int32Array; + /** + * Convert a value into a `Uint8Array` (Uint8Array). + */ + Uint8Array(v: any, opts?: BufferConverterOpts): Uint8Array; + /** + * Convert a value into a `Uint16Array` (Uint16Array). + */ + Uint16Array(v: any, opts?: BufferConverterOpts): Uint16Array; + /** + * Convert a value into a `Uint32Array` (Uint32Array). + */ + Uint32Array(v: any, opts?: BufferConverterOpts): Uint32Array; + /** + * Convert a value into a `Uint8ClampedArray` (Uint8ClampedArray). + */ + Uint8ClampedArray( + v: any, + opts?: BufferConverterOpts, + ): Uint8ClampedArray; + /** + * Convert a value into a `Float32Array` (Float32Array). + */ + Float32Array(v: any, opts?: BufferConverterOpts): Float32Array; + /** + * Convert a value into a `Float64Array` (Float64Array). + */ + Float64Array(v: any, opts?: BufferConverterOpts): Float64Array; + /** + * Convert a value into an `ArrayBufferView` (ArrayBufferView). + */ + ArrayBufferView(v: any, opts?: BufferConverterOpts): ArrayBufferView; + /** + * Convert a value into a `BufferSource` (ArrayBuffer or ArrayBufferView). + */ + BufferSource( + v: any, + opts?: BufferConverterOpts, + ): ArrayBuffer | ArrayBufferView; + /** + * Convert a value into a `DOMTimeStamp` (u64). Alias for unsigned long long + */ + DOMTimeStamp(v: any, opts?: IntConverterOpts): number; + /** + * Convert a value into a `Function` ((...args: any[]) => any). + */ + Function(v: any, opts?: ValueConverterOpts): (...args: any) => any; + /** + * Convert a value into a `VoidFunction` (() => void). + */ + VoidFunction(v: any, opts?: ValueConverterOpts): () => void; + ["UVString?"](v: any, opts?: ValueConverterOpts): string | null; + ["sequence"](v: any, opts?: ValueConverterOpts): number[]; + + [type: string]: (v: any, opts: ValueConverterOpts) => any; + }; + + /** + * Assert that the a function has at least a required amount of arguments. + */ + declare function requiredArguments( + length: number, + required: number, + opts: ConverterOpts, + ): void; + declare type Dictionary = DictionaryMember[]; + declare interface DictionaryMember { + key: string; + converter: (v: any, opts: ValueConverterOpts) => any; + defaultValue?: any; + required?: boolean; + } + + /** + * Create a converter for dictionaries. + */ + declare function createDictionaryConverter( + name: string, + ...dictionaries: Dictionary[] + ): (v: any, opts: ValueConverterOpts) => T; + + /** + * Create a converter for enums. + */ + declare function createEnumConverter( + name: string, + values: string[], + ): (v: any, opts: ValueConverterOpts) => string; + + /** + * Create a converter that makes the contained type nullable. + */ + declare function createNullableConverter( + 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( + converter: (v: any, opts: ValueConverterOpts) => T, + ): (v: any, opts: ValueConverterOpts) => T[]; + + /** + * Throw an illegal constructor error. + */ + declare function illegalConstructor(): never; + + /** + * The branding symbol. + */ + declare const brand: unique symbol; + + /** + * Create a branded instance of an interface. + */ + declare function createBranded(self: any): any; + + /** + * Assert that self is branded. + */ + declare function assertBranded(self: any, type: any): void; + + /** + * Create a converter for interfaces. + */ + declare function createInterfaceConverter( + name: string, + prototype: any, + ): (v: any, opts: ValueConverterOpts) => any; + + declare function createRecordConverter< + K extends string | number | symbol, + V, + >( + keyConverter: (v: any, opts: ValueConverterOpts) => K, + valueConverter: (v: any, opts: ValueConverterOpts) => V, + ): ( + v: Record, + opts: ValueConverterOpts, + ) => any; + } + } +} diff --git a/op_crates/webidl/lib.rs b/op_crates/webidl/lib.rs new file mode 100644 index 00000000000000..7e617c7a766121 --- /dev/null +++ b/op_crates/webidl/lib.rs @@ -0,0 +1,14 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. + +use deno_core::JsRuntime; + +/// Load and execute the javascript code. +pub fn init(isolate: &mut JsRuntime) { + let files = vec![( + "deno:op_crates/webidl/00_webidl.js", + include_str!("00_webidl.js"), + )]; + for (url, source_code) in files { + isolate.execute(url, source_code).unwrap(); + } +} diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 0ece4228ebc3f8..f654e015c0472e 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -22,6 +22,8 @@ deno_core = { path = "../core", version = "0.80.2" } deno_crypto = { path = "../op_crates/crypto", version = "0.14.1" } deno_fetch = { path = "../op_crates/fetch", version = "0.22.3" } deno_web = { path = "../op_crates/web", version = "0.30.3" } +deno_url = { path = "../op_crates/url", version = "0.1.0" } +deno_webidl = { path = "../op_crates/webidl", version = "0.1.0" } deno_websocket = { path = "../op_crates/websocket", version = "0.5.3" } deno_webgpu = { path = "../op_crates/webgpu", version = "0.1.1" } @@ -34,6 +36,8 @@ deno_core = { path = "../core", version = "0.80.2" } deno_crypto = { path = "../op_crates/crypto", version = "0.14.1" } deno_fetch = { path = "../op_crates/fetch", version = "0.22.3" } deno_web = { path = "../op_crates/web", version = "0.30.3" } +deno_url = { path = "../op_crates/url", version = "0.1.0" } +deno_webidl = { path = "../op_crates/webidl", version = "0.1.0" } deno_websocket = { path = "../op_crates/websocket", version = "0.5.3" } deno_webgpu = { path = "../op_crates/webgpu", version = "0.1.1" } diff --git a/runtime/build.rs b/runtime/build.rs index 2481485684b762..67f80c8672bd17 100644 --- a/runtime/build.rs +++ b/runtime/build.rs @@ -13,6 +13,8 @@ fn create_snapshot( snapshot_path: &Path, files: Vec, ) { + deno_webidl::init(&mut js_runtime); + deno_url::init(&mut js_runtime); deno_web::init(&mut js_runtime); deno_fetch::init(&mut js_runtime); deno_websocket::init(&mut js_runtime); diff --git a/runtime/lib.rs b/runtime/lib.rs index c523b24b7abf71..1406372616593f 100644 --- a/runtime/lib.rs +++ b/runtime/lib.rs @@ -9,8 +9,10 @@ extern crate log; pub use deno_crypto; pub use deno_fetch; +pub use deno_url; pub use deno_web; pub use deno_webgpu; +pub use deno_webidl; pub use deno_websocket; pub mod colors; diff --git a/runtime/ops/mod.rs b/runtime/ops/mod.rs index 0ef04ff3cf8de9..6b64b8042f8887 100644 --- a/runtime/ops/mod.rs +++ b/runtime/ops/mod.rs @@ -20,6 +20,7 @@ pub mod signal; pub mod timers; pub mod tls; pub mod tty; +pub mod url; pub mod web_worker; pub mod webgpu; pub mod websocket; diff --git a/runtime/ops/url.rs b/runtime/ops/url.rs new file mode 100644 index 00000000000000..4add9132d6f769 --- /dev/null +++ b/runtime/ops/url.rs @@ -0,0 +1,18 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. +use deno_url::op_url_parse; +use deno_url::op_url_parse_search_params; +use deno_url::op_url_stringify_search_params; + +pub fn init(rt: &mut deno_core::JsRuntime) { + super::reg_json_sync(rt, "op_url_parse", op_url_parse); + super::reg_json_sync( + rt, + "op_url_parse_search_params", + op_url_parse_search_params, + ); + super::reg_json_sync( + rt, + "op_url_stringify_search_params", + op_url_stringify_search_params, + ); +} diff --git a/runtime/web_worker.rs b/runtime/web_worker.rs index 73d351c9c64d09..f35b38d3ba90f5 100644 --- a/runtime/web_worker.rs +++ b/runtime/web_worker.rs @@ -231,17 +231,7 @@ impl WebWorker { ); ops::reg_json_sync(js_runtime, "op_close", deno_core::op_close); ops::reg_json_sync(js_runtime, "op_resources", deno_core::op_resources); - ops::reg_json_sync(js_runtime, "op_parse_url", deno_web::op_parse_url); - ops::reg_json_sync( - js_runtime, - "op_parse_url_search_params", - deno_web::op_parse_url_search_params, - ); - ops::reg_json_sync( - js_runtime, - "op_stringify_url_search_params", - deno_web::op_stringify_url_search_params, - ); + ops::url::init(js_runtime); ops::io::init(js_runtime); ops::webgpu::init(js_runtime); ops::websocket::init( diff --git a/runtime/worker.rs b/runtime/worker.rs index e63fdbe18cf3fc..51fe1dc273adeb 100644 --- a/runtime/worker.rs +++ b/runtime/worker.rs @@ -127,17 +127,7 @@ impl MainWorker { ops::crypto::init(js_runtime, options.seed); ops::reg_json_sync(js_runtime, "op_close", deno_core::op_close); ops::reg_json_sync(js_runtime, "op_resources", deno_core::op_resources); - ops::reg_json_sync(js_runtime, "op_parse_url", deno_web::op_parse_url); - ops::reg_json_sync( - js_runtime, - "op_parse_url_search_params", - deno_web::op_parse_url_search_params, - ); - ops::reg_json_sync( - js_runtime, - "op_stringify_url_search_params", - deno_web::op_stringify_url_search_params, - ); + ops::url::init(js_runtime); ops::fs_events::init(js_runtime); ops::fs::init(js_runtime); ops::io::init(js_runtime);