Skip to content

Commit 3a0d8d9

Browse files
authored
fix(wasm): reset assetUrlRE.lastIndex before .test() in SSR builds (#21780)
1 parent 6803be6 commit 3a0d8d9

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { describe, expect, test } from 'vitest'
2+
import { assetUrlRE } from '../../plugins/asset'
3+
4+
describe('wasm plugin assetUrlRE usage', () => {
5+
// Regression test: assetUrlRE has the /g flag, which makes .test()
6+
// stateful via lastIndex. When the wasm plugin called assetUrlRE.test()
7+
// on consecutive asset URLs without resetting lastIndex, the second call
8+
// would fail because lastIndex was already past the end of the string.
9+
// This caused a non-deterministic bug where ~half of wasm files would
10+
// miss the __VITE_ASSET__ -> __VITE_WASM_INIT__ replacement in SSR
11+
// builds, leading to ENOENT errors at runtime.
12+
test('assetUrlRE.test() fails on second call without lastIndex reset', () => {
13+
const url1 = '__VITE_ASSET__abc123__'
14+
const url2 = '__VITE_ASSET__def456__'
15+
16+
// Simulate the bug: two consecutive .test() calls without resetting lastIndex
17+
assetUrlRE.lastIndex = 0
18+
expect(assetUrlRE.test(url1)).toBe(true)
19+
// After the first successful match, lastIndex is advanced past the string
20+
expect(assetUrlRE.lastIndex).toBeGreaterThan(0)
21+
// The second call fails because lastIndex > url2.length
22+
expect(assetUrlRE.test(url2)).toBe(false)
23+
24+
// Clean up
25+
assetUrlRE.lastIndex = 0
26+
})
27+
28+
test('assetUrlRE.test() succeeds on consecutive calls with lastIndex reset', () => {
29+
const url1 = '__VITE_ASSET__abc123__'
30+
const url2 = '__VITE_ASSET__def456__'
31+
32+
assetUrlRE.lastIndex = 0
33+
expect(assetUrlRE.test(url1)).toBe(true)
34+
35+
// The fix: reset lastIndex before the next call
36+
assetUrlRE.lastIndex = 0
37+
expect(assetUrlRE.test(url2)).toBe(true)
38+
39+
// Clean up
40+
assetUrlRE.lastIndex = 0
41+
})
42+
})

packages/vite/src/node/plugins/wasm.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ export default ${wasmHelperCode}
9898

9999
id = id.split('?')[0]
100100
let url = await fileToUrl(this, id, ssr)
101+
assetUrlRE.lastIndex = 0
101102
if (ssr && assetUrlRE.test(url)) {
102103
url = url.replace('__VITE_ASSET__', '__VITE_WASM_INIT__')
103104
}

0 commit comments

Comments
 (0)