mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
chore: split web op crate (#9635)
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.
This commit is contained in:
parent
2f9d7c02dc
commit
e83ff62ccb
37 changed files with 785 additions and 1256 deletions
19
Cargo.lock
generated
19
Cargo.lock
generated
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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()
|
||||
|
|
1
cli/dts/lib.deno.shared_globals.d.ts
vendored
1
cli/dts/lib.deno.shared_globals.d.ts
vendored
|
@ -5,6 +5,7 @@
|
|||
|
||||
/// <reference no-default-lib="true" />
|
||||
/// <reference lib="esnext" />
|
||||
/// <reference lib="deno.url" />
|
||||
/// <reference lib="deno.web" />
|
||||
/// <reference lib="deno.fetch" />
|
||||
/// <reference lib="deno.websocket" />
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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 */
|
||||
}
|
19
op_crates/url/Cargo.toml
Normal file
19
op_crates/url/Cargo.toml
Normal file
|
@ -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"] }
|
5
op_crates/url/README.md
Normal file
5
op_crates/url/README.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
# deno_url
|
||||
|
||||
This crate implements the URL API for Deno.
|
||||
|
||||
Spec: https://url.spec.whatwg.org/
|
13
op_crates/url/internal.d.ts
vendored
Normal file
13
op_crates/url/internal.d.ts
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
/// <reference no-default-lib="true" />
|
||||
/// <reference lib="esnext" />
|
||||
|
||||
declare namespace globalThis {
|
||||
declare namespace __bootstrap {
|
||||
declare var url: {
|
||||
URL: typeof URL;
|
||||
URLSearchParams: typeof URLSearchParams;
|
||||
};
|
||||
}
|
||||
}
|
175
op_crates/url/lib.deno_url.d.ts
vendored
Normal file
175
op_crates/url/lib.deno_url.d.ts
vendored
Normal file
|
@ -0,0 +1,175 @@
|
|||
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
// deno-lint-ignore-file no-explicit-any
|
||||
|
||||
/// <reference no-default-lib="true" />
|
||||
/// <reference lib="esnext" />
|
||||
|
||||
declare class URLSearchParams {
|
||||
constructor(
|
||||
init?: string[][] | Record<string, string> | 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<string>;
|
||||
|
||||
/** 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<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.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;
|
||||
}
|
155
op_crates/url/lib.rs
Normal file
155
op_crates/url/lib.rs
Normal file
|
@ -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<Value, AnyError> {
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct UrlParseArgs {
|
||||
href: String,
|
||||
base_href: Option<String>,
|
||||
// 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<String>,
|
||||
set_host: Option<String>,
|
||||
set_hostname: Option<String>,
|
||||
set_password: Option<String>,
|
||||
set_pathname: Option<String>,
|
||||
set_port: Option<String>,
|
||||
set_protocol: Option<String>,
|
||||
set_search: Option<String>,
|
||||
set_username: Option<String>,
|
||||
}
|
||||
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<Value, AnyError> {
|
||||
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<Value, AnyError> {
|
||||
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")
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
// @ts-check
|
||||
/// <reference path="../../core/lib.deno_core.d.ts" />
|
||||
/// <reference path="../webidl/internal.d.ts" />
|
||||
/// <reference path="../web/internal.d.ts" />
|
||||
/// <reference path="../web/lib.deno_web.d.ts" />
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -1,140 +0,0 @@
|
|||
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||
"use strict";
|
||||
function assert(cond) {
|
||||
if (!cond) {
|
||||
throw Error("assert");
|
||||
}
|
||||
}
|
||||
|
||||
function assertEquals(left, right) {
|
||||
assert(left === right);
|
||||
}
|
||||
|
||||
function assertThrows(fn) {
|
||||
let error = null;
|
||||
try {
|
||||
fn();
|
||||
} catch (error_) {
|
||||
error = error_;
|
||||
}
|
||||
if (error == null) {
|
||||
throw new Error("Didn't throw.");
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
function basicAbortController() {
|
||||
const controller = new AbortController();
|
||||
assert(controller);
|
||||
const { signal } = controller;
|
||||
assert(signal);
|
||||
assertEquals(signal.aborted, false);
|
||||
controller.abort();
|
||||
assertEquals(signal.aborted, true);
|
||||
}
|
||||
|
||||
function signalCallsOnabort() {
|
||||
const controller = new AbortController();
|
||||
const { signal } = controller;
|
||||
let called = false;
|
||||
signal.onabort = (evt) => {
|
||||
assert(evt);
|
||||
assertEquals(evt.type, "abort");
|
||||
called = true;
|
||||
};
|
||||
controller.abort();
|
||||
assert(called);
|
||||
}
|
||||
|
||||
function signalEventListener() {
|
||||
const controller = new AbortController();
|
||||
const { signal } = controller;
|
||||
let called = false;
|
||||
signal.addEventListener("abort", function (ev) {
|
||||
assert(this === signal);
|
||||
assertEquals(ev.type, "abort");
|
||||
called = true;
|
||||
});
|
||||
controller.abort();
|
||||
assert(called);
|
||||
}
|
||||
|
||||
function onlyAbortsOnce() {
|
||||
const controller = new AbortController();
|
||||
const { signal } = controller;
|
||||
let called = 0;
|
||||
signal.addEventListener("abort", () => called++);
|
||||
signal.onabort = () => {
|
||||
called++;
|
||||
};
|
||||
controller.abort();
|
||||
assertEquals(called, 2);
|
||||
controller.abort();
|
||||
assertEquals(called, 2);
|
||||
}
|
||||
|
||||
function controllerHasProperToString() {
|
||||
const actual = Object.prototype.toString.call(new AbortController());
|
||||
assertEquals(actual, "[object AbortController]");
|
||||
}
|
||||
|
||||
function abortSignalIllegalConstructor() {
|
||||
const error = assertThrows(() => new AbortSignal());
|
||||
assert(error instanceof TypeError);
|
||||
assertEquals(error.message, "Illegal constructor.");
|
||||
}
|
||||
|
||||
function abortSignalEventOrder() {
|
||||
const arr = [];
|
||||
const controller = new AbortController();
|
||||
const { signal } = controller;
|
||||
signal.addEventListener("abort", () => arr.push(1));
|
||||
signal.onabort = () => arr.push(2);
|
||||
signal.addEventListener("abort", () => arr.push(3));
|
||||
controller.abort();
|
||||
assertEquals(arr[0], 1);
|
||||
assertEquals(arr[1], 2);
|
||||
assertEquals(arr[2], 3);
|
||||
}
|
||||
|
||||
function abortSignalEventOrderComplex() {
|
||||
const arr = [];
|
||||
const controller = new AbortController();
|
||||
const { signal } = controller;
|
||||
signal.addEventListener("abort", () => arr.push(1));
|
||||
signal.onabort = () => {
|
||||
throw new Error();
|
||||
};
|
||||
signal.addEventListener("abort", () => arr.push(3));
|
||||
signal.onabort = () => arr.push(2);
|
||||
controller.abort();
|
||||
assertEquals(arr[0], 1);
|
||||
assertEquals(arr[1], 2);
|
||||
assertEquals(arr[2], 3);
|
||||
}
|
||||
|
||||
function abortSignalHandlerLocation() {
|
||||
const controller = new AbortController();
|
||||
const { signal } = controller;
|
||||
const abortHandler = Object.getOwnPropertyDescriptor(signal, "onabort");
|
||||
assertEquals(abortHandler, undefined);
|
||||
}
|
||||
function abortSignalLength() {
|
||||
const controller = new AbortController();
|
||||
const { signal } = controller;
|
||||
assertEquals(signal.constructor.length, 0);
|
||||
}
|
||||
function main() {
|
||||
basicAbortController();
|
||||
signalCallsOnabort();
|
||||
signalEventListener();
|
||||
onlyAbortsOnce();
|
||||
controllerHasProperToString();
|
||||
abortSignalIllegalConstructor();
|
||||
abortSignalEventOrder();
|
||||
abortSignalEventOrderComplex();
|
||||
abortSignalHandlerLocation();
|
||||
abortSignalLength();
|
||||
}
|
||||
|
||||
main();
|
|
@ -1,245 +0,0 @@
|
|||
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||
"use strict";
|
||||
function assert(cond) {
|
||||
if (!cond) {
|
||||
throw Error("assert");
|
||||
}
|
||||
}
|
||||
|
||||
function addEventListenerTest() {
|
||||
const document = new EventTarget();
|
||||
|
||||
assert(document.addEventListener("x", null, false) === undefined);
|
||||
assert(document.addEventListener("x", null, true) === undefined);
|
||||
assert(document.addEventListener("x", null) === undefined);
|
||||
}
|
||||
|
||||
function constructedEventTargetCanBeUsedAsExpected() {
|
||||
const target = new EventTarget();
|
||||
const event = new Event("foo", { bubbles: true, cancelable: false });
|
||||
let callCount = 0;
|
||||
|
||||
const listener = (e) => {
|
||||
assert(e === event);
|
||||
++callCount;
|
||||
};
|
||||
|
||||
target.addEventListener("foo", listener);
|
||||
|
||||
target.dispatchEvent(event);
|
||||
assert(callCount === 1);
|
||||
|
||||
target.dispatchEvent(event);
|
||||
assert(callCount === 2);
|
||||
|
||||
target.removeEventListener("foo", listener);
|
||||
target.dispatchEvent(event);
|
||||
assert(callCount === 2);
|
||||
}
|
||||
|
||||
function anEventTargetCanBeSubclassed() {
|
||||
class NicerEventTarget extends EventTarget {
|
||||
on(
|
||||
type,
|
||||
callback,
|
||||
options,
|
||||
) {
|
||||
this.addEventListener(type, callback, options);
|
||||
}
|
||||
|
||||
off(
|
||||
type,
|
||||
callback,
|
||||
options,
|
||||
) {
|
||||
this.removeEventListener(type, callback, options);
|
||||
}
|
||||
}
|
||||
|
||||
const target = new NicerEventTarget();
|
||||
new Event("foo", { bubbles: true, cancelable: false });
|
||||
let callCount = 0;
|
||||
|
||||
const listener = () => {
|
||||
++callCount;
|
||||
};
|
||||
|
||||
target.on("foo", listener);
|
||||
assert(callCount === 0);
|
||||
|
||||
target.off("foo", listener);
|
||||
assert(callCount === 0);
|
||||
}
|
||||
|
||||
function removingNullEventListenerShouldSucceed() {
|
||||
const document = new EventTarget();
|
||||
assert(document.removeEventListener("x", null, false) === undefined);
|
||||
assert(document.removeEventListener("x", null, true) === undefined);
|
||||
assert(document.removeEventListener("x", null) === undefined);
|
||||
}
|
||||
|
||||
function constructedEventTargetUseObjectPrototype() {
|
||||
const target = new EventTarget();
|
||||
const event = new Event("toString", { bubbles: true, cancelable: false });
|
||||
let callCount = 0;
|
||||
|
||||
const listener = (e) => {
|
||||
assert(e === event);
|
||||
++callCount;
|
||||
};
|
||||
|
||||
target.addEventListener("toString", listener);
|
||||
|
||||
target.dispatchEvent(event);
|
||||
assert(callCount === 1);
|
||||
|
||||
target.dispatchEvent(event);
|
||||
assert(callCount === 2);
|
||||
|
||||
target.removeEventListener("toString", listener);
|
||||
target.dispatchEvent(event);
|
||||
assert(callCount === 2);
|
||||
}
|
||||
|
||||
function toStringShouldBeWebCompatible() {
|
||||
const target = new EventTarget();
|
||||
assert(target.toString() === "[object EventTarget]");
|
||||
}
|
||||
|
||||
function dispatchEventShouldNotThrowError() {
|
||||
let hasThrown = false;
|
||||
|
||||
try {
|
||||
const target = new EventTarget();
|
||||
const event = new Event("hasOwnProperty", {
|
||||
bubbles: true,
|
||||
cancelable: false,
|
||||
});
|
||||
const listener = () => {};
|
||||
target.addEventListener("hasOwnProperty", listener);
|
||||
target.dispatchEvent(event);
|
||||
} catch {
|
||||
hasThrown = true;
|
||||
}
|
||||
|
||||
assert(hasThrown === false);
|
||||
}
|
||||
|
||||
function eventTargetThisShouldDefaultToWindow() {
|
||||
const {
|
||||
addEventListener,
|
||||
dispatchEvent,
|
||||
removeEventListener,
|
||||
} = EventTarget.prototype;
|
||||
let n = 1;
|
||||
const event = new Event("hello");
|
||||
const listener = () => {
|
||||
n = 2;
|
||||
};
|
||||
|
||||
addEventListener("hello", listener);
|
||||
globalThis.dispatchEvent(event);
|
||||
assert(n === 2);
|
||||
n = 1;
|
||||
removeEventListener("hello", listener);
|
||||
globalThis.dispatchEvent(event);
|
||||
assert(n === 1);
|
||||
|
||||
globalThis.addEventListener("hello", listener);
|
||||
dispatchEvent(event);
|
||||
assert(n === 2);
|
||||
n = 1;
|
||||
globalThis.removeEventListener("hello", listener);
|
||||
dispatchEvent(event);
|
||||
assert(n === 1);
|
||||
}
|
||||
|
||||
function eventTargetShouldAcceptEventListenerObject() {
|
||||
const target = new EventTarget();
|
||||
const event = new Event("foo", { bubbles: true, cancelable: false });
|
||||
let callCount = 0;
|
||||
|
||||
const listener = {
|
||||
handleEvent(e) {
|
||||
assert(e === event);
|
||||
++callCount;
|
||||
},
|
||||
};
|
||||
|
||||
target.addEventListener("foo", listener);
|
||||
|
||||
target.dispatchEvent(event);
|
||||
assert(callCount === 1);
|
||||
|
||||
target.dispatchEvent(event);
|
||||
assert(callCount === 2);
|
||||
|
||||
target.removeEventListener("foo", listener);
|
||||
target.dispatchEvent(event);
|
||||
assert(callCount === 2);
|
||||
}
|
||||
|
||||
function eventTargetShouldAcceptAsyncFunction() {
|
||||
const target = new EventTarget();
|
||||
const event = new Event("foo", { bubbles: true, cancelable: false });
|
||||
let callCount = 0;
|
||||
|
||||
const listener = (e) => {
|
||||
assert(e === event);
|
||||
++callCount;
|
||||
};
|
||||
|
||||
target.addEventListener("foo", listener);
|
||||
|
||||
target.dispatchEvent(event);
|
||||
assert(callCount === 1);
|
||||
|
||||
target.dispatchEvent(event);
|
||||
assert(callCount === 2);
|
||||
|
||||
target.removeEventListener("foo", listener);
|
||||
target.dispatchEvent(event);
|
||||
assert(callCount === 2);
|
||||
}
|
||||
|
||||
function eventTargetShouldAcceptAsyncFunctionForEventListenerObject() {
|
||||
const target = new EventTarget();
|
||||
const event = new Event("foo", { bubbles: true, cancelable: false });
|
||||
let callCount = 0;
|
||||
|
||||
const listener = {
|
||||
handleEvent(e) {
|
||||
assert(e === event);
|
||||
++callCount;
|
||||
},
|
||||
};
|
||||
|
||||
target.addEventListener("foo", listener);
|
||||
|
||||
target.dispatchEvent(event);
|
||||
assert(callCount === 1);
|
||||
|
||||
target.dispatchEvent(event);
|
||||
assert(callCount === 2);
|
||||
|
||||
target.removeEventListener("foo", listener);
|
||||
target.dispatchEvent(event);
|
||||
assert(callCount === 2);
|
||||
}
|
||||
|
||||
function main() {
|
||||
globalThis.__bootstrap.eventTarget.setEventTargetData(globalThis);
|
||||
addEventListenerTest();
|
||||
constructedEventTargetCanBeUsedAsExpected();
|
||||
anEventTargetCanBeSubclassed();
|
||||
removingNullEventListenerShouldSucceed();
|
||||
constructedEventTargetUseObjectPrototype();
|
||||
toStringShouldBeWebCompatible();
|
||||
dispatchEventShouldNotThrowError();
|
||||
eventTargetThisShouldDefaultToWindow();
|
||||
eventTargetShouldAcceptEventListenerObject();
|
||||
eventTargetShouldAcceptAsyncFunction();
|
||||
eventTargetShouldAcceptAsyncFunctionForEventListenerObject();
|
||||
}
|
||||
|
||||
main();
|
|
@ -1,142 +0,0 @@
|
|||
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||
"use strict";
|
||||
function assert(cond) {
|
||||
if (!cond) {
|
||||
throw Error("assert");
|
||||
}
|
||||
}
|
||||
|
||||
function eventInitializedWithType() {
|
||||
const type = "click";
|
||||
const event = new Event(type);
|
||||
|
||||
assert(event.isTrusted === false);
|
||||
assert(event.target === null);
|
||||
assert(event.currentTarget === null);
|
||||
assert(event.type === "click");
|
||||
assert(event.bubbles === false);
|
||||
assert(event.cancelable === false);
|
||||
}
|
||||
|
||||
function eventInitializedWithTypeAndDict() {
|
||||
const init = "submit";
|
||||
const eventInit = { bubbles: true, cancelable: true };
|
||||
const event = new Event(init, eventInit);
|
||||
|
||||
assert(event.isTrusted === false);
|
||||
assert(event.target === null);
|
||||
assert(event.currentTarget === null);
|
||||
assert(event.type === "submit");
|
||||
assert(event.bubbles === true);
|
||||
assert(event.cancelable === true);
|
||||
}
|
||||
|
||||
function eventComposedPathSuccess() {
|
||||
const type = "click";
|
||||
const event = new Event(type);
|
||||
const composedPath = event.composedPath();
|
||||
|
||||
assert(composedPath.length === 0);
|
||||
}
|
||||
|
||||
function eventStopPropagationSuccess() {
|
||||
const type = "click";
|
||||
const event = new Event(type);
|
||||
|
||||
assert(event.cancelBubble === false);
|
||||
event.stopPropagation();
|
||||
assert(event.cancelBubble === true);
|
||||
}
|
||||
|
||||
function eventStopImmediatePropagationSuccess() {
|
||||
const type = "click";
|
||||
const event = new Event(type);
|
||||
|
||||
assert(event.cancelBubble === false);
|
||||
event.stopImmediatePropagation();
|
||||
assert(event.cancelBubble === true);
|
||||
}
|
||||
|
||||
function eventPreventDefaultSuccess() {
|
||||
const type = "click";
|
||||
const event = new Event(type);
|
||||
|
||||
assert(event.defaultPrevented === false);
|
||||
event.preventDefault();
|
||||
assert(event.defaultPrevented === false);
|
||||
|
||||
const eventInit = { bubbles: true, cancelable: true };
|
||||
const cancelableEvent = new Event(type, eventInit);
|
||||
assert(cancelableEvent.defaultPrevented === false);
|
||||
cancelableEvent.preventDefault();
|
||||
assert(cancelableEvent.defaultPrevented === true);
|
||||
}
|
||||
|
||||
function eventInitializedWithNonStringType() {
|
||||
const type = undefined;
|
||||
const event = new Event(type);
|
||||
|
||||
assert(event.isTrusted === false);
|
||||
assert(event.target === null);
|
||||
assert(event.currentTarget === null);
|
||||
assert(event.type === "undefined");
|
||||
assert(event.bubbles === false);
|
||||
assert(event.cancelable === false);
|
||||
}
|
||||
|
||||
// ref https://github.com/web-platform-tests/wpt/blob/master/dom/events/Event-isTrusted.any.js
|
||||
function eventIsTrusted() {
|
||||
const desc1 = Object.getOwnPropertyDescriptor(new Event("x"), "isTrusted");
|
||||
assert(desc1);
|
||||
assert(typeof desc1.get === "function");
|
||||
|
||||
const desc2 = Object.getOwnPropertyDescriptor(new Event("x"), "isTrusted");
|
||||
assert(desc2);
|
||||
assert(typeof desc2.get === "function");
|
||||
|
||||
assert(desc1.get === desc2.get);
|
||||
}
|
||||
|
||||
function eventIsTrustedGetterName() {
|
||||
const { get } = Object.getOwnPropertyDescriptor(new Event("x"), "isTrusted");
|
||||
assert(get.name === "get isTrusted");
|
||||
try {
|
||||
Reflect.construct(get);
|
||||
throw new Error("Should not have reached here");
|
||||
} catch (e) {
|
||||
assert(e.message.includes("not a constructor"));
|
||||
}
|
||||
}
|
||||
function eventAbortSignal() {
|
||||
let count = 0;
|
||||
function handler() {
|
||||
count++;
|
||||
}
|
||||
const et = new EventTarget();
|
||||
const controller = new AbortController();
|
||||
et.addEventListener("test", handler, { signal: controller.signal });
|
||||
et.dispatchEvent(new Event("test"));
|
||||
assert(count === 1);
|
||||
et.dispatchEvent(new Event("test"));
|
||||
assert(count === 2);
|
||||
controller.abort();
|
||||
et.dispatchEvent(new Event("test"));
|
||||
assert(count === 2);
|
||||
et.addEventListener("test", handler, { signal: controller.signal });
|
||||
et.dispatchEvent(new Event("test"));
|
||||
assert(count === 2);
|
||||
}
|
||||
function main() {
|
||||
eventInitializedWithType();
|
||||
eventInitializedWithTypeAndDict();
|
||||
eventComposedPathSuccess();
|
||||
eventStopPropagationSuccess();
|
||||
eventStopImmediatePropagationSuccess();
|
||||
eventPreventDefaultSuccess();
|
||||
eventInitializedWithNonStringType();
|
||||
eventIsTrusted();
|
||||
eventIsTrustedGetterName();
|
||||
eventAbortSignal();
|
||||
}
|
||||
|
||||
main();
|
287
op_crates/web/internal.d.ts
vendored
287
op_crates/web/internal.d.ts
vendored
|
@ -1,301 +1,14 @@
|
|||
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||
// deno-lint-ignore-file no-explicit-any ban-types
|
||||
|
||||
/// <reference no-default-lib="true" />
|
||||
/// <reference lib="esnext" />
|
||||
|
||||
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<double>"](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<T>(
|
||||
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<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>(
|
||||
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<K, V>,
|
||||
opts: ValueConverterOpts,
|
||||
) => any;
|
||||
}
|
||||
|
||||
declare var eventTarget: {
|
||||
EventTarget: typeof EventTarget;
|
||||
};
|
||||
|
||||
declare var url: {
|
||||
URLSearchParams: typeof URLSearchParams;
|
||||
};
|
||||
|
||||
declare var location: {
|
||||
getLocationHref(): string | undefined;
|
||||
};
|
||||
|
|
169
op_crates/web/lib.deno_web.d.ts
vendored
169
op_crates/web/lib.deno_web.d.ts
vendored
|
@ -313,172 +313,3 @@ declare var FileReader: {
|
|||
readonly EMPTY: number;
|
||||
readonly LOADING: number;
|
||||
};
|
||||
|
||||
declare class URLSearchParams {
|
||||
constructor(
|
||||
init?: string[][] | Record<string, string> | 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<string>;
|
||||
|
||||
/** 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<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.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;
|
||||
}
|
||||
|
|
|
@ -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,213 +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<Value, AnyError> {
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct UrlParseArgs {
|
||||
href: String,
|
||||
base_href: Option<String>,
|
||||
// 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<String>,
|
||||
set_host: Option<String>,
|
||||
set_hostname: Option<String>,
|
||||
set_password: Option<String>,
|
||||
set_pathname: Option<String>,
|
||||
set_port: Option<String>,
|
||||
set_protocol: Option<String>,
|
||||
set_search: Option<String>,
|
||||
set_username: Option<String>,
|
||||
}
|
||||
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<Value, AnyError> {
|
||||
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<Value, AnyError> {
|
||||
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")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use deno_core::JsRuntime;
|
||||
use futures::future::lazy;
|
||||
use futures::task::Context;
|
||||
use futures::task::Poll;
|
||||
|
||||
fn run_in_task<F>(f: F)
|
||||
where
|
||||
F: FnOnce(&mut Context) + Send + 'static,
|
||||
{
|
||||
futures::executor::block_on(lazy(move |cx| f(cx)));
|
||||
}
|
||||
|
||||
fn setup() -> JsRuntime {
|
||||
let mut isolate = JsRuntime::new(Default::default());
|
||||
crate::init(&mut isolate);
|
||||
isolate
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_abort_controller() {
|
||||
run_in_task(|mut cx| {
|
||||
let mut isolate = setup();
|
||||
isolate
|
||||
.execute(
|
||||
"abort_controller_test.js",
|
||||
include_str!("abort_controller_test.js"),
|
||||
)
|
||||
.unwrap();
|
||||
if let Poll::Ready(Err(_)) = isolate.poll_event_loop(&mut cx) {
|
||||
unreachable!();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_event() {
|
||||
run_in_task(|mut cx| {
|
||||
let mut isolate = setup();
|
||||
isolate
|
||||
.execute("event_test.js", include_str!("event_test.js"))
|
||||
.unwrap();
|
||||
if let Poll::Ready(Err(_)) = isolate.poll_event_loop(&mut cx) {
|
||||
unreachable!();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_event_error() {
|
||||
run_in_task(|mut cx| {
|
||||
let mut isolate = setup();
|
||||
let result = isolate.execute("foo.js", "new Event()");
|
||||
if let Err(error) = result {
|
||||
let error_string = error.to_string();
|
||||
// Test that the script specifier is a URL: `deno:<repo-relative path>`.
|
||||
assert!(error_string.contains("deno:op_crates/web/02_event.js"));
|
||||
assert!(error_string.contains("TypeError"));
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
if let Poll::Ready(Err(_)) = isolate.poll_event_loop(&mut cx) {
|
||||
unreachable!();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_event_target() {
|
||||
run_in_task(|mut cx| {
|
||||
let mut isolate = setup();
|
||||
isolate
|
||||
.execute("event_target_test.js", include_str!("event_target_test.js"))
|
||||
.unwrap();
|
||||
if let Poll::Ready(Err(_)) = isolate.poll_event_loop(&mut cx) {
|
||||
unreachable!();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
17
op_crates/webidl/Cargo.toml
Normal file
17
op_crates/webidl/Cargo.toml
Normal file
|
@ -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" }
|
6
op_crates/webidl/README.md
Normal file
6
op_crates/webidl/README.md
Normal file
|
@ -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/
|
291
op_crates/webidl/internal.d.ts
vendored
Normal file
291
op_crates/webidl/internal.d.ts
vendored
Normal file
|
@ -0,0 +1,291 @@
|
|||
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||
// deno-lint-ignore-file no-explicit-any ban-types
|
||||
|
||||
/// <reference no-default-lib="true" />
|
||||
/// <reference lib="esnext" />
|
||||
|
||||
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<double>"](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<T>(
|
||||
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<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>(
|
||||
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<K, V>,
|
||||
opts: ValueConverterOpts,
|
||||
) => any;
|
||||
}
|
||||
}
|
||||
}
|
14
op_crates/webidl/lib.rs
Normal file
14
op_crates/webidl/lib.rs
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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" }
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ fn create_snapshot(
|
|||
snapshot_path: &Path,
|
||||
files: Vec<PathBuf>,
|
||||
) {
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
18
runtime/ops/url.rs
Normal file
18
runtime/ops/url.rs
Normal file
|
@ -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,
|
||||
);
|
||||
}
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue