UNPKG

@napi-rs/cli

Version:

Cli tools for napi-rs

165 lines (146 loc) 5.25 kB
import ava, { type ExecutionContext } from 'ava' import { parseSync } from 'oxc-parser' import { createCjsBinding, createEsmBinding } from '../templates/js-binding.js' import { createWasiBrowserBinding } from '../templates/load-wasi-template.js' import { createWasiBrowserWorkerBinding } from '../templates/wasi-worker-template.js' const test = ava // Snapshot tests for full template output test('createWasiBrowserBinding default', (t) => { t.snapshot(createWasiBrowserBinding('test-wasi')) }) test('createWasiBrowserBinding with errorEvent', (t) => { t.snapshot( createWasiBrowserBinding( 'test-wasi', 4000, 65536, false, false, false, true, ), ) }) test('createWasiBrowserBinding with errorEvent and fs', (t) => { t.snapshot( createWasiBrowserBinding( 'test-wasi', 4000, 65536, true, false, false, true, ), ) }) test('createWasiBrowserWorkerBinding default', (t) => { t.snapshot(createWasiBrowserWorkerBinding(false, false)) }) test('createWasiBrowserWorkerBinding with errorEvent', (t) => { t.snapshot(createWasiBrowserWorkerBinding(false, true)) }) test('createWasiBrowserWorkerBinding with errorEvent and fs', (t) => { t.snapshot(createWasiBrowserWorkerBinding(true, true)) }) function assertValidJS(t: ExecutionContext, code: string, label: string) { const { errors } = parseSync('test.mjs', code, { sourceType: 'module' }) t.deepEqual( errors, [], `${label}: generated code should have no syntax errors`, ) } const browserBindingCases: Array<{ name: string args: Parameters<typeof createWasiBrowserBinding> }> = [ { name: 'default', args: ['test'] }, { name: 'fs', args: ['test', 4000, 65536, true] }, { name: 'asyncInit', args: ['test', 4000, 65536, false, true] }, { name: 'buffer', args: ['test', 4000, 65536, false, false, true] }, { name: 'errorEvent', args: ['test', 4000, 65536, false, false, false, true], }, { name: 'fs + errorEvent', args: ['test', 4000, 65536, true, false, false, true], }, { name: 'fs + buffer', args: ['test', 4000, 65536, true, false, true] }, { name: 'fs + buffer + errorEvent', args: ['test', 4000, 65536, true, false, true, true], }, { name: 'asyncInit + errorEvent', args: ['test', 4000, 65536, false, true, false, true], }, { name: 'all options', args: ['test', 4000, 65536, true, true, true, true] }, ] for (const { name, args } of browserBindingCases) { test(`createWasiBrowserBinding syntax valid: ${name}`, (t) => { assertValidJS(t, createWasiBrowserBinding(...args), name) }) } const workerBindingCases: Array<{ name: string args: Parameters<typeof createWasiBrowserWorkerBinding> }> = [ { name: 'default', args: [false, false] }, { name: 'fs', args: [true, false] }, { name: 'errorEvent', args: [false, true] }, { name: 'fs + errorEvent', args: [true, true] }, ] for (const { name, args } of workerBindingCases) { test(`createWasiBrowserWorkerBinding syntax valid: ${name}`, (t) => { assertValidJS(t, createWasiBrowserWorkerBinding(...args), name) }) } // The CJS binding loader ships inside published packages whose `engines` // can declare support for old Node versions (e.g. `>= 10`). It must therefore // avoid syntax/APIs newer than what those runtimes support: // - `require('node:*')` — the `node:` scheme in CommonJS `require()` is only // available on Node >= 14.18 / 16. // - optional chaining (`?.`) and nullish coalescing (`??`) — Node >= 14. // - the `new Error(message, { cause })` options form — Node < 16.9 ignores // the second argument, dropping the load-error chain; assign // `error.cause` instead. const cjsBindingCases: Array<{ name: string; code: string }> = [ { name: 'default', code: createCjsBinding('test', '@scope/test', ['sum', 'sub']), }, { name: 'with version check', code: createCjsBinding('test', '@scope/test', ['sum', 'sub'], '1.0.0'), }, ] // Matches a `node:` builtin scheme in either a `require('node:fs')` or an // `import ... from 'node:module'` specifier. const NODE_SCHEME_RE = /['"]node:/ for (const { name, code } of cjsBindingCases) { test(`createCjsBinding is Node 12 compatible: ${name}`, (t) => { assertValidJS(t, code, name) t.false( NODE_SCHEME_RE.test(code), 'CJS loader must not use the node: scheme (unsupported on Node < 14.18/16 for require())', ) t.false(code.includes('?.'), 'CJS loader must not use optional chaining') t.false(code.includes('??'), 'CJS loader must not use nullish coalescing') t.false( /\bcause:/.test(code), 'CJS loader must not pass `{ cause }` to the Error constructor (ignored on Node < 16.9); assign `error.cause` instead', ) }) } test('createEsmBinding is Node 12 compatible', (t) => { const code = createEsmBinding('test', '@scope/test', ['sum']) assertValidJS(t, code, 'esm') t.false( NODE_SCHEME_RE.test(code), 'ESM loader must not use the node: scheme (incl. `import ... from "node:module"`)', ) t.false(code.includes('?.'), 'ESM loader must not use optional chaining') t.false(code.includes('??'), 'ESM loader must not use nullish coalescing') })