diff --git a/moli-renderer-v8/src/context_bootstrap/exposed_interfaces/metadata.rs b/moli-renderer-v8/src/context_bootstrap/exposed_interfaces/metadata.rs index 7e8449997d..eee2c8436f 100644 --- a/moli-renderer-v8/src/context_bootstrap/exposed_interfaces/metadata.rs +++ b/moli-renderer-v8/src/context_bootstrap/exposed_interfaces/metadata.rs @@ -53,6 +53,7 @@ pub(in crate::context_bootstrap) const WORKER_SHARED_INTERFACE_NAMES: &[&str] = "Crypto", "SubtleCrypto", "CryptoKey", + "PerformanceServerTiming", "MediaCapabilities", "NavigatorUAData", "Lock", diff --git a/moli-renderer-v8/src/context_bootstrap/specs/registry.rs b/moli-renderer-v8/src/context_bootstrap/specs/registry.rs index 14dd1a4885..3054e60403 100644 --- a/moli-renderer-v8/src/context_bootstrap/specs/registry.rs +++ b/moli-renderer-v8/src/context_bootstrap/specs/registry.rs @@ -580,6 +580,22 @@ const CONSTRUCTOR_SPECS_BEFORE_STREAMS: &[ConstructorSpec] = &[ interface: web_api_interfaces::WebSocketStream::DESCRIPTOR, kind: ConstructorKind::WebSocketStream, }, + ConstructorSpec { + interface: web_api_interfaces::PerformanceServerTiming::DESCRIPTOR, + kind: ConstructorKind::Illegal, + }, + ConstructorSpec { + interface: web_api_interfaces::PerformancePaintTiming::DESCRIPTOR, + kind: ConstructorKind::Illegal, + }, + ConstructorSpec { + interface: web_api_interfaces::PerformanceEventTiming::DESCRIPTOR, + kind: ConstructorKind::Illegal, + }, + ConstructorSpec { + interface: web_api_interfaces::LargestContentfulPaint::DESCRIPTOR, + kind: ConstructorKind::Illegal, + }, ConstructorSpec { interface: web_api_interfaces::Performance::DESCRIPTOR, kind: ConstructorKind::Illegal, diff --git a/moli-renderer-v8/src/script_vm/tests/mod.rs b/moli-renderer-v8/src/script_vm/tests/mod.rs index 486f6018a1..4c21849802 100644 --- a/moli-renderer-v8/src/script_vm/tests/mod.rs +++ b/moli-renderer-v8/src/script_vm/tests/mod.rs @@ -2171,6 +2171,7 @@ mod media_owner_playback_interfaces; mod media_recorder_shell; mod performance_observer_contract; mod performance_receiver_consolidation; +mod performance_timing_interface_exposure_interfaces; mod svg_animation_interfaces; mod svg_computed_path_precision; mod svg_detached_lengths; diff --git a/moli-renderer-v8/src/script_vm/tests/performance_timing_interface_exposure_interfaces.rs b/moli-renderer-v8/src/script_vm/tests/performance_timing_interface_exposure_interfaces.rs new file mode 100644 index 0000000000..6df73d8c52 --- /dev/null +++ b/moli-renderer-v8/src/script_vm/tests/performance_timing_interface_exposure_interfaces.rs @@ -0,0 +1,91 @@ +use super::*; + +#[test] +fn performance_timing_interface_exposure_interfaces_have_realm_local_constructors_and_exposure() { + for url in [ + "https://interface-exposure.test/", + "http://interface-exposure.test/", + ] { + let mut vm = new_storage_test_vm(url); + assert_eq!(vm.eval(r#" +(() => { + const assert = (ok, message) => { if (!ok) throw Error(message); }; + const names = ["LargestContentfulPaint", "PerformanceEventTiming", "PerformancePaintTiming", "PerformanceServerTiming"]; + const parents = {"LargestContentfulPaint": "PerformanceEntry", "PerformanceEventTiming": "PerformanceEntry", "PerformancePaintTiming": "PerformanceEntry", "PerformanceServerTiming": null}; + if (!document.documentElement) document.appendChild(document.createElement('html')); + if (!document.body) document.documentElement.appendChild(document.createElement('body')); + const child = document.createElement('iframe'); + document.body.appendChild(child); + const other = child.contentWindow; + for (const realm of [window, other]) { + for (const name of names) { + const C = realm[name]; + assert(typeof C === 'function' && C.name === name && C.length === 0, name + ' constructor'); + assert(C.prototype.constructor === C, name + ' prototype identity'); + assert(Object.getPrototypeOf(C.prototype) === (parents[name] ? realm[parents[name]].prototype : realm.Object.prototype), name + ' prototype inheritance'); + assert(realm[name] === C, name + ' stable lazy materialization'); + for (const invoke of [() => C(), () => new C(), () => Reflect.construct(C, [], function Subclass() {})]) { + let error; + try { invoke(); } catch (caught) { error = caught; } + assert(error instanceof realm.TypeError, name + ' rejects construction in callee realm'); + } + assert(C !== (realm === window ? other[name] : window[name]), name + ' distinct realm constructors'); + } + } + return 'passed'; +})() +"#).unwrap(), "passed", "{url}"); + } +} + +#[test] +fn performance_timing_interface_exposure_interfaces_worker_exposure_follows_realm_and_security_rules() + { + use crate::context_bootstrap::exposed_interfaces::RealmKind; + use std::pin::pin; + crate::ensure_v8_for_test(); + for realm in [ + RealmKind::DedicatedWorker, + RealmKind::SharedWorker, + RealmKind::ServiceWorker, + ] { + let mut isolate = v8::Isolate::new(Default::default()); + let scope = pin!(v8::HandleScope::new(&mut isolate)); + let scope = &mut scope.init(); + for secure in [false, true] { + let context = v8::Context::new(scope, Default::default()); + let scope = &mut v8::ContextScope::new(scope, context); + let global = context.global(scope); + crate::context_bootstrap::install_worker_lazy_exposed_interfaces( + scope, global, realm, secure, + ) + .expect("worker interfaces"); + let name = "PerformanceServerTiming"; + let expected = true; + let key = crate::util::v8str(scope, name); + assert_eq!( + global.has_own_property(scope, key.into()), + Some(expected), + "{realm:?}/{secure}/{name}" + ); + if expected { + assert!( + global.get(scope, key.into()).unwrap().is_function(), + "{name} materialization" + ); + } + for name in [ + "LargestContentfulPaint", + "PerformanceEventTiming", + "PerformancePaintTiming", + ] { + let key = crate::util::v8str(scope, name); + assert_eq!( + global.has_own_property(scope, key.into()), + Some(false), + "{realm:?}/{name}" + ); + } + } + } +} diff --git a/moli-renderer-v8/src/web_api_interfaces.rs b/moli-renderer-v8/src/web_api_interfaces.rs index 9ab6e495ba..f5aff879cf 100644 --- a/moli-renderer-v8/src/web_api_interfaces.rs +++ b/moli-renderer-v8/src/web_api_interfaces.rs @@ -370,6 +370,10 @@ interfaces! { PageTransitionEvent: Event; Path2D; PaymentResponse: EventTarget; + LargestContentfulPaint: PerformanceEntry; + PerformanceEventTiming: PerformanceEntry; + PerformancePaintTiming: PerformanceEntry; + PerformanceServerTiming; Performance: EventTarget; PerformanceEntry; PerformanceMark: PerformanceEntry;