Skip to content

Commit

Permalink
Add a simple API to reject promises with DOM error values.
Browse files Browse the repository at this point in the history
  • Loading branch information
jdm committed Sep 22, 2016
1 parent ae81ab3 commit 27d44c8
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 2 deletions.
12 changes: 12 additions & 0 deletions components/script/dom/bindings/error.rs
Expand Up @@ -19,6 +19,7 @@ use js::jsapi::JS_ErrorFromException;
use js::jsapi::JS_GetPendingException;
use js::jsapi::JS_IsExceptionPending;
use js::jsapi::JS_SetPendingException;
use js::jsapi::MutableHandleValue;
use js::jsval::UndefinedValue;
use libc::c_uint;
use std::slice::from_raw_parts;
Expand Down Expand Up @@ -266,3 +267,14 @@ pub unsafe fn throw_invalid_this(cx: *mut JSContext, proto_id: u16) {
proto_id_to_name(proto_id));
throw_type_error(cx, &error);
}

impl Error {
/// Convert this error value to a JS value, consuming it in the process.
pub unsafe fn to_jsval(self, cx: *mut JSContext, global: GlobalRef, rval: MutableHandleValue) {
assert!(!JS_IsExceptionPending(cx));
throw_dom_exception(cx, global, self);
assert!(JS_IsExceptionPending(cx));
assert!(JS_GetPendingException(cx, rval));
JS_ClearPendingException(cx);
}
}
11 changes: 10 additions & 1 deletion components/script/dom/promise.rs
Expand Up @@ -14,7 +14,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::error::{Error, Fallible};
use dom::bindings::global::GlobalRef;
use dom::bindings::js::MutHeapJSVal;
use dom::bindings::reflector::{Reflectable, MutReflectable, Reflector};
Expand Down Expand Up @@ -156,6 +156,15 @@ impl Promise {
self.maybe_reject(cx, v.handle());
}

#[allow(unsafe_code)]
pub fn maybe_reject_error(&self, cx: *mut JSContext, error: Error) {
rooted!(in(cx) let mut v = UndefinedValue());
unsafe {
error.maybe_to_jsval(cx, self.global().r(), v.handle_mut());
}
self.maybe_reject(cx, v.handle());
}

#[allow(unrooted_must_root, unsafe_code)]
pub fn maybe_reject(&self,
cx: *mut JSContext,
Expand Down
6 changes: 5 additions & 1 deletion components/script/dom/testbinding.rs
Expand Up @@ -20,7 +20,7 @@ use dom::bindings::codegen::UnionTypes::{EventOrUSVString, HTMLElementOrLong, Lo
use dom::bindings::codegen::UnionTypes::{HTMLElementOrUnsignedLongOrStringOrBoolean, LongSequenceOrBoolean};
use dom::bindings::codegen::UnionTypes::{StringOrLongSequence, StringOrStringSequence, StringSequenceOrUnsignedLong};
use dom::bindings::codegen::UnionTypes::{StringOrUnsignedLong, StringOrBoolean, UnsignedLongOrBoolean};
use dom::bindings::error::Fallible;
use dom::bindings::error::{Error, Fallible};
use dom::bindings::global::{GlobalRef, global_root_from_context};
use dom::bindings::js::Root;
use dom::bindings::mozmap::MozMap;
Expand Down Expand Up @@ -668,6 +668,10 @@ impl TestBindingMethods for TestBinding {
p.maybe_reject(cx, v);
}

fn PromiseRejectWithTypeError(&self, p: &Promise, s: USVString) {
p.maybe_reject_error(self.global().r().get_cx(), Error::Type(s.0));
}

#[allow(unrooted_must_root)]
fn PromiseNativeHandler(&self,
resolve: Option<Rc<SimpleCallback>>,
Expand Down
1 change: 1 addition & 0 deletions components/script/dom/webidls/TestBinding.webidl
Expand Up @@ -518,6 +518,7 @@ interface TestBinding {
Promise<any> promiseNativeHandler(SimpleCallback? resolve, SimpleCallback? reject);
void promiseResolveNative(Promise<any> p, any value);
void promiseRejectNative(Promise<any> p, any value);
void promiseRejectWithTypeError(Promise<any> p, USVString message);

void panic();
};
Expand Down
7 changes: 7 additions & 0 deletions tests/wpt/mozilla/tests/mozilla/promise.html
Expand Up @@ -21,6 +21,13 @@
});
}, 'Reject callback gets argument');

promise_test(function(test) {
var t = new TestBinding;
var p = new Promise(function() {});
t.promiseRejectWithTypeError(p, "success");
return promise_rejects(test, new TypeError("success"), p, "TypeError should be instantiated");
}, 'Native code rejects with exception');

promise_test(function(test) {
var t = new TestBinding;
var resolved;
Expand Down

0 comments on commit 27d44c8

Please sign in to comment.