diff options
author | Josh Matthews <josh@joshmatthews.net> | 2016-08-12 11:44:56 -0400 |
---|---|---|
committer | Josh Matthews <josh@joshmatthews.net> | 2016-09-22 16:16:52 -0400 |
commit | ab168204ed9b6068c312a98253ab32bcaa5e2239 (patch) | |
tree | 79d1bfd85843fd0995c33c5220bfec042e69b915 /components/script/dom/promise.rs | |
parent | 7ba3172ce0d9d9d6a003b27d66450fea876bd563 (diff) | |
download | servo-ab168204ed9b6068c312a98253ab32bcaa5e2239.tar.gz servo-ab168204ed9b6068c312a98253ab32bcaa5e2239.zip |
Support native promise callbacks.
Diffstat (limited to 'components/script/dom/promise.rs')
-rw-r--r-- | components/script/dom/promise.rs | 76 |
1 files changed, 74 insertions, 2 deletions
diff --git a/components/script/dom/promise.rs b/components/script/dom/promise.rs index c99ae69792c..79490e0bc13 100644 --- a/components/script/dom/promise.rs +++ b/components/script/dom/promise.rs @@ -4,6 +4,7 @@ use dom::bindings::callback::CallbackContainer; use dom::bindings::codegen::Bindings::PromiseBinding::AnyCallback; +use dom::bindings::conversions::root_from_object; use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::reflector::{Reflectable, MutReflectable, Reflector}; @@ -82,7 +83,7 @@ impl Promise { pub fn maybe_resolve_native<T>(&self, cx: *mut JSContext, val: &T) where T: ToJSValConvertible { rooted!(in(cx) let mut v = UndefinedValue()); unsafe { - val.to_jsval(cx, m.handle_mut()); + val.to_jsval(cx, v.handle_mut()); } self.maybe_resolve(cx, v.handle()); } @@ -102,7 +103,7 @@ impl Promise { pub fn maybe_reject_native<T>(&self, cx: *mut JSContext, val: &T) where T: ToJSValConvertible { rooted!(in(cx) let mut v = UndefinedValue()); unsafe { - val.to_jsval(cx, m.handle_mut()); + val.to_jsval(cx, v.handle_mut()); } self.maybe_reject(cx, v.handle()); } @@ -143,6 +144,29 @@ impl Promise { } obj } + + #[allow(unsafe_code)] + pub fn append_native_handler(&self, handler: &PromiseNativeHandler) { + let global = self.global(); + let cx = global.r().get_cx(); + rooted!(in(cx) let resolve_func = + create_native_handler_function(cx, + handler.reflector().get_jsobject(), + NativeHandlerTask::Resolve)); + + rooted!(in(cx) let reject_func = + create_native_handler_function(cx, + handler.reflector().get_jsobject(), + NativeHandlerTask::Reject)); + + unsafe { + let ok = AddPromiseReactions(cx, + self.promise_obj(), + resolve_func.handle(), + reject_func.handle()); + assert!(ok); + } + } } #[allow(unsafe_code)] @@ -151,3 +175,51 @@ unsafe extern fn do_nothing_promise_executor(_cx: *mut JSContext, argc: u32, vp: *args.rval() = UndefinedValue(); true } + +const SLOT_NATIVEHANDLER: usize = 0; +const SLOT_NATIVEHANDLER_TASK: usize = 1; + +#[derive(PartialEq)] +enum NativeHandlerTask { + Resolve = 0, + Reject = 1, +} + +#[allow(unsafe_code)] +unsafe extern fn native_handler_callback(cx: *mut JSContext, argc: u32, vp: *mut JSVal) -> bool { + let args = CallArgs::from_vp(vp, argc); + rooted!(in(cx) let v = *GetFunctionNativeReserved(args.callee(), SLOT_NATIVEHANDLER)); + assert!(v.get().is_object()); + + let handler = root_from_object::<PromiseNativeHandler>(v.to_object()) + .ok().expect("unexpected value for native handler in promise native handler callback"); + + rooted!(in(cx) let v = *GetFunctionNativeReserved(args.callee(), SLOT_NATIVEHANDLER_TASK)); + match v.to_int32() { + v if v == NativeHandlerTask::Resolve as i32 => handler.resolved_callback(cx, args.get(0)), + v if v == NativeHandlerTask::Reject as i32 => handler.rejected_callback(cx, args.get(0)), + _ => panic!("unexpected native handler task value"), + }; + + true +} + +#[allow(unsafe_code)] +fn create_native_handler_function(cx: *mut JSContext, + holder: HandleObject, + task: NativeHandlerTask) -> *mut JSObject { + unsafe { + let func = NewFunctionWithReserved(cx, Some(native_handler_callback), 1, 0, ptr::null()); + assert!(!func.is_null()); + + rooted!(in(cx) let obj = JS_GetFunctionObject(func)); + assert!(!obj.is_null()); + SetFunctionNativeReserved(obj.get(), + SLOT_NATIVEHANDLER, + &ObjectValue(&**holder)); + SetFunctionNativeReserved(obj.get(), + SLOT_NATIVEHANDLER_TASK, + &Int32Value(task as i32)); + obj.get() + } +} |