1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 extern crate env_logger;
15 build_jsapi_bindings();
19 /// Build the ./src/jsglue.cpp file containing C++ glue methods built on top of
21 fn build_jsglue_cpp() {
22 let dst = cmake::Config::new(".").build();
24 println!("cargo:rustc-link-search=native={}/lib", dst.display());
25 println!("cargo:rustc-link-lib=static=jsglue");
26 println!("cargo:rerun-if-changed=src/jsglue.cpp");
29 /// Find the public include directory within our mozjs-sys crate dependency.
30 fn get_mozjs_include_dir() -> path::PathBuf {
31 let out_dir = env::var("OUT_DIR")
32 .expect("cargo should invoke us with the OUT_DIR env var set");
34 let mut target_build_dir = path::PathBuf::from(out_dir);
35 target_build_dir.push("../../");
37 let mut include_dir_glob = target_build_dir.display().to_string();
38 include_dir_glob.push_str("mozjs_sys-*/out/dist/include");
40 let entries = glob::glob(&include_dir_glob)
41 .expect("Should find entries for mozjs-sys include dir");
43 for entry in entries {
44 if let Ok(path) = entry {
45 return path.canonicalize()
46 .expect("Should canonicalize include path");
50 panic!("Should have found either a mozjs_sys in target/debug or in target/release");
53 /// Invoke bindgen on the JSAPI headers to produce raw FFI bindings for use from
56 /// To add or remove which functions, types, and variables get bindings
57 /// generated, see the `const` configuration variables below.
58 fn build_jsapi_bindings() {
59 let mut builder = bindgen::builder()
60 .rust_target(bindgen::RustTarget::Stable_1_19)
61 .header("./etc/wrapper.hpp")
62 .raw_line("pub use self::root::*;")
63 // Translate every enum with the "rustified enum" strategy. We should
64 // investigate switching to the "constified module" strategy, which has
65 // similar ergonomics but avoids some potential Rust UB footguns.
67 .enable_cxx_namespaces();
69 if cfg!(feature = "debugmozjs") {
71 .clang_arg("-DJS_GC_ZEAL")
73 .clang_arg("-DJS_DEBUG");
76 if cfg!(feature = "bigint") {
77 builder = builder.clang_arg("-DENABLE_BIGINT");
80 let include_dir = get_mozjs_include_dir();
81 let include_dir = include_dir.to_str()
82 .expect("Path to mozjs include dir should be utf-8");
83 builder = builder.clang_arg("-I");
84 builder = builder.clang_arg(include_dir);
86 for ty in UNSAFE_IMPL_SYNC_TYPES {
87 builder = builder.raw_line(format!("unsafe impl Sync for {} {{}}", ty));
90 for extra in EXTRA_CLANG_FLAGS {
91 builder = builder.clang_arg(*extra);
94 for ty in WHITELIST_TYPES {
95 builder = builder.whitelist_type(ty);
98 for var in WHITELIST_VARS {
99 builder = builder.whitelist_var(var);
102 for func in WHITELIST_FUNCTIONS {
103 builder = builder.whitelist_function(func);
106 if cfg!(feature = "bigint") {
107 builder = builder.whitelist_type("JS::BigInt");
110 for ty in OPAQUE_TYPES {
111 builder = builder.opaque_type(ty);
114 for ty in BLACKLIST_TYPES {
115 builder = builder.blacklist_type(ty);
118 let bindings = builder.generate()
119 .expect("Should generate JSAPI bindings OK");
121 let out = path::PathBuf::from(env::var("OUT_DIR").unwrap());
123 if cfg!(feature = "debugmozjs") {
124 bindings.write_to_file(out.join("jsapi_debug.rs"))
125 .expect("Should write bindings to file OK");
127 bindings.write_to_file(out.join("jsapi.rs"))
128 .expect("Should write bindings to file OK");
131 println!("cargo:rerun-if-changed=etc/wrapper.hpp");
134 /// JSAPI types for which we should implement `Sync`.
135 const UNSAFE_IMPL_SYNC_TYPES: &'static [&'static str] = &[
140 "JSTypedMethodJitInfo",
143 /// Flags passed through bindgen directly to Clang.
144 const EXTRA_CLANG_FLAGS: &'static [&'static str] = &[
147 "-fno-sized-deallocation",
152 /// Types which we want to generate bindings for (and every other type they
153 /// transitively use).
154 const WHITELIST_TYPES: &'static [&'static str] = &[
155 "JS::AutoCheckCannotGC",
158 "JS::ContextOptions",
160 "js::DOMProxyShadowsResult",
164 "JS::HandleFunction",
169 "JS::HandleValueArray",
170 "JS::IsAcceptableThis",
172 "JSAutoStructuredCloneBuffer",
178 "JSErrorFormatString",
185 "JSGCInvocationKind",
190 "JSJitCompilerOption",
191 "JSJitGetterCallArgs",
192 "JSJitMethodCallArgs",
193 "JSJitSetterCallArgs",
199 "JSStructuredCloneReader",
200 "JSStructuredCloneWriter",
203 "JSTypedMethodJitInfo",
207 "JSWrapObjectCallbacks",
211 "JS::detail::MaybeWrapped",
213 "JS::MutableHandleObject",
214 "JS::MutableHandleValue",
217 "JS::ObjectOpResult",
218 "JS::PersistentRootedIdVector",
219 "JS::PersistentRootedObjectVector",
221 "JS::PropertyDescriptor",
225 "JS::RootingContext",
229 "js::shadow::Object",
230 "js::shadow::ObjectGroup",
233 "JSStructuredCloneCallbacks",
237 "JS::TransferableOwnership",
239 "JS::WarningReporter",
245 /// Global variables we want to generate bindings to.
246 const WHITELIST_VARS: &'static [&'static str] = &[
247 "JS_STRUCTURED_CLONE_VERSION",
253 "JS::FalseHandleValue",
254 "JS::NullHandleValue",
255 "JS::TrueHandleValue",
256 "JS::UndefinedHandleValue",
259 /// Functions we want to generate bindings to.
260 const WHITELIST_FUNCTIONS: &'static [&'static str] = &[
261 "INTERNED_STRING_TO_JSID",
262 "JS::ExceptionStackOrNull",
263 "JS_AddExtraGCRootsTracer",
264 "JS_AddInterruptCallback",
265 "JS::AddPromiseReactions",
266 "js::AddRawValueRoot",
267 "JS_AlreadyHasOwnPropertyById",
268 "JS_AtomizeAndPinString",
269 "js::AssertSameCompartment",
270 "JS::BuildStackString",
272 "JS_CallFunctionName",
273 "JS_CallFunctionValue",
274 "JS::CallOriginalPromiseThen",
275 "JS::CallOriginalPromiseResolve",
276 "JS::CallOriginalPromiseReject",
277 "JS::CompileFunctionUtf8",
279 "JS::ContextOptionsRef",
280 "JS_CopyPropertiesFrom",
281 "JS::CurrentGlobalOrNull",
282 "JS_DeletePropertyById",
283 "js::detail::IsWindowSlow",
285 "JS_ForwardGetPropertyTo",
286 "JS_ForwardSetPropertyTo",
287 "JS::GCTraceKindToAscii",
288 "JS::GetArrayBufferLengthAndData",
289 "js::GetArrayBufferViewLengthAndData",
290 "js::GetFunctionNativeReserved",
291 "JS::GetNonCCWObjectGlobal",
292 "js::GetObjectProto",
293 "JS_GetObjectRuntime",
294 "JS_GetOwnPropertyDescriptorById",
295 "JS::GetPromiseResult",
296 "JS::GetPromiseState",
297 "JS_GetPropertyDescriptorById",
298 "js::GetPropertyKeys",
301 "js::GetStaticPrototype",
302 "JS_HasOwnPropertyById",
304 "JS_HasPropertyById",
305 "JS::HeapObjectWriteBarriers",
306 "JS::HeapScriptWriteBarriers",
307 "JS::HeapStringWriteBarriers",
308 "JS::HeapValueWriteBarriers",
309 "JS_InitializePropertiesFromCompatibleNativeObject",
310 "JS::InitSelfHostedCode",
312 "JS::IsPromiseObject",
313 "JS_ClearPendingException",
316 "JS_DefineFunctions",
317 "JS_DefineProperties",
319 "JS_DefinePropertyById",
320 "JS_DefineUCProperty",
321 "JS::detail::InitWithFailureDiagnostic",
323 "JS::DisableIncrementalGC",
326 "JS_EnumerateStandardClasses",
327 "JS_ErrorFromException",
328 "JS_FireOnNewGlobalObject",
331 "JS::GetArrayBufferData",
332 "JS_GetArrayBufferViewType",
333 "JS_GetFloat32ArrayData",
334 "JS_GetFloat64ArrayData",
335 "JS_GetFunctionObject",
337 "JS_GetInt16ArrayData",
338 "JS_GetInt32ArrayData",
339 "JS_GetInt8ArrayData",
340 "JS_GetLatin1StringCharsAndLength",
341 "JS_GetParentRuntime",
342 "JS_GetPendingException",
344 "JS_GetPropertyById",
345 "js::GetPropertyKeys",
347 "JS_GetReservedSlot",
348 "JS::GetRealmErrorPrototype",
349 "JS::GetRealmFunctionPrototype",
350 "JS::GetRealmIteratorPrototype",
351 "JS::GetRealmObjectPrototype",
352 "JS::GetScriptedCallerGlobal",
353 "JS_GetTwoByteStringCharsAndLength",
354 "JS_GetUint16ArrayData",
355 "JS_GetUint32ArrayData",
356 "JS_GetUint8ArrayData",
357 "JS_GetUint8ClampedArrayData",
358 "JS::GetWellKnownSymbol",
359 "JS_GlobalObjectTraceHook",
360 "JS::HideScriptedCaller",
361 "JS::InitRealmStandardClasses",
363 "JS_IsExceptionPending",
367 "JS_LinkConstructorAndPrototype",
368 "JS_MayResolveStandardClass",
369 "JS::NewArrayBuffer",
372 "JS_NewFloat32Array",
373 "JS_NewFloat64Array",
375 "js::NewFunctionWithReserved",
376 "JS_NewGlobalObject",
381 "JS_NewObjectWithGivenProto",
382 "JS_NewObjectWithoutMetadata",
383 "JS_NewObjectWithUniqueType",
385 "JS::NewPromiseObject",
387 "JS_NewUCStringCopyN",
391 "JS_NewUint8ClampedArray",
392 "js::ObjectClassName",
396 "JS_ReadStructuredClone",
398 "JS_RemoveExtraGCRootsTracer",
399 "js::RemoveRawValueRoot",
400 "JS_ReportErrorASCII",
401 "JS_ReportErrorNumberUTF8",
402 "JS_RequestInterruptCallback",
403 "JS_ResolveStandardClass",
406 "js::SetDOMCallbacks",
407 "js::SetDOMProxyInformation",
408 "JS::SetEnqueuePromiseJobCallback",
409 "js::SetFunctionNativeReserved",
411 "JS::SetGCSliceCallback",
414 "JS::SetGetIncumbentGlobalCallback",
415 "JS_SetGlobalJitCompilerOption",
416 "JS_SetImmutablePrototype",
417 "JS_SetNativeStackQuota",
418 "JS_SetOffthreadIonCompilationEnabled",
419 "JS_SetParallelParsingEnabled",
420 "JS_SetPendingException",
421 "js::SetPreserveWrapperCallback",
422 "JS::SetPromiseRejectionTrackerCallback",
424 "js::SetWindowProxy",
425 "js::SetWindowProxyClass",
427 "JS_SetReservedSlot",
428 "JS_SetWrapObjectCallbacks",
430 "JS_SplicePrototype",
431 "js::StopDrainingJobQueue",
432 "JS_StrictPropertyStub",
433 "JS_StringEqualsAscii",
434 "JS_StringHasLatin1Chars",
438 "JS_WriteStructuredClone",
439 "JS_WriteUint32Pair",
440 "JS::ResolvePromise",
442 "JS::SetWarningReporter",
451 "JS_TransplantObject",
452 "js::detail::ToWindowProxyIfWindowSlow",
453 "JS::UnhideScriptedCaller",
454 "JS::UnwrapArrayBuffer",
455 "js::UnwrapArrayBufferView",
456 "js::UnwrapFloat32Array",
457 "js::UnwrapFloat64Array",
458 "js::UnwrapInt16Array",
459 "js::UnwrapInt32Array",
460 "js::UnwrapInt8Array",
461 "js::UnwrapUint16Array",
462 "js::UnwrapUint32Array",
463 "js::UnwrapUint8Array",
464 "js::UnwrapUint8ClampedArray",
465 "js::UseInternalJobQueues",
466 "JS_ValueToFunction",
469 /// Types that should be treated as an opaque blob of bytes whenever they show
470 /// up within a whitelisted type.
472 /// These are types which are too tricky for bindgen to handle, and/or use C++
473 /// features that don't have an equivalent in rust, such as partial template
475 const OPAQUE_TYPES: &'static [&'static str] = &[
476 "JS::ReadOnlyCompileOptions",
477 "mozilla::BufferList",
478 "mozilla::UniquePtr.*",
479 "JS::PersistentRooted",
483 /// Types for which we should NEVER generate bindings, even if it is used within
484 /// a type or function signature that we are generating bindings for.
485 const BLACKLIST_TYPES: &'static [&'static str] = &[
486 // We provide our own definition because we need to express trait bounds in
487 // the definition of the struct to make our Drop implementation correct.