mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-03-15 17:50:51 +00:00
Merge pull request #887 from fitzgen/iterating-over-js-values
Iterating over js values
This commit is contained in:
commit
ee0e4bc089
@ -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);
|
||||
|
@ -20,12 +20,12 @@
|
||||
|
||||
extern crate wasm_bindgen;
|
||||
|
||||
use std::mem;
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
|
||||
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering::SeqCst};
|
||||
use wasm_bindgen::JsCast;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering::SeqCst, ATOMIC_USIZE_INIT};
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
// When adding new imports:
|
||||
//
|
||||
@ -304,14 +304,22 @@ extern "C" {
|
||||
///
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce)
|
||||
#[wasm_bindgen(method)]
|
||||
pub fn reduce(this: &Array, predicate: &mut FnMut(JsValue, JsValue, u32, Array) -> JsValue, initial_value: &JsValue) -> JsValue;
|
||||
pub fn reduce(
|
||||
this: &Array,
|
||||
predicate: &mut FnMut(JsValue, JsValue, u32, Array) -> JsValue,
|
||||
initial_value: &JsValue,
|
||||
) -> JsValue;
|
||||
|
||||
/// The reduceRight() method applies a function against an accumulator and each value
|
||||
/// of the array (from right-to-left) to reduce it to a single value.
|
||||
///
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/ReduceRight)
|
||||
#[wasm_bindgen(method, js_name = reduceRight)]
|
||||
pub fn reduce_right(this: &Array, predicate: &mut FnMut(JsValue, JsValue, u32, Array) -> JsValue, initial_value: &JsValue) -> JsValue;
|
||||
pub fn reduce_right(
|
||||
this: &Array,
|
||||
predicate: &mut FnMut(JsValue, JsValue, u32, Array) -> JsValue,
|
||||
initial_value: &JsValue,
|
||||
) -> JsValue;
|
||||
|
||||
/// The reverse() method reverses an array in place. The first array
|
||||
/// element becomes the last, and the last array element becomes the first.
|
||||
@ -831,14 +839,25 @@ extern "C" {
|
||||
///
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call)
|
||||
#[wasm_bindgen(method, catch, js_name = call)]
|
||||
pub fn call2(this: &Function, context: &JsValue, arg1: &JsValue, arg2: &JsValue) -> Result<JsValue, JsValue>;
|
||||
pub fn call2(
|
||||
this: &Function,
|
||||
context: &JsValue,
|
||||
arg1: &JsValue,
|
||||
arg2: &JsValue,
|
||||
) -> Result<JsValue, JsValue>;
|
||||
|
||||
/// The `call()` method calls a function with a given this value and
|
||||
/// arguments provided individually.
|
||||
///
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call)
|
||||
#[wasm_bindgen(method, catch, js_name = call)]
|
||||
pub fn call3(this: &Function, context: &JsValue, arg1: &JsValue, arg2: &JsValue, arg3: &JsValue) -> Result<JsValue, JsValue>;
|
||||
pub fn call3(
|
||||
this: &Function,
|
||||
context: &JsValue,
|
||||
arg1: &JsValue,
|
||||
arg2: &JsValue,
|
||||
arg3: &JsValue,
|
||||
) -> Result<JsValue, JsValue>;
|
||||
|
||||
/// The bind() method creates a new function that, when called, has its this keyword set to the provided value,
|
||||
/// with a given sequence of arguments preceding any provided when the new function is called.
|
||||
@ -885,7 +904,7 @@ impl Function {
|
||||
|
||||
// Generator
|
||||
#[wasm_bindgen]
|
||||
extern {
|
||||
extern "C" {
|
||||
#[wasm_bindgen(extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub type Generator;
|
||||
@ -1072,7 +1091,7 @@ extern "C" {
|
||||
|
||||
// Map
|
||||
#[wasm_bindgen]
|
||||
extern {
|
||||
extern "C" {
|
||||
#[wasm_bindgen(extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub type Map;
|
||||
@ -1134,7 +1153,7 @@ extern {
|
||||
|
||||
// Map Iterator
|
||||
#[wasm_bindgen]
|
||||
extern {
|
||||
extern "C" {
|
||||
/// The entries() method returns a new Iterator object that contains
|
||||
/// the [key, value] pairs for each element in the Map object in
|
||||
/// insertion order.
|
||||
@ -1160,7 +1179,7 @@ extern {
|
||||
|
||||
// Iterator
|
||||
#[wasm_bindgen]
|
||||
extern {
|
||||
extern "C" {
|
||||
/// Any object that conforms to the JS iterator protocol. For example,
|
||||
/// something returned by `myArray[Symbol.iterator]()`.
|
||||
///
|
||||
@ -1176,11 +1195,17 @@ extern {
|
||||
pub fn next(this: &Iterator) -> Result<IteratorNext, JsValue>;
|
||||
}
|
||||
|
||||
/// An iterator over the JS `Symbol.iterator` iteration protocol.
|
||||
///
|
||||
/// Use the `IntoIterator for &js_sys::Iterator` implementation to create this.
|
||||
pub struct Iter<'a> {
|
||||
js: &'a Iterator,
|
||||
state: IterState,
|
||||
}
|
||||
|
||||
/// An iterator over the JS `Symbol.iterator` iteration protocol.
|
||||
///
|
||||
/// Use the `IntoIterator for js_sys::Iterator` implementation to create this.
|
||||
pub struct IntoIter {
|
||||
js: Iterator,
|
||||
state: IterState,
|
||||
@ -1195,7 +1220,10 @@ impl<'a> IntoIterator for &'a Iterator {
|
||||
type IntoIter = Iter<'a>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a> {
|
||||
Iter { js: self, state: IterState::new() }
|
||||
Iter {
|
||||
js: self,
|
||||
state: IterState::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1212,7 +1240,10 @@ impl IntoIterator for Iterator {
|
||||
type IntoIter = IntoIter;
|
||||
|
||||
fn into_iter(self) -> IntoIter {
|
||||
IntoIter { js: self, state: IterState::new() }
|
||||
IntoIter {
|
||||
js: self,
|
||||
state: IterState::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1231,13 +1262,13 @@ impl IterState {
|
||||
|
||||
fn next(&mut self, js: &Iterator) -> Option<Result<JsValue, JsValue>> {
|
||||
if self.done {
|
||||
return None
|
||||
return None;
|
||||
}
|
||||
let next = match js.next() {
|
||||
Ok(val) => val,
|
||||
Err(e) => {
|
||||
self.done = true;
|
||||
return Some(Err(e))
|
||||
return Some(Err(e));
|
||||
}
|
||||
};
|
||||
if next.done() {
|
||||
@ -1249,9 +1280,35 @@ impl IterState {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create an iterator over `val` using the JS iteration protocol and
|
||||
/// `Symbol.iterator`.
|
||||
pub fn try_iter(val: &JsValue) -> Result<Option<IntoIter>, JsValue> {
|
||||
let iter_sym = Symbol::iterator();
|
||||
let iter_fn = Reflect::get(val, iter_sym.as_ref())?;
|
||||
if !iter_fn.is_function() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let iter_fn: Function = iter_fn.unchecked_into();
|
||||
let it = iter_fn.call0(val)?;
|
||||
if !it.is_object() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let next = JsValue::from("next");
|
||||
let next = Reflect::get(&it, &next)?;
|
||||
|
||||
Ok(if next.is_function() {
|
||||
let it: Iterator = it.unchecked_into();
|
||||
Some(it.into_iter())
|
||||
} else {
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
// IteratorNext
|
||||
#[wasm_bindgen]
|
||||
extern {
|
||||
extern "C" {
|
||||
/// The result of calling `next()` on a JS iterator.
|
||||
///
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols)
|
||||
@ -1368,7 +1425,6 @@ extern "C" {
|
||||
#[wasm_bindgen(static_method_of = Math)]
|
||||
pub fn cos(x: f64) -> f64;
|
||||
|
||||
|
||||
/// The Math.cosh() function returns the hyperbolic cosine of a number,
|
||||
/// that can be expressed using the constant e.
|
||||
///
|
||||
@ -1996,7 +2052,8 @@ extern "C" {
|
||||
///
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
|
||||
#[wasm_bindgen(static_method_of = Object, js_name = assign)]
|
||||
pub fn assign3(target: &Object, source1: &Object, source2: &Object, source3: &Object) -> Object;
|
||||
pub fn assign3(target: &Object, source1: &Object, source2: &Object, source3: &Object)
|
||||
-> Object;
|
||||
|
||||
/// The Object.create() method creates a new object, using an existing
|
||||
/// object to provide the newly created object's prototype.
|
||||
@ -2213,7 +2270,7 @@ impl Object {
|
||||
|
||||
// Proxy
|
||||
#[wasm_bindgen]
|
||||
extern {
|
||||
extern "C" {
|
||||
#[derive(Clone, Debug)]
|
||||
pub type Proxy;
|
||||
|
||||
@ -2235,7 +2292,7 @@ extern {
|
||||
|
||||
// RangeError
|
||||
#[wasm_bindgen]
|
||||
extern {
|
||||
extern "C" {
|
||||
/// The RangeError object indicates an error when a value is not in the set
|
||||
/// or range of allowed values.
|
||||
///
|
||||
@ -2254,7 +2311,7 @@ extern {
|
||||
|
||||
// ReferenceError
|
||||
#[wasm_bindgen]
|
||||
extern {
|
||||
extern "C" {
|
||||
/// The ReferenceError object represents an error when a non-existent
|
||||
/// variable is referenced.
|
||||
///
|
||||
@ -2283,47 +2340,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
|
||||
@ -2331,30 +2408,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
|
||||
@ -2362,17 +2439,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
|
||||
@ -2380,13 +2467,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;
|
||||
@ -2563,7 +2650,7 @@ extern {
|
||||
|
||||
// Set
|
||||
#[wasm_bindgen]
|
||||
extern {
|
||||
extern "C" {
|
||||
#[wasm_bindgen(extends = Object)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub type Set;
|
||||
@ -2619,7 +2706,7 @@ extern {
|
||||
|
||||
// SetIterator
|
||||
#[wasm_bindgen]
|
||||
extern {
|
||||
extern "C" {
|
||||
/// The `entries()` method returns a new Iterator object that contains an
|
||||
/// array of [value, value] for each element in the Set object, in insertion
|
||||
/// order. For Set objects there is no key like in Map objects. However, to
|
||||
@ -2648,7 +2735,7 @@ extern {
|
||||
|
||||
// SyntaxError
|
||||
#[wasm_bindgen]
|
||||
extern {
|
||||
extern "C" {
|
||||
/// A SyntaxError is thrown when the JavaScript engine encounters tokens or
|
||||
/// token order that does not conform to the syntax of the language when
|
||||
/// parsing code.
|
||||
@ -2669,7 +2756,7 @@ extern {
|
||||
|
||||
// TypeError
|
||||
#[wasm_bindgen]
|
||||
extern {
|
||||
extern "C" {
|
||||
/// The TypeError object represents an error when a value is not of the
|
||||
/// expected type.
|
||||
///
|
||||
@ -2902,7 +2989,7 @@ extern "C" {
|
||||
|
||||
// URIError
|
||||
#[wasm_bindgen]
|
||||
extern {
|
||||
extern "C" {
|
||||
/// The URIError object represents an error when a global URI handling
|
||||
/// function was used in a wrong way.
|
||||
///
|
||||
@ -3446,7 +3533,12 @@ extern "C" {
|
||||
///
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare)
|
||||
#[wasm_bindgen(method, js_class = "String", js_name = localeCompare)]
|
||||
pub fn locale_compare(this: &JsString, compare_string: &str, locales: &Array, options: &Object) -> i32;
|
||||
pub fn locale_compare(
|
||||
this: &JsString,
|
||||
compare_string: &str,
|
||||
locales: &Array,
|
||||
options: &Object,
|
||||
) -> i32;
|
||||
|
||||
/// The match() method retrieves the matches when matching a string against a regular expression.
|
||||
///
|
||||
@ -3498,14 +3590,22 @@ extern "C" {
|
||||
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace)
|
||||
#[wasm_bindgen(method, js_class = "String", js_name = replace)]
|
||||
pub fn replace_with_function(this: &JsString, pattern: &str, replacement: &Function) -> JsString;
|
||||
pub fn replace_with_function(
|
||||
this: &JsString,
|
||||
pattern: &str,
|
||||
replacement: &Function,
|
||||
) -> JsString;
|
||||
|
||||
#[wasm_bindgen(method, js_class = "String", js_name = replace)]
|
||||
pub fn replace_by_pattern(this: &JsString, pattern: &RegExp, replacement: &str) -> JsString;
|
||||
|
||||
/// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace)
|
||||
#[wasm_bindgen(method, js_class = "String", js_name = replace)]
|
||||
pub fn replace_by_pattern_with_function(this: &JsString, pattern: &RegExp, replacement: &Function) -> JsString;
|
||||
pub fn replace_by_pattern_with_function(
|
||||
this: &JsString,
|
||||
pattern: &RegExp,
|
||||
replacement: &Function,
|
||||
) -> JsString;
|
||||
|
||||
/// The search() method executes a search for a match between
|
||||
/// a regular expression and this String object.
|
||||
@ -4148,7 +4248,7 @@ pub mod Intl {
|
||||
|
||||
// Promise
|
||||
#[wasm_bindgen]
|
||||
extern {
|
||||
extern "C" {
|
||||
/// The `Promise` object represents the eventual completion (or failure) of
|
||||
/// an asynchronous operation, and its resulting value.
|
||||
///
|
||||
@ -4227,9 +4327,11 @@ extern {
|
||||
|
||||
/// Same as `then`, only with both arguments provided.
|
||||
#[wasm_bindgen(method, js_name = then)]
|
||||
pub fn then2(this: &Promise,
|
||||
resolve: &Closure<FnMut(JsValue)>,
|
||||
reject: &Closure<FnMut(JsValue)>) -> Promise;
|
||||
pub fn then2(
|
||||
this: &Promise,
|
||||
resolve: &Closure<FnMut(JsValue)>,
|
||||
reject: &Closure<FnMut(JsValue)>,
|
||||
) -> Promise;
|
||||
|
||||
/// The `finally()` method returns a `Promise`. When the promise is settled,
|
||||
/// whether fulfilled or rejected, the specified callback function is
|
||||
|
19
crates/js-sys/tests/wasm/Iterator.js
Normal file
19
crates/js-sys/tests/wasm/Iterator.js
Normal file
@ -0,0 +1,19 @@
|
||||
exports.get_iterable = () => ["one", "two", "three"];
|
||||
|
||||
exports.get_not_iterable = () => new Object;
|
||||
|
||||
exports.get_symbol_iterator_throws = () => ({
|
||||
[Symbol.iterator]: () => { throw new Error("nope"); },
|
||||
});
|
||||
|
||||
exports.get_symbol_iterator_not_function = () => ({
|
||||
[Symbol.iterator]: 5,
|
||||
});
|
||||
|
||||
exports.get_symbol_iterator_returns_not_object = () => ({
|
||||
[Symbol.iterator]: () => 5,
|
||||
});
|
||||
|
||||
exports.get_symbol_iterator_returns_object_without_next = () => ({
|
||||
[Symbol.iterator]: () => new Object,
|
||||
});
|
36
crates/js-sys/tests/wasm/Iterator.rs
Normal file
36
crates/js-sys/tests/wasm/Iterator.rs
Normal file
@ -0,0 +1,36 @@
|
||||
use js_sys::*;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen_test::*;
|
||||
|
||||
#[wasm_bindgen(module = "tests/wasm/Iterator.js")]
|
||||
extern "C" {
|
||||
fn get_iterable() -> JsValue;
|
||||
|
||||
fn get_not_iterable() -> JsValue;
|
||||
|
||||
fn get_symbol_iterator_throws() -> JsValue;
|
||||
|
||||
fn get_symbol_iterator_not_function() -> JsValue;
|
||||
|
||||
fn get_symbol_iterator_returns_not_object() -> JsValue;
|
||||
|
||||
fn get_symbol_iterator_returns_object_without_next() -> JsValue;
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn try_iter_handles_iteration_protocol() {
|
||||
assert_eq!(
|
||||
try_iter(&get_iterable())
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.map(|x| x.unwrap().as_string().unwrap())
|
||||
.collect::<Vec<_>>(),
|
||||
vec!["one", "two", "three"]
|
||||
);
|
||||
|
||||
assert!(try_iter(&get_not_iterable()).unwrap().is_none());
|
||||
assert!(try_iter(&get_symbol_iterator_throws()).is_err());
|
||||
assert!(try_iter(&get_symbol_iterator_not_function()).unwrap().is_none());
|
||||
assert!(try_iter(&get_symbol_iterator_returns_not_object()).unwrap().is_none());
|
||||
assert!(try_iter(&get_symbol_iterator_returns_object_without_next()).unwrap().is_none());
|
||||
}
|
@ -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());
|
||||
|
@ -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");
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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"); },
|
||||
});
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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>());
|
||||
|
@ -19,6 +19,7 @@ pub mod EvalError;
|
||||
pub mod Function;
|
||||
pub mod Generator;
|
||||
pub mod Intl;
|
||||
pub mod Iterator;
|
||||
pub mod JsString;
|
||||
pub mod JSON;
|
||||
pub mod Map;
|
||||
|
@ -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));
|
||||
|
@ -30,6 +30,7 @@
|
||||
- [Passing Rust Closures to JS](./reference/passing-rust-closures-to-js.md)
|
||||
- [Receiving JS Closures in Rust](./reference/receiving-js-closures-in-rust.md)
|
||||
- [`Promise`s and `Future`s](./reference/js-promises-and-rust-futures.md)
|
||||
- [Iterating over JS Values](./reference/iterating-over-js-values.md)
|
||||
- [No ES Modules](./reference/no-esm.md)
|
||||
- [Arbitrary Data with Serde](./reference/arbitrary-data-with-serde.md)
|
||||
- [Accessing Properties of Untyped JS Values](./reference/accessing-properties-of-untyped-js-values.md)
|
||||
|
@ -18,7 +18,7 @@ A function that returns the value of a property.
|
||||
#### Rust Usage
|
||||
|
||||
```rust
|
||||
let value = js_sys::Reflect::get(&target, &property_key);
|
||||
let value = js_sys::Reflect::get(&target, &property_key)?;
|
||||
```
|
||||
|
||||
#### JavaScript Equivalent
|
||||
@ -37,7 +37,7 @@ the update was successful.
|
||||
#### Rust Usage
|
||||
|
||||
```rust
|
||||
js_sys::Reflect::set(&target, &property_key, &value);
|
||||
js_sys::Reflect::set(&target, &property_key, &value)?;
|
||||
```
|
||||
|
||||
#### JavaScript Equivalent
|
||||
@ -56,7 +56,7 @@ an own or inherited property exists on the target.
|
||||
#### Rust Usage
|
||||
|
||||
```rust
|
||||
if js_sys::Reflect::has(&target, &property_key) {
|
||||
if js_sys::Reflect::has(&target, &property_key)? {
|
||||
// ...
|
||||
} else {
|
||||
// ...
|
||||
|
95
guide/src/reference/iterating-over-js-values.md
Normal file
95
guide/src/reference/iterating-over-js-values.md
Normal file
@ -0,0 +1,95 @@
|
||||
# Iterating over JavaScript Values
|
||||
|
||||
## Methods That Return `js_sys::Iterator`
|
||||
|
||||
Some JavaScript collections have methods for iterating over their values or
|
||||
keys:
|
||||
|
||||
* [`Map::values`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Map.html#method.values)
|
||||
* [`Set::keys`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Set.html#method.keys)
|
||||
* etc...
|
||||
|
||||
These methods return
|
||||
[`js_sys::Iterator`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Iterator.html),
|
||||
which is the Rust representation of a JavaScript object that has a `next` method
|
||||
that either returns the next item in the iteration, notes that iteration has
|
||||
completed, or throws an error. That is, `js_sys::Iterator` represents an object
|
||||
that implements [the duck-typed JavaScript iteration
|
||||
protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols).
|
||||
|
||||
`js_sys::Iterator` can be converted into a Rust iterator either by reference
|
||||
(into
|
||||
[`js_sys::Iter<'a>`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Iter.html))
|
||||
or by value (into
|
||||
[`js_sys::IntoIter`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.IntoIter.html)). The
|
||||
Rust iterator will yield items of type `Result<JsValue>`. If it yields an
|
||||
`Ok(...)`, then the JS iterator protocol returned an element. If it yields an
|
||||
`Err(...)`, then the JS iterator protocol threw an exception.
|
||||
|
||||
```rust
|
||||
extern crate js_sys;
|
||||
extern crate wasm_bindgen;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn count_strings_in_set(set: &js_sys::Set) -> u32 {
|
||||
let mut count = 0;
|
||||
|
||||
// Call `keys` to get an iterator over the set's elements. Because this is
|
||||
// in a `for ... in ...` loop, Rust will automatically call its
|
||||
// `IntoIterator` trait implementation to convert it into a Rust iterator.
|
||||
for x in set.keys() {
|
||||
// We know the built-in iterator for set elements won't throw
|
||||
// exceptions, so just unwrap the element. If this was an untrusted
|
||||
// iterator, we might want to explicitly handle the case where it throws
|
||||
// an exception instead of returning a `{ value, done }` object.
|
||||
let x = x.unwrap();
|
||||
|
||||
// If `x` is a string, increment our count of strings in the set!
|
||||
if x.is_string() {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
count
|
||||
}
|
||||
```
|
||||
|
||||
## Iterating Over <u>Any</u> JavaScript Object that Implements the Iterator Protocol
|
||||
|
||||
You could manually test for whether an object implements JS's duck-typed
|
||||
iterator protocol, and if so, convert it into a `js_sys::Iterator` that you can
|
||||
finally iterate over. You don't need to do this by-hand, however, since we
|
||||
bundled this up as [the `js_sys::try_iter`
|
||||
function!](https://rustwasm.github.io/wasm-bindgen/api/js_sys/fn.try_iter.html)
|
||||
|
||||
For example, we can write a function that collects the numbers from any JS
|
||||
iterable and returns them as an `Array`:
|
||||
|
||||
```rust
|
||||
extern crate js_sys;
|
||||
extern crate wasm_bindgen;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn collect_numbers(some_iterable: &JsValue) -> Result<js_sys::Array, JsValue> {
|
||||
let nums = js_sys::Array::new();
|
||||
|
||||
let iterator = match js_sys::try_iter(some_iterable)?.ok_or_else(|| {
|
||||
"need to pass iterable JS values!".into()
|
||||
})?;
|
||||
|
||||
for x in iterator {
|
||||
// If the iterator's `next` method throws an error, propagate it
|
||||
// up to the caller.
|
||||
let x = x?;
|
||||
|
||||
// If `x` is a number, add it to our array of numbers!
|
||||
if x.is_f64() {
|
||||
nums.push(&x);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(nums)
|
||||
}
|
||||
```
|
Loading…
x
Reference in New Issue
Block a user