mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Enqueue promise jobs from SpiderMonkey callbacks, and execute them in batches. Implement native Promise APIs.
Add SpiderMonkey hooks for enqueuing promise jobs. Start porting various native Promise APIs.
This commit is contained in:
parent
a1091772ec
commit
fd778b4240
4 changed files with 154 additions and 20 deletions
|
@ -826,7 +826,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
rooted!(in(cx) let globalObj = CurrentGlobalOrNull(cx));
|
||||
let promiseGlobal = global_root_from_object_maybe_wrapped(globalObj.handle().get());
|
||||
|
||||
let mut valueToResolve = RootedValue::new(cx, $${val}.get());
|
||||
rooted!(in(cx) let mut valueToResolve = $${val}.get());
|
||||
if !JS_WrapValue(cx, valueToResolve.handle_mut()) {
|
||||
$*{exceptionCode}
|
||||
}
|
||||
|
@ -5482,6 +5482,7 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries
|
|||
'js::jsapi::JS_SetProperty',
|
||||
'js::jsapi::JS_SetReservedSlot',
|
||||
'js::jsapi::JS_SplicePrototype',
|
||||
'js::jsapi::JS_WrapValue',
|
||||
'js::jsapi::MutableHandle',
|
||||
'js::jsapi::MutableHandleObject',
|
||||
'js::jsapi::MutableHandleValue',
|
||||
|
|
|
@ -2,26 +2,33 @@
|
|||
* 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::callback::CallbackContainer;
|
||||
use dom::bindings::codegen::Bindings::PromiseBinding::AnyCallback;
|
||||
use dom::bindings::error::Fallible;
|
||||
use dom::bindings::global::GlobalRef;
|
||||
use dom::bindings::reflector::{Reflectable, Reflector};
|
||||
use js::jsapi::{JSAutoCompartment, RootedObject, CallArgs, JS_GetFunctionObject, JS_NewFunction};
|
||||
use js::jsapi::{JSContext, HandleValue, HandleObject, IsPromiseObject, CallOriginalPromiseResolve};
|
||||
use js::jsapi::{MutableHandleObject, NewPromiseObject};
|
||||
use js::jsval::{JSVal, UndefinedValue};
|
||||
use dom::bindings::reflector::{Reflectable, MutReflectable, Reflector};
|
||||
use dom::promisenativehandler::PromiseNativeHandler;
|
||||
use js::conversions::ToJSValConvertible;
|
||||
use js::jsapi::{CallOriginalPromiseResolve, CallOriginalPromiseReject, CallOriginalPromiseThen};
|
||||
use js::jsapi::{JSAutoCompartment, CallArgs, JS_GetFunctionObject, JS_NewFunction};
|
||||
use js::jsapi::{JSContext, HandleValue, HandleObject, IsPromiseObject, GetFunctionNativeReserved};
|
||||
use js::jsapi::{JS_ClearPendingException, JSObject};
|
||||
use js::jsapi::{MutableHandleObject, NewPromiseObject, ResolvePromise, RejectPromise};
|
||||
use js::jsapi::{SetFunctionNativeReserved, NewFunctionWithReserved, AddPromiseReactions};
|
||||
use js::jsval::{JSVal, UndefinedValue, ObjectValue, Int32Value};
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct Promise {
|
||||
reflector: Reflector
|
||||
reflector: Reflector,
|
||||
}
|
||||
|
||||
impl Promise {
|
||||
#[allow(unsafe_code)]
|
||||
pub fn new(global: GlobalRef) -> Rc<Promise> {
|
||||
let cx = global.get_cx();
|
||||
let mut obj = RootedObject::new(cx, ptr::null_mut());
|
||||
rooted!(in(cx) let mut obj = ptr::null_mut());
|
||||
unsafe {
|
||||
Promise::create_js_promise(cx, HandleObject::null(), obj.handle_mut());
|
||||
}
|
||||
|
@ -41,12 +48,13 @@ impl Promise {
|
|||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn create_js_promise(cx: *mut JSContext, proto: HandleObject, mut obj: MutableHandleObject) {
|
||||
let do_nothing_func = JS_NewFunction(cx, Some(do_nothing_promise_executor), 2, 0, ptr::null());
|
||||
unsafe fn create_js_promise(cx: *mut JSContext, proto: HandleObject, obj: MutableHandleObject) {
|
||||
let do_nothing_func = JS_NewFunction(cx, Some(do_nothing_promise_executor), /* nargs = */ 2,
|
||||
/* flags = */ 0, ptr::null());
|
||||
assert!(!do_nothing_func.is_null());
|
||||
let do_nothing_obj = RootedObject::new(cx, JS_GetFunctionObject(do_nothing_func));
|
||||
assert!(!do_nothing_obj.handle().is_null());
|
||||
*obj = NewPromiseObject(cx, do_nothing_obj.handle(), proto);
|
||||
rooted!(in(cx) let do_nothing_obj = JS_GetFunctionObject(do_nothing_func));
|
||||
assert!(!do_nothing_obj.is_null());
|
||||
obj.set(NewPromiseObject(cx, do_nothing_obj.handle(), proto));
|
||||
assert!(!obj.is_null());
|
||||
}
|
||||
|
||||
|
@ -55,12 +63,68 @@ impl Promise {
|
|||
cx: *mut JSContext,
|
||||
value: HandleValue) -> Fallible<Rc<Promise>> {
|
||||
let _ac = JSAutoCompartment::new(cx, global.reflector().get_jsobject().get());
|
||||
let p = unsafe {
|
||||
RootedObject::new(cx, CallOriginalPromiseResolve(cx, value))
|
||||
};
|
||||
rooted!(in(cx) let p = unsafe { CallOriginalPromiseResolve(cx, value) });
|
||||
assert!(!p.handle().is_null());
|
||||
Ok(Promise::new_with_js_promise(p.handle()))
|
||||
}
|
||||
|
||||
#[allow(unrooted_must_root, unsafe_code)]
|
||||
pub fn Reject(global: GlobalRef,
|
||||
cx: *mut JSContext,
|
||||
value: HandleValue) -> Fallible<Rc<Promise>> {
|
||||
let _ac = JSAutoCompartment::new(cx, global.reflector().get_jsobject().get());
|
||||
rooted!(in(cx) let p = unsafe { CallOriginalPromiseReject(cx, value) });
|
||||
assert!(!p.handle().is_null());
|
||||
Ok(Promise::new_with_js_promise(p.handle()))
|
||||
}
|
||||
|
||||
#[allow(unrooted_must_root, unsafe_code)]
|
||||
pub fn maybe_resolve(&self,
|
||||
cx: *mut JSContext,
|
||||
value: HandleValue) {
|
||||
unsafe {
|
||||
if !ResolvePromise(cx, self.promise_obj(), value) {
|
||||
JS_ClearPendingException(cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unrooted_must_root, unsafe_code)]
|
||||
pub fn maybe_reject(&self,
|
||||
cx: *mut JSContext,
|
||||
value: HandleValue) {
|
||||
unsafe {
|
||||
if !RejectPromise(cx, self.promise_obj(), value) {
|
||||
JS_ClearPendingException(cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unrooted_must_root, unsafe_code)]
|
||||
pub fn then(&self,
|
||||
cx: *mut JSContext,
|
||||
_callee: HandleObject,
|
||||
cb_resolve: AnyCallback,
|
||||
cb_reject: AnyCallback,
|
||||
result: MutableHandleObject) {
|
||||
let promise = self.promise_obj();
|
||||
rooted!(in(cx) let resolve = cb_resolve.callback());
|
||||
rooted!(in(cx) let reject = cb_reject.callback());
|
||||
unsafe {
|
||||
rooted!(in(cx) let res =
|
||||
CallOriginalPromiseThen(cx, promise, resolve.handle(), reject.handle()));
|
||||
result.set(*res);
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
fn promise_obj(&self) -> HandleObject {
|
||||
let obj = self.reflector().get_jsobject();
|
||||
unsafe {
|
||||
assert!(IsPromiseObject(obj));
|
||||
}
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
|
|
|
@ -5,7 +5,12 @@
|
|||
// This interface is entirely internal to Servo, and should not be accessible to
|
||||
// web pages.
|
||||
|
||||
[NoInterfaceObject]
|
||||
callback PromiseJobCallback = void();
|
||||
|
||||
[TreatNonCallableAsNull]
|
||||
callback AnyCallback = any (any value);
|
||||
|
||||
[NoInterfaceObject, Exposed=(Window,Worker)]
|
||||
// Need to escape "Promise" so it's treated as an identifier.
|
||||
interface _Promise {
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue