diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index e3cc2287..782d953b 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -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); diff --git a/crates/js-sys/src/lib.rs b/crates/js-sys/src/lib.rs index 598ceb16..27229d2f 100644 --- a/crates/js-sys/src/lib.rs +++ b/crates/js-sys/src/lib.rs @@ -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; + pub fn apply( + target: &Function, + this_argument: &JsValue, + arguments_list: &Array, + ) -> Result; /// 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; + + /// 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; /// 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; /// 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; /// 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; /// 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; /// 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; /// 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; /// 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; /// 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; /// 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; /// 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; + + /// 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; /// 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; } // RegExp #[wasm_bindgen] -extern { +extern "C" { #[wasm_bindgen(extends = Object)] #[derive(Clone, Debug)] pub type RegExp; diff --git a/crates/js-sys/tests/wasm/JSON.rs b/crates/js-sys/tests/wasm/JSON.rs index d38bae3b..affbf3f7 100644 --- a/crates/js-sys/tests/wasm/JSON.rs +++ b/crates/js-sys/tests/wasm/JSON.rs @@ -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()); diff --git a/crates/js-sys/tests/wasm/JsString.rs b/crates/js-sys/tests/wasm/JsString.rs index 5d5b5975..0240dbdf 100644 --- a/crates/js-sys/tests/wasm/JsString.rs +++ b/crates/js-sys/tests/wasm/JsString.rs @@ -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"); diff --git a/crates/js-sys/tests/wasm/MapIterator.rs b/crates/js-sys/tests/wasm/MapIterator.rs index ee76a85e..3e28a204 100644 --- a/crates/js-sys/tests/wasm/MapIterator.rs +++ b/crates/js-sys/tests/wasm/MapIterator.rs @@ -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()); diff --git a/crates/js-sys/tests/wasm/Object.rs b/crates/js-sys/tests/wasm/Object.rs index 52e6fa50..e89d16f5 100644 --- a/crates/js-sys/tests/wasm/Object.rs +++ b/crates/js-sys/tests/wasm/Object.rs @@ -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); } diff --git a/crates/js-sys/tests/wasm/Reflect.js b/crates/js-sys/tests/wasm/Reflect.js index ffba2069..98169e2e 100644 --- a/crates/js-sys/tests/wasm/Reflect.js +++ b/crates/js-sys/tests/wasm/Reflect.js @@ -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"); }, +}); diff --git a/crates/js-sys/tests/wasm/Reflect.rs b/crates/js-sys/tests/wasm/Reflect.rs index da2c5217..47b5ac4a 100644 --- a/crates/js-sys/tests/wasm/Reflect.rs +++ b/crates/js-sys/tests/wasm/Reflect.rs @@ -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::()); 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()); +} diff --git a/crates/js-sys/tests/wasm/WebAssembly.rs b/crates/js-sys/tests/wasm/WebAssembly.rs index 65385ec5..f67c742b 100644 --- a/crates/js-sys/tests/wasm/WebAssembly.rs +++ b/crates/js-sys/tests/wasm/WebAssembly.rs @@ -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 { .map(|obj| { assert!( Reflect::get(obj.as_ref(), &"instance".into()) + .unwrap() .is_instance_of::() ); }) @@ -209,7 +210,7 @@ fn instantiate_streaming() -> impl Future { #[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::()); assert!(mem.is_instance_of::()); diff --git a/examples/wasm-in-wasm/src/lib.rs b/examples/wasm-in-wasm/src/lib.rs index f2382534..3496a3e7 100644 --- a/examples/wasm-in-wasm/src/lib.rs +++ b/examples/wasm-in-wasm/src/lib.rs @@ -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::() .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::() .expect("memory export wasn't a `WebAssembly.Memory`"); console_log!("created module has {} pages of memory", mem.grow(0));