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