mirror of https://github.com/status-im/metro.git
Apply inline code + constant fold transforms when dev is false
Reviewed By: davidaurelio Differential Revision: D5940962 fbshipit-source-id: 699d45416bade8471164d6ddf5ef3ade535376b3
This commit is contained in:
parent
0fdf36d06d
commit
367a5f5db8
|
@ -6,6 +6,7 @@
|
|||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @emails oncall+javascript_foundation
|
||||
* @format
|
||||
*/
|
||||
'use strict';
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @emails oncall+javascript_foundation
|
||||
* @format
|
||||
*/
|
||||
'use strict';
|
||||
|
@ -46,26 +47,56 @@ describe('code transformation worker:', () => {
|
|||
filename,
|
||||
localPath,
|
||||
sourceCode,
|
||||
{transform: transformOptions},
|
||||
{dev: true, transform: transformOptions},
|
||||
() => {},
|
||||
);
|
||||
expect(transformer.transform).toBeCalledWith({
|
||||
filename,
|
||||
localPath,
|
||||
options: transformOptions,
|
||||
plugins: [],
|
||||
src: sourceCode,
|
||||
});
|
||||
});
|
||||
|
||||
it('calls the transform with two plugins when not in dev mode', () => {
|
||||
const filename = 'arbitrary/file.js';
|
||||
const localPath = `local/${filename}`;
|
||||
const sourceCode = 'arbitrary(code)';
|
||||
const options = {dev: false, transform: {arbitrary: 'options'}};
|
||||
|
||||
transformCode(
|
||||
transformer,
|
||||
filename,
|
||||
localPath,
|
||||
sourceCode,
|
||||
options,
|
||||
() => {},
|
||||
);
|
||||
|
||||
const plugins = transformer.transform.mock.calls[0][0].plugins;
|
||||
|
||||
expect(plugins[0]).toEqual([expect.any(Object), options]);
|
||||
expect(plugins[1]).toEqual([expect.any(Object), options]);
|
||||
});
|
||||
|
||||
it('prefixes JSON files with an assignment to module.exports to make the code valid', function() {
|
||||
const filename = 'arbitrary/file.json';
|
||||
const localPath = `local/${filename}`;
|
||||
const sourceCode = '{"arbitrary":"property"}';
|
||||
transformCode(transformer, filename, localPath, sourceCode, {}, () => {});
|
||||
transformCode(
|
||||
transformer,
|
||||
filename,
|
||||
localPath,
|
||||
sourceCode,
|
||||
{dev: true},
|
||||
() => {},
|
||||
);
|
||||
expect(transformer.transform).toBeCalledWith({
|
||||
filename,
|
||||
localPath,
|
||||
options: undefined,
|
||||
plugins: [],
|
||||
src: `module.exports=${sourceCode}`,
|
||||
});
|
||||
});
|
||||
|
@ -232,90 +263,4 @@ describe('code transformation worker:', () => {
|
|||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Minifications:', () => {
|
||||
let constantFolding, inline, options;
|
||||
let transformResult, dependencyData;
|
||||
const filename = 'arbitrary/file.js';
|
||||
const foldedCode = 'arbitrary(folded(code));';
|
||||
const foldedMap = {version: 3, sources: ['fold.js']};
|
||||
|
||||
beforeEach(() => {
|
||||
constantFolding = require('../constant-folding').mockReturnValue({
|
||||
code: foldedCode,
|
||||
map: foldedMap,
|
||||
});
|
||||
extractDependencies = require('../extract-dependencies');
|
||||
inline = require('../inline');
|
||||
|
||||
options = {minify: true, transform: {generateSourceMaps: true}};
|
||||
dependencyData = {
|
||||
dependencies: ['a', 'b', 'c'],
|
||||
dependencyOffsets: [100, 120, 140],
|
||||
};
|
||||
|
||||
extractDependencies.mockImplementation(
|
||||
code => (code === foldedCode ? dependencyData : {}),
|
||||
);
|
||||
|
||||
transformer.transform.mockImplementation(
|
||||
(src, fileName, _) => transformResult,
|
||||
);
|
||||
});
|
||||
|
||||
it('passes the transform result to `inline` for constant inlining', done => {
|
||||
transformResult = {map: {version: 3}, code: 'arbitrary(code)'};
|
||||
transformCode(transformer, filename, filename, 'code', options, () => {
|
||||
expect(inline).toBeCalledWith(filename, transformResult, options);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('passes the result obtained from `inline` on to `constant-folding`', done => {
|
||||
const inlineResult = {map: {version: 3, sources: []}, ast: {}};
|
||||
inline.mockReturnValue(inlineResult);
|
||||
transformCode(transformer, filename, filename, 'code', options, () => {
|
||||
expect(constantFolding).toBeCalledWith(filename, inlineResult);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Uses the code obtained from `constant-folding` to extract dependencies', done => {
|
||||
transformCode(transformer, filename, filename, 'code', options, () => {
|
||||
expect(extractDependencies).toBeCalledWith(foldedCode, filename);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('uses the dependencies obtained from the optimized result', done => {
|
||||
transformCode(
|
||||
transformer,
|
||||
filename,
|
||||
filename,
|
||||
'code',
|
||||
options,
|
||||
(_, data) => {
|
||||
const result = data.result;
|
||||
expect(result.dependencies).toEqual(dependencyData.dependencies);
|
||||
done();
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('uses data produced by `constant-folding` for the result', done => {
|
||||
transformCode(
|
||||
transformer,
|
||||
'filename',
|
||||
'local/filename',
|
||||
'code',
|
||||
options,
|
||||
(_, data) => {
|
||||
expect(data.result).toEqual(
|
||||
objectContaining({code: foldedCode, map: foldedMap}),
|
||||
);
|
||||
done();
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -111,10 +111,15 @@ const transformCode: TransformCode = asyncify(
|
|||
start_timestamp: process.hrtime(),
|
||||
};
|
||||
|
||||
const plugins = options.dev
|
||||
? []
|
||||
: [[inline.plugin, options], [constantFolding.plugin, options]];
|
||||
|
||||
const transformed = transformer.transform({
|
||||
filename,
|
||||
localPath,
|
||||
options: options.transform,
|
||||
plugins,
|
||||
src: sourceCode,
|
||||
});
|
||||
|
||||
|
@ -123,16 +128,7 @@ const transformCode: TransformCode = asyncify(
|
|||
'Missing transform results despite having no error.',
|
||||
);
|
||||
|
||||
var code, map;
|
||||
if (options.minify) {
|
||||
({code, map} = constantFolding(
|
||||
filename,
|
||||
inline(filename, transformed, options),
|
||||
));
|
||||
invariant(code != null, 'Missing code from constant-folding transform.');
|
||||
} else {
|
||||
({code, map} = transformed);
|
||||
}
|
||||
let {code, map} = transformed;
|
||||
|
||||
if (isJson) {
|
||||
code = code.replace(/^\w+\.exports=/, '');
|
||||
|
|
|
@ -15,9 +15,7 @@ global.require = _require;
|
|||
global.__d = define;
|
||||
|
||||
var modules = Object.create(null);
|
||||
if (__DEV__) {
|
||||
var verboseNamesToModuleIds = Object.create(null);
|
||||
}
|
||||
|
||||
|
||||
function define(factory, moduleId, dependencyMap) {
|
||||
if (moduleId in modules) {
|
||||
|
@ -30,28 +28,9 @@ function define(factory, moduleId, dependencyMap) {
|
|||
hasError: false,
|
||||
isInitialized: false
|
||||
};
|
||||
if (__DEV__) {
|
||||
modules[moduleId].hot = createHotReloadingObject();
|
||||
|
||||
var _verboseName = arguments[3];
|
||||
if (_verboseName) {
|
||||
modules[moduleId].verboseName = _verboseName;
|
||||
verboseNamesToModuleIds[_verboseName] = moduleId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _require(moduleId) {
|
||||
if (__DEV__ && typeof moduleId === 'string') {
|
||||
var _verboseName2 = moduleId;
|
||||
moduleId = verboseNamesToModuleIds[_verboseName2];
|
||||
if (moduleId == null) {
|
||||
throw new Error('Unknown named module: \\\\'' + _verboseName2 + '\\\\'');
|
||||
} else {
|
||||
console.warn('Requiring module \\\\'' + _verboseName2 + '\\\\' by name is only supported for ' + 'debugging purposes and will BREAK IN PRODUCTION!');
|
||||
}
|
||||
}
|
||||
|
||||
var moduleIdReallyIsNumber = moduleId;
|
||||
var module = modules[moduleIdReallyIsNumber];
|
||||
return module && module.isInitialized ? module.exports : guardedLoadModule(moduleIdReallyIsNumber, module);
|
||||
|
@ -100,10 +79,6 @@ function loadModuleImplementation(moduleId, module) {
|
|||
throw moduleThrewError(moduleId, module.error);
|
||||
}
|
||||
|
||||
if (__DEV__) {
|
||||
var Systrace = _require.Systrace;
|
||||
}
|
||||
|
||||
module.isInitialized = true;
|
||||
var exports = module.exports = {};
|
||||
var _module = module,
|
||||
|
@ -111,25 +86,16 @@ function loadModuleImplementation(moduleId, module) {
|
|||
dependencyMap = _module.dependencyMap;
|
||||
|
||||
try {
|
||||
if (__DEV__) {
|
||||
Systrace.beginEvent('JS_require_' + (module.verboseName || moduleId));
|
||||
}
|
||||
|
||||
var _moduleObject = { exports: exports };
|
||||
if (__DEV__ && module.hot) {
|
||||
_moduleObject.hot = module.hot;
|
||||
}
|
||||
|
||||
factory(global, _require, _moduleObject, exports, dependencyMap);
|
||||
|
||||
if (!__DEV__) {
|
||||
{
|
||||
module.factory = undefined;
|
||||
module.dependencyMap = undefined;
|
||||
}
|
||||
|
||||
if (__DEV__) {
|
||||
Systrace.endEvent();
|
||||
}
|
||||
return module.exports = _moduleObject.exports;
|
||||
} catch (e) {
|
||||
module.hasError = true;
|
||||
|
@ -142,95 +108,14 @@ function loadModuleImplementation(moduleId, module) {
|
|||
|
||||
function unknownModuleError(id) {
|
||||
var message = 'Requiring unknown module \\"' + id + '\\".';
|
||||
if (__DEV__) {
|
||||
message += 'If you are sure the module is there, try restarting Metro Bundler. ' + 'You may also want to run \`yarn\`, or \`npm install\` (depending on your environment).';
|
||||
}
|
||||
|
||||
return Error(message);
|
||||
}
|
||||
|
||||
function moduleThrewError(id, error) {
|
||||
var displayName = __DEV__ && modules[id] && modules[id].verboseName || id;
|
||||
var displayName = id;
|
||||
return Error('Requiring module \\"' + displayName + '\\", which threw an exception: ' + error);
|
||||
}
|
||||
|
||||
if (__DEV__) {
|
||||
var createHotReloadingObject;
|
||||
|
||||
(function () {
|
||||
_require.Systrace = { beginEvent: function beginEvent() {}, endEvent: function endEvent() {} };
|
||||
|
||||
_require.getModules = function () {
|
||||
return modules;
|
||||
};
|
||||
|
||||
createHotReloadingObject = function createHotReloadingObject() {
|
||||
var hot = {
|
||||
acceptCallback: null,
|
||||
accept: function accept(callback) {
|
||||
hot.acceptCallback = callback;
|
||||
}
|
||||
};
|
||||
return hot;
|
||||
};
|
||||
|
||||
var acceptAll = function acceptAll(dependentModules, inverseDependencies) {
|
||||
if (!dependentModules || dependentModules.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var notAccepted = dependentModules.filter(function (module) {
|
||||
return !accept(module, undefined, inverseDependencies);
|
||||
});
|
||||
|
||||
var parents = [];
|
||||
for (var i = 0; i < notAccepted.length; i++) {
|
||||
if (inverseDependencies[notAccepted[i]].length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
parents.push.apply(parents, babelHelpers.toConsumableArray(inverseDependencies[notAccepted[i]]));
|
||||
}
|
||||
|
||||
return acceptAll(parents, inverseDependencies);
|
||||
};
|
||||
|
||||
var accept = function accept(id, factory, inverseDependencies) {
|
||||
var mod = modules[id];
|
||||
|
||||
if (!mod && factory) {
|
||||
define(factory, id);
|
||||
return true;
|
||||
}
|
||||
|
||||
var hot = mod.hot;
|
||||
|
||||
if (!hot) {
|
||||
console.warn('Cannot accept module because Hot Module Replacement ' + 'API was not installed.');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (factory) {
|
||||
mod.factory = factory;
|
||||
}
|
||||
mod.hasError = false;
|
||||
mod.isInitialized = false;
|
||||
_require(id);
|
||||
|
||||
if (hot.acceptCallback) {
|
||||
hot.acceptCallback();
|
||||
return true;
|
||||
} else {
|
||||
if (!inverseDependencies) {
|
||||
throw new Error('Undefined \`inverseDependencies\`');
|
||||
}
|
||||
|
||||
return acceptAll(inverseDependencies[id], inverseDependencies);
|
||||
}
|
||||
};
|
||||
|
||||
global.__accept = accept;
|
||||
})();
|
||||
}
|
||||
})(typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this);
|
||||
(function(global) {
|
||||
|
||||
|
@ -297,9 +182,7 @@ global.require = _require;
|
|||
global.__d = define;
|
||||
|
||||
var modules = Object.create(null);
|
||||
if (__DEV__) {
|
||||
var verboseNamesToModuleIds = Object.create(null);
|
||||
}
|
||||
|
||||
|
||||
function define(factory, moduleId, dependencyMap) {
|
||||
if (moduleId in modules) {
|
||||
|
@ -312,28 +195,9 @@ function define(factory, moduleId, dependencyMap) {
|
|||
hasError: false,
|
||||
isInitialized: false
|
||||
};
|
||||
if (__DEV__) {
|
||||
modules[moduleId].hot = createHotReloadingObject();
|
||||
|
||||
var _verboseName = arguments[3];
|
||||
if (_verboseName) {
|
||||
modules[moduleId].verboseName = _verboseName;
|
||||
verboseNamesToModuleIds[_verboseName] = moduleId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _require(moduleId) {
|
||||
if (__DEV__ && typeof moduleId === 'string') {
|
||||
var _verboseName2 = moduleId;
|
||||
moduleId = verboseNamesToModuleIds[_verboseName2];
|
||||
if (moduleId == null) {
|
||||
throw new Error('Unknown named module: \\\\'' + _verboseName2 + '\\\\'');
|
||||
} else {
|
||||
console.warn('Requiring module \\\\'' + _verboseName2 + '\\\\' by name is only supported for ' + 'debugging purposes and will BREAK IN PRODUCTION!');
|
||||
}
|
||||
}
|
||||
|
||||
var moduleIdReallyIsNumber = moduleId;
|
||||
var module = modules[moduleIdReallyIsNumber];
|
||||
return module && module.isInitialized ? module.exports : guardedLoadModule(moduleIdReallyIsNumber, module);
|
||||
|
@ -382,10 +246,6 @@ function loadModuleImplementation(moduleId, module) {
|
|||
throw moduleThrewError(moduleId, module.error);
|
||||
}
|
||||
|
||||
if (__DEV__) {
|
||||
var Systrace = _require.Systrace;
|
||||
}
|
||||
|
||||
module.isInitialized = true;
|
||||
var exports = module.exports = {};
|
||||
var _module = module,
|
||||
|
@ -393,25 +253,16 @@ function loadModuleImplementation(moduleId, module) {
|
|||
dependencyMap = _module.dependencyMap;
|
||||
|
||||
try {
|
||||
if (__DEV__) {
|
||||
Systrace.beginEvent('JS_require_' + (module.verboseName || moduleId));
|
||||
}
|
||||
|
||||
var _moduleObject = { exports: exports };
|
||||
if (__DEV__ && module.hot) {
|
||||
_moduleObject.hot = module.hot;
|
||||
}
|
||||
|
||||
factory(global, _require, _moduleObject, exports, dependencyMap);
|
||||
|
||||
if (!__DEV__) {
|
||||
{
|
||||
module.factory = undefined;
|
||||
module.dependencyMap = undefined;
|
||||
}
|
||||
|
||||
if (__DEV__) {
|
||||
Systrace.endEvent();
|
||||
}
|
||||
return module.exports = _moduleObject.exports;
|
||||
} catch (e) {
|
||||
module.hasError = true;
|
||||
|
@ -424,95 +275,14 @@ function loadModuleImplementation(moduleId, module) {
|
|||
|
||||
function unknownModuleError(id) {
|
||||
var message = 'Requiring unknown module \\"' + id + '\\".';
|
||||
if (__DEV__) {
|
||||
message += 'If you are sure the module is there, try restarting Metro Bundler. ' + 'You may also want to run \`yarn\`, or \`npm install\` (depending on your environment).';
|
||||
}
|
||||
|
||||
return Error(message);
|
||||
}
|
||||
|
||||
function moduleThrewError(id, error) {
|
||||
var displayName = __DEV__ && modules[id] && modules[id].verboseName || id;
|
||||
var displayName = id;
|
||||
return Error('Requiring module \\"' + displayName + '\\", which threw an exception: ' + error);
|
||||
}
|
||||
|
||||
if (__DEV__) {
|
||||
var createHotReloadingObject;
|
||||
|
||||
(function () {
|
||||
_require.Systrace = { beginEvent: function beginEvent() {}, endEvent: function endEvent() {} };
|
||||
|
||||
_require.getModules = function () {
|
||||
return modules;
|
||||
};
|
||||
|
||||
createHotReloadingObject = function createHotReloadingObject() {
|
||||
var hot = {
|
||||
acceptCallback: null,
|
||||
accept: function accept(callback) {
|
||||
hot.acceptCallback = callback;
|
||||
}
|
||||
};
|
||||
return hot;
|
||||
};
|
||||
|
||||
var acceptAll = function acceptAll(dependentModules, inverseDependencies) {
|
||||
if (!dependentModules || dependentModules.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var notAccepted = dependentModules.filter(function (module) {
|
||||
return !accept(module, undefined, inverseDependencies);
|
||||
});
|
||||
|
||||
var parents = [];
|
||||
for (var i = 0; i < notAccepted.length; i++) {
|
||||
if (inverseDependencies[notAccepted[i]].length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
parents.push.apply(parents, babelHelpers.toConsumableArray(inverseDependencies[notAccepted[i]]));
|
||||
}
|
||||
|
||||
return acceptAll(parents, inverseDependencies);
|
||||
};
|
||||
|
||||
var accept = function accept(id, factory, inverseDependencies) {
|
||||
var mod = modules[id];
|
||||
|
||||
if (!mod && factory) {
|
||||
define(factory, id);
|
||||
return true;
|
||||
}
|
||||
|
||||
var hot = mod.hot;
|
||||
|
||||
if (!hot) {
|
||||
console.warn('Cannot accept module because Hot Module Replacement ' + 'API was not installed.');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (factory) {
|
||||
mod.factory = factory;
|
||||
}
|
||||
mod.hasError = false;
|
||||
mod.isInitialized = false;
|
||||
_require(id);
|
||||
|
||||
if (hot.acceptCallback) {
|
||||
hot.acceptCallback();
|
||||
return true;
|
||||
} else {
|
||||
if (!inverseDependencies) {
|
||||
throw new Error('Undefined \`inverseDependencies\`');
|
||||
}
|
||||
|
||||
return acceptAll(inverseDependencies[id], inverseDependencies);
|
||||
}
|
||||
};
|
||||
|
||||
global.__accept = accept;
|
||||
})();
|
||||
}
|
||||
})(typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this);
|
||||
__d(/* /TestBundle.js */function(global, require, module, exports) {
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ const getBabelRC = (function() {
|
|||
* Given a filename and options, build a Babel
|
||||
* config object with the appropriate plugins.
|
||||
*/
|
||||
function buildBabelConfig(filename, options) {
|
||||
function buildBabelConfig(filename, options, plugins?: BabelPlugins = []) {
|
||||
const babelRC = getBabelRC(options.projectRoot);
|
||||
|
||||
const extraConfig = {
|
||||
|
@ -109,7 +109,7 @@ function buildBabelConfig(filename, options) {
|
|||
extraPlugins.push(inlineRequiresPlugin);
|
||||
}
|
||||
|
||||
config.plugins = extraPlugins.concat(config.plugins);
|
||||
config.plugins = extraPlugins.concat(config.plugins, plugins);
|
||||
|
||||
if (options.dev && options.hot) {
|
||||
const hmrConfig = makeHMRConfig(options, filename);
|
||||
|
@ -126,14 +126,14 @@ type Params = {
|
|||
src: string,
|
||||
};
|
||||
|
||||
function transform({filename, options, src}: Params) {
|
||||
function transform({filename, options, src, plugins}: Params) {
|
||||
options = options || {platform: '', projectRoot: '', inlineRequires: false};
|
||||
|
||||
const OLD_BABEL_ENV = process.env.BABEL_ENV;
|
||||
process.env.BABEL_ENV = options.dev ? 'development' : 'production';
|
||||
|
||||
try {
|
||||
const babelConfig = buildBabelConfig(filename, options);
|
||||
const babelConfig = buildBabelConfig(filename, options, plugins);
|
||||
const {ast, ignored} = babel.transform(src, babelConfig);
|
||||
|
||||
if (ignored) {
|
||||
|
|
Loading…
Reference in New Issue