Skip to content

Commit 7f769aa

Browse files
fix: avoid crash on big data URL source maps
1 parent 2da2b2e commit 7f769aa

File tree

4 files changed

+30
-27
lines changed

4 files changed

+30
-27
lines changed

package-lock.json

Lines changed: 5 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@
4141
"webpack": "^4.0.0 || ^5.0.0"
4242
},
4343
"dependencies": {
44-
"neo-async": "^2.6.1",
44+
"data-urls": "^2.0.0",
4545
"loader-utils": "^2.0.0",
46-
"schema-utils": "^2.6.6"
46+
"neo-async": "^2.6.1",
47+
"schema-utils": "^2.6.6",
48+
"whatwg-encoding": "^1.0.5"
4749
},
4850
"devDependencies": {
4951
"@babel/cli": "^7.8.4",

src/index.js

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import path from 'path';
77

88
import validateOptions from 'schema-utils';
99
import async from 'neo-async';
10+
import parseDataURL from 'data-urls';
11+
import { labelToName, decode } from 'whatwg-encoding';
1012
import { getOptions, urlToRequest } from 'loader-utils';
1113

1214
import schema from './options.json';
@@ -18,8 +20,6 @@ const baseRegex =
1820
const regex1 = new RegExp(`/\\*${baseRegex}\\s*\\*/`);
1921
// Matches // .... comments
2022
const regex2 = new RegExp(`//${baseRegex}($|\n|\r\n?)`);
21-
// Matches DataUrls
22-
const regexDataUrl = /data:[^;\n]+(?:;charset=[^;\n]+)?;base64,([a-zA-Z0-9+/]+={0,2})/;
2323

2424
export default function loader(input, inputMap) {
2525
const options = getOptions(this);
@@ -39,20 +39,23 @@ export default function loader(input, inputMap) {
3939
}
4040

4141
const [, url] = match;
42-
const dataUrlMatch = regexDataUrl.exec(url);
43-
const { context, resolve, addDependency, emitWarning } = this;
4442

45-
if (dataUrlMatch) {
46-
const [, mapBase64] = dataUrlMatch;
47-
const mapStr = new Buffer(mapBase64, 'base64').toString();
43+
const dataURL = parseDataURL(url);
44+
45+
const { context, resolve, addDependency, emitWarning } = this;
4846

47+
if (dataURL) {
4948
let map;
5049

5150
try {
52-
map = JSON.parse(mapStr);
51+
dataURL.encodingName =
52+
labelToName(dataURL.mimeType.parameters.get('charset')) || 'UTF-8';
53+
54+
map = decode(dataURL.body, dataURL.encodingName);
55+
map = JSON.parse(map);
5356
} catch (error) {
5457
emitWarning(
55-
`Cannot parse inline SourceMap '${mapBase64.substr(0, 50)}': ${error}`
58+
`Cannot parse inline SourceMap with Charset ${dataURL.encodingName}: ${error}`
5659
);
5760

5861
callback(null, input, inputMap);
@@ -65,6 +68,14 @@ export default function loader(input, inputMap) {
6568
return;
6669
}
6770

71+
if (url.toLowerCase().indexOf('data:') === 0) {
72+
emitWarning(`Cannot parse inline SourceMap: ${url}`);
73+
74+
callback(null, input, inputMap);
75+
76+
return;
77+
}
78+
6879
resolve(context, urlToRequest(url, true), (resolveError, result) => {
6980
if (resolveError) {
7081
emitWarning(`Cannot find SourceMap '${url}': ${resolveError}`);

test/index.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ describe('source-map-loader', () => {
181181
expect(map).toBeUndefined();
182182
expect(deps).toEqual([]);
183183
expect(warns).toEqual([
184-
"Cannot parse inline SourceMap 'invalid/base64=': SyntaxError: Unexpected token � in JSON at position 0",
184+
'Cannot parse inline SourceMap: data:application/source-map;base64,invalid/base64=',
185185
]);
186186
done();
187187
}

0 commit comments

Comments
 (0)