Skip to content

Commit 249e0e6

Browse files
committed
Fix source map HMR via unique nonce
1 parent 511d7b9 commit 249e0e6

File tree

2 files changed

+19
-17
lines changed

2 files changed

+19
-17
lines changed

core/index.js

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,25 @@ class Token {
1414
}
1515
}
1616

17-
let invalidationToken = new Token();
17+
const state = {
18+
sourceNonce: 0,
19+
invalidationToken: new Token(),
20+
mapperCache: new Map(),
21+
sourceCache: new Map(),
22+
inboundRequests: new Set(),
23+
// List of mapped class names for batch rendering
24+
renderQueue: [],
25+
};
1826

1927
function task(fn) {
20-
const token = invalidationToken;
28+
const token = state.invalidationToken;
2129
return result => {
2230
if (!token.cancelled) {
2331
return fn(result);
2432
}
2533
};
2634
}
2735

28-
const state = {
29-
mapperCache: new Map(),
30-
sourceCache: new Map(),
31-
inboundRequests: new Set(),
32-
// List of mapped class names for batch rendering
33-
renderQueue: [],
34-
};
35-
3636
export function initWasm(url) {
3737
SourceMapConsumer.initialize({
3838
"lib/mappings.wasm": url,
@@ -60,7 +60,8 @@ export function renderCSS() {
6060

6161
const map = {
6262
version: 3,
63-
sources,
63+
// Source URLs need to be unique for source maps to reload
64+
sources: sources.map(source => `${source}?n=${state.sourceNonce}`),
6465
mappings,
6566
sourcesContent: sources.map(source => state.sourceCache.get(source)),
6667
};
@@ -77,15 +78,16 @@ export function addMappedClass({className, stackInfo, stackIndex}) {
7778

7879
export function invalidate() {
7980
// Token should be immediately invalidated
80-
invalidationToken.cancel();
81-
invalidationToken = new Token();
81+
state.invalidationToken.cancel();
82+
state.invalidationToken = new Token();
8283

8384
// After invalidation, existing mapped class names should be rendered
8485
// using the existing sourceCache
8586
const css = renderCSS();
8687

8788
state.mapperCache = new Map();
8889
state.sourceCache = new Map();
90+
state.sourceNonce++;
8991

9092
// Replay inbound requests with cleared caches
9193
for (const request of state.inboundRequests) {

tests/index.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,10 @@ test(`replaying requests after invalidation`, async t => {
8787
t.equal(pos.column, 0, "mapped column matches expected");
8888
t.equal(
8989
pos.source,
90-
"webpack:///client.js",
90+
"webpack:///client.js?n=1",
9191
"mapped source matches expected",
9292
);
93-
const content = consumer.sourceContentFor("webpack:///client.js");
93+
const content = consumer.sourceContentFor("webpack:///client.js?n=1");
9494
t.equal(
9595
content,
9696
fixtures.clientSource,
@@ -142,10 +142,10 @@ function testSingleMap(route) {
142142
t.equal(pos.column, 0, "mapped column matches expected");
143143
t.equal(
144144
pos.source,
145-
"webpack:///client.js",
145+
"webpack:///client.js?n=0",
146146
"mapped source matches expected",
147147
);
148-
const content = consumer.sourceContentFor("webpack:///client.js");
148+
const content = consumer.sourceContentFor("webpack:///client.js?n=0");
149149
t.equal(
150150
content,
151151
fixtures.clientSource,

0 commit comments

Comments
 (0)