mirror of
https://github.com/lexmount/moli.git
synced 2026-10-16 08:01:27 +00:00
feat(media): expose the native MediaRecorder interface shell
This commit is contained in:
@@ -592,6 +592,32 @@ mod tests {
|
||||
assert!(worker_location.is_exposed(RealmKind::ServiceWorker, true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shell_media_recorder_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 ["MediaRecorder"] {
|
||||
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, false),
|
||||
(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 chromium_worker_exposure_exceptions_are_preserved() {
|
||||
let table = ExposedInterfaceMetadataTable::from_constructor_specs(&[
|
||||
|
||||
@@ -1195,6 +1195,10 @@ const CONSTRUCTOR_SPECS_AFTER_STREAMS: &[ConstructorSpec] = &[
|
||||
interface: web_api_interfaces::MediaSource::DESCRIPTOR,
|
||||
kind: ConstructorKind::MediaSource,
|
||||
},
|
||||
ConstructorSpec {
|
||||
interface: web_api_interfaces::MediaRecorder::DESCRIPTOR,
|
||||
kind: ConstructorKind::Shell { length: 1 },
|
||||
},
|
||||
ConstructorSpec {
|
||||
interface: web_api_interfaces::MediaError::DESCRIPTOR,
|
||||
kind: ConstructorKind::MediaError,
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
(() => {
|
||||
const assert = (ok, message) => { if (!ok) throw Error(message); };
|
||||
const interfaces = [["MediaRecorder", "EventTarget", 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,19 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn shell_media_recorder_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!("media_recorder_shell.js")).unwrap(),
|
||||
"ok",
|
||||
"{url}"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2146,6 +2146,7 @@ mod event_receivers;
|
||||
mod headers_list;
|
||||
mod http_fixture;
|
||||
mod media_owner_playback_interfaces;
|
||||
mod media_recorder_shell;
|
||||
mod svg_animation_interfaces;
|
||||
|
||||
mod audio_event_interfaces;
|
||||
|
||||
@@ -297,6 +297,7 @@ interfaces! {
|
||||
MediaList;
|
||||
MediaQueryList: EventTarget;
|
||||
MediaQueryListEvent: Event;
|
||||
MediaRecorder: EventTarget;
|
||||
MediaSession;
|
||||
MediaSource: EventTarget;
|
||||
MemoryInfo;
|
||||
|
||||
Reference in New Issue
Block a user