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