diff --git a/js/rust/Cargo.toml b/js/rust/Cargo.toml index 624dfc6cd040..d821f24f7ce7 100644 --- a/js/rust/Cargo.toml +++ b/js/rust/Cargo.toml @@ -39,6 +39,7 @@ doctest = false debugmozjs = ['mozjs_sys/debugmozjs'] promises = ['mozjs_sys/promises'] nonzero = [] +bigint = ['mozjs_sys/bigint'] [dependencies.mozjs_sys] path = "../src" diff --git a/js/rust/build.rs b/js/rust/build.rs index 38475a73783d..e85d3b730acc 100644 --- a/js/rust/build.rs +++ b/js/rust/build.rs @@ -73,6 +73,10 @@ fn build_jsapi_bindings() { .clang_arg("-DJS_DEBUG"); } + if cfg!(feature = "bigint") { + builder = builder.clang_arg("-DENABLE_BIGINT"); + } + let include_dir = get_mozjs_include_dir(); let include_dir = include_dir.to_str() .expect("Path to mozjs include dir should be utf-8"); @@ -99,6 +103,10 @@ fn build_jsapi_bindings() { builder = builder.whitelist_function(func); } + if cfg!(feature = "bigint") { + builder = builder.whitelist_type("JS::BigInt"); + } + for ty in OPAQUE_TYPES { builder = builder.opaque_type(ty); } diff --git a/js/rust/src/jsval.rs b/js/rust/src/jsval.rs index 6df051e0754a..ac9e42647494 100644 --- a/js/rust/src/jsval.rs +++ b/js/rust/src/jsval.rs @@ -25,6 +25,8 @@ enum ValueTag { UNDEFINED = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_UNDEFINED as u32), STRING = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_STRING as u32), SYMBOL = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_SYMBOL as u32), + #[cfg(feature = "bigint")] + BIGINT = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_BIGINT as u32), BOOLEAN = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_BOOLEAN as u32), MAGIC = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_MAGIC as u32), NULL = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_NULL as u32), @@ -41,6 +43,8 @@ enum ValueTag { UNDEFINED = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_UNDEFINED as u32), STRING = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_STRING as u32), SYMBOL = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_SYMBOL as u32), + #[cfg(feature = "bigint")] + BIGINT = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_BIGINT as u32), BOOLEAN = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_BOOLEAN as u32), MAGIC = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_MAGIC as u32), NULL = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_NULL as u32), @@ -57,6 +61,8 @@ enum ValueShiftedTag { UNDEFINED = ((ValueTag::UNDEFINED as u64) << JSVAL_TAG_SHIFT), STRING = ((ValueTag::STRING as u64) << JSVAL_TAG_SHIFT), SYMBOL = ((ValueTag::SYMBOL as u64) << JSVAL_TAG_SHIFT), + #[cfg(feature = "bigint")] + BIGINT = ((ValueTag::BIGINT as u64) << JSVAL_TAG_SHIFT), BOOLEAN = ((ValueTag::BOOLEAN as u64) << JSVAL_TAG_SHIFT), MAGIC = ((ValueTag::MAGIC as u64) << JSVAL_TAG_SHIFT), NULL = ((ValueTag::NULL as u64) << JSVAL_TAG_SHIFT), @@ -187,6 +193,23 @@ pub fn PrivateValue(o: *const c_void) -> JS::Value { BuildJSVal(ValueTag::PRIVATE, ptrBits) } +#[inline(always)] +#[cfg(feature = "bigint")] +#[cfg(target_pointer_width = "64")] +pub fn BigIntValue(b: &JS::BigInt) -> JS::Value { + let bits = b as *const JS::BigInt as usize as u64; + assert!((bits >> JSVAL_TAG_SHIFT) == 0); + BuildJSVal(ValueTag::BIGINT, bits) +} + +#[inline(always)] +#[cfg(target_pointer_width = "32")] +#[inline(always)] +pub fn BigIntValue(s: &JS::BigInt) -> JS::Value { + let bits = s as *const JS::BigInt as usize as u64; + BuildJSVal(ValueTag::BIGINT, bits) +} + impl JS::Value { #[inline(always)] unsafe fn asBits(&self) -> u64 { @@ -363,6 +386,24 @@ impl JS::Value { } } + #[inline(always)] + #[cfg(feature = "bigint")] + #[cfg(target_pointer_width = "64")] + pub fn is_bigint(&self) -> bool { + unsafe { + (self.asBits() >> JSVAL_TAG_SHIFT) == ValueTag::BIGINT as u64 + } + } + + #[inline(always)] + #[cfg(feature = "bigint")] + #[cfg(target_pointer_width = "32")] + pub fn is_bigint(&self) -> bool { + unsafe { + (self.asBits() >> 32) == ValueTag::BIGINT as u64 + } + } + #[inline(always)] #[cfg(target_pointer_width = "64")] pub fn to_boolean(&self) -> bool { diff --git a/js/rust/src/rust.rs b/js/rust/src/rust.rs index 758d8ab4123c..71ce57c6bc99 100644 --- a/js/rust/src/rust.rs +++ b/js/rust/src/rust.rs @@ -306,6 +306,12 @@ impl RootKind for *mut JS::Symbol { fn rootKind() -> JS::RootKind { JS::RootKind::Symbol } } +#[cfg(feature = "bigint")] +impl RootKind for *mut JS::BigInt { + #[inline(always)] + fn rootKind() -> JS::RootKind { JS::RootKind::BigInt } +} + impl RootKind for *mut JSScript { #[inline(always)] fn rootKind() -> JS::RootKind { JS::RootKind::Script } diff --git a/js/src/Cargo.toml b/js/src/Cargo.toml index 4829b49b101e..060ea42f4b5d 100644 --- a/js/src/Cargo.toml +++ b/js/src/Cargo.toml @@ -8,6 +8,7 @@ build = "build.rs" [features] debugmozjs = [] promises = [] +bigint = [] [lib] name = "mozjs_sys" diff --git a/js/src/build.rs b/js/src/build.rs index 5230e5ed803c..e42c1020d0b8 100644 --- a/js/src/build.rs +++ b/js/src/build.rs @@ -16,11 +16,9 @@ fn main() { env::set_var("MAKEFLAGS", format!("-j{}", num_cpus::get())); env::set_current_dir(&js_src).unwrap(); - let variant = if cfg!(feature = "debugmozjs") { - "plaindebug" - } else { - "plain" - }; + let variant = format!("{}{}", + if cfg!(feature = "bigint") { "bigint" } else { "plain" }, + if cfg!(feature = "debugmozjs") { "debug" } else { "" }); let python = env::var("PYTHON").unwrap_or("python2.7".into()); let mut cmd = Command::new(&python); @@ -36,7 +34,7 @@ fn main() { // already exists but wasn't created by autospider. "--dep", "--objdir", &out_dir, - variant]) + &variant]) .env("SOURCE", &js_src) .env("PWD", &js_src) .stdout(Stdio::inherit()) @@ -54,6 +52,10 @@ fn main() { println!("cargo:rustc-link-search=native={}/dist/bin", out_dir); println!("cargo:rustc-link-lib=nspr4"); + if cfg!(feature = "bigint") { + println!("cargo:rustc-link-lib=gmp"); + } + if target.contains("windows") { println!("cargo:rustc-link-lib=winmm"); if target.contains("gnu") { diff --git a/js/src/devtools/automation/variants/bigint b/js/src/devtools/automation/variants/bigint new file mode 100644 index 000000000000..46cfd9d4c1c5 --- /dev/null +++ b/js/src/devtools/automation/variants/bigint @@ -0,0 +1,7 @@ +{ + "configure-args": "--enable-bigint", + "optimize": true, + "env": { + "JSTESTS_EXTRA_ARGS": "--jitflags=all" + } +} diff --git a/js/src/devtools/automation/variants/bigintdebug b/js/src/devtools/automation/variants/bigintdebug new file mode 100644 index 000000000000..c5f622fe84c3 --- /dev/null +++ b/js/src/devtools/automation/variants/bigintdebug @@ -0,0 +1,7 @@ +{ + "configure-args": "--enable-bigint", + "debug": true, + "env": { + "JSTESTS_EXTRA_ARGS": "--jitflags=debug" + } +}