mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
Auto merge of #22005 - ferjm:media.timeline, r=ceyusa
Basic HTMLMediaElement seeking - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #21998 This allows media seeking only when the server supports byte-range requests. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/22005) <!-- Reviewable:end -->
This commit is contained in:
commit
cb915d669a
10 changed files with 380 additions and 117 deletions
|
@ -74,6 +74,8 @@ scan
|
||||||
screen
|
screen
|
||||||
scroll-position
|
scroll-position
|
||||||
search
|
search
|
||||||
|
seeked
|
||||||
|
seeking
|
||||||
select
|
select
|
||||||
serif
|
serif
|
||||||
statechange
|
statechange
|
||||||
|
|
|
@ -16,6 +16,7 @@ use dom::bindings::codegen::InheritTypes::{ElementTypeId, HTMLElementTypeId};
|
||||||
use dom::bindings::codegen::InheritTypes::{HTMLMediaElementTypeId, NodeTypeId};
|
use dom::bindings::codegen::InheritTypes::{HTMLMediaElementTypeId, NodeTypeId};
|
||||||
use dom::bindings::error::{Error, ErrorResult};
|
use dom::bindings::error::{Error, ErrorResult};
|
||||||
use dom::bindings::inheritance::Castable;
|
use dom::bindings::inheritance::Castable;
|
||||||
|
use dom::bindings::num::Finite;
|
||||||
use dom::bindings::refcounted::Trusted;
|
use dom::bindings::refcounted::Trusted;
|
||||||
use dom::bindings::reflector::DomObject;
|
use dom::bindings::reflector::DomObject;
|
||||||
use dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom};
|
use dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom};
|
||||||
|
@ -34,7 +35,7 @@ use dom::virtualmethods::VirtualMethods;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use fetch::FetchCanceller;
|
use fetch::FetchCanceller;
|
||||||
use html5ever::{LocalName, Prefix};
|
use html5ever::{LocalName, Prefix};
|
||||||
use hyper::header::ContentLength;
|
use hyper::header::{ByteRangeSpec, ContentLength, Headers, Range as HyperRange};
|
||||||
use ipc_channel::ipc;
|
use ipc_channel::ipc;
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
use microtask::{Microtask, MicrotaskRunnable};
|
use microtask::{Microtask, MicrotaskRunnable};
|
||||||
|
@ -47,7 +48,7 @@ use script_layout_interface::HTMLMediaData;
|
||||||
use script_thread::ScriptThread;
|
use script_thread::ScriptThread;
|
||||||
use servo_media::Error as ServoMediaError;
|
use servo_media::Error as ServoMediaError;
|
||||||
use servo_media::ServoMedia;
|
use servo_media::ServoMedia;
|
||||||
use servo_media::player::{PlaybackState, Player, PlayerEvent};
|
use servo_media::player::{PlaybackState, Player, PlayerEvent, StreamType};
|
||||||
use servo_media::player::frame::{Frame, FrameRenderer};
|
use servo_media::player::frame::{Frame, FrameRenderer};
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
@ -161,7 +162,7 @@ pub struct HTMLMediaElement {
|
||||||
#[ignore_malloc_size_of = "promises are hard"]
|
#[ignore_malloc_size_of = "promises are hard"]
|
||||||
in_flight_play_promises_queue: DomRefCell<VecDeque<(Box<[Rc<Promise>]>, ErrorResult)>>,
|
in_flight_play_promises_queue: DomRefCell<VecDeque<(Box<[Rc<Promise>]>, ErrorResult)>>,
|
||||||
#[ignore_malloc_size_of = "servo_media"]
|
#[ignore_malloc_size_of = "servo_media"]
|
||||||
player: Box<Player<Error=ServoMediaError>>,
|
player: Box<Player<Error = ServoMediaError>>,
|
||||||
#[ignore_malloc_size_of = "Arc"]
|
#[ignore_malloc_size_of = "Arc"]
|
||||||
frame_renderer: Arc<Mutex<MediaFrameRenderer>>,
|
frame_renderer: Arc<Mutex<MediaFrameRenderer>>,
|
||||||
fetch_canceller: DomRefCell<FetchCanceller>,
|
fetch_canceller: DomRefCell<FetchCanceller>,
|
||||||
|
@ -169,6 +170,14 @@ pub struct HTMLMediaElement {
|
||||||
show_poster: Cell<bool>,
|
show_poster: Cell<bool>,
|
||||||
/// https://html.spec.whatwg.org/multipage/#dom-media-duration
|
/// https://html.spec.whatwg.org/multipage/#dom-media-duration
|
||||||
duration: Cell<f64>,
|
duration: Cell<f64>,
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#official-playback-position
|
||||||
|
playback_position: Cell<f64>,
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#default-playback-start-position
|
||||||
|
default_playback_start_position: Cell<f64>,
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#dom-media-seeking
|
||||||
|
seeking: Cell<bool>,
|
||||||
|
/// URL of the media resource, if any.
|
||||||
|
resource_url: DomRefCell<Option<ServoUrl>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://html.spec.whatwg.org/multipage/#dom-media-networkstate>
|
/// <https://html.spec.whatwg.org/multipage/#dom-media-networkstate>
|
||||||
|
@ -216,6 +225,10 @@ impl HTMLMediaElement {
|
||||||
fetch_canceller: DomRefCell::new(Default::default()),
|
fetch_canceller: DomRefCell::new(Default::default()),
|
||||||
show_poster: Cell::new(true),
|
show_poster: Cell::new(true),
|
||||||
duration: Cell::new(f64::NAN),
|
duration: Cell::new(f64::NAN),
|
||||||
|
playback_position: Cell::new(0.),
|
||||||
|
default_playback_start_position: Cell::new(0.),
|
||||||
|
seeking: Cell::new(false),
|
||||||
|
resource_url: DomRefCell::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -660,6 +673,65 @@ impl HTMLMediaElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fetch_request(&self, offset: Option<u64>) {
|
||||||
|
if self.resource_url.borrow().is_none() {
|
||||||
|
eprintln!("Missing request url");
|
||||||
|
self.queue_dedicated_media_source_failure_steps();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME(nox): Handle CORS setting from crossorigin attribute.
|
||||||
|
let document = document_from_node(self);
|
||||||
|
let destination = match self.media_type_id() {
|
||||||
|
HTMLMediaElementTypeId::HTMLAudioElement => Destination::Audio,
|
||||||
|
HTMLMediaElementTypeId::HTMLVideoElement => Destination::Video,
|
||||||
|
};
|
||||||
|
let mut headers = Headers::new();
|
||||||
|
headers.set(HyperRange::Bytes(vec![ByteRangeSpec::AllFrom(
|
||||||
|
offset.unwrap_or(0),
|
||||||
|
)]));
|
||||||
|
let request = RequestInit {
|
||||||
|
url: self.resource_url.borrow().as_ref().unwrap().clone(),
|
||||||
|
headers,
|
||||||
|
destination,
|
||||||
|
credentials_mode: CredentialsMode::Include,
|
||||||
|
use_url_credentials: true,
|
||||||
|
origin: document.origin().immutable().clone(),
|
||||||
|
pipeline_id: Some(self.global().pipeline_id()),
|
||||||
|
referrer_url: Some(document.url()),
|
||||||
|
referrer_policy: document.get_referrer_policy(),
|
||||||
|
..RequestInit::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let context = Arc::new(Mutex::new(HTMLMediaElementContext::new(self)));
|
||||||
|
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
||||||
|
let window = window_from_node(self);
|
||||||
|
let listener = NetworkListener {
|
||||||
|
context,
|
||||||
|
task_source: window.networking_task_source(),
|
||||||
|
canceller: Some(window.task_canceller(TaskSourceName::Networking)),
|
||||||
|
};
|
||||||
|
ROUTER.add_route(
|
||||||
|
action_receiver.to_opaque(),
|
||||||
|
Box::new(move |message| {
|
||||||
|
listener.notify_fetch(message.to().unwrap());
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
// This method may be called the first time we try to fetch the media
|
||||||
|
// resource or after a seek is requested. In the latter case, we need to
|
||||||
|
// cancel any previous on-going request. initialize() takes care of
|
||||||
|
// cancelling previous fetches if any exist.
|
||||||
|
let cancel_receiver = self.fetch_canceller.borrow_mut().initialize();
|
||||||
|
let global = self.global();
|
||||||
|
global
|
||||||
|
.core_resource_thread()
|
||||||
|
.send(CoreResourceMsg::Fetch(
|
||||||
|
request,
|
||||||
|
FetchChannels::ResponseMsg(action_sender, Some(cancel_receiver)),
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#concept-media-load-resource
|
// https://html.spec.whatwg.org/multipage/#concept-media-load-resource
|
||||||
fn resource_fetch_algorithm(&self, resource: Resource) {
|
fn resource_fetch_algorithm(&self, resource: Resource) {
|
||||||
if let Err(e) = self.setup_media_player() {
|
if let Err(e) = self.setup_media_player() {
|
||||||
|
@ -667,6 +739,14 @@ impl HTMLMediaElement {
|
||||||
self.queue_dedicated_media_source_failure_steps();
|
self.queue_dedicated_media_source_failure_steps();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX(ferjm) Since we only support Blob for now it is fine to always set
|
||||||
|
// the stream type to StreamType::Seekable. Once we support MediaStream,
|
||||||
|
// this should be changed to also consider StreamType::Stream.
|
||||||
|
if let Err(e) = self.player.set_stream_type(StreamType::Seekable) {
|
||||||
|
eprintln!("Could not set stream type to Seekable. {:?}", e);
|
||||||
|
}
|
||||||
|
|
||||||
// Steps 1-2.
|
// Steps 1-2.
|
||||||
// Unapplicable, the `resource` variable already conveys which mode
|
// Unapplicable, the `resource` variable already conveys which mode
|
||||||
// is in use.
|
// is in use.
|
||||||
|
@ -714,47 +794,8 @@ impl HTMLMediaElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 4.remote.2.
|
// Step 4.remote.2.
|
||||||
// FIXME(nox): Handle CORS setting from crossorigin attribute.
|
*self.resource_url.borrow_mut() = Some(url);
|
||||||
let document = document_from_node(self);
|
self.fetch_request(None);
|
||||||
let destination = match self.media_type_id() {
|
|
||||||
HTMLMediaElementTypeId::HTMLAudioElement => Destination::Audio,
|
|
||||||
HTMLMediaElementTypeId::HTMLVideoElement => Destination::Video,
|
|
||||||
};
|
|
||||||
let request = RequestInit {
|
|
||||||
url,
|
|
||||||
destination,
|
|
||||||
credentials_mode: CredentialsMode::Include,
|
|
||||||
use_url_credentials: true,
|
|
||||||
origin: document.origin().immutable().clone(),
|
|
||||||
pipeline_id: Some(self.global().pipeline_id()),
|
|
||||||
referrer_url: Some(document.url()),
|
|
||||||
referrer_policy: document.get_referrer_policy(),
|
|
||||||
..RequestInit::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let context = Arc::new(Mutex::new(HTMLMediaElementContext::new(self)));
|
|
||||||
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
|
||||||
let window = window_from_node(self);
|
|
||||||
let listener = NetworkListener {
|
|
||||||
context: context,
|
|
||||||
task_source: window.networking_task_source(),
|
|
||||||
canceller: Some(window.task_canceller(TaskSourceName::Networking)),
|
|
||||||
};
|
|
||||||
ROUTER.add_route(
|
|
||||||
action_receiver.to_opaque(),
|
|
||||||
Box::new(move |message| {
|
|
||||||
listener.notify_fetch(message.to().unwrap());
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
let cancel_receiver = self.fetch_canceller.borrow_mut().initialize();
|
|
||||||
let global = self.global();
|
|
||||||
global
|
|
||||||
.core_resource_thread()
|
|
||||||
.send(CoreResourceMsg::Fetch(
|
|
||||||
request,
|
|
||||||
FetchChannels::ResponseMsg(action_sender, Some(cancel_receiver)),
|
|
||||||
))
|
|
||||||
.unwrap();
|
|
||||||
},
|
},
|
||||||
Resource::Object => {
|
Resource::Object => {
|
||||||
// FIXME(nox): Actually do something with the object.
|
// FIXME(nox): Actually do something with the object.
|
||||||
|
@ -867,11 +908,16 @@ impl HTMLMediaElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 6.7.
|
// Step 6.7.
|
||||||
// FIXME(nox): If seeking is true, set it to false.
|
if !self.seeking.get() {
|
||||||
|
self.seeking.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
// Step 6.8.
|
// Step 6.8.
|
||||||
// FIXME(nox): Set current and official playback position to 0 and
|
let queue_timeupdate_event = self.playback_position.get() != 0.;
|
||||||
// maybe queue a task to fire a timeupdate event.
|
self.playback_position.set(0.);
|
||||||
|
if queue_timeupdate_event {
|
||||||
|
task_source.queue_simple_event(self.upcast(), atom!("timeupdate"), &window);
|
||||||
|
}
|
||||||
|
|
||||||
// Step 6.9.
|
// Step 6.9.
|
||||||
// FIXME(nox): Set timeline offset to NaN.
|
// FIXME(nox): Set timeline offset to NaN.
|
||||||
|
@ -961,8 +1007,77 @@ impl HTMLMediaElement {
|
||||||
self.media_element_load_algorithm();
|
self.media_element_load_algorithm();
|
||||||
}
|
}
|
||||||
|
|
||||||
// servo media player
|
// https://html.spec.whatwg.org/multipage/#dom-media-seek
|
||||||
fn setup_media_player(&self) -> Result<(), ServoMediaError>{
|
fn seek(&self, time: f64, _approximate_for_speed: bool) {
|
||||||
|
// Step 1.
|
||||||
|
self.show_poster.set(false);
|
||||||
|
|
||||||
|
// Step 2.
|
||||||
|
if self.ready_state.get() == ReadyState::HaveNothing {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3.
|
||||||
|
if self.seeking.get() {
|
||||||
|
// This will cancel only the sync part of the seek algorithm.
|
||||||
|
self.generation_id.set(self.generation_id.get() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4.
|
||||||
|
// The flag will be cleared when the media engine tells us the seek was done.
|
||||||
|
self.seeking.set(true);
|
||||||
|
|
||||||
|
// Step 5.
|
||||||
|
// XXX(ferjm) The rest of the steps should be run in parallel, so seeking cancelation
|
||||||
|
// can be done properly. No other browser does it yet anyway.
|
||||||
|
|
||||||
|
// Step 6.
|
||||||
|
let time = f64::min(time, self.Duration());
|
||||||
|
|
||||||
|
// Step 7.
|
||||||
|
let time = f64::max(time, 0.);
|
||||||
|
|
||||||
|
// Step 8.
|
||||||
|
// XXX(ferjm) seekable attribute: we need to get the information about
|
||||||
|
// what's been decoded and buffered so far from servo-media
|
||||||
|
// and add the seekable attribute as a TimeRange.
|
||||||
|
|
||||||
|
// Step 9.
|
||||||
|
// servo-media with gstreamer does not support inaccurate seeking for now.
|
||||||
|
|
||||||
|
// Step 10.
|
||||||
|
let window = window_from_node(self);
|
||||||
|
let task_source = window.media_element_task_source();
|
||||||
|
task_source.queue_simple_event(self.upcast(), atom!("seeking"), &window);
|
||||||
|
|
||||||
|
// Step 11.
|
||||||
|
if let Err(e) = self.player.seek(time) {
|
||||||
|
eprintln!("Seek error {:?}", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The rest of the steps are handled when the media engine signals a
|
||||||
|
// ready state change or otherwise satisfies seek completion and signals
|
||||||
|
// a position change.
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-media-seek
|
||||||
|
fn seek_end(&self) {
|
||||||
|
// Step 14.
|
||||||
|
self.seeking.set(false);
|
||||||
|
|
||||||
|
// Step 15.
|
||||||
|
self.time_marches_on();
|
||||||
|
|
||||||
|
// Step 16.
|
||||||
|
let window = window_from_node(self);
|
||||||
|
let task_source = window.media_element_task_source();
|
||||||
|
task_source.queue_simple_event(self.upcast(), atom!("timeupdate"), &window);
|
||||||
|
|
||||||
|
// Step 17.
|
||||||
|
task_source.queue_simple_event(self.upcast(), atom!("seeked"), &window);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_media_player(&self) -> Result<(), ServoMediaError> {
|
||||||
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
||||||
|
|
||||||
self.player.register_event_handler(action_sender)?;
|
self.player.register_event_handler(action_sender)?;
|
||||||
|
@ -1004,8 +1119,7 @@ impl HTMLMediaElement {
|
||||||
// XXX(ferjm) Update the timeline offset.
|
// XXX(ferjm) Update the timeline offset.
|
||||||
|
|
||||||
// Step 3.
|
// Step 3.
|
||||||
// XXX(ferjm) Set the current and official playback positions
|
self.playback_position.set(0.);
|
||||||
// to the earliest possible position.
|
|
||||||
|
|
||||||
// Step 4.
|
// Step 4.
|
||||||
if let Some(duration) = metadata.duration {
|
if let Some(duration) = metadata.duration {
|
||||||
|
@ -1028,7 +1142,30 @@ impl HTMLMediaElement {
|
||||||
// Step 6.
|
// Step 6.
|
||||||
self.change_ready_state(ReadyState::HaveMetadata);
|
self.change_ready_state(ReadyState::HaveMetadata);
|
||||||
|
|
||||||
// XXX(ferjm) Steps 7 to 13.
|
// Step 7.
|
||||||
|
let mut _jumped = false;
|
||||||
|
|
||||||
|
// Step 8.
|
||||||
|
if self.default_playback_start_position.get() > 0. {
|
||||||
|
self.seek(
|
||||||
|
self.default_playback_start_position.get(),
|
||||||
|
/* approximate_for_speed*/ false,
|
||||||
|
);
|
||||||
|
_jumped = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 9.
|
||||||
|
self.default_playback_start_position.set(0.);
|
||||||
|
|
||||||
|
// Steps 10 and 11.
|
||||||
|
// XXX(ferjm) Implement parser for
|
||||||
|
// https://www.w3.org/TR/media-frags/#media-fragment-syntax
|
||||||
|
// https://github.com/servo/media/issues/156
|
||||||
|
|
||||||
|
// XXX Steps 12 and 13 require audio and video tracks support.
|
||||||
|
},
|
||||||
|
PlayerEvent::PositionChanged(position) => {
|
||||||
|
self.playback_position.set(position as f64);
|
||||||
},
|
},
|
||||||
PlayerEvent::StateChanged(ref state) => match *state {
|
PlayerEvent::StateChanged(ref state) => match *state {
|
||||||
PlaybackState::Paused => {
|
PlaybackState::Paused => {
|
||||||
|
@ -1038,11 +1175,6 @@ impl HTMLMediaElement {
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
},
|
},
|
||||||
PlayerEvent::PositionChanged(_) |
|
|
||||||
PlayerEvent::SeekData(_) |
|
|
||||||
PlayerEvent::SeekDone(_) => {
|
|
||||||
// TODO: Support for HTMLMediaElement seeking and related API properties #21998
|
|
||||||
},
|
|
||||||
PlayerEvent::EndOfStream => {
|
PlayerEvent::EndOfStream => {
|
||||||
// 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 data can be fetched but is found by inspection to be in
|
// => "If the media data can be fetched but is found by inspection to be in
|
||||||
|
@ -1054,6 +1186,20 @@ impl HTMLMediaElement {
|
||||||
PlayerEvent::FrameUpdated => {
|
PlayerEvent::FrameUpdated => {
|
||||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||||
},
|
},
|
||||||
|
PlayerEvent::SeekData(p) => {
|
||||||
|
self.fetch_request(Some(p));
|
||||||
|
},
|
||||||
|
PlayerEvent::SeekDone(_) => {
|
||||||
|
// Continuation of
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-media-seek
|
||||||
|
|
||||||
|
// Step 13.
|
||||||
|
let task = MediaElementMicrotask::SeekedTask {
|
||||||
|
elem: DomRoot::from_ref(self),
|
||||||
|
generation_id: self.generation_id.get(),
|
||||||
|
};
|
||||||
|
ScriptThread::await_stable_state(Microtask::MediaElement(task));
|
||||||
|
},
|
||||||
PlayerEvent::Error => {
|
PlayerEvent::Error => {
|
||||||
self.error.set(Some(&*MediaError::new(
|
self.error.set(Some(&*MediaError::new(
|
||||||
&*window_from_node(self),
|
&*window_from_node(self),
|
||||||
|
@ -1157,6 +1303,35 @@ impl HTMLMediaElementMethods for HTMLMediaElement {
|
||||||
fn Duration(&self) -> f64 {
|
fn Duration(&self) -> f64 {
|
||||||
self.duration.get()
|
self.duration.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-media-currenttime
|
||||||
|
fn CurrentTime(&self) -> Finite<f64> {
|
||||||
|
Finite::wrap(if self.default_playback_start_position.get() != 0. {
|
||||||
|
self.default_playback_start_position.get()
|
||||||
|
} else {
|
||||||
|
self.playback_position.get()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-media-currenttime
|
||||||
|
fn SetCurrentTime(&self, time: Finite<f64>) {
|
||||||
|
if self.ready_state.get() == ReadyState::HaveNothing {
|
||||||
|
self.default_playback_start_position.set(*time);
|
||||||
|
} else {
|
||||||
|
self.playback_position.set(*time);
|
||||||
|
self.seek(*time, /* approximate_for_speed */ false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-media-seeking
|
||||||
|
fn Seeking(&self) -> bool {
|
||||||
|
self.seeking.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-media-fastseek
|
||||||
|
fn FastSeek(&self, time: Finite<f64>) {
|
||||||
|
self.seek(*time, /* approximat_for_speed */ true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VirtualMethods for HTMLMediaElement {
|
impl VirtualMethods for HTMLMediaElement {
|
||||||
|
@ -1214,6 +1389,10 @@ pub enum MediaElementMicrotask {
|
||||||
PauseIfNotInDocumentTask {
|
PauseIfNotInDocumentTask {
|
||||||
elem: DomRoot<HTMLMediaElement>,
|
elem: DomRoot<HTMLMediaElement>,
|
||||||
},
|
},
|
||||||
|
SeekedTask {
|
||||||
|
elem: DomRoot<HTMLMediaElement>,
|
||||||
|
generation_id: u32,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MicrotaskRunnable for MediaElementMicrotask {
|
impl MicrotaskRunnable for MediaElementMicrotask {
|
||||||
|
@ -1233,6 +1412,14 @@ impl MicrotaskRunnable for MediaElementMicrotask {
|
||||||
elem.internal_pause_steps();
|
elem.internal_pause_steps();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
&MediaElementMicrotask::SeekedTask {
|
||||||
|
ref elem,
|
||||||
|
generation_id,
|
||||||
|
} => {
|
||||||
|
if generation_id == elem.generation_id.get() {
|
||||||
|
elem.seek_end();
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1347,6 +1534,8 @@ impl FetchResponseListener for HTMLMediaElementContext {
|
||||||
elem.network_state.set(NetworkState::Idle);
|
elem.network_state.set(NetworkState::Idle);
|
||||||
|
|
||||||
elem.upcast::<EventTarget>().fire_event(atom!("suspend"));
|
elem.upcast::<EventTarget>().fire_event(atom!("suspend"));
|
||||||
|
|
||||||
|
elem.delay_load_event(false);
|
||||||
}
|
}
|
||||||
// => "If the connection is interrupted after some media data has been received..."
|
// => "If the connection is interrupted after some media data has been received..."
|
||||||
else if elem.ready_state.get() != ReadyState::HaveNothing {
|
else if elem.ready_state.get() != ReadyState::HaveNothing {
|
||||||
|
|
|
@ -451,7 +451,7 @@ macro_rules! global_event_handlers(
|
||||||
event_handler!(keypress, GetOnkeypress, SetOnkeypress);
|
event_handler!(keypress, GetOnkeypress, SetOnkeypress);
|
||||||
event_handler!(keyup, GetOnkeyup, SetOnkeyup);
|
event_handler!(keyup, GetOnkeyup, SetOnkeyup);
|
||||||
event_handler!(loadeddata, GetOnloadeddata, SetOnloadeddata);
|
event_handler!(loadeddata, GetOnloadeddata, SetOnloadeddata);
|
||||||
event_handler!(loadedmetata, GetOnloadedmetadata, SetOnloadedmetadata);
|
event_handler!(loadedmetadata, GetOnloadedmetadata, SetOnloadedmetadata);
|
||||||
event_handler!(loadstart, GetOnloadstart, SetOnloadstart);
|
event_handler!(loadstart, GetOnloadstart, SetOnloadstart);
|
||||||
event_handler!(mousedown, GetOnmousedown, SetOnmousedown);
|
event_handler!(mousedown, GetOnmousedown, SetOnmousedown);
|
||||||
event_handler!(mouseenter, GetOnmouseenter, SetOnmouseenter);
|
event_handler!(mouseenter, GetOnmouseenter, SetOnmouseenter);
|
||||||
|
|
|
@ -34,11 +34,11 @@ interface HTMLMediaElement : HTMLElement {
|
||||||
const unsigned short HAVE_FUTURE_DATA = 3;
|
const unsigned short HAVE_FUTURE_DATA = 3;
|
||||||
const unsigned short HAVE_ENOUGH_DATA = 4;
|
const unsigned short HAVE_ENOUGH_DATA = 4;
|
||||||
readonly attribute unsigned short readyState;
|
readonly attribute unsigned short readyState;
|
||||||
// readonly attribute boolean seeking;
|
readonly attribute boolean seeking;
|
||||||
|
|
||||||
// playback state
|
// playback state
|
||||||
// attribute double currentTime;
|
attribute double currentTime;
|
||||||
// void fastSeek(double time);
|
void fastSeek(double time);
|
||||||
readonly attribute unrestricted double duration;
|
readonly attribute unrestricted double duration;
|
||||||
// Date getStartDate();
|
// Date getStartDate();
|
||||||
readonly attribute boolean paused;
|
readonly attribute boolean paused;
|
||||||
|
|
|
@ -6783,18 +6783,6 @@
|
||||||
[HTMLMediaElement interface: document.createElement("video") must inherit property "buffered" with the proper type]
|
[HTMLMediaElement interface: document.createElement("video") must inherit property "buffered" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[HTMLMediaElement interface: document.createElement("video") must inherit property "seeking" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLMediaElement interface: document.createElement("video") must inherit property "currentTime" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLMediaElement interface: document.createElement("video") must inherit property "fastSeek(double)" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLMediaElement interface: calling fastSeek(double) on document.createElement("video") with too few arguments must throw TypeError]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLMediaElement interface: document.createElement("video") must inherit property "getStartDate()" with the proper type]
|
[HTMLMediaElement interface: document.createElement("video") must inherit property "getStartDate()" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -6852,18 +6840,6 @@
|
||||||
[HTMLMediaElement interface: document.createElement("audio") must inherit property "buffered" with the proper type]
|
[HTMLMediaElement interface: document.createElement("audio") must inherit property "buffered" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[HTMLMediaElement interface: document.createElement("audio") must inherit property "seeking" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLMediaElement interface: document.createElement("audio") must inherit property "currentTime" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLMediaElement interface: document.createElement("audio") must inherit property "fastSeek(double)" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLMediaElement interface: calling fastSeek(double) on document.createElement("audio") with too few arguments must throw TypeError]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLMediaElement interface: document.createElement("audio") must inherit property "getStartDate()" with the proper type]
|
[HTMLMediaElement interface: document.createElement("audio") must inherit property "getStartDate()" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -7140,15 +7116,6 @@
|
||||||
[HTMLMediaElement interface: attribute buffered]
|
[HTMLMediaElement interface: attribute buffered]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[HTMLMediaElement interface: attribute seeking]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLMediaElement interface: attribute currentTime]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLMediaElement interface: operation fastSeek(double)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLMediaElement interface: operation getStartDate()]
|
[HTMLMediaElement interface: operation getStartDate()]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
[currentTime.html]
|
|
||||||
type: testharness
|
|
||||||
expected: TIMEOUT
|
|
||||||
[currentTime initial value]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[setting currentTime with a media controller present]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[setting currentTime when readyState is HAVE_NOTHING]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[setting currentTime when readyState is greater than HAVE_NOTHING]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
[seek-to-currentTime.html]
|
[seek-to-currentTime.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: TIMEOUT
|
|
||||||
[seek to currentTime]
|
[seek to currentTime]
|
||||||
expected: TIMEOUT
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
[seek-to-max-value.htm]
|
[seek-to-max-value.htm]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: TIMEOUT
|
|
||||||
[seek to Number.MAX_VALUE]
|
[seek to Number.MAX_VALUE]
|
||||||
expected: TIMEOUT
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
[seek-to-negative-time.htm]
|
[seek-to-negative-time.htm]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: TIMEOUT
|
|
||||||
[seek to negative time]
|
[seek to negative time]
|
||||||
expected: TIMEOUT
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -5,253 +5,376 @@
|
||||||
|
|
||||||
[onabort: must be on the appropriate locations for GlobalEventHandlers]
|
[onabort: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onabort: the default value must be null]
|
[onabort: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onauxclick: must be on the appropriate locations for GlobalEventHandlers]
|
[onauxclick: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onauxclick: the default value must be null]
|
[onauxclick: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onauxclick: the content attribute must be compiled into a function as the corresponding property]
|
[onauxclick: the content attribute must be compiled into a function as the corresponding property]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onblur: must be on the appropriate locations for GlobalEventHandlers]
|
[onblur: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onblur: the default value must be null]
|
[onblur: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[oncancel: must be on the appropriate locations for GlobalEventHandlers]
|
[oncancel: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[oncancel: the default value must be null]
|
[oncancel: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[oncanplay: must be on the appropriate locations for GlobalEventHandlers]
|
[oncanplay: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[oncanplay: the default value must be null]
|
[oncanplay: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[oncanplaythrough: must be on the appropriate locations for GlobalEventHandlers]
|
[oncanplaythrough: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[oncanplaythrough: the default value must be null]
|
[oncanplaythrough: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onchange: must be on the appropriate locations for GlobalEventHandlers]
|
[onchange: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onchange: the default value must be null]
|
[onchange: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onclick: must be on the appropriate locations for GlobalEventHandlers]
|
[onclick: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onclick: the default value must be null]
|
[onclick: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onclose: must be on the appropriate locations for GlobalEventHandlers]
|
[onclose: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onclose: the default value must be null]
|
[onclose: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[oncontextmenu: must be on the appropriate locations for GlobalEventHandlers]
|
[oncontextmenu: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[oncontextmenu: the default value must be null]
|
[oncontextmenu: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[oncuechange: must be on the appropriate locations for GlobalEventHandlers]
|
[oncuechange: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[oncuechange: the default value must be null]
|
[oncuechange: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ondblclick: must be on the appropriate locations for GlobalEventHandlers]
|
[ondblclick: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ondblclick: the default value must be null]
|
[ondblclick: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ondrag: must be on the appropriate locations for GlobalEventHandlers]
|
[ondrag: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ondrag: the default value must be null]
|
[ondrag: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ondragend: must be on the appropriate locations for GlobalEventHandlers]
|
[ondragend: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ondragend: the default value must be null]
|
[ondragend: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ondragenter: must be on the appropriate locations for GlobalEventHandlers]
|
[ondragenter: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ondragenter: the default value must be null]
|
[ondragenter: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ondragexit: must be on the appropriate locations for GlobalEventHandlers]
|
[ondragexit: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ondragexit: the default value must be null]
|
[ondragexit: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ondragleave: must be on the appropriate locations for GlobalEventHandlers]
|
[ondragleave: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ondragleave: the default value must be null]
|
[ondragleave: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ondragover: must be on the appropriate locations for GlobalEventHandlers]
|
[ondragover: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ondragover: the default value must be null]
|
[ondragover: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ondragstart: must be on the appropriate locations for GlobalEventHandlers]
|
[ondragstart: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ondragstart: the default value must be null]
|
[ondragstart: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ondrop: must be on the appropriate locations for GlobalEventHandlers]
|
[ondrop: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ondrop: the default value must be null]
|
[ondrop: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ondurationchange: must be on the appropriate locations for GlobalEventHandlers]
|
[ondurationchange: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ondurationchange: the default value must be null]
|
[ondurationchange: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onemptied: must be on the appropriate locations for GlobalEventHandlers]
|
[onemptied: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onemptied: the default value must be null]
|
[onemptied: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onended: must be on the appropriate locations for GlobalEventHandlers]
|
[onended: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onended: the default value must be null]
|
[onended: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onfocus: must be on the appropriate locations for GlobalEventHandlers]
|
[onfocus: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onfocus: the default value must be null]
|
[onfocus: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[oninput: must be on the appropriate locations for GlobalEventHandlers]
|
[oninput: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[oninput: the default value must be null]
|
[oninput: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[oninvalid: must be on the appropriate locations for GlobalEventHandlers]
|
[oninvalid: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[oninvalid: the default value must be null]
|
[oninvalid: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onkeydown: must be on the appropriate locations for GlobalEventHandlers]
|
[onkeydown: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onkeydown: the default value must be null]
|
[onkeydown: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onkeypress: must be on the appropriate locations for GlobalEventHandlers]
|
[onkeypress: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onkeypress: the default value must be null]
|
[onkeypress: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onkeyup: must be on the appropriate locations for GlobalEventHandlers]
|
[onkeyup: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onkeyup: the default value must be null]
|
[onkeyup: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onload: must be on the appropriate locations for GlobalEventHandlers]
|
[onload: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onload: the default value must be null]
|
[onload: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onloadeddata: must be on the appropriate locations for GlobalEventHandlers]
|
[onloadeddata: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onloadeddata: the default value must be null]
|
[onloadeddata: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onloadedmetadata: must be on the appropriate locations for GlobalEventHandlers]
|
[onloadedmetadata: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onloadedmetadata: the default value must be null]
|
[onloadedmetadata: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
[onloadedmetadata: the content attribute must be compiled into a function as the corresponding property]
|
|
||||||
expected: FAIL
|
|
||||||
[onloadend: must be on the appropriate locations for GlobalEventHandlers]
|
[onloadend: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onloadend: the default value must be null]
|
[onloadend: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onloadend: the content attribute must be compiled into a function as the corresponding property]
|
[onloadend: the content attribute must be compiled into a function as the corresponding property]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onloadstart: must be on the appropriate locations for GlobalEventHandlers]
|
[onloadstart: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onloadstart: the default value must be null]
|
[onloadstart: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onmousedown: must be on the appropriate locations for GlobalEventHandlers]
|
[onmousedown: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onmousedown: the default value must be null]
|
[onmousedown: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onmouseenter: must be on the appropriate locations for GlobalEventHandlers]
|
[onmouseenter: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onmouseenter: the default value must be null]
|
[onmouseenter: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onmouseleave: must be on the appropriate locations for GlobalEventHandlers]
|
[onmouseleave: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onmouseleave: the default value must be null]
|
[onmouseleave: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onmousemove: must be on the appropriate locations for GlobalEventHandlers]
|
[onmousemove: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onmousemove: the default value must be null]
|
[onmousemove: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onmouseout: must be on the appropriate locations for GlobalEventHandlers]
|
[onmouseout: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onmouseout: the default value must be null]
|
[onmouseout: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onmouseover: must be on the appropriate locations for GlobalEventHandlers]
|
[onmouseover: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onmouseover: the default value must be null]
|
[onmouseover: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onmouseup: must be on the appropriate locations for GlobalEventHandlers]
|
[onmouseup: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onmouseup: the default value must be null]
|
[onmouseup: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onwheel: must be on the appropriate locations for GlobalEventHandlers]
|
[onwheel: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onwheel: the default value must be null]
|
[onwheel: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onpause: must be on the appropriate locations for GlobalEventHandlers]
|
[onpause: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onpause: the default value must be null]
|
[onpause: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onplay: must be on the appropriate locations for GlobalEventHandlers]
|
[onplay: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onplay: the default value must be null]
|
[onplay: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onplaying: must be on the appropriate locations for GlobalEventHandlers]
|
[onplaying: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onplaying: the default value must be null]
|
[onplaying: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onprogress: must be on the appropriate locations for GlobalEventHandlers]
|
[onprogress: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onprogress: the default value must be null]
|
[onprogress: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onratechange: must be on the appropriate locations for GlobalEventHandlers]
|
[onratechange: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onratechange: the default value must be null]
|
[onratechange: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onreset: must be on the appropriate locations for GlobalEventHandlers]
|
[onreset: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onreset: the default value must be null]
|
[onreset: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onresize: must be on the appropriate locations for GlobalEventHandlers]
|
[onresize: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onresize: the default value must be null]
|
[onresize: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onscroll: must be on the appropriate locations for GlobalEventHandlers]
|
[onscroll: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onscroll: the default value must be null]
|
[onscroll: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onsecuritypolicyviolation: must be on the appropriate locations for GlobalEventHandlers]
|
[onsecuritypolicyviolation: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onsecuritypolicyviolation: the default value must be null]
|
[onsecuritypolicyviolation: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onsecuritypolicyviolation: the content attribute must be compiled into a function as the corresponding property]
|
[onsecuritypolicyviolation: the content attribute must be compiled into a function as the corresponding property]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onseeked: must be on the appropriate locations for GlobalEventHandlers]
|
[onseeked: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onseeked: the default value must be null]
|
[onseeked: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onseeking: must be on the appropriate locations for GlobalEventHandlers]
|
[onseeking: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onseeking: the default value must be null]
|
[onseeking: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onselect: must be on the appropriate locations for GlobalEventHandlers]
|
[onselect: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onselect: the default value must be null]
|
[onselect: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onstalled: must be on the appropriate locations for GlobalEventHandlers]
|
[onstalled: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onstalled: the default value must be null]
|
[onstalled: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onsubmit: must be on the appropriate locations for GlobalEventHandlers]
|
[onsubmit: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onsubmit: the default value must be null]
|
[onsubmit: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onsuspend: must be on the appropriate locations for GlobalEventHandlers]
|
[onsuspend: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onsuspend: the default value must be null]
|
[onsuspend: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ontimeupdate: must be on the appropriate locations for GlobalEventHandlers]
|
[ontimeupdate: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ontimeupdate: the default value must be null]
|
[ontimeupdate: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ontoggle: must be on the appropriate locations for GlobalEventHandlers]
|
[ontoggle: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[ontoggle: the default value must be null]
|
[ontoggle: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onvolumechange: must be on the appropriate locations for GlobalEventHandlers]
|
[onvolumechange: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onvolumechange: the default value must be null]
|
[onvolumechange: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onwaiting: must be on the appropriate locations for GlobalEventHandlers]
|
[onwaiting: must be on the appropriate locations for GlobalEventHandlers]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[onwaiting: the default value must be null]
|
[onwaiting: the default value must be null]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue