oxc-coverage-instrument 0.7.2 → 0.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/browser.js CHANGED
@@ -1 +1,17 @@
1
- export * from '@oxc-coverage-instrument/binding-wasm32-wasi'
1
+ // oxc-coverage-instrument: browser WASI selector (issue #87)
2
+ const binding =
3
+ globalThis.OXC_COVERAGE_FORCE_WASI_SINGLE_THREADED === true ||
4
+ typeof SharedArrayBuffer === 'undefined'
5
+ ? await import('@oxc-coverage-instrument/binding-wasm32-wasi-singlethreaded')
6
+ : await import('@oxc-coverage-instrument/binding-wasm32-wasi');
7
+
8
+ const api = binding.default ?? binding;
9
+
10
+ export default api;
11
+ export const instrument = binding.instrument ?? api.instrument;
12
+ export const remapCoverageMap = binding.remapCoverageMap ?? api.remapCoverageMap;
13
+ export const remapCoverageMapWithLoader =
14
+ binding.remapCoverageMapWithLoader ?? api.remapCoverageMapWithLoader;
15
+ export const v8ToIstanbul = binding.v8ToIstanbul ?? api.v8ToIstanbul;
16
+ export const v8ToIstanbulWithLoader =
17
+ binding.v8ToIstanbulWithLoader ?? api.v8ToIstanbulWithLoader;
@@ -4,24 +4,40 @@ import {
4
4
  instantiateNapiModuleSync as __emnapiInstantiateNapiModuleSync,
5
5
  WASI as __WASI,
6
6
  } from '@napi-rs/wasm-runtime'
7
+ import __wasmModule from './coverage-instrument.wasm32-wasi.wasm'
7
8
 
8
9
 
9
10
 
11
+
12
+ // oxc-coverage-instrument: SharedArrayBuffer guard (issue #89)
13
+ if (typeof SharedArrayBuffer === 'undefined') {
14
+ throw new Error(
15
+ 'oxc-coverage-instrument: the browser WASM binding requires SharedArrayBuffer. ' +
16
+ 'Enable Cross-Origin-Opener-Policy: same-origin and ' +
17
+ 'Cross-Origin-Embedder-Policy: require-corp on your host page so the ' +
18
+ 'browser is cross-origin isolated. See ' +
19
+ 'https://github.com/fallow-rs/oxc-coverage-instrument#runtime-matrix',
20
+ );
21
+ }
22
+
10
23
  const __wasi = new __WASI({
11
24
  version: 'preview1',
12
25
  })
13
26
 
14
- const __wasmUrl = new URL('./coverage-instrument.wasm32-wasi.wasm', import.meta.url).href
15
27
  const __emnapiContext = __emnapiGetDefaultContext()
16
28
 
17
29
 
18
30
  const __sharedMemory = new WebAssembly.Memory({
19
31
  initial: 4000,
20
32
  maximum: 65536,
21
- shared: true,
22
33
  })
23
34
 
24
- const __wasmFile = await fetch(__wasmUrl).then((res) => res.arrayBuffer())
35
+ const __wasmFile =
36
+ __wasmModule instanceof WebAssembly.Module
37
+ ? __wasmModule
38
+ : typeof __wasmModule === 'string'
39
+ ? await fetch(__wasmModule).then((res) => res.arrayBuffer())
40
+ : __wasmModule
25
41
 
