js-sys: Catch exceptions thrown in Reflect APIs

Proxies passed to Reflect APIs can throw for any of these operations and it is a
bit of a mess.
This commit is contained in:
Nick Fitzgerald 2018-09-25 11:55:28 -07:00
parent 6edb871c36
commit e3d2ea2628
10 changed files with 171 additions and 92 deletions

View File

@ -1210,11 +1210,13 @@ impl ToTokens for ast::DictionaryField {
(quote! {
pub fn #name(&mut self, val: #ty) -> &mut Self {
use wasm_bindgen::JsValue;
::js_sys::Reflect::set(
let r = ::js_sys::Reflect::set(
self.obj.as_ref(),
&JsValue::from(stringify!(#name)),
&JsValue::from(val),
);
debug_assert!(r.is_ok(), "setting properties should never fail on our dictionary objects");
let _ = r;
self
}
}).to_tokens(tokens);

View File

@ -2289,47 +2289,67 @@ extern "C" {
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/apply)
#[wasm_bindgen(static_method_of = Reflect, catch)]
pub fn apply(target: &Function, this_argument: &JsValue, arguments_list: &Array)
-> Result<JsValue, JsValue>;
pub fn apply(
target: &Function,
this_argument: &JsValue,
arguments_list: &Array,
) -> Result<JsValue, JsValue>;
/// The static `Reflect.construct()` method acts like the new operator, but
/// as a function. It is equivalent to calling `new target(...args)`. It
/// gives also the added option to specify a different prototype.
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/construct)
#[wasm_bindgen(static_method_of = Reflect)]
pub fn construct(target: &Function, arguments_list: &Array) -> JsValue;
#[wasm_bindgen(static_method_of = Reflect, js_name = construct)]
pub fn construct_with_new_target(target: &Function, arguments_list: &Array, new_target: &Function) -> JsValue;
#[wasm_bindgen(static_method_of = Reflect, catch)]
pub fn construct(target: &Function, arguments_list: &Array) -> Result<JsValue, JsValue>;
/// The static `Reflect.construct()` method acts like the new operator, but
/// as a function. It is equivalent to calling `new target(...args)`. It
/// gives also the added option to specify a different prototype.
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/construct)
#[wasm_bindgen(static_method_of = Reflect, js_name = construct, catch)]
pub fn construct_with_new_target(
target: &Function,
arguments_list: &Array,
new_target: &Function,
) -> Result<JsValue, JsValue>;
/// The static `Reflect.defineProperty()` method is like
/// `Object.defineProperty()` but returns a `Boolean`.
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/defineProperty)
#[wasm_bindgen(static_method_of = Reflect, js_name = defineProperty)]
pub fn define_property(target: &Object, property_key: &JsValue, attributes: &Object) -> bool;
#[wasm_bindgen(static_method_of = Reflect, js_name = defineProperty, catch)]
pub fn define_property(
target: &Object,
property_key: &JsValue,
attributes: &Object,
) -> Result<bool, JsValue>;
/// The static `Reflect.deleteProperty()` method allows to delete
/// properties. It is like the `delete` operator as a function.
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/deleteProperty)
#[wasm_bindgen(static_method_of = Reflect, js_name = deleteProperty)]
pub fn delete_property(target: &Object, key: &JsValue) -> bool;
#[wasm_bindgen(static_method_of = Reflect, js_name = deleteProperty, catch)]
pub fn delete_property(target: &Object, key: &JsValue) -> Result<bool, JsValue>;
/// The static `Reflect.get()` method works like getting a property from
/// an object (`target[propertyKey]`) as a function.
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/get)
#[wasm_bindgen(static_method_of = Reflect)]
pub fn get(target: &JsValue, key: &JsValue) -> JsValue;
#[wasm_bindgen(static_method_of = Reflect, catch)]
pub fn get(target: &JsValue, key: &JsValue) -> Result<JsValue, JsValue>;
/// The static `Reflect.getOwnPropertyDescriptor()` method is similar to
/// `Object.getOwnPropertyDescriptor()`. It returns a property descriptor
/// of the given property if it exists on the object, `undefined` otherwise.
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/getOwnPropertyDescriptor)
#[wasm_bindgen(static_method_of = Reflect, js_name = getOwnPropertyDescriptor)]
pub fn get_own_property_descriptor(target: &Object, property_key: &JsValue) -> JsValue;
#[wasm_bindgen(static_method_of = Reflect, js_name = getOwnPropertyDescriptor, catch)]
pub fn get_own_property_descriptor(
target: &Object,
property_key: &JsValue,
) -> Result<JsValue, JsValue>;
/// The static `Reflect.getPrototypeOf()` method is almost the same
/// method as `Object.getPrototypeOf()`. It returns the prototype
@ -2337,30 +2357,30 @@ extern "C" {
/// the specified object.
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/getPrototypeOf)
#[wasm_bindgen(static_method_of = Reflect, js_name = getPrototypeOf)]
pub fn get_prototype_of(target: &JsValue) -> Object;
#[wasm_bindgen(static_method_of = Reflect, js_name = getPrototypeOf, catch)]
pub fn get_prototype_of(target: &JsValue) -> Result<Object, JsValue>;
/// The static `Reflect.has()` method works like the in operator as a
/// function.
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/has)
#[wasm_bindgen(static_method_of = Reflect)]
pub fn has(target: &JsValue, property_key: &JsValue) -> bool;
#[wasm_bindgen(static_method_of = Reflect, catch)]
pub fn has(target: &JsValue, property_key: &JsValue) -> Result<bool, JsValue>;
/// The static `Reflect.isExtensible()` method determines if an object is
/// extensible (whether it can have new properties added to it). It is
/// similar to `Object.isExtensible()`, but with some differences.
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/isExtensible)
#[wasm_bindgen(static_method_of = Reflect, js_name = isExtensible)]
pub fn is_extensible(target: &Object) -> bool;
#[wasm_bindgen(static_method_of = Reflect, js_name = isExtensible, catch)]
pub fn is_extensible(target: &Object) -> Result<bool, JsValue>;
/// The static `Reflect.ownKeys()` method returns an array of the
/// target object's own property keys.
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/ownKeys)
#[wasm_bindgen(static_method_of = Reflect, js_name = ownKeys)]
pub fn own_keys(target: &JsValue) -> Array;
#[wasm_bindgen(static_method_of = Reflect, js_name = ownKeys, catch)]
pub fn own_keys(target: &JsValue) -> Result<Array, JsValue>;
/// The static `Reflect.preventExtensions()` method prevents new
/// properties from ever being added to an object (i.e. prevents
@ -2368,17 +2388,27 @@ extern "C" {
/// `Object.preventExtensions()`, but with some differences.
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/preventExtensions)
#[wasm_bindgen(static_method_of = Reflect, js_name = preventExtensions)]
pub fn prevent_extensions(target: &Object) -> bool;
#[wasm_bindgen(static_method_of = Reflect, js_name = preventExtensions, catch)]
pub fn prevent_extensions(target: &Object) -> Result<bool, JsValue>;
/// The static `Reflect.set()` method works like setting a
/// property on an object.
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/set)
#[wasm_bindgen(static_method_of = Reflect)]
pub fn set(target: &JsValue, property_key: &JsValue, value: &JsValue) -> bool;
#[wasm_bindgen(static_method_of = Reflect, js_name = set)]
pub fn set_with_receiver(target: &JsValue, property_key: &JsValue, value: &JsValue, receiver: &JsValue) -> bool;
#[wasm_bindgen(static_method_of = Reflect, catch)]
pub fn set(target: &JsValue, property_key: &JsValue, value: &JsValue) -> Result<bool, JsValue>;
/// The static `Reflect.set()` method works like setting a
/// property on an object.
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/set)
#[wasm_bindgen(static_method_of = Reflect, js_name = set, catch)]
pub fn set_with_receiver(
target: &JsValue,
property_key: &JsValue,
value: &JsValue,
receiver: &JsValue,
) -> Result<bool, JsValue>;
/// The static `Reflect.setPrototypeOf()` method is the same
/// method as `Object.setPrototypeOf()`. It sets the prototype
@ -2386,13 +2416,13 @@ extern "C" {
/// object to another object or to null.
///
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/setPrototypeOf)
#[wasm_bindgen(static_method_of = Reflect, js_name = setPrototypeOf)]
pub fn set_prototype_of(target: &Object, prototype: &JsValue) -> bool;
#[wasm_bindgen(static_method_of = Reflect, js_name = setPrototypeOf, catch)]
pub fn set_prototype_of(target: &Object, prototype: &JsValue) -> Result<bool, JsValue>;
}
// RegExp
#[wasm_bindgen]
extern {
extern "C" {
#[wasm_bindgen(extends = Object)]
#[derive(Clone, Debug)]
pub type RegExp;

View File

@ -72,7 +72,7 @@ fn stringify() {
fn stringify_error() {
let func = Function::new_no_args("throw new Error(\"rust really rocks\")");
let obj = Object::new();
Reflect::set(obj.as_ref(), &JsValue::from("toJSON"), func.as_ref());
Reflect::set(obj.as_ref(), &JsValue::from("toJSON"), func.as_ref()).unwrap();
let result = JSON::stringify(&JsValue::from(obj));
assert!(result.is_err());

View File

@ -168,7 +168,7 @@ fn locale_compare() {
assert!(js_b.locale_compare(a, &locales, &options) < 0);
locales.push(&"en".into());
Reflect::set(options.as_ref(), &"sensitivity".into(), &"base".into());
Reflect::set(options.as_ref(), &"sensitivity".into(), &"base".into()).unwrap();
assert_eq!(js_a.locale_compare(a, &locales, &options), 0);
assert_eq!(js_a.locale_compare(b, &locales, &options), 0);
@ -211,7 +211,7 @@ fn locale_compare() {
assert!(js_ten.locale_compare(two, &locales, &options) > 0);
let locales = Array::new();
Reflect::set(options.as_ref(), &"numeric".into(), &JsValue::TRUE);
Reflect::set(options.as_ref(), &"numeric".into(), &JsValue::TRUE).unwrap();
assert!(js_two.locale_compare(ten, &locales, &options) < 0);
assert!(js_ten.locale_compare(two, &locales, &options) > 0);
@ -224,8 +224,8 @@ fn match_() {
let result = JsString::from(s).match_(&re);
let obj = result.unwrap();
assert_eq!(Reflect::get(obj.as_ref(), &"0".into()), "T");
assert_eq!(Reflect::get(obj.as_ref(), &"1".into()), "I");
assert_eq!(Reflect::get(obj.as_ref(), &"0".into()).unwrap(), "T");
assert_eq!(Reflect::get(obj.as_ref(), &"1".into()).unwrap(), "I");
let result = JsString::from("foo").match_(&re);
assert!(result.is_none());
@ -235,11 +235,11 @@ fn match_() {
let result = JsString::from(s).match_(&re);
let obj = result.unwrap();
assert_eq!(Reflect::get(obj.as_ref(), &"0".into()), "see Chapter 3.4.5.1");
assert_eq!(Reflect::get(obj.as_ref(), &"1".into()), "Chapter 3.4.5.1");
assert_eq!(Reflect::get(obj.as_ref(), &"2".into()), ".1");
assert_eq!(Reflect::get(obj.as_ref(), &"index".into()), 22);
assert_eq!(Reflect::get(obj.as_ref(), &"input".into()), s);
assert_eq!(Reflect::get(obj.as_ref(), &"0".into()).unwrap(), "see Chapter 3.4.5.1");
assert_eq!(Reflect::get(obj.as_ref(), &"1".into()).unwrap(), "Chapter 3.4.5.1");
assert_eq!(Reflect::get(obj.as_ref(), &"2".into()).unwrap(), ".1");
assert_eq!(Reflect::get(obj.as_ref(), &"index".into()).unwrap(), 22);
assert_eq!(Reflect::get(obj.as_ref(), &"input".into()).unwrap(), s);
}
#[wasm_bindgen_test]
@ -494,7 +494,7 @@ fn value_of() {
fn raw() {
let call_site = Object::new();
let raw = Array::of3(&"foo".into(), &"bar".into(), &"123".into());
Reflect::set(&call_site.as_ref(), &"raw".into(), &raw.into());
Reflect::set(&call_site.as_ref(), &"raw".into(), &raw.into()).unwrap();
assert_eq!(JsString::raw_2(&call_site, "5", "JavaScript").unwrap(), "foo5barJavaScript123");
let substitutions = Array::of2(&"5".into(), &"JavaScript".into());
assert_eq!(JsString::raw(&call_site, &substitutions).unwrap(), "foo5barJavaScript123");

View File

@ -11,8 +11,8 @@ fn entries() {
let next = entries.next().unwrap();
assert_eq!(next.done(), false);
assert!(next.value().is_object());
assert_eq!(Reflect::get(&next.value(), &0.into()), "uno");
assert_eq!(Reflect::get(&next.value(), &1.into()), 1);
assert_eq!(Reflect::get(&next.value(), &0.into()).unwrap(), "uno");
assert_eq!(Reflect::get(&next.value(), &1.into()).unwrap(), 1);
let next = entries.next().unwrap();
assert!(next.done());

View File

@ -57,23 +57,23 @@ fn assign() {
let c = JsValue::from("c");
let target = Object::new();
Reflect::set(target.as_ref(), a.as_ref(), a.as_ref());
Reflect::set(target.as_ref(), a.as_ref(), a.as_ref()).unwrap();
let src1 = Object::new();
Reflect::set(src1.as_ref(), &a, &c);
Reflect::set(src1.as_ref(), &a, &c).unwrap();
let src2 = Object::new();
Reflect::set(src2.as_ref(), &b, &b);
Reflect::set(src2.as_ref(), &b, &b).unwrap();
let src3 = Object::new();
Reflect::set(src3.as_ref(), &c, &c);
Reflect::set(src3.as_ref(), &c, &c).unwrap();
let res = Object::assign3(&target, &src1, &src2, &src3);
assert!(Object::is(target.as_ref(), res.as_ref()));
assert_eq!(Reflect::get(target.as_ref(), &a), c);
assert_eq!(Reflect::get(target.as_ref(), &b), b);
assert_eq!(Reflect::get(target.as_ref(), &c), c);
assert_eq!(Reflect::get(target.as_ref(), &a).unwrap(), c);
assert_eq!(Reflect::get(target.as_ref(), &b).unwrap(), b);
assert_eq!(Reflect::get(target.as_ref(), &c).unwrap(), c);
}
#[wasm_bindgen_test]
@ -102,8 +102,8 @@ fn define_properties() {
let descriptor = DefinePropertyAttrs::from(JsValue::from(Object::new()));
descriptor.set_value(&42.into());
let descriptor = JsValue::from(descriptor);
Reflect::set(props.as_ref(), &JsValue::from("bar"), &descriptor);
Reflect::set(props.as_ref(), &JsValue::from("car"), &descriptor);
Reflect::set(props.as_ref(), &JsValue::from("bar"), &descriptor).unwrap();
Reflect::set(props.as_ref(), &JsValue::from("car"), &descriptor).unwrap();
let foo = foo_42();
let foo = Object::define_properties(&foo, &props);
assert!(foo.has_own_property(&"bar".into()));
@ -136,7 +136,7 @@ fn get_own_property_descriptor() {
fn get_own_property_descriptors() {
let foo = foo_42();
let descriptors = Object::get_own_property_descriptors(&foo);
let foo_desc = Reflect::get(&descriptors, &"foo".into());
let foo_desc = Reflect::get(&descriptors, &"foo".into()).unwrap();
assert_eq!(PropertyDescriptor::from(foo_desc).value(), 42);
}

View File

@ -23,3 +23,19 @@ exports.Rectangle2 = class {
return x === y;
}
};
exports.throw_all_the_time = () => new Proxy({}, {
getPrototypeOf() { throw new Error("nope"); },
setPrototypeOf() { throw new Error("nope"); },
isExtensible() { throw new Error("nope"); },
preventExtensions() { throw new Error("nope"); },
getOwnPropertyDescriptor() { throw new Error("nope"); },
defineProperty() { throw new Error("nope"); },
has() { throw new Error("nope"); },
get() { throw new Error("nope"); },
set() { throw new Error("nope"); },
deleteProperty() { throw new Error("nope"); },
ownKeys() { throw new Error("nope"); },
apply() { throw new Error("nope"); },
construct() { throw new Error("nope"); },
});

View File

@ -21,6 +21,8 @@ extern {
fn x_jsval(this: &Rectangle) -> JsValue;
#[wasm_bindgen(method, setter, structural)]
fn set_x(this: &Rectangle, x: u32);
fn throw_all_the_time() -> Object;
}
#[wasm_bindgen]
@ -51,7 +53,7 @@ fn construct() {
let args = Array::new();
args.push(&10.into());
args.push(&10.into());
let instance = Reflect::construct(&RECTANGLE_CLASS, &args);
let instance = Reflect::construct(&RECTANGLE_CLASS, &args).unwrap();
assert_eq!(Rectangle::from(instance).x(), 10);
}
@ -64,7 +66,7 @@ fn construct_with_new_target() {
&RECTANGLE_CLASS,
&args,
&RECTANGLE2_CLASS,
);
).unwrap();
assert_eq!(Rectangle::from(instance).x(), 10);
}
@ -73,7 +75,7 @@ fn define_property() {
let value = DefinePropertyAttrs::from(JsValue::from(Object::new()));
value.set_value(&42.into());
let obj = Object::from(JsValue::from(value));
assert!(Reflect::define_property(&obj, &"key".into(), &obj));
assert!(Reflect::define_property(&obj, &"key".into(), &obj).unwrap());
}
#[wasm_bindgen_test]
@ -82,13 +84,13 @@ fn delete_property() {
r.set_x(10);
let obj = Object::from(JsValue::from(r.clone()));
Reflect::delete_property(&obj, &"x".into());
Reflect::delete_property(&obj, &"x".into()).unwrap();
assert!(r.x_jsval().is_undefined());
let array = Array::new();
array.push(&1.into());
let obj = Object::from(JsValue::from(array));
Reflect::delete_property(&obj, &0.into());
Reflect::delete_property(&obj, &0.into()).unwrap();
let array = Array::from(&JsValue::from(obj));
assert!(array.length() == 1);
array.for_each(&mut |x, _, _| assert!(x.is_undefined()));
@ -100,7 +102,7 @@ fn get() {
r.set_x(10);
let obj = JsValue::from(r.clone());
assert_eq!(Reflect::get(&obj, &"x".into()), 10);
assert_eq!(Reflect::get(&obj, &"x".into()).unwrap(), 10);
}
#[wasm_bindgen_test]
@ -109,41 +111,41 @@ fn get_own_property_descriptor() {
r.set_x(10);
let obj = Object::from(JsValue::from(r.clone()));
let desc = Reflect::get_own_property_descriptor(&obj, &"x".into());
let desc = Reflect::get_own_property_descriptor(&obj, &"x".into()).unwrap();
assert_eq!(PropertyDescriptor::from(desc).value(), 10);
let desc = Reflect::get_own_property_descriptor(&obj, &"foo".into());
let desc = Reflect::get_own_property_descriptor(&obj, &"foo".into()).unwrap();
assert!(PropertyDescriptor::from(desc).value().is_undefined());
}
#[wasm_bindgen_test]
fn get_prototype_of() {
let proto = JsValue::from(Reflect::get_prototype_of(&Object::new().into()));
let proto = JsValue::from(Reflect::get_prototype_of(&Object::new().into()).unwrap());
assert_eq!(proto, *OBJECT_PROTOTYPE);
let proto = JsValue::from(Reflect::get_prototype_of(&Array::new().into()));
let proto = JsValue::from(Reflect::get_prototype_of(&Array::new().into()).unwrap());
assert_eq!(proto, *ARRAY_PROTOTYPE);
}
#[wasm_bindgen_test]
fn has() {
let obj = JsValue::from(Rectangle::new());
assert!(Reflect::has(&obj, &"x".into()));
assert!(!Reflect::has(&obj, &"foo".into()));
assert!(Reflect::has(&obj, &"x".into()).unwrap());
assert!(!Reflect::has(&obj, &"foo".into()).unwrap());
}
#[wasm_bindgen_test]
fn is_extensible() {
let obj = Object::from(JsValue::from(Rectangle::new()));
assert!(Reflect::is_extensible(&obj));
Reflect::prevent_extensions(&obj);
assert!(!Reflect::is_extensible(&obj));
assert!(Reflect::is_extensible(&obj).unwrap());
Reflect::prevent_extensions(&obj).unwrap();
assert!(!Reflect::is_extensible(&obj).unwrap());
let obj = Object::seal(&Object::new());
assert!(!Reflect::is_extensible(&obj));
assert!(!Reflect::is_extensible(&obj).unwrap());
}
#[wasm_bindgen_test]
fn own_keys() {
let obj = JsValue::from(Rectangle::new());
let keys = Reflect::own_keys(&obj);
let keys = Reflect::own_keys(&obj).unwrap();
assert!(keys.length() == 2);
keys.for_each(&mut |k, _, _| {
assert!(k == "x" || k == "y");
@ -153,32 +155,32 @@ fn own_keys() {
#[wasm_bindgen_test]
fn prevent_extensions() {
let obj = Object::new();
Reflect::prevent_extensions(&obj);
assert!(!Reflect::is_extensible(&obj));
Reflect::prevent_extensions(&obj).unwrap();
assert!(!Reflect::is_extensible(&obj).unwrap());
}
#[wasm_bindgen_test]
fn set() {
let obj = JsValue::from(Object::new());
assert!(Reflect::set(&obj, &"key".into(), &"value".into()));
assert_eq!(Reflect::get(&obj, &"key".into()), "value");
assert!(Reflect::set(&obj, &"key".into(), &"value".into()).unwrap());
assert_eq!(Reflect::get(&obj, &"key".into()).unwrap(), "value");
}
#[wasm_bindgen_test]
fn set_with_receiver() {
let obj1 = JsValue::from(Object::new());
let obj2 = JsValue::from(Object::new());
assert!(Reflect::set_with_receiver(&obj2, &"key".into(), &"value".into(), &obj2));
assert!(Reflect::get(&obj1, &"key".into()).is_undefined());
assert_eq!(Reflect::get(&obj2, &"key".into()), "value");
assert!(Reflect::set_with_receiver(&obj2, &"key".into(), &"value".into(), &obj2).unwrap());
assert!(Reflect::get(&obj1, &"key".into()).unwrap().is_undefined());
assert_eq!(Reflect::get(&obj2, &"key".into()).unwrap(), "value");
}
#[wasm_bindgen_test]
fn set_prototype_of() {
let obj = Object::new();
assert!(Reflect::set_prototype_of(&obj, &JsValue::null()));
assert!(Reflect::set_prototype_of(&obj, &JsValue::null()).unwrap());
let obj = JsValue::from(obj);
assert_eq!(JsValue::from(Reflect::get_prototype_of(&obj)), JsValue::null());
assert_eq!(JsValue::from(Reflect::get_prototype_of(&obj).unwrap()), JsValue::null());
}
#[wasm_bindgen_test]
@ -192,3 +194,32 @@ fn reflect_extends() {
assert!(reflect.is_instance_of::<Object>());
let _: &Object = reflect.as_ref();
}
#[wasm_bindgen_test]
fn reflect_bindings_handle_proxies_that_just_throw_for_everything() {
let p = throw_all_the_time();
let desc = Object::new();
Reflect::set(desc.as_ref(), &"value".into(), &1.into()).unwrap();
assert!(Reflect::define_property(&p, &"a".into(), &desc).is_err());
assert!(Reflect::delete_property(&p, &"a".into()).is_err());
assert!(Reflect::get(p.as_ref(), &"a".into()).is_err());
assert!(Reflect::get_own_property_descriptor(&p, &"a".into()).is_err());
assert!(Reflect::get_prototype_of(p.as_ref()).is_err());
assert!(Reflect::has(p.as_ref(), &"a".into()).is_err());
assert!(Reflect::is_extensible(&p).is_err());
assert!(Reflect::own_keys(p.as_ref()).is_err());
assert!(Reflect::prevent_extensions(&p).is_err());
assert!(Reflect::set(p.as_ref(), &"a".into(), &1.into()).is_err());
assert!(Reflect::set_prototype_of(&p, Object::new().as_ref()).is_err());
}

View File

@ -178,7 +178,7 @@ fn webassembly_instance() {
// Has expected exports.
let exports = instance.exports();
assert!(Reflect::has(exports.as_ref(), &"exported_func".into()));
assert!(Reflect::has(exports.as_ref(), &"exported_func".into()).unwrap());
}
#[wasm_bindgen_test(async)]
@ -201,6 +201,7 @@ fn instantiate_streaming() -> impl Future<Item = (), Error = JsValue> {
.map(|obj| {
assert!(
Reflect::get(obj.as_ref(), &"instance".into())
.unwrap()
.is_instance_of::<WebAssembly::Instance>()
);
})
@ -209,7 +210,7 @@ fn instantiate_streaming() -> impl Future<Item = (), Error = JsValue> {
#[wasm_bindgen_test]
fn memory_works() {
let obj = Object::new();
Reflect::set(obj.as_ref(), &"initial".into(), &1.into());
Reflect::set(obj.as_ref(), &"initial".into(), &1.into()).unwrap();
let mem = WebAssembly::Memory::new(&obj).unwrap();
assert!(mem.is_instance_of::<WebAssembly::Memory>());
assert!(mem.is_instance_of::<Object>());

View File

@ -1,9 +1,9 @@
extern crate wasm_bindgen;
extern crate js_sys;
extern crate wasm_bindgen;
use js_sys::{Function, Object, Reflect, Uint8Array, WebAssembly};
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use js_sys::{WebAssembly, Object, Reflect, Function, Uint8Array};
// lifted from the `console_log` example
#[wasm_bindgen]
@ -30,22 +30,21 @@ pub fn run() -> Result<(), JsValue> {
// (aka do a memory allocation in Rust) it'll cause the buffer to change.
// That means we can't actually do any memory allocations after we do this
// until we pass it back to JS.
let my_memory = Uint8Array::new(&my_memory.buffer())
.subarray(
WASM.as_ptr() as u32,
WASM.as_ptr() as u32 + WASM.len() as u32,
);
let my_memory = Uint8Array::new(&my_memory.buffer()).subarray(
WASM.as_ptr() as u32,
WASM.as_ptr() as u32 + WASM.len() as u32,
);
let a = WebAssembly::Module::new(my_memory.as_ref())?;
let b = WebAssembly::Instance::new(&a, &Object::new())?;
let c = b.exports();
let add = Reflect::get(c.as_ref(), &"add".into())
let add = Reflect::get(c.as_ref(), &"add".into())?
.dyn_into::<Function>()
.expect("add export wasn't a function");
let three = add.call2(&JsValue::undefined(), &1.into(), &2.into())?;
console_log!("1 + 2 = {:?}", three);
let mem = Reflect::get(c.as_ref(), &"memory".into())
let mem = Reflect::get(c.as_ref(), &"memory".into())?
.dyn_into::<WebAssembly::Memory>()
.expect("memory export wasn't a `WebAssembly.Memory`");
console_log!("created module has {} pages of memory", mem.grow(0));