mirror of
https://github.com/servo/servo.git
synced 2025-06-19 14:48:59 +01:00
Do not NIH queueing a task to fire an event in htmlmediaelement
This commit is contained in:
parent
6168e898c1
commit
62c73b61b7
2 changed files with 89 additions and 59 deletions
|
@ -2,6 +2,8 @@ abort
|
||||||
activate
|
activate
|
||||||
beforeunload
|
beforeunload
|
||||||
button
|
button
|
||||||
|
canplay
|
||||||
|
canplaythrough
|
||||||
center
|
center
|
||||||
change
|
change
|
||||||
characteristicvaluechanged
|
characteristicvaluechanged
|
||||||
|
@ -16,6 +18,7 @@ datetime-local
|
||||||
dir
|
dir
|
||||||
DOMContentLoaded
|
DOMContentLoaded
|
||||||
email
|
email
|
||||||
|
emptied
|
||||||
error
|
error
|
||||||
fantasy
|
fantasy
|
||||||
fetch
|
fetch
|
||||||
|
@ -31,6 +34,8 @@ keydown
|
||||||
keypress
|
keypress
|
||||||
left
|
left
|
||||||
load
|
load
|
||||||
|
loadeddata
|
||||||
|
loadedmetadata
|
||||||
loadend
|
loadend
|
||||||
loadstart
|
loadstart
|
||||||
message
|
message
|
||||||
|
@ -43,6 +48,9 @@ number
|
||||||
onchange
|
onchange
|
||||||
open
|
open
|
||||||
password
|
password
|
||||||
|
pause
|
||||||
|
play
|
||||||
|
playing
|
||||||
print
|
print
|
||||||
progress
|
progress
|
||||||
radio
|
radio
|
||||||
|
@ -58,11 +66,14 @@ serif
|
||||||
statechange
|
statechange
|
||||||
storage
|
storage
|
||||||
submit
|
submit
|
||||||
|
suspend
|
||||||
tel
|
tel
|
||||||
text
|
text
|
||||||
time
|
time
|
||||||
|
timeupdate
|
||||||
toggle
|
toggle
|
||||||
transitionend
|
transitionend
|
||||||
url
|
url
|
||||||
|
waiting
|
||||||
webglcontextcreationerror
|
webglcontextcreationerror
|
||||||
week
|
week
|
||||||
|
|
|
@ -19,7 +19,7 @@ use dom::bindings::reflector::DomObject;
|
||||||
use dom::bindings::str::DOMString;
|
use dom::bindings::str::DOMString;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::element::{Element, AttributeMutation};
|
use dom::element::{Element, AttributeMutation};
|
||||||
use dom::event::{Event, EventBubbles, EventCancelable};
|
use dom::eventtarget::EventTarget;
|
||||||
use dom::htmlaudioelement::HTMLAudioElement;
|
use dom::htmlaudioelement::HTMLAudioElement;
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::htmlsourceelement::HTMLSourceElement;
|
use dom::htmlsourceelement::HTMLSourceElement;
|
||||||
|
@ -36,7 +36,6 @@ use net_traits::{FetchResponseListener, FetchMetadata, Metadata, NetworkError};
|
||||||
use net_traits::request::{CredentialsMode, Destination, RequestInit, Type as RequestType};
|
use net_traits::request::{CredentialsMode, Destination, RequestInit, Type as RequestType};
|
||||||
use network_listener::{NetworkListener, PreInvoke};
|
use network_listener::{NetworkListener, PreInvoke};
|
||||||
use script_thread::{Runnable, ScriptThread};
|
use script_thread::{Runnable, ScriptThread};
|
||||||
use servo_atoms::Atom;
|
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
@ -111,7 +110,12 @@ impl FetchResponseListener for HTMLMediaElementContext {
|
||||||
// https://html.spec.whatwg.org/multipage/#concept-media-load-resource step 4,
|
// https://html.spec.whatwg.org/multipage/#concept-media-load-resource step 4,
|
||||||
// => "If mode is remote" step 2
|
// => "If mode is remote" step 2
|
||||||
if time::get_time() > self.next_progress_event {
|
if time::get_time() > self.next_progress_event {
|
||||||
elem.queue_fire_simple_event("progress");
|
let window = window_from_node(&*elem);
|
||||||
|
window.dom_manipulation_task_source().queue_simple_event(
|
||||||
|
elem.upcast(),
|
||||||
|
atom!("progress"),
|
||||||
|
&window,
|
||||||
|
);
|
||||||
self.next_progress_event = time::get_time() + Duration::milliseconds(350);
|
self.next_progress_event = time::get_time() + Duration::milliseconds(350);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,11 +133,11 @@ impl FetchResponseListener for HTMLMediaElementContext {
|
||||||
else if status.is_ok() {
|
else if status.is_ok() {
|
||||||
elem.change_ready_state(HAVE_ENOUGH_DATA);
|
elem.change_ready_state(HAVE_ENOUGH_DATA);
|
||||||
|
|
||||||
elem.fire_simple_event("progress");
|
elem.upcast::<EventTarget>().fire_event(atom!("progress"));
|
||||||
|
|
||||||
elem.network_state.set(NETWORK_IDLE);
|
elem.network_state.set(NETWORK_IDLE);
|
||||||
|
|
||||||
elem.fire_simple_event("suspend");
|
elem.upcast::<EventTarget>().fire_event(atom!("suspend"));
|
||||||
}
|
}
|
||||||
// => "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() != HAVE_NOTHING {
|
else if elem.ready_state.get() != HAVE_NOTHING {
|
||||||
|
@ -147,7 +151,7 @@ impl FetchResponseListener for HTMLMediaElementContext {
|
||||||
// TODO: Step 4 - update delay load flag
|
// TODO: Step 4 - update delay load flag
|
||||||
|
|
||||||
// Step 5
|
// Step 5
|
||||||
elem.fire_simple_event("error");
|
elem.upcast::<EventTarget>().fire_event(atom!("error"));
|
||||||
} else {
|
} else {
|
||||||
// => "If the media data cannot be fetched at all..."
|
// => "If the media data cannot be fetched at all..."
|
||||||
elem.queue_dedicated_media_source_failure_steps();
|
elem.queue_dedicated_media_source_failure_steps();
|
||||||
|
@ -267,7 +271,7 @@ impl HTMLMediaElement {
|
||||||
// https://html.spec.whatwg.org/multipage/#notify-about-playing
|
// https://html.spec.whatwg.org/multipage/#notify-about-playing
|
||||||
fn notify_about_playing(&self) {
|
fn notify_about_playing(&self) {
|
||||||
// Step 1
|
// Step 1
|
||||||
self.fire_simple_event("playing");
|
self.upcast::<EventTarget>().fire_event(atom!("playing"));
|
||||||
// TODO Step 2
|
// TODO Step 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,11 +301,11 @@ impl HTMLMediaElement {
|
||||||
|
|
||||||
impl Runnable for Task {
|
impl Runnable for Task {
|
||||||
fn handler(self: Box<Task>) {
|
fn handler(self: Box<Task>) {
|
||||||
let elem = self.elem.root();
|
let target = Root::upcast::<EventTarget>(self.elem.root());
|
||||||
// 2.2.1
|
// 2.2.1
|
||||||
elem.fire_simple_event("timeupdate");
|
target.fire_event(atom!("timeupdate"));
|
||||||
// 2.2.2
|
// 2.2.2
|
||||||
elem.fire_simple_event("pause");
|
target.fire_event(atom!("pause"));
|
||||||
// TODO 2.2.3
|
// TODO 2.2.3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -313,21 +317,6 @@ impl HTMLMediaElement {
|
||||||
let _ = win.dom_manipulation_task_source().queue(task, win.upcast());
|
let _ = win.dom_manipulation_task_source().queue(task, win.upcast());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn queue_fire_simple_event(&self, type_: &'static str) {
|
|
||||||
let win = window_from_node(self);
|
|
||||||
let task = box FireSimpleEventTask::new(self, type_);
|
|
||||||
let _ = win.dom_manipulation_task_source().queue(task, win.upcast());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fire_simple_event(&self, type_: &str) {
|
|
||||||
let window = window_from_node(self);
|
|
||||||
let event = Event::new(window.upcast(),
|
|
||||||
Atom::from(type_),
|
|
||||||
EventBubbles::DoesNotBubble,
|
|
||||||
EventCancelable::NotCancelable);
|
|
||||||
event.fire(self.upcast());
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#ready-states
|
// https://html.spec.whatwg.org/multipage/#ready-states
|
||||||
fn change_ready_state(&self, ready_state: u16) {
|
fn change_ready_state(&self, ready_state: u16) {
|
||||||
let old_ready_state = self.ready_state.get();
|
let old_ready_state = self.ready_state.get();
|
||||||
|
@ -337,12 +326,19 @@ impl HTMLMediaElement {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let window = window_from_node(self);
|
||||||
|
let task_source = window.dom_manipulation_task_source();
|
||||||
|
|
||||||
// Step 1
|
// Step 1
|
||||||
match (old_ready_state, ready_state) {
|
match (old_ready_state, ready_state) {
|
||||||
// previous ready state was HAVE_NOTHING, and the new ready state is
|
// previous ready state was HAVE_NOTHING, and the new ready state is
|
||||||
// HAVE_METADATA
|
// HAVE_METADATA
|
||||||
(HAVE_NOTHING, HAVE_METADATA) => {
|
(HAVE_NOTHING, HAVE_METADATA) => {
|
||||||
self.queue_fire_simple_event("loadedmetadata");
|
task_source.queue_simple_event(
|
||||||
|
self.upcast(),
|
||||||
|
atom!("loadedmetadata"),
|
||||||
|
&window,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// previous ready state was HAVE_METADATA and the new ready state is
|
// previous ready state was HAVE_METADATA and the new ready state is
|
||||||
|
@ -352,7 +348,11 @@ impl HTMLMediaElement {
|
||||||
(HAVE_METADATA, HAVE_ENOUGH_DATA) => {
|
(HAVE_METADATA, HAVE_ENOUGH_DATA) => {
|
||||||
if self.first_data_load.get() {
|
if self.first_data_load.get() {
|
||||||
self.first_data_load.set(false);
|
self.first_data_load.set(false);
|
||||||
self.queue_fire_simple_event("loadeddata");
|
task_source.queue_simple_event(
|
||||||
|
self.upcast(),
|
||||||
|
atom!("loadeddata"),
|
||||||
|
&window,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,7 +379,11 @@ impl HTMLMediaElement {
|
||||||
(HAVE_CURRENT_DATA, HAVE_FUTURE_DATA) |
|
(HAVE_CURRENT_DATA, HAVE_FUTURE_DATA) |
|
||||||
(HAVE_METADATA, HAVE_FUTURE_DATA) |
|
(HAVE_METADATA, HAVE_FUTURE_DATA) |
|
||||||
(HAVE_NOTHING, HAVE_FUTURE_DATA) => {
|
(HAVE_NOTHING, HAVE_FUTURE_DATA) => {
|
||||||
self.queue_fire_simple_event("canplay");
|
task_source.queue_simple_event(
|
||||||
|
self.upcast(),
|
||||||
|
atom!("canplay"),
|
||||||
|
&window,
|
||||||
|
);
|
||||||
|
|
||||||
if !self.Paused() {
|
if !self.Paused() {
|
||||||
self.queue_notify_about_playing();
|
self.queue_notify_about_playing();
|
||||||
|
@ -389,7 +393,11 @@ impl HTMLMediaElement {
|
||||||
// new ready state is HAVE_ENOUGH_DATA
|
// new ready state is HAVE_ENOUGH_DATA
|
||||||
(_, HAVE_ENOUGH_DATA) => {
|
(_, HAVE_ENOUGH_DATA) => {
|
||||||
if old_ready_state <= HAVE_CURRENT_DATA {
|
if old_ready_state <= HAVE_CURRENT_DATA {
|
||||||
self.queue_fire_simple_event("canplay");
|
task_source.queue_simple_event(
|
||||||
|
self.upcast(),
|
||||||
|
atom!("canplay"),
|
||||||
|
&window,
|
||||||
|
);
|
||||||
|
|
||||||
if !self.Paused() {
|
if !self.Paused() {
|
||||||
self.queue_notify_about_playing();
|
self.queue_notify_about_playing();
|
||||||
|
@ -404,14 +412,22 @@ impl HTMLMediaElement {
|
||||||
self.paused.set(false);
|
self.paused.set(false);
|
||||||
// TODO step 2: show poster
|
// TODO step 2: show poster
|
||||||
// Step 3
|
// Step 3
|
||||||
self.queue_fire_simple_event("play");
|
task_source.queue_simple_event(
|
||||||
|
self.upcast(),
|
||||||
|
atom!("play"),
|
||||||
|
&window,
|
||||||
|
);
|
||||||
// Step 4
|
// Step 4
|
||||||
self.queue_notify_about_playing();
|
self.queue_notify_about_playing();
|
||||||
// Step 5
|
// Step 5
|
||||||
self.autoplaying.set(false);
|
self.autoplaying.set(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.queue_fire_simple_event("canplaythrough");
|
task_source.queue_simple_event(
|
||||||
|
self.upcast(),
|
||||||
|
atom!("canplaythrough"),
|
||||||
|
&window,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -460,7 +476,12 @@ impl HTMLMediaElement {
|
||||||
self.network_state.set(NETWORK_LOADING);
|
self.network_state.set(NETWORK_LOADING);
|
||||||
|
|
||||||
// Step 8
|
// Step 8
|
||||||
self.queue_fire_simple_event("loadstart");
|
let window = window_from_node(self);
|
||||||
|
window.dom_manipulation_task_source().queue_simple_event(
|
||||||
|
self.upcast(),
|
||||||
|
atom!("loadstart"),
|
||||||
|
&window,
|
||||||
|
);
|
||||||
|
|
||||||
// Step 9
|
// Step 9
|
||||||
match mode {
|
match mode {
|
||||||
|
@ -511,7 +532,12 @@ impl HTMLMediaElement {
|
||||||
self.network_state.set(NETWORK_IDLE);
|
self.network_state.set(NETWORK_IDLE);
|
||||||
|
|
||||||
// 4.1.2
|
// 4.1.2
|
||||||
self.queue_fire_simple_event("suspend");
|
let window = window_from_node(self);
|
||||||
|
window.dom_manipulation_task_source().queue_simple_event(
|
||||||
|
self.upcast(),
|
||||||
|
atom!("suspend"),
|
||||||
|
&window,
|
||||||
|
);
|
||||||
|
|
||||||
// TODO 4.1.3 (delay load flag)
|
// TODO 4.1.3 (delay load flag)
|
||||||
|
|
||||||
|
@ -584,7 +610,7 @@ impl HTMLMediaElement {
|
||||||
// TODO step 4 (show poster)
|
// TODO step 4 (show poster)
|
||||||
|
|
||||||
// Step 5
|
// Step 5
|
||||||
self.fire_simple_event("error");
|
self.upcast::<EventTarget>().fire_event(atom!("error"));
|
||||||
|
|
||||||
// TODO step 6 (resolve pending play promises)
|
// TODO step 6 (resolve pending play promises)
|
||||||
// TODO step 7 (delay load event)
|
// TODO step 7 (delay load event)
|
||||||
|
@ -600,16 +626,23 @@ impl HTMLMediaElement {
|
||||||
self.generation_id.set(self.generation_id.get() + 1);
|
self.generation_id.set(self.generation_id.get() + 1);
|
||||||
// TODO reject pending play promises
|
// TODO reject pending play promises
|
||||||
|
|
||||||
|
let window = window_from_node(self);
|
||||||
|
let task_source = window.dom_manipulation_task_source();
|
||||||
|
|
||||||
// Step 3
|
// Step 3
|
||||||
let network_state = self.NetworkState();
|
let network_state = self.NetworkState();
|
||||||
if network_state == NETWORK_LOADING || network_state == NETWORK_IDLE {
|
if network_state == NETWORK_LOADING || network_state == NETWORK_IDLE {
|
||||||
self.queue_fire_simple_event("abort");
|
task_source.queue_simple_event(
|
||||||
|
self.upcast(),
|
||||||
|
atom!("abort"),
|
||||||
|
&window,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 4
|
// Step 4
|
||||||
if network_state != NETWORK_EMPTY {
|
if network_state != NETWORK_EMPTY {
|
||||||
// 4.1
|
// 4.1
|
||||||
self.queue_fire_simple_event("emptied");
|
task_source.queue_simple_event(self.upcast(), atom!("emptied"), &window);
|
||||||
|
|
||||||
// TODO 4.2 (abort in-progress fetch)
|
// TODO 4.2 (abort in-progress fetch)
|
||||||
|
|
||||||
|
@ -721,14 +754,21 @@ impl HTMLMediaElementMethods for HTMLMediaElement {
|
||||||
|
|
||||||
// TODO 7.2 (show poster)
|
// TODO 7.2 (show poster)
|
||||||
|
|
||||||
|
let window = window_from_node(self);
|
||||||
|
let task_source = window.dom_manipulation_task_source();
|
||||||
|
|
||||||
// 7.3
|
// 7.3
|
||||||
self.queue_fire_simple_event("play");
|
task_source.queue_simple_event(self.upcast(), atom!("play"), &window);
|
||||||
|
|
||||||
// 7.4
|
// 7.4
|
||||||
if state == HAVE_NOTHING ||
|
if state == HAVE_NOTHING ||
|
||||||
state == HAVE_METADATA ||
|
state == HAVE_METADATA ||
|
||||||
state == HAVE_CURRENT_DATA {
|
state == HAVE_CURRENT_DATA {
|
||||||
self.queue_fire_simple_event("waiting");
|
task_source.queue_simple_event(
|
||||||
|
self.upcast(),
|
||||||
|
atom!("waiting"),
|
||||||
|
&window,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
self.queue_notify_about_playing();
|
self.queue_notify_about_playing();
|
||||||
}
|
}
|
||||||
|
@ -820,27 +860,6 @@ impl MicrotaskRunnable for MediaElementMicrotask {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FireSimpleEventTask {
|
|
||||||
elem: Trusted<HTMLMediaElement>,
|
|
||||||
type_: &'static str,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FireSimpleEventTask {
|
|
||||||
fn new(target: &HTMLMediaElement, type_: &'static str) -> FireSimpleEventTask {
|
|
||||||
FireSimpleEventTask {
|
|
||||||
elem: Trusted::new(target),
|
|
||||||
type_: type_,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Runnable for FireSimpleEventTask {
|
|
||||||
fn handler(self: Box<FireSimpleEventTask>) {
|
|
||||||
let elem = self.elem.root();
|
|
||||||
elem.fire_simple_event(self.type_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DedicatedMediaSourceFailureTask {
|
struct DedicatedMediaSourceFailureTask {
|
||||||
elem: Trusted<HTMLMediaElement>,
|
elem: Trusted<HTMLMediaElement>,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue