summaryrefslogtreecommitdiffstats
path: root/js/rust/build.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--js/rust/build.rs494
1 files changed, 494 insertions, 0 deletions
diff --git a/js/rust/build.rs b/js/rust/build.rs
new file mode 100644
index 0000000000..6d16065b7d
--- /dev/null
+++ b/js/rust/build.rs
@@ -0,0 +1,494 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+extern crate bindgen;
+extern crate cmake;
+extern crate env_logger;
+extern crate glob;
+
+use std::env;
+use std::path;
+
+fn main() {
+ env_logger::init();
+ build_jsapi_bindings();
+ build_jsglue_cpp();
+}
+
+/// Build the ./src/jsglue.cpp file containing C++ glue methods built on top of
+/// JSAPI.
+fn build_jsglue_cpp() {
+ let dst = cmake::Config::new(".").build();
+
+ println!("cargo:rustc-link-search=native={}/lib", dst.display());
+ println!("cargo:rustc-link-lib=static=jsglue");
+ println!("cargo:rerun-if-changed=src/jsglue.cpp");
+}
+
+/// Find the public include directory within our mozjs-sys crate dependency.
+fn get_mozjs_include_dir() -> path::PathBuf {
+ let out_dir = env::var("OUT_DIR").expect("cargo should invoke us with the OUT_DIR env var set");
+
+ let mut target_build_dir = path::PathBuf::from(out_dir);
+ target_build_dir.push("../../");
+
+ let mut include_dir_glob = target_build_dir.display().to_string();
+ include_dir_glob.push_str("mozjs_sys-*/out/dist/include");
+
+ let entries =
+ glob::glob(&include_dir_glob).expect("Should find entries for mozjs-sys include dir");
+
+ for entry in entries {
+ if let Ok(path) = entry {
+ return path
+ .canonicalize()
+ .expect("Should canonicalize include path");
+ }
+ }
+
+ panic!("Should have found either a mozjs_sys in target/debug or in target/release");
+}
+
+/// Invoke bindgen on the JSAPI headers to produce raw FFI bindings for use from
+/// Rust.
+///
+/// To add or remove which functions, types, and variables get bindings
+/// generated, see the `const` configuration variables below.
+fn build_jsapi_bindings() {
+ let mut builder = bindgen::builder()
+ .rust_target(bindgen::RustTarget::Stable_1_19)
+ .size_t_is_usize(true)
+ .header("./etc/wrapper.hpp")
+ .raw_line("pub use self::root::*;")
+ // Translate every enum with the "rustified enum" strategy. We should
+ // investigate switching to the "constified module" strategy, which has
+ // similar ergonomics but avoids some potential Rust UB footguns.
+ .rustified_enum(".*")
+ .enable_cxx_namespaces();
+
+ if cfg!(feature = "debugmozjs") {
+ builder = builder
+ .clang_arg("-DJS_GC_ZEAL")
+ .clang_arg("-DDEBUG")
+ .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");
+ builder = builder.clang_arg("-I");
+ builder = builder.clang_arg(include_dir);
+
+ for ty in UNSAFE_IMPL_SYNC_TYPES {
+ builder = builder.raw_line(format!("unsafe impl Sync for {} {{}}", ty));
+ }
+
+ for extra in EXTRA_CLANG_FLAGS {
+ builder = builder.clang_arg(*extra);
+ }
+
+ for ty in WHITELIST_TYPES {
+ builder = builder.whitelist_type(ty);
+ }
+
+ for var in WHITELIST_VARS {
+ builder = builder.whitelist_var(var);
+ }
+
+ for func in WHITELIST_FUNCTIONS {
+ 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);
+ }
+
+ for ty in BLACKLIST_TYPES {
+ builder = builder.blacklist_type(ty);
+ }
+
+ let bindings = builder
+ .generate()
+ .expect("Should generate JSAPI bindings OK");
+
+ let out = path::PathBuf::from(env::var("OUT_DIR").unwrap());
+
+ if cfg!(feature = "debugmozjs") {
+ bindings
+ .write_to_file(out.join("jsapi_debug.rs"))
+ .expect("Should write bindings to file OK");
+ } else {
+ bindings
+ .write_to_file(out.join("jsapi.rs"))
+ .expect("Should write bindings to file OK");
+ }
+
+ println!("cargo:rerun-if-changed=etc/wrapper.hpp");
+}
+
+/// JSAPI types for which we should implement `Sync`.
+const UNSAFE_IMPL_SYNC_TYPES: &'static [&'static str] = &[
+ "JSClass",
+ "JSFunctionSpec",
+ "JSNativeWrapper",
+ "JSPropertySpec",
+ "JSTypedMethodJitInfo",
+];
+
+/// Flags passed through bindgen directly to Clang.
+const EXTRA_CLANG_FLAGS: &'static [&'static str] = &[
+ "-x",
+ "c++",
+ "-std=gnu++17",
+ "-fno-sized-deallocation",
+ "-fno-aligned-new",
+ "-DRUST_BINDGEN",
+];
+
+/// Types which we want to generate bindings for (and every other type they
+/// transitively use).
+const WHITELIST_TYPES: &'static [&'static str] = &[
+ "JS::AutoCheckCannotGC",
+ "JS::CallArgs",
+ "JS::RealmOptions",
+ "JS::ContextOptions",
+ "js::DOMCallbacks",
+ "JS::DOMProxyShadowsResult",
+ "js::ESClass",
+ "JS::ForOfIterator",
+ "JS::Handle",
+ "JS::HandleFunction",
+ "JS::HandleId",
+ "JS::HandleObject",
+ "JS::HandleString",
+ "JS::HandleValue",
+ "JS::HandleValueArray",
+ "JS::IsAcceptableThis",
+ "JSAutoRealm",
+ "JSAutoStructuredCloneBuffer",
+ "JSClass",
+ "JSClassOps",
+ "JSContext",
+ "JSErrNum",
+ "JSErrorCallback",
+ "JSErrorFormatString",
+ "JSErrorReport",
+ "JSExnType",
+ "JSLinearString",
+ "JSFunction",
+ "JSFunctionSpec",
+ "JS::GCDescription",
+ "JSGCInvocationKind",
+ "JSGCMode",
+ "JSGCParamKey",
+ "JS::GCProgress",
+ "JSGCStatus",
+ "JSJitCompilerOption",
+ "JSJitGetterCallArgs",
+ "JSJitMethodCallArgs",
+ "JSJitSetterCallArgs",
+ "JSNativeWrapper",
+ "JSPropertySpec",
+ "JSProtoKey",
+ "JSObject",
+ "JSString",
+ "JSStructuredCloneReader",
+ "JSStructuredCloneWriter",
+ "JSScript",
+ "JSType",
+ "JSTypedMethodJitInfo",
+ "JSValueTag",
+ "JSValueType",
+ "JSVersion",
+ "JSWrapObjectCallbacks",
+ "jsid",
+ "JS::Compartment",
+ "JS::Latin1Char",
+ "JS::detail::RootedPtr",
+ "JS::detail::RootListEntry",
+ "JS::MutableHandle",
+ "JS::MutableHandleObject",
+ "JS::MutableHandleValue",
+ "JS::NativeImpl",
+ "js::ObjectOps",
+ "JS::ObjectOpResult",
+ "JS::PersistentRootedIdVector",
+ "JS::PersistentRootedObjectVector",
+ "JS::PromiseState",
+ "JS::PropertyDescriptor",
+ "JS::Rooted",
+ "JS::RootedObject",
+ "JS::RootedValue",
+ "JS::RootingContext",
+ "JS::RootKind",
+ "js::Scalar::Type",
+ "JS::ServoSizes",
+ "JS::shadow::Object",
+ "JS::shadow::ObjectGroup",
+ "JS::SourceText",
+ "js::StackFormat",
+ "JSStructuredCloneCallbacks",
+ "JS::Symbol",
+ "JS::SymbolCode",
+ "JS::TraceKind",
+ "JS::TransferableOwnership",
+ "JS::Value",
+ "JS::WarningReporter",
+ "JS::shadow::Realm",
+ "JS::shadow::Zone",
+ "JS::Zone",
+];
+
+/// Global variables we want to generate bindings to.
+const WHITELIST_VARS: &'static [&'static str] = &[
+ "JS_STRUCTURED_CLONE_VERSION",
+ "JSCLASS_.*",
+ "JSFUN_.*",
+ "JSID_TYPE_VOID",
+ "JSITER_.*",
+ "JSPROP_.*",
+ "JS::FalseHandleValue",
+ "JS::NullHandleValue",
+ "JS::TrueHandleValue",
+ "JS::UndefinedHandleValue",
+];
+
+/// Functions we want to generate bindings to.
+const WHITELIST_FUNCTIONS: &'static [&'static str] = &[
+ "JS::ExceptionStackOrNull",
+ "JS_AddExtraGCRootsTracer",
+ "JS_AddInterruptCallback",
+ "JS::AddPromiseReactions",
+ "js::AddRawValueRoot",
+ "JS_AlreadyHasOwnPropertyById",
+ "JS_AtomizeAndPinString",
+ "js::AssertSameCompartment",
+ "JS::BuildStackString",
+ "JS::Call",
+ "JS_CallFunctionName",
+ "JS_CallFunctionValue",
+ "JS::CallOriginalPromiseThen",
+ "JS::CallOriginalPromiseResolve",
+ "JS::CallOriginalPromiseReject",
+ "JS::CompileFunctionUtf8",
+ "JS::Construct",
+ "JS::ContextOptionsRef",
+ "JS_CopyOwnPropertiesAndPrivateFields",
+ "JS::CurrentGlobalOrNull",
+ "JS_DeletePropertyById",
+ "js::detail::IsWindowSlow",
+ "JS::Evaluate",
+ "JS_ForwardGetPropertyTo",
+ "JS_ForwardSetPropertyTo",
+ "JS::GCTraceKindToAscii",
+ "JS::GetArrayBufferLengthAndData",
+ "js::GetArrayBufferViewLengthAndData",
+ "js::GetFunctionNativeReserved",
+ "JS::GetNonCCWObjectGlobal",
+ "js::GetObjectProto",
+ "JS_GetObjectRuntime",
+ "JS_GetOwnPropertyDescriptorById",
+ "JS::GetPromiseResult",
+ "JS::GetPromiseState",
+ "JS_GetPropertyDescriptorById",
+ "js::GetPropertyKeys",
+ "JS_GetPrototype",
+ "JS_GetRuntime",
+ "js::GetStaticPrototype",
+ "JS_HasOwnPropertyById",
+ "JS_HasProperty",
+ "JS_HasPropertyById",
+ "JS::HeapBigIntWriteBarriers",
+ "JS::HeapObjectWriteBarriers",
+ "JS::HeapScriptWriteBarriers",
+ "JS::HeapStringWriteBarriers",
+ "JS::HeapValueWriteBarriers",
+ "JS_InitializePropertiesFromCompatibleNativeObject",
+ "JS::InitSelfHostedCode",
+ "JS::IsConstructor",
+ "JS::IsPromiseObject",
+ "JS_ClearPendingException",
+ "JS_DefineElement",
+ "JS_DefineFunction",
+ "JS_DefineFunctions",
+ "JS_DefineProperties",
+ "JS_DefineProperty",
+ "JS_DefinePropertyById",
+ "JS_DefineUCProperty",
+ "JS_DeprecatedStringHasLatin1Chars",
+ "JS::detail::InitWithFailureDiagnostic",
+ "JS_DestroyContext",
+ "JS::DisableIncrementalGC",
+ "js::Dump.*",
+ "JS::EnterRealm",
+ "JS_EnumerateStandardClasses",
+ "JS_ErrorFromException",
+ "JS_FireOnNewGlobalObject",
+ "JS_free",
+ "JS_GC",
+ "JS::GetArrayBufferData",
+ "JS_GetArrayBufferViewType",
+ "JS_GetFloat32ArrayData",
+ "JS_GetFloat64ArrayData",
+ "JS_GetFunctionObject",
+ "JS_GetGCParameter",
+ "JS_GetInt16ArrayData",
+ "JS_GetInt32ArrayData",
+ "JS_GetInt8ArrayData",
+ "JS_GetLatin1StringCharsAndLength",
+ "JS_GetParentRuntime",
+ "JS_GetPendingException",
+ "JS_GetProperty",
+ "JS_GetPropertyById",
+ "js::GetPropertyKeys",
+ "JS_GetPrototype",
+ "JS::GetReservedSlot",
+ "JS::GetRealmErrorPrototype",
+ "JS::GetRealmFunctionPrototype",
+ "JS::GetRealmIteratorPrototype",
+ "JS::GetRealmObjectPrototype",
+ "JS::GetScriptedCallerGlobal",
+ "JS_GetTwoByteStringCharsAndLength",
+ "JS_GetUint16ArrayData",
+ "JS_GetUint32ArrayData",
+ "JS_GetUint8ArrayData",
+ "JS_GetUint8ClampedArrayData",
+ "JS::GetWellKnownSymbol",
+ "JS_GlobalObjectTraceHook",
+ "JS::HideScriptedCaller",
+ "JS::InitRealmStandardClasses",
+ "JS::IsArrayObject",
+ "JS_IsExceptionPending",
+ "JS_IsGlobalObject",
+ "JS::IsCallable",
+ "JS::LeaveRealm",
+ "JS_LinkConstructorAndPrototype",
+ "JS_MayResolveStandardClass",
+ "JS::NewArrayBuffer",
+ "JS::NewArrayObject",
+ "JS_NewContext",
+ "JS_NewFloat32Array",
+ "JS_NewFloat64Array",
+ "JS_NewFunction",
+ "js::NewFunctionWithReserved",
+ "JS_NewGlobalObject",
+ "JS_NewInt16Array",
+ "JS_NewInt32Array",
+ "JS_NewInt8Array",
+ "JS_NewObject",
+ "JS_NewObjectWithGivenProto",
+ "JS_NewObjectWithoutMetadata",
+ "JS_NewPlainObject",
+ "JS::NewPromiseObject",
+ "JS_NewStringCopyN",
+ "JS_NewUCStringCopyN",
+ "JS_NewUint16Array",
+ "JS_NewUint32Array",
+ "JS_NewUint8Array",
+ "JS_NewUint8ClampedArray",
+ "JS::ObjectIsDate",
+ "JS_ParseJSON",
+ "JS_ReadBytes",
+ "JS_ReadStructuredClone",
+ "JS_ReadUint32Pair",
+ "JS_RemoveExtraGCRootsTracer",
+ "js::RemoveRawValueRoot",
+ "JS_ReportErrorASCII",
+ "JS_ReportErrorNumberUTF8",
+ "JS_RequestInterruptCallback",
+ "JS_ResolveStandardClass",
+ "js::RunJobs",
+ "JS::SameValue",
+ "js::SetDOMCallbacks",
+ "js::SetDOMProxyInformation",
+ "JS::SetEnqueuePromiseJobCallback",
+ "js::SetFunctionNativeReserved",
+ "JS_SetGCCallback",
+ "JS::SetGCSliceCallback",
+ "JS_SetGCParameter",
+ "JS_SetGCZeal",
+ "JS::SetGetIncumbentGlobalCallback",
+ "JS_SetGlobalJitCompilerOption",
+ "JS_SetImmutablePrototype",
+ "JS_SetNativeStackQuota",
+ "JS_SetOffthreadIonCompilationEnabled",
+ "JS_SetParallelParsingEnabled",
+ "JS_SetPendingException",
+ "js::SetPreserveWrapperCallback",
+ "JS::SetPromiseRejectionTrackerCallback",
+ "JS_SetPrototype",
+ "js::SetWindowProxy",
+ "js::SetWindowProxyClass",
+ "JS_SetProperty",
+ "JS_SetReservedSlot",
+ "JS_SetWrapObjectCallbacks",
+ "JS_ShutDown",
+ "JS_SplicePrototype",
+ "js::StopDrainingJobQueue",
+ "JS_StrictPropertyStub",
+ "JS_StringEqualsAscii",
+ "JS_WrapObject",
+ "JS_WrapValue",
+ "JS_WriteBytes",
+ "JS_WriteStructuredClone",
+ "JS_WriteUint32Pair",
+ "JS::ResolvePromise",
+ "JS::RejectPromise",
+ "JS::SetWarningReporter",
+ "js::ToBooleanSlow",
+ "js::ToInt32Slow",
+ "js::ToInt64Slow",
+ "js::ToNumberSlow",
+ "js::ToStringSlow",
+ "js::ToUint16Slow",
+ "js::ToUint32Slow",
+ "js::ToUint64Slow",
+ "JS_TransplantObject",
+ "js::detail::ToWindowProxyIfWindowSlow",
+ "JS::UnhideScriptedCaller",
+ "JS::UnwrapArrayBuffer",
+ "js::UnwrapArrayBufferView",
+ "js::UnwrapFloat32Array",
+ "js::UnwrapFloat64Array",
+ "js::UnwrapInt16Array",
+ "js::UnwrapInt32Array",
+ "js::UnwrapInt8Array",
+ "js::UnwrapUint16Array",
+ "js::UnwrapUint32Array",
+ "js::UnwrapUint8Array",
+ "js::UnwrapUint8ClampedArray",
+ "js::UseInternalJobQueues",
+ "JS_ValueToFunction",
+];
+
+/// Types that should be treated as an opaque blob of bytes whenever they show
+/// up within a whitelisted type.
+///
+/// These are types which are too tricky for bindgen to handle, and/or use C++
+/// features that don't have an equivalent in rust, such as partial template
+/// specialization.
+const OPAQUE_TYPES: &'static [&'static str] = &[
+ "JS::ReadOnlyCompileOptions",
+ "mozilla::BufferList",
+ "mozilla::UniquePtr.*",
+ "JS::PersistentRooted",
+ "JS::StackGCVector",
+];
+
+/// Types for which we should NEVER generate bindings, even if it is used within
+/// a type or function signature that we are generating bindings for.
+const BLACKLIST_TYPES: &'static [&'static str] = &[
+ // We provide our own definition because we need to express trait bounds in
+ // the definition of the struct to make our Drop implementation correct.
+ "JS::Heap",
+];