261018.1 · 4caa87cda978f25211499266fcc99e637c582ebc
chore: update swc to v1.16.18
reading declarations
Changes to deps/swc/bindings/binding_native_addon/. All files
deps/swc/bindings/binding_native_addon/Cargo.toml
@@ -0,0 +1,36 @@+[package]+name = "binding_native_addon"+version = "0.1.0"+edition = "2021"+rust-version = "1.85"+license = "Apache-2.0"+publish = false+build = "build.rs"++[lib]+crate-type = ["cdylib", "rlib"]++[features]+embedded-payload = []++[dependencies]+swc_native_addon = { path = "../../crates/swc_native_addon" }+libloading = "=0.8.9"+tracing = { version = "=0.1.44", default-features = false, features = ["std"] }++[build-dependencies]+swc_native_addon = { path = "../../crates/swc_native_addon" }+tempfile = "=3.12.0"++[dev-dependencies]+tempfile = "=3.12.0"++[package.metadata.cargo-shear]+# The carrier imports the shared ACL fixture with #[path] from swc_native_addon.+# cargo-shear does not scan that external source, which uses windows-sys.+ignored = ["windows-sys"]++[target.'cfg(windows)'.dev-dependencies]+windows-sys = { version = "=0.52.0", features = [+ "Win32_Foundation", "Win32_Security", "Win32_Security_Authorization",+] }
deps/swc/bindings/binding_native_addon/NOTICE
@@ -0,0 +1,24 @@+The registration descriptor and constructor contract in src/legacy.rs follow+the public N-API NAPI_MODULE_X interface in Node.js v10.0.0's src/node_api.h.+The following Node.js attribution is retained for that interface adaptation.+No implementation from SWC PR #12000 or the napi-rs compression PoC is used.++Copyright Node.js contributors. All rights reserved.++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to+deal in the Software without restriction, including without limitation the+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or+sell copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in+all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS+IN THE SOFTWARE.
deps/swc/bindings/binding_native_addon/build.rs
@@ -0,0 +1,81 @@+use std::{env, fs, path::PathBuf};++use swc_native_addon::{+ format::{NativeTarget, Payload},+ integrity::RuntimeIntegrity,+};++fn main() {+ println!("cargo:rerun-if-env-changed=SWC_NATIVE_BINDING_PAYLOAD");+ let output = PathBuf::from(env::var_os("OUT_DIR").unwrap()).join("payload.rs");+ if env::var_os("CARGO_FEATURE_EMBEDDED_PAYLOAD").is_none() {+ fs::write(+ output,+ "static PAYLOAD: &[u8] = &[];\nstatic INTEGRITY: &[u8] = &[];\n",+ )+ .unwrap();+ return;+ }+ let target = env::var("TARGET").unwrap();+ let target = NativeTarget::parse(&target).expect("native carrier target");+ let path = PathBuf::from(+ env::var_os("SWC_NATIVE_BINDING_PAYLOAD")+ .expect("embedded-payload requires SWC_NATIVE_BINDING_PAYLOAD=/absolute/payload.swcn"),+ );+ assert!(+ path.is_absolute(),+ "SWC_NATIVE_BINDING_PAYLOAD must be absolute"+ );+ println!("cargo:rerun-if-changed={}", path.display());+ let bytes = fs::read(&path).expect("read native addon payload");+ let payload = Payload::parse(&bytes).expect("validate native addon payload header");+ assert_eq!(+ payload.header.target, target,+ "embedded native addon payload target does not match Cargo TARGET"+ );+ let output_parent = output.parent().expect("OUT_DIR has a parent");+ let mut raw = tempfile::Builder::new()+ .prefix(".swc-native-addon-validate-")+ .tempfile_in(output_parent)+ .expect("stage decoded native addon validation");+ payload+ .decode_into(&mut raw)+ .expect("decode embedded native addon bytes");+ payload+ .verify_target(&mut raw)+ .expect("validate embedded native addon target");+ let integrity = RuntimeIntegrity::from_raw(&payload.header, &mut raw)+ .expect("derive runtime integrity from SHA-512 verified raw addon");+ let integrity_path = output.with_file_name("integrity.swcn");+ fs::write(&integrity_path, integrity.encode()).expect("snapshot native runtime integrity");+ // Copy to OUT_DIR so a later input replacement cannot change the validated+ // payload between build-script validation and rustc's include_bytes call.+ let embedded = output.with_file_name("payload.swcn");+ fs::write(&embedded, &bytes).expect("snapshot validated addon payload");+ // Retain a complete, mapped payload for final-artifact verification. LTO+ // may otherwise fold header reads and eliminate parts of include_bytes.+ // Section names fit the Mach-O (16-byte) and PE (8-byte) limits.+ fs::write(+ output,+ format!(+ r#"#[used]+#[cfg_attr(target_os = "linux", link_section = ".swc_native")]+#[cfg_attr(target_os = "macos", link_section = "__TEXT,__swc_native")]+#[cfg_attr(windows, link_section = ".swcn")]+static EMBEDDED_PAYLOAD: [u8; {}] = *include_bytes!({:?});+static PAYLOAD: &[u8] = &EMBEDDED_PAYLOAD;+#[used]+#[cfg_attr(target_os = "linux", link_section = ".swc_integrity")]+#[cfg_attr(target_os = "macos", link_section = "__TEXT,__swc_integrity")]+#[cfg_attr(windows, link_section = ".swci")]+static EMBEDDED_INTEGRITY: [u8; {}] = *include_bytes!({:?});+static INTEGRITY: &[u8] = &EMBEDDED_INTEGRITY;+"#,+ payload.header.compressed_len + swc_native_addon::format::HEADER_LEN as u64,+ embedded,+ swc_native_addon::integrity::INTEGRITY_LEN,+ integrity_path,+ ),+ )+ .unwrap();+}
deps/swc/bindings/binding_native_addon/src/legacy.rs
@@ -0,0 +1,58 @@+//! Node 10.0 predates lookup of napi_register_module_v1 by symbol. Its original+//! napi_module_register entry point is required even though all APIs used by+//! the initializer itself exist there. New Node versions also accept this hook.+//!+//! Constructors only register metadata. Decompression, IO, and native loading+//! stay in the initializer, outside the Windows loader lock.+//! See ../NOTICE for the Node.js MIT attribution of this public ABI adaptation.++use std::{+ ffi::{c_char, c_void},+ ptr,+};++use crate::napi::Register;++#[repr(C)]+struct Module {+ version: i32,+ flags: u32,+ filename: *const c_char,+ register: Register,+ name: *const c_char,+ private: *mut c_void,+ reserved: [*mut c_void; 4],+}++static mut MODULE: Module = Module {+ version: 1,+ flags: 0,+ filename: b"swc-native-carrier\0".as_ptr().cast(),+ register: crate::napi_register_module_v1,+ name: b"swc_native_carrier\0".as_ptr().cast(),+ private: ptr::null_mut(),+ reserved: [ptr::null_mut(); 4],+};++unsafe extern "C" fn register() {+ #[cfg(unix)]+ let process = libloading::os::unix::Library::this();+ #[cfg(windows)]+ let process = match libloading::os::windows::Library::this() {+ Ok(process) => process,+ Err(_) => return,+ };+ // Test executables are not Node hosts. They can link the rlib without+ // registering anything; Node always exports this original N-API function.+ if let Ok(register) =+ process.get::<unsafe extern "C" fn(*mut Module)>(b"napi_module_register\0")+ {+ register(ptr::addr_of_mut!(MODULE));+ }+}++#[used]+#[cfg_attr(target_os = "linux", link_section = ".init_array")]+#[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")]+#[cfg_attr(windows, link_section = ".CRT$XCU")]+static INITIALIZER: unsafe extern "C" fn() = register;
deps/swc/bindings/binding_native_addon/src/lib.rs
@@ -0,0 +1,191 @@+//! Self-loading target carrier. All native image bytes are verified before the+//! OS loader sees them; N-API registration is forwarded without wrapping+//! exports.++mod legacy;+mod napi;++use std::sync::Mutex;++use libloading::Library;+use swc_native_addon::{+ cache::{self, CacheMode, Materialized},+ format::Payload,+ integrity::RuntimeIntegrity,+ platform, replacement, Error, ErrorKind, Result,+};++include!(concat!(env!("OUT_DIR"), "/payload.rs"));++struct Loaded {+ register: napi::Register,+ _library: Library,+ _materialized: Materialized,+}++// Statics are deliberately never dropped. Addon callbacks can survive the+// original registration call and other Node environments in the same process.+// A Windows temporary's cleanup pipe is closed by process teardown.+static LOADED: Mutex<Option<Loaded>> = Mutex::new(None);+static IMAGE_ANCHOR: u8 = 0;++fn replacement_carrier(+ mode: &CacheMode,+ resolve: impl FnOnce() -> Result<std::path::PathBuf>,+) -> Option<std::path::PathBuf> {+ // APFS self-replacement recompresses the decoded image with ditto and+ // decodes it again for this process. Keep macOS first loads on the verified+ // cache path, even for writable installations, before resolving the carrier.+ if cfg!(target_os = "macos") || *mode == CacheMode::Temporary {+ return None;+ }+ match resolve() {+ Ok(path) => Some(path),+ Err(error) => {+ tracing::debug!(%error, "native carrier path unavailable; using cache");+ None+ }+ }+}++fn initialize() -> Result<napi::Register> {+ let mut loaded = LOADED.lock().map_err(|_| {+ Error::new(+ ErrorKind::Load,+ "native loader initialization lock was poisoned",+ )+ })?;+ if let Some(loaded) = loaded.as_ref() {+ return Ok(loaded.register);+ }+ let payload = Payload::parse(PAYLOAD)?.with_integrity(RuntimeIntegrity::parse(INTEGRITY)?)?;+ let mode = CacheMode::from_env()?;+ let replacement = if let Some(carrier) = replacement_carrier(&mode, || unsafe {+ platform::carrier_path((&IMAGE_ANCHOR as *const u8).cast())+ }) {+ // Compression and replacement are optional. Integrity is rechecked in+ // the cache path; no fallback ever loads an unverified original buffer.+ match replacement::try_replace(&payload, &carrier) {+ Ok(replacement) => replacement,+ Err(error) => {+ tracing::debug!(path = %carrier.display(), %error, "native self-replacement unavailable; using cache");+ None+ }+ }+ } else {+ None+ };+ let mut materialized = match replacement {+ Some(file) => file,+ None => cache::materialize(&payload, &mode)?,+ };+ #[cfg(unix)]+ let library = unsafe {+ libloading::os::unix::Library::open(+ Some(materialized.path()),+ libloading::os::unix::RTLD_NOW | libloading::os::unix::RTLD_LOCAL,+ )+ .map(Library::from)+ };+ #[cfg(windows)]+ let library = unsafe { Library::new(materialized.path()) };+ let library = library.map_err(|e| {+ Error::new(+ ErrorKind::Load,+ format!("load verified addon {}: {e}", materialized.path().display()),+ )+ })?;+ let register = *unsafe { library.get::<napi::Register>(b"napi_register_module_v1\0") }+ .map_err(|e| {+ Error::new(+ ErrorKind::Load,+ format!("verified addon has no napi_register_module_v1: {e}"),+ )+ })?;+ if register as usize == napi_register_module_v1 as *const () as usize {+ return Err(Error::new(+ ErrorKind::Load,+ "raw addon registration resolved back to the carrier",+ ));+ }+ materialized.loaded()?;+ *loaded = Some(Loaded {+ register,+ _library: library,+ _materialized: materialized,+ });+ Ok(register)+}++/// The raw packages already target N-API 3, supported by their Node minimums.+#[no_mangle]+pub extern "C" fn node_api_module_get_api_version_v1() -> i32 {+ 3+}++/// Forward each environment independently, including a raw initializer+/// returning a different exports value or null with a pending JavaScript+/// exception.+///+/// # Safety+/// Node must pass a live `napi_env` and its associated initial exports value.+#[no_mangle]+pub unsafe extern "C" fn napi_register_module_v1(+ env: napi::Env,+ exports: napi::Value,+) -> napi::Value {+ let error = match std::panic::catch_unwind(initialize) {+ Ok(Ok(register)) => return register(env, exports),+ Ok(Err(error)) => error,+ Err(_) => Error::new(ErrorKind::Load, "native loader initialization panicked"),+ };+ // Successful registration forwards the raw initializer directly. Resolving+ // exception helpers would open and close the process image unnecessarily on+ // every environment; only the failure path needs those symbols.+ let api = match napi::Api::load() {+ Ok(api) => api,+ Err(error) => {+ // This can only occur outside the supported Node ABI: without even+ // napi_throw_error there is no legal way to create a JS exception.+ eprintln!("SWC native addon cannot initialize its N-API host: {error}");+ std::process::abort();+ }+ };+ api.throw(env, &error)+}++#[cfg(test)]+mod tests {+ use super::*;++ #[test]+ fn temporary_mode_skips_carrier_resolution() {+ assert!(replacement_carrier(&CacheMode::Temporary, || -> Result<_> {+ panic!("temporary mode must not resolve the carrier")+ })+ .is_none());+ }++ #[test]+ #[cfg(not(target_os = "macos"))]+ fn unavailable_carrier_disables_replacement() {+ assert!(replacement_carrier(&CacheMode::Default, || {+ Err(Error::new(ErrorKind::Load, "carrier is unavailable"))+ })+ .is_none());+ }++ #[test]+ #[cfg(target_os = "macos")]+ fn macos_persistent_modes_skip_carrier_resolution() {+ for mode in [+ CacheMode::Default,+ CacheMode::Custom("/custom/cache".into()),+ ] {+ assert!(replacement_carrier(&mode, || -> Result<_> {+ panic!("macOS must not resolve the carrier for self-replacement")+ })+ .is_none());+ }+ }+}
deps/swc/bindings/binding_native_addon/src/napi.rs
@@ -0,0 +1,70 @@+//! Only original N-API functions are used here. No generated napi-rs module+//! initialization or newer path-discovery API is linked into the carrier.++use std::ffi::{c_char, c_void, CString};++use swc_native_addon::{Error, ErrorKind, Result};++pub type Env = *mut c_void;+pub type Value = *mut c_void;+pub type Register = unsafe extern "C" fn(Env, Value) -> Value;+type ThrowError = unsafe extern "C" fn(Env, *const c_char, *const c_char) -> i32;+type FatalError = unsafe extern "C" fn(*const c_char, usize, *const c_char, usize);++pub struct Api {+ throw_error: ThrowError,+ fatal_error: FatalError,+}++impl Api {+ pub unsafe fn load() -> Result<Self> {+ #[cfg(unix)]+ let process = libloading::os::unix::Library::this();+ #[cfg(windows)]+ let process = libloading::os::windows::Library::this()+ .map_err(|e| Error::new(ErrorKind::Load, format!("open Node process symbols: {e}")))?;+ let throw_error = *process+ .get::<ThrowError>(b"napi_throw_error\0")+ .map_err(|e| {+ Error::new(+ ErrorKind::Load,+ format!("Node must expose napi_throw_error: {e}"),+ )+ })?;+ let fatal_error = *process+ .get::<FatalError>(b"napi_fatal_error\0")+ .map_err(|e| {+ Error::new(+ ErrorKind::Load,+ format!("Node must expose napi_fatal_error: {e}"),+ )+ })?;+ Ok(Self {+ throw_error,+ fatal_error,+ })+ }++ pub unsafe fn throw(&self, env: Env, error: &Error) -> Value {+ let code = CString::new(error.kind.code()).unwrap();+ let message = format!(+ "SWC native addon: {error}. Reinstall the native package if its payload is damaged; \+ check SWC_NATIVE_BINDING_CACHE and directory permissions for materialization \+ failures."+ );+ let message = CString::new(message.replace('\0', "?")).unwrap();+ if (self.throw_error)(env, code.as_ptr(), message.as_ptr()) != 0 {+ // A functioning Node host always provides the original throw API.+ // If it cannot create an exception, returning exports would falsely+ // report success. N-API's original fatal API is the last resort.+ let location = b"swc native loader";+ (self.fatal_error)(+ location.as_ptr().cast(),+ location.len(),+ message.as_ptr(),+ message.as_bytes().len(),+ );+ }+ std::ptr::null_mut()+ }+}