diff options
-rw-r--r-- | Cargo.lock | 14 | ||||
-rw-r--r-- | components/atoms/static_atoms.txt | 1 | ||||
-rw-r--r-- | components/malloc_size_of/Cargo.toml | 2 | ||||
-rw-r--r-- | components/script/Cargo.toml | 2 | ||||
-rw-r--r-- | components/script/dom/globalscope.rs | 58 | ||||
-rw-r--r-- | components/script/dom/mod.rs | 1 | ||||
-rw-r--r-- | components/script/dom/promise.rs | 2 | ||||
-rw-r--r-- | components/script/dom/promiserejectionevent.rs | 114 | ||||
-rw-r--r-- | components/script/dom/webidls/PromiseRejectionEvent.webidl | 16 | ||||
-rw-r--r-- | components/script/microtask.rs | 14 | ||||
-rw-r--r-- | components/script/script_runtime.rs | 128 | ||||
-rw-r--r-- | components/script/script_thread.rs | 10 |
12 files changed, 342 insertions, 20 deletions
diff --git a/Cargo.lock b/Cargo.lock index 8508834d885..cd5bca3d7e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2026,7 +2026,7 @@ dependencies = [ "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", "hyper_serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "keyboard-types 0.4.2-servo (registry+https://github.com/rust-lang/crates.io-index)", - "mozjs 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "mozjs 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", "selectors 0.20.0", "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2227,20 +2227,20 @@ dependencies = [ [[package]] name = "mozjs" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "mozjs_sys 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", + "mozjs_sys 0.61.1 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mozjs_sys" -version = "0.61.0" +version = "0.61.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bindgen 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3004,7 +3004,7 @@ dependencies = [ "mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "mitochondria 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "mozangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "mozjs 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "mozjs 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", "net_traits 0.0.1", "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4505,8 +4505,8 @@ dependencies = [ "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum mitochondria 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9de3eca27871df31c33b807f834b94ef7d000956f57aa25c5aed9c5f0aae8f6f" "checksum mozangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "45a8a18a41cfab0fde25cc2f43ea89064d211a0fbb33225b8ff93ab20406e0e7" -"checksum mozjs 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b9f85c1120b07d7a2acc9d1d62df1fe16f64162399448fb5307bf2bc3bd066c9" -"checksum mozjs_sys 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ff07b0f0a2371dc08d75d55371ca311be67e1fdfa6c146fc8ad154c340f70c9" +"checksum mozjs 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bd0bdded611cb03c8ca638e0b663befe67eb7fbcb1fe2dfd25061656ee4ff365" +"checksum mozjs_sys 0.61.1 (registry+https://github.com/rust-lang/crates.io-index)" = "070dd9dcd0be8b524fe4f6fcc791d56d630518652f98c2b152fdebe28eb71a5b" "checksum msdos_time 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aad9dfe950c057b1bfe9c1f2aa51583a8468ef2a5baba2ebbe06d775efeb7729" "checksum muldiv 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "451a9a05d2a32c566c897835e0ea95cf79ed2fdfe957924045a1721a36c9980f" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" diff --git a/components/atoms/static_atoms.txt b/components/atoms/static_atoms.txt index 4281c7004d0..f123a2b66c5 100644 --- a/components/atoms/static_atoms.txt +++ b/components/atoms/static_atoms.txt @@ -86,6 +86,7 @@ time timeupdate toggle transitionend +unhandledrejection unload url waiting diff --git a/components/malloc_size_of/Cargo.toml b/components/malloc_size_of/Cargo.toml index e982925e57a..04df21fd628 100644 --- a/components/malloc_size_of/Cargo.toml +++ b/components/malloc_size_of/Cargo.toml @@ -32,7 +32,7 @@ hashglobe = { path = "../hashglobe" } hyper = { version = "0.10", optional = true } hyper_serde = { version = "0.8", optional = true } keyboard-types = {version = "0.4.2-servo", features = ["serde"], optional = true} -mozjs = { version = "0.9.0", optional = true } +mozjs = { version = "0.9.3", optional = true } selectors = { path = "../selectors" } serde = { version = "1.0.27", optional = true } serde_bytes = { version = "0.10", optional = true } diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index ece8095f021..12cb7c6c667 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -68,7 +68,7 @@ metrics = {path = "../metrics"} mitochondria = "1.1.2" mime = "0.2.1" mime_guess = "1.8.0" -mozjs = "0.9.0" +mozjs = "0.9.3" msg = {path = "../msg"} net_traits = {path = "../net_traits"} num-traits = "0.2" diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index 62eae2dedae..c38a5869d61 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -30,6 +30,7 @@ use ipc_channel::ipc::IpcSender; use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL}; use js::glue::{IsWrapper, UnwrapObject}; use js::jsapi::{CurrentGlobalOrNull, GetGlobalForObjectCrossCompartment}; +use js::jsapi::{Heap, HandleObject}; use js::jsapi::{JSAutoCompartment, JSContext}; use js::jsapi::JSObject; use js::panic::maybe_resume_unwind; @@ -135,6 +136,23 @@ pub struct GlobalScope { /// Vector storing references of all eventsources. event_source_tracker: DOMTracker<EventSource>, + + /// Storage for watching rejected promises waiting for some client to + /// consume their rejection. + /// Promises in this list have been rejected in the last turn of the + /// event loop without the rejection being handled. + /// Note that this can contain nullptrs in place of promises removed because + /// they're consumed before it'd be reported. + /// + /// <https://html.spec.whatwg.org/multipage/#about-to-be-notified-rejected-promises-list> + uncaught_rejections: DomRefCell<Vec<Box<Heap<*mut JSObject>>>>, + + /// Promises in this list have previously been reported as rejected + /// (because they were in the above list), but the rejection was handled + /// in the last turn of the event loop. + /// + /// <https://html.spec.whatwg.org/multipage/#outstanding-rejected-promises-weak-set> + consumed_rejections: DomRefCell<Vec<Box<Heap<*mut JSObject>>>>, } impl GlobalScope { @@ -169,6 +187,8 @@ impl GlobalScope { microtask_queue, list_auto_close_worker: Default::default(), event_source_tracker: DOMTracker::new(), + uncaught_rejections: Default::default(), + consumed_rejections: Default::default(), } } @@ -230,6 +250,39 @@ impl GlobalScope { GlobalScope::from_object(obj) } + pub fn add_uncaught_rejection(&self, rejection: HandleObject) { + self.uncaught_rejections.borrow_mut().push(Heap::boxed(rejection.get())); + } + + pub fn remove_uncaught_rejection(&self, rejection: HandleObject) { + let mut uncaught_rejections = self.uncaught_rejections.borrow_mut(); + + if let Some(index) = uncaught_rejections.iter().position(|promise| *promise == Heap::boxed(rejection.get())) { + uncaught_rejections.remove(index); + } + } + + pub fn get_uncaught_rejections(&self) -> &DomRefCell<Vec<Box<Heap<*mut JSObject>>>> { + &self.uncaught_rejections + } + + pub fn add_consumed_rejection(&self, rejection: HandleObject) { + self.consumed_rejections.borrow_mut().push(Heap::boxed(rejection.get())); + } + + pub fn remove_consumed_rejection(&self, rejection: HandleObject) { + let mut consumed_rejections = self.consumed_rejections.borrow_mut(); + + if let Some(index) = consumed_rejections.iter().position(|promise| *promise == Heap::boxed(rejection.get())) { + consumed_rejections.remove(index); + } + } + + pub fn get_consumed_rejections(&self) -> &DomRefCell<Vec<Box<Heap<*mut JSObject>>>> { + &self.consumed_rejections + } + + #[allow(unsafe_code)] pub fn get_cx(&self) -> *mut JSContext { Runtime::get() } @@ -586,7 +639,10 @@ impl GlobalScope { /// Perform a microtask checkpoint. pub fn perform_a_microtask_checkpoint(&self) { self.microtask_queue - .checkpoint(|_| Some(DomRoot::from_ref(self))); + .checkpoint( + |_| Some(DomRoot::from_ref(self)), + vec![DomRoot::from_ref(self)] + ); } /// Enqueue a microtask for subsequent execution. diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 3587a11a0ad..88b50d54f2f 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -428,6 +428,7 @@ pub mod processinginstruction; pub mod progressevent; pub mod promise; pub mod promisenativehandler; +pub mod promiserejectionevent; pub mod radionodelist; pub mod range; pub mod request; diff --git a/components/script/dom/promise.rs b/components/script/dom/promise.rs index 8112794f1c9..e7e40fb188b 100644 --- a/components/script/dom/promise.rs +++ b/components/script/dom/promise.rs @@ -93,7 +93,7 @@ impl Promise { } #[allow(unsafe_code, unrooted_must_root)] - unsafe fn new_with_js_promise(obj: HandleObject, cx: *mut JSContext) -> Rc<Promise> { + pub unsafe fn new_with_js_promise(obj: HandleObject, cx: *mut JSContext) -> Rc<Promise> { assert!(IsPromiseObject(obj)); let promise = Promise { reflector: Reflector::new(), diff --git a/components/script/dom/promiserejectionevent.rs b/components/script/dom/promiserejectionevent.rs new file mode 100644 index 00000000000..500e59643cd --- /dev/null +++ b/components/script/dom/promiserejectionevent.rs @@ -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 http://mozilla.org/MPL/2.0/. */ + +use dom::bindings::codegen::Bindings::EventBinding::EventMethods; +use dom::bindings::codegen::Bindings::PromiseRejectionEventBinding; +use dom::bindings::codegen::Bindings::PromiseRejectionEventBinding::PromiseRejectionEventMethods; +use dom::bindings::error::Fallible; +use dom::bindings::inheritance::Castable; +use dom::bindings::reflector::reflect_dom_object; +use dom::bindings::root::DomRoot; +use dom::bindings::str::DOMString; +use dom::bindings::trace::RootedTraceableBox; +use dom::event::{Event, EventBubbles, EventCancelable}; +use dom::globalscope::GlobalScope; +use dom::promise::Promise; +use dom_struct::dom_struct; +use js::jsapi::{Heap, JSContext}; +use js::jsval::JSVal; +use js::rust::HandleValue; +use servo_atoms::Atom; +use std::rc::Rc; + +#[dom_struct] +pub struct PromiseRejectionEvent { + event: Event, + #[ignore_malloc_size_of = "Rc"] + promise: Rc<Promise>, + #[ignore_malloc_size_of = "Defined in rust-mozjs"] + reason: Heap<JSVal>, +} + +impl PromiseRejectionEvent { + #[allow(unrooted_must_root)] + fn new_inherited(promise: Rc<Promise>) -> Self { + PromiseRejectionEvent { + event: Event::new_inherited(), + promise, + reason: Heap::default() + } + } + + #[allow(unrooted_must_root)] + pub fn new( + global: &GlobalScope, + type_: Atom, + bubbles: EventBubbles, + cancelable: EventCancelable, + promise: Rc<Promise>, + reason: HandleValue + ) -> DomRoot<Self> { + let ev = reflect_dom_object( + Box::new(PromiseRejectionEvent::new_inherited(promise)), + global, + PromiseRejectionEventBinding::Wrap + ); + + { + let event = ev.upcast::<Event>(); + event.init_event( + type_, + bool::from(bubbles), + bool::from(cancelable) + ); + + ev.reason.set(reason.get()); + } + ev + } + + #[allow(unrooted_must_root)] + pub fn Constructor( + global: &GlobalScope, + type_: DOMString, + init: RootedTraceableBox<PromiseRejectionEventBinding::PromiseRejectionEventInit> + ) -> Fallible<DomRoot<Self>> { + let reason = init.reason.handle(); + let promise = match init.promise.as_ref() { + Some(promise) => promise.clone(), + None => Promise::new(global) + }; + let bubbles = EventBubbles::from(init.parent.bubbles); + let cancelable = EventCancelable::from(init.parent.cancelable); + + let event = PromiseRejectionEvent::new( + global, + Atom::from(type_), + bubbles, + cancelable, + promise, + reason + ); + Ok(event) + } +} + +impl PromiseRejectionEventMethods for PromiseRejectionEvent { + #[allow(unrooted_must_root)] + // https://html.spec.whatwg.org/multipage/#dom-promiserejectionevent-promise + fn Promise(&self) -> Rc<Promise> { + self.promise.clone() + } + + #[allow(unsafe_code)] + // https://html.spec.whatwg.org/multipage/#dom-promiserejectionevent-reason + unsafe fn Reason(&self, _cx: *mut JSContext) -> JSVal { + self.reason.get() + } + + // https://dom.spec.whatwg.org/#dom-event-istrusted + fn IsTrusted(&self) -> bool { + self.event.IsTrusted() + } +} diff --git a/components/script/dom/webidls/PromiseRejectionEvent.webidl b/components/script/dom/webidls/PromiseRejectionEvent.webidl new file mode 100644 index 00000000000..5e94062f2ff --- /dev/null +++ b/components/script/dom/webidls/PromiseRejectionEvent.webidl @@ -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 http://mozilla.org/MPL/2.0/. */ + +// https://html.spec.whatwg.org/multipage/#the-promiserejectionevent-interface + +[Constructor(DOMString type, optional PromiseRejectionEventInit eventInitDict), Exposed=(Window,Worker)] +interface PromiseRejectionEvent : Event { + readonly attribute Promise<any> promise; + readonly attribute any reason; +}; + +dictionary PromiseRejectionEventInit : EventInit { + /* required */ Promise<any> promise; + any reason; +}; diff --git a/components/script/microtask.rs b/components/script/microtask.rs index a4221dd92dc..1a707d8fc3f 100644 --- a/components/script/microtask.rs +++ b/components/script/microtask.rs @@ -15,6 +15,7 @@ use dom::htmlimageelement::ImageElementMicrotask; use dom::htmlmediaelement::MediaElementMicrotask; use dom::mutationobserver::MutationObserver; use msg::constellation_msg::PipelineId; +use script_runtime::notify_about_rejected_promises; use script_thread::ScriptThread; use std::cell::Cell; use std::mem; @@ -59,7 +60,7 @@ impl MicrotaskQueue { /// <https://html.spec.whatwg.org/multipage/#perform-a-microtask-checkpoint> /// Perform a microtask checkpoint, executing all queued microtasks until the queue is empty. - pub fn checkpoint<F>(&self, target_provider: F) + pub fn checkpoint<F>(&self, target_provider: F, globalscopes: Vec<DomRoot<GlobalScope>>) where F: Fn(PipelineId) -> Option<DomRoot<GlobalScope>>, { @@ -70,7 +71,7 @@ impl MicrotaskQueue { // Step 1 self.performing_a_microtask_checkpoint.set(true); - // Steps 2-7 + // Steps 2 while !self.microtask_queue.borrow().is_empty() { rooted_vec!(let mut pending_queue); mem::swap(&mut *pending_queue, &mut *self.microtask_queue.borrow_mut()); @@ -98,9 +99,14 @@ impl MicrotaskQueue { } } - //TODO: Step 8 - notify about rejected promises + // Step 3 + for global in globalscopes.into_iter() { + notify_about_rejected_promises(&global); + } + + // TODO: Step 4 - Cleanup Indexed Database transactions. - // Step 9 + // Step 5 self.performing_a_microtask_checkpoint.set(false); } } diff --git a/components/script/script_runtime.rs b/components/script/script_runtime.rs index 18138dcc2b0..276a913647a 100644 --- a/components/script/script_runtime.rs +++ b/components/script/script_runtime.rs @@ -8,24 +8,34 @@ use dom::bindings::codegen::Bindings::PromiseBinding::PromiseJobCallback; use dom::bindings::conversions::get_dom_class; use dom::bindings::conversions::private_from_object; +use dom::bindings::inheritance::Castable; use dom::bindings::refcounted::{LiveDOMReferences, trace_refcounted_objects}; +use dom::bindings::refcounted::{Trusted, TrustedPromise}; +use dom::bindings::reflector::DomObject; use dom::bindings::root::trace_roots; use dom::bindings::settings_stack; use dom::bindings::trace::{JSTraceable, trace_traceables}; use dom::bindings::utils::DOM_CALLBACKS; +use dom::event::{Event, EventBubbles, EventCancelable, EventStatus}; +use dom::eventtarget::EventTarget; use dom::globalscope::GlobalScope; +use dom::promise::Promise; +use dom::promiserejectionevent::PromiseRejectionEvent; use js::glue::CollectServoSizes; use js::glue::SetBuildId; -use js::jsapi::{DisableIncrementalGC, GCDescription, GCProgress, HandleObject}; +use js::jsapi::{BuildIdCharVector, DisableIncrementalGC, GCDescription, GCProgress}; +use js::jsapi::{Heap, HandleObject}; use js::jsapi::{JSContext, JSTracer, SetDOMCallbacks, SetGCSliceCallback}; use js::jsapi::{JSGCInvocationKind, JSGCStatus, JS_AddExtraGCRootsTracer, JS_SetGCCallback}; use js::jsapi::{JSGCMode, JSGCParamKey, JS_SetGCParameter, JS_SetGlobalJitCompilerOption}; use js::jsapi::{JSJitCompilerOption, JS_SetOffthreadIonCompilationEnabled, JS_SetParallelParsingEnabled}; -use js::jsapi::{JSObject, SetPreserveWrapperCallback, SetEnqueuePromiseJobCallback}; -use js::jsapi::{SetBuildIdOp, BuildIdCharVector}; +use js::jsapi::{JSObject, PromiseRejectionHandlingState, SetPreserveWrapperCallback}; +use js::jsapi::{SetBuildIdOp, SetEnqueuePromiseJobCallback, SetPromiseRejectionTrackerCallback}; use js::jsapi::ContextOptionsRef; use js::panic::wrap_panic; +use js::rust::Handle; use js::rust::Runtime as RustRuntime; +use js::rust::wrappers::{GetPromiseIsHandled, GetPromiseResult}; use malloc_size_of::MallocSizeOfOps; use microtask::{EnqueuedPromiseCallback, Microtask}; use msg::constellation_msg::PipelineId; @@ -43,7 +53,7 @@ use std::panic::AssertUnwindSafe; use std::ptr; use style::thread_state::{self, ThreadState}; use task::TaskBox; -use task_source::TaskSourceName; +use task_source::{TaskSource, TaskSourceName}; use time::{Tm, now}; /// Common messages used to control the event loops in both the script and the worker @@ -140,6 +150,115 @@ unsafe extern "C" fn enqueue_job( ) } +#[allow(unsafe_code)] +/// https://html.spec.whatwg.org/multipage/#the-hostpromiserejectiontracker-implementation +unsafe extern "C" fn promise_rejection_tracker( + cx: *mut JSContext, + promise: HandleObject, + state: PromiseRejectionHandlingState, + _data: *mut c_void +) { + // TODO: Step 2 - If script's muted errors is true, terminate these steps. + + // Step 3. + let global = GlobalScope::from_context(cx); + + wrap_panic(AssertUnwindSafe(|| { + match state { + // Step 4. + PromiseRejectionHandlingState::Unhandled => { + global.add_uncaught_rejection(promise); + }, + // Step 5. + PromiseRejectionHandlingState::Handled => { + // Step 5-1. + if global.get_uncaught_rejections().borrow().contains(&Heap::boxed(promise.get())) { + global.remove_uncaught_rejection(promise); + return; + } + + // Step 5-2. + if !global.get_consumed_rejections().borrow().contains(&Heap::boxed(promise.get())) { + global.add_consumed_rejection(promise); + return; + } + + // Step 5-3. + global.remove_consumed_rejection(promise); + + // TODO: Step 5-4 - Queue a task to fire `rejectionhandled` event + } + }; + }), ()); +} + +#[allow(unsafe_code, unrooted_must_root)] +/// https://html.spec.whatwg.org/multipage/#notify-about-rejected-promises +pub fn notify_about_rejected_promises(global: &GlobalScope) { + unsafe { + let cx = global.get_cx(); + + // Step 2. + if global.get_uncaught_rejections().borrow().len() > 0 { + // Step 1. + let uncaught_rejections: Vec<TrustedPromise> = global.get_uncaught_rejections() + .borrow() + .iter() + .map(|promise| { + let promise = Promise::new_with_js_promise(Handle::from_raw(promise.handle()), cx); + + TrustedPromise::new(promise) + }) + .collect(); + + // Step 3. + global.get_uncaught_rejections().borrow_mut().clear(); + + let target = Trusted::new(global.upcast::<EventTarget>()); + + // Step 4. + global.as_window().dom_manipulation_task_source().queue( + task!(unhandled_rejection_event: move || { + let target = target.root(); + let cx = target.global().get_cx(); + + for promise in uncaught_rejections { + let promise = promise.root(); + + // Step 4-1. + let promise_is_handled = GetPromiseIsHandled(promise.reflector().get_jsobject()); + if promise_is_handled { + continue; + } + + // Step 4-2. + rooted!(in(cx) let reason = GetPromiseResult(promise.reflector().get_jsobject())); + + let event = PromiseRejectionEvent::new( + &target.global(), + atom!("unhandledrejection"), + EventBubbles::DoesNotBubble, + EventCancelable::Cancelable, + promise, + reason.handle() + ); + + let event_status = event.upcast::<Event>().fire(&target); + + // Step 4-3. + if event_status == EventStatus::Canceled { + // TODO: The promise rejection is not handled; we need to add it back to the list. + } + + // TODO: Step 4-4 - If [[PromiseIsHandled]] is false, add promise to consumed_rejections + } + }), + global.upcast(), + ).unwrap(); + } + } +} + #[derive(JSTraceable)] pub struct Runtime(RustRuntime); @@ -182,6 +301,7 @@ pub unsafe fn new_rt_and_cx() -> Runtime { DisableIncrementalGC(cx); SetEnqueuePromiseJobCallback(cx, Some(enqueue_job), ptr::null_mut()); + SetPromiseRejectionTrackerCallback(cx, Some(promise_rejection_tracker), ptr::null_mut()); set_gc_zeal_options(cx); diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 931b0d230ef..0f756caccca 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -3200,8 +3200,16 @@ impl ScriptThread { } fn perform_a_microtask_checkpoint(&self) { + let globals = self.documents.borrow() + .iter() + .map(|(_id, document)| document.global()) + .collect(); + self.microtask_queue - .checkpoint(|id| self.documents.borrow().find_global(id)) + .checkpoint( + |id| self.documents.borrow().find_global(id), + globals + ) } } |