diff --git a/Cargo.lock b/Cargo.lock index 5a379a2..cb41dfa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -334,7 +334,7 @@ version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -1728,7 +1728,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -1997,7 +1997,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -2353,9 +2353,9 @@ checksum = "fd3ca314f692efd6c868f8408f53fe444634a845f96c028b97d35f6a1f79f0ee" [[package]] name = "tokio" -version = "1.54.0" +version = "1.54.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c168a474b95bfecfe908a65d4bdffc523144b649a74c09c286afb35d53e0bc" +checksum = "b52fd3255258d26fac7264ab5a76b53c13367136dc011d3d6ad4f8ed070396a3" dependencies = [ "bytes", "libc", @@ -2654,7 +2654,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] diff --git a/crates/feedparser-rs-node/index.js b/crates/feedparser-rs-node/index.js index 84e9717..640f8b1 100644 --- a/crates/feedparser-rs-node/index.js +++ b/crates/feedparser-rs-node/index.js @@ -6,8 +6,13 @@ const { readFileSync } = require('fs') let nativeBinding = null // Which artifact actually loaded. The WASI fallback chain overwrites it with // the flavor it resolved; the late native retry below leaves it alone because -// it only runs while no WASI candidate has been loaded. +// it only runs while no WASI candidate has been loaded. The take-over check +// after the load-failure block can also set it. let __napiLoadedBindingTarget = 'native' +// What this loader's own `requireNative()` calls returned. The check after +// the load-failure block compares it with `nativeBinding` to tell a binding +// this loader loaded from one that code outside it put in its place. +let __napiRequiredNativeBinding = null const loadErrors = [] const isMusl = () => { @@ -269,6 +274,22 @@ function requireNative() { } catch (e) { loadErrors.push(e) } + } else if (process.arch === 'ppc64') { + try { + return require('./feedparser-rs.freebsd-ppc64.node') + } catch (e) { + loadErrors.push(e) + } + try { + const binding = require('feedparser-rs-freebsd-ppc64') + const bindingPackageVersion = require('feedparser-rs-freebsd-ppc64/package.json').version + if (bindingPackageVersion !== '0.7.1' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { + throw new Error(`Native binding package version mismatch, expected 0.7.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) + } + return binding + } catch (e) { + loadErrors.push(e) + } } else { loadErrors.push(new Error(`Unsupported architecture on FreeBSD: ${process.arch}`)) } @@ -585,6 +606,7 @@ const forceWasi = if (!forceWasi) { nativeBinding = requireNative() + __napiRequiredNativeBinding = nativeBinding } if (!nativeBinding || forceWasi) { @@ -686,6 +708,7 @@ if (!nativeBinding || forceWasi) { !__napiWasiFlavorRequested ) { nativeBinding = requireNative() + __napiRequiredNativeBinding = nativeBinding } if ((forceWasiError || __napiWasiFlavorRequested) && !wasiBindingLoaded) { const error = new Error( @@ -713,6 +736,40 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } +// A package can patch its own fallback in front of the load-failure check +// above, e.g. a WebContainer download through `napi-postinstall/fallback`. +// That fallback swaps `nativeBinding` for a generated WASI loader, which has +// already stamped its own flavor, while the target above still says 'native'. +// Take that flavor over, or the CommonJS stamp throws a conflict and the ESM +// export reports the wrong artifact. Three limits keep the conflict check: +// - only a binding this loader did not load itself, so a native addon whose +// `#[napi(module_exports)]` hook claims the name is still rejected; +// - only an own data property, read through its descriptor, so no addon +// getter runs here, and it must read back the same, as the stamp reads it; +// - only a flavor in `__napiWasiFlavors`, the ones this loader's own WASI +// chain can report ('wasm32-wasi' for a package without a WASI target). +// This is metadata and never fails a load: a throwing Proxy trap keeps 'native'. +if ( + __napiLoadedBindingTarget === 'native' && + nativeBinding !== __napiRequiredNativeBinding +) { + try { + const __napiBindingTargetDescriptor = Object.getOwnPropertyDescriptor( + nativeBinding, + '__napiBindingTarget', + ) + if ( + __napiBindingTargetDescriptor && + __napiWasiFlavors.indexOf(__napiBindingTargetDescriptor.value) !== -1 && + nativeBinding.__napiBindingTarget === __napiBindingTargetDescriptor.value + ) { + __napiLoadedBindingTarget = __napiBindingTargetDescriptor.value + } + } catch { + // keep 'native' + } +} + function __napiStampBindingTarget(exportsObject, target) { if ( Object.prototype.hasOwnProperty.call(exportsObject, '__napiBindingTarget') diff --git a/crates/feedparser-rs-node/pnpm-lock.yaml b/crates/feedparser-rs-node/pnpm-lock.yaml index 8572c2a..a390c44 100644 --- a/crates/feedparser-rs-node/pnpm-lock.yaml +++ b/crates/feedparser-rs-node/pnpm-lock.yaml @@ -16,7 +16,7 @@ importers: version: 2.6.2 '@napi-rs/cli': specifier: ^3.10.8 - version: 3.10.8(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + version: 3.10.9(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) c8: specifier: ^12.0.0 version: 12.0.0 @@ -262,8 +262,8 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@napi-rs/cli@3.10.8': - resolution: {integrity: sha512-hg7m8VwECTIIHxNzajDG8QgtTOEVAKiIVLCLCW90Th6Z5R/ijWjh16iaQrRvXj4ve/S2fcXYo5cctCWJ8aVxIg==} + '@napi-rs/cli@3.10.9': + resolution: {integrity: sha512-RpzJrTDlSxUi2Deo+dh4bmDTKklAVe295aSQjZspwbZyUBG7twbXbiKskL2w/bL4kNg3DdkrwbI/iQwI9kgQaQ==} engines: {node: ^20.17.0 || ^22.13.0 || >= 23.5.0} hasBin: true peerDependencies: @@ -1148,7 +1148,7 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.6.0 - '@napi-rs/cli@3.10.8(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': + '@napi-rs/cli@3.10.9(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': dependencies: '@inquirer/prompts': 8.7.4 '@napi-rs/cross-toolchain': 1.0.3 @@ -1163,8 +1163,8 @@ snapshots: typanion: 3.14.0 typescript: 6.0.3 optionalDependencies: - '@emnapi/core': 1.11.2 - '@emnapi/runtime': 1.11.2 + '@emnapi/core': 1.9.2 + '@emnapi/runtime': 1.9.2 transitivePeerDependencies: - '@napi-rs/cross-toolchain-arm64-target-aarch64' - '@napi-rs/cross-toolchain-arm64-target-armv7'