diff --git a/napi/transform/index.d.ts b/napi/transform/index.d.ts index 43b61c6e94bd6..e451937b74502 100644 --- a/napi/transform/index.d.ts +++ b/napi/transform/index.d.ts @@ -1,25 +1,30 @@ -/* tslint:disable */ -/* eslint-disable */ - /* auto-generated by NAPI-RS */ - -export interface TypeScriptBindingOptions { - jsxPragma?: string - jsxPragmaFrag?: string - onlyRemoveTypeImports?: boolean - allowNamespaces?: boolean - allowDeclareFields?: boolean +/* eslint-disable */ +export interface ArrowFunctionsBindingOptions { /** - * Also generate a `.d.ts` declaration file for TypeScript files. - * - * The source file must be compliant with all - * [`isolatedDeclarations`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html#isolated-declarations) - * requirements. + * This option enables the following: + * * Wrap the generated function in .bind(this) and keeps uses of this inside the function as-is, instead of using a renamed this. + * * Add a runtime check to ensure the functions are not instantiated. + * * Add names to arrow functions. * * @default false */ - declaration?: boolean + spec?: boolean +} + +export interface Es2015BindingOptions { + /** Transform arrow functions into function expressions. */ + arrowFunction?: ArrowFunctionsBindingOptions +} + +/** TypeScript Isolated Declarations for Standalone DTS Emit */ +export declare function isolatedDeclaration(filename: string, sourceText: string): IsolatedDeclarationsResult + +export interface IsolatedDeclarationsResult { + sourceText: string + errors: Array } + /** * Configure how TSX and JSX are transformed. * @@ -104,21 +109,30 @@ export interface ReactBindingOptions { */ useSpread?: boolean } -export interface ArrowFunctionsBindingOptions { - /** - * This option enables the following: - * * Wrap the generated function in .bind(this) and keeps uses of this inside the function as-is, instead of using a renamed this. - * * Add a runtime check to ensure the functions are not instantiated. - * * Add names to arrow functions. - * - * @default false - */ - spec?: boolean -} -export interface Es2015BindingOptions { - /** Transform arrow functions into function expressions. */ - arrowFunction?: ArrowFunctionsBindingOptions + +export interface SourceMap { + file?: string + mappings?: string + sourceRoot?: string + sources?: Array + sourcesContent?: Array + names?: Array } + +/** + * Transpile a JavaScript or TypeScript into a target ECMAScript version. + * + * @param filename The name of the file being transformed. If this is a + * relative path, consider setting the {@link TransformOptions#cwd} option.. + * @param sourceText the source code itself + * @param options The options for the transformation. See {@link + * TransformOptions} for more information. + * + * @returns an object containing the transformed code, source maps, and any + * errors that occurred during parsing or transformation. + */ +export declare function transform(filename: string, sourceText: string, options?: TransformOptions | undefined | null): TransformResult + /** * Options for transforming a JavaScript or TypeScript file. * @@ -154,20 +168,7 @@ export interface TransformOptions { */ sourcemap?: boolean } -export interface SourceMap { - file?: string - mappings?: string - sourceRoot?: string - sources?: Array - sourcesContent?: Array - names?: Array -} -export interface IsolatedDeclarationsResult { - sourceText: string - errors: Array -} -/** TypeScript Isolated Declarations for Standalone DTS Emit */ -declare function isolatedDeclaration(filename: string, sourceText: string): IsolatedDeclarationsResult + export interface TransformResult { /** * The transformed code. @@ -207,16 +208,22 @@ export interface TransformResult { */ errors: Array } -/** - * Transpile a JavaScript or TypeScript into a target ECMAScript version. - * - * @param filename The name of the file being transformed. If this is a - * relative path, consider setting the {@link TransformOptions#cwd} option.. - * @param sourceText the source code itself - * @param options The options for the transformation. See {@link - * TransformOptions} for more information. - * - * @returns an object containing the transformed code, source maps, and any - * errors that occurred during parsing or transformation. - */ -declare function transform(filename: string, sourceText: string, options?: TransformOptions | undefined | null): TransformResult + +export interface TypeScriptBindingOptions { + jsxPragma?: string + jsxPragmaFrag?: string + onlyRemoveTypeImports?: boolean + allowNamespaces?: boolean + allowDeclareFields?: boolean + /** + * Also generate a `.d.ts` declaration file for TypeScript files. + * + * The source file must be compliant with all + * [`isolatedDeclarations`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html#isolated-declarations) + * requirements. + * + * @default false + */ + declaration?: boolean +} + diff --git a/napi/transform/index.js b/napi/transform/index.js index 405b84e013750..e1092b640ae6c 100644 --- a/napi/transform/index.js +++ b/napi/transform/index.js @@ -1,316 +1,365 @@ -/* tslint:disable */ +// prettier-ignore /* eslint-disable */ -/* prettier-ignore */ - /* auto-generated by NAPI-RS */ -const { existsSync, readFileSync } = require('fs') -const { join } = require('path') - -const { platform, arch } = process +const { readFileSync } = require('fs') let nativeBinding = null -let localFileExisted = false -let loadError = null +const loadErrors = [] -function isMusl() { - // For Node 10 - if (!process.report || typeof process.report.getReport !== 'function') { - try { - const lddPath = require('child_process').execSync('which ldd').toString().trim() - return readFileSync(lddPath, 'utf8').includes('musl') - } catch (e) { +const isMusl = () => { + let musl = false + if (process.platform === 'linux') { + musl = isMuslFromFilesystem() + if (musl === null) { + musl = isMuslFromReport() + } + if (musl === null) { + musl = isMuslFromChildProcess() + } + } + return musl +} + +const isFileMusl = (f) => f.includes('libc.musl-') || f.includes('ld-musl-') + +const isMuslFromFilesystem = () => { + try { + return readFileSync('/usr/bin/ldd', 'utf-8').includes('musl') + } catch { + return null + } +} + +const isMuslFromReport = () => { + const report = typeof process.report.getReport === 'function' ? process.report.getReport() : null + if (!report) { + return null + } + if (report.header && report.header.glibcVersionRuntime) { + return false + } + if (Array.isArray(report.sharedObjects)) { + if (report.sharedObjects.some(isFileMusl)) { return true } - } else { - const { glibcVersionRuntime } = process.report.getReport().header - return !glibcVersionRuntime } + return false } -switch (platform) { - case 'android': - switch (arch) { - case 'arm64': - localFileExisted = existsSync(join(__dirname, 'index.android-arm64.node')) +const isMuslFromChildProcess = () => { + try { + return require('child_process').execSync('ldd --version', { encoding: 'utf8' }).includes('musl') + } catch (e) { + // If we reach this case, we don't know if the system is musl or not, so is better to just fallback to false + return false + } +} + +function requireNative() { + if (process.platform === 'android') { + if (process.arch === 'arm64') { + try { + return require('./transform.android-arm64.node') + } catch (e) { + loadErrors.push(e) + } + try { + return require('@oxc-transform/binding-android-arm64') + } catch (e) { + loadErrors.push(e) + } + + } else if (process.arch === 'arm') { + try { + return require('./transform.android-arm-eabi.node') + } catch (e) { + loadErrors.push(e) + } + try { + return require('@oxc-transform/binding-android-arm-eabi') + } catch (e) { + loadErrors.push(e) + } + + } else { + loadErrors.push(new Error(`Unsupported architecture on Android ${process.arch}`)) + } + } else if (process.platform === 'win32') { + if (process.arch === 'x64') { + try { + return require('./transform.win32-x64-msvc.node') + } catch (e) { + loadErrors.push(e) + } + try { + return require('@oxc-transform/binding-win32-x64-msvc') + } catch (e) { + loadErrors.push(e) + } + + } else if (process.arch === 'ia32') { + try { + return require('./transform.win32-ia32-msvc.node') + } catch (e) { + loadErrors.push(e) + } + try { + return require('@oxc-transform/binding-win32-ia32-msvc') + } catch (e) { + loadErrors.push(e) + } + + } else if (process.arch === 'arm64') { + try { + return require('./transform.win32-arm64-msvc.node') + } catch (e) { + loadErrors.push(e) + } + try { + return require('@oxc-transform/binding-win32-arm64-msvc') + } catch (e) { + loadErrors.push(e) + } + + } else { + loadErrors.push(new Error(`Unsupported architecture on Windows: ${process.arch}`)) + } + } else if (process.platform === 'darwin') { + try { + return require('./transform.darwin-universal.node') + } catch (e) { + loadErrors.push(e) + } + try { + return require('@oxc-transform/binding-darwin-universal') + } catch (e) { + loadErrors.push(e) + } + + if (process.arch === 'x64') { + try { + return require('./transform.darwin-x64.node') + } catch (e) { + loadErrors.push(e) + } + try { + return require('@oxc-transform/binding-darwin-x64') + } catch (e) { + loadErrors.push(e) + } + + } else if (process.arch === 'arm64') { + try { + return require('./transform.darwin-arm64.node') + } catch (e) { + loadErrors.push(e) + } + try { + return require('@oxc-transform/binding-darwin-arm64') + } catch (e) { + loadErrors.push(e) + } + + } else { + loadErrors.push(new Error(`Unsupported architecture on macOS: ${process.arch}`)) + } + } else if (process.platform === 'freebsd') { + if (process.arch === 'x64') { + try { + return require('./transform.freebsd-x64.node') + } catch (e) { + loadErrors.push(e) + } + try { + return require('@oxc-transform/binding-freebsd-x64') + } catch (e) { + loadErrors.push(e) + } + + } else if (process.arch === 'arm64') { + try { + return require('./transform.freebsd-arm64.node') + } catch (e) { + loadErrors.push(e) + } + try { + return require('@oxc-transform/binding-freebsd-arm64') + } catch (e) { + loadErrors.push(e) + } + + } else { + loadErrors.push(new Error(`Unsupported architecture on FreeBSD: ${process.arch}`)) + } + } else if (process.platform === 'linux') { + if (process.arch === 'x64') { + if (isMusl()) { try { - if (localFileExisted) { - nativeBinding = require('./index.android-arm64.node') - } else { - nativeBinding = require('@oxc-transform/binding-android-arm64') - } - } catch (e) { - loadError = e - } - break - case 'arm': - localFileExisted = existsSync(join(__dirname, 'index.android-arm-eabi.node')) + return require('./transform.linux-x64-musl.node') + } catch (e) { + loadErrors.push(e) + } + try { + return require('@oxc-transform/binding-linux-x64-musl') + } catch (e) { + loadErrors.push(e) + } + + } else { try { - if (localFileExisted) { - nativeBinding = require('./index.android-arm-eabi.node') - } else { - nativeBinding = require('@oxc-transform/binding-android-arm-eabi') - } - } catch (e) { - loadError = e - } - break - default: - throw new Error(`Unsupported architecture on Android ${arch}`) - } - break - case 'win32': - switch (arch) { - case 'x64': - localFileExisted = existsSync( - join(__dirname, 'index.win32-x64-msvc.node') - ) + return require('./transform.linux-x64-gnu.node') + } catch (e) { + loadErrors.push(e) + } + try { + return require('@oxc-transform/binding-linux-x64-gnu') + } catch (e) { + loadErrors.push(e) + } + + } + } else if (process.arch === 'arm64') { + if (isMusl()) { try { - if (localFileExisted) { - nativeBinding = require('./index.win32-x64-msvc.node') - } else { - nativeBinding = require('@oxc-transform/binding-win32-x64-msvc') - } - } catch (e) { - loadError = e - } - break - case 'ia32': - localFileExisted = existsSync( - join(__dirname, 'index.win32-ia32-msvc.node') - ) + return require('./transform.linux-arm64-musl.node') + } catch (e) { + loadErrors.push(e) + } + try { + return require('@oxc-transform/binding-linux-arm64-musl') + } catch (e) { + loadErrors.push(e) + } + + } else { try { - if (localFileExisted) { - nativeBinding = require('./index.win32-ia32-msvc.node') - } else { - nativeBinding = require('@oxc-transform/binding-win32-ia32-msvc') - } - } catch (e) { - loadError = e - } - break - case 'arm64': - localFileExisted = existsSync( - join(__dirname, 'index.win32-arm64-msvc.node') - ) + return require('./transform.linux-arm64-gnu.node') + } catch (e) { + loadErrors.push(e) + } + try { + return require('@oxc-transform/binding-linux-arm64-gnu') + } catch (e) { + loadErrors.push(e) + } + + } + } else if (process.arch === 'arm') { + if (isMusl()) { try { - if (localFileExisted) { - nativeBinding = require('./index.win32-arm64-msvc.node') - } else { - nativeBinding = require('@oxc-transform/binding-win32-arm64-msvc') - } - } catch (e) { - loadError = e - } - break - default: - throw new Error(`Unsupported architecture on Windows: ${arch}`) - } - break - case 'darwin': - localFileExisted = existsSync(join(__dirname, 'index.darwin-universal.node')) - try { - if (localFileExisted) { - nativeBinding = require('./index.darwin-universal.node') + return require('./transform.linux-arm-musleabihf.node') + } catch (e) { + loadErrors.push(e) + } + try { + return require('@oxc-transform/binding-linux-arm-musleabihf') + } catch (e) { + loadErrors.push(e) + } + } else { - nativeBinding = require('@oxc-transform/binding-darwin-universal') + try { + return require('./transform.linux-arm-gnueabihf.node') + } catch (e) { + loadErrors.push(e) + } + try { + return require('@oxc-transform/binding-linux-arm-gnueabihf') + } catch (e) { + loadErrors.push(e) + } + } - break - } catch {} - switch (arch) { - case 'x64': - localFileExisted = existsSync(join(__dirname, 'index.darwin-x64.node')) + } else if (process.arch === 'riscv64') { + if (isMusl()) { try { - if (localFileExisted) { - nativeBinding = require('./index.darwin-x64.node') - } else { - nativeBinding = require('@oxc-transform/binding-darwin-x64') - } - } catch (e) { - loadError = e - } - break - case 'arm64': - localFileExisted = existsSync( - join(__dirname, 'index.darwin-arm64.node') - ) + return require('./transform.linux-riscv64-musl.node') + } catch (e) { + loadErrors.push(e) + } + try { + return require('@oxc-transform/binding-linux-riscv64-musl') + } catch (e) { + loadErrors.push(e) + } + + } else { try { - if (localFileExisted) { - nativeBinding = require('./index.darwin-arm64.node') - } else { - nativeBinding = require('@oxc-transform/binding-darwin-arm64') - } - } catch (e) { - loadError = e - } - break - default: - throw new Error(`Unsupported architecture on macOS: ${arch}`) + return require('./transform.linux-riscv64-gnu.node') + } catch (e) { + loadErrors.push(e) + } + try { + return require('@oxc-transform/binding-linux-riscv64-gnu') + } catch (e) { + loadErrors.push(e) + } + + } + } else if (process.arch === 'ppc64') { + try { + return require('./transform.linux-ppc64-gnu.node') + } catch (e) { + loadErrors.push(e) + } + try { + return require('@oxc-transform/binding-linux-ppc64-gnu') + } catch (e) { + loadErrors.push(e) + } + + } else if (process.arch === 's390x') { + try { + return require('./transform.linux-s390x-gnu.node') + } catch (e) { + loadErrors.push(e) + } + try { + return require('@oxc-transform/binding-linux-s390x-gnu') + } catch (e) { + loadErrors.push(e) + } + + } else { + loadErrors.push(new Error(`Unsupported architecture on Linux: ${process.arch}`)) } - break - case 'freebsd': - if (arch !== 'x64') { - throw new Error(`Unsupported architecture on FreeBSD: ${arch}`) + } else { + loadErrors.push(new Error(`Unsupported OS: ${process.platform}, architecture: ${process.arch}`)) + } +} + +nativeBinding = requireNative() + +if (!nativeBinding || process.env.NAPI_RS_FORCE_WASI) { + try { + nativeBinding = require('./transform.wasi.cjs') + } catch (err) { + if (process.env.NAPI_RS_FORCE_WASI) { + console.error(err) } - localFileExisted = existsSync(join(__dirname, 'index.freebsd-x64.node')) + } + if (!nativeBinding) { try { - if (localFileExisted) { - nativeBinding = require('./index.freebsd-x64.node') - } else { - nativeBinding = require('@oxc-transform/binding-freebsd-x64') + nativeBinding = require('@oxc-transform/binding-wasm32-wasi') + } catch (err) { + if (process.env.NAPI_RS_FORCE_WASI) { + console.error(err) } - } catch (e) { - loadError = e - } - break - case 'linux': - switch (arch) { - case 'x64': - if (isMusl()) { - localFileExisted = existsSync( - join(__dirname, 'index.linux-x64-musl.node') - ) - try { - if (localFileExisted) { - nativeBinding = require('./index.linux-x64-musl.node') - } else { - nativeBinding = require('@oxc-transform/binding-linux-x64-musl') - } - } catch (e) { - loadError = e - } - } else { - localFileExisted = existsSync( - join(__dirname, 'index.linux-x64-gnu.node') - ) - try { - if (localFileExisted) { - nativeBinding = require('./index.linux-x64-gnu.node') - } else { - nativeBinding = require('@oxc-transform/binding-linux-x64-gnu') - } - } catch (e) { - loadError = e - } - } - break - case 'arm64': - if (isMusl()) { - localFileExisted = existsSync( - join(__dirname, 'index.linux-arm64-musl.node') - ) - try { - if (localFileExisted) { - nativeBinding = require('./index.linux-arm64-musl.node') - } else { - nativeBinding = require('@oxc-transform/binding-linux-arm64-musl') - } - } catch (e) { - loadError = e - } - } else { - localFileExisted = existsSync( - join(__dirname, 'index.linux-arm64-gnu.node') - ) - try { - if (localFileExisted) { - nativeBinding = require('./index.linux-arm64-gnu.node') - } else { - nativeBinding = require('@oxc-transform/binding-linux-arm64-gnu') - } - } catch (e) { - loadError = e - } - } - break - case 'arm': - if (isMusl()) { - localFileExisted = existsSync( - join(__dirname, 'index.linux-arm-musleabihf.node') - ) - try { - if (localFileExisted) { - nativeBinding = require('./index.linux-arm-musleabihf.node') - } else { - nativeBinding = require('@oxc-transform/binding-linux-arm-musleabihf') - } - } catch (e) { - loadError = e - } - } else { - localFileExisted = existsSync( - join(__dirname, 'index.linux-arm-gnueabihf.node') - ) - try { - if (localFileExisted) { - nativeBinding = require('./index.linux-arm-gnueabihf.node') - } else { - nativeBinding = require('@oxc-transform/binding-linux-arm-gnueabihf') - } - } catch (e) { - loadError = e - } - } - break - case 'riscv64': - if (isMusl()) { - localFileExisted = existsSync( - join(__dirname, 'index.linux-riscv64-musl.node') - ) - try { - if (localFileExisted) { - nativeBinding = require('./index.linux-riscv64-musl.node') - } else { - nativeBinding = require('@oxc-transform/binding-linux-riscv64-musl') - } - } catch (e) { - loadError = e - } - } else { - localFileExisted = existsSync( - join(__dirname, 'index.linux-riscv64-gnu.node') - ) - try { - if (localFileExisted) { - nativeBinding = require('./index.linux-riscv64-gnu.node') - } else { - nativeBinding = require('@oxc-transform/binding-linux-riscv64-gnu') - } - } catch (e) { - loadError = e - } - } - break - case 's390x': - localFileExisted = existsSync( - join(__dirname, 'index.linux-s390x-gnu.node') - ) - try { - if (localFileExisted) { - nativeBinding = require('./index.linux-s390x-gnu.node') - } else { - nativeBinding = require('@oxc-transform/binding-linux-s390x-gnu') - } - } catch (e) { - loadError = e - } - break - default: - throw new Error(`Unsupported architecture on Linux: ${arch}`) } - break - default: - throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`) + } } if (!nativeBinding) { - if (loadError) { - throw loadError + if (loadErrors.length > 0) { + // TODO Link to documentation with potential fixes + // - The package owner could build/publish bindings for this arch + // - The user may need to bundle the correct files + // - The user may need to re-install node_modules to get new packages + throw new Error('Failed to load native binding', { cause: loadErrors }) } throw new Error(`Failed to load native binding`) } -const { isolatedDeclaration, transform } = nativeBinding - -module.exports.isolatedDeclaration = isolatedDeclaration -module.exports.transform = transform +module.exports.isolatedDeclaration = nativeBinding.isolatedDeclaration +module.exports.transform = nativeBinding.transform