From 4af3854b8b83da558cc72772fbfb9eb185c1649d Mon Sep 17 00:00:00 2001 From: ldm0 Date: Thu, 1 Oct 2026 22:49:28 +0800 Subject: [PATCH] feat(webrtc): expose non-constructible transport and RTP interfaces --- .../src/context_bootstrap/specs/registry.rs | 32 +++++++++++++++ moli-renderer-v8/src/script_vm/tests/mod.rs | 1 + ...transport_interface_exposure_interfaces.rs | 39 +++++++++++++++++++ moli-renderer-v8/src/web_api_interfaces.rs | 8 ++++ 4 files changed, 80 insertions(+) create mode 100644 moli-renderer-v8/src/script_vm/tests/rtc_transport_interface_exposure_interfaces.rs diff --git a/moli-renderer-v8/src/context_bootstrap/specs/registry.rs b/moli-renderer-v8/src/context_bootstrap/specs/registry.rs index e2175cedbb..5736c508dc 100644 --- a/moli-renderer-v8/src/context_bootstrap/specs/registry.rs +++ b/moli-renderer-v8/src/context_bootstrap/specs/registry.rs @@ -4,6 +4,38 @@ use crate::web_api_interfaces; use std::collections::HashSet; const CONSTRUCTOR_SPECS_BEFORE_STREAMS: &[ConstructorSpec] = &[ + ConstructorSpec { + interface: web_api_interfaces::RTCCertificate::DESCRIPTOR, + kind: ConstructorKind::Illegal, + }, + ConstructorSpec { + interface: web_api_interfaces::RTCDTMFSender::DESCRIPTOR, + kind: ConstructorKind::Illegal, + }, + ConstructorSpec { + interface: web_api_interfaces::RTCDtlsTransport::DESCRIPTOR, + kind: ConstructorKind::Illegal, + }, + ConstructorSpec { + interface: web_api_interfaces::RTCIceTransport::DESCRIPTOR, + kind: ConstructorKind::Illegal, + }, + ConstructorSpec { + interface: web_api_interfaces::RTCRtpSender::DESCRIPTOR, + kind: ConstructorKind::Illegal, + }, + ConstructorSpec { + interface: web_api_interfaces::RTCRtpTransceiver::DESCRIPTOR, + kind: ConstructorKind::Illegal, + }, + ConstructorSpec { + interface: web_api_interfaces::RTCSctpTransport::DESCRIPTOR, + kind: ConstructorKind::Illegal, + }, + ConstructorSpec { + interface: web_api_interfaces::RTCStatsReport::DESCRIPTOR, + kind: ConstructorKind::Illegal, + }, ConstructorSpec { interface: web_api_interfaces::External::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 c36aeb02e0..90f1e16da4 100644 --- a/moli-renderer-v8/src/script_vm/tests/mod.rs +++ b/moli-renderer-v8/src/script_vm/tests/mod.rs @@ -2194,3 +2194,4 @@ mod media_device_interfaces; mod dom_rect_factory_descriptors; mod dom_rect_structured_clone; +mod rtc_transport_interface_exposure_interfaces; diff --git a/moli-renderer-v8/src/script_vm/tests/rtc_transport_interface_exposure_interfaces.rs b/moli-renderer-v8/src/script_vm/tests/rtc_transport_interface_exposure_interfaces.rs new file mode 100644 index 0000000000..78e550af23 --- /dev/null +++ b/moli-renderer-v8/src/script_vm/tests/rtc_transport_interface_exposure_interfaces.rs @@ -0,0 +1,39 @@ +use super::*; + +#[test] +fn rtc_transport_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 = ["RTCCertificate", "RTCDTMFSender", "RTCDtlsTransport", "RTCIceTransport", "RTCRtpSender", "RTCRtpTransceiver", "RTCSctpTransport", "RTCStatsReport"]; + const parents = {"RTCCertificate": null, "RTCDTMFSender": "EventTarget", "RTCDtlsTransport": "EventTarget", "RTCIceTransport": "EventTarget", "RTCRtpSender": null, "RTCRtpTransceiver": null, "RTCSctpTransport": "EventTarget", "RTCStatsReport": 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}"); + } +} diff --git a/moli-renderer-v8/src/web_api_interfaces.rs b/moli-renderer-v8/src/web_api_interfaces.rs index 5c4acccc69..b5a7276edb 100644 --- a/moli-renderer-v8/src/web_api_interfaces.rs +++ b/moli-renderer-v8/src/web_api_interfaces.rs @@ -20,6 +20,14 @@ macro_rules! interfaces { } interfaces! { + RTCCertificate; + RTCDTMFSender: EventTarget; + RTCDtlsTransport: EventTarget; + RTCIceTransport: EventTarget; + RTCRtpSender; + RTCRtpTransceiver; + RTCSctpTransport: EventTarget; + RTCStatsReport; AbortController; AbortSignal: EventTarget; AbstractRange;