aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
Diffstat (limited to 'components/script')
-rw-r--r--components/script/dom/promise.rs14
-rw-r--r--components/script/microtask.rs4
-rw-r--r--components/script/script_runtime.rs12
-rw-r--r--components/script/timers.rs7
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);