Added AudioTrack, AudioTrackList, VideoTrack, VideoTrackList, and TrackEvent interfaces

This commit is contained in:
sreeise 2019-01-04 07:55:38 -05:00
parent 4d8d54fc00
commit cac4aa56f7
19 changed files with 974 additions and 138 deletions

View file

@ -0,0 +1,97 @@
/* 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 crate::dom::bindings::codegen::Bindings::AudioTrackBinding::{self, AudioTrackMethods};
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString;
use crate::dom::window::Window;
use dom_struct::dom_struct;
use std::cell::Cell;
#[dom_struct]
pub struct AudioTrack {
reflector_: Reflector,
id: DOMString,
kind: DOMString,
label: DOMString,
language: DOMString,
enabled: Cell<bool>,
}
impl AudioTrack {
pub fn new_inherited(
id: DOMString,
kind: DOMString,
label: DOMString,
language: DOMString,
) -> AudioTrack {
AudioTrack {
reflector_: Reflector::new(),
id: id.into(),
kind: kind.into(),
label: label.into(),
language: language.into(),
enabled: Cell::new(false),
}
}
pub fn new(
window: &Window,
id: DOMString,
kind: DOMString,
label: DOMString,
language: DOMString,
) -> DomRoot<AudioTrack> {
reflect_dom_object(
Box::new(AudioTrack::new_inherited(id, kind, label, language)),
window,
AudioTrackBinding::Wrap,
)
}
pub fn id(&self) -> DOMString {
self.id.clone()
}
pub fn enabled(&self) -> bool {
self.enabled.get()
}
pub fn set_enabled(&self, value: bool) {
self.enabled.set(value);
}
}
impl AudioTrackMethods for AudioTrack {
// https://html.spec.whatwg.org/multipage/#dom-audiotrack-id
fn Id(&self) -> DOMString {
self.id()
}
// https://html.spec.whatwg.org/multipage/#dom-audiotrack-kind
fn Kind(&self) -> DOMString {
self.kind.clone()
}
// https://html.spec.whatwg.org/multipage/#dom-audiotrack-label
fn Label(&self) -> DOMString {
self.label.clone()
}
// https://html.spec.whatwg.org/multipage/#dom-audiotrack-language
fn Language(&self) -> DOMString {
self.language.clone()
}
// https://html.spec.whatwg.org/multipage/#dom-audiotrack-enabled
fn Enabled(&self) -> bool {
self.enabled()
}
// https://html.spec.whatwg.org/multipage/#dom-audiotrack-enabled
fn SetEnabled(&self, value: bool) {
self.set_enabled(value);
}
}

View file

@ -0,0 +1,126 @@
/* 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 crate::dom::audiotrack::AudioTrack;
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::AudioTrackListBinding::{self, AudioTrackListMethods};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::DOMString;
use crate::dom::eventtarget::EventTarget;
use crate::dom::window::Window;
use crate::task_source::TaskSource;
use dom_struct::dom_struct;
#[dom_struct]
pub struct AudioTrackList {
eventtarget: EventTarget,
tracks: DomRefCell<Vec<Dom<AudioTrack>>>,
}
impl AudioTrackList {
pub fn new_inherited(tracks: &[&AudioTrack]) -> AudioTrackList {
AudioTrackList {
eventtarget: EventTarget::new_inherited(),
tracks: DomRefCell::new(tracks.iter().map(|track| Dom::from_ref(&**track)).collect()),
}
}
pub fn new(window: &Window, tracks: &[&AudioTrack]) -> DomRoot<AudioTrackList> {
reflect_dom_object(
Box::new(AudioTrackList::new_inherited(tracks)),
window,
AudioTrackListBinding::Wrap,
)
}
pub fn len(&self) -> usize {
self.tracks.borrow().len()
}
pub fn item(&self, idx: usize) -> Option<DomRoot<AudioTrack>> {
self.tracks
.borrow()
.get(idx)
.map(|track| DomRoot::from_ref(&**track))
}
pub fn enabled_index(&self) -> Option<usize> {
self.tracks
.borrow()
.iter()
.position(|track| track.enabled())
}
// TODO(#22799) Integrate DOM Audio and Video track selection with media player.
pub fn set_enabled(&self, idx: usize, value: bool) {
let track = match self.item(idx) {
Some(t) => t,
None => return,
};
// If the chosen tracks enabled status is the same as the new status, return early.
if track.enabled() == value {
return;
}
// Set the tracks enabled status.
track.set_enabled(value);
// Queue a task to fire an event named change.
let global = &self.global();
let this = Trusted::new(self);
let (source, canceller) = global
.as_window()
.task_manager()
.media_element_task_source_with_canceller();
let _ = source.queue_with_canceller(
task!(media_track_change: move || {
let this = this.root();
this.upcast::<EventTarget>().fire_event(atom!("change"));
}),
&canceller,
);
}
pub fn add(&self, track: &AudioTrack) {
self.tracks.borrow_mut().push(Dom::from_ref(track));
}
pub fn clear(&self) {
self.tracks.borrow_mut().clear();
}
}
impl AudioTrackListMethods for AudioTrackList {
// https://html.spec.whatwg.org/multipage/#dom-audiotracklist-length
fn Length(&self) -> u32 {
self.len() as u32
}
// https://html.spec.whatwg.org/multipage/#dom-tracklist-item
fn IndexedGetter(&self, idx: u32) -> Option<DomRoot<AudioTrack>> {
self.item(idx as usize)
}
// https://html.spec.whatwg.org/multipage/#dom-audiotracklist-gettrackbyid
fn GetTrackById(&self, id: DOMString) -> Option<DomRoot<AudioTrack>> {
self.tracks
.borrow()
.iter()
.find(|track| track.id() == id)
.map(|track| DomRoot::from_ref(&**track))
}
// https://html.spec.whatwg.org/multipage/#handler-tracklist-onchange
event_handler!(change, GetOnchange, SetOnchange);
// https://html.spec.whatwg.org/multipage/#handler-tracklist-onaddtrack
event_handler!(addtrack, GetOnaddtrack, SetOnaddtrack);
// https://html.spec.whatwg.org/multipage/#handler-tracklist-onremovetrack
event_handler!(removetrack, GetOnremovetrack, SetOnremovetrack);
}

View file

@ -4,6 +4,8 @@
use crate::document_loader::{LoadBlocker, LoadType}; use crate::document_loader::{LoadBlocker, LoadType};
use crate::dom::attr::Attr; use crate::dom::attr::Attr;
use crate::dom::audiotrack::AudioTrack;
use crate::dom::audiotracklist::AudioTrackList;
use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::AttrBinding::AttrMethods; use crate::dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
use crate::dom::bindings::codegen::Bindings::HTMLMediaElementBinding::CanPlayTypeResult; use crate::dom::bindings::codegen::Bindings::HTMLMediaElementBinding::CanPlayTypeResult;
@ -15,6 +17,7 @@ use crate::dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorMethod
use crate::dom::bindings::codegen::Bindings::TextTrackBinding::{TextTrackKind, TextTrackMode}; use crate::dom::bindings::codegen::Bindings::TextTrackBinding::{TextTrackKind, TextTrackMode};
use crate::dom::bindings::codegen::InheritTypes::{ElementTypeId, HTMLElementTypeId}; use crate::dom::bindings::codegen::InheritTypes::{ElementTypeId, HTMLElementTypeId};
use crate::dom::bindings::codegen::InheritTypes::{HTMLMediaElementTypeId, NodeTypeId}; use crate::dom::bindings::codegen::InheritTypes::{HTMLMediaElementTypeId, NodeTypeId};
use crate::dom::bindings::codegen::UnionTypes::VideoTrackOrAudioTrackOrTextTrack;
use crate::dom::bindings::error::{Error, ErrorResult, Fallible}; use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::num::Finite; use crate::dom::bindings::num::Finite;
@ -25,6 +28,7 @@ use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::blob::Blob; use crate::dom::blob::Blob;
use crate::dom::document::Document; use crate::dom::document::Document;
use crate::dom::element::{AttributeMutation, Element}; use crate::dom::element::{AttributeMutation, Element};
use crate::dom::event::Event;
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::htmlelement::HTMLElement; use crate::dom::htmlelement::HTMLElement;
@ -37,6 +41,9 @@ use crate::dom::promise::Promise;
use crate::dom::texttrack::TextTrack; use crate::dom::texttrack::TextTrack;
use crate::dom::texttracklist::TextTrackList; use crate::dom::texttracklist::TextTrackList;
use crate::dom::timeranges::{TimeRanges, TimeRangesContainer}; use crate::dom::timeranges::{TimeRanges, TimeRangesContainer};
use crate::dom::trackevent::TrackEvent;
use crate::dom::videotrack::VideoTrack;
use crate::dom::videotracklist::VideoTrackList;
use crate::dom::virtualmethods::VirtualMethods; use crate::dom::virtualmethods::VirtualMethods;
use crate::fetch::FetchCanceller; use crate::fetch::FetchCanceller;
use crate::microtask::{Microtask, MicrotaskRunnable}; use crate::microtask::{Microtask, MicrotaskRunnable};
@ -206,6 +213,10 @@ pub struct HTMLMediaElement {
/// https://html.spec.whatwg.org/multipage/#dom-media-played /// https://html.spec.whatwg.org/multipage/#dom-media-played
#[ignore_malloc_size_of = "Rc"] #[ignore_malloc_size_of = "Rc"]
played: DomRefCell<TimeRangesContainer>, played: DomRefCell<TimeRangesContainer>,
// https://html.spec.whatwg.org/multipage/#dom-media-audiotracks
audio_tracks_list: MutNullableDom<AudioTrackList>,
// https://html.spec.whatwg.org/multipage/#dom-media-videotracks
video_tracks_list: MutNullableDom<VideoTrackList>,
/// https://html.spec.whatwg.org/multipage/#dom-media-texttracks /// https://html.spec.whatwg.org/multipage/#dom-media-texttracks
text_tracks_list: MutNullableDom<TextTrackList>, text_tracks_list: MutNullableDom<TextTrackList>,
/// Time of last timeupdate notification. /// Time of last timeupdate notification.
@ -268,6 +279,8 @@ impl HTMLMediaElement {
seeking: Cell::new(false), seeking: Cell::new(false),
resource_url: DomRefCell::new(None), resource_url: DomRefCell::new(None),
played: DomRefCell::new(TimeRangesContainer::new()), played: DomRefCell::new(TimeRangesContainer::new()),
audio_tracks_list: Default::default(),
video_tracks_list: Default::default(),
text_tracks_list: Default::default(), text_tracks_list: Default::default(),
next_timeupdate_event: Cell::new(time::get_time() + Duration::milliseconds(250)), next_timeupdate_event: Cell::new(time::get_time() + Duration::milliseconds(250)),
current_fetch_context: DomRefCell::new(None), current_fetch_context: DomRefCell::new(None),
@ -803,7 +816,8 @@ impl HTMLMediaElement {
))); )));
// Step 2. // Step 2.
// FIXME(nox): Forget the media-resource-specific tracks. this.AudioTracks().clear();
this.VideoTracks().clear();
// Step 3. // Step 3.
this.network_state.set(NetworkState::NoSource); this.network_state.set(NetworkState::NoSource);
@ -904,7 +918,8 @@ impl HTMLMediaElement {
// FIXME(nox): Detach MediaSource media provider object. // FIXME(nox): Detach MediaSource media provider object.
// Step 6.4. // Step 6.4.
// FIXME(nox): Forget the media-resource-specific tracks. self.AudioTracks().clear();
self.VideoTracks().clear();
// Step 6.5. // Step 6.5.
if self.ready_state.get() != ReadyState::HaveNothing { if self.ready_state.get() != ReadyState::HaveNothing {
@ -1227,6 +1242,92 @@ impl HTMLMediaElement {
}, },
PlayerEvent::MetadataUpdated(ref metadata) => { PlayerEvent::MetadataUpdated(ref metadata) => {
// https://html.spec.whatwg.org/multipage/#media-data-processing-steps-list // https://html.spec.whatwg.org/multipage/#media-data-processing-steps-list
// => If the media resource is found to have an audio track
if !metadata.audio_tracks.is_empty() {
for (i, _track) in metadata.audio_tracks.iter().enumerate() {
// Step 1.
let kind = match i {
0 => DOMString::from("main"),
_ => DOMString::new(),
};
let window = window_from_node(self);
let audio_track = AudioTrack::new(
&window,
DOMString::new(),
kind,
DOMString::new(),
DOMString::new(),
);
// Steps 2. & 3.
self.AudioTracks().add(&audio_track);
// Step 4
// https://www.w3.org/TR/media-frags/#media-fragment-syntax
// https://github.com/servo/servo/issues/22366
// Step 5. & 6,
if self.AudioTracks().enabled_index().is_none() {
self.AudioTracks()
.set_enabled(self.AudioTracks().len() - 1, true);
}
// Steps 7.
let event = TrackEvent::new(
&self.global(),
atom!("addtrack"),
false,
false,
&Some(VideoTrackOrAudioTrackOrTextTrack::AudioTrack(audio_track)),
);
event.upcast::<Event>().fire(self.upcast::<EventTarget>());
}
}
// => If the media resource is found to have a video track
if !metadata.video_tracks.is_empty() {
for (i, _track) in metadata.video_tracks.iter().enumerate() {
// Step 1.
let kind = match i {
0 => DOMString::from("main"),
_ => DOMString::new(),
};
let window = window_from_node(self);
let video_track = VideoTrack::new(
&window,
DOMString::new(),
kind,
DOMString::new(),
DOMString::new(),
);
// Steps 2. & 3.
self.VideoTracks().add(&video_track);
// Step 4.
// https://www.w3.org/TR/media-frags/#media-fragment-syntax
// https://github.com/servo/servo/issues/22366
// Step 5. & 6.
if self.VideoTracks().selected_index().is_none() {
self.VideoTracks()
.set_selected(self.VideoTracks().len() - 1, true);
}
// Steps 7.
let event = TrackEvent::new(
&self.global(),
atom!("addtrack"),
false,
false,
&Some(VideoTrackOrAudioTrackOrTextTrack::VideoTrack(video_track)),
);
event.upcast::<Event>().fire(self.upcast::<EventTarget>());
}
}
// => "Once enough of the media data has been fetched to determine the duration..." // => "Once enough of the media data has been fetched to determine the duration..."
// Step 1. // Step 1.
// servo-media owns the media timeline. // servo-media owns the media timeline.
@ -1287,7 +1388,7 @@ impl HTMLMediaElement {
// https://www.w3.org/TR/media-frags/#media-fragment-syntax // https://www.w3.org/TR/media-frags/#media-fragment-syntax
// https://github.com/servo/media/issues/156 // https://github.com/servo/media/issues/156
// XXX Steps 12 and 13 require audio and video tracks support. // Step 12 & 13 are already handled by the earlier media track processing.
}, },
PlayerEvent::NeedData => { PlayerEvent::NeedData => {
// The player needs more data. // The player needs more data.
@ -1702,6 +1803,20 @@ impl HTMLMediaElementMethods for HTMLMediaElement {
TimeRanges::new(self.global().as_window(), buffered) TimeRanges::new(self.global().as_window(), buffered)
} }
// https://html.spec.whatwg.org/multipage/#dom-media-audiotracks
fn AudioTracks(&self) -> DomRoot<AudioTrackList> {
let window = window_from_node(self);
self.audio_tracks_list
.or_init(|| AudioTrackList::new(&window, &[]))
}
// https://html.spec.whatwg.org/multipage/#dom-media-videotracks
fn VideoTracks(&self) -> DomRoot<VideoTrackList> {
let window = window_from_node(self);
self.video_tracks_list
.or_init(|| VideoTrackList::new(&window, &[]))
}
// https://html.spec.whatwg.org/multipage/#dom-media-texttracks // https://html.spec.whatwg.org/multipage/#dom-media-texttracks
fn TextTracks(&self) -> DomRoot<TextTrackList> { fn TextTracks(&self) -> DomRoot<TextTrackList> {
let window = window_from_node(self); let window = window_from_node(self);

View file

@ -225,6 +225,8 @@ pub mod audiolistener;
pub mod audionode; pub mod audionode;
pub mod audioparam; pub mod audioparam;
pub mod audioscheduledsourcenode; pub mod audioscheduledsourcenode;
pub mod audiotrack;
pub mod audiotracklist;
pub mod baseaudiocontext; pub mod baseaudiocontext;
pub mod beforeunloadevent; pub mod beforeunloadevent;
pub mod bindings; pub mod bindings;
@ -478,6 +480,7 @@ pub mod timeranges;
pub mod touch; pub mod touch;
pub mod touchevent; pub mod touchevent;
pub mod touchlist; pub mod touchlist;
pub mod trackevent;
pub mod transitionevent; pub mod transitionevent;
pub mod treewalker; pub mod treewalker;
pub mod uievent; pub mod uievent;
@ -488,6 +491,8 @@ pub mod userscripts;
pub mod validation; pub mod validation;
pub mod validitystate; pub mod validitystate;
pub mod values; pub mod values;
pub mod videotrack;
pub mod videotracklist;
pub mod virtualmethods; pub mod virtualmethods;
pub mod vrdisplay; pub mod vrdisplay;
pub mod vrdisplaycapabilities; pub mod vrdisplaycapabilities;

View file

@ -4,13 +4,18 @@
use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::TextTrackListBinding::{self, TextTrackListMethods}; use crate::dom::bindings::codegen::Bindings::TextTrackListBinding::{self, TextTrackListMethods};
use crate::dom::bindings::codegen::UnionTypes::VideoTrackOrAudioTrackOrTextTrack;
use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::reflect_dom_object; use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
use crate::dom::event::Event;
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
use crate::dom::texttrack::TextTrack; use crate::dom::texttrack::TextTrack;
use crate::dom::trackevent::TrackEvent;
use crate::dom::window::Window; use crate::dom::window::Window;
use crate::task_source::TaskSource;
use dom_struct::dom_struct; use dom_struct::dom_struct;
#[dom_struct] #[dom_struct]
@ -56,8 +61,40 @@ impl TextTrackList {
// Only add a track if it does not exist in the list // Only add a track if it does not exist in the list
if self.find(track).is_none() { if self.find(track).is_none() {
self.dom_tracks.borrow_mut().push(Dom::from_ref(track)); self.dom_tracks.borrow_mut().push(Dom::from_ref(track));
let this = Trusted::new(self);
let (source, canceller) = &self
.global()
.as_window()
.task_manager()
.media_element_task_source_with_canceller();
let idx = match self.find(&track) {
Some(t) => t,
None => return,
}; };
self.upcast::<EventTarget>().fire_event(atom!("addtrack"));
let _ = source.queue_with_canceller(
task!(track_event_queue: move || {
let this = this.root();
if let Some(track) = this.item(idx) {
let event = TrackEvent::new(
&this.global(),
atom!("addtrack"),
false,
false,
&Some(VideoTrackOrAudioTrackOrTextTrack::TextTrack(
DomRoot::from_ref(&track)
)),
);
event.upcast::<Event>().fire(this.upcast::<EventTarget>());
}
}),
&canceller,
);
}
} }
// FIXME(#22314, dlrobertson) allow TextTracks to be // FIXME(#22314, dlrobertson) allow TextTracks to be

View file

@ -0,0 +1,114 @@
/* 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 crate::dom::audiotrack::AudioTrack;
use crate::dom::bindings::codegen::Bindings::EventBinding::EventBinding::EventMethods;
use crate::dom::bindings::codegen::Bindings::TrackEventBinding;
use crate::dom::bindings::codegen::Bindings::TrackEventBinding::TrackEventMethods;
use crate::dom::bindings::codegen::UnionTypes::VideoTrackOrAudioTrackOrTextTrack;
use crate::dom::bindings::error::Fallible;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::DOMString;
use crate::dom::event::Event;
use crate::dom::globalscope::GlobalScope;
use crate::dom::texttrack::TextTrack;
use crate::dom::videotrack::VideoTrack;
use crate::dom::window::Window;
use dom_struct::dom_struct;
use servo_atoms::Atom;
#[must_root]
#[derive(JSTraceable, MallocSizeOf)]
enum MediaTrack {
Video(Dom<VideoTrack>),
Audio(Dom<AudioTrack>),
Text(Dom<TextTrack>),
}
#[dom_struct]
pub struct TrackEvent {
event: Event,
track: Option<MediaTrack>,
}
impl TrackEvent {
#[allow(unrooted_must_root)]
fn new_inherited(track: &Option<VideoTrackOrAudioTrackOrTextTrack>) -> TrackEvent {
let media_track = match track {
Some(VideoTrackOrAudioTrackOrTextTrack::VideoTrack(VideoTrack)) => {
Some(MediaTrack::Video(Dom::from_ref(VideoTrack)))
},
Some(VideoTrackOrAudioTrackOrTextTrack::AudioTrack(AudioTrack)) => {
Some(MediaTrack::Audio(Dom::from_ref(AudioTrack)))
},
Some(VideoTrackOrAudioTrackOrTextTrack::TextTrack(TextTrack)) => {
Some(MediaTrack::Text(Dom::from_ref(TextTrack)))
},
None => None,
};
TrackEvent {
event: Event::new_inherited(),
track: media_track,
}
}
pub fn new(
global: &GlobalScope,
type_: Atom,
bubbles: bool,
cancelable: bool,
track: &Option<VideoTrackOrAudioTrackOrTextTrack>,
) -> DomRoot<TrackEvent> {
let te = reflect_dom_object(
Box::new(TrackEvent::new_inherited(&track)),
global,
TrackEventBinding::Wrap,
);
{
let event = te.upcast::<Event>();
event.init_event(type_, bubbles, cancelable);
}
te
}
pub fn Constructor(
window: &Window,
type_: DOMString,
init: &TrackEventBinding::TrackEventInit,
) -> Fallible<DomRoot<TrackEvent>> {
Ok(TrackEvent::new(
&window.global(),
Atom::from(type_),
init.parent.bubbles,
init.parent.cancelable,
&init.track,
))
}
}
impl TrackEventMethods for TrackEvent {
// https://html.spec.whatwg.org/multipage/#dom-trackevent-track
fn GetTrack(&self) -> Option<VideoTrackOrAudioTrackOrTextTrack> {
match &self.track {
Some(MediaTrack::Video(VideoTrack)) => Some(
VideoTrackOrAudioTrackOrTextTrack::VideoTrack(DomRoot::from_ref(VideoTrack)),
),
Some(MediaTrack::Audio(AudioTrack)) => Some(
VideoTrackOrAudioTrackOrTextTrack::AudioTrack(DomRoot::from_ref(AudioTrack)),
),
Some(MediaTrack::Text(TextTrack)) => Some(
VideoTrackOrAudioTrackOrTextTrack::TextTrack(DomRoot::from_ref(TextTrack)),
),
None => None,
}
}
// https://dom.spec.whatwg.org/#dom-event-istrusted
fn IsTrusted(&self) -> bool {
self.event.IsTrusted()
}
}

View file

@ -0,0 +1,97 @@
/* 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 crate::dom::bindings::codegen::Bindings::VideoTrackBinding::{self, VideoTrackMethods};
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString;
use crate::dom::window::Window;
use dom_struct::dom_struct;
use std::cell::Cell;
#[dom_struct]
pub struct VideoTrack {
reflector_: Reflector,
id: DOMString,
kind: DOMString,
label: DOMString,
language: DOMString,
selected: Cell<bool>,
}
impl VideoTrack {
pub fn new_inherited(
id: DOMString,
kind: DOMString,
label: DOMString,
language: DOMString,
) -> VideoTrack {
VideoTrack {
reflector_: Reflector::new(),
id: id.into(),
kind: kind.into(),
label: label.into(),
language: language.into(),
selected: Cell::new(false),
}
}
pub fn new(
window: &Window,
id: DOMString,
kind: DOMString,
label: DOMString,
language: DOMString,
) -> DomRoot<VideoTrack> {
reflect_dom_object(
Box::new(VideoTrack::new_inherited(id, kind, label, language)),
window,
VideoTrackBinding::Wrap,
)
}
pub fn id(&self) -> DOMString {
self.id.clone()
}
pub fn selected(&self) -> bool {
self.selected.get().clone()
}
pub fn set_selected(&self, value: bool) {
self.selected.set(value);
}
}
impl VideoTrackMethods for VideoTrack {
// https://html.spec.whatwg.org/multipage/#dom-videotrack-id
fn Id(&self) -> DOMString {
self.id()
}
// https://html.spec.whatwg.org/multipage/#dom-videotrack-kind
fn Kind(&self) -> DOMString {
self.kind.clone()
}
// https://html.spec.whatwg.org/multipage/#dom-videotrack-label
fn Label(&self) -> DOMString {
self.label.clone()
}
// https://html.spec.whatwg.org/multipage/#dom-videotrack-language
fn Language(&self) -> DOMString {
self.language.clone()
}
// https://html.spec.whatwg.org/multipage/#dom-videotrack-selected
fn Selected(&self) -> bool {
self.selected()
}
// https://html.spec.whatwg.org/multipage/#dom-videotrack-selected
fn SetSelected(&self, value: bool) {
self.set_selected(value);
}
}

View file

@ -0,0 +1,164 @@
/* 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 crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::VideoTrackListBinding::{self, VideoTrackListMethods};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
use crate::dom::bindings::root::Dom;
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString;
use crate::dom::eventtarget::EventTarget;
use crate::dom::videotrack::VideoTrack;
use crate::dom::window::Window;
use crate::task_source::TaskSource;
use dom_struct::dom_struct;
#[dom_struct]
pub struct VideoTrackList {
eventtarget: EventTarget,
tracks: DomRefCell<Vec<Dom<VideoTrack>>>,
}
impl VideoTrackList {
pub fn new_inherited(tracks: &[&VideoTrack]) -> VideoTrackList {
VideoTrackList {
eventtarget: EventTarget::new_inherited(),
tracks: DomRefCell::new(tracks.iter().map(|track| Dom::from_ref(&**track)).collect()),
}
}
pub fn new(window: &Window, tracks: &[&VideoTrack]) -> DomRoot<VideoTrackList> {
reflect_dom_object(
Box::new(VideoTrackList::new_inherited(tracks)),
window,
VideoTrackListBinding::Wrap,
)
}
pub fn len(&self) -> usize {
self.tracks.borrow().len()
}
pub fn item(&self, idx: usize) -> Option<DomRoot<VideoTrack>> {
self.tracks
.borrow()
.get(idx)
.map(|track| DomRoot::from_ref(&**track))
}
pub fn selected_index(&self) -> Option<usize> {
self.tracks
.borrow()
.iter()
.position(|track| track.selected())
}
// TODO(#22799) Integrate DOM Audio and Video track selection with media player.
pub fn set_selected(&self, idx: usize, value: bool) {
let track = match self.item(idx) {
Some(t) => t,
None => return,
};
// If the chosen tracks selected status is the same as the new status, return early.
if track.selected() == value {
return;
}
let global = &self.global();
let this = Trusted::new(self);
let (source, canceller) = global
.as_window()
.task_manager()
.media_element_task_source_with_canceller();
if let Some(current) = self.selected_index() {
if current != idx {
self.tracks.borrow()[current].set_selected(false);
track.set_selected(true);
let _ = source.queue_with_canceller(
task!(media_track_change: move || {
let this = this.root();
this.upcast::<EventTarget>().fire_event(atom!("change"));
}),
&canceller,
);
} else {
self.tracks.borrow()[current].set_selected(false);
let _ = source.queue_with_canceller(
task!(media_track_change: move || {
let this = this.root();
this.upcast::<EventTarget>().fire_event(atom!("change"));
}),
&canceller,
);
}
} else {
track.set_selected(true);
let _ = source.queue_with_canceller(
task!(media_track_change: move || {
let this = this.root();
this.upcast::<EventTarget>().fire_event(atom!("change"));
}),
&canceller,
);
}
}
pub fn add(&self, track: &VideoTrack) {
self.tracks.borrow_mut().push(Dom::from_ref(track));
if track.selected() {
if let Some(idx) = self.selected_index() {
self.set_selected(idx, false);
}
}
}
pub fn clear(&self) {
self.tracks.borrow_mut().clear();
}
}
impl VideoTrackListMethods for VideoTrackList {
// https://html.spec.whatwg.org/multipage/#dom-videotracklist-length
fn Length(&self) -> u32 {
self.len() as u32
}
// https://html.spec.whatwg.org/multipage/#dom-tracklist-item
fn IndexedGetter(&self, idx: u32) -> Option<DomRoot<VideoTrack>> {
self.item(idx as usize)
}
// https://html.spec.whatwg.org/multipage/#dom-videotracklist-gettrackbyid
fn GetTrackById(&self, id: DOMString) -> Option<DomRoot<VideoTrack>> {
self.tracks
.borrow()
.iter()
.find(|track| track.id() == id)
.map(|track| DomRoot::from_ref(&**track))
}
// https://html.spec.whatwg.org/multipage/#dom-videotrack-selected
fn SelectedIndex(&self) -> i32 {
if let Some(idx) = self.selected_index() {
return idx as i32;
}
return -1;
}
// https://html.spec.whatwg.org/multipage/#handler-tracklist-onchange
event_handler!(change, GetOnchange, SetOnchange);
// https://html.spec.whatwg.org/multipage/#handler-tracklist-onaddtrack
event_handler!(addtrack, GetOnaddtrack, SetOnaddtrack);
// https://html.spec.whatwg.org/multipage/#handler-tracklist-onremovetrack
event_handler!(removetrack, GetOnremovetrack, SetOnremovetrack);
}

View file

@ -0,0 +1,14 @@
/* 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/. */
// https://html.spec.whatwg.org/multipage/#audiotrack
[Exposed=Window]
interface AudioTrack {
readonly attribute DOMString id;
readonly attribute DOMString kind;
readonly attribute DOMString label;
readonly attribute DOMString language;
attribute boolean enabled;
};

