Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 58 additions & 1 deletion crates/feedparser-rs-node/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = () => {
Expand Down Expand Up @@ -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}`))
}
Expand Down Expand Up @@ -585,6 +606,7 @@ const forceWasi =

if (!forceWasi) {
nativeBinding = requireNative()
__napiRequiredNativeBinding = nativeBinding
}

if (!nativeBinding || forceWasi) {
Expand Down Expand Up @@ -686,6 +708,7 @@ if (!nativeBinding || forceWasi) {
!__napiWasiFlavorRequested
) {
nativeBinding = requireNative()
__napiRequiredNativeBinding = nativeBinding
}
if ((forceWasiError || __napiWasiFlavorRequested) && !wasiBindingLoaded) {
const error = new Error(
Expand Down Expand Up @@ -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')
Expand Down
12 changes: 6 additions & 6 deletions crates/feedparser-rs-node/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading