зеркало из https://github.com/mozilla/gecko-dev.git
487 строки
14 KiB
Rust
487 строки
14 KiB
Rust
/* 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)
|
|
.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++14",
|
|
"-fno-sized-deallocation",
|
|
"-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::AutoIdVector",
|
|
"JS::AutoObjectVector",
|
|
"JS::CallArgs",
|
|
"js::Class",
|
|
"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",
|
|
"JSFlatString",
|
|
"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::MaybeWrapped",
|
|
"JS::MutableHandle",
|
|
"JS::MutableHandleObject",
|
|
"JS::MutableHandleValue",
|
|
"JS::NativeImpl",
|
|
"js::ObjectOps",
|
|
"JS::ObjectOpResult",
|
|
"JS::PromiseState",
|
|
"JS::PropertyDescriptor",
|
|
"JS::Rooted",
|
|
"JS::RootedObject",
|
|
"JS::RootingContext",
|
|
"JS::RootKind",
|
|
"js::Scalar::Type",
|
|
"JS::ServoSizes",
|
|
"js::shadow::Object",
|
|
"js::shadow::ObjectGroup",
|
|
"JS::SourceBufferHolder",
|
|
"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] = &[
|
|
"INTERNED_STRING_TO_JSID",
|
|
"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_CopyPropertiesFrom",
|
|
"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::HeapObjectPostBarrier",
|
|
"JS::HeapValuePostBarrier",
|
|
"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::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_NewObjectWithUniqueType",
|
|
"JS_NewPlainObject",
|
|
"JS::NewPromiseObject",
|
|
"JS_NewStringCopyN",
|
|
"JS_NewUCStringCopyN",
|
|
"JS_NewUint16Array",
|
|
"JS_NewUint32Array",
|
|
"JS_NewUint8Array",
|
|
"JS_NewUint8ClampedArray",
|
|
"js::ObjectClassName",
|
|
"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_StringHasLatin1Chars",
|
|
"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::Rooted<JS::Auto.*Vector.*>",
|
|
"JS::Auto.*Vector"
|
|
];
|
|
|
|
/// 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",
|
|
];
|