Change the name JSFileWrapping uses for `require`

Reviewed By: jeanlauliac

Differential Revision: D7502266

fbshipit-source-id: 23457eba7321fccb6d9a1f2d3d950e75cdc8a26a
This commit is contained in:
Peter van der Zee 2018-04-10 10:09:52 -07:00 committed by Facebook Github Bot
parent c35f1a2c01
commit 6ab9e7d09c
5 changed files with 159 additions and 73 deletions

View File

@ -67,7 +67,7 @@ describe('code transformation worker:', () => {
expect(result.code).toBe( expect(result.code).toBe(
[ [
'__d(function (global, _require, module, exports, _dependencyMap) {', '__d(function (global, _$$_REQUIRE, module, exports, _dependencyMap) {',
' arbitrary(code);', ' arbitrary(code);',
'});', '});',
].join('\n'), ].join('\n'),
@ -103,16 +103,16 @@ describe('code transformation worker:', () => {
expect(BABEL_VERSION).toBe(7); expect(BABEL_VERSION).toBe(7);
expect(result.code).toBe( expect(result.code).toBe(
[ [
'__d(function (global, _require, module, exports, _dependencyMap) {', '__d(function (global, _$$_REQUIRE, module, exports, _dependencyMap) {',
" 'use strict';", " 'use strict';",
'', '',
' var _c = babelHelpers.interopRequireDefault(_require(_dependencyMap[0], "./c"));', ' var _c = babelHelpers.interopRequireDefault(_$$_REQUIRE(_dependencyMap[0], "./c"));',
'', '',
' _require(_dependencyMap[1], "./a");', ' _$$_REQUIRE(_dependencyMap[1], "./a");',
'', '',
' arbitrary(code);', ' arbitrary(code);',
'', '',
' var b = _require(_dependencyMap[2], "b");', ' var b = _$$_REQUIRE(_dependencyMap[2], "b");',
'});', '});',
].join('\n'), ].join('\n'),
); );
@ -145,16 +145,16 @@ describe('code transformation worker:', () => {
expect(BABEL_VERSION).toBe(6); expect(BABEL_VERSION).toBe(6);
expect(result.code).toBe( expect(result.code).toBe(
[ [
'__d(function (global, _require, module, exports, _dependencyMap) {', '__d(function (global, _$$_REQUIRE, module, exports, _dependencyMap) {',
' var _c = _require(_dependencyMap[0], "./c");', ' var _c = _$$_REQUIRE(_dependencyMap[0], "./c");',
'', '',
' var _c2 = babelHelpers.interopRequireDefault(_c);', ' var _c2 = babelHelpers.interopRequireDefault(_c);',
'', '',
' _require(_dependencyMap[1], "./a");', ' _$$_REQUIRE(_dependencyMap[1], "./a");',
'', '',
' arbitrary(code);', ' arbitrary(code);',
'', '',
' var b = _require(_dependencyMap[2], "b");', ' var b = _$$_REQUIRE(_dependencyMap[2], "b");',
'});', '});',
].join('\n'), ].join('\n'),
); );

View File

@ -15,6 +15,7 @@ const {babelTypes, babelTraverse: traverse} = require('../../babel-bridge');
const MODULE_FACTORY_PARAMETERS = ['global', 'require', 'module', 'exports']; const MODULE_FACTORY_PARAMETERS = ['global', 'require', 'module', 'exports'];
const POLYFILL_FACTORY_PARAMETERS = ['global']; const POLYFILL_FACTORY_PARAMETERS = ['global'];
const WRAP_NAME = '$$_REQUIRE'; // note: babel will prefix this with _
function wrapModule( function wrapModule(
fileAst: Object, fileAst: Object,
@ -66,21 +67,23 @@ function makeIdentifier(name: string): Object {
} }
function renameRequires(ast: Object) { function renameRequires(ast: Object) {
let requireName = 'require'; let newRequireName = WRAP_NAME;
traverse(ast, { traverse(ast, {
Program(path) { Program(path) {
const body = path.get('body.0.expression.arguments.0.body'); const body = path.get('body.0.expression.arguments.0.body');
requireName = body.scope.generateUid('_require'); newRequireName = body.scope.generateUid(WRAP_NAME);
body.scope.rename('require', requireName); body.scope.rename('require', newRequireName);
}, },
}); });
return requireName; return newRequireName;
} }
module.exports = { module.exports = {
WRAP_NAME,
wrapJson, wrapJson,
wrapModule, wrapModule,
wrapPolyfill, wrapPolyfill,

View File

@ -16,6 +16,12 @@ const JsFileWrapping = require('../JsFileWrapping');
const {babylon} = require('../../../babel-bridge'); const {babylon} = require('../../../babel-bridge');
const {codeFromAst, comparableCode} = require('../../test-helpers'); const {codeFromAst, comparableCode} = require('../../test-helpers');
const {WRAP_NAME} = JsFileWrapping;
// Note; it's not important HOW Babel changes the name. Only THAT it does.
// At the time of writing, it will prefix an underscore for our first rename
const BABEL_RENAMED = '_' + WRAP_NAME;
const BABEL_RENAMED2 = '_' + WRAP_NAME + '2';
it('wraps a module correctly', () => { it('wraps a module correctly', () => {
const dependencyMapName = '_dependencyMapName'; const dependencyMapName = '_dependencyMapName';
@ -33,53 +39,130 @@ it('wraps a module correctly', () => {
dependencyMapName, dependencyMapName,
); );
expect(requireName).toBe('_require'); expect(requireName).toBe(BABEL_RENAMED);
expect(codeFromAst(ast)).toEqual( expect(codeFromAst(ast)).toEqual(
comparableCode(` comparableCode(`
__d(function (global, _require, module, exports, _dependencyMapName) { __d(function (global, ${BABEL_RENAMED}, module, exports, _dependencyMapName) {
const dynamicRequire = _require; const dynamicRequire = ${BABEL_RENAMED};
const a = _require('b/lib/a'); const a = ${BABEL_RENAMED}('b/lib/a');
exports.do = () => _require("do"); exports.do = () => ${BABEL_RENAMED}("do");
if (!something) { if (!something) {
_require("setup/something"); ${BABEL_RENAMED}("setup/something");
} }
_require.blah('do'); ${BABEL_RENAMED}.blah('do');
});`), });`),
); );
}); });
it('replaces the require variable by a unique one', () => { describe('safe renaming of require', () => {
const dependencyMapName = '_dependencyMapName'; ['let', 'const', 'var'].forEach(declKeyword => {
describe('decl type = ' + declKeyword, () => {
it(`original name will always be renamed so local decl should be fine`, () => {
const dependencyMapName = '_dependencyMapName';
const originalAst = astFromCode(` const originalAst = astFromCode(`
const dynamicRequire = require; const dynamicRequire = require;
const a = require('b/lib/a'); const a = require('b/lib/a');
let _require = 'foo'; ${declKeyword} ${WRAP_NAME} = 'foo';
exports.do = () => require("do"); exports.do = () => require("do");
if (!something) { if (!something) {
require("setup/something"); require("setup/something");
} }
require.blah('do'); require.blah('do');
`); `);
const {ast, requireName} = JsFileWrapping.wrapModule( const {ast, requireName} = JsFileWrapping.wrapModule(
originalAst, originalAst,
dependencyMapName, dependencyMapName,
); );
expect(requireName).toBe('_require2'); expect(requireName).toBe(BABEL_RENAMED);
expect(codeFromAst(ast)).toEqual( expect(codeFromAst(ast)).toEqual(
comparableCode(` comparableCode(`
__d(function (global, _require2, module, exports, _dependencyMapName) { __d(function (global, ${BABEL_RENAMED}, module, exports, _dependencyMapName) {
const dynamicRequire = _require2; const dynamicRequire = ${BABEL_RENAMED};
const a = _require2('b/lib/a'); const a = ${BABEL_RENAMED}('b/lib/a');
let _require = 'foo'; ${declKeyword} ${WRAP_NAME} = 'foo';
exports.do = () => _require2("do"); exports.do = () => ${BABEL_RENAMED}("do");
if (!something) { if (!something) {
_require2("setup/something"); ${BABEL_RENAMED}("setup/something");
} }
_require2.blah('do'); ${BABEL_RENAMED}.blah('do');
});`), });`),
); );
});
it(`when the scope has the new name defined too`, () => {
const dependencyMapName = '_dependencyMapName';
const originalAst = astFromCode(`
const dynamicRequire = require;
const a = require('b/lib/a');
${declKeyword} ${BABEL_RENAMED} = 'foo';
exports.do = () => require("do");
if (!something) {
require("setup/something");
}
require.blah('do');
`);
const {ast, requireName} = JsFileWrapping.wrapModule(
originalAst,
dependencyMapName,
);
expect(requireName).toBe(BABEL_RENAMED2);
expect(codeFromAst(ast)).toEqual(
comparableCode(`
__d(function (global, ${BABEL_RENAMED2}, module, exports, _dependencyMapName) {
const dynamicRequire = ${BABEL_RENAMED2};
const a = ${BABEL_RENAMED2}('b/lib/a');
${declKeyword} ${BABEL_RENAMED} = 'foo';
exports.do = () => ${BABEL_RENAMED2}("do");
if (!something) {
${BABEL_RENAMED2}("setup/something");
}
${BABEL_RENAMED2}.blah('do');
});`),
);
});
it(`when an inner scope already has the new name defined too`, () => {
const dependencyMapName = '_dependencyMapName';
// Note; it's not important HOW Babel changes the name. Only THAT it does.
const BABEL_RENAMED = '_' + WRAP_NAME;
const originalAst = astFromCode(`
const dynamicRequire = require;
const a = require('b/lib/a');
if (a) {
(function () {
${declKeyword} ${BABEL_RENAMED} = require('dingus');
a(${BABEL_RENAMED}(dynamicRequire));
})
}
`);
const {ast, requireName} = JsFileWrapping.wrapModule(
originalAst,
dependencyMapName,
);
expect(requireName).toBe(BABEL_RENAMED2);
expect(codeFromAst(ast)).toEqual(
comparableCode(`
__d(function (global, ${BABEL_RENAMED2}, module, exports, _dependencyMapName) {
const dynamicRequire = ${BABEL_RENAMED2};
const a = ${BABEL_RENAMED2}('b/lib/a');
if (a) {
(function () {
${declKeyword} ${BABEL_RENAMED} = ${BABEL_RENAMED2}('dingus');
a(${BABEL_RENAMED}(dynamicRequire));
});
}
});`),
);
});
});
});
}); });
it('wraps a polyfill correctly', () => { it('wraps a polyfill correctly', () => {

View File

@ -135,7 +135,7 @@ describe('transforming JS modules:', () => {
const {code, dependencyMapName} = result.details.transformed.default; const {code, dependencyMapName} = result.details.transformed.default;
invariant(dependencyMapName != null, 'dependencyMapName cannot be null'); invariant(dependencyMapName != null, 'dependencyMapName cannot be null');
expect(code.replace(/\s+/g, '')).toEqual( expect(code.replace(/\s+/g, '')).toEqual(
`__d(function(global,_require,module,exports,${dependencyMapName}){${transformedCode}});`, `__d(function(global,_$$_REQUIRE,module,exports,${dependencyMapName}){${transformedCode}});`,
); );
}); });
@ -192,12 +192,12 @@ describe('transforming JS modules:', () => {
invariant(result.type === 'code', 'result must be code'); invariant(result.type === 'code', 'result must be code');
const {dev, prod} = result.details.transformed; const {dev, prod} = result.details.transformed;
expect(dev.code.replace(/\s+/g, '')).toEqual( expect(dev.code.replace(/\s+/g, '')).toEqual(
`__d(function(global,_require,module,exports,${nullthrows( `__d(function(global,_$$_REQUIRE,module,exports,${nullthrows(
dev.dependencyMapName, dev.dependencyMapName,
)}){arbitrary(code);});`, )}){arbitrary(code);});`,
); );
expect(prod.code.replace(/\s+/g, '')).toEqual( expect(prod.code.replace(/\s+/g, '')).toEqual(
`__d(function(global,_require,module,exports,${nullthrows( `__d(function(global,_$$_REQUIRE,module,exports,${nullthrows(
prod.dependencyMapName, prod.dependencyMapName,
)}){arbitrary(code);});`, )}){arbitrary(code);});`,
); );

View File

@ -138,40 +138,40 @@ exports[`basic_bundle bundles package with polyfills 1`] = `
String.prototype.repeat = function () {}; String.prototype.repeat = function () {};
} }
})(this); })(this);
__d(function (global, _require, module, exports, _dependencyMap) { __d(function (global, _$$_REQUIRE, module, exports, _dependencyMap) {
'use strict'; 'use strict';
var Bar = _require(_dependencyMap[0]); var Bar = _$$_REQUIRE(_dependencyMap[0]);
var Foo = _require(_dependencyMap[1]); var Foo = _$$_REQUIRE(_dependencyMap[1]);
module.exports = { module.exports = {
Foo: Foo, Foo: Foo,
Bar: Bar Bar: Bar
}; };
},0,[1,2]); },0,[1,2]);
__d(function (global, _require, module, exports, _dependencyMap) { __d(function (global, _$$_REQUIRE, module, exports, _dependencyMap) {
'use strict'; 'use strict';
var Foo = _require(_dependencyMap[0]); var Foo = _$$_REQUIRE(_dependencyMap[0]);
module.exports = { module.exports = {
type: 'bar', type: 'bar',
foo: Foo.type foo: Foo.type
}; };
},1,[2]); },1,[2]);
__d(function (global, _require, module, exports, _dependencyMap) { __d(function (global, _$$_REQUIRE, module, exports, _dependencyMap) {
'use strict'; 'use strict';
var asset = _require(_dependencyMap[0]); var asset = _$$_REQUIRE(_dependencyMap[0]);
module.exports = { module.exports = {
type: 'foo', type: 'foo',
asset: asset asset: asset
}; };
},2,[3]); },2,[3]);
__d(function (global, _require, module, exports, _dependencyMap) { __d(function (global, _$$_REQUIRE, module, exports, _dependencyMap) {
module.exports = _require(_dependencyMap[0]).registerAsset({ module.exports = _$$_REQUIRE(_dependencyMap[0]).registerAsset({
\\"__packager_asset\\": true, \\"__packager_asset\\": true,
\\"httpServerLocation\\": \\"/assets\\", \\"httpServerLocation\\": \\"/assets\\",
\\"width\\": 8, \\"width\\": 8,
@ -182,7 +182,7 @@ __d(function (global, _require, module, exports, _dependencyMap) {
\\"type\\": \\"png\\" \\"type\\": \\"png\\"
}); });
},3,[4]); },3,[4]);
__d(function (global, _require, module, exports, _dependencyMap) { __d(function (global, _$$_REQUIRE, module, exports, _dependencyMap) {
'use strict'; 'use strict';
},4,[]); },4,[]);
require(0);" require(0);"
@ -312,40 +312,40 @@ exports[`basic_bundle bundles package without polyfills 1`] = `
return Error('Requiring module \\"' + displayName + '\\", which threw an exception: ' + error); return Error('Requiring module \\"' + displayName + '\\", which threw an exception: ' + error);
} }
})(this); })(this);
__d(function (global, _require, module, exports, _dependencyMap) { __d(function (global, _$$_REQUIRE, module, exports, _dependencyMap) {
'use strict'; 'use strict';
var Bar = _require(_dependencyMap[0]); var Bar = _$$_REQUIRE(_dependencyMap[0]);
var Foo = _require(_dependencyMap[1]); var Foo = _$$_REQUIRE(_dependencyMap[1]);
module.exports = { module.exports = {
Foo: Foo, Foo: Foo,
Bar: Bar Bar: Bar
}; };
},0,[1,2]); },0,[1,2]);
__d(function (global, _require, module, exports, _dependencyMap) { __d(function (global, _$$_REQUIRE, module, exports, _dependencyMap) {
'use strict'; 'use strict';
var Foo = _require(_dependencyMap[0]); var Foo = _$$_REQUIRE(_dependencyMap[0]);
module.exports = { module.exports = {
type: 'bar', type: 'bar',
foo: Foo.type foo: Foo.type
}; };
},1,[2]); },1,[2]);
__d(function (global, _require, module, exports, _dependencyMap) { __d(function (global, _$$_REQUIRE, module, exports, _dependencyMap) {
'use strict'; 'use strict';
var asset = _require(_dependencyMap[0]); var asset = _$$_REQUIRE(_dependencyMap[0]);
module.exports = { module.exports = {
type: 'foo', type: 'foo',
asset: asset asset: asset
}; };
},2,[3]); },2,[3]);
__d(function (global, _require, module, exports, _dependencyMap) { __d(function (global, _$$_REQUIRE, module, exports, _dependencyMap) {
module.exports = _require(_dependencyMap[0]).registerAsset({ module.exports = _$$_REQUIRE(_dependencyMap[0]).registerAsset({
\\"__packager_asset\\": true, \\"__packager_asset\\": true,
\\"httpServerLocation\\": \\"/assets\\", \\"httpServerLocation\\": \\"/assets\\",
\\"width\\": 8, \\"width\\": 8,
@ -356,7 +356,7 @@ __d(function (global, _require, module, exports, _dependencyMap) {
\\"type\\": \\"png\\" \\"type\\": \\"png\\"
}); });
},3,[4]); },3,[4]);
__d(function (global, _require, module, exports, _dependencyMap) { __d(function (global, _$$_REQUIRE, module, exports, _dependencyMap) {
'use strict'; 'use strict';
},4,[]); },4,[]);
require(0);" require(0);"