26
42
  const {
27
43
  instance: __napiInstance,
@@ -29,22 +45,17 @@ const {
29
45
  napiModule: __napiModule,
30
46
  } = __emnapiInstantiateNapiModuleSync(__wasmFile, {
31
47
  context: __emnapiContext,
32
- asyncWorkPoolSize: 4,
48
+ asyncWorkPoolSize: 0,
33
49
  wasi: __wasi,
34
- onCreateWorker() {
35
- const worker = new Worker(new URL('./wasi-worker-browser.mjs', import.meta.url), {
36
- type: 'module',
37
- })
38
-
39
-
40
- return worker
41
- },
42
50
  overwriteImports(importObject) {
43
51
  importObject.env = {
44
52
  ...importObject.env,
45
53
  ...importObject.napi,
46
54
  ...importObject.emnapi,
47
55
  memory: __sharedMemory,
56
+ __tls_align: 1,
57
+ __tls_size: 0,
58
+ __wasm_init_tls: () => {},
48
59
  }
49
60
  return importObject
50
61
  },
@@ -29,7 +29,6 @@ const __emnapiContext = __emnapiGetDefaultContext()
29
29
  const __sharedMemory = new WebAssembly.Memory({
30
30
  initial: 4000,
31
31
  maximum: 65536,
32
- shared: true,
33
32
  })
34
33
 
35
34
  let __wasmFilePath = __nodePath.join(__dirname, 'coverage-instrument.wasm32-wasi.wasm')
@@ -39,63 +38,25 @@ if (__nodeFs.existsSync(__wasmDebugFilePath)) {
39
38
  __wasmFilePath = __wasmDebugFilePath
40
39
  } else if (!__nodeFs.existsSync(__wasmFilePath)) {
41
40
  try {
42
- __wasmFilePath = require.resolve('@oxc-coverage-instrument/binding-wasm32-wasi/coverage-instrument.wasm32-wasi.wasm')
41
+ __wasmFilePath = require.resolve('@oxc-coverage-instrument/binding-wasm32-wasi-singlethreaded-singlethreaded/coverage-instrument.wasm32-wasi.wasm')
43
42
  } catch {
44
- throw new Error('Cannot find coverage-instrument.wasm32-wasi.wasm file, and @oxc-coverage-instrument/binding-wasm32-wasi package is not installed.')
43
+ throw new Error('Cannot find coverage-instrument.wasm32-wasi.wasm file, and @oxc-coverage-instrument/binding-wasm32-wasi-singlethreaded-singlethreaded package is not installed.')
45
44
  }
46
45
  }
47
46
 
48
47
  const { instance: __napiInstance, module: __wasiModule, napiModule: __napiModule } = __emnapiInstantiateNapiModuleSync(__nodeFs.readFileSync(__wasmFilePath), {
49
48
  context: __emnapiContext,
50
- asyncWorkPoolSize: (function() {
51
- const threadsSizeFromEnv = Number(process.env.NAPI_RS_ASYNC_WORK_POOL_SIZE ?? process.env.UV_THREADPOOL_SIZE)
52
- // NaN > 0 is false
53
- if (threadsSizeFromEnv > 0) {
54
- return threadsSizeFromEnv
55
- } else {
56
- return 4
57
- }
58
- })(),
59
- reuseWorker: true,
49
+ asyncWorkPoolSize: 0,
60
50
  wasi: __wasi,
61
- onCreateWorker() {
62
- const worker = new Worker(__nodePath.join(__dirname, 'wasi-worker.mjs'), {
63
- env: process.env,
64
- })
65
- worker.onmessage = ({ data }) => {
66
- __wasmCreateOnMessageForFsProxy(__nodeFs)(data)
67
- }
68
-
69
- // The main thread of Node.js waits for all the active handles before exiting.
70
- // But Rust threads are never waited without `thread::join`.
71
- // So here we hack the code of Node.js to prevent the workers from being referenced (active).
72
- // According to https://github.com/nodejs/node/blob/19e0d472728c79d418b74bddff588bea70a403d0/lib/internal/worker.js#L415,
73
- // a worker is consist of two handles: kPublicPort and kHandle.
74
- {
75
- const kPublicPort = Object.getOwnPropertySymbols(worker).find(s =>
76
- s.toString().includes("kPublicPort")
77
- );
78
- if (kPublicPort) {
79
- worker[kPublicPort].ref = () => {};
80
- }
81
-
82
- const kHandle = Object.getOwnPropertySymbols(worker).find(s =>
83
- s.toString().includes("kHandle")
84
- );
85
- if (kHandle) {
86
- worker[kHandle].ref = () => {};
87
- }
88
-
89
- worker.unref();
90
- }
91
- return worker
92
- },
93
51
  overwriteImports(importObject) {
94
52
  importObject.env = {
95
53
  ...importObject.env,
96
54
  ...importObject.napi,
97
55
  ...importObject.emnapi,
98
56
  memory: __sharedMemory,
57
+ __tls_align: 1,
58
+ __tls_size: 0,
59
+ __wasm_init_tls: () => {},
99
60
  }
100
61
  return importObject
101
62
  },
package/index.d.ts CHANGED
@@ -102,8 +102,13 @@ export interface InstrumentResult {
102
102
  * the Vitest istanbul reporter path. For nyc's disk-read flow (Mode A
103
103
  * fallback) use [`remap_coverage_map_with_loader`] and supply a
104
104
  * `Record<string, string>` of preloaded maps keyed by FileCoverage path.
105
+ *
106
+ * Pass `{ dropUnmapped: true }` to align with `istanbul-lib-source-maps`'s
107
+ * `transformer.js` and drop entries whose positions cannot be looked up in
108
+ * the source map (instead of silently keeping their generated-output
109
+ * coordinates). See [`RemapOptions`] for the full per-kind drop semantics.
105
110
  */
106
- export declare function remapCoverageMap(coverageJson: string): string
111
+ export declare function remapCoverageMap(coverageJson: string, options?: RemapOptions | undefined | null): string
107
112
 
108
113
  /**
109
114
  * Like [`remap_coverage_map`], but with a preloaded map dictionary used as
@@ -119,7 +124,30 @@ export declare function remapCoverageMap(coverageJson: string): string
119
124
  * [`oxc_coverage_instrument::SourceMapStore`] (Mode B continuous remap)
120
125
  * stays Rust-only until a Jest provider integration targets it directly.
121
126
  */
122
- export declare function remapCoverageMapWithLoader(coverageJson: string, sourceMaps: Record<string, string>): string
127
+ export declare function remapCoverageMapWithLoader(coverageJson: string, sourceMaps: Record<string, string>, options?: RemapOptions | undefined | null): string
128
+
129
+ /**
130
+ * Options for `remapCoverageMap` and `remapCoverageMapWithLoader`.
131
+ *
132
+ * Defaults to the legacy keep-generated-position behaviour, so callers that
133
+ * omit this argument see no change.
134
+ */
135
+ export interface RemapOptions {
136
+ /**
137
+ * When `true`, statement / function / branch entries whose positions
138
+ * cannot be looked up in the source map are pruned, along with their
139
+ * matching `s` / `f` / `b` / `bT` hit-count slots.
140
+ *
141
+ * Drop semantics mirror `istanbul-lib-source-maps`'s `transformer.js`:
142
+ * statements drop when start or end fails to remap; functions drop when
143
+ * any of `decl` / `loc` start or end fails; branch arms drop per arm,
144
+ * and the whole branch drops when no arms survive or when the umbrella
145
+ * `loc` start/end fails to remap.
146
+ *
147
+ * Defaults to `false`.
148
+ */
149
+ dropUnmapped?: boolean
150
+ }
123
151
 
124
152
  /** A coverage pragma comment that was found but not handled. */
125
153
  export interface UnhandledPragma {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oxc-coverage-instrument",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "description": "Istanbul-compatible JavaScript/TypeScript coverage instrumentation using the Oxc AST. 8-48x faster than istanbul-lib-instrument.",
5
5
  "main": "index.js",
6
6
  "browser": "browser.js",
@@ -55,6 +55,7 @@
55
55
  "x86_64-unknown-linux-musl",
56
56
  "x86_64-pc-windows-msvc",
57
57
  "aarch64-pc-windows-msvc",
58
+ "wasm32-wasip1",
58
59
  "wasm32-wasip1-threads"
59
60
  ]
60
61
  },
@@ -62,24 +63,27 @@
62
63
  "@napi-rs/wasm-runtime": "^1.1.4"
63
64
  },
64
65
  "devDependencies": {
65
- "@napi-rs/cli": "^3.6.0",
66
+ "@napi-rs/cli": "3.6.2",
66
67
  "istanbul-lib-instrument": "^6.0.3"
67
68
  },
68
69
  "scripts": {
69
- "build": "napi build --release --platform",
70
- "build:debug": "napi build --platform",
70
+ "build": "napi build --release --platform && npm run patch-shim",
71
+ "build:debug": "napi build --platform && npm run patch-shim",
72
+ "patch-shim": "node scripts/patch-wasi-browser-shim.mjs && node scripts/patch-browser-loader.mjs",
71
73
  "prepublishOnly": "napi prepublish -t npm",
72
74
  "artifacts": "napi artifacts",
73
- "test": "node test.mjs"
75
+ "test": "node test.mjs && node scripts/patch-wasi-browser-shim.test.mjs",
76
+ "test:browser-loader": "node scripts/browser-loader.test.mjs"
74
77
  },
75
78
  "optionalDependencies": {
76
- "@oxc-coverage-instrument/binding-darwin-arm64": "0.7.2",
77
- "@oxc-coverage-instrument/binding-darwin-x64": "0.7.2",
78
- "@oxc-coverage-instrument/binding-linux-arm64-gnu": "0.7.2",
79
- "@oxc-coverage-instrument/binding-linux-x64-gnu": "0.7.2",
80
- "@oxc-coverage-instrument/binding-linux-x64-musl": "0.7.2",
81
- "@oxc-coverage-instrument/binding-win32-arm64-msvc": "0.7.2",
82
- "@oxc-coverage-instrument/binding-win32-x64-msvc": "0.7.2",
83
- "@oxc-coverage-instrument/binding-wasm32-wasi": "0.7.2"
79
+ "@oxc-coverage-instrument/binding-darwin-arm64": "0.7.3",
80
+ "@oxc-coverage-instrument/binding-darwin-x64": "0.7.3",
81
+ "@oxc-coverage-instrument/binding-linux-arm64-gnu": "0.7.3",
82
+ "@oxc-coverage-instrument/binding-linux-x64-gnu": "0.7.3",
83
+ "@oxc-coverage-instrument/binding-linux-x64-musl": "0.7.3",
84
+ "@oxc-coverage-instrument/binding-win32-arm64-msvc": "0.7.3",
85
+ "@oxc-coverage-instrument/binding-win32-x64-msvc": "0.7.3",
86
+ "@oxc-coverage-instrument/binding-wasm32-wasi": "0.7.3",
87
+ "@oxc-coverage-instrument/binding-wasm32-wasi-singlethreaded": "0.7.3"
84
88
  }
85
- }
89
+ }