View file

@ -0,0 +1,16 @@
/* 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/. */
// https://html.spec.whatwg.org/multipage/#audiotracklist
[Exposed=Window]
interface AudioTrackList : EventTarget {
readonly attribute unsigned long length;
getter AudioTrack (unsigned long index);
AudioTrack? getTrackById(DOMString id);
attribute EventHandler onchange;
attribute EventHandler onaddtrack;
attribute EventHandler onremovetrack;
};

View file

@ -59,8 +59,8 @@ interface HTMLMediaElement : HTMLElement {
[CEReactions] attribute boolean defaultMuted; [CEReactions] attribute boolean defaultMuted;
// tracks // tracks
// readonly attribute AudioTrackList audioTracks; readonly attribute AudioTrackList audioTracks;
// readonly attribute VideoTrackList videoTracks; readonly attribute VideoTrackList videoTracks;
readonly attribute TextTrackList textTracks; readonly attribute TextTrackList textTracks;
TextTrack addTextTrack(TextTrackKind kind, optional DOMString label = "", optional DOMString language = ""); TextTrack addTextTrack(TextTrackKind kind, optional DOMString label = "", optional DOMString language = "");
}; };

View file

@ -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 https://mozilla.org/MPL/2.0/. */
// https://html.spec.whatwg.org/multipage/#the-trackevent-interface
[Exposed=Window,
Constructor(DOMString type, optional TrackEventInit eventInitDict)]
interface TrackEvent : Event {
readonly attribute (VideoTrack or AudioTrack or TextTrack)? track;
};
dictionary TrackEventInit : EventInit {
(VideoTrack or AudioTrack or TextTrack)? track = null;
};

