diff options
author | Andreu Botella <abb@randomunok.com> | 2021-08-16 14:29:54 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-16 14:29:54 +0200 |
commit | ddbb7b83f2c483e354f425dfb70dbab494b05ea5 (patch) | |
tree | fa84f5607395773284e331fe32f2b86b59f02a5d | |
parent | d1d2388d7f1a09fd2469b356f00b6b361269a0b7 (diff) |
feat(runtime): support classic workers for internal testing (#11338)
This commit implements classic workers, but only when the `--enable-testing-features-do-not-use` flag is provided. This change is not user facing. Classic workers are used extensively in WPT tests. The classic workers do not support loading from disk, and do not support TypeScript.
Co-authored-by: Luca Casonato <hello@lcas.dev>
-rw-r--r-- | cli/main.rs | 3 | ||||
-rw-r--r-- | cli/standalone.rs | 1 | ||||
-rw-r--r-- | ext/fetch/lib.rs | 4 | ||||
-rw-r--r-- | runtime/examples/hello_runtime.rs | 1 | ||||
-rw-r--r-- | runtime/js/11_workers.js | 31 | ||||
-rw-r--r-- | runtime/js/99_main.js | 46 | ||||
-rw-r--r-- | runtime/ops/mod.rs | 2 | ||||
-rw-r--r-- | runtime/ops/web_worker.rs | 16 | ||||
-rw-r--r-- | runtime/ops/web_worker/sync_fetch.rs | 155 | ||||
-rw-r--r-- | runtime/ops/worker_host.rs | 16 | ||||
-rw-r--r-- | runtime/web_worker.rs | 20 | ||||
-rw-r--r-- | runtime/worker.rs | 4 | ||||
-rwxr-xr-x | tools/wpt.ts | 3 | ||||
-rw-r--r-- | tools/wpt/expectation.json | 197 | ||||
-rw-r--r-- | tools/wpt/runner.ts | 1 |
15 files changed, 485 insertions, 15 deletions
diff --git a/cli/main.rs b/cli/main.rs index e3da6ae0f..ffed7d37a 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -109,6 +109,7 @@ fn create_web_worker_callback( .log_level .map_or(false, |l| l == log::Level::Debug), unstable: program_state.flags.unstable, + enable_testing_features: program_state.flags.enable_testing_features, unsafely_ignore_certificate_errors: program_state .flags .unsafely_ignore_certificate_errors @@ -120,6 +121,7 @@ fn create_web_worker_callback( create_web_worker_cb, js_error_create_fn: Some(js_error_create_fn), use_deno_namespace: args.use_deno_namespace, + worker_type: args.worker_type, maybe_inspector_server, runtime_version: version::deno(), ts_version: version::TYPESCRIPT.to_string(), @@ -193,6 +195,7 @@ pub fn create_main_worker( .log_level .map_or(false, |l| l == log::Level::Debug), unstable: program_state.flags.unstable, + enable_testing_features: program_state.flags.enable_testing_features, unsafely_ignore_certificate_errors: program_state .flags .unsafely_ignore_certificate_errors diff --git a/cli/standalone.rs b/cli/standalone.rs index 013e2e60f..800dca4cb 100644 --- a/cli/standalone.rs +++ b/cli/standalone.rs @@ -253,6 +253,7 @@ pub async fn run( debug_flag: metadata.log_level.map_or(false, |l| l == log::Level::Debug), user_agent: version::get_user_agent(), unstable: metadata.unstable, + enable_testing_features: false, unsafely_ignore_certificate_errors: metadata .unsafely_ignore_certificate_errors, root_cert_store: Some(root_cert_store), diff --git a/ext/fetch/lib.rs b/ext/fetch/lib.rs index eb2fed683..8f49d8859 100644 --- a/ext/fetch/lib.rs +++ b/ext/fetch/lib.rs @@ -52,7 +52,9 @@ use tokio::sync::mpsc; use tokio_stream::wrappers::ReceiverStream; use tokio_util::io::StreamReader; -pub use reqwest; // Re-export reqwest +// Re-export reqwest and data_url +pub use data_url; +pub use reqwest; pub fn init<P: FetchPermissions + 'static>( user_agent: String, diff --git a/runtime/examples/hello_runtime.rs b/runtime/examples/hello_runtime.rs index 776dc23c3..9ac1d0a27 100644 --- a/runtime/examples/hello_runtime.rs +++ b/runtime/examples/hello_runtime.rs @@ -27,6 +27,7 @@ async fn main() -> Result<(), AnyError> { args: vec![], debug_flag: false, unstable: false, + enable_testing_features: false, unsafely_ignore_certificate_errors: None, root_cert_store: None, user_agent: "hello_runtime".to_string(), diff --git a/runtime/js/11_workers.js b/runtime/js/11_workers.js index b5a8a9d0c..2f9413119 100644 --- a/runtime/js/11_workers.js +++ b/runtime/js/11_workers.js @@ -7,7 +7,6 @@ ArrayIsArray, ArrayPrototypeMap, Error, - Uint8Array, StringPrototypeStartsWith, String, SymbolIterator, @@ -28,6 +27,7 @@ useDenoNamespace, permissions, name, + workerType, ) { return core.opSync("op_create_worker", { hasSourceCode, @@ -36,6 +36,7 @@ sourceCode, specifier, useDenoNamespace, + workerType, }); } @@ -183,20 +184,12 @@ } } - if (type !== "module") { - throw new Error( - 'Not yet implemented: only "module" type workers are supported', - ); - } - - this.#name = name; - const hasSourceCode = false; - const sourceCode = core.decode(new Uint8Array()); + const workerType = webidl.converters["WorkerType"](type); if ( StringPrototypeStartsWith(specifier, "./") || StringPrototypeStartsWith(specifier, "../") || - StringPrototypeStartsWith(specifier, "/") || type == "classic" + StringPrototypeStartsWith(specifier, "/") || workerType === "classic" ) { const baseUrl = getLocationHref(); if (baseUrl != null) { @@ -204,6 +197,16 @@ } } + this.#name = name; + let hasSourceCode, sourceCode; + if (workerType === "classic") { + hasSourceCode = true; + sourceCode = `importScripts("#");`; + } else { + hasSourceCode = false; + sourceCode = ""; + } + const id = createWorker( specifier, hasSourceCode, @@ -213,6 +216,7 @@ ? null : parsePermissions(workerDenoAttributes.permissions), options?.name, + workerType, ); this.#id = id; this.#pollControl(); @@ -344,6 +348,11 @@ defineEventHandler(Worker.prototype, "message"); defineEventHandler(Worker.prototype, "messageerror"); + webidl.converters["WorkerType"] = webidl.createEnumConverter("WorkerType", [ + "classic", + "module", + ]); + window.__bootstrap.worker = { parsePermissions, Worker, diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js index 6d5599e71..b1f7d1473 100644 --- a/runtime/js/99_main.js +++ b/runtime/js/99_main.js @@ -8,6 +8,7 @@ delete Object.prototype.__proto__; ((window) => { const core = Deno.core; const { + ArrayPrototypeMap, Error, FunctionPrototypeCall, FunctionPrototypeBind, @@ -164,6 +165,44 @@ delete Object.prototype.__proto__; } } + let loadedMainWorkerScript = false; + + function importScripts(...urls) { + if (core.opSync("op_worker_get_type") === "module") { + throw new TypeError("Can't import scripts in a module worker."); + } + + const baseUrl = location.getLocationHref(); + const parsedUrls = ArrayPrototypeMap(urls, (scriptUrl) => { + try { + return new url.URL(scriptUrl, baseUrl ?? undefined).href; + } catch { + throw new domException.DOMException( + "Failed to parse URL.", + "SyntaxError", + ); + } + }); + + // A classic worker's main script has looser MIME type checks than any + // imported scripts, so we use `loadedMainWorkerScript` to distinguish them. + // TODO(andreubotella) Refactor worker creation so the main script isn't + // loaded with `importScripts()`. + const scripts = core.opSync( + "op_worker_sync_fetch", + parsedUrls, + !loadedMainWorkerScript, + ); + loadedMainWorkerScript = true; + + for (const { url, script } of scripts) { + const err = core.evalContext(script, url)[1]; + if (err !== null) { + throw err.thrown; + } + } + } + function opMainModule() { return core.opSync("op_main_module"); } @@ -597,6 +636,13 @@ delete Object.prototype.__proto__; } ObjectDefineProperties(globalThis, workerRuntimeGlobalProperties); ObjectDefineProperties(globalThis, { name: util.readOnly(name) }); + if (runtimeOptions.enableTestingFeaturesFlag) { + ObjectDefineProperty( + globalThis, + "importScripts", + util.writable(importScripts), + ); + } ObjectSetPrototypeOf(globalThis, DedicatedWorkerGlobalScope.prototype); const consoleFromDeno = globalThis.console; diff --git a/runtime/ops/mod.rs b/runtime/ops/mod.rs index e08ddd1c0..ee2bc0a1e 100644 --- a/runtime/ops/mod.rs +++ b/runtime/ops/mod.rs @@ -84,3 +84,5 @@ pub fn check_unstable2(state: &Rc<RefCell<OpState>>, api_name: &str) { let state = state.borrow(); state.borrow::<UnstableChecker>().check_unstable(api_name) } + +pub struct TestingFeaturesEnabled(pub bool); diff --git a/runtime/ops/web_worker.rs b/runtime/ops/web_worker.rs index 026e38157..8439e4384 100644 --- a/runtime/ops/web_worker.rs +++ b/runtime/ops/web_worker.rs @@ -1,6 +1,9 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. +mod sync_fetch; + use crate::web_worker::WebWorkerInternalHandle; +use crate::web_worker::WebWorkerType; use crate::web_worker::WorkerControlEvent; use deno_core::error::generic_error; use deno_core::error::AnyError; @@ -13,6 +16,8 @@ use deno_web::JsMessageData; use std::cell::RefCell; use std::rc::Rc; +use self::sync_fetch::op_worker_sync_fetch; + pub fn init() -> Extension { Extension::builder() .ops(vec![ @@ -25,6 +30,8 @@ pub fn init() -> Extension { "op_worker_unhandled_error", op_sync(op_worker_unhandled_error), ), + ("op_worker_get_type", op_sync(op_worker_get_type)), + ("op_worker_sync_fetch", op_sync(op_worker_sync_fetch)), ]) .build() } @@ -79,3 +86,12 @@ fn op_worker_unhandled_error( .expect("Failed to propagate error event to parent worker"); Ok(()) } + +fn op_worker_get_type( + state: &mut OpState, + _: (), + _: (), +) -> Result<WebWorkerType, AnyError> { + let handle = state.borrow::<WebWorkerInternalHandle>().clone(); + Ok(handle.worker_type) +} diff --git a/runtime/ops/web_worker/sync_fetch.rs b/runtime/ops/web_worker/sync_fetch.rs new file mode 100644 index 000000000..6ad6edba7 --- /dev/null +++ b/runtime/ops/web_worker/sync_fetch.rs @@ -0,0 +1,155 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. + +use crate::web_worker::WebWorkerInternalHandle; +use crate::web_worker::WebWorkerType; +use deno_core::error::type_error; +use deno_core::error::AnyError; +use deno_core::url::Url; +use deno_core::OpState; +use deno_fetch::data_url::DataUrl; +use deno_fetch::reqwest; +use deno_web::BlobStore; +use deno_websocket::DomExceptionNetworkError; +use hyper::body::Bytes; +use serde::{Deserialize, Serialize}; +use tokio::task::JoinHandle; + +// TODO(andreubotella) Properly parse the MIME type +fn mime_type_essence(mime_type: &str) -> String { + let essence = match mime_type.split_once(";") { + Some((essence, _)) => essence, + None => mime_type, + }; + essence.trim().to_ascii_lowercase() +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SyncFetchScript { + url: String, + script: String, +} + +pub fn op_worker_sync_fetch( + state: &mut OpState, + scripts: Vec<String>, + mut loose_mime_checks: bool, +) -> Result<Vec<SyncFetchScript>, AnyError> { + let handle = state.borrow::<WebWorkerInternalHandle>().clone(); + assert_eq!(handle.worker_type, WebWorkerType::Classic); + + // TODO(andreubotella) Make the runtime into a resource and add a new op to + // block on each request, so a script can run while the next loads. + + let runtime = tokio::runtime::Builder::new_current_thread() + .enable_io() + .enable_time() + .build() + .unwrap(); + + // TODO(andreubotella) It's not good to throw an exception related to blob + // URLs when none of the script URLs use the blob scheme. + // Also, in which contexts are blob URLs not supported? + let blob_store = state.try_borrow::<BlobStore>().ok_or_else(|| { + type_error("Blob URLs are not supported in this context.") + })?; + + let handles: Vec<_> = scripts + .into_iter() + .map(|script| -> JoinHandle<Result<SyncFetchScript, AnyError>> { + let blob_store = blob_store.clone(); + runtime.spawn(async move { + let script_url = + Url::parse(&script).map_err(|_| type_error("Invalid script URL"))?; + + let (body, mime_type, res_url) = match script_url.scheme() { + "http" | "https" => { + let resp = reqwest::get(script_url).await?.error_for_status()?; + + let res_url = resp.url().to_string(); + + // TODO(andreubotella) Properly run fetch's "extract a MIME type". + let mime_type = resp + .headers() + .get("Content-Type") + .and_then(|v| v.to_str().ok()) + .map(mime_type_essence); + + // Always check the MIME type with HTTP(S). + loose_mime_checks = false; + + let body = resp.bytes().await?; + + (body, mime_type, res_url) + } + "data" => { + let data_url = DataUrl::process(&script) + .map_err(|e| type_error(format!("{:?}", e)))?; + + let mime_type = { + let mime = data_url.mime_type(); + format!("{}/{}", mime.type_, mime.subtype) + }; + + let (body, _) = data_url + .decode_to_vec() + .map_err(|e| type_error(format!("{:?}", e)))?; + + (Bytes::from(body), Some(mime_type), script) + } + "blob" => { + let blob = blob_store + .get_object_url(script_url)? + .ok_or_else(|| type_error("Blob for the given URL not found."))?; + + let mime_type = mime_type_essence(&blob.media_type); + + let body = blob.read_all().await?; + + (Bytes::from(body), Some(mime_type), script) + } + _ => { + return Err(type_error(format!( + "Classic scripts with scheme {}: are not supported in workers.", + script_url.scheme() + ))) + } + }; + + if !loose_mime_checks { + // TODO(andreubotella) Check properly for a Javascript MIME type. + match mime_type.as_deref() { + Some("application/javascript" | "text/javascript") => {} + Some(mime_type) => { + return Err( + DomExceptionNetworkError { + msg: format!("Invalid MIME type {:?}.", mime_type), + } + .into(), + ) + } + None => { + return Err( + DomExceptionNetworkError::new("Missing MIME type.").into(), + ) + } + } + } + + let (text, _) = encoding_rs::UTF_8.decode_with_bom_removal(&body); + + Ok(SyncFetchScript { + url: res_url, + script: text.into_owned(), + }) + }) + }) + .collect(); + + let mut ret = Vec::with_capacity(handles.len()); + for handle in handles { + let script = runtime.block_on(handle)??; + ret.push(script); + } + Ok(ret) +} diff --git a/runtime/ops/worker_host.rs b/runtime/ops/worker_host.rs index 5315ff5c7..d80a39502 100644 --- a/runtime/ops/worker_host.rs +++ b/runtime/ops/worker_host.rs @@ -1,5 +1,6 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. +use crate::ops::TestingFeaturesEnabled; use crate::permissions::resolve_read_allowlist; use crate::permissions::resolve_write_allowlist; use crate::permissions::EnvDescriptor; @@ -16,6 +17,7 @@ use crate::web_worker::run_web_worker; use crate::web_worker::SendableWebWorkerHandle; use crate::web_worker::WebWorker; use crate::web_worker::WebWorkerHandle; +use crate::web_worker::WebWorkerType; use crate::web_worker::WorkerControlEvent; use crate::web_worker::WorkerId; use deno_core::error::custom_error; @@ -48,6 +50,7 @@ pub struct CreateWebWorkerArgs { pub permissions: Permissions, pub main_module: ModuleSpecifier, pub use_deno_namespace: bool, + pub worker_type: WebWorkerType, } pub type CreateWebWorkerCb = dyn Fn(CreateWebWorkerArgs) -> (WebWorker, SendableWebWorkerHandle) @@ -460,6 +463,7 @@ pub struct CreateWorkerArgs { source_code: String, specifier: String, use_deno_namespace: bool, + worker_type: WebWorkerType, } /// Create worker as the host @@ -479,6 +483,17 @@ fn op_create_worker( if use_deno_namespace { super::check_unstable(state, "Worker.deno.namespace"); } + let worker_type = args.worker_type; + if let WebWorkerType::Classic = worker_type { + if let TestingFeaturesEnabled(false) = state.borrow() { + return Err( + deno_webstorage::DomExceptionNotSupportedError::new( + "Classic workers are not supported.", + ) + .into(), + ); + } + } let parent_permissions = state.borrow::<Permissions>().clone(); let worker_permissions = if let Some(permissions) = args.permissions { super::check_unstable(state, "Worker.deno.permissions"); @@ -518,6 +533,7 @@ fn op_create_worker( permissions: worker_permissions, main_module: module_specifier.clone(), use_deno_namespace, + worker_type, }); // Send thread safe handle from newly created worker to host thread diff --git a/runtime/web_worker.rs b/runtime/web_worker.rs index 495fedb81..240d79d1f 100644 --- a/runtime/web_worker.rs +++ b/runtime/web_worker.rs @@ -44,6 +44,13 @@ use std::sync::Arc; use std::task::Context; use std::task::Poll; +#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum WebWorkerType { + Classic, + Module, +} + #[derive( Debug, Default, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, )] @@ -110,6 +117,7 @@ pub struct WebWorkerInternalHandle { pub cancel: Rc<CancelHandle>, terminated: Arc<AtomicBool>, isolate_handle: v8::IsolateHandle, + pub worker_type: WebWorkerType, } impl WebWorkerInternalHandle { @@ -215,6 +223,7 @@ impl WebWorkerHandle { fn create_handles( isolate_handle: v8::IsolateHandle, + worker_type: WebWorkerType, ) -> (WebWorkerInternalHandle, SendableWebWorkerHandle) { let (parent_port, worker_port) = create_entangled_message_port(); let (ctrl_tx, ctrl_rx) = mpsc::channel::<WorkerControlEvent>(1); @@ -225,6 +234,7 @@ fn create_handles( terminated: terminated.clone(), isolate_handle: isolate_handle.clone(), cancel: CancelHandle::new_rc(), + worker_type, }; let external_handle = SendableWebWorkerHandle { receiver: ctrl_rx, @@ -245,6 +255,7 @@ pub struct WebWorker { pub name: String, internal_handle: WebWorkerInternalHandle, pub use_deno_namespace: bool, + pub worker_type: WebWorkerType, pub main_module: ModuleSpecifier, } @@ -253,6 +264,7 @@ pub struct WebWorkerOptions { pub args: Vec<String>, pub debug_flag: bool, pub unstable: bool, + pub enable_testing_features: bool, pub unsafely_ignore_certificate_errors: Option<Vec<String>>, pub root_cert_store: Option<RootCertStore>, pub user_agent: String, @@ -261,6 +273,7 @@ pub struct WebWorkerOptions { pub create_web_worker_cb: Arc<ops::worker_host::CreateWebWorkerCb>, pub js_error_create_fn: Option<Rc<JsErrorCreateFn>>, pub use_deno_namespace: bool, + pub worker_type: WebWorkerType, pub maybe_inspector_server: Option<Arc<InspectorServer>>, pub apply_source_maps: bool, /// Sets `Deno.version.deno` in JS runtime. @@ -286,10 +299,12 @@ impl WebWorker { ) -> (Self, SendableWebWorkerHandle) { // Permissions: many ops depend on this let unstable = options.unstable; + let enable_testing_features = options.enable_testing_features; let perm_ext = Extension::builder() .state(move |state| { state.put::<Permissions>(permissions.clone()); state.put(ops::UnstableChecker { unstable }); + state.put(ops::TestingFeaturesEnabled(enable_testing_features)); Ok(()) }) .build(); @@ -386,7 +401,8 @@ impl WebWorker { let (internal_handle, external_handle) = { let handle = js_runtime.v8_isolate().thread_safe_handle(); - let (internal_handle, external_handle) = create_handles(handle); + let (internal_handle, external_handle) = + create_handles(handle, options.worker_type); let op_state = js_runtime.op_state(); let mut op_state = op_state.borrow_mut(); op_state.put(internal_handle.clone()); @@ -400,6 +416,7 @@ impl WebWorker { name, internal_handle, use_deno_namespace: options.use_deno_namespace, + worker_type: options.worker_type, main_module, }, external_handle, @@ -418,6 +435,7 @@ impl WebWorker { "target": env!("TARGET"), "tsVersion": options.ts_version, "unstableFlag": options.unstable, + "enableTestingFeaturesFlag": options.enable_testing_features, "v8Version": deno_core::v8_version(), "location": self.main_module, "cpuCount": options.cpu_count, diff --git a/runtime/worker.rs b/runtime/worker.rs index b200ef08e..b1096024b 100644 --- a/runtime/worker.rs +++ b/runtime/worker.rs @@ -50,6 +50,7 @@ pub struct WorkerOptions { pub args: Vec<String>, pub debug_flag: bool, pub unstable: bool, + pub enable_testing_features: bool, pub unsafely_ignore_certificate_errors: Option<Vec<String>>, pub root_cert_store: Option<RootCertStore>, pub user_agent: String, @@ -84,10 +85,12 @@ impl MainWorker { ) -> Self { // Permissions: many ops depend on this let unstable = options.unstable; + let enable_testing_features = options.enable_testing_features; let perm_ext = Extension::builder() .state(move |state| { state.put::<Permissions>(permissions.clone()); state.put(ops::UnstableChecker { unstable }); + state.put(ops::TestingFeaturesEnabled(enable_testing_features)); Ok(()) }) .build(); @@ -304,6 +307,7 @@ mod tests { args: vec![], debug_flag: false, unstable: false, + enable_testing_features: false, unsafely_ignore_certificate_errors: None, root_cert_store: None, seed: None, diff --git a/tools/wpt.ts b/tools/wpt.ts index a3999a425..4ebe875c9 100755 --- a/tools/wpt.ts +++ b/tools/wpt.ts @@ -647,7 +647,8 @@ function discoverTestsToRun( const url = new URL(path, "http://web-platform.test:8000"); if ( !url.pathname.endsWith(".any.html") && - !url.pathname.endsWith(".window.html") + !url.pathname.endsWith(".window.html") && + !url.pathname.endsWith(".worker.html") ) { continue; } diff --git a/tools/wpt/expectation.json b/tools/wpt/expectation.json index 0618d6a39..c38b1ad3e 100644 --- a/tools/wpt/expectation.json +++ b/tools/wpt/expectation.json @@ -16611,5 +16611,200 @@ "constructor.any.html?wss": true } } + }, + "workers": { + "Worker-base64.any.worker.html": true, + "Worker-call.worker.html": true, + "Worker-constructor-proto.any.worker.html": true, + "Worker-custom-event.any.worker.html": true, + "Worker-formdata.any.worker.html": [ + "Test FormData interface object" + ], + "Worker-location.sub.any.worker.html": [ + "Test WorkerLocation properties." + ], + "Worker-replace-event-handler.any.worker.html": true, + "Worker-replace-global-constructor.any.worker.html": true, + "Worker-replace-self.any.worker.html": true, + "WorkerGlobalScope_requestAnimationFrame.tentative.worker.html": [ + "WorkerGlobalScope_requestAnimationFrame" + ], + "WorkerLocation-origin.sub.window.html": [ + "workerLocation.origin must use ASCII code points" + ], + "WorkerNavigator-hardware-concurrency.any.worker.html": [ + "Test worker navigator hardware concurrency." + ], + "WorkerNavigator.any.worker.html": [ + "Testing Navigator properties on workers." + ], + "constructors": { + "Worker": { + "DedicatedWorkerGlobalScope-members.worker.html": [ + "existence of onoffline", + "existence of ononline" + ], + "expected-self-properties.worker.html": [ + "existence of XMLHttpRequest", + "existence of EventSource", + "existence of SharedWorker" + ], + "unexpected-self-properties.worker.html": true + } + }, + "dedicated-worker-from-blob-url.window.html": [ + "Creating a dedicated worker from a blob URL works immediately before revoking." + ], + "dedicated-worker-in-data-url-context.window.html": [ + "Create a dedicated worker in a data url frame", + "Create a dedicated worker in a data url dedicated worker", + "Create a data url dedicated worker in a data url frame" + ], + "examples": { + "general.any.worker.html": true, + "general.worker.html": true + }, + "importscripts_mime.any.worker.html": [ + "importScripts() requires scripty MIME types: text/ecmascript is allowed." + ], + "interfaces": { + "DedicatedWorkerGlobalScope": { + "EventTarget.worker.html": true, + "onmessage.worker.html": [ + "Setting onmessage to 1", + "Setting onmessage to 1 (again)" + ], + "postMessage": { + "return-value.worker.html": true + } + }, + "WorkerGlobalScope": { + "location": { + "returns-same-object.any.worker.html": true + }, + "self.any.worker.html": true + }, + "WorkerUtils": { + "importScripts": { + "001.worker.html": true, + "002.worker.html": true, + "catch.sub.any.worker.html": [ + "Cross-origin syntax error", + "Cross-origin throw", + "Redirect-to-cross-origin syntax error", + "Redirect-to-Cross-origin throw" + ], + "report-error-cross-origin.sub.any.worker.html": false, + "report-error-redirect-to-cross-origin.sub.any.worker.html": false, + "report-error-same-origin.sub.any.worker.html": false, + "report-error-setTimeout-cross-origin.sub.any.worker.html": false, + "report-error-setTimeout-redirect-to-cross-origin.sub.any.worker.html": false, + "report-error-setTimeout-same-origin.sub.any.worker.html": false + } + } + }, + "modules": { + "dedicated-worker-import-blob-url.any.html": true, + "dedicated-worker-import-blob-url.any.worker.html": true, + "dedicated-worker-import-data-url.any.html": true, + "dedicated-worker-import-data-url.any.worker.html": true, + "dedicated-worker-import.any.html": true, + "dedicated-worker-import.any.worker.html": true, + "shared-worker-import-blob-url.window.html": [ + "Static import.", + "Static import (cross-origin).", + "Static import (redirect).", + "Nested static import.", + "Static import and then dynamic import.", + "Dynamic import.", + "Nested dynamic import.", + "Dynamic import and then static import.", + "eval(import())." + ], + "shared-worker-import-data-url.window.html": [ + "Static import.", + "Static import (cross-origin).", + "Static import (redirect).", + "Nested static import.", + "Static import and then dynamic import.", + "Dynamic import.", + "Nested dynamic import.", + "Dynamic import and then static import.", + "eval(import())." + ], + "shared-worker-import.window.html": [ + "Static import.", + "Static import (cross-origin).", + "Static import (redirect).", + "Nested static import.", + "Static import and then dynamic import.", + "Dynamic import.", + "Nested dynamic import.", + "Dynamic import and then static import.", + "eval(import())." + ] + }, + "nested_worker.worker.html": true, + "nested_worker_close_self.worker.html": true, + "nested_worker_importScripts.worker.html": true, + "nested_worker_sync_xhr.worker.html": [ + "Nested worker that issues a sync XHR" + ], + "semantics": { + "encodings": { + "004.worker.html": true + }, + "interface-objects": { + "001.worker.html": [ + "The SharedWorker interface object should be exposed.", + "The ImageData interface object should be exposed.", + "The ImageBitmap interface object should be exposed.", + "The CanvasGradient interface object should be exposed.", + "The CanvasPattern interface object should be exposed.", + "The CanvasPath interface object should be exposed.", + "The TextMetrics interface object should be exposed.", + "The Path2D interface object should be exposed.", + "The PromiseRejectionEvent interface object should be exposed.", + "The EventSource interface object should be exposed.", + "The XMLHttpRequestEventTarget interface object should be exposed.", + "The XMLHttpRequestUpload interface object should be exposed.", + "The XMLHttpRequest interface object should be exposed.", + "The FileList interface object should be exposed.", + "The FileReaderSync interface object should be exposed.", + "The IDBRequest interface object should be exposed.", + "The IDBOpenDBRequest interface object should be exposed.", + "The IDBVersionChangeEvent interface object should be exposed.", + "The IDBFactory interface object should be exposed.", + "The IDBDatabase interface object should be exposed.", + "The IDBObjectStore interface object should be exposed.", + "The IDBIndex interface object should be exposed.", + "The IDBKeyRange interface object should be exposed.", + "The IDBCursor interface object should be exposed.", + "The IDBCursorWithValue interface object should be exposed.", + "The IDBTransaction interface object should be exposed." + ], + "002.worker.html": true + }, + "multiple-workers": { + "exposure.any.html": [ + "SharedWorker exposure" + ], + "exposure.any.worker.html": true + } + }, + "shared-worker-from-blob-url.window.html": [ + "Creating a shared worker from a blob URL works.", + "Creating a shared worker from a blob URL works immediately before revoking.", + "Connecting to a shared worker on a revoked blob URL works." + ], + "shared-worker-in-data-url-context.window.html": [ + "Create a shared worker in a data url frame", + "Create a data url shared worker in a data url frame" + ], + "worker-performance.worker.html": [ + "Resource timing seems to work in workers", + "performance.clearResourceTimings in workers", + "performance.setResourceTimingBufferSize in workers" + ] } -}
\ No newline at end of file +} diff --git a/tools/wpt/runner.ts b/tools/wpt/runner.ts index 07edcec68..27b94da1f 100644 --- a/tools/wpt/runner.ts +++ b/tools/wpt/runner.ts @@ -94,6 +94,7 @@ export async function runSingleTest( "run", "-A", "--unstable", + "--enable-testing-features-do-not-use", "--location", url.toString(), "--cert", |