diff options
95 files changed, 2001 insertions, 284 deletions
diff --git a/.gitignore b/.gitignore index 73c2fce6cda..630eb63b9bb 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,9 @@ webrender-captures/ Session.vim Sessionx.vim +# Zed +/.zed + /unminified-js /unminified-css diff --git a/Cargo.lock b/Cargo.lock index 2ced6f8fe76..0d5553c9c73 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2027,9 +2027,9 @@ dependencies = [ [[package]] name = "error-code" -version = "3.3.1" +version = "3.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f" +checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" [[package]] name = "etagere" @@ -8557,6 +8557,7 @@ dependencies = [ "glow", "half", "ipc-channel", + "itertools 0.14.0", "log", "pixels", "snapshot", diff --git a/components/config/prefs.rs b/components/config/prefs.rs index 96c40c91360..a9ec112e3eb 100644 --- a/components/config/prefs.rs +++ b/components/config/prefs.rs @@ -236,6 +236,8 @@ pub struct Preferences { /// The user-agent to use for Servo. This can also be set via [`UserAgentPlatform`] in /// order to set the value to the default value for the given platform. pub user_agent: String, + + pub log_filter: String, } impl Preferences { @@ -398,6 +400,7 @@ impl Preferences { threadpools_webrender_workers_max: 4, webgl_testing_context_creation_error: false, user_agent: String::new(), + log_filter: String::new(), } } } diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index e3590461604..a4b05e7f445 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -4321,7 +4321,7 @@ impl Document { }, }; - self.global().report_csp_violations(violations); + self.global().report_csp_violations(violations, Some(el)); result } diff --git a/components/script/dom/event.rs b/components/script/dom/event.rs index e199e12f655..743ced42a4b 100644 --- a/components/script/dom/event.rs +++ b/components/script/dom/event.rs @@ -1040,14 +1040,39 @@ impl From<bool> for EventCancelable { } impl From<EventCancelable> for bool { - fn from(bubbles: EventCancelable) -> Self { - match bubbles { + fn from(cancelable: EventCancelable) -> Self { + match cancelable { EventCancelable::Cancelable => true, EventCancelable::NotCancelable => false, } } } +#[derive(Clone, Copy, MallocSizeOf, PartialEq)] +pub(crate) enum EventComposed { + Composed, + NotComposed, +} + +impl From<bool> for EventComposed { + fn from(boolean: bool) -> Self { + if boolean { + EventComposed::Composed + } else { + EventComposed::NotComposed + } + } +} + +impl From<EventComposed> for bool { + fn from(composed: EventComposed) -> Self { + match composed { + EventComposed::Composed => true, + EventComposed::NotComposed => false, + } + } +} + #[derive(Clone, Copy, Debug, Eq, JSTraceable, PartialEq)] #[repr(u16)] #[derive(MallocSizeOf)] diff --git a/components/script/dom/eventsource.rs b/components/script/dom/eventsource.rs index 273abda0a02..7cf7bd6106f 100644 --- a/components/script/dom/eventsource.rs +++ b/components/script/dom/eventsource.rs @@ -448,7 +448,7 @@ impl FetchResponseListener for EventSourceContext { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { let global = &self.resource_timing_global(); - global.report_csp_violations(violations); + global.report_csp_violations(violations, None); } } diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index 98c4c3ed53d..902d4622db9 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -106,6 +106,7 @@ use crate::dom::crypto::Crypto; use crate::dom::dedicatedworkerglobalscope::{ DedicatedWorkerControlMsg, DedicatedWorkerGlobalScope, }; +use crate::dom::element::Element; use crate::dom::errorevent::ErrorEvent; use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus}; use crate::dom::eventsource::EventSource; @@ -115,6 +116,7 @@ use crate::dom::htmlscriptelement::{ScriptId, SourceCode}; use crate::dom::imagebitmap::ImageBitmap; use crate::dom::messageevent::MessageEvent; use crate::dom::messageport::MessagePort; +use crate::dom::node::Node; use crate::dom::paintworkletglobalscope::PaintWorkletGlobalScope; use crate::dom::performance::Performance; use crate::dom::performanceobserver::VALID_ENTRY_TYPES; @@ -2930,7 +2932,7 @@ impl GlobalScope { let (is_js_evaluation_allowed, violations) = csp_list.is_js_evaluation_allowed(source); - self.report_csp_violations(violations); + self.report_csp_violations(violations, None); is_js_evaluation_allowed == CheckResult::Allowed } @@ -2957,7 +2959,7 @@ impl GlobalScope { let (result, violations) = csp_list.should_navigation_request_be_blocked(&request, NavigationCheckType::Other); - self.report_csp_violations(violations); + self.report_csp_violations(violations, None); result == CheckResult::Blocked } @@ -3444,8 +3446,13 @@ impl GlobalScope { unreachable!(); } + /// <https://www.w3.org/TR/CSP/#report-violation> #[allow(unsafe_code)] - pub(crate) fn report_csp_violations(&self, violations: Vec<Violation>) { + pub(crate) fn report_csp_violations( + &self, + violations: Vec<Violation>, + element: Option<&Element>, + ) { let scripted_caller = unsafe { describe_scripted_caller(*GlobalScope::get_cx()) }.unwrap_or_default(); for violation in violations { @@ -3471,7 +3478,38 @@ impl GlobalScope { .line_number(scripted_caller.line) .column_number(scripted_caller.col + 1) .build(self); - let task = CSPViolationReportTask::new(self, report); + // Step 1: Let global be violation’s global object. + // We use `self` as `global`; + // Step 2: Let target be violation’s element. + let target = element.and_then(|event_target| { + // Step 3.1: If target is not null, and global is a Window, + // and target’s shadow-including root is not global’s associated Document, set target to null. + if let Some(window) = self.downcast::<Window>() { + if !window + .Document() + .upcast::<Node>() + .is_shadow_including_inclusive_ancestor_of(event_target.upcast()) + { + return None; + } + } + Some(event_target) + }); + let target = match target { + // Step 3.2: If target is null: + None => { + // Step 3.2.2: If target is a Window, set target to target’s associated Document. + if let Some(window) = self.downcast::<Window>() { + Trusted::new(window.Document().upcast()) + } else { + // Step 3.2.1: Set target to violation’s global object. + Trusted::new(self.upcast()) + } + }, + Some(event_target) => Trusted::new(event_target.upcast()), + }; + // Step 3: Queue a task to run the following steps: + let task = CSPViolationReportTask::new(Trusted::new(self), target, report); self.task_manager() .dom_manipulation_task_source() .queue(task); diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index e0c8e9ef726..a79c7f6e463 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -298,7 +298,7 @@ impl FetchResponseListener for ImageContext { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { let global = &self.resource_timing_global(); - global.report_csp_violations(violations); + global.report_csp_violations(violations, None); } } diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs index 51aa6bee286..18bd426acdb 100644 --- a/components/script/dom/htmllinkelement.rs +++ b/components/script/dom/htmllinkelement.rs @@ -773,7 +773,7 @@ impl FetchResponseListener for PrefetchContext { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { let global = &self.resource_timing_global(); - global.report_csp_violations(violations); + global.report_csp_violations(violations, None); } } diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index 361c22c1250..391da272ef3 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -2951,7 +2951,7 @@ impl FetchResponseListener for HTMLMediaElementFetchListener { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { let global = &self.resource_timing_global(); - global.report_csp_violations(violations); + global.report_csp_violations(violations, None); } } diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index 777b30d1e63..4ee1397b4ed 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -546,7 +546,8 @@ impl FetchResponseListener for ClassicContext { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { let global = &self.resource_timing_global(); - global.report_csp_violations(violations); + let elem = self.elem.root(); + global.report_csp_violations(violations, Some(elem.upcast::<Element>())); } } diff --git a/components/script/dom/htmlvideoelement.rs b/components/script/dom/htmlvideoelement.rs index 6f27c164d02..c5d21c19d9b 100644 --- a/components/script/dom/htmlvideoelement.rs +++ b/components/script/dom/htmlvideoelement.rs @@ -422,7 +422,7 @@ impl FetchResponseListener for PosterFrameFetchContext { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { let global = &self.resource_timing_global(); - global.report_csp_violations(violations); + global.report_csp_violations(violations, None); } } diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 4bc272db8dd..1622cf57b79 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -631,6 +631,8 @@ pub(crate) mod webgpu; pub(crate) use self::webgpu::*; #[cfg(not(feature = "webgpu"))] pub(crate) mod gpucanvascontext; +pub(crate) mod transformstream; +pub(crate) mod transformstreamdefaultcontroller; pub(crate) mod wheelevent; #[allow(dead_code)] pub(crate) mod window; diff --git a/components/script/dom/notification.rs b/components/script/dom/notification.rs index 4dbb97430e5..1aecb785475 100644 --- a/components/script/dom/notification.rs +++ b/components/script/dom/notification.rs @@ -795,7 +795,7 @@ impl FetchResponseListener for ResourceFetchListener { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { let global = &self.resource_timing_global(); - global.report_csp_violations(violations); + global.report_csp_violations(violations, None); } } diff --git a/components/script/dom/readablestreamdefaultcontroller.rs b/components/script/dom/readablestreamdefaultcontroller.rs index c52fb712a03..80c800d1bbe 100644 --- a/components/script/dom/readablestreamdefaultcontroller.rs +++ b/components/script/dom/readablestreamdefaultcontroller.rs @@ -383,7 +383,6 @@ impl ReadableStreamDefaultController { } /// <https://streams.spec.whatwg.org/#set-up-readable-stream-default-controller> - #[allow(unsafe_code)] pub(crate) fn setup( &self, stream: DomRoot<ReadableStream>, @@ -866,7 +865,6 @@ impl ReadableStreamDefaultController { } /// <https://streams.spec.whatwg.org/#rs-default-controller-has-backpressure> - #[allow(unused)] pub(crate) fn has_backpressure(&self) -> bool { // If ! ReadableStreamDefaultControllerShouldCallPull(controller) is true, return false. // Otherwise, return true. diff --git a/components/script/dom/readablestreamgenericreader.rs b/components/script/dom/readablestreamgenericreader.rs index 8ba1149bcb5..d2a109ee692 100644 --- a/components/script/dom/readablestreamgenericreader.rs +++ b/components/script/dom/readablestreamgenericreader.rs @@ -80,7 +80,6 @@ pub(crate) trait ReadableStreamGenericReader { } /// <https://streams.spec.whatwg.org/#readable-stream-reader-generic-release> - #[allow(unsafe_code)] fn generic_release(&self, can_gc: CanGc) -> Fallible<()> { // Let stream be reader.[[stream]]. diff --git a/components/script/dom/securitypolicyviolationevent.rs b/components/script/dom/securitypolicyviolationevent.rs index 3580e525e55..3c528cc5814 100644 --- a/components/script/dom/securitypolicyviolationevent.rs +++ b/components/script/dom/securitypolicyviolationevent.rs @@ -15,7 +15,7 @@ use crate::dom::bindings::codegen::Bindings::SecurityPolicyViolationEventBinding use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::str::{DOMString, USVString}; -use crate::dom::event::{Event, EventBubbles, EventCancelable}; +use crate::dom::event::{Event, EventBubbles, EventCancelable, EventComposed}; use crate::dom::globalscope::GlobalScope; use crate::script_runtime::CanGc; @@ -70,12 +70,14 @@ impl SecurityPolicyViolationEvent { ) } + #[allow(clippy::too_many_arguments)] fn new_with_proto( global: &GlobalScope, proto: Option<HandleObject>, type_: Atom, bubbles: EventBubbles, cancelable: EventCancelable, + composed: EventComposed, init: &SecurityPolicyViolationEventInit, can_gc: CanGc, ) -> DomRoot<Self> { @@ -83,6 +85,7 @@ impl SecurityPolicyViolationEvent { { let event = ev.upcast::<Event>(); event.init_event(type_, bool::from(bubbles), bool::from(cancelable)); + event.set_composed(bool::from(composed)); } ev } @@ -92,10 +95,13 @@ impl SecurityPolicyViolationEvent { type_: Atom, bubbles: EventBubbles, cancelable: EventCancelable, + composed: EventComposed, init: &SecurityPolicyViolationEventInit, can_gc: CanGc, ) -> DomRoot<Self> { - Self::new_with_proto(global, None, type_, bubbles, cancelable, init, can_gc) + Self::new_with_proto( + global, None, type_, bubbles, cancelable, composed, init, can_gc, + ) } } @@ -115,6 +121,7 @@ impl SecurityPolicyViolationEventMethods<crate::DomTypeHolder> for SecurityPolic Atom::from(type_), EventBubbles::from(init.parent.bubbles), EventCancelable::from(init.parent.cancelable), + EventComposed::from(init.parent.composed), init, can_gc, ) diff --git a/components/script/dom/servoparser/mod.rs b/components/script/dom/servoparser/mod.rs index 3a1efdfb291..9e45124522a 100644 --- a/components/script/dom/servoparser/mod.rs +++ b/components/script/dom/servoparser/mod.rs @@ -1075,7 +1075,8 @@ impl FetchResponseListener for ParserContext { }; let document = &parser.document; let global = &document.global(); - global.report_csp_violations(violations); + // TODO(https://github.com/w3c/webappsec-csp/issues/687): Update after spec is resolved + global.report_csp_violations(violations, None); } } diff --git a/components/script/dom/transformstream.rs b/components/script/dom/transformstream.rs new file mode 100644 index 00000000000..023fe7ac483 --- /dev/null +++ b/components/script/dom/transformstream.rs @@ -0,0 +1,999 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use std::cell::Cell; +use std::ptr::{self}; +use std::rc::Rc; + +use dom_struct::dom_struct; +use js::jsapi::{Heap, IsPromiseObject, JSObject}; +use js::jsval::{JSVal, ObjectValue, UndefinedValue}; +use js::rust::{HandleObject as SafeHandleObject, HandleValue as SafeHandleValue, IntoHandle}; +use script_bindings::callback::ExceptionHandling; +use script_bindings::realms::InRealm; + +use super::bindings::codegen::Bindings::QueuingStrategyBinding::QueuingStrategySize; +use super::promisenativehandler::Callback; +use super::types::{TransformStreamDefaultController, WritableStream}; +use crate::dom::bindings::cell::DomRefCell; +use crate::dom::bindings::codegen::Bindings::QueuingStrategyBinding::QueuingStrategy; +use crate::dom::bindings::codegen::Bindings::TransformStreamBinding::TransformStreamMethods; +use crate::dom::bindings::codegen::Bindings::TransformerBinding::Transformer; +use crate::dom::bindings::conversions::ConversionResult; +use crate::dom::bindings::error::{Error, Fallible}; +use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object_with_proto}; +use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom}; +use crate::dom::countqueuingstrategy::{extract_high_water_mark, extract_size_algorithm}; +use crate::dom::globalscope::GlobalScope; +use crate::dom::promise::Promise; +use crate::dom::readablestream::{ReadableStream, create_readable_stream}; +use crate::dom::types::PromiseNativeHandler; +use crate::dom::underlyingsourcecontainer::UnderlyingSourceType; +use crate::dom::writablestream::create_writable_stream; +use crate::dom::writablestreamdefaultcontroller::UnderlyingSinkType; +use crate::realms::enter_realm; +use crate::script_runtime::{CanGc, JSContext as SafeJSContext}; + +impl js::gc::Rootable for TransformBackPressureChangePromiseFulfillment {} + +/// Reacting to backpressureChangePromise as part of +/// <https://streams.spec.whatwg.org/#transform-stream-default-sink-write-algorithm> +#[derive(JSTraceable, MallocSizeOf)] +#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)] +struct TransformBackPressureChangePromiseFulfillment { + /// The result of reacting to backpressureChangePromise. + #[ignore_malloc_size_of = "Rc is hard"] + result_promise: Rc<Promise>, + + #[ignore_malloc_size_of = "mozjs"] + chunk: Box<Heap<JSVal>>, + + /// The writable used in the fulfillment steps + writable: Dom<WritableStream>, + + controller: Dom<TransformStreamDefaultController>, +} + +impl Callback for TransformBackPressureChangePromiseFulfillment { + /// Reacting to backpressureChangePromise with the following fulfillment steps: + fn callback(&self, cx: SafeJSContext, _v: SafeHandleValue, _realm: InRealm, can_gc: CanGc) { + // Let writable be stream.[[writable]]. + // Let state be writable.[[state]]. + // If state is "erroring", throw writable.[[storedError]]. + if self.writable.is_erroring() { + rooted!(in(*cx) let mut error = UndefinedValue()); + self.writable.get_stored_error(error.handle_mut()); + self.result_promise.reject(cx, error.handle(), can_gc); + return; + } + + // Assert: state is "writable". + assert!(self.writable.is_writable()); + + // Return ! TransformStreamDefaultControllerPerformTransform(controller, chunk). + rooted!(in(*cx) let mut chunk = UndefinedValue()); + chunk.set(self.chunk.get()); + let transform_result = self + .controller + .transform_stream_default_controller_perform_transform( + cx, + &self.writable.global(), + chunk.handle(), + can_gc, + ) + .expect("perform transform failed"); + + // PerformTransformFulfillment and PerformTransformRejection do not need + // to be rooted because they only contain an Rc. + let handler = PromiseNativeHandler::new( + &self.writable.global(), + Some(Box::new(PerformTransformFulfillment { + result_promise: self.result_promise.clone(), + })), + Some(Box::new(PerformTransformRejection { + result_promise: self.result_promise.clone(), + })), + can_gc, + ); + + let realm = enter_realm(&*self.writable.global()); + let comp = InRealm::Entered(&realm); + transform_result.append_native_handler(&handler, comp, can_gc); + } +} + +#[derive(JSTraceable, MallocSizeOf)] +#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)] +/// Reacting to fulfillment of performTransform as part of +/// <https://streams.spec.whatwg.org/#transform-stream-default-sink-write-algorithm> +struct PerformTransformFulfillment { + #[ignore_malloc_size_of = "Rc is hard"] + result_promise: Rc<Promise>, +} + +impl Callback for PerformTransformFulfillment { + fn callback(&self, _cx: SafeJSContext, _v: SafeHandleValue, _realm: InRealm, can_gc: CanGc) { + // Fulfilled: resolve the outer promise + self.result_promise.resolve_native(&(), can_gc); + } +} + +#[derive(JSTraceable, MallocSizeOf)] +#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)] +/// Reacting to rejection of performTransform as part of +/// <https://streams.spec.whatwg.org/#transform-stream-default-sink-write-algorithm> +struct PerformTransformRejection { + #[ignore_malloc_size_of = "Rc is hard"] + result_promise: Rc<Promise>, +} + +impl Callback for PerformTransformRejection { + fn callback(&self, cx: SafeJSContext, v: SafeHandleValue, _realm: InRealm, can_gc: CanGc) { + // Stream already errored in perform_transform, just reject result_promise + self.result_promise.reject(cx, v, can_gc); + } +} + +#[derive(JSTraceable, MallocSizeOf)] +#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)] +/// Reacting to rejection of backpressureChangePromise as part of +/// <https://streams.spec.whatwg.org/#transform-stream-default-sink-write-algorithm> +struct BackpressureChangeRejection { + #[ignore_malloc_size_of = "Rc is hard"] + result_promise: Rc<Promise>, +} + +impl Callback for BackpressureChangeRejection { + fn callback(&self, cx: SafeJSContext, reason: SafeHandleValue, _realm: InRealm, can_gc: CanGc) { + self.result_promise.reject(cx, reason, can_gc); + } +} + +impl js::gc::Rootable for CancelPromiseFulfillment {} + +/// Reacting to fulfillment of the cancelpromise as part of +/// <https://streams.spec.whatwg.org/#transform-stream-default-sink-abort-algorithm> +#[derive(JSTraceable, MallocSizeOf)] +#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)] +struct CancelPromiseFulfillment { + readable: Dom<ReadableStream>, + controller: Dom<TransformStreamDefaultController>, + #[ignore_malloc_size_of = "mozjs"] + reason: Box<Heap<JSVal>>, +} + +impl Callback for CancelPromiseFulfillment { + /// Reacting to backpressureChangePromise with the following fulfillment steps: + fn callback(&self, cx: SafeJSContext, _v: SafeHandleValue, _realm: InRealm, can_gc: CanGc) { + // If readable.[[state]] is "errored", reject controller.[[finishPromise]] with readable.[[storedError]]. + if self.readable.is_errored() { + rooted!(in(*cx) let mut error = UndefinedValue()); + self.readable.get_stored_error(error.handle_mut()); + self.controller + .get_finish_promise() + .expect("finish promise is not set") + .reject_native(&error.handle(), can_gc); + } else { + // Otherwise: + // Perform ! ReadableStreamDefaultControllerError(readable.[[controller]], reason). + rooted!(in(*cx) let mut reason = UndefinedValue()); + reason.set(self.reason.get()); + self.readable + .get_default_controller() + .error(reason.handle(), can_gc); + + // Resolve controller.[[finishPromise]] with undefined. + self.controller + .get_finish_promise() + .expect("finish promise is not set") + .resolve_native(&(), can_gc); + } + } +} + +impl js::gc::Rootable for CancelPromiseRejection {} + +/// Reacting to rejection of cancelpromise as part of +/// <https://streams.spec.whatwg.org/#transform-stream-default-sink-abort-algorithm> +#[derive(JSTraceable, MallocSizeOf)] +#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)] +struct CancelPromiseRejection { + readable: Dom<ReadableStream>, + controller: Dom<TransformStreamDefaultController>, +} + +impl Callback for CancelPromiseRejection { + /// Reacting to backpressureChangePromise with the following fulfillment steps: + fn callback(&self, cx: SafeJSContext, v: SafeHandleValue, _realm: InRealm, can_gc: CanGc) { + // Perform ! ReadableStreamDefaultControllerError(readable.[[controller]], r). + self.readable.get_default_controller().error(v, can_gc); + + // Reject controller.[[finishPromise]] with r. + self.controller + .get_finish_promise() + .expect("finish promise is not set") + .reject(cx, v, can_gc); + } +} + +impl js::gc::Rootable for SourceCancelPromiseFulfillment {} + +/// Reacting to fulfillment of the cancelpromise as part of +/// <https://streams.spec.whatwg.org/#transform-stream-default-source-cancel> +#[derive(JSTraceable, MallocSizeOf)] +#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)] +struct SourceCancelPromiseFulfillment { + writeable: Dom<WritableStream>, + controller: Dom<TransformStreamDefaultController>, + stream: Dom<TransformStream>, + #[ignore_malloc_size_of = "mozjs"] + reason: Box<Heap<JSVal>>, +} + +impl Callback for SourceCancelPromiseFulfillment { + /// Reacting to backpressureChangePromise with the following fulfillment steps: + fn callback(&self, cx: SafeJSContext, _v: SafeHandleValue, _realm: InRealm, can_gc: CanGc) { + // If cancelPromise was fulfilled, then: + let finish_promise = self + .controller + .get_finish_promise() + .expect("finish promise is not set"); + + let global = &self.writeable.global(); + // If writable.[[state]] is "errored", reject controller.[[finishPromise]] with writable.[[storedError]]. + if self.writeable.is_errored() { + rooted!(in(*cx) let mut error = UndefinedValue()); + self.writeable.get_stored_error(error.handle_mut()); + finish_promise.reject(cx, error.handle(), can_gc); + } else { + // Otherwise: + // Perform ! WritableStreamDefaultControllerErrorIfNeeded(writable.[[controller]], reason). + rooted!(in(*cx) let mut reason = UndefinedValue()); + reason.set(self.reason.get()); + self.writeable.get_default_controller().error_if_needed( + cx, + reason.handle(), + global, + can_gc, + ); + + // Perform ! TransformStreamUnblockWrite(stream). + self.stream.unblock_write(global, can_gc); + + // Resolve controller.[[finishPromise]] with undefined. + finish_promise.resolve_native(&(), can_gc); + } + } +} + +impl js::gc::Rootable for SourceCancelPromiseRejection {} + +/// Reacting to rejection of cancelpromise as part of +/// <https://streams.spec.whatwg.org/#transform-stream-default-source-cancel> +#[derive(JSTraceable, MallocSizeOf)] +#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)] +struct SourceCancelPromiseRejection { + writeable: Dom<WritableStream>, + controller: Dom<TransformStreamDefaultController>, + stream: Dom<TransformStream>, +} + +impl Callback for SourceCancelPromiseRejection { + /// Reacting to backpressureChangePromise with the following fulfillment steps: + fn callback(&self, cx: SafeJSContext, v: SafeHandleValue, _realm: InRealm, can_gc: CanGc) { + // Perform ! WritableStreamDefaultControllerErrorIfNeeded(writable.[[controller]], r). + let global = &self.writeable.global(); + + self.writeable + .get_default_controller() + .error_if_needed(cx, v, global, can_gc); + + // Perform ! TransformStreamUnblockWrite(stream). + self.stream.unblock_write(global, can_gc); + + // Reject controller.[[finishPromise]] with r. + self.controller + .get_finish_promise() + .expect("finish promise is not set") + .reject(cx, v, can_gc); + } +} + +impl js::gc::Rootable for FlushPromiseFulfillment {} + +/// Reacting to fulfillment of the flushpromise as part of +/// <https://streams.spec.whatwg.org/#transform-stream-default-sink-close-algorithm> +#[derive(JSTraceable, MallocSizeOf)] +#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)] +struct FlushPromiseFulfillment { + readable: Dom<ReadableStream>, + controller: Dom<TransformStreamDefaultController>, +} + +impl Callback for FlushPromiseFulfillment { + /// Reacting to flushpromise with the following fulfillment steps: + fn callback(&self, cx: SafeJSContext, _v: SafeHandleValue, _realm: InRealm, can_gc: CanGc) { + // If flushPromise was fulfilled, then: + let finish_promise = self + .controller + .get_finish_promise() + .expect("finish promise is not set"); + + // If readable.[[state]] is "errored", reject controller.[[finishPromise]] with readable.[[storedError]]. + if self.readable.is_errored() { + rooted!(in(*cx) let mut error = UndefinedValue()); + self.readable.get_stored_error(error.handle_mut()); + finish_promise.reject(cx, error.handle(), can_gc); + } else { + // Otherwise: + // Perform ! ReadableStreamDefaultControllerClose(readable.[[controller]]). + self.readable.get_default_controller().close(can_gc); + + // Resolve controller.[[finishPromise]] with undefined. + finish_promise.resolve_native(&(), can_gc); + } + } +} + +impl js::gc::Rootable for FlushPromiseRejection {} +/// Reacting to rejection of flushpromise as part of +/// <https://streams.spec.whatwg.org/#transform-stream-default-sink-close-algorithm> + +#[derive(JSTraceable, MallocSizeOf)] +#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)] +struct FlushPromiseRejection { + readable: Dom<ReadableStream>, + controller: Dom<TransformStreamDefaultController>, +} + +impl Callback for FlushPromiseRejection { + /// Reacting to flushpromise with the following fulfillment steps: + fn callback(&self, cx: SafeJSContext, v: SafeHandleValue, _realm: InRealm, can_gc: CanGc) { + // If flushPromise was rejected with reason r, then: + // Perform ! ReadableStreamDefaultControllerError(readable.[[controller]], r). + self.readable.get_default_controller().error(v, can_gc); + + // Reject controller.[[finishPromise]] with r. + self.controller + .get_finish_promise() + .expect("finish promise is not set") + .reject(cx, v, can_gc); + } +} + +/// <https://streams.spec.whatwg.org/#ts-class> +#[dom_struct] +pub struct TransformStream { + reflector_: Reflector, + + /// <https://streams.spec.whatwg.org/#transformstream-backpressure> + backpressure: Cell<bool>, + + /// <https://streams.spec.whatwg.org/#transformstream-backpressurechangepromise> + #[ignore_malloc_size_of = "Rc is hard"] + backpressure_change_promise: DomRefCell<Option<Rc<Promise>>>, + + /// <https://streams.spec.whatwg.org/#transformstream-controller> + controller: MutNullableDom<TransformStreamDefaultController>, + + /// <https://streams.spec.whatwg.org/#transformstream-detached> + detached: Cell<bool>, + + /// <https://streams.spec.whatwg.org/#transformstream-readable> + readable: MutNullableDom<ReadableStream>, + + /// <https://streams.spec.whatwg.org/#transformstream-writable> + writable: MutNullableDom<WritableStream>, +} + +impl TransformStream { + #[cfg_attr(crown, allow(crown::unrooted_must_root))] + /// <https://streams.spec.whatwg.org/#initialize-transform-stream> + fn new_inherited() -> TransformStream { + TransformStream { + reflector_: Reflector::new(), + backpressure: Default::default(), + backpressure_change_promise: DomRefCell::new(None), + controller: MutNullableDom::new(None), + detached: Cell::new(false), + readable: MutNullableDom::new(None), + writable: MutNullableDom::new(None), + } + } + + pub(crate) fn new_with_proto( + global: &GlobalScope, + proto: Option<SafeHandleObject>, + can_gc: CanGc, + ) -> DomRoot<TransformStream> { + reflect_dom_object_with_proto( + Box::new(TransformStream::new_inherited()), + global, + proto, + can_gc, + ) + } + + pub(crate) fn get_controller(&self) -> DomRoot<TransformStreamDefaultController> { + self.controller.get().expect("controller is not set") + } + + pub(crate) fn get_writable(&self) -> DomRoot<WritableStream> { + self.writable.get().expect("writable stream is not set") + } + + pub(crate) fn get_readable(&self) -> DomRoot<ReadableStream> { + self.readable.get().expect("readable stream is not set") + } + + pub(crate) fn get_backpressure(&self) -> bool { + self.backpressure.get() + } + + /// <https://streams.spec.whatwg.org/#initialize-transform-stream> + #[allow(clippy::too_many_arguments)] + fn initialize( + &self, + cx: SafeJSContext, + global: &GlobalScope, + start_promise: Rc<Promise>, + writable_high_water_mark: f64, + writable_size_algorithm: Rc<QueuingStrategySize>, + readable_high_water_mark: f64, + readable_size_algorithm: Rc<QueuingStrategySize>, + can_gc: CanGc, + ) -> Fallible<()> { + // Let startAlgorithm be an algorithm that returns startPromise. + // Let writeAlgorithm be the following steps, taking a chunk argument: + // Return ! TransformStreamDefaultSinkWriteAlgorithm(stream, chunk). + // Let abortAlgorithm be the following steps, taking a reason argument: + // Return ! TransformStreamDefaultSinkAbortAlgorithm(stream, reason). + // Let closeAlgorithm be the following steps: + // Return ! TransformStreamDefaultSinkCloseAlgorithm(stream). + // Set stream.[[writable]] to ! CreateWritableStream(startAlgorithm, writeAlgorithm, + // closeAlgorithm, abortAlgorithm, writableHighWaterMark, writableSizeAlgorithm). + // Note: Those steps are implemented using UnderlyingSinkType::Transform. + + let writable = create_writable_stream( + cx, + global, + writable_high_water_mark, + writable_size_algorithm, + UnderlyingSinkType::Transform(Dom::from_ref(self), start_promise.clone()), + can_gc, + )?; + self.writable.set(Some(&writable)); + + // Let pullAlgorithm be the following steps: + + // Return ! TransformStreamDefaultSourcePullAlgorithm(stream). + + // Let cancelAlgorithm be the following steps, taking a reason argument: + + // Return ! TransformStreamDefaultSourceCancelAlgorithm(stream, reason). + + // Set stream.[[readable]] to ! CreateReadableStream(startAlgorithm, pullAlgorithm, + // cancelAlgorithm, readableHighWaterMark, readableSizeAlgorithm). + + let readable = create_readable_stream( + global, + UnderlyingSourceType::Transform(Dom::from_ref(self), start_promise.clone()), + Some(readable_size_algorithm), + Some(readable_high_water_mark), + can_gc, + ); + self.readable.set(Some(&readable)); + + // Set stream.[[backpressure]] and stream.[[backpressureChangePromise]] to undefined. + // Note: This is done in the constructor. + + // Perform ! TransformStreamSetBackpressure(stream, true). + self.set_backpressure(global, true, can_gc); + + // Set stream.[[controller]] to undefined. + self.controller.set(None); + + Ok(()) + } + + /// <https://streams.spec.whatwg.org/#transform-stream-set-backpressure> + pub(crate) fn set_backpressure(&self, global: &GlobalScope, backpressure: bool, can_gc: CanGc) { + // Assert: stream.[[backpressure]] is not backpressure. + assert!(self.backpressure.get() != backpressure); + + // If stream.[[backpressureChangePromise]] is not undefined, resolve + // stream.[[backpressureChangePromise]] with undefined. + if let Some(promise) = self.backpressure_change_promise.borrow_mut().take() { + promise.resolve_native(&(), can_gc); + } + + // Set stream.[[backpressureChangePromise]] to a new promise.; + *self.backpressure_change_promise.borrow_mut() = Some(Promise::new(global, can_gc)); + + // Set stream.[[backpressure]] to backpressure. + self.backpressure.set(backpressure); + } + + /// <https://streams.spec.whatwg.org/#set-up-transform-stream-default-controller> + fn set_up_transform_stream_default_controller( + &self, + controller: &TransformStreamDefaultController, + ) { + // Assert: stream implements TransformStream. + // Note: this is checked with type. + + // Assert: stream.[[controller]] is undefined. + assert!(self.controller.get().is_none()); + + // Set controller.[[stream]] to stream. + controller.set_stream(self); + + // Set stream.[[controller]] to controller. + self.controller.set(Some(controller)); + + // Set controller.[[transformAlgorithm]] to transformAlgorithm. + // Set controller.[[flushAlgorithm]] to flushAlgorithm. + // Set controller.[[cancelAlgorithm]] to cancelAlgorithm. + // Note: These are set in the constructor. + } + + /// <https://streams.spec.whatwg.org/#set-up-transform-stream-default-controller-from-transformer> + fn set_up_transform_stream_default_controller_from_transformer( + &self, + global: &GlobalScope, + transformer_obj: SafeHandleObject, + transformer: &Transformer, + can_gc: CanGc, + ) { + // Let controller be a new TransformStreamDefaultController. + let controller = TransformStreamDefaultController::new(global, transformer, can_gc); + + // Let transformAlgorithm be the following steps, taking a chunk argument: + // Let result be TransformStreamDefaultControllerEnqueue(controller, chunk). + // If result is an abrupt completion, return a promise rejected with result.[[Value]]. + // Otherwise, return a promise resolved with undefined. + + // Let flushAlgorithm be an algorithm which returns a promise resolved with undefined. + // Let cancelAlgorithm be an algorithm which returns a promise resolved with undefined. + + // If transformerDict["transform"] exists, set transformAlgorithm to an algorithm which + // takes an argument + // chunk and returns the result of invoking transformerDict["transform"] with argument + // list « chunk, controller » + // and callback this value transformer. + + // If transformerDict["flush"] exists, set flushAlgorithm to an algorithm which returns + // the result + // of invoking transformerDict["flush"] with argument list « controller » and callback + // this value transformer. + + // If transformerDict["cancel"] exists, set cancelAlgorithm to an algorithm which takes an argument + // reason and returns the result of invoking transformerDict["cancel"] with argument list « reason » + // and callback this value transformer. + controller.set_transform_obj(transformer_obj); + + // Perform ! SetUpTransformStreamDefaultController(stream, controller, + // transformAlgorithm, flushAlgorithm, cancelAlgorithm). + self.set_up_transform_stream_default_controller(&controller); + } + + /// <https://streams.spec.whatwg.org/#transform-stream-default-sink-write-algorithm> + pub(crate) fn transform_stream_default_sink_write_algorithm( + &self, + cx: SafeJSContext, + global: &GlobalScope, + chunk: SafeHandleValue, + can_gc: CanGc, + ) -> Fallible<Rc<Promise>> { + // Assert: stream.[[writable]].[[state]] is "writable". + assert!(self.writable.get().is_some()); + + // Let controller be stream.[[controller]]. + let controller = self.controller.get().expect("controller is not set"); + + // If stream.[[backpressure]] is true, + if self.backpressure.get() { + // Let backpressureChangePromise be stream.[[backpressureChangePromise]]. + let backpressure_change_promise = self.backpressure_change_promise.borrow(); + + // Assert: backpressureChangePromise is not undefined. + assert!(backpressure_change_promise.is_some()); + + // Return the result of reacting to backpressureChangePromise with the following fulfillment steps: + let result_promise = Promise::new(global, can_gc); + rooted!(in(*cx) let mut fulfillment_handler = Some(TransformBackPressureChangePromiseFulfillment { + controller: Dom::from_ref(&controller), + writable: Dom::from_ref(&self.writable.get().expect("writable stream")), + chunk: Heap::boxed(chunk.get()), + result_promise: result_promise.clone(), + })); + + let handler = PromiseNativeHandler::new( + global, + fulfillment_handler.take().map(|h| Box::new(h) as Box<_>), + Some(Box::new(BackpressureChangeRejection { + result_promise: result_promise.clone(), + })), + can_gc, + ); + let realm = enter_realm(global); + let comp = InRealm::Entered(&realm); + backpressure_change_promise + .as_ref() + .expect("Promise must be some by now.") + .append_native_handler(&handler, comp, can_gc); + + return Ok(result_promise); + } + + // Return ! TransformStreamDefaultControllerPerformTransform(controller, chunk). + controller.transform_stream_default_controller_perform_transform(cx, global, chunk, can_gc) + } + + /// <https://streams.spec.whatwg.org/#transform-stream-default-sink-abort-algorithm> + pub(crate) fn transform_stream_default_sink_abort_algorithm( + &self, + cx: SafeJSContext, + global: &GlobalScope, + reason: SafeHandleValue, + can_gc: CanGc, + ) -> Fallible<Rc<Promise>> { + // Let controller be stream.[[controller]]. + let controller = self.controller.get().expect("controller is not set"); + + // If controller.[[finishPromise]] is not undefined, return controller.[[finishPromise]]. + if let Some(finish_promise) = controller.get_finish_promise() { + return Ok(finish_promise); + } + + // Let readable be stream.[[readable]]. + let readable = self.readable.get().expect("readable stream is not set"); + + // Let controller.[[finishPromise]] be a new promise. + controller.set_finish_promise(Promise::new(global, can_gc)); + + // Let cancelPromise be the result of performing controller.[[cancelAlgorithm]], passing reason. + let cancel_promise = controller.perform_cancel(cx, global, reason, can_gc)?; + + // Perform ! TransformStreamDefaultControllerClearAlgorithms(controller). + controller.clear_algorithms(); + + // React to cancelPromise: + let handler = PromiseNativeHandler::new( + global, + Some(Box::new(CancelPromiseFulfillment { + readable: Dom::from_ref(&readable), + controller: Dom::from_ref(&controller), + reason: Heap::boxed(reason.get()), + })), + Some(Box::new(CancelPromiseRejection { + readable: Dom::from_ref(&readable), + controller: Dom::from_ref(&controller), + })), + can_gc, + ); + let realm = enter_realm(global); + let comp = InRealm::Entered(&realm); + cancel_promise.append_native_handler(&handler, comp, can_gc); + + // Return controller.[[finishPromise]]. + let finish_promise = controller + .get_finish_promise() + .expect("finish promise is not set"); + Ok(finish_promise) + } + + /// <https://streams.spec.whatwg.org/#transform-stream-default-sink-close-algorithm> + pub(crate) fn transform_stream_default_sink_close_algorithm( + &self, + cx: SafeJSContext, + global: &GlobalScope, + can_gc: CanGc, + ) -> Fallible<Rc<Promise>> { + // Let controller be stream.[[controller]]. + let controller = self + .controller + .get() + .ok_or(Error::Type("controller is not set".to_string()))?; + + // If controller.[[finishPromise]] is not undefined, return controller.[[finishPromise]]. + if let Some(finish_promise) = controller.get_finish_promise() { + return Ok(finish_promise); + } + + // Let readable be stream.[[readable]]. + let readable = self + .readable + .get() + .ok_or(Error::Type("readable stream is not set".to_string()))?; + + // Let controller.[[finishPromise]] be a new promise. + controller.set_finish_promise(Promise::new(global, can_gc)); + + // Let flushPromise be the result of performing controller.[[flushAlgorithm]]. + let flush_promise = controller.perform_flush(cx, global, can_gc)?; + + // Perform ! TransformStreamDefaultControllerClearAlgorithms(controller). + controller.clear_algorithms(); + + // React to flushPromise: + let handler = PromiseNativeHandler::new( + global, + Some(Box::new(FlushPromiseFulfillment { + readable: Dom::from_ref(&readable), + controller: Dom::from_ref(&controller), + })), + Some(Box::new(FlushPromiseRejection { + readable: Dom::from_ref(&readable), + controller: Dom::from_ref(&controller), + })), + can_gc, + ); + + let realm = enter_realm(global); + let comp = InRealm::Entered(&realm); + flush_promise.append_native_handler(&handler, comp, can_gc); + // Return controller.[[finishPromise]]. + let finish_promise = controller + .get_finish_promise() + .expect("finish promise is not set"); + Ok(finish_promise) + } + + /// <https://streams.spec.whatwg.org/#transform-stream-default-source-cancel> + pub(crate) fn transform_stream_default_source_cancel( + &self, + cx: SafeJSContext, + global: &GlobalScope, + reason: SafeHandleValue, + can_gc: CanGc, + ) -> Fallible<Rc<Promise>> { + // Let controller be stream.[[controller]]. + let controller = self + .controller + .get() + .ok_or(Error::Type("controller is not set".to_string()))?; + + // If controller.[[finishPromise]] is not undefined, return controller.[[finishPromise]]. + if let Some(finish_promise) = controller.get_finish_promise() { + return Ok(finish_promise); + } + + // Let writable be stream.[[writable]]. + let writable = self + .writable + .get() + .ok_or(Error::Type("writable stream is not set".to_string()))?; + + // Let controller.[[finishPromise]] be a new promise. + controller.set_finish_promise(Promise::new(global, can_gc)); + + // Let cancelPromise be the result of performing controller.[[cancelAlgorithm]], passing reason. + let cancel_promise = controller.perform_cancel(cx, global, reason, can_gc)?; + + // Perform ! TransformStreamDefaultControllerClearAlgorithms(controller). + controller.clear_algorithms(); + + // React to cancelPromise: + let handler = PromiseNativeHandler::new( + global, + Some(Box::new(SourceCancelPromiseFulfillment { + writeable: Dom::from_ref(&writable), + controller: Dom::from_ref(&controller), + stream: Dom::from_ref(self), + reason: Heap::boxed(reason.get()), + })), + Some(Box::new(SourceCancelPromiseRejection { + writeable: Dom::from_ref(&writable), + controller: Dom::from_ref(&controller), + stream: Dom::from_ref(self), + })), + can_gc, + ); + + // Return controller.[[finishPromise]]. + let finish_promise = controller + .get_finish_promise() + .expect("finish promise is not set"); + let realm = enter_realm(global); + let comp = InRealm::Entered(&realm); + cancel_promise.append_native_handler(&handler, comp, can_gc); + Ok(finish_promise) + } + + /// <https://streams.spec.whatwg.org/#transform-stream-default-source-pull> + pub(crate) fn transform_stream_default_source_pull( + &self, + global: &GlobalScope, + can_gc: CanGc, + ) -> Fallible<Rc<Promise>> { + // Assert: stream.[[backpressure]] is true. + assert!(self.backpressure.get()); + + // Assert: stream.[[backpressureChangePromise]] is not undefined. + assert!(self.backpressure_change_promise.borrow().is_some()); + + // Perform ! TransformStreamSetBackpressure(stream, false). + self.set_backpressure(global, false, can_gc); + + // Return stream.[[backpressureChangePromise]]. + Ok(self + .backpressure_change_promise + .borrow() + .clone() + .expect("Promise must be some by now.")) + } + + /// <https://streams.spec.whatwg.org/#transform-stream-error-writable-and-unblock-write> + pub(crate) fn error_writable_and_unblock_write( + &self, + cx: SafeJSContext, + global: &GlobalScope, + error: SafeHandleValue, + can_gc: CanGc, + ) { + // Perform ! TransformStreamDefaultControllerClearAlgorithms(stream.[[controller]]). + self.get_controller().clear_algorithms(); + + // Perform ! WritableStreamDefaultControllerErrorIfNeeded(stream.[[writable]].[[controller]], e). + self.get_writable() + .get_default_controller() + .error_if_needed(cx, error, global, can_gc); + + // Perform ! TransformStreamUnblockWrite(stream). + self.unblock_write(global, can_gc) + } + + /// <https://streams.spec.whatwg.org/#transform-stream-unblock-write> + pub(crate) fn unblock_write(&self, global: &GlobalScope, can_gc: CanGc) { + // If stream.[[backpressure]] is true, perform ! TransformStreamSetBackpressure(stream, false). + if self.backpressure.get() { + self.set_backpressure(global, false, can_gc); + } + } + + /// <https://streams.spec.whatwg.org/#transform-stream-error> + pub(crate) fn error( + &self, + cx: SafeJSContext, + global: &GlobalScope, + error: SafeHandleValue, + can_gc: CanGc, + ) { + // Perform ! ReadableStreamDefaultControllerError(stream.[[readable]].[[controller]], e). + self.get_readable() + .get_default_controller() + .error(error, can_gc); + + // Perform ! TransformStreamErrorWritableAndUnblockWrite(stream, e). + self.error_writable_and_unblock_write(cx, global, error, can_gc); + } +} + +impl TransformStreamMethods<crate::DomTypeHolder> for TransformStream { + /// <https://streams.spec.whatwg.org/#ts-constructor> + #[allow(unsafe_code)] + fn Constructor( + cx: SafeJSContext, + global: &GlobalScope, + proto: Option<SafeHandleObject>, + can_gc: CanGc, + transformer: Option<*mut JSObject>, + writable_strategy: &QueuingStrategy, + readable_strategy: &QueuingStrategy, + ) -> Fallible<DomRoot<TransformStream>> { + // If transformer is missing, set it to null. + rooted!(in(*cx) let transformer_obj = transformer.unwrap_or(ptr::null_mut())); + + // Let underlyingSinkDict be underlyingSink, + // converted to an IDL value of type UnderlyingSink. + let transformer_dict = if !transformer_obj.is_null() { + rooted!(in(*cx) let obj_val = ObjectValue(transformer_obj.get())); + match Transformer::new(cx, obj_val.handle()) { + Ok(ConversionResult::Success(val)) => val, + Ok(ConversionResult::Failure(error)) => return Err(Error::Type(error.to_string())), + _ => { + return Err(Error::JSFailed); + }, + } + } else { + Transformer::empty() + }; + + // If transformerDict["readableType"] exists, throw a RangeError exception. + if !transformer_dict.readableType.handle().is_undefined() { + return Err(Error::Range("readableType is set".to_string())); + } + + // If transformerDict["writableType"] exists, throw a RangeError exception. + if !transformer_dict.writableType.handle().is_undefined() { + return Err(Error::Range("writableType is set".to_string())); + } + + // Let readableHighWaterMark be ? ExtractHighWaterMark(readableStrategy, 0). + let readable_high_water_mark = extract_high_water_mark(readable_strategy, 0.0)?; + + // Let readableSizeAlgorithm be ! ExtractSizeAlgorithm(readableStrategy). + let readable_size_algorithm = extract_size_algorithm(readable_strategy, can_gc); + + // Let writableHighWaterMark be ? ExtractHighWaterMark(writableStrategy, 1). + let writable_high_water_mark = extract_high_water_mark(writable_strategy, 1.0)?; + + // Let writableSizeAlgorithm be ! ExtractSizeAlgorithm(writableStrategy). + let writable_size_algorithm = extract_size_algorithm(writable_strategy, can_gc); + + // Let startPromise be a new promise. + let start_promise = Promise::new(global, can_gc); + + // Perform ! InitializeTransformStream(this, startPromise, writableHighWaterMark, + // writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm). + let stream = TransformStream::new_with_proto(global, proto, can_gc); + stream.initialize( + cx, + global, + start_promise.clone(), + writable_high_water_mark, + writable_size_algorithm, + readable_high_water_mark, + readable_size_algorithm, + can_gc, + )?; + + // Perform ? SetUpTransformStreamDefaultControllerFromTransformer(this, transformer, transformerDict). + stream.set_up_transform_stream_default_controller_from_transformer( + global, + transformer_obj.handle(), + &transformer_dict, + can_gc, + ); + + // If transformerDict["start"] exists, then resolve startPromise with the + // result of invoking transformerDict["start"] + // with argument list « this.[[controller]] » and callback this value transformer. + if let Some(start) = &transformer_dict.start { + rooted!(in(*cx) let mut result_object = ptr::null_mut::<JSObject>()); + rooted!(in(*cx) let mut result: JSVal); + rooted!(in(*cx) let this_object = transformer_obj.get()); + start.Call_( + &this_object.handle(), + &stream.get_controller(), + result.handle_mut(), + ExceptionHandling::Rethrow, + can_gc, + )?; + let is_promise = unsafe { + if result.is_object() { + result_object.set(result.to_object()); + IsPromiseObject(result_object.handle().into_handle()) + } else { + false + } + }; + let promise = if is_promise { + let promise = Promise::new_with_js_promise(result_object.handle(), cx); + promise + } else { + Promise::new_resolved(global, cx, result.get(), can_gc) + }; + start_promise.resolve_native(&promise, can_gc); + } else { + // Otherwise, resolve startPromise with undefined. + start_promise.resolve_native(&(), can_gc); + }; + + Ok(stream) + } + + /// <https://streams.spec.whatwg.org/#ts-readable> + fn Readable(&self) -> DomRoot<ReadableStream> { + // Return this.[[readable]]. + self.readable.get().expect("readable stream is not set") + } + + /// <https://streams.spec.whatwg.org/#ts-writable> + fn Writable(&self) -> DomRoot<WritableStream> { + // Return this.[[writable]]. + self.writable.get().expect("writable stream is not set") + } +} diff --git a/components/script/dom/transformstreamdefaultcontroller.rs b/components/script/dom/transformstreamdefaultcontroller.rs new file mode 100644 index 00000000000..41813ef6f96 --- /dev/null +++ b/components/script/dom/transformstreamdefaultcontroller.rs @@ -0,0 +1,420 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use std::cell::RefCell; +use std::rc::Rc; + +use dom_struct::dom_struct; +use js::jsapi::{ + ExceptionStackBehavior, Heap, JS_IsExceptionPending, JS_SetPendingException, JSObject, +}; +use js::jsval::UndefinedValue; +use js::rust::{HandleObject as SafeHandleObject, HandleValue as SafeHandleValue}; + +use super::bindings::cell::DomRefCell; +use super::bindings::codegen::Bindings::TransformerBinding::{ + Transformer, TransformerCancelCallback, TransformerFlushCallback, TransformerTransformCallback, +}; +use super::types::TransformStream; +use crate::dom::bindings::callback::ExceptionHandling; +use crate::dom::bindings::codegen::Bindings::TransformStreamDefaultControllerBinding::TransformStreamDefaultControllerMethods; +use crate::dom::bindings::error::{Error, ErrorToJsval, Fallible}; +use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object}; +use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom}; +use crate::dom::globalscope::GlobalScope; +use crate::dom::promise::Promise; +use crate::dom::promisenativehandler::{Callback, PromiseNativeHandler}; +use crate::realms::{InRealm, enter_realm}; +use crate::script_runtime::{CanGc, JSContext as SafeJSContext}; + +impl js::gc::Rootable for TransformTransformPromiseRejection {} + +/// Reacting to transformPromise as part of +/// <https://streams.spec.whatwg.org/#transform-stream-default-controller-perform-transform> +#[derive(JSTraceable, MallocSizeOf)] +#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)] +struct TransformTransformPromiseRejection { + controller: Dom<TransformStreamDefaultController>, +} + +impl Callback for TransformTransformPromiseRejection { + /// Reacting to transformPromise with the following fulfillment steps: + #[allow(unsafe_code)] + fn callback(&self, cx: SafeJSContext, v: SafeHandleValue, _realm: InRealm, can_gc: CanGc) { + // Perform ! TransformStreamError(controller.[[stream]], r). + self.controller + .error(cx, &self.controller.global(), v, can_gc); + + // Throw r. + // Note: this is done part of perform_transform(). + } +} + +/// <https://streams.spec.whatwg.org/#transformstreamdefaultcontroller> +#[dom_struct] +pub struct TransformStreamDefaultController { + reflector_: Reflector, + + /// <https://streams.spec.whatwg.org/#transformstreamdefaultcontroller-cancelalgorithm> + #[ignore_malloc_size_of = "Rc is hard"] + cancel: RefCell<Option<Rc<TransformerCancelCallback>>>, + + /// <https://streams.spec.whatwg.org/#transformstreamdefaultcontroller-flushalgorithm> + #[ignore_malloc_size_of = "Rc is hard"] + flush: RefCell<Option<Rc<TransformerFlushCallback>>>, + + /// <https://streams.spec.whatwg.org/#transformstreamdefaultcontroller-transformalgorithm> + #[ignore_malloc_size_of = "Rc is hard"] + transform: RefCell<Option<Rc<TransformerTransformCallback>>>, + + /// The JS object used as `this` when invoking sink algorithms. + #[ignore_malloc_size_of = "mozjs"] + transform_obj: Heap<*mut JSObject>, + + /// <https://streams.spec.whatwg.org/#TransformStreamDefaultController-stream> + stream: MutNullableDom<TransformStream>, + + /// <https://streams.spec.whatwg.org/#transformstreamdefaultcontroller-finishpromise> + #[ignore_malloc_size_of = "Rc is hard"] + finish_promise: DomRefCell<Option<Rc<Promise>>>, +} + +impl TransformStreamDefaultController { + #[cfg_attr(crown, allow(crown::unrooted_must_root))] + fn new_inherited(transformer: &Transformer) -> TransformStreamDefaultController { + TransformStreamDefaultController { + reflector_: Reflector::new(), + cancel: RefCell::new(transformer.cancel.clone()), + flush: RefCell::new(transformer.flush.clone()), + transform: RefCell::new(transformer.transform.clone()), + finish_promise: DomRefCell::new(None), + stream: MutNullableDom::new(None), + transform_obj: Default::default(), + } + } + + #[cfg_attr(crown, allow(crown::unrooted_must_root))] + pub(crate) fn new( + global: &GlobalScope, + transformer: &Transformer, + can_gc: CanGc, + ) -> DomRoot<TransformStreamDefaultController> { + reflect_dom_object( + Box::new(TransformStreamDefaultController::new_inherited(transformer)), + global, + can_gc, + ) + } + + /// Setting the JS object after the heap has settled down. + pub(crate) fn set_transform_obj(&self, this_object: SafeHandleObject) { + self.transform_obj.set(*this_object); + } + + pub(crate) fn set_stream(&self, stream: &TransformStream) { + self.stream.set(Some(stream)); + } + + pub(crate) fn get_finish_promise(&self) -> Option<Rc<Promise>> { + self.finish_promise.borrow().clone() + } + + pub(crate) fn set_finish_promise(&self, promise: Rc<Promise>) { + *self.finish_promise.borrow_mut() = Some(promise); + } + + /// <https://streams.spec.whatwg.org/#transform-stream-default-controller-perform-transform> + pub(crate) fn transform_stream_default_controller_perform_transform( + &self, + cx: SafeJSContext, + global: &GlobalScope, + chunk: SafeHandleValue, + can_gc: CanGc, + ) -> Fallible<Rc<Promise>> { + // Let transformPromise be the result of performing controller.[[transformAlgorithm]], passing chunk. + let transform_promise = self.perform_transform(cx, global, chunk, can_gc)?; + + // Return the result of reacting to transformPromise with the following rejection steps given the argument r: + rooted!(in(*cx) let mut reject_handler = Some(TransformTransformPromiseRejection { + controller: Dom::from_ref(self), + })); + + let handler = PromiseNativeHandler::new( + global, + None, + reject_handler.take().map(|h| Box::new(h) as Box<_>), + can_gc, + ); + let realm = enter_realm(global); + let comp = InRealm::Entered(&realm); + transform_promise.append_native_handler(&handler, comp, can_gc); + + Ok(transform_promise) + } + + pub(crate) fn perform_transform( + &self, + cx: SafeJSContext, + global: &GlobalScope, + chunk: SafeHandleValue, + can_gc: CanGc, + ) -> Fallible<Rc<Promise>> { + // If transformerDict["transform"] exists, set transformAlgorithm to an algorithm which + // takes an argument chunk and returns the result of invoking transformerDict["transform"] with argument list + // « chunk, controller » and callback this value transformer. + let algo = self.transform.borrow().clone(); + let result = if let Some(transform) = algo { + rooted!(in(*cx) let this_object = self.transform_obj.get()); + let call_result = transform.Call_( + &this_object.handle(), + chunk, + self, + ExceptionHandling::Rethrow, + can_gc, + ); + match call_result { + Ok(p) => p, + Err(e) => { + let p = Promise::new(global, can_gc); + p.reject_error(e, can_gc); + p + }, + } + } else { + // Let transformAlgorithm be the following steps, taking a chunk argument: + // Let result be TransformStreamDefaultControllerEnqueue(controller, chunk). + // If result is an abrupt completion, return a promise rejected with result.[[Value]]. + let promise = if let Err(error) = self.enqueue(cx, global, chunk, can_gc) { + rooted!(in(*cx) let mut error_val = UndefinedValue()); + error.to_jsval(cx, global, error_val.handle_mut(), can_gc); + Promise::new_rejected(global, cx, error_val.handle(), can_gc) + } else { + // Otherwise, return a promise resolved with undefined. + Promise::new_resolved(global, cx, (), can_gc) + }; + + promise + }; + + Ok(result) + } + + pub(crate) fn perform_cancel( + &self, + cx: SafeJSContext, + global: &GlobalScope, + chunk: SafeHandleValue, + can_gc: CanGc, + ) -> Fallible<Rc<Promise>> { + // If transformerDict["cancel"] exists, set cancelAlgorithm to an algorithm which takes an argument + // reason and returns the result of invoking transformerDict["cancel"] with argument list « reason » + // and callback this value transformer. + let algo = self.cancel.borrow().clone(); + let result = if let Some(cancel) = algo { + rooted!(in(*cx) let this_object = self.transform_obj.get()); + let call_result = cancel.Call_( + &this_object.handle(), + chunk, + ExceptionHandling::Rethrow, + can_gc, + ); + match call_result { + Ok(p) => p, + Err(e) => { + let p = Promise::new(global, can_gc); + p.reject_error(e, can_gc); + p + }, + } + } else { + // Let cancelAlgorithm be an algorithm which returns a promise resolved with undefined. + Promise::new_resolved(global, cx, (), can_gc) + }; + + Ok(result) + } + + pub(crate) fn perform_flush( + &self, + cx: SafeJSContext, + global: &GlobalScope, + can_gc: CanGc, + ) -> Fallible<Rc<Promise>> { + // If transformerDict["flush"] exists, set flushAlgorithm to an algorithm which returns the result of + // invoking transformerDict["flush"] with argument list « controller » and callback this value transformer. + let algo = self.flush.borrow().clone(); + let result = if let Some(flush) = algo { + rooted!(in(*cx) let this_object = self.transform_obj.get()); + let call_result = flush.Call_( + &this_object.handle(), + self, + ExceptionHandling::Rethrow, + can_gc, + ); + match call_result { + Ok(p) => p, + Err(e) => { + let p = Promise::new(global, can_gc); + p.reject_error(e, can_gc); + p + }, + } + } else { + // Let flushAlgorithm be an algorithm which returns a promise resolved with undefined. + Promise::new_resolved(global, cx, (), can_gc) + }; + + Ok(result) + } + + /// <https://streams.spec.whatwg.org/#transform-stream-default-controller-enqueue> + #[allow(unsafe_code)] + pub(crate) fn enqueue( + &self, + cx: SafeJSContext, + global: &GlobalScope, + chunk: SafeHandleValue, + can_gc: CanGc, + ) -> Fallible<()> { + // Let stream be controller.[[stream]]. + let stream = self.stream.get().expect("stream is null"); + + // Let readableController be stream.[[readable]].[[controller]]. + let readable = stream.get_readable(); + let readable_controller = readable.get_default_controller(); + + // If ! ReadableStreamDefaultControllerCanCloseOrEnqueue(readableController) + // is false, throw a TypeError exception. + if !readable_controller.can_close_or_enqueue() { + return Err(Error::Type( + "ReadableStreamDefaultControllerCanCloseOrEnqueue is false".to_owned(), + )); + } + + // Let enqueueResult be ReadableStreamDefaultControllerEnqueue(readableController, chunk). + // If enqueueResult is an abrupt completion, + if let Err(error) = readable_controller.enqueue(cx, chunk, can_gc) { + // Perform ! TransformStreamErrorWritableAndUnblockWrite(stream, enqueueResult.[[Value]]). + rooted!(in(*cx) let mut rooted_error = UndefinedValue()); + error + .clone() + .to_jsval(cx, global, rooted_error.handle_mut(), can_gc); + stream.error_writable_and_unblock_write(cx, global, rooted_error.handle(), can_gc); + + // Throw stream.[[readable]].[[storedError]]. + unsafe { + if !JS_IsExceptionPending(*cx) { + rooted!(in(*cx) let mut stored_error = UndefinedValue()); + readable.get_stored_error(stored_error.handle_mut()); + + JS_SetPendingException( + *cx, + stored_error.handle().into(), + ExceptionStackBehavior::Capture, + ); + } + } + return Err(error); + } + + // Let backpressure be ! ReadableStreamDefaultControllerHasBackpressure(readableController). + let backpressure = readable_controller.has_backpressure(); + + // If backpressure is not stream.[[backpressure]], + if backpressure != stream.get_backpressure() { + // Assert: backpressure is true. + assert!(backpressure); + + // Perform ! TransformStreamSetBackpressure(stream, true). + stream.set_backpressure(global, true, can_gc); + } + Ok(()) + } + + /// <https://streams.spec.whatwg.org/#transform-stream-default-controller-error> + pub(crate) fn error( + &self, + cx: SafeJSContext, + global: &GlobalScope, + reason: SafeHandleValue, + can_gc: CanGc, + ) { + // Perform ! TransformStreamError(controller.[[stream]], e). + self.stream + .get() + .expect("stream is undefined") + .error(cx, global, reason, can_gc); + } + + /// <https://streams.spec.whatwg.org/#transform-stream-default-controller-clear-algorithms> + pub(crate) fn clear_algorithms(&self) { + // Set controller.[[transformAlgorithm]] to undefined. + self.transform.replace(None); + + // Set controller.[[flushAlgorithm]] to undefined. + self.flush.replace(None); + + // Set controller.[[cancelAlgorithm]] to undefined. + self.cancel.replace(None); + } + + /// <https://streams.spec.whatwg.org/#transform-stream-default-controller-terminate> + pub(crate) fn terminate(&self, cx: SafeJSContext, global: &GlobalScope, can_gc: CanGc) { + // Let stream be controller.[[stream]]. + let stream = self.stream.get().expect("stream is null"); + + // Let readableController be stream.[[readable]].[[controller]]. + let readable = stream.get_readable(); + let readable_controller = readable.get_default_controller(); + + // Perform ! ReadableStreamDefaultControllerClose(readableController). + readable_controller.close(can_gc); + + // Let error be a TypeError exception indicating that the stream has been terminated. + let error = Error::Type("stream has been terminated".to_owned()); + + // Perform ! TransformStreamErrorWritableAndUnblockWrite(stream, error). + rooted!(in(*cx) let mut rooted_error = UndefinedValue()); + error.to_jsval(cx, global, rooted_error.handle_mut(), can_gc); + stream.error_writable_and_unblock_write(cx, global, rooted_error.handle(), can_gc); + } +} + +impl TransformStreamDefaultControllerMethods<crate::DomTypeHolder> + for TransformStreamDefaultController +{ + /// <https://streams.spec.whatwg.org/#ts-default-controller-desired-size> + fn GetDesiredSize(&self) -> Option<f64> { + // Let readableController be this.[[stream]].[[readable]].[[controller]]. + let readable_controller = self + .stream + .get() + .expect("stream is null") + .get_readable() + .get_default_controller(); + + // Return ! ReadableStreamDefaultControllerGetDesiredSize(readableController). + readable_controller.get_desired_size() + } + + /// <https://streams.spec.whatwg.org/#ts-default-controller-enqueue> + fn Enqueue(&self, cx: SafeJSContext, chunk: SafeHandleValue, can_gc: CanGc) -> Fallible<()> { + // Perform ? TransformStreamDefaultControllerEnqueue(this, chunk). + self.enqueue(cx, &self.global(), chunk, can_gc) + } + + /// <https://streams.spec.whatwg.org/#ts-default-controller-error> + fn Error(&self, cx: SafeJSContext, reason: SafeHandleValue, can_gc: CanGc) -> Fallible<()> { + // Perform ? TransformStreamDefaultControllerError(this, e). + self.error(cx, &self.global(), reason, can_gc); + Ok(()) + } + + /// <https://streams.spec.whatwg.org/#ts-default-controller-terminate> + fn Terminate(&self, can_gc: CanGc) -> Fallible<()> { + // Perform ? TransformStreamDefaultControllerTerminate(this). + self.terminate(GlobalScope::get_cx(), &self.global(), can_gc); + Ok(()) + } +} diff --git a/components/script/dom/trustedtypepolicyfactory.rs b/components/script/dom/trustedtypepolicyfactory.rs index 0927446b904..284fa7045eb 100644 --- a/components/script/dom/trustedtypepolicyfactory.rs +++ b/components/script/dom/trustedtypepolicyfactory.rs @@ -66,7 +66,7 @@ impl TrustedTypePolicyFactory { (CheckResult::Allowed, Vec::new()) }; - global.report_csp_violations(violations); + global.report_csp_violations(violations, None); // Step 2: If allowedByCSP is "Blocked", throw a TypeError and abort further steps. if allowed_by_csp == CheckResult::Blocked { @@ -230,7 +230,7 @@ impl TrustedTypePolicyFactory { .should_sink_type_mismatch_violation_be_blocked_by_csp( sink, sink_group, &input, ); - global.report_csp_violations(violations); + global.report_csp_violations(violations, None); // Step 6.2: If disposition is “Allowed”, return stringified input and abort further steps. if disposition == CheckResult::Allowed { Ok(input) diff --git a/components/script/dom/underlyingsourcecontainer.rs b/components/script/dom/underlyingsourcecontainer.rs index 4acb58bafef..dd4b867df45 100644 --- a/components/script/dom/underlyingsourcecontainer.rs +++ b/components/script/dom/underlyingsourcecontainer.rs @@ -20,6 +20,7 @@ use crate::dom::defaultteeunderlyingsource::DefaultTeeUnderlyingSource; use crate::dom::globalscope::GlobalScope; use crate::dom::messageport::MessagePort; use crate::dom::promise::Promise; +use crate::dom::transformstream::TransformStream; use crate::script_runtime::{CanGc, JSContext as SafeJSContext}; /// <https://streams.spec.whatwg.org/#underlying-source-api> @@ -46,8 +47,7 @@ pub(crate) enum UnderlyingSourceType { /// A struct representing a JS object as underlying source, /// and the actual JS object for use as `thisArg` in callbacks. /// This is used for the `TransformStream` API. - #[allow(unused)] - Transform(/* Dom<TransformStream>, Rc<Promise>*/), + Transform(Dom<TransformStream>, Rc<Promise>), } impl UnderlyingSourceType { @@ -139,9 +139,9 @@ impl UnderlyingSourceContainer { // Call the cancel algorithm for the appropriate branch. tee_underlying_source.cancel_algorithm(cx, global, reason, can_gc) }, - UnderlyingSourceType::Transform() => { + UnderlyingSourceType::Transform(stream, _) => { // Return ! TransformStreamDefaultSourceCancelAlgorithm(stream, reason). - todo!(); + Some(stream.transform_stream_default_source_cancel(cx, global, reason, can_gc)) }, UnderlyingSourceType::Transfer(port) => { // Let cancelAlgorithm be the following steps, taking a reason argument: @@ -213,9 +213,9 @@ impl UnderlyingSourceContainer { Some(Ok(promise)) }, // Note: other source type have no pull steps for now. - UnderlyingSourceType::Transform() => { + UnderlyingSourceType::Transform(stream, _) => { // Return ! TransformStreamDefaultSourcePullAlgorithm(stream). - todo!(); + Some(stream.transform_stream_default_source_pull(&self.global(), can_gc)) }, _ => None, } @@ -280,9 +280,9 @@ impl UnderlyingSourceContainer { // from <https://streams.spec.whatwg.org/#abstract-opdef-setupcrossrealmtransformreadable None }, - UnderlyingSourceType::Transform() => { - // Some(transform_underlying_source.start_algorithm()) - todo!(); + UnderlyingSourceType::Transform(_, start_promise) => { + // Let startAlgorithm be an algorithm that returns startPromise. + Some(Ok(start_promise.clone())) }, _ => None, } diff --git a/components/script/dom/websocket.rs b/components/script/dom/websocket.rs index b9b1b50c901..bbb637dfe28 100644 --- a/components/script/dom/websocket.rs +++ b/components/script/dom/websocket.rs @@ -471,7 +471,7 @@ struct ReportCSPViolationTask { impl TaskOnce for ReportCSPViolationTask { fn run_once(self) { let global = self.websocket.root().global(); - global.report_csp_violations(self.violations); + global.report_csp_violations(self.violations, None); } } diff --git a/components/script/dom/writablestream.rs b/components/script/dom/writablestream.rs index 1b029f592de..f528f4fbde2 100644 --- a/components/script/dom/writablestream.rs +++ b/components/script/dom/writablestream.rs @@ -962,14 +962,13 @@ impl WritableStream { /// <https://streams.spec.whatwg.org/#create-writable-stream> #[cfg_attr(crown, allow(crown::unrooted_must_root))] -#[allow(unused)] pub(crate) fn create_writable_stream( cx: SafeJSContext, global: &GlobalScope, - can_gc: CanGc, writable_high_water_mark: f64, writable_size_algorithm: Rc<QueuingStrategySize>, underlying_sink_type: UnderlyingSinkType, + can_gc: CanGc, ) -> Fallible<DomRoot<WritableStream>> { // Assert: ! IsNonNegativeNumber(highWaterMark) is true. assert!(writable_high_water_mark >= 0.0); diff --git a/components/script/dom/writablestreamdefaultcontroller.rs b/components/script/dom/writablestreamdefaultcontroller.rs index 084165a6892..135ee6faa59 100644 --- a/components/script/dom/writablestreamdefaultcontroller.rs +++ b/components/script/dom/writablestreamdefaultcontroller.rs @@ -12,6 +12,7 @@ use js::jsval::{JSVal, UndefinedValue}; use js::rust::{HandleObject as SafeHandleObject, HandleValue as SafeHandleValue, IntoHandle}; use super::bindings::codegen::Bindings::QueuingStrategyBinding::QueuingStrategySize; +use super::types::TransformStream; use crate::dom::bindings::callback::ExceptionHandling; use crate::dom::bindings::codegen::Bindings::UnderlyingSinkBinding::{ UnderlyingSinkAbortCallback, UnderlyingSinkCloseCallback, UnderlyingSinkStartCallback, @@ -290,8 +291,7 @@ pub enum UnderlyingSinkType { port: Dom<MessagePort>, }, /// Algorithms supporting transform streams are implemented in Rust. - #[allow(unused)] - Transform(/*Dom<TransformStream>, Rc<Promise>*/), + Transform(Dom<TransformStream>, Rc<Promise>), } impl UnderlyingSinkType { @@ -413,7 +413,7 @@ impl WritableStreamDefaultController { } => { backpressure_promise.borrow_mut().take(); }, - UnderlyingSinkType::Transform() => { + UnderlyingSinkType::Transform(_, _) => { return; }, } @@ -423,7 +423,6 @@ impl WritableStreamDefaultController { } /// <https://streams.spec.whatwg.org/#set-up-writable-stream-default-controller> - #[allow(unsafe_code)] pub(crate) fn setup( &self, cx: SafeJSContext, @@ -560,9 +559,9 @@ impl WritableStreamDefaultController { // Let startAlgorithm be an algorithm that returns undefined. Ok(Promise::new_resolved(global, cx, (), can_gc)) }, - UnderlyingSinkType::Transform() => { + UnderlyingSinkType::Transform(_, start_promise) => { // Let startAlgorithm be an algorithm that returns startPromise. - todo!() + Ok(start_promise.clone()) }, } } @@ -622,9 +621,11 @@ impl WritableStreamDefaultController { } promise }, - UnderlyingSinkType::Transform() => { + UnderlyingSinkType::Transform(stream, _) => { // Return ! TransformStreamDefaultSinkAbortAlgorithm(stream, reason). - todo!() + stream + .transform_stream_default_sink_abort_algorithm(cx, global, reason, can_gc) + .expect("Transform stream default sink abort algorithm should not fail.") }, }; @@ -707,9 +708,11 @@ impl WritableStreamDefaultController { .append_native_handler(&handler, comp, can_gc); result_promise }, - UnderlyingSinkType::Transform() => { + UnderlyingSinkType::Transform(stream, _) => { // Return ! TransformStreamDefaultSinkWriteAlgorithm(stream, chunk). - todo!() + stream + .transform_stream_default_sink_write_algorithm(cx, global, chunk, can_gc) + .expect("Transform stream default sink write algorithm should not fail.") }, } } @@ -757,9 +760,11 @@ impl WritableStreamDefaultController { // Return a promise resolved with undefined. Promise::new_resolved(global, cx, (), can_gc) }, - UnderlyingSinkType::Transform() => { + UnderlyingSinkType::Transform(stream, _) => { // Return ! TransformStreamDefaultSinkCloseAlgorithm(stream). - todo!() + stream + .transform_stream_default_sink_close_algorithm(cx, global, can_gc) + .expect("Transform stream default sink close algorithm should not fail.") }, } } @@ -1038,7 +1043,7 @@ impl WritableStreamDefaultController { } /// <https://streams.spec.whatwg.org/#writable-stream-default-controller-error> - fn error( + pub(crate) fn error( &self, stream: &WritableStream, cx: SafeJSContext, diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index 9cef58acc9a..ca5bb72a1dc 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -148,7 +148,7 @@ impl FetchResponseListener for XHRContext { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { let global = &self.resource_timing_global(); - global.report_csp_violations(violations); + global.report_csp_violations(violations, None); } } diff --git a/components/script/fetch.rs b/components/script/fetch.rs index 9192a030b66..989cdba862a 100644 --- a/components/script/fetch.rs +++ b/components/script/fetch.rs @@ -313,7 +313,7 @@ impl FetchResponseListener for FetchContext { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { let global = &self.resource_timing_global(); - global.report_csp_violations(violations); + global.report_csp_violations(violations, None); } } diff --git a/components/script/layout_image.rs b/components/script/layout_image.rs index df542b4b759..546e758e38c 100644 --- a/components/script/layout_image.rs +++ b/components/script/layout_image.rs @@ -81,7 +81,7 @@ impl FetchResponseListener for LayoutImageContext { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { let global = &self.resource_timing_global(); - global.report_csp_violations(violations); + global.report_csp_violations(violations, None); } } diff --git a/components/script/script_module.rs b/components/script/script_module.rs index 0aa35a2eda8..449f17901ed 100644 --- a/components/script/script_module.rs +++ b/components/script/script_module.rs @@ -1277,7 +1277,7 @@ impl FetchResponseListener for ModuleContext { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { let global = &self.resource_timing_global(); - global.report_csp_violations(violations); + global.report_csp_violations(violations, None); } } diff --git a/components/script/script_runtime.rs b/components/script/script_runtime.rs index 1f05c15d74e..c407f9cfc73 100644 --- a/components/script/script_runtime.rs +++ b/components/script/script_runtime.rs @@ -390,7 +390,7 @@ unsafe extern "C" fn content_security_policy_allows( RuntimeCode::WASM => csp_list.is_wasm_evaluation_allowed(), }; - global.report_csp_violations(violations); + global.report_csp_violations(violations, None); allowed = is_evaluation_allowed == CheckResult::Allowed; }); allowed diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 54cf89a213f..d6ab18be49b 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -3606,7 +3606,8 @@ impl ScriptThread { fn handle_csp_violations(&self, id: PipelineId, _: RequestId, violations: Vec<csp::Violation>) { if let Some(global) = self.documents.borrow().find_global(id) { - global.report_csp_violations(violations); + // TODO(https://github.com/w3c/webappsec-csp/issues/687): Update after spec is resolved + global.report_csp_violations(violations, None); } } diff --git a/components/script/security_manager.rs b/components/script/security_manager.rs index ee320206de2..ee062594eb8 100644 --- a/components/script/security_manager.rs +++ b/components/script/security_manager.rs @@ -14,8 +14,7 @@ use crate::dom::bindings::codegen::Bindings::SecurityPolicyViolationEventBinding }; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::refcounted::Trusted; -use crate::dom::bindings::reflector::DomGlobal; -use crate::dom::event::{Event, EventBubbles, EventCancelable}; +use crate::dom::event::{Event, EventBubbles, EventCancelable, EventComposed}; use crate::dom::eventtarget::EventTarget; use crate::dom::securitypolicyviolationevent::SecurityPolicyViolationEvent; use crate::dom::types::GlobalScope; @@ -23,6 +22,7 @@ use crate::script_runtime::CanGc; use crate::task::TaskOnce; pub(crate) struct CSPViolationReportTask { + global: Trusted<GlobalScope>, event_target: Trusted<EventTarget>, violation_report: SecurityPolicyViolationReport, } @@ -159,28 +159,31 @@ impl CSPViolationReportBuilder { impl CSPViolationReportTask { pub fn new( - global: &GlobalScope, - report: SecurityPolicyViolationReport, + global: Trusted<GlobalScope>, + event_target: Trusted<EventTarget>, + violation_report: SecurityPolicyViolationReport, ) -> CSPViolationReportTask { CSPViolationReportTask { - violation_report: report, - event_target: Trusted::new(global.upcast::<EventTarget>()), + global, + event_target, + violation_report, } } fn fire_violation_event(self, can_gc: CanGc) { - let target = self.event_target.root(); - let global = &target.global(); let event = SecurityPolicyViolationEvent::new( - global, + &self.global.root(), Atom::from("securitypolicyviolation"), EventBubbles::Bubbles, EventCancelable::Cancelable, + EventComposed::Composed, &self.violation_report.convert(), can_gc, ); - event.upcast::<Event>().fire(&target, can_gc); + event + .upcast::<Event>() + .fire(&self.event_target.root(), can_gc); } } diff --git a/components/script/stylesheet_loader.rs b/components/script/stylesheet_loader.rs index 67e186c7f6a..a18d63e323b 100644 --- a/components/script/stylesheet_loader.rs +++ b/components/script/stylesheet_loader.rs @@ -286,7 +286,7 @@ impl FetchResponseListener for StylesheetContext { fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<csp::Violation>) { let global = &self.resource_timing_global(); - global.report_csp_violations(violations); + global.report_csp_violations(violations, None); } } diff --git a/components/script/webdriver_handlers.rs b/components/script/webdriver_handlers.rs index f90f3024a70..330ae4f0788 100644 --- a/components/script/webdriver_handlers.rs +++ b/components/script/webdriver_handlers.rs @@ -199,7 +199,7 @@ unsafe fn is_arguments_object(cx: *mut JSContext, value: HandleValue) -> bool { jsstring_to_str(cx, class_name) == "[object Arguments]" } -#[derive(Eq, Hash, PartialEq)] +#[derive(Clone, Eq, Hash, PartialEq)] struct HashableJSVal(u64); impl From<HandleValue<'_>> for HashableJSVal { @@ -209,6 +209,7 @@ impl From<HandleValue<'_>> for HashableJSVal { } #[allow(unsafe_code)] +/// <https://w3c.github.io/webdriver/#dfn-json-deserialize> pub(crate) fn jsval_to_webdriver( cx: SafeJSContext, global_scope: &GlobalScope, @@ -231,12 +232,6 @@ unsafe fn jsval_to_webdriver_inner( val: HandleValue, seen: &mut HashSet<HashableJSVal>, ) -> WebDriverJSResult { - let hashable = val.into(); - if seen.contains(&hashable) { - return Err(WebDriverJSError::JSError); - } - seen.insert(hashable); - let _ac = enter_realm(global_scope); if val.get().is_undefined() { Ok(WebDriverJSValue::Undefined) @@ -268,14 +263,26 @@ unsafe fn jsval_to_webdriver_inner( _ => unreachable!(), }; Ok(WebDriverJSValue::String(String::from(string))) - } else if val.get().is_object() { + } + // https://w3c.github.io/webdriver/#dfn-clone-an-object + else if val.get().is_object() { + let hashable = val.into(); + // Step 1. If value is in `seen`, return error with error code javascript error. + if seen.contains(&hashable) { + return Err(WebDriverJSError::JSError); + } + //Step 2. Append value to `seen`. + seen.insert(hashable.clone()); + rooted!(in(cx) let object = match FromJSValConvertible::from_jsval(cx, val, ()).unwrap() { ConversionResult::Success(object) => object, _ => unreachable!(), }); let _ac = JSAutoRealm::new(cx, *object); - if is_array_like::<crate::DomTypeHolder>(cx, val) || is_arguments_object(cx, val) { + let return_val = if is_array_like::<crate::DomTypeHolder>(cx, val) || + is_arguments_object(cx, val) + { let mut result: Vec<WebDriverJSValue> = Vec::new(); let length = match get_property::<u32>( @@ -298,7 +305,7 @@ unsafe fn jsval_to_webdriver_inner( return Err(WebDriverJSError::JSError); }, }; - + // Step 4. For each enumerable property in value, run the following substeps: for i in 0..length { rooted!(in(cx) let mut item = UndefinedValue()); match get_property_jsval(cx, object.handle(), &i.to_string(), item.handle_mut()) { @@ -319,7 +326,6 @@ unsafe fn jsval_to_webdriver_inner( }, } } - Ok(WebDriverJSValue::ArrayLike(result)) } else if let Ok(element) = root_from_object::<Element>(*object, cx) { Ok(WebDriverJSValue::Element(WebElement( @@ -328,7 +334,7 @@ unsafe fn jsval_to_webdriver_inner( } else if let Ok(window) = root_from_object::<Window>(*object, cx) { let window_proxy = window.window_proxy(); if window_proxy.is_browsing_context_discarded() { - Err(WebDriverJSError::StaleElementReference) + return Err(WebDriverJSError::StaleElementReference); } else if window_proxy.browsing_context_id() == window_proxy.webview_id() { Ok(WebDriverJSValue::Window(WebWindow( window.Document().upcast::<Node>().unique_id(), @@ -348,7 +354,12 @@ unsafe fn jsval_to_webdriver_inner( &HandleValueArray::empty(), value.handle_mut(), ) { - jsval_to_webdriver_inner(cx, global_scope, value.handle(), seen) + Ok(jsval_to_webdriver_inner( + cx, + global_scope, + value.handle(), + seen, + )?) } else { throw_dom_exception( SafeJSContext::from_ptr(cx), @@ -356,7 +367,7 @@ unsafe fn jsval_to_webdriver_inner( Error::JSFailed, CanGc::note(), ); - Err(WebDriverJSError::JSError) + return Err(WebDriverJSError::JSError); } } else { let mut result = HashMap::new(); @@ -408,9 +419,12 @@ unsafe fn jsval_to_webdriver_inner( } } } - Ok(WebDriverJSValue::Object(result)) - } + }; + // Step 5. Remove the last element of `seen`. + seen.remove(&hashable); + // Step 6. Return success with data `result`. + return_val } else { Err(WebDriverJSError::UnknownType) } diff --git a/components/script_bindings/webidls/TransformStream.webidl b/components/script_bindings/webidls/TransformStream.webidl new file mode 100644 index 00000000000..c36a49b114a --- /dev/null +++ b/components/script_bindings/webidls/TransformStream.webidl @@ -0,0 +1,18 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * The origin of this IDL file is + * https://streams.spec.whatwg.org/#ts-class-definition + */ + +[Exposed=*] // [Transferable] - See Bug 1562065 +interface TransformStream { + [Throws] + constructor(optional object transformer, + optional QueuingStrategy writableStrategy = {}, + optional QueuingStrategy readableStrategy = {}); + + readonly attribute ReadableStream readable; + readonly attribute WritableStream writable; +}; diff --git a/components/script_bindings/webidls/TransformStreamDefaultController.webidl b/components/script_bindings/webidls/TransformStreamDefaultController.webidl new file mode 100644 index 00000000000..5f5511ed4b6 --- /dev/null +++ b/components/script_bindings/webidls/TransformStreamDefaultController.webidl @@ -0,0 +1,15 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * The origin of this IDL file is + * https://streams.spec.whatwg.org/#ts-default-controller-class-definition + */ + +[Exposed=*] +interface TransformStreamDefaultController { + readonly attribute unrestricted double? desiredSize; + [Throws] undefined enqueue(optional any chunk); + [Throws] undefined error(optional any reason); + [Throws] undefined terminate(); +}; diff --git a/components/script_bindings/webidls/Transformer.webidl b/components/script_bindings/webidls/Transformer.webidl new file mode 100644 index 00000000000..652511450a4 --- /dev/null +++ b/components/script_bindings/webidls/Transformer.webidl @@ -0,0 +1,22 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * The origin of this IDL file is + * https://streams.spec.whatwg.org/#transformer-api + */ + +[GenerateInit] +dictionary Transformer { + TransformerStartCallback start; + TransformerTransformCallback transform; + TransformerFlushCallback flush; + TransformerCancelCallback cancel; + any readableType; + any writableType; +}; + +callback TransformerStartCallback = any (TransformStreamDefaultController controller); +callback TransformerFlushCallback = Promise<undefined> (TransformStreamDefaultController controller); +callback TransformerTransformCallback = Promise<undefined> (any chunk, TransformStreamDefaultController controller); +callback TransformerCancelCallback = Promise<undefined> (any reason); diff --git a/components/webgl/Cargo.toml b/components/webgl/Cargo.toml index b0c1c0ceb29..542a3cb4fae 100644 --- a/components/webgl/Cargo.toml +++ b/components/webgl/Cargo.toml @@ -26,6 +26,7 @@ fnv = { workspace = true } glow = { workspace = true } half = "2" ipc-channel = { workspace = true } +itertools = { workspace = true } log = { workspace = true } pixels = { path = "../pixels" } snapshot = { workspace = true } diff --git a/components/webgl/webgl_thread.rs b/components/webgl/webgl_thread.rs index b1ac2b2d3c4..9562c4cb4e0 100644 --- a/components/webgl/webgl_thread.rs +++ b/components/webgl/webgl_thread.rs @@ -32,6 +32,7 @@ use glow::{ }; use half::f16; use ipc_channel::ipc::IpcSharedMemory; +use itertools::Itertools; use log::{debug, error, trace, warn}; use pixels::{self, PixelFormat, unmultiply_inplace}; use surfman::chains::{PreserveBuffer, SwapChains, SwapChainsAPI}; @@ -2570,24 +2571,10 @@ impl WebGLImpl { chan.send((range_min, range_max, precision)).unwrap(); } - fn get_extensions(gl: &Gl, chan: &WebGLSender<String>) { - let mut ext_count = [0]; - unsafe { - gl.get_parameter_i32_slice(gl::NUM_EXTENSIONS, &mut ext_count); - } - // Fall back to the depricated extensions API if that fails - if unsafe { gl.get_error() } != gl::NO_ERROR { - chan.send(unsafe { gl.get_parameter_string(gl::EXTENSIONS) }) - .unwrap(); - return; - } - let ext_count = ext_count[0] as usize; - let mut extensions = Vec::with_capacity(ext_count); - for idx in 0..ext_count { - extensions.push(unsafe { gl.get_parameter_indexed_string(gl::EXTENSIONS, idx as u32) }) - } - let extensions = extensions.join(" "); - chan.send(extensions).unwrap(); + /// This is an implementation of `getSupportedExtensions()` from + /// <https://registry.khronos.org/webgl/specs/latest/1.0/#5.14> + fn get_extensions(gl: &Gl, result_sender: &WebGLSender<String>) { + let _ = result_sender.send(gl.supported_extensions().iter().join(" ")); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6 diff --git a/ports/servoshell/prefs.rs b/ports/servoshell/prefs.rs index a2efe3bab3b..a3ebda231d0 100644 --- a/ports/servoshell/prefs.rs +++ b/ports/servoshell/prefs.rs @@ -428,7 +428,11 @@ pub(crate) fn parse_command_line_arguments(args: Vec<String>) -> ArgumentParsing #[cfg(target_env = "ohos")] let log_filter = { let filters = opt_match.opt_strs("log-filter").join(","); - (!filters.is_empty()).then_some(filters) + let log_filter = (!filters.is_empty()).then_some(filters).or_else(|| { + (!preferences.log_filter.is_empty()).then_some(preferences.log_filter.clone()) + }); + log::debug!("Set log_filter to: {:?}", log_filter); + log_filter }; let mut debug_options = DebugOptions::default(); diff --git a/tests/wpt/include.ini b/tests/wpt/include.ini index ba81ab64b83..8ea1e50b8d0 100644 --- a/tests/wpt/include.ini +++ b/tests/wpt/include.ini @@ -256,6 +256,8 @@ skip: true skip: true [writable-streams] skip: false + [transform-streams] + skip: false [subresource-integrity] skip: false [touch-events] diff --git a/tests/wpt/meta/MANIFEST.json b/tests/wpt/meta/MANIFEST.json index df2beac06bd..893b07e9e3f 100644 --- a/tests/wpt/meta/MANIFEST.json +++ b/tests/wpt/meta/MANIFEST.json @@ -569742,7 +569742,7 @@ ] ], "icon-blocked.sub.html": [ - "cc882347a1ac7b595275c2263ef266826e6f07bd", + "4c39e5dec735c10635a603356367610d3aad3fa2", [ null, {} @@ -569797,6 +569797,13 @@ {} ] ], + "img-src-targeting.html": [ + "3b4fe7c690b0b980a9626de0deb02c8950f5d4a0", + [ + null, + {} + ] + ], "img-src-wildcard-allowed.html": [ "050a4d14100bb1ef719d6700bfbd37a97424af59", [ diff --git a/tests/wpt/meta/content-security-policy/gen/top.http-rp/script-src-self/script-tag.http.html.ini b/tests/wpt/meta/content-security-policy/gen/top.http-rp/script-src-self/script-tag.http.html.ini index e29f4dd5d4e..5891a18681e 100644 --- a/tests/wpt/meta/content-security-policy/gen/top.http-rp/script-src-self/script-tag.http.html.ini +++ b/tests/wpt/meta/content-security-policy/gen/top.http-rp/script-src-self/script-tag.http.html.ini @@ -1,13 +1,4 @@ [script-tag.http.html] - [Content Security Policy: Expects blocked for script-tag to cross-http origin and keep-origin redirection from http context.: securitypolicyviolation] - expected: FAIL - - [Content Security Policy: Expects blocked for script-tag to cross-http origin and no-redirect redirection from http context.: securitypolicyviolation] - expected: FAIL - - [Content Security Policy: Expects blocked for script-tag to cross-http origin and swap-origin redirection from http context.: securitypolicyviolation] - expected: FAIL - [Content Security Policy: Expects blocked for script-tag to same-http origin and swap-origin redirection from http context.] expected: FAIL diff --git a/tests/wpt/meta/content-security-policy/gen/top.http-rp/script-src-self/script-tag.https.html.ini b/tests/wpt/meta/content-security-policy/gen/top.http-rp/script-src-self/script-tag.https.html.ini index bbe30519d0b..699a0dd6238 100644 --- a/tests/wpt/meta/content-security-policy/gen/top.http-rp/script-src-self/script-tag.https.html.ini +++ b/tests/wpt/meta/content-security-policy/gen/top.http-rp/script-src-self/script-tag.https.html.ini @@ -1,13 +1,4 @@ [script-tag.https.html] - [Content Security Policy: Expects blocked for script-tag to cross-https origin and keep-origin redirection from https context.: securitypolicyviolation] - expected: FAIL - - [Content Security Policy: Expects blocked for script-tag to cross-https origin and no-redirect redirection from https context.: securitypolicyviolation] - expected: FAIL - - [Content Security Policy: Expects blocked for script-tag to cross-https origin and swap-origin redirection from https context.: securitypolicyviolation] - expected: FAIL - [Content Security Policy: Expects blocked for script-tag to same-https origin and swap-origin redirection from https context.] expected: FAIL diff --git a/tests/wpt/meta/content-security-policy/gen/top.meta/script-src-self/script-tag.http.html.ini b/tests/wpt/meta/content-security-policy/gen/top.meta/script-src-self/script-tag.http.html.ini index e29f4dd5d4e..5891a18681e 100644 --- a/tests/wpt/meta/content-security-policy/gen/top.meta/script-src-self/script-tag.http.html.ini +++ b/tests/wpt/meta/content-security-policy/gen/top.meta/script-src-self/script-tag.http.html.ini @@ -1,13 +1,4 @@ [script-tag.http.html] - [Content Security Policy: Expects blocked for script-tag to cross-http origin and keep-origin redirection from http context.: securitypolicyviolation] - expected: FAIL - - [Content Security Policy: Expects blocked for script-tag to cross-http origin and no-redirect redirection from http context.: securitypolicyviolation] - expected: FAIL - - [Content Security Policy: Expects blocked for script-tag to cross-http origin and swap-origin redirection from http context.: securitypolicyviolation] - expected: FAIL - [Content Security Policy: Expects blocked for script-tag to same-http origin and swap-origin redirection from http context.] expected: FAIL diff --git a/tests/wpt/meta/content-security-policy/gen/top.meta/script-src-self/script-tag.https.html.ini b/tests/wpt/meta/content-security-policy/gen/top.meta/script-src-self/script-tag.https.html.ini index bbe30519d0b..699a0dd6238 100644 --- a/tests/wpt/meta/content-security-policy/gen/top.meta/script-src-self/script-tag.https.html.ini +++ b/tests/wpt/meta/content-security-policy/gen/top.meta/script-src-self/script-tag.https.html.ini @@ -1,13 +1,4 @@ [script-tag.https.html] - [Content Security Policy: Expects blocked for script-tag to cross-https origin and keep-origin redirection from https context.: securitypolicyviolation] - expected: FAIL - - [Content Security Policy: Expects blocked for script-tag to cross-https origin and no-redirect redirection from https context.: securitypolicyviolation] - expected: FAIL - - [Content Security Policy: Expects blocked for script-tag to cross-https origin and swap-origin redirection from https context.: securitypolicyviolation] - expected: FAIL - [Content Security Policy: Expects blocked for script-tag to same-https origin and swap-origin redirection from https context.] expected: FAIL diff --git a/tests/wpt/meta/content-security-policy/navigation/to-javascript-url-script-src.html.ini b/tests/wpt/meta/content-security-policy/navigation/to-javascript-url-script-src.html.ini deleted file mode 100644 index 213ed2d4692..00000000000 --- a/tests/wpt/meta/content-security-policy/navigation/to-javascript-url-script-src.html.ini +++ /dev/null @@ -1,13 +0,0 @@ -[to-javascript-url-script-src.html] - expected: TIMEOUT - [<iframe src='javascript:'> blocked without 'unsafe-inline'.] - expected: TIMEOUT - - [<iframe> navigated to 'javascript:' blocked without 'unsafe-inline'.] - expected: NOTRUN - - [<iframe src='...'> with 'unsafe-inline' navigated to 'javascript:' blocked in this document] - expected: NOTRUN - - [<iframe src='...'> without 'unsafe-inline' navigated to 'javascript:' blocked in this document.] - expected: NOTRUN diff --git a/tests/wpt/meta/content-security-policy/reporting/report-original-url.sub.html.ini b/tests/wpt/meta/content-security-policy/reporting/report-original-url.sub.html.ini index 9d64a7e6bc4..66a2ee93f3b 100644 --- a/tests/wpt/meta/content-security-policy/reporting/report-original-url.sub.html.ini +++ b/tests/wpt/meta/content-security-policy/reporting/report-original-url.sub.html.ini @@ -1,11 +1,5 @@ [report-original-url.sub.html] expected: TIMEOUT - [Direct block, same-origin = full URL in report] - expected: TIMEOUT - - [Direct block, cross-origin = full URL in report] - expected: TIMEOUT - [Block after redirect, same-origin = original URL in report] expected: TIMEOUT diff --git a/tests/wpt/meta/content-security-policy/script-src/script-src-report-only-policy-works-with-hash-policy.html.ini b/tests/wpt/meta/content-security-policy/script-src/script-src-report-only-policy-works-with-hash-policy.html.ini deleted file mode 100644 index 31bfeae4a12..00000000000 --- a/tests/wpt/meta/content-security-policy/script-src/script-src-report-only-policy-works-with-hash-policy.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[script-src-report-only-policy-works-with-hash-policy.html] - expected: TIMEOUT - [Test that the securitypolicyviolation event is fired] - expected: NOTRUN diff --git a/tests/wpt/meta/content-security-policy/securitypolicyviolation/blockeduri-eval.html.ini b/tests/wpt/meta/content-security-policy/securitypolicyviolation/blockeduri-eval.html.ini deleted file mode 100644 index bebd42f2743..00000000000 --- a/tests/wpt/meta/content-security-policy/securitypolicyviolation/blockeduri-eval.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[blockeduri-eval.html] - expected: TIMEOUT - [Eval violations have a blockedURI of 'eval'] - expected: TIMEOUT diff --git a/tests/wpt/meta/content-security-policy/securitypolicyviolation/blockeduri-inline.html.ini b/tests/wpt/meta/content-security-policy/securitypolicyviolation/blockeduri-inline.html.ini index 9c191e43078..3d0febce2b5 100644 --- a/tests/wpt/meta/content-security-policy/securitypolicyviolation/blockeduri-inline.html.ini +++ b/tests/wpt/meta/content-security-policy/securitypolicyviolation/blockeduri-inline.html.ini @@ -1,4 +1,3 @@ [blockeduri-inline.html] - expected: TIMEOUT [Inline violations have a blockedURI of 'inline'] - expected: TIMEOUT + expected: FAIL diff --git a/tests/wpt/meta/content-security-policy/securitypolicyviolation/blockeduri-ws-wss-scheme.html.ini b/tests/wpt/meta/content-security-policy/securitypolicyviolation/blockeduri-ws-wss-scheme.html.ini index 6ebb357445f..14fa5353a94 100644 --- a/tests/wpt/meta/content-security-policy/securitypolicyviolation/blockeduri-ws-wss-scheme.html.ini +++ b/tests/wpt/meta/content-security-policy/securitypolicyviolation/blockeduri-ws-wss-scheme.html.ini @@ -1,13 +1,3 @@ [blockeduri-ws-wss-scheme.html] - expected: TIMEOUT - [ws] - expected: FAIL - - [wss] - expected: FAIL - - [cross-origin] - expected: FAIL - [redirect] - expected: TIMEOUT + expected: FAIL diff --git a/tests/wpt/meta/content-security-policy/securitypolicyviolation/linenumber.tentative.html.ini b/tests/wpt/meta/content-security-policy/securitypolicyviolation/linenumber.tentative.html.ini index fed78a0aa49..e8114229ab9 100644 --- a/tests/wpt/meta/content-security-policy/securitypolicyviolation/linenumber.tentative.html.ini +++ b/tests/wpt/meta/content-security-policy/securitypolicyviolation/linenumber.tentative.html.ini @@ -1,4 +1,3 @@ [linenumber.tentative.html] - expected: TIMEOUT [linenumber] - expected: NOTRUN + expected: FAIL diff --git a/tests/wpt/meta/content-security-policy/securitypolicyviolation/script-sample-no-opt-in.html.ini b/tests/wpt/meta/content-security-policy/securitypolicyviolation/script-sample-no-opt-in.html.ini index b12f81377d1..409022079e0 100644 --- a/tests/wpt/meta/content-security-policy/securitypolicyviolation/script-sample-no-opt-in.html.ini +++ b/tests/wpt/meta/content-security-policy/securitypolicyviolation/script-sample-no-opt-in.html.ini @@ -1,13 +1,7 @@ [script-sample-no-opt-in.html] expected: TIMEOUT - [Inline script should not have a sample.] - expected: TIMEOUT - - [Inline event handlers should not have a sample.] - expected: TIMEOUT - [JavaScript URLs in iframes should not have a sample.] expected: TIMEOUT - [eval()-alikes should not have a sample.] + [Inline event handlers should not have a sample.] expected: TIMEOUT diff --git a/tests/wpt/meta/content-security-policy/securitypolicyviolation/script-sample.html.ini b/tests/wpt/meta/content-security-policy/securitypolicyviolation/script-sample.html.ini index f4c315396f6..8723775f27e 100644 --- a/tests/wpt/meta/content-security-policy/securitypolicyviolation/script-sample.html.ini +++ b/tests/wpt/meta/content-security-policy/securitypolicyviolation/script-sample.html.ini @@ -1,19 +1,7 @@ [script-sample.html] expected: TIMEOUT - [Inline script should have a sample.] - expected: TIMEOUT - - [Inline event handlers should have a sample.] - expected: TIMEOUT - [JavaScript URLs in iframes should have a sample.] expected: TIMEOUT - [eval() should have a sample.] - expected: TIMEOUT - - [setInterval() should have a sample.] - expected: TIMEOUT - - [setTimeout() should have a sample.] + [Inline event handlers should have a sample.] expected: TIMEOUT diff --git a/tests/wpt/meta/content-security-policy/securitypolicyviolation/source-file-blob-scheme.html.ini b/tests/wpt/meta/content-security-policy/securitypolicyviolation/source-file-blob-scheme.html.ini index 03d164a4050..514f91961e3 100644 --- a/tests/wpt/meta/content-security-policy/securitypolicyviolation/source-file-blob-scheme.html.ini +++ b/tests/wpt/meta/content-security-policy/securitypolicyviolation/source-file-blob-scheme.html.ini @@ -1,4 +1,3 @@ [source-file-blob-scheme.html] - expected: TIMEOUT [Violations from data:-URL scripts have a sourceFile of 'blob'] - expected: TIMEOUT + expected: FAIL diff --git a/tests/wpt/meta/content-security-policy/securitypolicyviolation/source-file-data-scheme.html.ini b/tests/wpt/meta/content-security-policy/securitypolicyviolation/source-file-data-scheme.html.ini index 387a7e2ff98..ed4dba7d3c3 100644 --- a/tests/wpt/meta/content-security-policy/securitypolicyviolation/source-file-data-scheme.html.ini +++ b/tests/wpt/meta/content-security-policy/securitypolicyviolation/source-file-data-scheme.html.ini @@ -1,4 +1,3 @@ [source-file-data-scheme.html] - expected: TIMEOUT [Violations from data:-URL scripts have a sourceFile of 'data'] - expected: TIMEOUT + expected: FAIL diff --git a/tests/wpt/meta/content-security-policy/securitypolicyviolation/style-sample-no-opt-in.html.ini b/tests/wpt/meta/content-security-policy/securitypolicyviolation/style-sample-no-opt-in.html.ini index eb10ad61b2c..ef89e7cb1a9 100644 --- a/tests/wpt/meta/content-security-policy/securitypolicyviolation/style-sample-no-opt-in.html.ini +++ b/tests/wpt/meta/content-security-policy/securitypolicyviolation/style-sample-no-opt-in.html.ini @@ -1,7 +1,4 @@ [style-sample-no-opt-in.html] expected: TIMEOUT - [Inline style blocks should not have a sample.] - expected: TIMEOUT - [Inline style attributes should not have a sample.] expected: TIMEOUT diff --git a/tests/wpt/meta/content-security-policy/securitypolicyviolation/style-sample.html.ini b/tests/wpt/meta/content-security-policy/securitypolicyviolation/style-sample.html.ini index 460e21bd6cd..63e278182d8 100644 --- a/tests/wpt/meta/content-security-policy/securitypolicyviolation/style-sample.html.ini +++ b/tests/wpt/meta/content-security-policy/securitypolicyviolation/style-sample.html.ini @@ -1,7 +1,4 @@ [style-sample.html] expected: TIMEOUT - [Inline style blocks should have a sample.] - expected: TIMEOUT - [Inline style attributes should have a sample.] expected: TIMEOUT diff --git a/tests/wpt/meta/content-security-policy/securitypolicyviolation/targeting.html.ini b/tests/wpt/meta/content-security-policy/securitypolicyviolation/targeting.html.ini index 88da5e48238..952c5185dd8 100644 --- a/tests/wpt/meta/content-security-policy/securitypolicyviolation/targeting.html.ini +++ b/tests/wpt/meta/content-security-policy/securitypolicyviolation/targeting.html.ini @@ -4,13 +4,10 @@ expected: NOTRUN [Inline violations target the right element.] - expected: TIMEOUT + expected: FAIL [Correct targeting inside shadow tree (inline handler).] expected: TIMEOUT - [Correct targeting inside shadow tree (style).] - expected: TIMEOUT - [Elements created in this document, but pushed into a same-origin frame trigger on that frame's document, not on this frame's document.] expected: TIMEOUT diff --git a/tests/wpt/meta/content-security-policy/style-src/style-src-hash-blocked.html.ini b/tests/wpt/meta/content-security-policy/style-src/style-src-hash-blocked.html.ini deleted file mode 100644 index f63f4a41072..00000000000 --- a/tests/wpt/meta/content-security-policy/style-src/style-src-hash-blocked.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[style-src-hash-blocked.html] - expected: TIMEOUT - [Should fire a securitypolicyviolation event] - expected: NOTRUN diff --git a/tests/wpt/meta/content-security-policy/style-src/style-src-imported-style-blocked.html.ini b/tests/wpt/meta/content-security-policy/style-src/style-src-imported-style-blocked.html.ini deleted file mode 100644 index fba57c0f24f..00000000000 --- a/tests/wpt/meta/content-security-policy/style-src/style-src-imported-style-blocked.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[style-src-imported-style-blocked.html] - expected: TIMEOUT - [Should fire a securitypolicyviolation event] - expected: NOTRUN diff --git a/tests/wpt/meta/content-security-policy/style-src/style-src-injected-inline-style-blocked.html.ini b/tests/wpt/meta/content-security-policy/style-src/style-src-injected-inline-style-blocked.html.ini deleted file mode 100644 index d77abcc7908..00000000000 --- a/tests/wpt/meta/content-security-policy/style-src/style-src-injected-inline-style-blocked.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[style-src-injected-inline-style-blocked.html] - expected: TIMEOUT - [Should fire a securitypolicyviolation event] - expected: NOTRUN diff --git a/tests/wpt/meta/content-security-policy/style-src/style-src-injected-stylesheet-blocked.sub.html.ini b/tests/wpt/meta/content-security-policy/style-src/style-src-injected-stylesheet-blocked.sub.html.ini deleted file mode 100644 index 0b431bab548..00000000000 --- a/tests/wpt/meta/content-security-policy/style-src/style-src-injected-stylesheet-blocked.sub.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[style-src-injected-stylesheet-blocked.sub.html] - expected: TIMEOUT - [Should fire a securitypolicyviolation event] - expected: NOTRUN diff --git a/tests/wpt/meta/content-security-policy/style-src/style-src-inline-style-blocked.html.ini b/tests/wpt/meta/content-security-policy/style-src/style-src-inline-style-blocked.html.ini deleted file mode 100644 index 3884b98ae92..00000000000 --- a/tests/wpt/meta/content-security-policy/style-src/style-src-inline-style-blocked.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[style-src-inline-style-blocked.html] - expected: TIMEOUT - [Should fire a securitypolicyviolation event] - expected: NOTRUN diff --git a/tests/wpt/meta/content-security-policy/style-src/style-src-inline-style-nonce-blocked-error-event.html.ini b/tests/wpt/meta/content-security-policy/style-src/style-src-inline-style-nonce-blocked-error-event.html.ini index 63a1c9b6240..eb2f1c46fbb 100644 --- a/tests/wpt/meta/content-security-policy/style-src/style-src-inline-style-nonce-blocked-error-event.html.ini +++ b/tests/wpt/meta/content-security-policy/style-src/style-src-inline-style-nonce-blocked-error-event.html.ini @@ -1,7 +1,4 @@ [style-src-inline-style-nonce-blocked-error-event.html] expected: TIMEOUT - [Should fire a securitypolicyviolation event] - expected: NOTRUN - [Test that paragraph remains unmodified and error events received.] expected: NOTRUN diff --git a/tests/wpt/meta/content-security-policy/style-src/style-src-inline-style-nonce-blocked.html.ini b/tests/wpt/meta/content-security-policy/style-src/style-src-inline-style-nonce-blocked.html.ini deleted file mode 100644 index f2eac484989..00000000000 --- a/tests/wpt/meta/content-security-policy/style-src/style-src-inline-style-nonce-blocked.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[style-src-inline-style-nonce-blocked.html] - expected: TIMEOUT - [Should fire a securitypolicyviolation event] - expected: NOTRUN diff --git a/tests/wpt/meta/content-security-policy/style-src/style-src-none-blocked.html.ini b/tests/wpt/meta/content-security-policy/style-src/style-src-none-blocked.html.ini deleted file mode 100644 index c3014b37c31..00000000000 --- a/tests/wpt/meta/content-security-policy/style-src/style-src-none-blocked.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[style-src-none-blocked.html] - expected: TIMEOUT - [Should fire a securitypolicyviolation event] - expected: NOTRUN diff --git a/tests/wpt/meta/content-security-policy/style-src/style-src-stylesheet-nonce-blocked.html.ini b/tests/wpt/meta/content-security-policy/style-src/style-src-stylesheet-nonce-blocked.html.ini deleted file mode 100644 index b8645f13da7..00000000000 --- a/tests/wpt/meta/content-security-policy/style-src/style-src-stylesheet-nonce-blocked.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[style-src-stylesheet-nonce-blocked.html] - expected: TIMEOUT - [Should fire a securitypolicyviolation event] - expected: NOTRUN diff --git a/tests/wpt/meta/fetch/metadata/report.https.sub.html.ini b/tests/wpt/meta/fetch/metadata/report.https.sub.html.ini index 058151d81ce..0348be9f384 100644 --- a/tests/wpt/meta/fetch/metadata/report.https.sub.html.ini +++ b/tests/wpt/meta/fetch/metadata/report.https.sub.html.ini @@ -1,2 +1,10 @@ [report.https.sub.html] - expected: TIMEOUT + expected: ERROR + [same-origin report] + expected: TIMEOUT + + [same-site report] + expected: TIMEOUT + + [cross-site report] + expected: TIMEOUT diff --git a/tests/wpt/meta/streams/transferable/transfer-with-messageport.window.js.ini b/tests/wpt/meta/streams/transferable/transfer-with-messageport.window.js.ini index fc885c5a594..a2502281be7 100644 --- a/tests/wpt/meta/streams/transferable/transfer-with-messageport.window.js.ini +++ b/tests/wpt/meta/streams/transferable/transfer-with-messageport.window.js.ini @@ -7,6 +7,3 @@ [Transferring a MessagePort with multiple streams should set `.ports`] expected: FAIL - - [TransformStream must not be serializable] - expected: FAIL diff --git a/tests/wpt/meta/streams/transferable/transform-stream-members.any.js.ini b/tests/wpt/meta/streams/transferable/transform-stream-members.any.js.ini index c5d5f43d1a4..4414054a1cf 100644 --- a/tests/wpt/meta/streams/transferable/transform-stream-members.any.js.ini +++ b/tests/wpt/meta/streams/transferable/transform-stream-members.any.js.ini @@ -10,14 +10,10 @@ [transform-stream-members.any.shadowrealm-in-window.html] expected: ERROR -[transform-stream-members.any.html] - expected: ERROR [transform-stream-members.https.any.shadowrealm-in-serviceworker.html] expected: ERROR -[transform-stream-members.any.worker.html] - expected: ERROR [transform-stream-members.any.shadowrealm-in-dedicatedworker.html] expected: ERROR diff --git a/tests/wpt/meta/streams/transferable/transform-stream.html.ini b/tests/wpt/meta/streams/transferable/transform-stream.html.ini index dc6fe8a6c75..af9a1d42ae7 100644 --- a/tests/wpt/meta/streams/transferable/transform-stream.html.ini +++ b/tests/wpt/meta/streams/transferable/transform-stream.html.ini @@ -2,14 +2,5 @@ [window.postMessage should be able to transfer a TransformStream] expected: FAIL - [a TransformStream with a locked writable should not be transferable] - expected: FAIL - - [a TransformStream with a locked readable should not be transferable] - expected: FAIL - - [a TransformStream with both sides locked should not be transferable] - expected: FAIL - [piping through transferred transforms should work] expected: FAIL diff --git a/tests/wpt/meta/streams/transferable/writable-stream.html.ini b/tests/wpt/meta/streams/transferable/writable-stream.html.ini deleted file mode 100644 index 47326208f88..00000000000 --- a/tests/wpt/meta/streams/transferable/writable-stream.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[writable-stream.html] - [window.postMessage should be able to transfer a {readable, writable} pair] - expected: FAIL diff --git a/tests/wpt/meta/streams/transform-streams/backpressure.any.js.ini b/tests/wpt/meta/streams/transform-streams/backpressure.any.js.ini new file mode 100644 index 00000000000..099d3a6f2e0 --- /dev/null +++ b/tests/wpt/meta/streams/transform-streams/backpressure.any.js.ini @@ -0,0 +1,23 @@ +[backpressure.any.shadowrealm-in-shadowrealm.html] + expected: ERROR + +[backpressure.any.shadowrealm-in-window.html] + expected: ERROR + +[backpressure.any.serviceworker.html] + expected: ERROR + +[backpressure.any.shadowrealm-in-dedicatedworker.html] + expected: ERROR + +[backpressure.any.sharedworker.html] + expected: ERROR + +[backpressure.https.any.shadowrealm-in-serviceworker.html] + expected: ERROR + +[backpressure.any.shadowrealm-in-sharedworker.html] + expected: ERROR + +[backpressure.https.any.shadowrealm-in-audioworklet.html] + expected: ERROR
\ No newline at end of file diff --git a/tests/wpt/meta/streams/transform-streams/cancel.any.js.ini b/tests/wpt/meta/streams/transform-streams/cancel.any.js.ini new file mode 100644 index 00000000000..7e5a1b9af50 --- /dev/null +++ b/tests/wpt/meta/streams/transform-streams/cancel.any.js.ini @@ -0,0 +1,32 @@ +[cancel.any.shadowrealm-in-dedicatedworker.html] + expected: ERROR + +[cancel.any.serviceworker.html] + expected: ERROR + +[cancel.https.any.shadowrealm-in-audioworklet.html] + expected: ERROR + +[cancel.any.shadowrealm-in-sharedworker.html] + expected: ERROR + +[cancel.any.sharedworker.html] + expected: ERROR + +[cancel.any.shadowrealm-in-window.html] + expected: ERROR + +[cancel.any.shadowrealm-in-shadowrealm.html] + expected: ERROR + +[cancel.https.any.shadowrealm-in-serviceworker.html] + expected: ERROR + +[cancel.any.worker.html] + [readable.cancel() and a parallel writable.close() should reject if a transformer.cancel() calls controller.error()] + expected: FAIL + + +[cancel.any.html] + [readable.cancel() and a parallel writable.close() should reject if a transformer.cancel() calls controller.error()] + expected: FAIL diff --git a/tests/wpt/meta/streams/transform-streams/errors.any.js.ini b/tests/wpt/meta/streams/transform-streams/errors.any.js.ini new file mode 100644 index 00000000000..02eaa76ca8e --- /dev/null +++ b/tests/wpt/meta/streams/transform-streams/errors.any.js.ini @@ -0,0 +1,32 @@ +[errors.any.sharedworker.html] + expected: ERROR + +[errors.https.any.shadowrealm-in-serviceworker.html] + expected: ERROR + +[errors.any.shadowrealm-in-sharedworker.html] + expected: ERROR + +[errors.any.shadowrealm-in-shadowrealm.html] + expected: ERROR + +[errors.any.serviceworker.html] + expected: ERROR + +[errors.https.any.shadowrealm-in-audioworklet.html] + expected: ERROR + +[errors.any.shadowrealm-in-dedicatedworker.html] + expected: ERROR + +[errors.any.shadowrealm-in-window.html] + expected: ERROR + +[errors.any.html] + [abort should set the close reason for the writable when it happens before cancel during start, and cancel should reject] + expected: FAIL + + +[errors.any.worker.html] + [abort should set the close reason for the writable when it happens before cancel during start, and cancel should reject] + expected: FAIL diff --git a/tests/wpt/meta/streams/transform-streams/flush.any.js.ini b/tests/wpt/meta/streams/transform-streams/flush.any.js.ini new file mode 100644 index 00000000000..a2ee0101993 --- /dev/null +++ b/tests/wpt/meta/streams/transform-streams/flush.any.js.ini @@ -0,0 +1,23 @@ +[flush.any.shadowrealm-in-dedicatedworker.html] + expected: ERROR + +[flush.any.shadowrealm-in-window.html] + expected: ERROR + +[flush.https.any.shadowrealm-in-audioworklet.html] + expected: ERROR + +[flush.any.shadowrealm-in-sharedworker.html] + expected: ERROR + +[flush.any.shadowrealm-in-shadowrealm.html] + expected: ERROR + +[flush.any.sharedworker.html] + expected: ERROR + +[flush.https.any.shadowrealm-in-serviceworker.html] + expected: ERROR + +[flush.any.serviceworker.html] + expected: ERROR
\ No newline at end of file diff --git a/tests/wpt/meta/streams/transform-streams/general.any.js.ini b/tests/wpt/meta/streams/transform-streams/general.any.js.ini new file mode 100644 index 00000000000..11dfc7d4ece --- /dev/null +++ b/tests/wpt/meta/streams/transform-streams/general.any.js.ini @@ -0,0 +1,23 @@ +[general.any.shadowrealm-in-sharedworker.html] + expected: ERROR + +[general.https.any.shadowrealm-in-serviceworker.html] + expected: ERROR + +[general.any.shadowrealm-in-shadowrealm.html] + expected: ERROR + +[general.any.shadowrealm-in-dedicatedworker.html] + expected: ERROR + +[general.https.any.shadowrealm-in-audioworklet.html] + expected: ERROR + +[general.any.serviceworker.html] + expected: ERROR + +[general.any.shadowrealm-in-window.html] + expected: ERROR + +[general.any.sharedworker.html] + expected: ERROR diff --git a/tests/wpt/meta/streams/transform-streams/lipfuzz.any.js.ini b/tests/wpt/meta/streams/transform-streams/lipfuzz.any.js.ini new file mode 100644 index 00000000000..5af2be4a1ae --- /dev/null +++ b/tests/wpt/meta/streams/transform-streams/lipfuzz.any.js.ini @@ -0,0 +1,23 @@ +[lipfuzz.any.shadowrealm-in-window.html] + expected: ERROR + +[lipfuzz.https.any.shadowrealm-in-serviceworker.html] + expected: ERROR + +[lipfuzz.any.serviceworker.html] + expected: ERROR + +[lipfuzz.any.shadowrealm-in-shadowrealm.html] + expected: ERROR + +[lipfuzz.any.shadowrealm-in-dedicatedworker.html] + expected: ERROR + +[lipfuzz.https.any.shadowrealm-in-audioworklet.html] + expected: ERROR + +[lipfuzz.any.sharedworker.html] + expected: ERROR + +[lipfuzz.any.shadowrealm-in-sharedworker.html] + expected: ERROR diff --git a/tests/wpt/meta/streams/transform-streams/patched-global.any.js.ini b/tests/wpt/meta/streams/transform-streams/patched-global.any.js.ini new file mode 100644 index 00000000000..06a324cb060 --- /dev/null +++ b/tests/wpt/meta/streams/transform-streams/patched-global.any.js.ini @@ -0,0 +1,23 @@ +[patched-global.any.shadowrealm-in-dedicatedworker.html] + expected: ERROR + +[patched-global.any.shadowrealm-in-window.html] + expected: ERROR + +[patched-global.any.shadowrealm-in-sharedworker.html] + expected: ERROR + +[patched-global.https.any.shadowrealm-in-serviceworker.html] + expected: ERROR + +[patched-global.any.shadowrealm-in-shadowrealm.html] + expected: ERROR + +[patched-global.https.any.shadowrealm-in-audioworklet.html] + expected: ERROR + +[patched-global.any.sharedworker.html] + expected: ERROR + +[patched-global.any.serviceworker.html] + expected: ERROR diff --git a/tests/wpt/meta/streams/transform-streams/properties.any.js.ini b/tests/wpt/meta/streams/transform-streams/properties.any.js.ini new file mode 100644 index 00000000000..f5573ee57e4 --- /dev/null +++ b/tests/wpt/meta/streams/transform-streams/properties.any.js.ini @@ -0,0 +1,23 @@ +[properties.any.shadowrealm-in-shadowrealm.html] + expected: ERROR + +[properties.https.any.shadowrealm-in-serviceworker.html] + expected: ERROR + +[properties.any.shadowrealm-in-window.html] + expected: ERROR + +[properties.any.shadowrealm-in-dedicatedworker.html] + expected: ERROR + +[properties.any.sharedworker.html] + expected: ERROR + +[properties.https.any.shadowrealm-in-audioworklet.html] + expected: ERROR + +[properties.any.serviceworker.html] + expected: ERROR + +[properties.any.shadowrealm-in-sharedworker.html] + expected: ERROR diff --git a/tests/wpt/meta/streams/transform-streams/reentrant-strategies.any.js.ini b/tests/wpt/meta/streams/transform-streams/reentrant-strategies.any.js.ini new file mode 100644 index 00000000000..1c6b9fd51da --- /dev/null +++ b/tests/wpt/meta/streams/transform-streams/reentrant-strategies.any.js.ini @@ -0,0 +1,23 @@ +[reentrant-strategies.any.shadowrealm-in-window.html] + expected: ERROR + +[reentrant-strategies.https.any.shadowrealm-in-serviceworker.html] + expected: ERROR + +[reentrant-strategies.any.sharedworker.html] + expected: ERROR + +[reentrant-strategies.https.any.shadowrealm-in-audioworklet.html] + expected: ERROR + +[reentrant-strategies.any.shadowrealm-in-dedicatedworker.html] + expected: ERROR + +[reentrant-strategies.any.serviceworker.html] + expected: ERROR + +[reentrant-strategies.any.shadowrealm-in-sharedworker.html] + expected: ERROR + +[reentrant-strategies.any.shadowrealm-in-shadowrealm.html] + expected: ERROR diff --git a/tests/wpt/meta/streams/transform-streams/strategies.any.js.ini b/tests/wpt/meta/streams/transform-streams/strategies.any.js.ini new file mode 100644 index 00000000000..52c18b67fd4 --- /dev/null +++ b/tests/wpt/meta/streams/transform-streams/strategies.any.js.ini @@ -0,0 +1,24 @@ +[strategies.any.shadowrealm-in-shadowrealm.html] + expected: ERROR + +[strategies.any.serviceworker.html] + expected: ERROR + +[strategies.https.any.shadowrealm-in-serviceworker.html] + expected: ERROR + +[strategies.any.shadowrealm-in-window.html] + expected: ERROR + +[strategies.any.shadowrealm-in-sharedworker.html] + expected: ERROR + +[strategies.any.shadowrealm-in-dedicatedworker.html] + expected: ERROR + +[strategies.any.sharedworker.html] + expected: ERROR + +[strategies.https.any.shadowrealm-in-audioworklet.html] + expected: ERROR + diff --git a/tests/wpt/meta/streams/transform-streams/terminate.any.js.ini b/tests/wpt/meta/streams/transform-streams/terminate.any.js.ini new file mode 100644 index 00000000000..c81b1e40d1e --- /dev/null +++ b/tests/wpt/meta/streams/transform-streams/terminate.any.js.ini @@ -0,0 +1,23 @@ +[terminate.any.serviceworker.html] + expected: ERROR + +[terminate.any.shadowrealm-in-sharedworker.html] + expected: ERROR + +[terminate.https.any.shadowrealm-in-serviceworker.html] + expected: ERROR + +[terminate.any.shadowrealm-in-window.html] + expected: ERROR + +[terminate.any.shadowrealm-in-shadowrealm.html] + expected: ERROR + +[terminate.https.any.shadowrealm-in-audioworklet.html] + expected: ERROR + +[terminate.any.shadowrealm-in-dedicatedworker.html] + expected: ERROR + +[terminate.any.sharedworker.html] + expected: ERROR diff --git a/tests/wpt/meta/trusted-types/default-policy.html.ini b/tests/wpt/meta/trusted-types/default-policy.html.ini index 15588646951..cf57031ddbe 100644 --- a/tests/wpt/meta/trusted-types/default-policy.html.ini +++ b/tests/wpt/meta/trusted-types/default-policy.html.ini @@ -1,7 +1,7 @@ [default-policy.html] - expected: TIMEOUT + expected: OK [Count SecurityPolicyViolation events.] - expected: TIMEOUT + expected: FAIL [div.innerHTML no default policy] expected: FAIL diff --git a/tests/wpt/meta/trusted-types/empty-default-policy.html.ini b/tests/wpt/meta/trusted-types/empty-default-policy.html.ini index 4f06e4c971f..c3f34522557 100644 --- a/tests/wpt/meta/trusted-types/empty-default-policy.html.ini +++ b/tests/wpt/meta/trusted-types/empty-default-policy.html.ini @@ -1,7 +1,7 @@ [empty-default-policy.html] - expected: TIMEOUT + expected: OK [Count SecurityPolicyViolation events.] - expected: TIMEOUT + expected: FAIL [div.innerHTML default] expected: FAIL diff --git a/tests/wpt/meta/wasm/webapi/esm-integration/script-src-blocks-wasm.tentative.sub.html.ini b/tests/wpt/meta/wasm/webapi/esm-integration/script-src-blocks-wasm.tentative.sub.html.ini deleted file mode 100644 index c804530024c..00000000000 --- a/tests/wpt/meta/wasm/webapi/esm-integration/script-src-blocks-wasm.tentative.sub.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[script-src-blocks-wasm.tentative.sub.html] - [Importing a WebAssembly module should be guarded by script-src CSP.] - expected: FAIL diff --git a/tests/wpt/meta/webdriver/tests/classic/execute_async_script/collections.py.ini b/tests/wpt/meta/webdriver/tests/classic/execute_async_script/collections.py.ini index eb7c9dd30ae..710ae93d053 100644 --- a/tests/wpt/meta/webdriver/tests/classic/execute_async_script/collections.py.ini +++ b/tests/wpt/meta/webdriver/tests/classic/execute_async_script/collections.py.ini @@ -1,7 +1,4 @@ [collections.py] - [test_array_in_array] - expected: FAIL - [test_file_list] expected: FAIL diff --git a/tests/wpt/meta/webdriver/tests/classic/execute_script/collections.py.ini b/tests/wpt/meta/webdriver/tests/classic/execute_script/collections.py.ini index ff87e768065..710ae93d053 100644 --- a/tests/wpt/meta/webdriver/tests/classic/execute_script/collections.py.ini +++ b/tests/wpt/meta/webdriver/tests/classic/execute_script/collections.py.ini @@ -4,6 +4,3 @@ [test_html_all_collection] expected: FAIL - - [test_array_in_array] - expected: FAIL diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index 7035ae424dc..296804116f8 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -13575,14 +13575,14 @@ ] ], "interfaces.https.html": [ - "76d746b0663ed73865816e678c2536eceff31f2d", + "72918e837726b58740a491a9223eeeb625055ae5", [ null, {} ] ], "interfaces.worker.js": [ - "8d109502622fac7266a4564de09684a3ab94118c", + "e86f34f261442aeaa7074c525fb4b1206219769d", [ "mozilla/interfaces.worker.html", {} diff --git a/tests/wpt/mozilla/tests/mozilla/interfaces.https.html b/tests/wpt/mozilla/tests/mozilla/interfaces.https.html index 76d746b0663..72918e83772 100644 --- a/tests/wpt/mozilla/tests/mozilla/interfaces.https.html +++ b/tests/wpt/mozilla/tests/mozilla/interfaces.https.html @@ -371,6 +371,8 @@ test_interfaces([ "WritableStream", "WritableStreamDefaultController", "WritableStreamDefaultWriter", + "TransformStream", + "TransformStreamDefaultController", "WGSLLanguageFeatures", "XMLDocument", "XMLHttpRequest", diff --git a/tests/wpt/mozilla/tests/mozilla/interfaces.worker.js b/tests/wpt/mozilla/tests/mozilla/interfaces.worker.js index 8d109502622..e86f34f2614 100644 --- a/tests/wpt/mozilla/tests/mozilla/interfaces.worker.js +++ b/tests/wpt/mozilla/tests/mozilla/interfaces.worker.js @@ -137,6 +137,8 @@ test_interfaces([ "WritableStream", "WritableStreamDefaultController", "WritableStreamDefaultWriter", + "TransformStream", + "TransformStreamDefaultController", "WGSLLanguageFeatures", "XMLHttpRequest", "XMLHttpRequestEventTarget", diff --git a/tests/wpt/tests/content-security-policy/img-src/icon-blocked.sub.html b/tests/wpt/tests/content-security-policy/img-src/icon-blocked.sub.html index cc882347a1a..4c39e5dec73 100644 --- a/tests/wpt/tests/content-security-policy/img-src/icon-blocked.sub.html +++ b/tests/wpt/tests/content-security-policy/img-src/icon-blocked.sub.html @@ -12,6 +12,7 @@ var t_spv = async_test("Test that spv event is fired"); window.addEventListener("securitypolicyviolation", t_spv.step_func_done(function(e) { assert_equals(e.violatedDirective, 'img-src'); + assert_equals(e.target, document); assert_true(e.blockedURI.endsWith('/support/fail.png')); })); diff --git a/tests/wpt/tests/content-security-policy/img-src/img-src-targeting.html b/tests/wpt/tests/content-security-policy/img-src/img-src-targeting.html new file mode 100644 index 00000000000..3b4fe7c690b --- /dev/null +++ b/tests/wpt/tests/content-security-policy/img-src/img-src-targeting.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html> +<head> + <meta http-equiv="Content-Security-Policy" content="img-src 'none';"> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> +</head> +<body> +<p>Check that img-src sets correct target</p> + <script> + var t = async_test("Test that image does not load"); + var t_spv = async_test("Test that spv event is fired"); + window.addEventListener("securitypolicyviolation", t_spv.step_func_done(function(e) { + assert_equals(e.violatedDirective, 'img-src'); + assert_equals(e.target, document); + assert_true(e.blockedURI.endsWith('/support/fail.png')); + })); + </script> + <img src='/content-security-policy/support/fail.png' + onload='t.step(function() { assert_unreached("Image should not have loaded"); t.done(); });' + onerror='t.done();'> +</body> + +</html> |