View file

@ -0,0 +1,14 @@
/* 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/. */
// https://html.spec.whatwg.org/multipage/#videotrack
[Exposed=Window]
interface VideoTrack {
readonly attribute DOMString id;
readonly attribute DOMString kind;
readonly attribute DOMString label;
readonly attribute DOMString language;
attribute boolean selected;
};

View file

@ -0,0 +1,17 @@
/* 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/. */
// https://html.spec.whatwg.org/multipage/#videotracklist
[Exposed=Window]
interface VideoTrackList : EventTarget {
readonly attribute unsigned long length;
getter VideoTrack (unsigned long index);
VideoTrack? getTrackById(DOMString id);
readonly attribute long selectedIndex;
attribute EventHandler onchange;
attribute EventHandler onaddtrack;
attribute EventHandler onremovetrack;
};

View file

@ -1068,10 +1068,10 @@
expected: FAIL expected: FAIL
[HTMLMediaElement interface: document.createElement("video") must inherit property "audioTracks" with the proper type] [HTMLMediaElement interface: document.createElement("video") must inherit property "audioTracks" with the proper type]
expected: FAIL expected: PASS
[HTMLMediaElement interface: document.createElement("video") must inherit property "videoTracks" with the proper type] [HTMLMediaElement interface: document.createElement("video") must inherit property "videoTracks" with the proper type]
expected: FAIL expected: PASS
[HTMLMediaElement interface: document.createElement("video") must inherit property "textTracks" with the proper type] [HTMLMediaElement interface: document.createElement("video") must inherit property "textTracks" with the proper type]
expected: FAIL expected: FAIL
@ -1137,10 +1137,10 @@
expected: FAIL expected: FAIL
[HTMLMediaElement interface: document.createElement("audio") must inherit property "audioTracks" with the proper type] [HTMLMediaElement interface: document.createElement("audio") must inherit property "audioTracks" with the proper type]
expected: FAIL expected: PASS
[HTMLMediaElement interface: document.createElement("audio") must inherit property "videoTracks" with the proper type] [HTMLMediaElement interface: document.createElement("audio") must inherit property "videoTracks" with the proper type]
expected: FAIL expected: PASS
[HTMLMediaElement interface: document.createElement("audio") must inherit property "textTracks" with the proper type] [HTMLMediaElement interface: document.createElement("audio") must inherit property "textTracks" with the proper type]
expected: FAIL expected: FAIL
@ -1278,10 +1278,10 @@
expected: FAIL expected: FAIL
[HTMLMediaElement interface: new Audio() must inherit property "audioTracks" with the proper type] [HTMLMediaElement interface: new Audio() must inherit property "audioTracks" with the proper type]
expected: FAIL expected: PASS
[HTMLMediaElement interface: new Audio() must inherit property "videoTracks" with the proper type] [HTMLMediaElement interface: new Audio() must inherit property "videoTracks" with the proper type]
expected: FAIL expected: PASS
[HTMLMediaElement interface: new Audio() must inherit property "textTracks" with the proper type] [HTMLMediaElement interface: new Audio() must inherit property "textTracks" with the proper type]
expected: FAIL expected: FAIL
@ -1422,10 +1422,10 @@
expected: FAIL expected: FAIL
[HTMLMediaElement interface: attribute audioTracks] [HTMLMediaElement interface: attribute audioTracks]
expected: FAIL expected: PASS
[HTMLMediaElement interface: attribute videoTracks] [HTMLMediaElement interface: attribute videoTracks]
expected: FAIL expected: PASS
[HTMLMediaElement interface: attribute textTracks] [HTMLMediaElement interface: attribute textTracks]
expected: FAIL expected: FAIL
@ -1434,139 +1434,139 @@
expected: FAIL expected: FAIL
[AudioTrackList interface: existence and properties of interface object] [AudioTrackList interface: existence and properties of interface object]
expected: FAIL expected: PASS
[AudioTrackList interface object length] [AudioTrackList interface object length]
expected: FAIL expected: PASS
[AudioTrackList interface object name] [AudioTrackList interface object name]
expected: FAIL expected: PASS
[AudioTrackList interface: existence and properties of interface prototype object] [AudioTrackList interface: existence and properties of interface prototype object]
expected: FAIL expected: PASS
[AudioTrackList interface: existence and properties of interface prototype object's "constructor" property] [AudioTrackList interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL expected: PASS
[AudioTrackList interface: existence and properties of interface prototype object's @@unscopables property] [AudioTrackList interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL expected: PASS
[AudioTrackList interface: attribute length] [AudioTrackList interface: attribute length]
expected: FAIL expected: PASS
[AudioTrackList interface: operation getTrackById(DOMString)] [AudioTrackList interface: operation getTrackById(DOMString)]
expected: FAIL expected: PASS
[AudioTrackList interface: attribute onchange] [AudioTrackList interface: attribute onchange]
expected: FAIL expected: PASS
[AudioTrackList interface: attribute onaddtrack] [AudioTrackList interface: attribute onaddtrack]
expected: FAIL expected: PASS
[AudioTrackList interface: attribute onremovetrack] [AudioTrackList interface: attribute onremovetrack]
expected: FAIL expected: PASS
[AudioTrack interface: existence and properties of interface object] [AudioTrack interface: existence and properties of interface object]
expected: FAIL expected: PASS
[AudioTrack interface object length] [AudioTrack interface object length]
expected: FAIL expected: PASS
[AudioTrack interface object name] [AudioTrack interface object name]
expected: FAIL expected: PASS
[AudioTrack interface: existence and properties of interface prototype object] [AudioTrack interface: existence and properties of interface prototype object]
expected: FAIL expected: PASS
[AudioTrack interface: existence and properties of interface prototype object's "constructor" property] [AudioTrack interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL expected: PASS
[AudioTrack interface: existence and properties of interface prototype object's @@unscopables property] [AudioTrack interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL expected: PASS
[AudioTrack interface: attribute id] [AudioTrack interface: attribute id]
expected: FAIL expected: PASS
[AudioTrack interface: attribute kind] [AudioTrack interface: attribute kind]
expected: FAIL expected: PASS
[AudioTrack interface: attribute label] [AudioTrack interface: attribute label]
expected: FAIL expected: PASS
[AudioTrack interface: attribute language] [AudioTrack interface: attribute language]
expected: FAIL expected: PASS
[AudioTrack interface: attribute enabled] [AudioTrack interface: attribute enabled]
expected: FAIL expected: PASS
[VideoTrackList interface: existence and properties of interface object] [VideoTrackList interface: existence and properties of interface object]
expected: FAIL expected: PASS
[VideoTrackList interface object length] [VideoTrackList interface object length]
expected: FAIL expected: PASS
[VideoTrackList interface object name] [VideoTrackList interface object name]
expected: FAIL expected: PASS
[VideoTrackList interface: existence and properties of interface prototype object] [VideoTrackList interface: existence and properties of interface prototype object]
expected: FAIL expected: PASS
[VideoTrackList interface: existence and properties of interface prototype object's "constructor" property] [VideoTrackList interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL expected: PASS
[VideoTrackList interface: existence and properties of interface prototype object's @@unscopables property] [VideoTrackList interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL expected: PASS
[VideoTrackList interface: attribute length] [VideoTrackList interface: attribute length]
expected: FAIL expected: PASS
[VideoTrackList interface: operation getTrackById(DOMString)] [VideoTrackList interface: operation getTrackById(DOMString)]
expected: FAIL expected: PASS
[VideoTrackList interface: attribute selectedIndex] [VideoTrackList interface: attribute selectedIndex]
expected: FAIL expected: PASS
[VideoTrackList interface: attribute onchange] [VideoTrackList interface: attribute onchange]
expected: FAIL expected: PASS
[VideoTrackList interface: attribute onaddtrack] [VideoTrackList interface: attribute onaddtrack]
expected: FAIL expected: PASS
[VideoTrackList interface: attribute onremovetrack] [VideoTrackList interface: attribute onremovetrack]
expected: FAIL expected: PASS
[VideoTrack interface: existence and properties of interface object] [VideoTrack interface: existence and properties of interface object]
expected: FAIL expected: PASS
[VideoTrack interface object length] [VideoTrack interface object length]
expected: FAIL expected: PASS
[VideoTrack interface object name] [VideoTrack interface object name]
expected: FAIL expected: PASS
[VideoTrack interface: existence and properties of interface prototype object] [VideoTrack interface: existence and properties of interface prototype object]
expected: FAIL expected: PASS
[VideoTrack interface: existence and properties of interface prototype object's "constructor" property] [VideoTrack interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL expected: PASS
[VideoTrack interface: existence and properties of interface prototype object's @@unscopables property] [VideoTrack interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL expected: PASS
[VideoTrack interface: attribute id] [VideoTrack interface: attribute id]
expected: FAIL expected: PASS
[VideoTrack interface: attribute kind] [VideoTrack interface: attribute kind]
expected: FAIL expected: PASS
[VideoTrack interface: attribute label] [VideoTrack interface: attribute label]
expected: FAIL expected: PASS
[VideoTrack interface: attribute language] [VideoTrack interface: attribute language]
expected: FAIL expected: PASS
[VideoTrack interface: attribute selected] [VideoTrack interface: attribute selected]
expected: FAIL expected: PASS
[TextTrackList interface: existence and properties of interface object] [TextTrackList interface: existence and properties of interface object]
expected: FAIL expected: FAIL
@ -1848,34 +1848,34 @@
expected: FAIL expected: FAIL
[TrackEvent interface: existence and properties of interface object] [TrackEvent interface: existence and properties of interface object]
expected: FAIL expected: PASS
[TrackEvent interface object length] [TrackEvent interface object length]
expected: FAIL expected: PASS
[TrackEvent interface object name] [TrackEvent interface object name]
expected: FAIL expected: PASS
[TrackEvent interface: existence and properties of interface prototype object] [TrackEvent interface: existence and properties of interface prototype object]
expected: FAIL expected: PASS
[TrackEvent interface: existence and properties of interface prototype object's "constructor" property] [TrackEvent interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL expected: PASS
[TrackEvent interface: existence and properties of interface prototype object's @@unscopables property] [TrackEvent interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL expected: PASS
[TrackEvent interface: attribute track] [TrackEvent interface: attribute track]
expected: FAIL expected: PASS
[TrackEvent must be primary interface of new TrackEvent("addtrack", {track:document.createElement("track").track})] [TrackEvent must be primary interface of new TrackEvent("addtrack", {track:document.createElement("track").track})]
expected: FAIL expected: PASS
[Stringification of new TrackEvent("addtrack", {track:document.createElement("track").track})] [Stringification of new TrackEvent("addtrack", {track:document.createElement("track").track})]
expected: FAIL expected: PASS
[TrackEvent interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "track" with the proper type] [TrackEvent interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "track" with the proper type]
expected: FAIL expected: PASS
[HTMLMapElement interface: attribute name] [HTMLMapElement interface: attribute name]
expected: FAIL expected: FAIL
@ -6784,10 +6784,10 @@
expected: FAIL expected: FAIL
[HTMLMediaElement interface: document.createElement("video") must inherit property "audioTracks" with the proper type] [HTMLMediaElement interface: document.createElement("video") must inherit property "audioTracks" with the proper type]
expected: FAIL expected: PASS
[HTMLMediaElement interface: document.createElement("video") must inherit property "videoTracks" with the proper type] [HTMLMediaElement interface: document.createElement("video") must inherit property "videoTracks" with the proper type]
expected: FAIL expected: PASS
[HTMLMediaElement interface: document.createElement("audio") must inherit property "srcObject" with the proper type] [HTMLMediaElement interface: document.createElement("audio") must inherit property "srcObject" with the proper type]
expected: FAIL expected: FAIL
@ -6808,10 +6808,10 @@
expected: FAIL expected: FAIL
[HTMLMediaElement interface: document.createElement("audio") must inherit property "audioTracks" with the proper type] [HTMLMediaElement interface: document.createElement("audio") must inherit property "audioTracks" with the proper type]
expected: FAIL expected: PASS
[HTMLMediaElement interface: document.createElement("audio") must inherit property "videoTracks" with the proper type] [HTMLMediaElement interface: document.createElement("audio") must inherit property "videoTracks" with the proper type]
expected: FAIL expected: PASS
[HTMLMediaElement interface: new Audio() must inherit property "srcObject" with the proper type] [HTMLMediaElement interface: new Audio() must inherit property "srcObject" with the proper type]
expected: FAIL expected: FAIL
@ -6832,10 +6832,10 @@
expected: FAIL expected: FAIL
[HTMLMediaElement interface: new Audio() must inherit property "audioTracks" with the proper type] [HTMLMediaElement interface: new Audio() must inherit property "audioTracks" with the proper type]
expected: FAIL expected: PASS
[HTMLMediaElement interface: new Audio() must inherit property "videoTracks" with the proper type] [HTMLMediaElement interface: new Audio() must inherit property "videoTracks" with the proper type]
expected: FAIL expected: PASS
[HTMLMediaElement interface: attribute crossOrigin] [HTMLMediaElement interface: attribute crossOrigin]
expected: FAIL expected: FAIL
@ -6856,10 +6856,10 @@
expected: FAIL expected: FAIL
[HTMLMediaElement interface: attribute audioTracks] [HTMLMediaElement interface: attribute audioTracks]
expected: FAIL expected: PASS
[HTMLMediaElement interface: attribute videoTracks] [HTMLMediaElement interface: attribute videoTracks]
expected: FAIL expected: PASS
[HTMLMapElement interface: attribute name] [HTMLMapElement interface: attribute name]
expected: FAIL expected: FAIL
@ -9408,139 +9408,139 @@
expected: FAIL expected: FAIL
[AudioTrackList interface: existence and properties of interface object] [AudioTrackList interface: existence and properties of interface object]
expected: FAIL expected: PASS
[AudioTrackList interface object length] [AudioTrackList interface object length]
expected: FAIL expected: PASS
[AudioTrackList interface object name] [AudioTrackList interface object name]
expected: FAIL expected: PASS
[AudioTrackList interface: existence and properties of interface prototype object] [AudioTrackList interface: existence and properties of interface prototype object]
expected: FAIL expected: PASS
[AudioTrackList interface: existence and properties of interface prototype object's "constructor" property] [AudioTrackList interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL expected: PASS
[AudioTrackList interface: existence and properties of interface prototype object's @@unscopables property] [AudioTrackList interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL expected: PASS
[AudioTrackList interface: attribute length] [AudioTrackList interface: attribute length]
expected: FAIL expected: PASS
[AudioTrackList interface: operation getTrackById(DOMString)] [AudioTrackList interface: operation getTrackById(DOMString)]
expected: FAIL expected: PASS
[AudioTrackList interface: attribute onchange] [AudioTrackList interface: attribute onchange]
expected: FAIL expected: PASS
[AudioTrackList interface: attribute onaddtrack] [AudioTrackList interface: attribute onaddtrack]
expected: FAIL expected: PASS
[AudioTrackList interface: attribute onremovetrack] [AudioTrackList interface: attribute onremovetrack]
expected: FAIL expected: PASS
[AudioTrack interface: existence and properties of interface object] [AudioTrack interface: existence and properties of interface object]
expected: FAIL expected: PASS
[AudioTrack interface object length] [AudioTrack interface object length]
expected: FAIL expected: PASS
[AudioTrack interface object name] [AudioTrack interface object name]
expected: FAIL expected: PASS
[AudioTrack interface: existence and properties of interface prototype object] [AudioTrack interface: existence and properties of interface prototype object]
expected: FAIL expected: PASS
[AudioTrack interface: existence and properties of interface prototype object's "constructor" property] [AudioTrack interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL expected: PASS
[AudioTrack interface: existence and properties of interface prototype object's @@unscopables property] [AudioTrack interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL expected: PASS
[AudioTrack interface: attribute id] [AudioTrack interface: attribute id]
expected: FAIL expected: PASS
[AudioTrack interface: attribute kind] [AudioTrack interface: attribute kind]
expected: FAIL expected: PASS
[AudioTrack interface: attribute label] [AudioTrack interface: attribute label]
expected: FAIL expected: PASS
[AudioTrack interface: attribute language] [AudioTrack interface: attribute language]
expected: FAIL expected: PASS
[AudioTrack interface: attribute enabled] [AudioTrack interface: attribute enabled]
expected: FAIL expected: PASS
[VideoTrackList interface: existence and properties of interface object] [VideoTrackList interface: existence and properties of interface object]
expected: FAIL expected: PASS
[VideoTrackList interface object length] [VideoTrackList interface object length]
expected: FAIL expected: PASS
[VideoTrackList interface object name] [VideoTrackList interface object name]
expected: FAIL expected: PASS
[VideoTrackList interface: existence and properties of interface prototype object] [VideoTrackList interface: existence and properties of interface prototype object]
expected: FAIL expected: PASS
[VideoTrackList interface: existence and properties of interface prototype object's "constructor" property] [VideoTrackList interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL expected: PASS
[VideoTrackList interface: existence and properties of interface prototype object's @@unscopables property] [VideoTrackList interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL expected: PASS
[VideoTrackList interface: attribute length] [VideoTrackList interface: attribute length]
expected: FAIL expected: PASS
[VideoTrackList interface: operation getTrackById(DOMString)] [VideoTrackList interface: operation getTrackById(DOMString)]
expected: FAIL expected: PASS
[VideoTrackList interface: attribute selectedIndex] [VideoTrackList interface: attribute selectedIndex]
expected: FAIL expected: PASS
[VideoTrackList interface: attribute onchange] [VideoTrackList interface: attribute onchange]
expected: FAIL expected: PASS
[VideoTrackList interface: attribute onaddtrack] [VideoTrackList interface: attribute onaddtrack]
expected: FAIL expected: PASS
[VideoTrackList interface: attribute onremovetrack] [VideoTrackList interface: attribute onremovetrack]
expected: FAIL expected: PASS
[VideoTrack interface: existence and properties of interface object] [VideoTrack interface: existence and properties of interface object]
expected: FAIL expected: PASS
[VideoTrack interface object length] [VideoTrack interface object length]
expected: FAIL expected: PASS
[VideoTrack interface object name] [VideoTrack interface object name]
expected: FAIL expected: PASS
[VideoTrack interface: existence and properties of interface prototype object] [VideoTrack interface: existence and properties of interface prototype object]
expected: FAIL expected: PASS
[VideoTrack interface: existence and properties of interface prototype object's "constructor" property] [VideoTrack interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL expected: PASS
[VideoTrack interface: existence and properties of interface prototype object's @@unscopables property] [VideoTrack interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL expected: PASS
[VideoTrack interface: attribute id] [VideoTrack interface: attribute id]
expected: FAIL expected: PASS
[VideoTrack interface: attribute kind] [VideoTrack interface: attribute kind]
expected: FAIL expected: PASS
[VideoTrack interface: attribute label] [VideoTrack interface: attribute label]
expected: FAIL expected: PASS
[VideoTrack interface: attribute language] [VideoTrack interface: attribute language]
expected: FAIL expected: PASS
[VideoTrack interface: attribute selected] [VideoTrack interface: attribute selected]
expected: FAIL expected: PASS
[TextTrack interface: attribute inBandMetadataTrackDispatchType] [TextTrack interface: attribute inBandMetadataTrackDispatchType]
expected: FAIL expected: FAIL
@ -9549,34 +9549,34 @@
expected: FAIL expected: FAIL
[TrackEvent interface: existence and properties of interface object] [TrackEvent interface: existence and properties of interface object]
expected: FAIL expected: PASS
[TrackEvent interface object length] [TrackEvent interface object length]
expected: FAIL expected: PASS
[TrackEvent interface object name] [TrackEvent interface object name]
expected: FAIL expected: PASS
[TrackEvent interface: existence and properties of interface prototype object] [TrackEvent interface: existence and properties of interface prototype object]
expected: FAIL expected: PASS
[TrackEvent interface: existence and properties of interface prototype object's "constructor" property] [TrackEvent interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL expected: PASS
[TrackEvent interface: existence and properties of interface prototype object's @@unscopables property] [TrackEvent interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL expected: PASS
[TrackEvent interface: attribute track] [TrackEvent interface: attribute track]
expected: FAIL expected: PASS
[TrackEvent must be primary interface of new TrackEvent("addtrack", {track:document.createElement("track").track})] [TrackEvent must be primary interface of new TrackEvent("addtrack", {track:document.createElement("track").track})]
expected: FAIL expected: PASS
[Stringification of new TrackEvent("addtrack", {track:document.createElement("track").track})] [Stringification of new TrackEvent("addtrack", {track:document.createElement("track").track})]
expected: FAIL expected: PASS
[TrackEvent interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "track" with the proper type] [TrackEvent interface: new TrackEvent("addtrack", {track:document.createElement("track").track}) must inherit property "track" with the proper type]
expected: FAIL expected: PASS
[ValidityState must be primary interface of document.createElement("input").validity] [ValidityState must be primary interface of document.createElement("input").validity]
expected: FAIL expected: FAIL

View file

@ -1,7 +1,7 @@
[constructor.html] [constructor.html]
[TrackEvent constructor, two args] [TrackEvent constructor, two args]
expected: FAIL expected: PASS
[TrackEvent constructor, one arg] [TrackEvent constructor, one arg]
expected: FAIL expected: PASS

View file

@ -1,4 +1,4 @@
[createEvent.html] [createEvent.html]
[TrackEvent created with createEvent] [TrackEvent created with createEvent]
expected: FAIL expected: PASS

View file

@ -19557,7 +19557,7 @@
"testharness" "testharness"
], ],
"mozilla/interfaces.html": [ "mozilla/interfaces.html": [
"55cafc9995da83d48230eed5b5c3863d8cf173c9", "ab4ead5cfb5afc8b65cb71841e32ee46ec75318b",
"testharness" "testharness"
], ],
"mozilla/interfaces.js": [ "mozilla/interfaces.js": [

View file

@ -22,6 +22,8 @@ test_interfaces([
"AudioNode", "AudioNode",
"AudioParam", "AudioParam",
"AudioScheduledSourceNode", "AudioScheduledSourceNode",
"AudioTrack",
"AudioTrackList",
"BaseAudioContext", "BaseAudioContext",
"BeforeUnloadEvent", "BeforeUnloadEvent",
"BiquadFilterNode", "BiquadFilterNode",
@ -214,12 +216,15 @@ test_interfaces([
"Touch", "Touch",
"TouchEvent", "TouchEvent",
"TouchList", "TouchList",
"TrackEvent",
"TransitionEvent", "TransitionEvent",
"TreeWalker", "TreeWalker",
"UIEvent", "UIEvent",
"URL", "URL",
"URLSearchParams", "URLSearchParams",
"ValidityState", "ValidityState",
"VideoTrack",
"VideoTrackList",
"WebAssembly", "WebAssembly",
"WebGLRenderingContext", "WebGLRenderingContext",
"WebGLUniformLocation", "WebGLUniformLocation",