diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2020-03-26 09:15:00 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-26 09:15:00 -0400 |
commit | 0ed0c0d9f01ac5ae906d5b7842aa79c70b119adc (patch) | |
tree | 19f87d6806b246482db97c78c7d6b57ed6d367a3 /components | |
parent | 1c7fba31ed2b4c4ad054cd8e91f2d3ddb6c839c6 (diff) | |
parent | 5621c887fd5b387c7cab80c182fe579889822212 (diff) | |
download | servo-0ed0c0d9f01ac5ae906d5b7842aa79c70b119adc.tar.gz servo-0ed0c0d9f01ac5ae906d5b7842aa79c70b119adc.zip |
Auto merge of #26029 - paulrouget:uitask, r=jdm
Set user interactions for tasks
fix #26026
I need help here. Retrieving the interaction flag from the promise handle crashes.
```rust
let interaction = GetPromiseUserInputEventHandlingState(promise);
```
```
Stack trace for thread "ScriptThread PipelineId { namespace_id: PipelineNamespaceId(1), index: PipelineIndex(1) }"
stack backtrace:
0: backtrace::backtrace::libunwind::trace
at /Users/paul/.cargo/git/checkouts/backtrace-rs-96ebaf1bcb788384/91a0aa4/src/backtrace/libunwind.rs:86
backtrace::backtrace::trace_unsynchronized
at /Users/paul/.cargo/git/checkouts/backtrace-rs-96ebaf1bcb788384/91a0aa4/src/backtrace/mod.rs:66
1: <servo::backtrace::Print as core::fmt::Debug>::fmt
at ports/glutin/backtrace.rs:49
2: <&mut W as core::fmt::Write>::write_fmt
3: std::io::Write::write_fmt
at /rustc/45ebd5808afd3df7ba842797c0fcd4447ddf30fb/src/libstd/io/mod.rs:1427
4: servo::backtrace::print
at ports/glutin/backtrace.rs:17
5: servo::install_crash_handler::handler
at ports/glutin/main2.rs:68
6: <unknown>
7: _ZN2JS37GetPromiseUserInputEventHandlingStateENS_6HandleIP8JSObjectEE
at /Users/paul/.cargo/git/checkouts/mozjs-fa11ffc7d4f1cc2d/2392ebc/mozjs/js/src/vm/JSObject.h:106
```
Diffstat (limited to 'components')
-rw-r--r-- | components/script/dom/promise.rs | 14 | ||||
-rw-r--r-- | components/script/microtask.rs | 4 | ||||
-rw-r--r-- | components/script/script_runtime.rs | 12 | ||||
-rw-r--r-- | components/script/timers.rs | 7 |
4 files changed, 32 insertions, 5 deletions
diff --git a/components/script/dom/promise.rs b/components/script/dom/promise.rs index 5e60507f8fc..fae6421f622 100644 --- a/components/script/dom/promise.rs +++ b/components/script/dom/promise.rs @@ -19,19 +19,21 @@ use crate::dom::globalscope::GlobalScope; use crate::dom::promisenativehandler::PromiseNativeHandler; use crate::realms::{enter_realm, InRealm}; use crate::script_runtime::JSContext as SafeJSContext; +use crate::script_thread::ScriptThread; use dom_struct::dom_struct; use js::conversions::ToJSValConvertible; use js::jsapi::{AddRawValueRoot, CallArgs, GetFunctionNativeReserved}; use js::jsapi::{Heap, JS_ClearPendingException}; use js::jsapi::{JSAutoRealm, JSContext, JSObject, JS_GetFunctionObject}; -use js::jsapi::{JS_NewFunction, NewFunctionWithReserved, PromiseState}; +use js::jsapi::{JS_NewFunction, NewFunctionWithReserved}; +use js::jsapi::{PromiseState, PromiseUserInputEventHandlingState}; use js::jsapi::{RemoveRawValueRoot, SetFunctionNativeReserved}; use js::jsval::{Int32Value, JSVal, ObjectValue, UndefinedValue}; use js::rust::wrappers::{ AddPromiseReactions, CallOriginalPromiseReject, CallOriginalPromiseResolve, }; -use js::rust::wrappers::{GetPromiseState, IsPromiseObject}; -use js::rust::wrappers::{NewPromiseObject, RejectPromise, ResolvePromise}; +use js::rust::wrappers::{GetPromiseState, IsPromiseObject, NewPromiseObject, RejectPromise}; +use js::rust::wrappers::{ResolvePromise, SetPromiseUserInputEventHandlingState}; use js::rust::{HandleObject, HandleValue, MutableHandleObject, Runtime}; use std::ptr; use std::rc::Rc; @@ -131,6 +133,12 @@ impl Promise { assert!(!do_nothing_obj.is_null()); obj.set(NewPromiseObject(*cx, do_nothing_obj.handle())); assert!(!obj.is_null()); + let is_user_interacting = if ScriptThread::is_user_interacting() { + PromiseUserInputEventHandlingState::HadUserInteractionAtCreation + } else { + PromiseUserInputEventHandlingState::DidntHaveUserInteractionAtCreation + }; + SetPromiseUserInputEventHandlingState(obj.handle(), is_user_interacting); } } diff --git a/components/script/microtask.rs b/components/script/microtask.rs index 6241b6f63a0..ae4d3c6944e 100644 --- a/components/script/microtask.rs +++ b/components/script/microtask.rs @@ -52,6 +52,7 @@ pub struct EnqueuedPromiseCallback { #[ignore_malloc_size_of = "Rc has unclear ownership"] pub callback: Rc<PromiseJobCallback>, pub pipeline: PipelineId, + pub is_user_interacting: bool, } /// A microtask that comes from a queueMicrotask() Javascript call, @@ -105,7 +106,10 @@ impl MicrotaskQueue { match *job { Microtask::Promise(ref job) => { if let Some(target) = target_provider(job.pipeline) { + let was_interacting = ScriptThread::is_user_interacting(); + ScriptThread::set_user_interacting(job.is_user_interacting); let _ = job.callback.Call_(&*target, ExceptionHandling::Report); + ScriptThread::set_user_interacting(was_interacting); } }, Microtask::User(ref job) => { diff --git a/components/script/script_runtime.rs b/components/script/script_runtime.rs index 3cce6291d63..abe411521af 100644 --- a/components/script/script_runtime.rs +++ b/components/script/script_runtime.rs @@ -42,9 +42,11 @@ use js::glue::{ StreamConsumerNoteResponseURLs, StreamConsumerStreamEnd, StreamConsumerStreamError, }; use js::jsapi::ContextOptionsRef; +use js::jsapi::GetPromiseUserInputEventHandlingState; use js::jsapi::InitConsumeStreamCallback; use js::jsapi::InitDispatchToEventLoop; use js::jsapi::MimeType; +use js::jsapi::PromiseUserInputEventHandlingState; use js::jsapi::StreamConsumer as JSStreamConsumer; use js::jsapi::{BuildIdCharVector, DisableIncrementalGC, GCDescription, GCProgress}; use js::jsapi::{Dispatchable as JSRunnable, Dispatchable_MaybeShuttingDown}; @@ -197,7 +199,7 @@ unsafe extern "C" fn empty(extra: *const c_void) -> bool { unsafe extern "C" fn enqueue_promise_job( extra: *const c_void, cx: *mut RawJSContext, - _promise: HandleObject, + promise: HandleObject, job: HandleObject, _allocation_site: HandleObject, incumbent_global: HandleObject, @@ -208,10 +210,18 @@ unsafe extern "C" fn enqueue_promise_job( let microtask_queue = &*(extra as *const MicrotaskQueue); let global = GlobalScope::from_object(incumbent_global.get()); let pipeline = global.pipeline_id(); + let interaction = if promise.get().is_null() { + PromiseUserInputEventHandlingState::DontCare + } else { + GetPromiseUserInputEventHandlingState(promise) + }; + let is_user_interacting = + interaction == PromiseUserInputEventHandlingState::HadUserInteractionAtCreation; microtask_queue.enqueue( Microtask::Promise(EnqueuedPromiseCallback { callback: PromiseJobCallback::new(cx, job.get()), pipeline, + is_user_interacting, }), cx, ); diff --git a/components/script/timers.rs b/components/script/timers.rs index 4be6f822263..5d8893c3055 100644 --- a/components/script/timers.rs +++ b/components/script/timers.rs @@ -12,6 +12,7 @@ use crate::dom::eventsource::EventSourceTimeoutCallback; use crate::dom::globalscope::GlobalScope; use crate::dom::testbinding::TestBindingCallback; use crate::dom::xmlhttprequest::XHRTimeoutCallback; +use crate::script_thread::ScriptThread; use euclid::Length; use ipc_channel::ipc::IpcSender; use js::jsapi::Heap; @@ -367,6 +368,7 @@ pub struct JsTimerTask { is_interval: IsInterval, nesting_level: u32, duration: MsDuration, + is_user_interacting: bool, } // Enum allowing more descriptive values for the is_interval field @@ -444,6 +446,7 @@ impl JsTimers { source: source, callback: callback, is_interval: is_interval, + is_user_interacting: ScriptThread::is_user_interacting(), nesting_level: 0, duration: Length::new(0), }; @@ -524,12 +527,13 @@ impl JsTimerTask { timers.nesting_level.set(self.nesting_level); // step 4.2 + let was_user_interacting = ScriptThread::is_user_interacting(); + ScriptThread::set_user_interacting(self.is_user_interacting); match self.callback { InternalTimerCallback::StringTimerCallback(ref code_str) => { let global = this.global(); let cx = global.get_cx(); rooted!(in(*cx) let mut rval = UndefinedValue()); - global.evaluate_js_on_global_with_result(code_str, rval.handle_mut()); }, InternalTimerCallback::FunctionTimerCallback(ref function, ref arguments) => { @@ -537,6 +541,7 @@ impl JsTimerTask { let _ = function.Call_(this, arguments, Report); }, }; + ScriptThread::set_user_interacting(was_user_interacting); // reset nesting level (see above) timers.nesting_level.set(0); |