Skip to content

Commit 1026fac

Browse files
authored
Add graceful handling of sourcemap fetch errors (#20)
1 parent 290a66d commit 1026fac

File tree

2 files changed

+72
-3
lines changed

2 files changed

+72
-3
lines changed

core/index.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ async function getMapper(filename) {
154154
task(src => {
155155
const url = SourceMapUrl.getFrom(src);
156156
return url
157-
? getMapperFromUrl(url, filename)
157+
? getMapperFromUrl(url, filename, src)
158158
: getIdentityMapper(filename, src);
159159
}),
160160
);
@@ -163,11 +163,13 @@ async function getMapper(filename) {
163163
return result;
164164
}
165165

166-
function getMapperFromUrl(url, filename) {
166+
function getMapperFromUrl(url, filename, src) {
167167
return getSourceMapJsonFromUrl(url, filename).then(
168168
task(map => {
169169
return new SourceMapConsumer(map);
170170
}),
171+
// Fallback to identity mapper
172+
task(() => getIdentityMapper(filename, src)),
171173
);
172174
}
173175

@@ -190,7 +192,10 @@ async function getSourceMapJsonFromUrl(url, filename) {
190192
const fullUrl = new URL(url, filename).href;
191193
return fetch(fullUrl).then(
192194
task(res => {
193-
return res.json();
195+
if (res.status === 200) {
196+
return res.json();
197+
}
198+
return Promise.reject();
194199
}),
195200
);
196201
}

tests/index.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ const fixtures = {
2121
require.resolve("css-to-js-sourcemap-fixture-app/public/_static/no-map.js"),
2222
"utf-8",
2323
),
24+
clientExternalMapRaw: fs.readFileSync(
25+
require.resolve(
26+
"css-to-js-sourcemap-fixture-app/public/_static/external-map.js",
27+
),
28+
"utf-8",
29+
),
2430
};
2531

2632
testSingleMap("/external-map");
@@ -144,6 +150,64 @@ test(`replaying requests after invalidation`, async t => {
144150
});
145151
});
146152

153+
test(`fallback if sourcemap request is 404`, async t => {
154+
const {page, browser, server} = await setup(
155+
"/external-map",
156+
async msg => {
157+
if (msg.css) {
158+
const lines = msg.css.split("\n");
159+
t.equal(lines[0], ".__debug-1 {}", "has expected class on line 1");
160+
const consumer = await getConsumer(msg.css);
161+
const pos = consumer.originalPositionFor({line: 1, column: 0});
162+
t.equal(pos.line, 1, "mapped line number matches expected");
163+
t.equal(pos.column, 0, "mapped column matches expected");
164+
const {hostname, pathname, protocol} = new URL(pos.source);
165+
t.equal(hostname, "localhost");
166+
t.equal(pathname, "/_static/external-map.js");
167+
t.equal(protocol, "http:");
168+
const content = consumer.sourceContentFor(pos.source);
169+
t.equal(
170+
content,
171+
fixtures.clientExternalMapRaw,
172+
"mapped source content matches expected",
173+
);
174+
await browser.close();
175+
server.close();
176+
t.end();
177+
}
178+
},
179+
() => {
180+
t.fail("recieved error");
181+
},
182+
);
183+
await page.setRequestInterception(true);
184+
page.on("request", req => {
185+
if (req._url.endsWith(".js.map")) {
186+
req.respond({
187+
status: 404,
188+
});
189+
} else {
190+
req.continue();
191+
}
192+
});
193+
await page.evaluate(() => {
194+
window.worker.postMessage({
195+
id: "init_wasm",
196+
url: "/mappings.wasm",
197+
});
198+
window.worker.postMessage({
199+
id: "add_mapped_class",
200+
stackInfo: window.error1,
201+
className: "__debug-1",
202+
stackIndex: 0,
203+
});
204+
window.worker.postMessage({
205+
id: "set_render_interval",
206+
interval: 60,
207+
});
208+
});
209+
});
210+
147211
function testSingleMap(route) {
148212
test(`single mapped class works on ${route}`, async t => {
149213
const {page, browser, server} = await setup(

0 commit comments

Comments
 (0)