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
@@ -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()+ }+}