mirror of
https://github.com/lexmount/moli.git
synced 2026-10-17 08:01:26 +00:00
feat(webcodecs): expose the native EncodedVideoChunk interface shell
This commit is contained in:
@@ -94,6 +94,11 @@ pub(in crate::context_bootstrap) fn build_constructor_template<'s>(
|
||||
.length(0)
|
||||
.build(scope)
|
||||
}
|
||||
ConstructorKind::Shell { length } => {
|
||||
v8::FunctionTemplate::builder(shell_constructor_callback)
|
||||
.length(i32::from(length))
|
||||
.build(scope)
|
||||
}
|
||||
ConstructorKind::Event => {
|
||||
v8::FunctionTemplate::builder(moli_webapi_declare::web_api_constructor!(
|
||||
web_api_interfaces::Event,
|
||||
|
||||
@@ -21,7 +21,7 @@ mod elements;
|
||||
mod text_codecs;
|
||||
|
||||
pub(super) use core::{
|
||||
event_target_constructor_callback, illegal_constructor_callback,
|
||||
event_target_constructor_callback, illegal_constructor_callback, shell_constructor_callback,
|
||||
unsupported_constructor_callback, xpath_evaluator_constructor_callback,
|
||||
};
|
||||
pub(super) use custom_elements_registry::{
|
||||
|
||||
@@ -41,6 +41,18 @@ pub(in crate::context_bootstrap) fn illegal_constructor_callback(
|
||||
throw_type_error(scope, "Illegal constructor");
|
||||
}
|
||||
|
||||
pub(in crate::context_bootstrap) fn shell_constructor_callback<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
rv: v8::ReturnValue<'s, v8::Value>,
|
||||
) {
|
||||
if !args.is_construct_call() {
|
||||
throw_type_error(scope, "Constructor requires the 'new' operator.");
|
||||
return;
|
||||
}
|
||||
unsupported_constructor_callback(scope, args, rv);
|
||||
}
|
||||
|
||||
pub(in crate::context_bootstrap) fn unsupported_constructor_callback(
|
||||
scope: &mut v8::PinScope<'_, '_>,
|
||||
_args: v8::FunctionCallbackArguments<'_>,
|
||||
|
||||
@@ -54,6 +54,7 @@ pub(in crate::context_bootstrap) const WORKER_SHARED_INTERFACE_NAMES: &[&str] =
|
||||
"BroadcastChannel",
|
||||
"Notification",
|
||||
"ImageData",
|
||||
"EncodedVideoChunk",
|
||||
"ImageBitmap",
|
||||
"CanvasGradient",
|
||||
"CanvasPattern",
|
||||
@@ -242,6 +243,7 @@ impl ExposureSet {
|
||||
const SERVICE_WORKER: u8 = 1 << 3;
|
||||
|
||||
const WINDOW_ONLY: Self = Self(Self::WINDOW);
|
||||
const WINDOW_AND_DEDICATED_WORKER: Self = Self(Self::WINDOW | Self::DEDICATED_WORKER);
|
||||
const ALL_REALMS: Self =
|
||||
Self(Self::WINDOW | Self::DEDICATED_WORKER | Self::SHARED_WORKER | Self::SERVICE_WORKER);
|
||||
const WORKERS: Self = Self(Self::DEDICATED_WORKER | Self::SHARED_WORKER | Self::SERVICE_WORKER);
|
||||
@@ -400,6 +402,7 @@ pub(super) fn installation_for_spec(spec: ConstructorSpec) -> GlobalInstallation
|
||||
fn exposure_for_name(name: &str) -> ExposureSet {
|
||||
match name {
|
||||
"FileSystemSyncAccessHandle" => ExposureSet::DEDICATED_WORKER_ONLY,
|
||||
"EncodedVideoChunk" => ExposureSet::WINDOW_AND_DEDICATED_WORKER,
|
||||
_ if WINDOW_DEDICATED_AND_SHARED_WORKER_INTERFACE_NAMES.contains(&name) => {
|
||||
ExposureSet::WINDOW_DEDICATED_AND_SHARED_WORKER
|
||||
}
|
||||
@@ -494,6 +497,32 @@ mod tests {
|
||||
assert_eq!(child.installation, GlobalInstallation::Lazy);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shell_encoded_video_chunk_uses_the_expected_exposure_and_lazy_policy() {
|
||||
let table = ExposedInterfaceMetadataTable::from_constructor_specs(
|
||||
&crate::context_bootstrap::specs::constructor_specs(),
|
||||
)
|
||||
.expect("shell exposure metadata");
|
||||
for name in ["EncodedVideoChunk"] {
|
||||
let metadata = table.metadata_by_name(name).expect("interface metadata");
|
||||
assert_eq!(metadata.installation, GlobalInstallation::Lazy, "{name}");
|
||||
for (realm, expected) in [
|
||||
(RealmKind::Window, true),
|
||||
(RealmKind::DedicatedWorker, true),
|
||||
(RealmKind::SharedWorker, false),
|
||||
(RealmKind::ServiceWorker, false),
|
||||
] {
|
||||
assert_eq!(metadata.is_exposed(realm, true), expected, "{name}");
|
||||
assert_eq!(metadata.is_exposed(realm, false), expected, "{name}");
|
||||
assert_eq!(
|
||||
metadata.is_supported_by(TemplateBuildProfile::for_realm(realm)),
|
||||
expected,
|
||||
"{name}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn storage_policy_matches_window_and_worker_exposure() {
|
||||
let table = ExposedInterfaceMetadataTable::from_constructor_specs(&[
|
||||
|
||||
@@ -923,6 +923,10 @@ const CONSTRUCTOR_SPECS_AFTER_STREAMS: &[ConstructorSpec] = &[
|
||||
interface: web_api_interfaces::ImageBitmap::DESCRIPTOR,
|
||||
kind: ConstructorKind::Illegal,
|
||||
},
|
||||
ConstructorSpec {
|
||||
interface: web_api_interfaces::EncodedVideoChunk::DESCRIPTOR,
|
||||
kind: ConstructorKind::Shell { length: 1 },
|
||||
},
|
||||
ConstructorSpec {
|
||||
interface: web_api_interfaces::RTCPeerConnection::DESCRIPTOR,
|
||||
kind: ConstructorKind::RtcPeerConnection,
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
pub(in crate::context_bootstrap) enum ConstructorKind {
|
||||
Illegal,
|
||||
Unsupported,
|
||||
/// Interface exposure and inheritance without a constructor implementation.
|
||||
Shell {
|
||||
length: u8,
|
||||
},
|
||||
Event,
|
||||
AnimationEvent,
|
||||
TransitionEvent,
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
(() => {
|
||||
const assert = (ok, message) => { if (!ok) throw Error(message); };
|
||||
const interfaces = [["EncodedVideoChunk", null, 1]];
|
||||
for (const realm of [window, document.getElementById('child').contentWindow]) {
|
||||
for (const [name, parentName, length] of interfaces) {
|
||||
const constructor = realm[name], parent = realm[parentName ?? 'Object'];
|
||||
assert(typeof constructor === 'function' && constructor.name === name && constructor.length === length,
|
||||
name + ' interface object');
|
||||
const descriptor = Object.getOwnPropertyDescriptor(realm, name);
|
||||
assert(descriptor.writable && descriptor.configurable && !descriptor.enumerable, name + ' global descriptor');
|
||||
assert(Object.getPrototypeOf(constructor.prototype) === parent.prototype, name + ' prototype inheritance');
|
||||
assert(Object.getPrototypeOf(constructor) === (parentName ? parent : realm.Function.prototype), name + ' interface inheritance');
|
||||
assert(constructor.prototype.constructor === constructor, name + ' prototype constructor');
|
||||
const tag = Object.getOwnPropertyDescriptor(constructor.prototype, Symbol.toStringTag);
|
||||
assert(tag.value === name && !tag.writable && !tag.enumerable && tag.configurable, name + ' prototype tag');
|
||||
let callError;
|
||||
try { constructor(); } catch (error) { callError = error; }
|
||||
assert(callError instanceof realm.TypeError, name + ' call requires new in the callee realm');
|
||||
if (realm !== window) assert(!(callError instanceof TypeError), name + ' foreign TypeError');
|
||||
// These are interface shells. Argument conversion and backend operations remain unavailable.
|
||||
let constructionError;
|
||||
try { Reflect.construct(constructor, []); } catch (error) { constructionError = error; }
|
||||
assert(constructionError instanceof realm.DOMException && constructionError.name === 'NotSupportedError' && constructionError.code === 9,
|
||||
name + ' unavailable construction is explicit in the callee realm');
|
||||
if (realm !== window) assert(!(constructionError instanceof DOMException), name + ' foreign DOMException');
|
||||
assert(realm[name] === constructor, name + ' materialization remains stable');
|
||||
}
|
||||
}
|
||||
return 'ok';
|
||||
})()
|
||||
@@ -0,0 +1,20 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn shell_encoded_video_chunk_preserves_native_identity_and_callee_error_realms() {
|
||||
for url in [
|
||||
"https://shell-interfaces.test/",
|
||||
"http://shell-interfaces.test/",
|
||||
"http://localhost/",
|
||||
] {
|
||||
let mut vm = new_storage_page_task_executor_test_vm(url);
|
||||
vm.eval("document.body.innerHTML = '<iframe id=child></iframe>'")
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
vm.eval(include_str!("encoded_video_chunk_shell.js"))
|
||||
.unwrap(),
|
||||
"ok",
|
||||
"{url}"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2141,6 +2141,7 @@ mod device_events;
|
||||
mod dom_elements;
|
||||
mod dom_xhr;
|
||||
mod element_click;
|
||||
mod encoded_video_chunk_shell;
|
||||
mod event_receivers;
|
||||
mod headers_list;
|
||||
mod http_fixture;
|
||||
|
||||
@@ -141,6 +141,7 @@ interfaces! {
|
||||
DynamicsCompressorNode;
|
||||
Element: Node;
|
||||
ElementInternals;
|
||||
EncodedVideoChunk;
|
||||
ErrorEvent: Event;
|
||||
Event;
|
||||
EventCounts;
|
||||
|
||||
Reference in New Issue
Block a user