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