1 | //! Runtime support for the `wasm-bindgen` tool |
2 | //! |
3 | //! This crate contains the runtime support necessary for `wasm-bindgen` the |
4 | //! attribute and tool. Crates pull in the `#[wasm_bindgen]` attribute through |
5 | //! this crate and this crate also provides JS bindings through the `JsValue` |
6 | //! interface. |
7 | |
8 | #![no_std ] |
9 | #![allow (coherence_leak_check)] |
10 | #![doc (html_root_url = "https://docs.rs/wasm-bindgen/0.2" )] |
11 | |
12 | use core::convert::TryFrom; |
13 | use core::fmt; |
14 | use core::marker; |
15 | use core::mem; |
16 | use core::ops::{ |
17 | Add, BitAnd, BitOr, BitXor, Deref, DerefMut, Div, Mul, Neg, Not, Rem, Shl, Shr, Sub, |
18 | }; |
19 | use core::u32; |
20 | |
21 | use crate::convert::{FromWasmAbi, TryFromJsValue, WasmRet, WasmSlice}; |
22 | |
23 | macro_rules! if_std { |
24 | ($($i:item)*) => ($( |
25 | #[cfg(feature = "std" )] $i |
26 | )*) |
27 | } |
28 | |
29 | macro_rules! externs { |
30 | ($(#[$attr:meta])* extern "C" { $(fn $name:ident($($args:tt)*) -> $ret:ty;)* }) => ( |
31 | #[cfg(all(target_arch = "wasm32" , not(any(target_os = "emscripten" , target_os = "wasi" ))))] |
32 | $(#[$attr])* |
33 | extern "C" { |
34 | $(fn $name($($args)*) -> $ret;)* |
35 | } |
36 | |
37 | $( |
38 | #[cfg(not(all(target_arch = "wasm32" , not(any(target_os = "emscripten" , target_os = "wasi" )))))] |
39 | #[allow(unused_variables)] |
40 | unsafe extern fn $name($($args)*) -> $ret { |
41 | panic!("function not implemented on non-wasm32 targets" ) |
42 | } |
43 | )* |
44 | ) |
45 | } |
46 | |
47 | /// A module which is typically glob imported. |
48 | /// |
49 | /// ``` |
50 | /// use wasm_bindgen::prelude::*; |
51 | /// ``` |
52 | pub mod prelude { |
53 | pub use crate::JsCast; |
54 | pub use crate::JsValue; |
55 | pub use crate::UnwrapThrowExt; |
56 | #[doc (hidden)] |
57 | pub use wasm_bindgen_macro::__wasm_bindgen_class_marker; |
58 | pub use wasm_bindgen_macro::wasm_bindgen; |
59 | |
60 | if_std! { |
61 | pub use crate::closure::Closure; |
62 | } |
63 | |
64 | pub use crate::JsError; |
65 | } |
66 | |
67 | pub use wasm_bindgen_macro::link_to; |
68 | |
69 | pub mod convert; |
70 | pub mod describe; |
71 | |
72 | mod cast; |
73 | pub use crate::cast::{JsCast, JsObject}; |
74 | |
75 | if_std! { |
76 | extern crate std; |
77 | use std::prelude::v1::*; |
78 | pub mod closure; |
79 | mod externref; |
80 | |
81 | mod cache; |
82 | pub use cache::intern::{intern, unintern}; |
83 | } |
84 | |
85 | /// Representation of an object owned by JS. |
86 | /// |
87 | /// A `JsValue` doesn't actually live in Rust right now but actually in a table |
88 | /// owned by the `wasm-bindgen` generated JS glue code. Eventually the ownership |
89 | /// will transfer into wasm directly and this will likely become more efficient, |
90 | /// but for now it may be slightly slow. |
91 | pub struct JsValue { |
92 | idx: u32, |
93 | _marker: marker::PhantomData<*mut u8>, // not at all threadsafe |
94 | } |
95 | |
96 | const JSIDX_OFFSET: u32 = 128; // keep in sync with js/mod.rs |
97 | const JSIDX_UNDEFINED: u32 = JSIDX_OFFSET; |
98 | const JSIDX_NULL: u32 = JSIDX_OFFSET + 1; |
99 | const JSIDX_TRUE: u32 = JSIDX_OFFSET + 2; |
100 | const JSIDX_FALSE: u32 = JSIDX_OFFSET + 3; |
101 | const JSIDX_RESERVED: u32 = JSIDX_OFFSET + 4; |
102 | |
103 | impl JsValue { |
104 | /// The `null` JS value constant. |
105 | pub const NULL: JsValue = JsValue::_new(JSIDX_NULL); |
106 | |
107 | /// The `undefined` JS value constant. |
108 | pub const UNDEFINED: JsValue = JsValue::_new(JSIDX_UNDEFINED); |
109 | |
110 | /// The `true` JS value constant. |
111 | pub const TRUE: JsValue = JsValue::_new(JSIDX_TRUE); |
112 | |
113 | /// The `false` JS value constant. |
114 | pub const FALSE: JsValue = JsValue::_new(JSIDX_FALSE); |
115 | |
116 | #[inline ] |
117 | const fn _new(idx: u32) -> JsValue { |
118 | JsValue { |
119 | idx, |
120 | _marker: marker::PhantomData, |
121 | } |
122 | } |
123 | |
124 | /// Creates a new JS value which is a string. |
125 | /// |
126 | /// The utf-8 string provided is copied to the JS heap and the string will |
127 | /// be owned by the JS garbage collector. |
128 | #[allow (clippy::should_implement_trait)] // cannot fix without breaking change |
129 | #[inline ] |
130 | pub fn from_str(s: &str) -> JsValue { |
131 | unsafe { JsValue::_new(__wbindgen_string_new(s.as_ptr(), s.len())) } |
132 | } |
133 | |
134 | /// Creates a new JS value which is a number. |
135 | /// |
136 | /// This function creates a JS value representing a number (a heap |
137 | /// allocated number) and returns a handle to the JS version of it. |
138 | #[inline ] |
139 | pub fn from_f64(n: f64) -> JsValue { |
140 | unsafe { JsValue::_new(__wbindgen_number_new(n)) } |
141 | } |
142 | |
143 | /// Creates a new JS value which is a bigint from a string representing a number. |
144 | /// |
145 | /// This function creates a JS value representing a bigint (a heap |
146 | /// allocated large integer) and returns a handle to the JS version of it. |
147 | #[inline ] |
148 | pub fn bigint_from_str(s: &str) -> JsValue { |
149 | unsafe { JsValue::_new(__wbindgen_bigint_from_str(s.as_ptr(), s.len())) } |
150 | } |
151 | |
152 | /// Creates a new JS value which is a boolean. |
153 | /// |
154 | /// This function creates a JS object representing a boolean (a heap |
155 | /// allocated boolean) and returns a handle to the JS version of it. |
156 | #[inline ] |
157 | pub const fn from_bool(b: bool) -> JsValue { |
158 | if b { |
159 | JsValue::TRUE |
160 | } else { |
161 | JsValue::FALSE |
162 | } |
163 | } |
164 | |
165 | /// Creates a new JS value representing `undefined`. |
166 | #[inline ] |
167 | pub const fn undefined() -> JsValue { |
168 | JsValue::UNDEFINED |
169 | } |
170 | |
171 | /// Creates a new JS value representing `null`. |
172 | #[inline ] |
173 | pub const fn null() -> JsValue { |
174 | JsValue::NULL |
175 | } |
176 | |
177 | /// Creates a new JS symbol with the optional description specified. |
178 | /// |
179 | /// This function will invoke the `Symbol` constructor in JS and return the |
180 | /// JS object corresponding to the symbol created. |
181 | pub fn symbol(description: Option<&str>) -> JsValue { |
182 | unsafe { |
183 | match description { |
184 | Some(description) => JsValue::_new(__wbindgen_symbol_named_new( |
185 | description.as_ptr(), |
186 | description.len(), |
187 | )), |
188 | None => JsValue::_new(__wbindgen_symbol_anonymous_new()), |
189 | } |
190 | } |
191 | } |
192 | |
193 | /// Creates a new `JsValue` from the JSON serialization of the object `t` |
194 | /// provided. |
195 | /// |
196 | /// **This function is deprecated**, due to [creating a dependency cycle in |
197 | /// some circumstances][dep-cycle-issue]. Use [`serde-wasm-bindgen`] or |
198 | /// [`gloo_utils::format::JsValueSerdeExt`] instead. |
199 | /// |
200 | /// [dep-cycle-issue]: https://github.com/rustwasm/wasm-bindgen/issues/2770 |
201 | /// [`serde-wasm-bindgen`]: https://docs.rs/serde-wasm-bindgen |
202 | /// [`gloo_utils::format::JsValueSerdeExt`]: https://docs.rs/gloo-utils/latest/gloo_utils/format/trait.JsValueSerdeExt.html |
203 | /// |
204 | /// This function will serialize the provided value `t` to a JSON string, |
205 | /// send the JSON string to JS, parse it into a JS object, and then return |
206 | /// a handle to the JS object. This is unlikely to be super speedy so it's |
207 | /// not recommended for large payloads, but it's a nice to have in some |
208 | /// situations! |
209 | /// |
210 | /// Usage of this API requires activating the `serde-serialize` feature of |
211 | /// the `wasm-bindgen` crate. |
212 | /// |
213 | /// # Errors |
214 | /// |
215 | /// Returns any error encountered when serializing `T` into JSON. |
216 | #[cfg (feature = "serde-serialize" )] |
217 | #[deprecated = "causes dependency cycles, use `serde-wasm-bindgen` or `gloo_utils::format::JsValueSerdeExt` instead" ] |
218 | pub fn from_serde<T>(t: &T) -> serde_json::Result<JsValue> |
219 | where |
220 | T: serde::ser::Serialize + ?Sized, |
221 | { |
222 | let s = serde_json::to_string(t)?; |
223 | unsafe { Ok(JsValue::_new(__wbindgen_json_parse(s.as_ptr(), s.len()))) } |
224 | } |
225 | |
226 | /// Invokes `JSON.stringify` on this value and then parses the resulting |
227 | /// JSON into an arbitrary Rust value. |
228 | /// |
229 | /// **This function is deprecated**, due to [creating a dependency cycle in |
230 | /// some circumstances][dep-cycle-issue]. Use [`serde-wasm-bindgen`] or |
231 | /// [`gloo_utils::format::JsValueSerdeExt`] instead. |
232 | /// |
233 | /// [dep-cycle-issue]: https://github.com/rustwasm/wasm-bindgen/issues/2770 |
234 | /// [`serde-wasm-bindgen`]: https://docs.rs/serde-wasm-bindgen |
235 | /// [`gloo_utils::format::JsValueSerdeExt`]: https://docs.rs/gloo-utils/latest/gloo_utils/format/trait.JsValueSerdeExt.html |
236 | /// |
237 | /// This function will first call `JSON.stringify` on the `JsValue` itself. |
238 | /// The resulting string is then passed into Rust which then parses it as |
239 | /// JSON into the resulting value. |
240 | /// |
241 | /// Usage of this API requires activating the `serde-serialize` feature of |
242 | /// the `wasm-bindgen` crate. |
243 | /// |
244 | /// # Errors |
245 | /// |
246 | /// Returns any error encountered when parsing the JSON into a `T`. |
247 | #[cfg (feature = "serde-serialize" )] |
248 | #[deprecated = "causes dependency cycles, use `serde-wasm-bindgen` or `gloo_utils::format::JsValueSerdeExt` instead" ] |
249 | pub fn into_serde<T>(&self) -> serde_json::Result<T> |
250 | where |
251 | T: for<'a> serde::de::Deserialize<'a>, |
252 | { |
253 | unsafe { |
254 | let ret = __wbindgen_json_serialize(self.idx); |
255 | let s = String::from_abi(ret); |
256 | serde_json::from_str(&s) |
257 | } |
258 | } |
259 | |
260 | /// Returns the `f64` value of this JS value if it's an instance of a |
261 | /// number. |
262 | /// |
263 | /// If this JS value is not an instance of a number then this returns |
264 | /// `None`. |
265 | #[inline ] |
266 | pub fn as_f64(&self) -> Option<f64> { |
267 | unsafe { __wbindgen_number_get(self.idx).join() } |
268 | } |
269 | |
270 | /// Tests whether this JS value is a JS string. |
271 | #[inline ] |
272 | pub fn is_string(&self) -> bool { |
273 | unsafe { __wbindgen_is_string(self.idx) == 1 } |
274 | } |
275 | |
276 | /// If this JS value is a string value, this function copies the JS string |
277 | /// value into wasm linear memory, encoded as UTF-8, and returns it as a |
278 | /// Rust `String`. |
279 | /// |
280 | /// To avoid the copying and re-encoding, consider the |
281 | /// `JsString::try_from()` function from [js-sys](https://docs.rs/js-sys) |
282 | /// instead. |
283 | /// |
284 | /// If this JS value is not an instance of a string or if it's not valid |
285 | /// utf-8 then this returns `None`. |
286 | /// |
287 | /// # UTF-16 vs UTF-8 |
288 | /// |
289 | /// JavaScript strings in general are encoded as UTF-16, but Rust strings |
290 | /// are encoded as UTF-8. This can cause the Rust string to look a bit |
291 | /// different than the JS string sometimes. For more details see the |
292 | /// [documentation about the `str` type][caveats] which contains a few |
293 | /// caveats about the encodings. |
294 | /// |
295 | /// [caveats]: https://rustwasm.github.io/docs/wasm-bindgen/reference/types/str.html |
296 | #[cfg (feature = "std" )] |
297 | #[inline ] |
298 | pub fn as_string(&self) -> Option<String> { |
299 | unsafe { FromWasmAbi::from_abi(__wbindgen_string_get(self.idx)) } |
300 | } |
301 | |
302 | /// Returns the `bool` value of this JS value if it's an instance of a |
303 | /// boolean. |
304 | /// |
305 | /// If this JS value is not an instance of a boolean then this returns |
306 | /// `None`. |
307 | #[inline ] |
308 | pub fn as_bool(&self) -> Option<bool> { |
309 | unsafe { |
310 | match __wbindgen_boolean_get(self.idx) { |
311 | 0 => Some(false), |
312 | 1 => Some(true), |
313 | _ => None, |
314 | } |
315 | } |
316 | } |
317 | |
318 | /// Tests whether this JS value is `null` |
319 | #[inline ] |
320 | pub fn is_null(&self) -> bool { |
321 | unsafe { __wbindgen_is_null(self.idx) == 1 } |
322 | } |
323 | |
324 | /// Tests whether this JS value is `undefined` |
325 | #[inline ] |
326 | pub fn is_undefined(&self) -> bool { |
327 | unsafe { __wbindgen_is_undefined(self.idx) == 1 } |
328 | } |
329 | |
330 | /// Tests whether the type of this JS value is `symbol` |
331 | #[inline ] |
332 | pub fn is_symbol(&self) -> bool { |
333 | unsafe { __wbindgen_is_symbol(self.idx) == 1 } |
334 | } |
335 | |
336 | /// Tests whether `typeof self == "object" && self !== null`. |
337 | #[inline ] |
338 | pub fn is_object(&self) -> bool { |
339 | unsafe { __wbindgen_is_object(self.idx) == 1 } |
340 | } |
341 | |
342 | /// Tests whether this JS value is an instance of Array. |
343 | #[inline ] |
344 | pub fn is_array(&self) -> bool { |
345 | unsafe { __wbindgen_is_array(self.idx) == 1 } |
346 | } |
347 | |
348 | /// Tests whether the type of this JS value is `function`. |
349 | #[inline ] |
350 | pub fn is_function(&self) -> bool { |
351 | unsafe { __wbindgen_is_function(self.idx) == 1 } |
352 | } |
353 | |
354 | /// Tests whether the type of this JS value is `bigint`. |
355 | #[inline ] |
356 | pub fn is_bigint(&self) -> bool { |
357 | unsafe { __wbindgen_is_bigint(self.idx) == 1 } |
358 | } |
359 | |
360 | /// Applies the unary `typeof` JS operator on a `JsValue`. |
361 | /// |
362 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof) |
363 | #[inline ] |
364 | pub fn js_typeof(&self) -> JsValue { |
365 | unsafe { JsValue::_new(__wbindgen_typeof(self.idx)) } |
366 | } |
367 | |
368 | /// Applies the binary `in` JS operator on the two `JsValue`s. |
369 | /// |
370 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in) |
371 | #[inline ] |
372 | pub fn js_in(&self, obj: &JsValue) -> bool { |
373 | unsafe { __wbindgen_in(self.idx, obj.idx) == 1 } |
374 | } |
375 | |
376 | /// Tests whether the value is ["truthy"]. |
377 | /// |
378 | /// ["truthy"]: https://developer.mozilla.org/en-US/docs/Glossary/Truthy |
379 | #[inline ] |
380 | pub fn is_truthy(&self) -> bool { |
381 | !self.is_falsy() |
382 | } |
383 | |
384 | /// Tests whether the value is ["falsy"]. |
385 | /// |
386 | /// ["falsy"]: https://developer.mozilla.org/en-US/docs/Glossary/Falsy |
387 | #[inline ] |
388 | pub fn is_falsy(&self) -> bool { |
389 | unsafe { __wbindgen_is_falsy(self.idx) == 1 } |
390 | } |
391 | |
392 | /// Get a string representation of the JavaScript object for debugging. |
393 | #[cfg (feature = "std" )] |
394 | fn as_debug_string(&self) -> String { |
395 | unsafe { |
396 | let mut ret = [0; 2]; |
397 | __wbindgen_debug_string(&mut ret, self.idx); |
398 | let data = Vec::from_raw_parts(ret[0] as *mut u8, ret[1], ret[1]); |
399 | String::from_utf8_unchecked(data) |
400 | } |
401 | } |
402 | |
403 | /// Compare two `JsValue`s for equality, using the `==` operator in JS. |
404 | /// |
405 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Equality) |
406 | #[inline ] |
407 | pub fn loose_eq(&self, other: &Self) -> bool { |
408 | unsafe { __wbindgen_jsval_loose_eq(self.idx, other.idx) != 0 } |
409 | } |
410 | |
411 | /// Applies the unary `~` JS operator on a `JsValue`. |
412 | /// |
413 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_NOT) |
414 | #[inline ] |
415 | pub fn bit_not(&self) -> JsValue { |
416 | unsafe { JsValue::_new(__wbindgen_bit_not(self.idx)) } |
417 | } |
418 | |
419 | /// Applies the binary `>>>` JS operator on the two `JsValue`s. |
420 | /// |
421 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unsigned_right_shift) |
422 | #[inline ] |
423 | pub fn unsigned_shr(&self, rhs: &Self) -> u32 { |
424 | unsafe { __wbindgen_unsigned_shr(self.idx, rhs.idx) } |
425 | } |
426 | |
427 | /// Applies the binary `/` JS operator on two `JsValue`s, catching and returning any `RangeError` thrown. |
428 | /// |
429 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Division) |
430 | #[inline ] |
431 | pub fn checked_div(&self, rhs: &Self) -> Self { |
432 | unsafe { JsValue::_new(__wbindgen_checked_div(self.idx, rhs.idx)) } |
433 | } |
434 | |
435 | /// Applies the binary `**` JS operator on the two `JsValue`s. |
436 | /// |
437 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Exponentiation) |
438 | #[inline ] |
439 | pub fn pow(&self, rhs: &Self) -> Self { |
440 | unsafe { JsValue::_new(__wbindgen_pow(self.idx, rhs.idx)) } |
441 | } |
442 | |
443 | /// Applies the binary `<` JS operator on the two `JsValue`s. |
444 | /// |
445 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Less_than) |
446 | #[inline ] |
447 | pub fn lt(&self, other: &Self) -> bool { |
448 | unsafe { __wbindgen_lt(self.idx, other.idx) == 1 } |
449 | } |
450 | |
451 | /// Applies the binary `<=` JS operator on the two `JsValue`s. |
452 | /// |
453 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Less_than_or_equal) |
454 | #[inline ] |
455 | pub fn le(&self, other: &Self) -> bool { |
456 | unsafe { __wbindgen_le(self.idx, other.idx) == 1 } |
457 | } |
458 | |
459 | /// Applies the binary `>=` JS operator on the two `JsValue`s. |
460 | /// |
461 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Greater_than_or_equal) |
462 | #[inline ] |
463 | pub fn ge(&self, other: &Self) -> bool { |
464 | unsafe { __wbindgen_ge(self.idx, other.idx) == 1 } |
465 | } |
466 | |
467 | /// Applies the binary `>` JS operator on the two `JsValue`s. |
468 | /// |
469 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Greater_than) |
470 | #[inline ] |
471 | pub fn gt(&self, other: &Self) -> bool { |
472 | unsafe { __wbindgen_gt(self.idx, other.idx) == 1 } |
473 | } |
474 | |
475 | /// Applies the unary `+` JS operator on a `JsValue`. Can throw. |
476 | /// |
477 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unary_plus) |
478 | #[inline ] |
479 | pub fn unchecked_into_f64(&self) -> f64 { |
480 | unsafe { __wbindgen_as_number(self.idx) } |
481 | } |
482 | } |
483 | |
484 | impl PartialEq for JsValue { |
485 | /// Compares two `JsValue`s for equality, using the `===` operator in JS. |
486 | /// |
487 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Strict_equality) |
488 | #[inline ] |
489 | fn eq(&self, other: &Self) -> bool { |
490 | unsafe { __wbindgen_jsval_eq(self.idx, b:other.idx) != 0 } |
491 | } |
492 | } |
493 | |
494 | impl PartialEq<bool> for JsValue { |
495 | #[inline ] |
496 | fn eq(&self, other: &bool) -> bool { |
497 | self.as_bool() == Some(*other) |
498 | } |
499 | } |
500 | |
501 | impl PartialEq<str> for JsValue { |
502 | #[inline ] |
503 | fn eq(&self, other: &str) -> bool { |
504 | *self == JsValue::from_str(other) |
505 | } |
506 | } |
507 | |
508 | impl<'a> PartialEq<&'a str> for JsValue { |
509 | #[inline ] |
510 | fn eq(&self, other: &&'a str) -> bool { |
511 | <JsValue as PartialEq<str>>::eq(self, other) |
512 | } |
513 | } |
514 | |
515 | if_std! { |
516 | impl PartialEq<String> for JsValue { |
517 | #[inline ] |
518 | fn eq(&self, other: &String) -> bool { |
519 | <JsValue as PartialEq<str>>::eq(self, other) |
520 | } |
521 | } |
522 | impl<'a> PartialEq<&'a String> for JsValue { |
523 | #[inline ] |
524 | fn eq(&self, other: &&'a String) -> bool { |
525 | <JsValue as PartialEq<str>>::eq(self, other) |
526 | } |
527 | } |
528 | } |
529 | |
530 | macro_rules! forward_deref_unop { |
531 | (impl $imp:ident, $method:ident for $t:ty) => { |
532 | impl $imp for $t { |
533 | type Output = <&'static $t as $imp>::Output; |
534 | |
535 | #[inline] |
536 | fn $method(self) -> <&'static $t as $imp>::Output { |
537 | $imp::$method(&self) |
538 | } |
539 | } |
540 | }; |
541 | } |
542 | |
543 | macro_rules! forward_deref_binop { |
544 | (impl $imp:ident, $method:ident for $t:ty) => { |
545 | impl<'a> $imp<$t> for &'a $t { |
546 | type Output = <&'static $t as $imp<&'static $t>>::Output; |
547 | |
548 | #[inline] |
549 | fn $method(self, other: $t) -> <&'static $t as $imp<&'static $t>>::Output { |
550 | $imp::$method(self, &other) |
551 | } |
552 | } |
553 | |
554 | impl $imp<&$t> for $t { |
555 | type Output = <&'static $t as $imp<&'static $t>>::Output; |
556 | |
557 | #[inline] |
558 | fn $method(self, other: &$t) -> <&'static $t as $imp<&'static $t>>::Output { |
559 | $imp::$method(&self, other) |
560 | } |
561 | } |
562 | |
563 | impl $imp<$t> for $t { |
564 | type Output = <&'static $t as $imp<&'static $t>>::Output; |
565 | |
566 | #[inline] |
567 | fn $method(self, other: $t) -> <&'static $t as $imp<&'static $t>>::Output { |
568 | $imp::$method(&self, &other) |
569 | } |
570 | } |
571 | }; |
572 | } |
573 | |
574 | impl Not for &JsValue { |
575 | type Output = bool; |
576 | |
577 | /// Applies the `!` JS operator on a `JsValue`. |
578 | /// |
579 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_NOT) |
580 | #[inline ] |
581 | fn not(self) -> Self::Output { |
582 | JsValue::is_falsy(self) |
583 | } |
584 | } |
585 | |
586 | forward_deref_unop!(impl Not, not for JsValue); |
587 | |
588 | impl TryFrom<JsValue> for f64 { |
589 | type Error = JsValue; |
590 | |
591 | /// Applies the unary `+` JS operator on a `JsValue`. |
592 | /// Returns the numeric result on success, or the JS error value on error. |
593 | /// |
594 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unary_plus) |
595 | #[inline ] |
596 | fn try_from(val: JsValue) -> Result<Self, Self::Error> { |
597 | f64::try_from(&val) |
598 | } |
599 | } |
600 | |
601 | impl TryFrom<&JsValue> for f64 { |
602 | type Error = JsValue; |
603 | |
604 | /// Applies the unary `+` JS operator on a `JsValue`. |
605 | /// Returns the numeric result on success, or the JS error value on error. |
606 | /// |
607 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unary_plus) |
608 | #[inline ] |
609 | fn try_from(val: &JsValue) -> Result<Self, Self::Error> { |
610 | let jsval: JsValue = unsafe { JsValue::_new(idx:__wbindgen_try_into_number(val.idx)) }; |
611 | match jsval.as_f64() { |
612 | Some(num: f64) => Ok(num), |
613 | None => Err(jsval), |
614 | } |
615 | } |
616 | } |
617 | |
618 | impl Neg for &JsValue { |
619 | type Output = JsValue; |
620 | |
621 | /// Applies the unary `-` JS operator on a `JsValue`. |
622 | /// |
623 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unary_negation) |
624 | #[inline ] |
625 | fn neg(self) -> Self::Output { |
626 | unsafe { JsValue::_new(idx:__wbindgen_neg(self.idx)) } |
627 | } |
628 | } |
629 | |
630 | forward_deref_unop!(impl Neg, neg for JsValue); |
631 | |
632 | impl BitAnd for &JsValue { |
633 | type Output = JsValue; |
634 | |
635 | /// Applies the binary `&` JS operator on two `JsValue`s. |
636 | /// |
637 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_AND) |
638 | #[inline ] |
639 | fn bitand(self, rhs: Self) -> Self::Output { |
640 | unsafe { JsValue::_new(idx:__wbindgen_bit_and(self.idx, b:rhs.idx)) } |
641 | } |
642 | } |
643 | |
644 | forward_deref_binop!(impl BitAnd, bitand for JsValue); |
645 | |
646 | impl BitOr for &JsValue { |
647 | type Output = JsValue; |
648 | |
649 | /// Applies the binary `|` JS operator on two `JsValue`s. |
650 | /// |
651 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_OR) |
652 | #[inline ] |
653 | fn bitor(self, rhs: Self) -> Self::Output { |
654 | unsafe { JsValue::_new(idx:__wbindgen_bit_or(self.idx, b:rhs.idx)) } |
655 | } |
656 | } |
657 | |
658 | forward_deref_binop!(impl BitOr, bitor for JsValue); |
659 | |
660 | impl BitXor for &JsValue { |
661 | type Output = JsValue; |
662 | |
663 | /// Applies the binary `^` JS operator on two `JsValue`s. |
664 | /// |
665 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_XOR) |
666 | #[inline ] |
667 | fn bitxor(self, rhs: Self) -> Self::Output { |
668 | unsafe { JsValue::_new(idx:__wbindgen_bit_xor(self.idx, b:rhs.idx)) } |
669 | } |
670 | } |
671 | |
672 | forward_deref_binop!(impl BitXor, bitxor for JsValue); |
673 | |
674 | impl Shl for &JsValue { |
675 | type Output = JsValue; |
676 | |
677 | /// Applies the binary `<<` JS operator on two `JsValue`s. |
678 | /// |
679 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Left_shift) |
680 | #[inline ] |
681 | fn shl(self, rhs: Self) -> Self::Output { |
682 | unsafe { JsValue::_new(idx:__wbindgen_shl(self.idx, b:rhs.idx)) } |
683 | } |
684 | } |
685 | |
686 | forward_deref_binop!(impl Shl, shl for JsValue); |
687 | |
688 | impl Shr for &JsValue { |
689 | type Output = JsValue; |
690 | |
691 | /// Applies the binary `>>` JS operator on two `JsValue`s. |
692 | /// |
693 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Right_shift) |
694 | #[inline ] |
695 | fn shr(self, rhs: Self) -> Self::Output { |
696 | unsafe { JsValue::_new(idx:__wbindgen_shr(self.idx, b:rhs.idx)) } |
697 | } |
698 | } |
699 | |
700 | forward_deref_binop!(impl Shr, shr for JsValue); |
701 | |
702 | impl Add for &JsValue { |
703 | type Output = JsValue; |
704 | |
705 | /// Applies the binary `+` JS operator on two `JsValue`s. |
706 | /// |
707 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Addition) |
708 | #[inline ] |
709 | fn add(self, rhs: Self) -> Self::Output { |
710 | unsafe { JsValue::_new(idx:__wbindgen_add(self.idx, b:rhs.idx)) } |
711 | } |
712 | } |
713 | |
714 | forward_deref_binop!(impl Add, add for JsValue); |
715 | |
716 | impl Sub for &JsValue { |
717 | type Output = JsValue; |
718 | |
719 | /// Applies the binary `-` JS operator on two `JsValue`s. |
720 | /// |
721 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Subtraction) |
722 | #[inline ] |
723 | fn sub(self, rhs: Self) -> Self::Output { |
724 | unsafe { JsValue::_new(idx:__wbindgen_sub(self.idx, b:rhs.idx)) } |
725 | } |
726 | } |
727 | |
728 | forward_deref_binop!(impl Sub, sub for JsValue); |
729 | |
730 | impl Div for &JsValue { |
731 | type Output = JsValue; |
732 | |
733 | /// Applies the binary `/` JS operator on two `JsValue`s. |
734 | /// |
735 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Division) |
736 | #[inline ] |
737 | fn div(self, rhs: Self) -> Self::Output { |
738 | unsafe { JsValue::_new(idx:__wbindgen_div(self.idx, b:rhs.idx)) } |
739 | } |
740 | } |
741 | |
742 | forward_deref_binop!(impl Div, div for JsValue); |
743 | |
744 | impl Mul for &JsValue { |
745 | type Output = JsValue; |
746 | |
747 | /// Applies the binary `*` JS operator on two `JsValue`s. |
748 | /// |
749 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Multiplication) |
750 | #[inline ] |
751 | fn mul(self, rhs: Self) -> Self::Output { |
752 | unsafe { JsValue::_new(idx:__wbindgen_mul(self.idx, b:rhs.idx)) } |
753 | } |
754 | } |
755 | |
756 | forward_deref_binop!(impl Mul, mul for JsValue); |
757 | |
758 | impl Rem for &JsValue { |
759 | type Output = JsValue; |
760 | |
761 | /// Applies the binary `%` JS operator on two `JsValue`s. |
762 | /// |
763 | /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Remainder) |
764 | #[inline ] |
765 | fn rem(self, rhs: Self) -> Self::Output { |
766 | unsafe { JsValue::_new(idx:__wbindgen_rem(self.idx, b:rhs.idx)) } |
767 | } |
768 | } |
769 | |
770 | forward_deref_binop!(impl Rem, rem for JsValue); |
771 | |
772 | impl<'a> From<&'a str> for JsValue { |
773 | #[inline ] |
774 | fn from(s: &'a str) -> JsValue { |
775 | JsValue::from_str(s) |
776 | } |
777 | } |
778 | |
779 | impl<T> From<*mut T> for JsValue { |
780 | #[inline ] |
781 | fn from(s: *mut T) -> JsValue { |
782 | JsValue::from(s as usize) |
783 | } |
784 | } |
785 | |
786 | impl<T> From<*const T> for JsValue { |
787 | #[inline ] |
788 | fn from(s: *const T) -> JsValue { |
789 | JsValue::from(s as usize) |
790 | } |
791 | } |
792 | |
793 | if_std! { |
794 | impl<'a> From<&'a String> for JsValue { |
795 | #[inline ] |
796 | fn from(s: &'a String) -> JsValue { |
797 | JsValue::from_str(s) |
798 | } |
799 | } |
800 | |
801 | impl From<String> for JsValue { |
802 | #[inline ] |
803 | fn from(s: String) -> JsValue { |
804 | JsValue::from_str(&s) |
805 | } |
806 | } |
807 | |
808 | impl TryFrom<JsValue> for String { |
809 | type Error = JsValue; |
810 | |
811 | fn try_from(value: JsValue) -> Result<Self, Self::Error> { |
812 | match value.as_string() { |
813 | Some(s) => Ok(s), |
814 | None => Err(value), |
815 | } |
816 | } |
817 | } |
818 | |
819 | impl TryFromJsValue for String { |
820 | type Error = JsValue; |
821 | |
822 | fn try_from_js_value(value: JsValue) -> Result<Self, Self::Error> { |
823 | match value.as_string() { |
824 | Some(s) => Ok(s), |
825 | None => Err(value), |
826 | } |
827 | } |
828 | } |
829 | } |
830 | |
831 | impl From<bool> for JsValue { |
832 | #[inline ] |
833 | fn from(s: bool) -> JsValue { |
834 | JsValue::from_bool(s) |
835 | } |
836 | } |
837 | |
838 | impl<'a, T> From<&'a T> for JsValue |
839 | where |
840 | T: JsCast, |
841 | { |
842 | #[inline ] |
843 | fn from(s: &'a T) -> JsValue { |
844 | s.as_ref().clone() |
845 | } |
846 | } |
847 | |
848 | impl<T> From<Option<T>> for JsValue |
849 | where |
850 | JsValue: From<T>, |
851 | { |
852 | #[inline ] |
853 | fn from(s: Option<T>) -> JsValue { |
854 | match s { |
855 | Some(s: T) => s.into(), |
856 | None => JsValue::undefined(), |
857 | } |
858 | } |
859 | } |
860 | |
861 | impl JsCast for JsValue { |
862 | // everything is a `JsValue`! |
863 | #[inline ] |
864 | fn instanceof(_val: &JsValue) -> bool { |
865 | true |
866 | } |
867 | #[inline ] |
868 | fn unchecked_from_js(val: JsValue) -> Self { |
869 | val |
870 | } |
871 | #[inline ] |
872 | fn unchecked_from_js_ref(val: &JsValue) -> &Self { |
873 | val |
874 | } |
875 | } |
876 | |
877 | impl AsRef<JsValue> for JsValue { |
878 | #[inline ] |
879 | fn as_ref(&self) -> &JsValue { |
880 | self |
881 | } |
882 | } |
883 | |
884 | macro_rules! numbers { |
885 | ($($n:ident)*) => ($( |
886 | impl PartialEq<$n> for JsValue { |
887 | #[inline] |
888 | fn eq(&self, other: &$n) -> bool { |
889 | self.as_f64() == Some(f64::from(*other)) |
890 | } |
891 | } |
892 | |
893 | impl From<$n> for JsValue { |
894 | #[inline] |
895 | fn from(n: $n) -> JsValue { |
896 | JsValue::from_f64(n.into()) |
897 | } |
898 | } |
899 | )*) |
900 | } |
901 | |
902 | numbers! { i8 u8 i16 u16 i32 u32 f32 f64 } |
903 | |
904 | macro_rules! big_numbers { |
905 | (|$arg:ident|, $($n:ident = $handle:expr,)*) => ($( |
906 | impl PartialEq<$n> for JsValue { |
907 | #[inline] |
908 | fn eq(&self, other: &$n) -> bool { |
909 | self == &JsValue::from(*other) |
910 | } |
911 | } |
912 | |
913 | impl From<$n> for JsValue { |
914 | #[inline] |
915 | fn from($arg: $n) -> JsValue { |
916 | unsafe { JsValue::_new($handle) } |
917 | } |
918 | } |
919 | )*) |
920 | } |
921 | |
922 | fn bigint_get_as_i64(v: &JsValue) -> Option<i64> { |
923 | unsafe { __wbindgen_bigint_get_as_i64(v.idx).join() } |
924 | } |
925 | |
926 | macro_rules! try_from_for_num64 { |
927 | ($ty:ty) => { |
928 | impl TryFrom<JsValue> for $ty { |
929 | type Error = JsValue; |
930 | |
931 | #[inline] |
932 | fn try_from(v: JsValue) -> Result<Self, JsValue> { |
933 | bigint_get_as_i64(&v) |
934 | // Reinterpret bits; ABI-wise this is safe to do and allows us to avoid |
935 | // having separate intrinsics per signed/unsigned types. |
936 | .map(|as_i64| as_i64 as Self) |
937 | // Double-check that we didn't truncate the bigint to 64 bits. |
938 | .filter(|as_self| v == *as_self) |
939 | // Not a bigint or not in range. |
940 | .ok_or(v) |
941 | } |
942 | } |
943 | }; |
944 | } |
945 | |
946 | try_from_for_num64!(i64); |
947 | try_from_for_num64!(u64); |
948 | |
949 | macro_rules! try_from_for_num128 { |
950 | ($ty:ty, $hi_ty:ty) => { |
951 | impl TryFrom<JsValue> for $ty { |
952 | type Error = JsValue; |
953 | |
954 | #[inline] |
955 | fn try_from(v: JsValue) -> Result<Self, JsValue> { |
956 | // Truncate the bigint to 64 bits, this will give us the lower part. |
957 | let lo = match bigint_get_as_i64(&v) { |
958 | // The lower part must be interpreted as unsigned in both i128 and u128. |
959 | Some(lo) => lo as u64, |
960 | // Not a bigint. |
961 | None => return Err(v), |
962 | }; |
963 | // Now we know it's a bigint, so we can safely use `>> 64n` without |
964 | // worrying about a JS exception on type mismatch. |
965 | let hi = v >> JsValue::from(64_u64); |
966 | // The high part is the one we want checked against a 64-bit range. |
967 | // If it fits, then our original number is in the 128-bit range. |
968 | let hi = <$hi_ty>::try_from(hi)?; |
969 | Ok(Self::from(hi) << 64 | Self::from(lo)) |
970 | } |
971 | } |
972 | }; |
973 | } |
974 | |
975 | try_from_for_num128!(i128, i64); |
976 | try_from_for_num128!(u128, u64); |
977 | |
978 | big_numbers! { |
979 | |n|, |
980 | i64 = __wbindgen_bigint_from_i64(n), |
981 | u64 = __wbindgen_bigint_from_u64(n), |
982 | i128 = __wbindgen_bigint_from_i128((n >> 64) as i64, n as u64), |
983 | u128 = __wbindgen_bigint_from_u128((n >> 64) as u64, n as u64), |
984 | } |
985 | |
986 | // `usize` and `isize` have to be treated a bit specially, because we know that |
987 | // they're 32-bit but the compiler conservatively assumes they might be bigger. |
988 | // So, we have to manually forward to the `u32`/`i32` versions. |
989 | impl PartialEq<usize> for JsValue { |
990 | #[inline ] |
991 | fn eq(&self, other: &usize) -> bool { |
992 | *self == (*other as u32) |
993 | } |
994 | } |
995 | |
996 | impl From<usize> for JsValue { |
997 | #[inline ] |
998 | fn from(n: usize) -> Self { |
999 | Self::from(n as u32) |
1000 | } |
1001 | } |
1002 | |
1003 | impl PartialEq<isize> for JsValue { |
1004 | #[inline ] |
1005 | fn eq(&self, other: &isize) -> bool { |
1006 | *self == (*other as i32) |
1007 | } |
1008 | } |
1009 | |
1010 | impl From<isize> for JsValue { |
1011 | #[inline ] |
1012 | fn from(n: isize) -> Self { |
1013 | Self::from(n as i32) |
1014 | } |
1015 | } |
1016 | |
1017 | externs! { |
1018 | #[link (wasm_import_module = "__wbindgen_placeholder__" )] |
1019 | extern "C" { |
1020 | fn __wbindgen_object_clone_ref(idx: u32) -> u32; |
1021 | fn __wbindgen_object_drop_ref(idx: u32) -> (); |
1022 | |
1023 | fn __wbindgen_string_new(ptr: *const u8, len: usize) -> u32; |
1024 | fn __wbindgen_number_new(f: f64) -> u32; |
1025 | fn __wbindgen_bigint_from_str(ptr: *const u8, len: usize) -> u32; |
1026 | fn __wbindgen_bigint_from_i64(n: i64) -> u32; |
1027 | fn __wbindgen_bigint_from_u64(n: u64) -> u32; |
1028 | fn __wbindgen_bigint_from_i128(hi: i64, lo: u64) -> u32; |
1029 | fn __wbindgen_bigint_from_u128(hi: u64, lo: u64) -> u32; |
1030 | fn __wbindgen_symbol_named_new(ptr: *const u8, len: usize) -> u32; |
1031 | fn __wbindgen_symbol_anonymous_new() -> u32; |
1032 | |
1033 | fn __wbindgen_externref_heap_live_count() -> u32; |
1034 | |
1035 | fn __wbindgen_is_null(idx: u32) -> u32; |
1036 | fn __wbindgen_is_undefined(idx: u32) -> u32; |
1037 | fn __wbindgen_is_symbol(idx: u32) -> u32; |
1038 | fn __wbindgen_is_object(idx: u32) -> u32; |
1039 | fn __wbindgen_is_array(idx: u32) -> u32; |
1040 | fn __wbindgen_is_function(idx: u32) -> u32; |
1041 | fn __wbindgen_is_string(idx: u32) -> u32; |
1042 | fn __wbindgen_is_bigint(idx: u32) -> u32; |
1043 | fn __wbindgen_typeof(idx: u32) -> u32; |
1044 | |
1045 | fn __wbindgen_in(prop: u32, obj: u32) -> u32; |
1046 | |
1047 | fn __wbindgen_is_falsy(idx: u32) -> u32; |
1048 | fn __wbindgen_as_number(idx: u32) -> f64; |
1049 | fn __wbindgen_try_into_number(idx: u32) -> u32; |
1050 | fn __wbindgen_neg(idx: u32) -> u32; |
1051 | fn __wbindgen_bit_and(a: u32, b: u32) -> u32; |
1052 | fn __wbindgen_bit_or(a: u32, b: u32) -> u32; |
1053 | fn __wbindgen_bit_xor(a: u32, b: u32) -> u32; |
1054 | fn __wbindgen_bit_not(idx: u32) -> u32; |
1055 | fn __wbindgen_shl(a: u32, b: u32) -> u32; |
1056 | fn __wbindgen_shr(a: u32, b: u32) -> u32; |
1057 | fn __wbindgen_unsigned_shr(a: u32, b: u32) -> u32; |
1058 | fn __wbindgen_add(a: u32, b: u32) -> u32; |
1059 | fn __wbindgen_sub(a: u32, b: u32) -> u32; |
1060 | fn __wbindgen_div(a: u32, b: u32) -> u32; |
1061 | fn __wbindgen_checked_div(a: u32, b: u32) -> u32; |
1062 | fn __wbindgen_mul(a: u32, b: u32) -> u32; |
1063 | fn __wbindgen_rem(a: u32, b: u32) -> u32; |
1064 | fn __wbindgen_pow(a: u32, b: u32) -> u32; |
1065 | fn __wbindgen_lt(a: u32, b: u32) -> u32; |
1066 | fn __wbindgen_le(a: u32, b: u32) -> u32; |
1067 | fn __wbindgen_ge(a: u32, b: u32) -> u32; |
1068 | fn __wbindgen_gt(a: u32, b: u32) -> u32; |
1069 | |
1070 | fn __wbindgen_number_get(idx: u32) -> WasmRet<Option<f64>>; |
1071 | fn __wbindgen_boolean_get(idx: u32) -> u32; |
1072 | fn __wbindgen_string_get(idx: u32) -> WasmSlice; |
1073 | fn __wbindgen_bigint_get_as_i64(idx: u32) -> WasmRet<Option<i64>>; |
1074 | |
1075 | fn __wbindgen_debug_string(ret: *mut [usize; 2], idx: u32) -> (); |
1076 | |
1077 | fn __wbindgen_throw(a: *const u8, b: usize) -> !; |
1078 | fn __wbindgen_rethrow(a: u32) -> !; |
1079 | fn __wbindgen_error_new(a: *const u8, b: usize) -> u32; |
1080 | |
1081 | fn __wbindgen_cb_drop(idx: u32) -> u32; |
1082 | |
1083 | fn __wbindgen_describe(v: u32) -> (); |
1084 | fn __wbindgen_describe_closure(a: u32, b: u32, c: u32) -> u32; |
1085 | |
1086 | fn __wbindgen_json_parse(ptr: *const u8, len: usize) -> u32; |
1087 | fn __wbindgen_json_serialize(idx: u32) -> WasmSlice; |
1088 | fn __wbindgen_jsval_eq(a: u32, b: u32) -> u32; |
1089 | fn __wbindgen_jsval_loose_eq(a: u32, b: u32) -> u32; |
1090 | |
1091 | fn __wbindgen_copy_to_typed_array(ptr: *const u8, len: usize, idx: u32) -> (); |
1092 | |
1093 | fn __wbindgen_not(idx: u32) -> u32; |
1094 | |
1095 | fn __wbindgen_exports() -> u32; |
1096 | fn __wbindgen_memory() -> u32; |
1097 | fn __wbindgen_module() -> u32; |
1098 | fn __wbindgen_function_table() -> u32; |
1099 | } |
1100 | } |
1101 | |
1102 | impl Clone for JsValue { |
1103 | #[inline ] |
1104 | fn clone(&self) -> JsValue { |
1105 | unsafe { |
1106 | let idx: u32 = __wbindgen_object_clone_ref(self.idx); |
1107 | JsValue::_new(idx) |
1108 | } |
1109 | } |
1110 | } |
1111 | |
1112 | #[cfg (feature = "std" )] |
1113 | impl fmt::Debug for JsValue { |
1114 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
1115 | write!(f, "JsValue( {})" , self.as_debug_string()) |
1116 | } |
1117 | } |
1118 | |
1119 | #[cfg (not(feature = "std" ))] |
1120 | impl fmt::Debug for JsValue { |
1121 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
1122 | f.write_str("JsValue" ) |
1123 | } |
1124 | } |
1125 | |
1126 | impl Drop for JsValue { |
1127 | #[inline ] |
1128 | fn drop(&mut self) { |
1129 | unsafe { |
1130 | // We definitely should never drop anything in the stack area |
1131 | debug_assert!(self.idx >= JSIDX_OFFSET, "free of stack slot {}" , self.idx); |
1132 | |
1133 | // Otherwise if we're not dropping one of our reserved values, |
1134 | // actually call the intrinsic. See #1054 for eventually removing |
1135 | // this branch. |
1136 | if self.idx >= JSIDX_RESERVED { |
1137 | __wbindgen_object_drop_ref(self.idx); |
1138 | } |
1139 | } |
1140 | } |
1141 | } |
1142 | |
1143 | impl Default for JsValue { |
1144 | fn default() -> Self { |
1145 | Self::UNDEFINED |
1146 | } |
1147 | } |
1148 | |
1149 | /// Wrapper type for imported statics. |
1150 | /// |
1151 | /// This type is used whenever a `static` is imported from a JS module, for |
1152 | /// example this import: |
1153 | /// |
1154 | /// ```ignore |
1155 | /// #[wasm_bindgen] |
1156 | /// extern "C" { |
1157 | /// static console: JsValue; |
1158 | /// } |
1159 | /// ``` |
1160 | /// |
1161 | /// will generate in Rust a value that looks like: |
1162 | /// |
1163 | /// ```ignore |
1164 | /// static console: JsStatic<JsValue> = ...; |
1165 | /// ``` |
1166 | /// |
1167 | /// This type implements `Deref` to the inner type so it's typically used as if |
1168 | /// it were `&T`. |
1169 | #[cfg (feature = "std" )] |
1170 | pub struct JsStatic<T: 'static> { |
1171 | #[doc (hidden)] |
1172 | pub __inner: &'static std::thread::LocalKey<T>, |
1173 | } |
1174 | |
1175 | #[cfg (feature = "std" )] |
1176 | impl<T: FromWasmAbi + 'static> Deref for JsStatic<T> { |
1177 | type Target = T; |
1178 | fn deref(&self) -> &T { |
1179 | // We know that our tls key is never overwritten after initialization, |
1180 | // so it should be safe (on that axis at least) to hand out a reference |
1181 | // that lives longer than the closure below. |
1182 | // |
1183 | // FIXME: this is not sound if we ever implement thread exit hooks on |
1184 | // wasm, as the pointer will eventually be invalidated but you can get |
1185 | // `&'static T` from this interface. We... probably need to deprecate |
1186 | // and/or remove this interface nowadays. |
1187 | unsafe { self.__inner.with(|ptr: &T| &*(ptr as *const T)) } |
1188 | } |
1189 | } |
1190 | |
1191 | #[cold ] |
1192 | #[inline (never)] |
1193 | #[deprecated (note = "renamed to `throw_str`" )] |
1194 | #[doc (hidden)] |
1195 | pub fn throw(s: &str) -> ! { |
1196 | throw_str(s) |
1197 | } |
1198 | |
1199 | /// Throws a JS exception. |
1200 | /// |
1201 | /// This function will throw a JS exception with the message provided. The |
1202 | /// function will not return as the wasm stack will be popped when the exception |
1203 | /// is thrown. |
1204 | /// |
1205 | /// Note that it is very easy to leak memory with this function because this |
1206 | /// function, unlike `panic!` on other platforms, **will not run destructors**. |
1207 | /// It's recommended to return a `Result` where possible to avoid the worry of |
1208 | /// leaks. |
1209 | #[cold ] |
1210 | #[inline (never)] |
1211 | pub fn throw_str(s: &str) -> ! { |
1212 | unsafe { |
1213 | __wbindgen_throw(a:s.as_ptr(), b:s.len()); |
1214 | } |
1215 | } |
1216 | |
1217 | /// Rethrow a JS exception |
1218 | /// |
1219 | /// This function will throw a JS exception with the JS value provided. This |
1220 | /// function will not return and the wasm stack will be popped until the point |
1221 | /// of entry of wasm itself. |
1222 | /// |
1223 | /// Note that it is very easy to leak memory with this function because this |
1224 | /// function, unlike `panic!` on other platforms, **will not run destructors**. |
1225 | /// It's recommended to return a `Result` where possible to avoid the worry of |
1226 | /// leaks. |
1227 | #[cold ] |
1228 | #[inline (never)] |
1229 | pub fn throw_val(s: JsValue) -> ! { |
1230 | unsafe { |
1231 | let idx: u32 = s.idx; |
1232 | mem::forget(s); |
1233 | __wbindgen_rethrow(idx); |
1234 | } |
1235 | } |
1236 | |
1237 | /// Get the count of live `externref`s / `JsValue`s in `wasm-bindgen`'s heap. |
1238 | /// |
1239 | /// ## Usage |
1240 | /// |
1241 | /// This is intended for debugging and writing tests. |
1242 | /// |
1243 | /// To write a test that asserts against unnecessarily keeping `anref`s / |
1244 | /// `JsValue`s alive: |
1245 | /// |
1246 | /// * get an initial live count, |
1247 | /// |
1248 | /// * perform some series of operations or function calls that should clean up |
1249 | /// after themselves, and should not keep holding onto `externref`s / `JsValue`s |
1250 | /// after completion, |
1251 | /// |
1252 | /// * get the final live count, |
1253 | /// |
1254 | /// * and assert that the initial and final counts are the same. |
1255 | /// |
1256 | /// ## What is Counted |
1257 | /// |
1258 | /// Note that this only counts the *owned* `externref`s / `JsValue`s that end up in |
1259 | /// `wasm-bindgen`'s heap. It does not count borrowed `externref`s / `JsValue`s |
1260 | /// that are on its stack. |
1261 | /// |
1262 | /// For example, these `JsValue`s are accounted for: |
1263 | /// |
1264 | /// ```ignore |
1265 | /// #[wasm_bindgen] |
1266 | /// pub fn my_function(this_is_counted: JsValue) { |
1267 | /// let also_counted = JsValue::from_str("hi" ); |
1268 | /// assert!(wasm_bindgen::externref_heap_live_count() >= 2); |
1269 | /// } |
1270 | /// ``` |
1271 | /// |
1272 | /// While this borrowed `JsValue` ends up on the stack, not the heap, and |
1273 | /// therefore is not accounted for: |
1274 | /// |
1275 | /// ```ignore |
1276 | /// #[wasm_bindgen] |
1277 | /// pub fn my_other_function(this_is_not_counted: &JsValue) { |
1278 | /// // ... |
1279 | /// } |
1280 | /// ``` |
1281 | pub fn externref_heap_live_count() -> u32 { |
1282 | unsafe { __wbindgen_externref_heap_live_count() } |
1283 | } |
1284 | |
1285 | #[doc (hidden)] |
1286 | pub fn anyref_heap_live_count() -> u32 { |
1287 | externref_heap_live_count() |
1288 | } |
1289 | |
1290 | /// An extension trait for `Option<T>` and `Result<T, E>` for unwrapping the `T` |
1291 | /// value, or throwing a JS error if it is not available. |
1292 | /// |
1293 | /// These methods should have a smaller code size footprint than the normal |
1294 | /// `Option::unwrap` and `Option::expect` methods, but they are specific to |
1295 | /// working with wasm and JS. |
1296 | /// |
1297 | /// On non-wasm32 targets, defaults to the normal unwrap/expect calls. |
1298 | /// |
1299 | /// # Example |
1300 | /// |
1301 | /// ``` |
1302 | /// use wasm_bindgen::prelude::*; |
1303 | /// |
1304 | /// // If the value is `Option::Some` or `Result::Ok`, then we just get the |
1305 | /// // contained `T` value. |
1306 | /// let x = Some(42); |
1307 | /// assert_eq!(x.unwrap_throw(), 42); |
1308 | /// |
1309 | /// let y: Option<i32> = None; |
1310 | /// |
1311 | /// // This call would throw an error to JS! |
1312 | /// // |
1313 | /// // y.unwrap_throw() |
1314 | /// // |
1315 | /// // And this call would throw an error to JS with a custom error message! |
1316 | /// // |
1317 | /// // y.expect_throw("woopsie daisy!") |
1318 | /// ``` |
1319 | pub trait UnwrapThrowExt<T>: Sized { |
1320 | /// Unwrap this `Option` or `Result`, but instead of panicking on failure, |
1321 | /// throw an exception to JavaScript. |
1322 | #[cfg_attr (debug_assertions, track_caller)] |
1323 | fn unwrap_throw(self) -> T { |
1324 | if cfg!(all(debug_assertions, feature = "std" )) { |
1325 | let loc = core::panic::Location::caller(); |
1326 | let msg = std::format!( |
1327 | "`unwrap_throw` failed ( {}: {}: {})" , |
1328 | loc.file(), |
1329 | loc.line(), |
1330 | loc.column() |
1331 | ); |
1332 | self.expect_throw(&msg) |
1333 | } else { |
1334 | self.expect_throw("`unwrap_throw` failed" ) |
1335 | } |
1336 | } |
1337 | |
1338 | /// Unwrap this container's `T` value, or throw an error to JS with the |
1339 | /// given message if the `T` value is unavailable (e.g. an `Option<T>` is |
1340 | /// `None`). |
1341 | #[cfg_attr (debug_assertions, track_caller)] |
1342 | fn expect_throw(self, message: &str) -> T; |
1343 | } |
1344 | |
1345 | impl<T> UnwrapThrowExt<T> for Option<T> { |
1346 | #[cfg_attr (debug_assertions, track_caller)] |
1347 | fn expect_throw(self, message: &str) -> T { |
1348 | if cfg!(all( |
1349 | target_arch = "wasm32" , |
1350 | not(any(target_os = "emscripten" , target_os = "wasi" )) |
1351 | )) { |
1352 | match self { |
1353 | Some(val: T) => val, |
1354 | None => throw_str(message), |
1355 | } |
1356 | } else { |
1357 | self.expect(msg:message) |
1358 | } |
1359 | } |
1360 | } |
1361 | |
1362 | impl<T, E> UnwrapThrowExt<T> for Result<T, E> |
1363 | where |
1364 | E: core::fmt::Debug, |
1365 | { |
1366 | #[cfg_attr (debug_assertions, track_caller)] |
1367 | fn expect_throw(self, message: &str) -> T { |
1368 | if cfg!(all( |
1369 | target_arch = "wasm32" , |
1370 | not(any(target_os = "emscripten" , target_os = "wasi" )) |
1371 | )) { |
1372 | match self { |
1373 | Ok(val: T) => val, |
1374 | Err(_) => throw_str(message), |
1375 | } |
1376 | } else { |
1377 | self.expect(msg:message) |
1378 | } |
1379 | } |
1380 | } |
1381 | |
1382 | /// Returns a handle to this Wasm instance's `WebAssembly.Module`. |
1383 | /// This is only available when the final Wasm app is built with |
1384 | /// `--target no-modules` or `--target web`. |
1385 | pub fn module() -> JsValue { |
1386 | unsafe { JsValue::_new(idx:__wbindgen_module()) } |
1387 | } |
1388 | |
1389 | /// Returns a handle to this wasm instance's `WebAssembly.Instance.prototype.exports` |
1390 | pub fn exports() -> JsValue { |
1391 | unsafe { JsValue::_new(idx:__wbindgen_exports()) } |
1392 | } |
1393 | |
1394 | /// Returns a handle to this wasm instance's `WebAssembly.Memory` |
1395 | pub fn memory() -> JsValue { |
1396 | unsafe { JsValue::_new(idx:__wbindgen_memory()) } |
1397 | } |
1398 | |
1399 | /// Returns a handle to this wasm instance's `WebAssembly.Table` which is the |
1400 | /// indirect function table used by Rust |
1401 | pub fn function_table() -> JsValue { |
1402 | unsafe { JsValue::_new(idx:__wbindgen_function_table()) } |
1403 | } |
1404 | |
1405 | #[doc (hidden)] |
1406 | pub mod __rt { |
1407 | use crate::JsValue; |
1408 | use core::borrow::{Borrow, BorrowMut}; |
1409 | use core::cell::{Cell, UnsafeCell}; |
1410 | use core::convert::Infallible; |
1411 | use core::ops::{Deref, DerefMut}; |
1412 | |
1413 | pub extern crate core; |
1414 | #[cfg (feature = "std" )] |
1415 | pub extern crate std; |
1416 | |
1417 | #[macro_export ] |
1418 | #[doc (hidden)] |
1419 | #[cfg (feature = "std" )] |
1420 | macro_rules! __wbindgen_if_not_std { |
1421 | ($($i:item)*) => {}; |
1422 | } |
1423 | |
1424 | #[macro_export ] |
1425 | #[doc (hidden)] |
1426 | #[cfg (not(feature = "std" ))] |
1427 | macro_rules! __wbindgen_if_not_std { |
1428 | ($($i:item)*) => ($($i)*) |
1429 | } |
1430 | |
1431 | #[inline ] |
1432 | pub fn assert_not_null<T>(s: *mut T) { |
1433 | if s.is_null() { |
1434 | throw_null(); |
1435 | } |
1436 | } |
1437 | |
1438 | #[cold ] |
1439 | #[inline (never)] |
1440 | fn throw_null() -> ! { |
1441 | super::throw_str("null pointer passed to rust" ); |
1442 | } |
1443 | |
1444 | /// A vendored version of `RefCell` from the standard library. |
1445 | /// |
1446 | /// Now why, you may ask, would we do that? Surely `RefCell` in libstd is |
1447 | /// quite good. And you're right, it is indeed quite good! Functionally |
1448 | /// nothing more is needed from `RefCell` in the standard library but for |
1449 | /// now this crate is also sort of optimizing for compiled code size. |
1450 | /// |
1451 | /// One major factor to larger binaries in Rust is when a panic happens. |
1452 | /// Panicking in the standard library involves a fair bit of machinery |
1453 | /// (formatting, panic hooks, synchronization, etc). It's all worthwhile if |
1454 | /// you need it but for something like `WasmRefCell` here we don't actually |
1455 | /// need all that! |
1456 | /// |
1457 | /// This is just a wrapper around all Rust objects passed to JS intended to |
1458 | /// guard accidental reentrancy, so this vendored version is intended solely |
1459 | /// to not panic in libstd. Instead when it "panics" it calls our `throw` |
1460 | /// function in this crate which raises an error in JS. |
1461 | pub struct WasmRefCell<T: ?Sized> { |
1462 | borrow: Cell<usize>, |
1463 | value: UnsafeCell<T>, |
1464 | } |
1465 | |
1466 | impl<T: ?Sized> WasmRefCell<T> { |
1467 | pub fn new(value: T) -> WasmRefCell<T> |
1468 | where |
1469 | T: Sized, |
1470 | { |
1471 | WasmRefCell { |
1472 | value: UnsafeCell::new(value), |
1473 | borrow: Cell::new(0), |
1474 | } |
1475 | } |
1476 | |
1477 | pub fn get_mut(&mut self) -> &mut T { |
1478 | unsafe { &mut *self.value.get() } |
1479 | } |
1480 | |
1481 | pub fn borrow(&self) -> Ref<T> { |
1482 | unsafe { |
1483 | if self.borrow.get() == usize::max_value() { |
1484 | borrow_fail(); |
1485 | } |
1486 | self.borrow.set(self.borrow.get() + 1); |
1487 | Ref { |
1488 | value: &*self.value.get(), |
1489 | borrow: &self.borrow, |
1490 | } |
1491 | } |
1492 | } |
1493 | |
1494 | pub fn borrow_mut(&self) -> RefMut<T> { |
1495 | unsafe { |
1496 | if self.borrow.get() != 0 { |
1497 | borrow_fail(); |
1498 | } |
1499 | self.borrow.set(usize::max_value()); |
1500 | RefMut { |
1501 | value: &mut *self.value.get(), |
1502 | borrow: &self.borrow, |
1503 | } |
1504 | } |
1505 | } |
1506 | |
1507 | pub fn into_inner(self) -> T |
1508 | where |
1509 | T: Sized, |
1510 | { |
1511 | self.value.into_inner() |
1512 | } |
1513 | } |
1514 | |
1515 | pub struct Ref<'b, T: ?Sized + 'b> { |
1516 | value: &'b T, |
1517 | borrow: &'b Cell<usize>, |
1518 | } |
1519 | |
1520 | impl<'b, T: ?Sized> Deref for Ref<'b, T> { |
1521 | type Target = T; |
1522 | |
1523 | #[inline ] |
1524 | fn deref(&self) -> &T { |
1525 | self.value |
1526 | } |
1527 | } |
1528 | |
1529 | impl<'b, T: ?Sized> Borrow<T> for Ref<'b, T> { |
1530 | #[inline ] |
1531 | fn borrow(&self) -> &T { |
1532 | self.value |
1533 | } |
1534 | } |
1535 | |
1536 | impl<'b, T: ?Sized> Drop for Ref<'b, T> { |
1537 | fn drop(&mut self) { |
1538 | self.borrow.set(self.borrow.get() - 1); |
1539 | } |
1540 | } |
1541 | |
1542 | pub struct RefMut<'b, T: ?Sized + 'b> { |
1543 | value: &'b mut T, |
1544 | borrow: &'b Cell<usize>, |
1545 | } |
1546 | |
1547 | impl<'b, T: ?Sized> Deref for RefMut<'b, T> { |
1548 | type Target = T; |
1549 | |
1550 | #[inline ] |
1551 | fn deref(&self) -> &T { |
1552 | self.value |
1553 | } |
1554 | } |
1555 | |
1556 | impl<'b, T: ?Sized> DerefMut for RefMut<'b, T> { |
1557 | #[inline ] |
1558 | fn deref_mut(&mut self) -> &mut T { |
1559 | self.value |
1560 | } |
1561 | } |
1562 | |
1563 | impl<'b, T: ?Sized> Borrow<T> for RefMut<'b, T> { |
1564 | #[inline ] |
1565 | fn borrow(&self) -> &T { |
1566 | self.value |
1567 | } |
1568 | } |
1569 | |
1570 | impl<'b, T: ?Sized> BorrowMut<T> for RefMut<'b, T> { |
1571 | #[inline ] |
1572 | fn borrow_mut(&mut self) -> &mut T { |
1573 | self.value |
1574 | } |
1575 | } |
1576 | |
1577 | impl<'b, T: ?Sized> Drop for RefMut<'b, T> { |
1578 | fn drop(&mut self) { |
1579 | self.borrow.set(0); |
1580 | } |
1581 | } |
1582 | |
1583 | fn borrow_fail() -> ! { |
1584 | super::throw_str( |
1585 | "recursive use of an object detected which would lead to \ |
1586 | unsafe aliasing in rust" , |
1587 | ); |
1588 | } |
1589 | |
1590 | if_std! { |
1591 | use std::alloc::{alloc, dealloc, realloc, Layout}; |
1592 | |
1593 | #[no_mangle ] |
1594 | pub extern "C" fn __wbindgen_malloc(size: usize, align: usize) -> *mut u8 { |
1595 | if let Ok(layout) = Layout::from_size_align(size, align) { |
1596 | unsafe { |
1597 | if layout.size() > 0 { |
1598 | let ptr = alloc(layout); |
1599 | if !ptr.is_null() { |
1600 | return ptr |
1601 | } |
1602 | } else { |
1603 | return align as *mut u8 |
1604 | } |
1605 | } |
1606 | } |
1607 | |
1608 | malloc_failure(); |
1609 | } |
1610 | |
1611 | #[no_mangle ] |
1612 | pub unsafe extern "C" fn __wbindgen_realloc(ptr: *mut u8, old_size: usize, new_size: usize, align: usize) -> *mut u8 { |
1613 | debug_assert!(old_size > 0); |
1614 | debug_assert!(new_size > 0); |
1615 | if let Ok(layout) = Layout::from_size_align(old_size, align) { |
1616 | let ptr = realloc(ptr, layout, new_size); |
1617 | if !ptr.is_null() { |
1618 | return ptr |
1619 | } |
1620 | } |
1621 | malloc_failure(); |
1622 | } |
1623 | |
1624 | #[cold ] |
1625 | fn malloc_failure() -> ! { |
1626 | if cfg!(debug_assertions) { |
1627 | super::throw_str("invalid malloc request" ) |
1628 | } else { |
1629 | std::process::abort(); |
1630 | } |
1631 | } |
1632 | |
1633 | #[no_mangle ] |
1634 | pub unsafe extern "C" fn __wbindgen_free(ptr: *mut u8, size: usize, align: usize) { |
1635 | // This happens for zero-length slices, and in that case `ptr` is |
1636 | // likely bogus so don't actually send this to the system allocator |
1637 | if size == 0 { |
1638 | return |
1639 | } |
1640 | let layout = Layout::from_size_align_unchecked(size, align); |
1641 | dealloc(ptr, layout); |
1642 | } |
1643 | } |
1644 | |
1645 | /// This is a curious function necessary to get wasm-bindgen working today, |
1646 | /// and it's a bit of an unfortunate hack. |
1647 | /// |
1648 | /// The general problem is that somehow we need the above two symbols to |
1649 | /// exist in the final output binary (__wbindgen_malloc and |
1650 | /// __wbindgen_free). These symbols may be called by JS for various |
1651 | /// bindings, so we for sure need to make sure they're exported. |
1652 | /// |
1653 | /// The problem arises, though, when what if no Rust code uses the symbols? |
1654 | /// For all intents and purposes it looks to LLVM and the linker like the |
1655 | /// above two symbols are dead code, so they're completely discarded! |
1656 | /// |
1657 | /// Specifically what happens is this: |
1658 | /// |
1659 | /// * The above two symbols are generated into some object file inside of |
1660 | /// libwasm_bindgen.rlib |
1661 | /// * The linker, LLD, will not load this object file unless *some* symbol |
1662 | /// is loaded from the object. In this case, if the Rust code never calls |
1663 | /// __wbindgen_malloc or __wbindgen_free then the symbols never get linked |
1664 | /// in. |
1665 | /// * Later when `wasm-bindgen` attempts to use the symbols they don't |
1666 | /// exist, causing an error. |
1667 | /// |
1668 | /// This function is a weird hack for this problem. We inject a call to this |
1669 | /// function in all generated code. Usage of this function should then |
1670 | /// ensure that the above two intrinsics are translated. |
1671 | /// |
1672 | /// Due to how rustc creates object files this function (and anything inside |
1673 | /// it) will be placed into the same object file as the two intrinsics |
1674 | /// above. That means if this function is called and referenced we'll pull |
1675 | /// in the object file and link the intrinsics. |
1676 | /// |
1677 | /// Ideas for how to improve this are most welcome! |
1678 | pub fn link_mem_intrinsics() { |
1679 | crate::externref::link_intrinsics(); |
1680 | } |
1681 | |
1682 | static mut GLOBAL_EXNDATA: [u32; 2] = [0; 2]; |
1683 | |
1684 | #[no_mangle ] |
1685 | pub unsafe extern "C" fn __wbindgen_exn_store(idx: u32) { |
1686 | debug_assert_eq!(GLOBAL_EXNDATA[0], 0); |
1687 | GLOBAL_EXNDATA[0] = 1; |
1688 | GLOBAL_EXNDATA[1] = idx; |
1689 | } |
1690 | |
1691 | pub fn take_last_exception() -> Result<(), super::JsValue> { |
1692 | unsafe { |
1693 | let ret = if GLOBAL_EXNDATA[0] == 1 { |
1694 | Err(super::JsValue::_new(GLOBAL_EXNDATA[1])) |
1695 | } else { |
1696 | Ok(()) |
1697 | }; |
1698 | GLOBAL_EXNDATA[0] = 0; |
1699 | GLOBAL_EXNDATA[1] = 0; |
1700 | ret |
1701 | } |
1702 | } |
1703 | |
1704 | /// An internal helper trait for usage in `#[wasm_bindgen]` on `async` |
1705 | /// functions to convert the return value of the function to |
1706 | /// `Result<JsValue, JsValue>` which is what we'll return to JS (where an |
1707 | /// error is a failed future). |
1708 | pub trait IntoJsResult { |
1709 | fn into_js_result(self) -> Result<JsValue, JsValue>; |
1710 | } |
1711 | |
1712 | impl IntoJsResult for () { |
1713 | fn into_js_result(self) -> Result<JsValue, JsValue> { |
1714 | Ok(JsValue::undefined()) |
1715 | } |
1716 | } |
1717 | |
1718 | impl<T: Into<JsValue>> IntoJsResult for T { |
1719 | fn into_js_result(self) -> Result<JsValue, JsValue> { |
1720 | Ok(self.into()) |
1721 | } |
1722 | } |
1723 | |
1724 | impl<T: Into<JsValue>, E: Into<JsValue>> IntoJsResult for Result<T, E> { |
1725 | fn into_js_result(self) -> Result<JsValue, JsValue> { |
1726 | match self { |
1727 | Ok(e) => Ok(e.into()), |
1728 | Err(e) => Err(e.into()), |
1729 | } |
1730 | } |
1731 | } |
1732 | |
1733 | impl<E: Into<JsValue>> IntoJsResult for Result<(), E> { |
1734 | fn into_js_result(self) -> Result<JsValue, JsValue> { |
1735 | match self { |
1736 | Ok(()) => Ok(JsValue::undefined()), |
1737 | Err(e) => Err(e.into()), |
1738 | } |
1739 | } |
1740 | } |
1741 | |
1742 | /// An internal helper trait for usage in `#[wasm_bindgen(start)]` |
1743 | /// functions to throw the error (if it is `Err`). |
1744 | pub trait Start { |
1745 | fn start(self); |
1746 | } |
1747 | |
1748 | impl Start for () { |
1749 | #[inline ] |
1750 | fn start(self) {} |
1751 | } |
1752 | |
1753 | impl<E: Into<JsValue>> Start for Result<(), E> { |
1754 | #[inline ] |
1755 | fn start(self) { |
1756 | if let Err(e) = self { |
1757 | crate::throw_val(e.into()); |
1758 | } |
1759 | } |
1760 | } |
1761 | |
1762 | /// An internal helper struct for usage in `#[wasm_bindgen(main)]` |
1763 | /// functions to throw the error (if it is `Err`). |
1764 | pub struct MainWrapper<T>(pub Option<T>); |
1765 | |
1766 | pub trait Main { |
1767 | fn __wasm_bindgen_main(&mut self); |
1768 | } |
1769 | |
1770 | impl Main for &mut &mut MainWrapper<()> { |
1771 | #[inline ] |
1772 | fn __wasm_bindgen_main(&mut self) {} |
1773 | } |
1774 | |
1775 | impl Main for &mut &mut MainWrapper<Infallible> { |
1776 | #[inline ] |
1777 | fn __wasm_bindgen_main(&mut self) {} |
1778 | } |
1779 | |
1780 | impl<E: Into<JsValue>> Main for &mut &mut MainWrapper<Result<(), E>> { |
1781 | #[inline ] |
1782 | fn __wasm_bindgen_main(&mut self) { |
1783 | if let Err(e) = self.0.take().unwrap() { |
1784 | crate::throw_val(e.into()); |
1785 | } |
1786 | } |
1787 | } |
1788 | |
1789 | impl<E: std::fmt::Debug> Main for &mut MainWrapper<Result<(), E>> { |
1790 | #[inline ] |
1791 | fn __wasm_bindgen_main(&mut self) { |
1792 | if let Err(e) = self.0.take().unwrap() { |
1793 | crate::throw_str(&std::format!(" {:?}" , e)); |
1794 | } |
1795 | } |
1796 | } |
1797 | } |
1798 | |
1799 | /// A wrapper type around slices and vectors for binding the `Uint8ClampedArray` |
1800 | /// array in JS. |
1801 | /// |
1802 | /// If you need to invoke a JS API which must take `Uint8ClampedArray` array, |
1803 | /// then you can define it as taking one of these types: |
1804 | /// |
1805 | /// * `Clamped<&[u8]>` |
1806 | /// * `Clamped<&mut [u8]>` |
1807 | /// * `Clamped<Vec<u8>>` |
1808 | /// |
1809 | /// All of these types will show up as `Uint8ClampedArray` in JS and will have |
1810 | /// different forms of ownership in Rust. |
1811 | #[derive (Copy, Clone, PartialEq, Debug, Eq)] |
1812 | pub struct Clamped<T>(pub T); |
1813 | |
1814 | impl<T> Deref for Clamped<T> { |
1815 | type Target = T; |
1816 | |
1817 | fn deref(&self) -> &T { |
1818 | &self.0 |
1819 | } |
1820 | } |
1821 | |
1822 | impl<T> DerefMut for Clamped<T> { |
1823 | fn deref_mut(&mut self) -> &mut T { |
1824 | &mut self.0 |
1825 | } |
1826 | } |
1827 | |
1828 | /// Convenience type for use on exported `fn() -> Result<T, JsError>` functions, where you wish to |
1829 | /// throw a JavaScript `Error` object. |
1830 | /// |
1831 | /// You can get wasm_bindgen to throw basic errors by simply returning |
1832 | /// `Err(JsError::new("message"))` from such a function. |
1833 | /// |
1834 | /// For more complex error handling, `JsError` implements `From<T> where T: std::error::Error` by |
1835 | /// converting it to a string, so you can use it with `?`. Many Rust error types already do this, |
1836 | /// and you can use [`thiserror`](https://crates.io/crates/thiserror) to derive Display |
1837 | /// implementations easily or use any number of boxed error types that implement it already. |
1838 | /// |
1839 | /// |
1840 | /// To allow JavaScript code to catch only your errors, you may wish to add a subclass of `Error` |
1841 | /// in a JS module, and then implement `Into<JsValue>` directly on a type and instantiate that |
1842 | /// subclass. In that case, you would not need `JsError` at all. |
1843 | /// |
1844 | /// ### Basic example |
1845 | /// |
1846 | /// ```rust,no_run |
1847 | /// use wasm_bindgen::prelude::*; |
1848 | /// |
1849 | /// #[wasm_bindgen] |
1850 | /// pub fn throwing_function() -> Result<(), JsError> { |
1851 | /// Err(JsError::new("message" )) |
1852 | /// } |
1853 | /// ``` |
1854 | /// |
1855 | /// ### Complex Example |
1856 | /// |
1857 | /// ```rust,no_run |
1858 | /// use wasm_bindgen::prelude::*; |
1859 | /// |
1860 | /// #[derive(Debug, Clone)] |
1861 | /// enum MyErrorType { |
1862 | /// SomeError, |
1863 | /// } |
1864 | /// |
1865 | /// use core::fmt; |
1866 | /// impl std::error::Error for MyErrorType {} |
1867 | /// impl fmt::Display for MyErrorType { |
1868 | /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1869 | /// write!(f, "display implementation becomes the error message" ) |
1870 | /// } |
1871 | /// } |
1872 | /// |
1873 | /// fn internal_api() -> Result<(), MyErrorType> { |
1874 | /// Err(MyErrorType::SomeError) |
1875 | /// } |
1876 | /// |
1877 | /// #[wasm_bindgen] |
1878 | /// pub fn throwing_function() -> Result<(), JsError> { |
1879 | /// internal_api()?; |
1880 | /// Ok(()) |
1881 | /// } |
1882 | /// |
1883 | /// ``` |
1884 | #[derive (Clone)] |
1885 | pub struct JsError { |
1886 | value: JsValue, |
1887 | } |
1888 | |
1889 | impl JsError { |
1890 | /// Construct a JavaScript `Error` object with a string message |
1891 | #[inline ] |
1892 | pub fn new(s: &str) -> JsError { |
1893 | Self { |
1894 | value: unsafe { JsValue::_new(idx:crate::__wbindgen_error_new(a:s.as_ptr(), b:s.len())) }, |
1895 | } |
1896 | } |
1897 | } |
1898 | |
1899 | if_std! { |
1900 | impl<E> From<E> for JsError |
1901 | where |
1902 | E: std::error::Error, |
1903 | { |
1904 | fn from(error: E) -> Self { |
1905 | JsError::new(&error.to_string()) |
1906 | } |
1907 | } |
1908 | } |
1909 | |
1910 | impl From<JsError> for JsValue { |
1911 | fn from(error: JsError) -> Self { |
1912 | error.value |
1913 | } |
1914 | } |
1915 | |