@ 261027.7

261018.1 · 4caa87cda978f25211499266fcc99e637c582ebc

chore: update swc to v1.16.18

reading declarations

Changes to deps/swc/bindings/binding_native_addon/src/. All files

deps/swc/bindings/binding_native_addon/src/legacy.rs

new file mode 100644@@ -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

new file mode 100644@@ -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

new file mode 100644@@ -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()+    }+}