From d6d056cdc83a8b336c2e8aaa761a5fe7f82818fa Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Thu, 2 Sep 2021 13:09:20 -0400 Subject: [PATCH] Add math-related intrinsics/functions for `JsValue`s (#2629) * Allow accessing JS math operators from Rust Useful for dealing with JS `BigInt`s * Add `typeof` and `in` methods/intrinsics * Add comparison operators * Remove Object.is intrinsic * Make conversion into f64 faillible * Add `#[inline]`s * Fix methods to make them take references * cargo fmt * Add BigInt to js-sys (no constructor yet) * Remove useless import * Fix UI tests * Add BigInt constructor * Allow catching `to_string` method for BigInt * Fix tests again * Add inlines * Rework PartialEq impl * Implement FromStr for BigInt * Add more inlines * Update formatting * Add more trait impls and feature for integration with `rust-num` * Add `PartialOrd` and `Ord` impls for more types * Cargo fmt * Remove `num-traits` from `wasm-bindgen`, integrate `js-sys` with `rust-num` further * Update Cargo.toml * Update Rust version for CI (to allow proc-macro2 to build again) * Fix link in Markdown * Remove all `rust-num` code from `js-sys` --- azure-pipelines.yml | 4 +- crates/cli-support/src/intrinsic.rs | 78 +++ crates/cli-support/src/js/mod.rs | 130 +++++ crates/js-sys/src/lib.rs | 555 +++++++++++++++++++++- crates/macro/ui-tests/async-errors.stderr | 2 +- src/lib.rs | 420 +++++++++++++++- 6 files changed, 1176 insertions(+), 13 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 8d6ec65f24e..db3496e1f7a 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -93,7 +93,7 @@ jobs: steps: - template: ci/azure-install-rust.yml parameters: - toolchain: nightly-2021-05-09 + toolchain: nightly-2021-09-02 - template: ci/azure-install-node.yml - script: cargo test --target wasm32-unknown-unknown --features nightly --test wasm @@ -210,7 +210,7 @@ jobs: steps: - template: ci/azure-install-rust.yml parameters: - toolchain: nightly-2021-05-09 + toolchain: nightly-2021-09-02 - script: rustup component add rust-src displayName: "install rust-src" - script: | diff --git a/crates/cli-support/src/intrinsic.rs b/crates/cli-support/src/intrinsic.rs index 748e313f950..538e32d1e92 100644 --- a/crates/cli-support/src/intrinsic.rs +++ b/crates/cli-support/src/intrinsic.rs @@ -85,6 +85,9 @@ intrinsics! { #[symbol = "__wbindgen_jsval_eq"] #[signature = fn(ref_externref(), ref_externref()) -> Boolean] JsvalEq, + #[symbol = "__wbindgen_jsval_loose_eq"] + #[signature = fn(ref_externref(), ref_externref()) -> Boolean] + JsvalLooseEq, #[symbol = "__wbindgen_is_function"] #[signature = fn(ref_externref()) -> Boolean] IsFunction, @@ -103,9 +106,81 @@ intrinsics! { #[symbol = "__wbindgen_is_string"] #[signature = fn(ref_externref()) -> Boolean] IsString, + #[symbol = "__wbindgen_is_bigint"] + #[signature = fn(ref_externref()) -> Boolean] + IsBigInt, + #[symbol = "__wbindgen_typeof"] + #[signature = fn(ref_externref()) -> Externref] + Typeof, + #[symbol = "__wbindgen_in"] + #[signature = fn(ref_externref(), ref_externref()) -> Boolean] + In, #[symbol = "__wbindgen_is_falsy"] #[signature = fn(ref_externref()) -> Boolean] IsFalsy, + #[symbol = "__wbindgen_as_number"] + #[signature = fn(ref_externref()) -> F64] + AsNumber, + #[symbol = "__wbindgen_try_into_number"] + #[signature = fn(ref_externref()) -> Externref] + TryIntoNumber, + #[symbol = "__wbindgen_neg"] + #[signature = fn(ref_externref()) -> Externref] + Neg, + #[symbol = "__wbindgen_bit_and"] + #[signature = fn(ref_externref(), ref_externref()) -> Externref] + BitAnd, + #[symbol = "__wbindgen_bit_or"] + #[signature = fn(ref_externref(), ref_externref()) -> Externref] + BitOr, + #[symbol = "__wbindgen_bit_xor"] + #[signature = fn(ref_externref(), ref_externref()) -> Externref] + BitXor, + #[symbol = "__wbindgen_bit_not"] + #[signature = fn(ref_externref()) -> Externref] + BitNot, + #[symbol = "__wbindgen_shl"] + #[signature = fn(ref_externref(), ref_externref()) -> Externref] + Shl, + #[symbol = "__wbindgen_shr"] + #[signature = fn(ref_externref(), ref_externref()) -> Externref] + Shr, + #[symbol = "__wbindgen_unsigned_shr"] + #[signature = fn(ref_externref(), ref_externref()) -> U32] + UnsignedShr, + #[symbol = "__wbindgen_add"] + #[signature = fn(ref_externref(), ref_externref()) -> Externref] + Add, + #[symbol = "__wbindgen_sub"] + #[signature = fn(ref_externref(), ref_externref()) -> Externref] + Sub, + #[symbol = "__wbindgen_div"] + #[signature = fn(ref_externref(), ref_externref()) -> Externref] + Div, + #[symbol = "__wbindgen_checked_div"] + #[signature = fn(ref_externref(), ref_externref()) -> Externref] + CheckedDiv, + #[symbol = "__wbindgen_mul"] + #[signature = fn(ref_externref(), ref_externref()) -> Externref] + Mul, + #[symbol = "__wbindgen_rem"] + #[signature = fn(ref_externref(), ref_externref()) -> Externref] + Rem, + #[symbol = "__wbindgen_pow"] + #[signature = fn(ref_externref(), ref_externref()) -> Externref] + Pow, + #[symbol = "__wbindgen_lt"] + #[signature = fn(ref_externref(), ref_externref()) -> Boolean] + LT, + #[symbol = "__wbindgen_le"] + #[signature = fn(ref_externref(), ref_externref()) -> Boolean] + LE, + #[symbol = "__wbindgen_ge"] + #[signature = fn(ref_externref(), ref_externref()) -> Boolean] + GE, + #[symbol = "__wbindgen_gt"] + #[signature = fn(ref_externref(), ref_externref()) -> Boolean] + GT, #[symbol = "__wbindgen_object_clone_ref"] #[signature = fn(ref_externref()) -> Externref] ObjectCloneRef, @@ -118,6 +193,9 @@ intrinsics! { #[symbol = "__wbindgen_number_new"] #[signature = fn(F64) -> Externref] NumberNew, + #[symbol = "__wbindgen_bigint_new"] + #[signature = fn(ref_string()) -> Externref] + BigIntNew, #[symbol = "__wbindgen_string_new"] #[signature = fn(ref_string()) -> Externref] StringNew, diff --git a/crates/cli-support/src/js/mod.rs b/crates/cli-support/src/js/mod.rs index 1e12d158c43..724aafbef3e 100644 --- a/crates/cli-support/src/js/mod.rs +++ b/crates/cli-support/src/js/mod.rs @@ -2907,6 +2907,11 @@ impl<'a> Context<'a> { format!("{} === {}", args[0], args[1]) } + Intrinsic::JsvalLooseEq => { + assert_eq!(args.len(), 2); + format!("{} == {}", args[0], args[1]) + } + Intrinsic::IsFunction => { assert_eq!(args.len(), 1); format!("typeof({}) === 'function'", args[0]) @@ -2938,11 +2943,131 @@ impl<'a> Context<'a> { format!("typeof({}) === 'string'", args[0]) } + Intrinsic::IsBigInt => { + assert_eq!(args.len(), 1); + format!("typeof({}) === 'bigint'", args[0]) + } + + Intrinsic::Typeof => { + assert_eq!(args.len(), 1); + format!("typeof {}", args[0]) + } + + Intrinsic::In => { + assert_eq!(args.len(), 2); + format!("{} in {}", args[0], args[1]) + } + Intrinsic::IsFalsy => { assert_eq!(args.len(), 1); format!("!{}", args[0]) } + Intrinsic::AsNumber => { + assert_eq!(args.len(), 1); + format!("+{}", args[0]) + } + + Intrinsic::TryIntoNumber => { + assert_eq!(args.len(), 1); + format!("try {{ +{} }} catch(e) {{ e }}", args[0]) + } + + Intrinsic::Neg => { + assert_eq!(args.len(), 1); + format!("-{}", args[0]) + } + + Intrinsic::BitAnd => { + assert_eq!(args.len(), 2); + format!("{} & {}", args[0], args[1]) + } + + Intrinsic::BitOr => { + assert_eq!(args.len(), 2); + format!("{} | {}", args[0], args[1]) + } + + Intrinsic::BitXor => { + assert_eq!(args.len(), 2); + format!("{} ^ {}", args[0], args[1]) + } + + Intrinsic::BitNot => { + assert_eq!(args.len(), 1); + format!("~{}", args[0]) + } + + Intrinsic::Shl => { + assert_eq!(args.len(), 2); + format!("{} << {}", args[0], args[1]) + } + + Intrinsic::Shr => { + assert_eq!(args.len(), 2); + format!("{} >> {}", args[0], args[1]) + } + + Intrinsic::UnsignedShr => { + assert_eq!(args.len(), 2); + format!("{} >>> {}", args[0], args[1]) + } + + Intrinsic::Add => { + assert_eq!(args.len(), 2); + format!("{} + {}", args[0], args[1]) + } + + Intrinsic::Sub => { + assert_eq!(args.len(), 2); + format!("{} - {}", args[0], args[1]) + } + + Intrinsic::Div => { + assert_eq!(args.len(), 2); + format!("{} / {}", args[0], args[1]) + } + + Intrinsic::CheckedDiv => { + assert_eq!(args.len(), 2); + format!("try {{ {} / {} }} catch (e) {{ if (e instanceof RangeError) {{ e }} else {{ throw e }} }}", args[0], args[1]) + } + + Intrinsic::Mul => { + assert_eq!(args.len(), 2); + format!("{} * {}", args[0], args[1]) + } + + Intrinsic::Rem => { + assert_eq!(args.len(), 2); + format!("{} % {}", args[0], args[1]) + } + + Intrinsic::Pow => { + assert_eq!(args.len(), 2); + format!("{} ** {}", args[0], args[1]) + } + + Intrinsic::LT => { + assert_eq!(args.len(), 2); + format!("{} < {}", args[0], args[1]) + } + + Intrinsic::LE => { + assert_eq!(args.len(), 2); + format!("{} <= {}", args[0], args[1]) + } + + Intrinsic::GE => { + assert_eq!(args.len(), 2); + format!("{} >= {}", args[0], args[1]) + } + + Intrinsic::GT => { + assert_eq!(args.len(), 2); + format!("{} > {}", args[0], args[1]) + } + Intrinsic::ObjectCloneRef => { assert_eq!(args.len(), 1); args[0].clone() @@ -2968,6 +3093,11 @@ impl<'a> Context<'a> { args[0].clone() } + Intrinsic::BigIntNew => { + assert_eq!(args.len(), 1); + format!("BigInt({})", args[0]) + } + Intrinsic::StringNew => { assert_eq!(args.len(), 1); args[0].clone() diff --git a/crates/js-sys/src/lib.rs b/crates/js-sys/src/lib.rs index 16d44988c1b..71db35e51d9 100644 --- a/crates/js-sys/src/lib.rs +++ b/crates/js-sys/src/lib.rs @@ -5,7 +5,7 @@ //! APIs. Only the things that are guaranteed to exist in the global scope by //! the ECMAScript standard. //! -//! https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects +//! //! //! ## A Note About `camelCase`, `snake_case`, and Naming Conventions //! @@ -18,11 +18,15 @@ #![doc(html_root_url = "https://docs.rs/js-sys/0.2")] -use std::convert; +use core::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Not, Rem, Shl, Shr, Sub}; +use std::cmp::Ordering; +use std::convert::{self, Infallible}; use std::f64; use std::fmt; +use std::iter::{self, Product, Sum}; use std::mem; use std::str; +use std::str::FromStr; use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; @@ -47,6 +51,167 @@ use wasm_bindgen::JsCast; // * Arguments that are `JsValue`s or imported JavaScript types should be taken // by reference. +macro_rules! forward_deref_unop { + (impl $imp:ident, $method:ident for $t:ty) => { + impl $imp for $t { + type Output = <&'static $t as $imp>::Output; + + #[inline] + fn $method(self) -> Self::Output { + $imp::$method(&self) + } + } + }; +} + +macro_rules! forward_deref_binop { + (impl $imp:ident, $method:ident for $t:ty) => { + impl<'a> $imp<$t> for &'a $t { + type Output = <&'static $t as $imp<&'static $t>>::Output; + + #[inline] + fn $method(self, other: $t) -> Self::Output { + $imp::$method(self, &other) + } + } + + impl $imp<&$t> for $t { + type Output = <&'static $t as $imp<&'static $t>>::Output; + + #[inline] + fn $method(self, other: &$t) -> Self::Output { + $imp::$method(&self, other) + } + } + + impl $imp<$t> for $t { + type Output = <&'static $t as $imp<&'static $t>>::Output; + + #[inline] + fn $method(self, other: $t) -> Self::Output { + $imp::$method(&self, &other) + } + } + }; +} + +macro_rules! forward_js_unop { + (impl $imp:ident, $method:ident for $t:ty) => { + impl $imp for &$t { + type Output = $t; + + #[inline] + fn $method(self) -> Self::Output { + $imp::$method(JsValue::as_ref(self)).unchecked_into() + } + } + + forward_deref_unop!(impl $imp, $method for $t); + }; +} + +macro_rules! forward_js_binop { + (impl $imp:ident, $method:ident for $t:ty) => { + impl $imp<&$t> for &$t { + type Output = $t; + + #[inline] + fn $method(self, other: &$t) -> Self::Output { + $imp::$method(JsValue::as_ref(self), JsValue::as_ref(other)).unchecked_into() + } + } + + forward_deref_binop!(impl $imp, $method for $t); + }; +} + +macro_rules! sum_product { + ($($a:ident)*) => ($( + impl Sum for $a { + #[inline] + fn sum>(iter: I) -> Self { + iter.fold( + $a::from(0), + |a, b| a + b, + ) + } + } + + impl Product for $a { + #[inline] + fn product>(iter: I) -> Self { + iter.fold( + $a::from(1), + |a, b| a * b, + ) + } + } + + impl<'a> Sum<&'a $a> for $a { + fn sum>(iter: I) -> Self { + iter.fold( + $a::from(0), + |a, b| a + b, + ) + } + } + + impl<'a> Product<&'a $a> for $a { + #[inline] + fn product>(iter: I) -> Self { + iter.fold( + $a::from(1), + |a, b| a * b, + ) + } + } + )*) +} + +macro_rules! partialord_ord { + ($t:ident) => { + impl PartialOrd for $t { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } + + #[inline] + fn lt(&self, other: &Self) -> bool { + JsValue::as_ref(self).lt(JsValue::as_ref(other)) + } + + #[inline] + fn le(&self, other: &Self) -> bool { + JsValue::as_ref(self).le(JsValue::as_ref(other)) + } + + #[inline] + fn ge(&self, other: &Self) -> bool { + JsValue::as_ref(self).ge(JsValue::as_ref(other)) + } + + #[inline] + fn gt(&self, other: &Self) -> bool { + JsValue::as_ref(self).gt(JsValue::as_ref(other)) + } + } + + impl Ord for $t { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + if self == other { + Ordering::Equal + } else if self.lt(other) { + Ordering::Less + } else { + Ordering::Greater + } + } + } + }; +} + #[wasm_bindgen] extern "C" { /// The `decodeURI()` function decodes a Uniform Resource Identifier (URI) @@ -774,6 +939,219 @@ pub mod Atomics { } } +// BigInt +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(extends = Object, is_type_of = |v| v.is_bigint(), typescript_type = "bigint")] + #[derive(Clone, PartialEq, Eq)] + pub type BigInt; + + #[wasm_bindgen(catch, js_name = BigInt)] + fn new_bigint(value: &JsValue) -> Result; + + #[wasm_bindgen(js_name = BigInt)] + fn new_bigint_unchecked(value: &JsValue) -> BigInt; + + /// Clamps a BigInt value to a signed integer value, and returns that value. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/asIntN) + #[wasm_bindgen(static_method_of = BigInt, js_name = asIntN)] + pub fn as_int_n(bits: f64, bigint: &BigInt) -> BigInt; + + /// Clamps a BigInt value to an unsigned integer value, and returns that value. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/asUintN) + #[wasm_bindgen(static_method_of = BigInt, js_name = asUintN)] + pub fn as_uint_n(bits: f64, bigint: &BigInt) -> BigInt; + + /// Returns a string with a language-sensitive representation of this BigInt value. Overrides the [`Object.prototype.toLocaleString()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/toLocaleString) method. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/toLocaleString) + #[wasm_bindgen(method, js_name = toLocaleString)] + pub fn to_locale_string(this: &BigInt, locales: &JsValue, options: &JsValue) -> JsString; + + /// Returns a string representing this BigInt value in the specified radix (base). Overrides the [`Object.prototype.toString()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString) method. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/toString) + #[wasm_bindgen(catch, method, js_name = toString)] + pub fn to_string(this: &BigInt, radix: u8) -> Result; + + #[wasm_bindgen(method, js_name = toString)] + fn to_string_unchecked(this: &BigInt, radix: u8) -> String; + + /// Returns this BigInt value. Overrides the [`Object.prototype.valueOf()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf) method. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/valueOf) + #[wasm_bindgen(method, js_name = valueOf)] + pub fn value_of(this: &BigInt, radix: u8) -> BigInt; +} + +impl BigInt { + /// Creates a new BigInt value. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/BigInt) + #[inline] + pub fn new(value: &JsValue) -> Result { + new_bigint(value) + } + + /// Applies the binary `/` JS operator on two `BigInt`s, catching and returning any `RangeError` thrown. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Division) + pub fn checked_div(&self, rhs: &Self) -> Result { + let result = JsValue::as_ref(self).checked_div(JsValue::as_ref(rhs)); + + if result.is_instance_of::() { + Err(result.unchecked_into()) + } else { + Ok(result.unchecked_into()) + } + } + + /// Applies the binary `**` JS operator on the two `BigInt`s. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Exponentiation) + #[inline] + pub fn pow(&self, rhs: &Self) -> Self { + JsValue::as_ref(self) + .pow(JsValue::as_ref(rhs)) + .unchecked_into() + } +} + +macro_rules! bigint_from { + ($($x:ident)*) => ($( + impl From<$x> for BigInt { + #[inline] + fn from(x: $x) -> BigInt { + new_bigint_unchecked(&JsValue::from(x)) + } + } + + impl PartialEq<$x> for BigInt { + #[inline] + fn eq(&self, other: &$x) -> bool { + JsValue::from(self) == BigInt::from(*other).unchecked_into::() + } + } + )*) +} +bigint_from!(i8 u8 i16 u16 i32 u32); + +macro_rules! bigint_from_big { + ($($x:ident)*) => ($( + impl From<$x> for BigInt { + #[inline] + fn from(x: $x) -> BigInt { + JsValue::from(x).unchecked_into() + } + } + + impl PartialEq<$x> for BigInt { + #[inline] + fn eq(&self, other: &$x) -> bool { + self == &BigInt::from(*other) + } + } + )*) +} +bigint_from_big!(i64 u64 i128 u128 isize usize); + +impl PartialEq for BigInt { + #[inline] + fn eq(&self, other: &Number) -> bool { + JsValue::as_ref(self).loose_eq(JsValue::as_ref(other)) + } +} + +impl Not for &BigInt { + type Output = BigInt; + + #[inline] + fn not(self) -> Self::Output { + JsValue::as_ref(self).bit_not().unchecked_into() + } +} + +forward_deref_unop!(impl Not, not for BigInt); +forward_js_unop!(impl Neg, neg for BigInt); +forward_js_binop!(impl BitAnd, bitand for BigInt); +forward_js_binop!(impl BitOr, bitor for BigInt); +forward_js_binop!(impl BitXor, bitxor for BigInt); +forward_js_binop!(impl Shl, shl for BigInt); +forward_js_binop!(impl Shr, shr for BigInt); +forward_js_binop!(impl Add, add for BigInt); +forward_js_binop!(impl Sub, sub for BigInt); +forward_js_binop!(impl Div, div for BigInt); +forward_js_binop!(impl Mul, mul for BigInt); +forward_js_binop!(impl Rem, rem for BigInt); +sum_product!(BigInt); + +partialord_ord!(BigInt); + +impl Default for BigInt { + fn default() -> Self { + BigInt::from(i32::default()) + } +} + +impl FromStr for BigInt { + type Err = Error; + + #[inline] + fn from_str(s: &str) -> Result { + BigInt::new(&s.into()) + } +} + +impl fmt::Debug for BigInt { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + +impl fmt::Display for BigInt { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad_integral(self >= &BigInt::from(0), "", &self.to_string_unchecked(10)) + } +} + +impl fmt::Binary for BigInt { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad_integral(self >= &BigInt::from(0), "0b", &self.to_string_unchecked(2)) + } +} + +impl fmt::Octal for BigInt { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad_integral(self >= &BigInt::from(0), "0o", &self.to_string_unchecked(8)) + } +} + +impl fmt::LowerHex for BigInt { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad_integral( + self >= &BigInt::from(0), + "0x", + &self.to_string_unchecked(16), + ) + } +} + +impl fmt::UpperHex for BigInt { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut s: String = self.to_string_unchecked(16); + s.make_ascii_uppercase(); + f.pad_integral(self >= &BigInt::from(0), "0x", &s) + } +} + // Boolean #[wasm_bindgen] extern "C" { @@ -819,7 +1197,13 @@ impl PartialEq for Boolean { impl fmt::Debug for Boolean { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.value_of().fmt(f) + fmt::Debug::fmt(&self.value_of(), f) + } +} + +impl fmt::Display for Boolean { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.value_of(), f) } } @@ -829,6 +1213,19 @@ impl Default for Boolean { } } +impl Not for &Boolean { + type Output = Boolean; + + #[inline] + fn not(self) -> Self::Output { + (!JsValue::as_ref(self)).into() + } +} + +forward_deref_unop!(impl Not, not for Boolean); + +partialord_ord!(Boolean); + // DataView #[wasm_bindgen] extern "C" { @@ -1100,6 +1497,8 @@ extern "C" { pub fn to_string(this: &Error) -> JsString; } +partialord_ord!(JsString); + // EvalError #[wasm_bindgen] extern "C" { @@ -1841,7 +2240,7 @@ pub mod Math { #[wasm_bindgen] extern "C" { #[wasm_bindgen(extends = Object, is_type_of = |v| v.as_f64().is_some(), typescript_type = "number")] - #[derive(Clone)] + #[derive(Clone, PartialEq)] pub type Number; /// The `Number.isFinite()` method determines whether the passed value is a finite number. @@ -1880,6 +2279,9 @@ extern "C" { #[allow(deprecated)] pub fn new(value: &JsValue) -> Number; + #[wasm_bindgen(constructor)] + fn new_from_str(value: &str) -> Number; + /// The `Number.parseInt()` method parses a string argument and returns an /// integer of the specified radix or base. /// @@ -1972,6 +2374,24 @@ impl Number { /// /// [MDN Documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/POSITIVE_INFINITY) pub const POSITIVE_INFINITY: f64 = f64::INFINITY; + + /// Applies the binary `**` JS operator on the two `Number`s. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Exponentiation) + #[inline] + pub fn pow(&self, rhs: &Self) -> Self { + JsValue::as_ref(self) + .pow(JsValue::as_ref(rhs)) + .unchecked_into() + } + + /// Applies the binary `>>>` JS operator on the two `Number`s. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unsigned_right_shift) + #[inline] + pub fn unsigned_shr(&self, rhs: &Self) -> Self { + Number::from(JsValue::as_ref(self).unsigned_shr(JsValue::as_ref(rhs))) + } } macro_rules! number_from { @@ -1993,16 +2413,45 @@ macro_rules! number_from { } number_from!(i8 u8 i16 u16 i32 u32 f32 f64); +// TODO: add this on the next major version, when blanket impl is removed +/* +impl convert::TryFrom for Number { + type Error = Error; + + fn try_from(value: JsValue) -> Result { + return match f64::try_from(value) { + Ok(num) => Ok(Number::from(num)), + Err(jsval) => Err(jsval.unchecked_into()) + } + } +} +*/ + +impl From<&Number> for f64 { + #[inline] + fn from(n: &Number) -> f64 { + n.value_of() + } +} + impl From for f64 { #[inline] fn from(n: Number) -> f64 { - n.value_of() + n.into() } } impl fmt::Debug for Number { + #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.value_of().fmt(f) + fmt::Debug::fmt(&self.value_of(), f) + } +} + +impl fmt::Display for Number { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.value_of(), f) } } @@ -2012,6 +2461,82 @@ impl Default for Number { } } +impl PartialEq for Number { + #[inline] + fn eq(&self, other: &BigInt) -> bool { + JsValue::as_ref(self).loose_eq(JsValue::as_ref(other)) + } +} + +impl Not for &Number { + type Output = BigInt; + + #[inline] + fn not(self) -> Self::Output { + JsValue::as_ref(self).bit_not().unchecked_into() + } +} + +forward_deref_unop!(impl Not, not for Number); +forward_js_unop!(impl Neg, neg for Number); +forward_js_binop!(impl BitAnd, bitand for Number); +forward_js_binop!(impl BitOr, bitor for Number); +forward_js_binop!(impl BitXor, bitxor for Number); +forward_js_binop!(impl Shl, shl for Number); +forward_js_binop!(impl Shr, shr for Number); +forward_js_binop!(impl Add, add for Number); +forward_js_binop!(impl Sub, sub for Number); +forward_js_binop!(impl Div, div for Number); +forward_js_binop!(impl Mul, mul for Number); +forward_js_binop!(impl Rem, rem for Number); + +sum_product!(Number); + +impl PartialOrd for Number { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + if Number::is_nan(self) || Number::is_nan(other) { + None + } else if self == other { + Some(Ordering::Equal) + } else if self.lt(other) { + Some(Ordering::Less) + } else { + Some(Ordering::Greater) + } + } + + #[inline] + fn lt(&self, other: &Self) -> bool { + JsValue::as_ref(self).lt(JsValue::as_ref(other)) + } + + #[inline] + fn le(&self, other: &Self) -> bool { + JsValue::as_ref(self).le(JsValue::as_ref(other)) + } + + #[inline] + fn ge(&self, other: &Self) -> bool { + JsValue::as_ref(self).ge(JsValue::as_ref(other)) + } + + #[inline] + fn gt(&self, other: &Self) -> bool { + JsValue::as_ref(self).gt(JsValue::as_ref(other)) + } +} + +impl FromStr for Number { + type Err = Infallible; + + #[allow(deprecated)] + #[inline] + fn from_str(s: &str) -> Result { + Ok(Number::new_from_str(s)) + } +} + // Date. #[wasm_bindgen] extern "C" { @@ -4348,8 +4873,16 @@ impl From for String { } impl fmt::Debug for JsString { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&String::from(self), f) + } +} + +impl fmt::Display for JsString { + #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - String::from(self).fmt(f) + fmt::Display::fmt(&String::from(self), f) } } @@ -5205,4 +5738,12 @@ arrays! { /// `Float64Array()` /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float64Array Float64Array: f64, + + /// `BigInt64Array()` + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt64Array + BigInt64Array: BigInt, + + /// `BigUint64Array()` + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigUint64Array + BigUint64Array: BigInt, } diff --git a/crates/macro/ui-tests/async-errors.stderr b/crates/macro/ui-tests/async-errors.stderr index 74d016db05d..b2fe6f99984 100644 --- a/crates/macro/ui-tests/async-errors.stderr +++ b/crates/macro/ui-tests/async-errors.stderr @@ -33,7 +33,7 @@ error[E0277]: the trait bound `wasm_bindgen::JsValue: From` is not sati > > > - and 63 others + and 72 others = note: required because of the requirements on the impl of `Into` for `BadType` = note: required because of the requirements on the impl of `IntoJsResult` for `BadType` = note: required by `into_js_result` diff --git a/src/lib.rs b/src/lib.rs index f0ee406445e..087a85bd589 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,10 +10,14 @@ #![doc(html_root_url = "https://docs.rs/wasm-bindgen/0.2")] #![cfg_attr(feature = "nightly", feature(unsize))] +use core::convert::TryFrom; use core::fmt; use core::marker; use core::mem; -use core::ops::{Deref, DerefMut}; +use core::ops::{ + Add, BitAnd, BitOr, BitXor, Deref, DerefMut, Div, Mul, Neg, Not, Rem, Shl, Shr, Sub, +}; +use core::u32; use crate::convert::{FromWasmAbi, WasmOptionalF64, WasmSlice}; @@ -143,6 +147,15 @@ impl JsValue { unsafe { JsValue::_new(__wbindgen_number_new(n)) } } + /// Creates a new JS value which is a bigint from a string representing a number. + /// + /// This function creates a JS value representing a bigint (a heap + /// allocated large integer) and returns a handle to the JS version of it. + #[inline] + pub fn bigint_from_str(s: &str) -> JsValue { + unsafe { JsValue::_new(__wbindgen_bigint_new(s.as_ptr(), s.len())) } + } + /// Creates a new JS value which is a boolean. /// /// This function creates a JS object representing a boolean (a heap @@ -238,11 +251,13 @@ impl JsValue { /// /// If this JS value is not an instance of a number then this returns /// `None`. + #[inline] pub fn as_f64(&self) -> Option { unsafe { FromWasmAbi::from_abi(__wbindgen_number_get(self.idx)) } } /// Tests whether this JS value is a JS string. + #[inline] pub fn is_string(&self) -> bool { unsafe { __wbindgen_is_string(self.idx) == 1 } } @@ -268,6 +283,7 @@ impl JsValue { /// /// [caveats]: https://rustwasm.github.io/docs/wasm-bindgen/reference/types/str.html #[cfg(feature = "std")] + #[inline] pub fn as_string(&self) -> Option { unsafe { FromWasmAbi::from_abi(__wbindgen_string_get(self.idx)) } } @@ -277,6 +293,7 @@ impl JsValue { /// /// If this JS value is not an instance of a boolean then this returns /// `None`. + #[inline] pub fn as_bool(&self) -> Option { unsafe { match __wbindgen_boolean_get(self.idx) { @@ -317,6 +334,28 @@ impl JsValue { unsafe { __wbindgen_is_function(self.idx) == 1 } } + /// Tests whether the type of this JS value is `function`. + #[inline] + pub fn is_bigint(&self) -> bool { + unsafe { __wbindgen_is_bigint(self.idx) == 1 } + } + + /// Applies the unary `typeof` JS operator on a `JsValue`. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof) + #[inline] + pub fn js_typeof(&self) -> JsValue { + unsafe { JsValue::_new(__wbindgen_typeof(self.idx)) } + } + + /// Applies the binary `in` JS operator on the two `JsValue`s. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof) + #[inline] + pub fn js_in(&self, obj: &JsValue) -> bool { + unsafe { __wbindgen_in(self.idx, obj.idx) == 1 } + } + /// Tests whether the value is ["truthy"]. /// /// ["truthy"]: https://developer.mozilla.org/en-US/docs/Glossary/Truthy @@ -333,7 +372,7 @@ impl JsValue { unsafe { __wbindgen_is_falsy(self.idx) == 1 } } - /// Get a string representation of the JavaScript object for debugging + /// Get a string representation of the JavaScript object for debugging. #[cfg(feature = "std")] fn as_debug_string(&self) -> String { unsafe { @@ -343,11 +382,94 @@ impl JsValue { String::from_utf8_unchecked(data) } } + + /// Compare two `JsValue`s for equality, using the `==` operator in JS. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Equality) + #[inline] + pub fn loose_eq(&self, other: &Self) -> bool { + unsafe { __wbindgen_jsval_loose_eq(self.idx, other.idx) != 0 } + } + + /// Applies the unary `~` JS operator on a `JsValue`. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_NOT) + #[inline] + pub fn bit_not(&self) -> JsValue { + unsafe { JsValue::_new(__wbindgen_bit_not(self.idx)) } + } + + /// Applies the binary `>>>` JS operator on the two `JsValue`s. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unsigned_right_shift) + #[inline] + pub fn unsigned_shr(&self, rhs: &Self) -> u32 { + unsafe { __wbindgen_unsigned_shr(self.idx, rhs.idx) } + } + + /// Applies the binary `/` JS operator on two `JsValue`s, catching and returning any `RangeError` thrown. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Division) + #[inline] + pub fn checked_div(&self, rhs: &Self) -> Self { + unsafe { JsValue::_new(__wbindgen_checked_div(self.idx, rhs.idx)) } + } + + /// Applies the binary `**` JS operator on the two `JsValue`s. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Exponentiation) + #[inline] + pub fn pow(&self, rhs: &Self) -> Self { + unsafe { JsValue::_new(__wbindgen_pow(self.idx, rhs.idx)) } + } + + /// Applies the binary `<` JS operator on the two `JsValue`s. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Less_than) + #[inline] + pub fn lt(&self, other: &Self) -> bool { + unsafe { __wbindgen_lt(self.idx, other.idx) == 1 } + } + + /// Applies the binary `<=` JS operator on the two `JsValue`s. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Less_than_or_equal) + #[inline] + pub fn le(&self, other: &Self) -> bool { + unsafe { __wbindgen_le(self.idx, other.idx) == 1 } + } + + /// Applies the binary `>=` JS operator on the two `JsValue`s. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Greater_than_or_equal) + #[inline] + pub fn ge(&self, other: &Self) -> bool { + unsafe { __wbindgen_ge(self.idx, other.idx) == 1 } + } + + /// Applies the binary `>` JS operator on the two `JsValue`s. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Greater_than) + #[inline] + pub fn gt(&self, other: &Self) -> bool { + unsafe { __wbindgen_gt(self.idx, other.idx) == 1 } + } + + /// Applies the unary `+` JS operator on a `JsValue`. Can throw. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unary_plus) + #[inline] + pub fn unchecked_into_f64(&self) -> f64 { + unsafe { __wbindgen_as_number(self.idx) } + } } impl PartialEq for JsValue { + /// Compares two `JsValue`s for equality, using the `===` operator in JS. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Strict_equality) #[inline] - fn eq(&self, other: &JsValue) -> bool { + fn eq(&self, other: &Self) -> bool { unsafe { __wbindgen_jsval_eq(self.idx, other.idx) != 0 } } } @@ -388,6 +510,248 @@ if_std! { } } +macro_rules! forward_deref_unop { + (impl $imp:ident, $method:ident for $t:ty) => { + impl $imp for $t { + type Output = <&'static $t as $imp>::Output; + + #[inline] + fn $method(self) -> <&'static $t as $imp>::Output { + $imp::$method(&self) + } + } + }; +} + +macro_rules! forward_deref_binop { + (impl $imp:ident, $method:ident for $t:ty) => { + impl<'a> $imp<$t> for &'a $t { + type Output = <&'static $t as $imp<&'static $t>>::Output; + + #[inline] + fn $method(self, other: $t) -> <&'static $t as $imp<&'static $t>>::Output { + $imp::$method(self, &other) + } + } + + impl $imp<&$t> for $t { + type Output = <&'static $t as $imp<&'static $t>>::Output; + + #[inline] + fn $method(self, other: &$t) -> <&'static $t as $imp<&'static $t>>::Output { + $imp::$method(&self, other) + } + } + + impl $imp<$t> for $t { + type Output = <&'static $t as $imp<&'static $t>>::Output; + + #[inline] + fn $method(self, other: $t) -> <&'static $t as $imp<&'static $t>>::Output { + $imp::$method(&self, &other) + } + } + }; +} + +impl Not for &JsValue { + type Output = bool; + + /// Applies the `!` JS operator on a `JsValue`. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_NOT) + #[inline] + fn not(self) -> Self::Output { + JsValue::is_falsy(self) + } +} + +forward_deref_unop!(impl Not, not for JsValue); + +impl TryFrom for f64 { + type Error = JsValue; + + /// Applies the unary `+` JS operator on a `JsValue`. + /// Returns the numeric result on success, or the JS error value on error. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unary_plus) + #[inline] + fn try_from(val: JsValue) -> Result { + f64::try_from(&val) + } +} + +impl TryFrom<&JsValue> for f64 { + type Error = JsValue; + + /// Applies the unary `+` JS operator on a `JsValue`. + /// Returns the numeric result on success, or the JS error value on error. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unary_plus) + #[inline] + fn try_from(val: &JsValue) -> Result { + let jsval = unsafe { JsValue::_new(__wbindgen_try_into_number(val.idx)) }; + return match jsval.as_f64() { + Some(num) => Ok(num), + None => Err(jsval), + }; + } +} + +impl Neg for &JsValue { + type Output = JsValue; + + /// Applies the unary `-` JS operator on a `JsValue`. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unary_negation) + #[inline] + fn neg(self) -> Self::Output { + unsafe { JsValue::_new(__wbindgen_neg(self.idx)) } + } +} + +forward_deref_unop!(impl Neg, neg for JsValue); + +impl BitAnd for &JsValue { + type Output = JsValue; + + /// Applies the binary `&` JS operator on two `JsValue`s. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_AND) + #[inline] + fn bitand(self, rhs: Self) -> Self::Output { + unsafe { JsValue::_new(__wbindgen_bit_and(self.idx, rhs.idx)) } + } +} + +forward_deref_binop!(impl BitAnd, bitand for JsValue); + +impl BitOr for &JsValue { + type Output = JsValue; + + /// Applies the binary `|` JS operator on two `JsValue`s. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_OR) + #[inline] + fn bitor(self, rhs: Self) -> Self::Output { + unsafe { JsValue::_new(__wbindgen_bit_or(self.idx, rhs.idx)) } + } +} + +forward_deref_binop!(impl BitOr, bitor for JsValue); + +impl BitXor for &JsValue { + type Output = JsValue; + + /// Applies the binary `^` JS operator on two `JsValue`s. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_XOR) + #[inline] + fn bitxor(self, rhs: Self) -> Self::Output { + unsafe { JsValue::_new(__wbindgen_bit_xor(self.idx, rhs.idx)) } + } +} + +forward_deref_binop!(impl BitXor, bitxor for JsValue); + +impl Shl for &JsValue { + type Output = JsValue; + + /// Applies the binary `<<` JS operator on two `JsValue`s. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Left_shift) + #[inline] + fn shl(self, rhs: Self) -> Self::Output { + unsafe { JsValue::_new(__wbindgen_shl(self.idx, rhs.idx)) } + } +} + +forward_deref_binop!(impl Shl, shl for JsValue); + +impl Shr for &JsValue { + type Output = JsValue; + + /// Applies the binary `>>` JS operator on two `JsValue`s. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Right_shift) + #[inline] + fn shr(self, rhs: Self) -> Self::Output { + unsafe { JsValue::_new(__wbindgen_shr(self.idx, rhs.idx)) } + } +} + +forward_deref_binop!(impl Shr, shr for JsValue); + +impl Add for &JsValue { + type Output = JsValue; + + /// Applies the binary `+` JS operator on two `JsValue`s. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Addition) + #[inline] + fn add(self, rhs: Self) -> Self::Output { + unsafe { JsValue::_new(__wbindgen_add(self.idx, rhs.idx)) } + } +} + +forward_deref_binop!(impl Add, add for JsValue); + +impl Sub for &JsValue { + type Output = JsValue; + + /// Applies the binary `-` JS operator on two `JsValue`s. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Subtraction) + #[inline] + fn sub(self, rhs: Self) -> Self::Output { + unsafe { JsValue::_new(__wbindgen_sub(self.idx, rhs.idx)) } + } +} + +forward_deref_binop!(impl Sub, sub for JsValue); + +impl Div for &JsValue { + type Output = JsValue; + + /// Applies the binary `/` JS operator on two `JsValue`s. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Division) + #[inline] + fn div(self, rhs: Self) -> Self::Output { + unsafe { JsValue::_new(__wbindgen_div(self.idx, rhs.idx)) } + } +} + +forward_deref_binop!(impl Div, div for JsValue); + +impl Mul for &JsValue { + type Output = JsValue; + + /// Applies the binary `*` JS operator on two `JsValue`s. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Multiplication) + #[inline] + fn mul(self, rhs: Self) -> Self::Output { + unsafe { JsValue::_new(__wbindgen_mul(self.idx, rhs.idx)) } + } +} + +forward_deref_binop!(impl Mul, mul for JsValue); + +impl Rem for &JsValue { + type Output = JsValue; + + /// Applies the binary `%` JS operator on two `JsValue`s. + /// + /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Remainder) + #[inline] + fn rem(self, rhs: Self) -> Self::Output { + unsafe { JsValue::_new(__wbindgen_rem(self.idx, rhs.idx)) } + } +} + +forward_deref_binop!(impl Rem, rem for JsValue); + impl<'a> From<&'a str> for JsValue { #[inline] fn from(s: &'a str) -> JsValue { @@ -484,6 +848,26 @@ macro_rules! numbers { numbers! { i8 u8 i16 u16 i32 u32 f32 f64 } +macro_rules! big_numbers { + ($($n:ident)*) => ($( + impl PartialEq<$n> for JsValue { + #[inline] + fn eq(&self, other: &$n) -> bool { + self == &JsValue::from(*other) + } + } + + impl From<$n> for JsValue { + #[inline] + fn from(n: $n) -> JsValue { + JsValue::bigint_from_str(&n.to_string()) + } + } + )*) +} + +big_numbers! { i64 u64 i128 u128 isize usize } + externs! { #[link(wasm_import_module = "__wbindgen_placeholder__")] extern "C" { @@ -492,6 +876,7 @@ externs! { fn __wbindgen_string_new(ptr: *const u8, len: usize) -> u32; fn __wbindgen_number_new(f: f64) -> u32; + fn __wbindgen_bigint_new(ptr: *const u8, len: usize) -> u32; fn __wbindgen_symbol_named_new(ptr: *const u8, len: usize) -> u32; fn __wbindgen_symbol_anonymous_new() -> u32; @@ -503,7 +888,33 @@ externs! { fn __wbindgen_is_object(idx: u32) -> u32; fn __wbindgen_is_function(idx: u32) -> u32; fn __wbindgen_is_string(idx: u32) -> u32; + fn __wbindgen_is_bigint(idx: u32) -> u32; + fn __wbindgen_typeof(idx: u32) -> u32; + + fn __wbindgen_in(prop: u32, obj: u32) -> u32; + fn __wbindgen_is_falsy(idx: u32) -> u32; + fn __wbindgen_as_number(idx: u32) -> f64; + fn __wbindgen_try_into_number(idx: u32) -> u32; + fn __wbindgen_neg(idx: u32) -> u32; + fn __wbindgen_bit_and(a: u32, b: u32) -> u32; + fn __wbindgen_bit_or(a: u32, b: u32) -> u32; + fn __wbindgen_bit_xor(a: u32, b: u32) -> u32; + fn __wbindgen_bit_not(idx: u32) -> u32; + fn __wbindgen_shl(a: u32, b: u32) -> u32; + fn __wbindgen_shr(a: u32, b: u32) -> u32; + fn __wbindgen_unsigned_shr(a: u32, b: u32) -> u32; + fn __wbindgen_add(a: u32, b: u32) -> u32; + fn __wbindgen_sub(a: u32, b: u32) -> u32; + fn __wbindgen_div(a: u32, b: u32) -> u32; + fn __wbindgen_checked_div(a: u32, b: u32) -> u32; + fn __wbindgen_mul(a: u32, b: u32) -> u32; + fn __wbindgen_rem(a: u32, b: u32) -> u32; + fn __wbindgen_pow(a: u32, b: u32) -> u32; + fn __wbindgen_lt(a: u32, b: u32) -> u32; + fn __wbindgen_le(a: u32, b: u32) -> u32; + fn __wbindgen_ge(a: u32, b: u32) -> u32; + fn __wbindgen_gt(a: u32, b: u32) -> u32; fn __wbindgen_number_get(idx: u32) -> WasmOptionalF64; fn __wbindgen_boolean_get(idx: u32) -> u32; @@ -522,6 +933,9 @@ externs! { fn __wbindgen_json_parse(ptr: *const u8, len: usize) -> u32; fn __wbindgen_json_serialize(idx: u32) -> WasmSlice; fn __wbindgen_jsval_eq(a: u32, b: u32) -> u32; + fn __wbindgen_jsval_loose_eq(a: u32, b: u32) -> u32; + + fn __wbindgen_not(idx: u32) -> u32; fn __wbindgen_memory() -> u32; fn __wbindgen_module() -> u32;