Improve source map quality when inserting numeric module IDs
Summary: This changes the way that module identifiers are replaced with numeric ids so that ids are padded with spaces on the right to take up the same space as the original string literal. By doing this, we keep the mappings for the generated source line intact. ``` // original source const React = require('react'); // old replacement const React = require(12 /* react */); // new replacement const React = require(12 ); // 12 = react ``` The remaining edge case are module names that are replaced with numeric IDs that are longer than the replaced string, e.g.: ``` const Q = require('q'); const Q = require(1234); ``` Reviewed By: cpojer Differential Revision: D4346092 fbshipit-source-id: ef3bb879495f388c4a7448a2f810b83c204e8984
This commit is contained in:
parent
a69b480cae
commit
2cc587f3f4
|
@ -330,7 +330,7 @@ describe('Resolver', function() {
|
||||||
var code = [
|
var code = [
|
||||||
// require
|
// require
|
||||||
'require("x")',
|
'require("x")',
|
||||||
'require("y")',
|
'require("y");require(\'abc\');',
|
||||||
'require( \'z\' )',
|
'require( \'z\' )',
|
||||||
'require( "a")',
|
'require( "a")',
|
||||||
'require("b" )',
|
'require("b" )',
|
||||||
|
@ -356,14 +356,17 @@ describe('Resolver', function() {
|
||||||
return [
|
return [
|
||||||
['x', createModule('changed')],
|
['x', createModule('changed')],
|
||||||
['y', createModule('Y')],
|
['y', createModule('Y')],
|
||||||
|
['abc', createModule('abc')]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
const moduleIds = new Map(
|
const moduleIds = new Map(
|
||||||
resolutionResponse
|
resolutionResponse
|
||||||
.getResolvedDependencyPairs()
|
.getResolvedDependencyPairs()
|
||||||
.map(([importId, module]) =>
|
.map(([importId, module]) => [
|
||||||
[importId, resolutionResponse.getModuleId(module)])
|
importId,
|
||||||
|
padRight(resolutionResponse.getModuleId(module), importId.length + 2),
|
||||||
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
return depResolver.wrapModule({
|
return depResolver.wrapModule({
|
||||||
|
@ -377,8 +380,9 @@ describe('Resolver', function() {
|
||||||
expect(processedCode).toEqual([
|
expect(processedCode).toEqual([
|
||||||
'__d(/* test module */function(global, require, module, exports) {' +
|
'__d(/* test module */function(global, require, module, exports) {' +
|
||||||
// require
|
// require
|
||||||
`require(${moduleIds.get('x')} /* x */)`,
|
`require(${moduleIds.get('x')}) // ${moduleIds.get('x').trim()} = x`,
|
||||||
`require(${moduleIds.get('y')} /* y */)`,
|
`require(${moduleIds.get('y')});require(${moduleIds.get('abc')
|
||||||
|
}); // ${moduleIds.get('abc').trim()} = abc // ${moduleIds.get('y').trim()} = y`,
|
||||||
'require( \'z\' )',
|
'require( \'z\' )',
|
||||||
'require( "a")',
|
'require( "a")',
|
||||||
'require("b" )',
|
'require("b" )',
|
||||||
|
@ -535,4 +539,10 @@ describe('Resolver', function() {
|
||||||
|
|
||||||
return ({path}) => knownIds.get(path) || createId(path);
|
return ({path}) => knownIds.get(path) || createId(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function padRight(value, width) {
|
||||||
|
const s = String(value);
|
||||||
|
const diff = width - s.length;
|
||||||
|
return diff > 0 ? s + Array(diff + 1).join(' ') : s;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -226,21 +226,13 @@ class Resolver {
|
||||||
// require('./c') => require(3);
|
// require('./c') => require(3);
|
||||||
// -- in b/index.js:
|
// -- in b/index.js:
|
||||||
// require('../a/c') => require(3);
|
// require('../a/c') => require(3);
|
||||||
const replaceModuleId = (codeMatch, quote, depName) =>
|
return dependencyOffsets.reduceRight(
|
||||||
depName in resolvedDeps
|
([unhandled, handled], offset) => [
|
||||||
? `${JSON.stringify(resolvedDeps[depName])} /* ${depName} */`
|
unhandled.slice(0, offset),
|
||||||
: codeMatch;
|
replaceDependencyID(unhandled.slice(offset) + handled, resolvedDeps),
|
||||||
|
],
|
||||||
const codeParts = dependencyOffsets.reduceRight((codeBits, offset) => {
|
[code, ''],
|
||||||
const first = codeBits.shift();
|
).join('');
|
||||||
codeBits.unshift(
|
|
||||||
first.slice(0, offset),
|
|
||||||
first.slice(offset).replace(/(['"])([^'"']*)\1/, replaceModuleId),
|
|
||||||
);
|
|
||||||
return codeBits;
|
|
||||||
}, [code]);
|
|
||||||
|
|
||||||
return codeParts.join('');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wrapModule({
|
wrapModule({
|
||||||
|
@ -318,4 +310,28 @@ function definePolyfillCode(code,) {
|
||||||
].join('');
|
].join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const reDepencencyString = /^(['"])([^'"']*)\1/;
|
||||||
|
function replaceDependencyID(stringWithDependencyIDAtStart, resolvedDeps) {
|
||||||
|
const match = reDepencencyString.exec(stringWithDependencyIDAtStart);
|
||||||
|
const dependencyName = match && match[2];
|
||||||
|
if (match != null && dependencyName in resolvedDeps) {
|
||||||
|
const {length} = match[0];
|
||||||
|
const id = String(resolvedDeps[dependencyName]);
|
||||||
|
return (
|
||||||
|
padRight(id, length) +
|
||||||
|
stringWithDependencyIDAtStart
|
||||||
|
.slice(length)
|
||||||
|
.replace(/$/m, ` // ${id} = ${dependencyName}`)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return stringWithDependencyIDAtStart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function padRight(string, length) {
|
||||||
|
return string.length < length
|
||||||
|
? string + Array(length - string.length + 1).join(' ')
|
||||||
|
: string;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = Resolver;
|
module.exports = Resolver;
|
||||||
|
|
Loading…
Reference in New Issue