mirror of https://github.com/status-im/metro.git
Simplify HMR codepath
Reviewed By: davidaurelio Differential Revision: D2839590 fb-gh-sync-id: 9bb14cafc69eec7d7a8712b60435e29f2ba48d3c
This commit is contained in:
parent
b324dc6ae5
commit
95b69d548b
|
@ -10,6 +10,7 @@
|
|||
|
||||
const _ = require('underscore');
|
||||
const base64VLQ = require('./base64-vlq');
|
||||
const BundleBase = require('./BundleBase');
|
||||
const UglifyJS = require('uglify-js');
|
||||
const ModuleTransport = require('../lib/ModuleTransport');
|
||||
const Activity = require('../Activity');
|
||||
|
@ -24,11 +25,9 @@ const getNameAndCode = ({name, code}) => ({name, code});
|
|||
const getNameAndMinifiedCode =
|
||||
({name, code}) => ({name, code: minifyCode(code)});
|
||||
|
||||
class Bundle {
|
||||
class Bundle extends BundleBase {
|
||||
constructor(sourceMapUrl) {
|
||||
this._finalized = false;
|
||||
this._modules = [];
|
||||
this._assets = [];
|
||||
super();
|
||||
this._sourceMap = false;
|
||||
this._sourceMapUrl = sourceMapUrl;
|
||||
this._shouldCombineSourceMaps = false;
|
||||
|
@ -36,58 +35,49 @@ class Bundle {
|
|||
this._numRequireCalls = 0;
|
||||
}
|
||||
|
||||
setMainModuleId(moduleId) {
|
||||
this._mainModuleId = moduleId;
|
||||
}
|
||||
addModule(resolver, response, module, transformed) {
|
||||
return resolver.wrapModule(
|
||||
response,
|
||||
module,
|
||||
transformed.code
|
||||
).then(({code, name}) => {
|
||||
const moduleTransport = new ModuleTransport({
|
||||
code,
|
||||
name,
|
||||
map: transformed.map,
|
||||
sourceCode: transformed.sourceCode,
|
||||
sourcePath: transformed.sourcePath,
|
||||
virtual: transformed.virtual,
|
||||
});
|
||||
|
||||
addModule(module) {
|
||||
if (!(module instanceof ModuleTransport)) {
|
||||
throw new Error('Expeceted a ModuleTransport object');
|
||||
}
|
||||
// If we get a map from the transformer we'll switch to a mode
|
||||
// were we're combining the source maps as opposed to
|
||||
if (!this._shouldCombineSourceMaps && moduleTransport.map != null) {
|
||||
this._shouldCombineSourceMaps = true;
|
||||
}
|
||||
|
||||
// If we get a map from the transformer we'll switch to a mode
|
||||
// were we're combining the source maps as opposed to
|
||||
if (!this._shouldCombineSourceMaps && module.map != null) {
|
||||
this._shouldCombineSourceMaps = true;
|
||||
}
|
||||
|
||||
this._modules.push(module);
|
||||
}
|
||||
|
||||
getModules() {
|
||||
return this._modules;
|
||||
}
|
||||
|
||||
getMainModuleId() {
|
||||
return this._mainModuleId;
|
||||
super.addModule(moduleTransport);
|
||||
});
|
||||
}
|
||||
|
||||
setNumPrependedModules(n) {
|
||||
this._numPrependedModules = n;
|
||||
}
|
||||
|
||||
addAsset(asset) {
|
||||
this._assets.push(asset);
|
||||
}
|
||||
|
||||
finalize(options) {
|
||||
options = options || {};
|
||||
if (options.runMainModule) {
|
||||
options.runBeforeMainModule.forEach(this._addRequireCall, this);
|
||||
this._addRequireCall(this._mainModuleId);
|
||||
this._addRequireCall(super.getMainModuleId());
|
||||
}
|
||||
|
||||
Object.freeze(this._modules);
|
||||
Object.seal(this._modules);
|
||||
Object.freeze(this._assets);
|
||||
Object.seal(this._assets);
|
||||
this._finalized = true;
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
_addRequireCall(moduleId) {
|
||||
const code = ';require("' + moduleId + '");';
|
||||
const name = 'require-' + moduleId;
|
||||
this.addModule(new ModuleTransport({
|
||||
super.addModule(new ModuleTransport({
|
||||
name,
|
||||
code,
|
||||
virtual: true,
|
||||
|
@ -97,21 +87,6 @@ class Bundle {
|
|||
this._numRequireCalls += 1;
|
||||
}
|
||||
|
||||
_assertFinalized() {
|
||||
if (!this._finalized) {
|
||||
throw new Error('Bundle needs to be finalized before getting any source');
|
||||
}
|
||||
}
|
||||
|
||||
_getSource(dev) {
|
||||
if (this._source) {
|
||||
return this._source;
|
||||
}
|
||||
|
||||
this._source = _.pluck(this._modules, 'code').join('\n');
|
||||
return this._source;
|
||||
}
|
||||
|
||||
_getInlineSourceMap(dev) {
|
||||
if (this._inlineSourceMap == null) {
|
||||
const sourceMap = this.getSourceMap({excludeSource: true, dev});
|
||||
|
@ -123,7 +98,7 @@ class Bundle {
|
|||
}
|
||||
|
||||
getSource(options) {
|
||||
this._assertFinalized();
|
||||
super.assertFinalized();
|
||||
|
||||
options = options || {};
|
||||
|
||||
|
@ -131,7 +106,7 @@ class Bundle {
|
|||
return this.getMinifiedSourceAndMap(options.dev).code;
|
||||
}
|
||||
|
||||
let source = this._getSource(options.dev);
|
||||
let source = super.getSource();
|
||||
|
||||
if (options.inlineSourceMap) {
|
||||
source += SOURCEMAPPING_URL + this._getInlineSourceMap(options.dev);
|
||||
|
@ -143,7 +118,7 @@ class Bundle {
|
|||
}
|
||||
|
||||
getUnbundle({minify}) {
|
||||
const allModules = this._modules.slice();
|
||||
const allModules = super.getModules().slice();
|
||||
const prependedModules = this._numPrependedModules;
|
||||
const requireCalls = this._numRequireCalls;
|
||||
|
||||
|
@ -163,13 +138,13 @@ class Bundle {
|
|||
}
|
||||
|
||||
getMinifiedSourceAndMap(dev) {
|
||||
this._assertFinalized();
|
||||
super.assertFinalized();
|
||||
|
||||
if (this._minifiedSourceAndMap) {
|
||||
return this._minifiedSourceAndMap;
|
||||
}
|
||||
|
||||
let source = this._getSource(dev);
|
||||
let source = this.getSource();
|
||||
let map = this.getSourceMap();
|
||||
|
||||
if (!dev) {
|
||||
|
@ -235,7 +210,7 @@ class Bundle {
|
|||
};
|
||||
|
||||
let line = 0;
|
||||
this._modules.forEach(function(module) {
|
||||
super.getModules().forEach(function(module) {
|
||||
let map = module.map;
|
||||
if (module.virtual) {
|
||||
map = generateSourceMapForVirtualModule(module);
|
||||
|
@ -256,7 +231,7 @@ class Bundle {
|
|||
}
|
||||
|
||||
getSourceMap(options) {
|
||||
this._assertFinalized();
|
||||
super.assertFinalized();
|
||||
|
||||
options = options || {};
|
||||
|
||||
|
@ -271,22 +246,18 @@ class Bundle {
|
|||
const mappings = this._getMappings();
|
||||
const map = {
|
||||
file: 'bundle.js',
|
||||
sources: _.pluck(this._modules, 'sourcePath'),
|
||||
sources: _.pluck(super.getModules(), 'sourcePath'),
|
||||
version: 3,
|
||||
names: [],
|
||||
mappings: mappings,
|
||||
sourcesContent: options.excludeSource
|
||||
? [] : _.pluck(this._modules, 'sourceCode')
|
||||
? [] : _.pluck(super.getModules(), 'sourceCode')
|
||||
};
|
||||
return map;
|
||||
}
|
||||
|
||||
getAssets() {
|
||||
return this._assets;
|
||||
}
|
||||
|
||||
_getMappings() {
|
||||
const modules = this._modules;
|
||||
const modules = super.getModules();
|
||||
|
||||
// The first line mapping in our package is basically the base64vlq code for
|
||||
// zeros (A).
|
||||
|
@ -333,7 +304,7 @@ class Bundle {
|
|||
}
|
||||
|
||||
getJSModulePaths() {
|
||||
return this._modules.filter(function(module) {
|
||||
return super.getModules().filter(function(module) {
|
||||
// Filter out non-js files. Like images etc.
|
||||
return !module.virtual;
|
||||
}).map(function(module) {
|
||||
|
@ -343,7 +314,7 @@ class Bundle {
|
|||
|
||||
getDebugInfo() {
|
||||
return [
|
||||
'<div><h3>Main Module:</h3> ' + this._mainModuleId + '</div>',
|
||||
'<div><h3>Main Module:</h3> ' + super.getMainModuleId() + '</div>',
|
||||
'<style>',
|
||||
'pre.collapsed {',
|
||||
' height: 10px;',
|
||||
|
@ -355,7 +326,7 @@ class Bundle {
|
|||
'}',
|
||||
'</style>',
|
||||
'<h3> Module paths and transformed code: </h3>',
|
||||
this._modules.map(function(m) {
|
||||
super.getModules().map(function(m) {
|
||||
return '<div> <h4> Path: </h4>' + m.sourcePath + '<br/> <h4> Source: </h4>' +
|
||||
'<code><pre class="collapsed" onclick="this.classList.remove(\'collapsed\')">' +
|
||||
_.escape(m.code) + '</pre></code></div>';
|
||||
|
@ -369,10 +340,9 @@ class Bundle {
|
|||
}
|
||||
|
||||
return {
|
||||
modules: this._modules,
|
||||
assets: this._assets,
|
||||
...super.toJSON(),
|
||||
sourceMapUrl: this._sourceMapUrl,
|
||||
mainModuleId: this._mainModuleId,
|
||||
mainModuleId: super.getMainModuleId(),
|
||||
numPrependedModules: this._numPrependedModules,
|
||||
numRequireCalls: this._numRequireCalls,
|
||||
};
|
||||
|
@ -380,18 +350,12 @@ class Bundle {
|
|||
|
||||
static fromJSON(json) {
|
||||
const bundle = new Bundle(json.sourceMapUrl);
|
||||
bundle._mainModuleId = json.mainModuleId;
|
||||
bundle._assets = json.assets;
|
||||
bundle._modules = json.modules;
|
||||
|
||||
bundle._sourceMapUrl = json.sourceMapUrl;
|
||||
bundle._numPrependedModules = json.numPrependedModules;
|
||||
bundle._numRequireCalls = json.numRequireCalls;
|
||||
|
||||
Object.freeze(bundle._modules);
|
||||
Object.seal(bundle._modules);
|
||||
Object.freeze(bundle._assets);
|
||||
Object.seal(bundle._assets);
|
||||
bundle._finalized = true;
|
||||
BundleBase.fromJSON(bundle, json);
|
||||
|
||||
return bundle;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* 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.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const _ = require('underscore');
|
||||
const ModuleTransport = require('../lib/ModuleTransport');
|
||||
|
||||
class BundleBase {
|
||||
constructor() {
|
||||
this._finalized = false;
|
||||
this._modules = [];
|
||||
this._assets = [];
|
||||
}
|
||||
|
||||
getMainModuleId() {
|
||||
return this._mainModuleId;
|
||||
}
|
||||
|
||||
setMainModuleId(moduleId) {
|
||||
this._mainModuleId = moduleId;
|
||||
}
|
||||
|
||||
addModule(module) {
|
||||
if (!module instanceof ModuleTransport) {
|
||||
throw new Error('Expeceted a ModuleTransport object');
|
||||
}
|
||||
|
||||
this._modules.push(module);
|
||||
}
|
||||
|
||||
getModules() {
|
||||
return this._modules;
|
||||
}
|
||||
|
||||
getAssets() {
|
||||
return this._assets;
|
||||
}
|
||||
|
||||
addAsset(asset) {
|
||||
this._assets.push(asset);
|
||||
}
|
||||
|
||||
finalize(options) {
|
||||
Object.freeze(this._modules);
|
||||
Object.seal(this._modules);
|
||||
Object.freeze(this._assets);
|
||||
Object.seal(this._assets);
|
||||
this._finalized = true;
|
||||
}
|
||||
|
||||
getSource(options) {
|
||||
this.assertFinalized();
|
||||
|
||||
if (this._source) {
|
||||
return this._source;
|
||||
}
|
||||
|
||||
this._source = _.pluck(this._modules, 'code').join('\n');
|
||||
return this._source;
|
||||
}
|
||||
|
||||
assertFinalized() {
|
||||
if (!this._finalized) {
|
||||
throw new Error('Bundle needs to be finalized before getting any source');
|
||||
}
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return {
|
||||
modules: this._modules,
|
||||
assets: this._assets,
|
||||
};
|
||||
}
|
||||
|
||||
static fromJSON(bundle, json) {
|
||||
bundle._assets = json.assets;
|
||||
bundle._modules = json.modules;
|
||||
bundle._mainModuleId = json.mainModuleId;
|
||||
|
||||
Object.freeze(bundle._modules);
|
||||
Object.seal(bundle._modules);
|
||||
Object.freeze(bundle._assets);
|
||||
Object.seal(bundle._assets);
|
||||
bundle._finalized = true;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BundleBase;
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* 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.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const BundleBase = require('./BundleBase');
|
||||
const ModuleTransport = require('../lib/ModuleTransport');
|
||||
|
||||
class HMRBundle extends BundleBase {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
addModule(resolver, response, module, transformed) {
|
||||
return resolver.resolveRequires(response,
|
||||
module,
|
||||
transformed.code,
|
||||
).then(({name, code}) => {
|
||||
code = `
|
||||
__accept(
|
||||
'${name}',
|
||||
function(global, require, module, exports) {
|
||||
${code}
|
||||
}
|
||||
);
|
||||
`;
|
||||
|
||||
const moduleTransport = new ModuleTransport({
|
||||
code,
|
||||
name,
|
||||
map: transformed.map,
|
||||
sourceCode: transformed.sourceCode,
|
||||
sourcePath: transformed.sourcePath,
|
||||
virtual: transformed.virtual,
|
||||
});
|
||||
|
||||
super.addModule(moduleTransport);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = HMRBundle;
|
|
@ -10,92 +10,106 @@
|
|||
|
||||
jest.autoMockOff();
|
||||
|
||||
var SourceMapGenerator = require('source-map').SourceMapGenerator;
|
||||
const Bundle = require('../Bundle');
|
||||
const ModuleTransport = require('../../lib/ModuleTransport');
|
||||
const Promise = require('Promise');
|
||||
const SourceMapGenerator = require('source-map').SourceMapGenerator;
|
||||
const UglifyJS = require('uglify-js');
|
||||
|
||||
var Bundle = require('../Bundle');
|
||||
var ModuleTransport = require('../../lib/ModuleTransport');
|
||||
var UglifyJS = require('uglify-js');
|
||||
|
||||
describe('Bundle', function() {
|
||||
describe('Bundle', () => {
|
||||
var bundle;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(() => {
|
||||
bundle = new Bundle('test_url');
|
||||
bundle.getSourceMap = jest.genMockFn().mockImpl(function() {
|
||||
bundle.getSourceMap = jest.genMockFn().mockImpl(() => {
|
||||
return 'test-source-map';
|
||||
});
|
||||
});
|
||||
|
||||
describe('source bundle', function() {
|
||||
it('should create a bundle and get the source', function() {
|
||||
bundle.addModule(new ModuleTransport({
|
||||
code: 'transformed foo;',
|
||||
sourceCode: 'source foo',
|
||||
sourcePath: 'foo path',
|
||||
}));
|
||||
bundle.addModule(new ModuleTransport({
|
||||
code: 'transformed bar;',
|
||||
sourceCode: 'source bar',
|
||||
sourcePath: 'bar path',
|
||||
}));
|
||||
|
||||
bundle.finalize({});
|
||||
expect(bundle.getSource({dev: true})).toBe([
|
||||
'transformed foo;',
|
||||
'transformed bar;',
|
||||
'\/\/# sourceMappingURL=test_url'
|
||||
].join('\n'));
|
||||
});
|
||||
|
||||
it('should be ok to leave out the source map url', function() {
|
||||
var p = new Bundle();
|
||||
p.addModule(new ModuleTransport({
|
||||
code: 'transformed foo;',
|
||||
sourceCode: 'source foo',
|
||||
sourcePath: 'foo path',
|
||||
}));
|
||||
p.addModule(new ModuleTransport({
|
||||
code: 'transformed bar;',
|
||||
sourceCode: 'source bar',
|
||||
sourcePath: 'bar path',
|
||||
}));
|
||||
|
||||
p.finalize({});
|
||||
expect(p.getSource({dev: true})).toBe([
|
||||
'transformed foo;',
|
||||
'transformed bar;',
|
||||
].join('\n'));
|
||||
});
|
||||
|
||||
it('should create a bundle and add run module code', function() {
|
||||
bundle.addModule(new ModuleTransport({
|
||||
code: 'transformed foo;',
|
||||
sourceCode: 'source foo',
|
||||
sourcePath: 'foo path'
|
||||
}));
|
||||
|
||||
bundle.addModule(new ModuleTransport({
|
||||
code: 'transformed bar;',
|
||||
sourceCode: 'source bar',
|
||||
sourcePath: 'bar path'
|
||||
}));
|
||||
|
||||
bundle.setMainModuleId('foo');
|
||||
bundle.finalize({
|
||||
runBeforeMainModule: ['bar'],
|
||||
runMainModule: true,
|
||||
describe('source bundle', () => {
|
||||
pit('should create a bundle and get the source', () => {
|
||||
return Promise.resolve().then(() => {
|
||||
return addModule({
|
||||
bundle,
|
||||
code: 'transformed foo;',
|
||||
sourceCode: 'source foo',
|
||||
sourcePath: 'foo path',
|
||||
});
|
||||
}).then(() => {
|
||||
return addModule({
|
||||
bundle,
|
||||
code: 'transformed bar;',
|
||||
sourceCode: 'source bar',
|
||||
sourcePath: 'bar path',
|
||||
});
|
||||
}).then(() => {
|
||||
bundle.finalize({});
|
||||
expect(bundle.getSource({dev: true})).toBe([
|
||||
'transformed foo;',
|
||||
'transformed bar;',
|
||||
'\/\/# sourceMappingURL=test_url'
|
||||
].join('\n'));
|
||||
});
|
||||
expect(bundle.getSource({dev: true})).toBe([
|
||||
'transformed foo;',
|
||||
'transformed bar;',
|
||||
';require("bar");',
|
||||
';require("foo");',
|
||||
'\/\/# sourceMappingURL=test_url',
|
||||
].join('\n'));
|
||||
});
|
||||
|
||||
it('should get minified source', function() {
|
||||
var minified = {
|
||||
pit('should be ok to leave out the source map url', () => {
|
||||
const otherBundle = new Bundle();
|
||||
return Promise.resolve().then(() => {
|
||||
return addModule({
|
||||
bundle: otherBundle,
|
||||
code: 'transformed foo;',
|
||||
sourceCode: 'source foo',
|
||||
sourcePath: 'foo path',
|
||||
});
|
||||
}).then(() => {
|
||||
return addModule({
|
||||
bundle: otherBundle,
|
||||
code: 'transformed bar;',
|
||||
sourceCode: 'source bar',
|
||||
sourcePath: 'bar path',
|
||||
});
|
||||
}).then(() => {
|
||||
otherBundle.finalize({});
|
||||
expect(otherBundle.getSource({dev: true})).toBe([
|
||||
'transformed foo;',
|
||||
'transformed bar;',
|
||||
].join('\n'));
|
||||
});
|
||||
});
|
||||
|
||||
pit('should create a bundle and add run module code', () => {
|
||||
return Promise.resolve().then(() => {
|
||||
return addModule({
|
||||
bundle,
|
||||
code: 'transformed foo;',
|
||||
sourceCode: 'source foo',
|
||||
sourcePath: 'foo path',
|
||||
});
|
||||
}).then(() => {
|
||||
return addModule({
|
||||
bundle,
|
||||
code: 'transformed bar;',
|
||||
sourceCode: 'source bar',
|
||||
sourcePath: 'bar path',
|
||||
});
|
||||
}).then(() => {
|
||||
bundle.setMainModuleId('foo');
|
||||
bundle.finalize({
|
||||
runBeforeMainModule: ['bar'],
|
||||
runMainModule: true,
|
||||
});
|
||||
expect(bundle.getSource({dev: true})).toBe([
|
||||
'transformed foo;',
|
||||
'transformed bar;',
|
||||
';require("bar");',
|
||||
';require("foo");',
|
||||
'\/\/# sourceMappingURL=test_url',
|
||||
].join('\n'));
|
||||
});
|
||||
});
|
||||
|
||||
pit('should get minified source', () => {
|
||||
const minified = {
|
||||
code: 'minified',
|
||||
map: 'map',
|
||||
};
|
||||
|
@ -104,141 +118,156 @@ describe('Bundle', function() {
|
|||
return minified;
|
||||
};
|
||||
|
||||
bundle.addModule(new ModuleTransport({
|
||||
code: 'transformed foo;',
|
||||
sourceCode: 'source foo',
|
||||
sourcePath: 'foo path'
|
||||
}));
|
||||
bundle.finalize();
|
||||
expect(bundle.getMinifiedSourceAndMap({dev: true})).toBe(minified);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sourcemap bundle', function() {
|
||||
it('should create sourcemap', function() {
|
||||
var p = new Bundle('test_url');
|
||||
p.addModule(new ModuleTransport({
|
||||
code: [
|
||||
'transformed foo',
|
||||
'transformed foo',
|
||||
'transformed foo',
|
||||
].join('\n'),
|
||||
sourceCode: [
|
||||
'source foo',
|
||||
'source foo',
|
||||
'source foo',
|
||||
].join('\n'),
|
||||
sourcePath: 'foo path',
|
||||
}));
|
||||
p.addModule(new ModuleTransport({
|
||||
code: [
|
||||
'transformed bar',
|
||||
'transformed bar',
|
||||
'transformed bar',
|
||||
].join('\n'),
|
||||
sourceCode: [
|
||||
'source bar',
|
||||
'source bar',
|
||||
'source bar',
|
||||
].join('\n'),
|
||||
sourcePath: 'bar path',
|
||||
}));
|
||||
|
||||
p.setMainModuleId('foo');
|
||||
p.finalize({
|
||||
runBeforeMainModule: [],
|
||||
runMainModule: true,
|
||||
});
|
||||
var s = p.getSourceMap({dev: true});
|
||||
expect(s).toEqual(genSourceMap(p.getModules()));
|
||||
});
|
||||
|
||||
it('should combine sourcemaps', function() {
|
||||
var p = new Bundle('test_url');
|
||||
|
||||
p.addModule(new ModuleTransport({
|
||||
code: 'transformed foo;\n',
|
||||
map: {name: 'sourcemap foo'},
|
||||
sourceCode: 'source foo',
|
||||
sourcePath: 'foo path'
|
||||
}));
|
||||
|
||||
p.addModule(new ModuleTransport({
|
||||
code: 'transformed foo;\n',
|
||||
map: {name: 'sourcemap bar'},
|
||||
sourceCode: 'source foo',
|
||||
sourcePath: 'foo path'
|
||||
}));
|
||||
|
||||
p.addModule(new ModuleTransport({
|
||||
code: 'image module;\nimage module;',
|
||||
virtual: true,
|
||||
sourceCode: 'image module;\nimage module;',
|
||||
sourcePath: 'image.png',
|
||||
}));
|
||||
|
||||
p.setMainModuleId('foo');
|
||||
p.finalize({
|
||||
runBeforeMainModule: ['InitializeJavaScriptAppEngine'],
|
||||
runMainModule: true,
|
||||
});
|
||||
|
||||
var s = p.getSourceMap({dev: true});
|
||||
expect(s).toEqual({
|
||||
file: 'bundle.js',
|
||||
version: 3,
|
||||
sections: [
|
||||
{ offset: { line: 0, column: 0 }, map: { name: 'sourcemap foo' } },
|
||||
{ offset: { line: 2, column: 0 }, map: { name: 'sourcemap bar' } },
|
||||
{
|
||||
offset: {
|
||||
column: 0,
|
||||
line: 4
|
||||
},
|
||||
map: {
|
||||
file: 'image.png',
|
||||
mappings: 'AAAA;AACA;',
|
||||
names: [],
|
||||
sources: [ 'image.png' ],
|
||||
sourcesContent: ['image module;\nimage module;'],
|
||||
version: 3,
|
||||
}
|
||||
},
|
||||
{
|
||||
offset: {
|
||||
column: 0,
|
||||
line: 6
|
||||
},
|
||||
map: {
|
||||
file: 'require-InitializeJavaScriptAppEngine.js',
|
||||
mappings: 'AAAA;',
|
||||
names: [],
|
||||
sources: [ 'require-InitializeJavaScriptAppEngine.js' ],
|
||||
sourcesContent: [';require("InitializeJavaScriptAppEngine");'],
|
||||
version: 3,
|
||||
}
|
||||
},
|
||||
{
|
||||
offset: {
|
||||
column: 0,
|
||||
line: 7
|
||||
},
|
||||
map: {
|
||||
file: 'require-foo.js',
|
||||
mappings: 'AAAA;',
|
||||
names: [],
|
||||
sources: [ 'require-foo.js' ],
|
||||
sourcesContent: [';require("foo");'],
|
||||
version: 3,
|
||||
}
|
||||
},
|
||||
],
|
||||
return Promise.resolve().then(() => {
|
||||
return addModule({
|
||||
bundle,
|
||||
code: 'transformed foo;',
|
||||
sourceCode: 'source foo',
|
||||
sourcePath: 'foo path',
|
||||
});
|
||||
}).then(() => {
|
||||
bundle.finalize();
|
||||
expect(bundle.getMinifiedSourceAndMap({dev: true})).toBe(minified);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAssets()', function() {
|
||||
it('should save and return asset objects', function() {
|
||||
describe('sourcemap bundle', () => {
|
||||
pit('should create sourcemap', () => {
|
||||
const otherBundle = new Bundle('test_url');
|
||||
|
||||
return Promise.resolve().then(() => {
|
||||
return addModule({
|
||||
bundle: otherBundle,
|
||||
code: [
|
||||
'transformed foo',
|
||||
'transformed foo',
|
||||
'transformed foo',
|
||||
].join('\n'),
|
||||
sourceCode: [
|
||||
'source foo',
|
||||
'source foo',
|
||||
'source foo',
|
||||
].join('\n'),
|
||||
sourcePath: 'foo path',
|
||||
});
|
||||
}).then(() => {
|
||||
return addModule({
|
||||
bundle: otherBundle,
|
||||
code: [
|
||||
'transformed bar',
|
||||
'transformed bar',
|
||||
'transformed bar',
|
||||
].join('\n'),
|
||||
sourceCode: [
|
||||
'source bar',
|
||||
'source bar',
|
||||
'source bar',
|
||||
].join('\n'),
|
||||
sourcePath: 'bar path',
|
||||
});
|
||||
}).then(() => {
|
||||
otherBundle.setMainModuleId('foo');
|
||||
otherBundle.finalize({
|
||||
runBeforeMainModule: [],
|
||||
runMainModule: true,
|
||||
});
|
||||
const sourceMap = otherBundle.getSourceMap({dev: true});
|
||||
expect(sourceMap).toEqual(genSourceMap(otherBundle.getModules()));
|
||||
});
|
||||
});
|
||||
|
||||
pit('should combine sourcemaps', () => {
|
||||
const otherBundle = new Bundle('test_url');
|
||||
|
||||
return Promise.resolve().then(() => {
|
||||
return addModule({
|
||||
bundle: otherBundle,
|
||||
code: 'transformed foo;\n',
|
||||
sourceCode: 'source foo',
|
||||
map: {name: 'sourcemap foo'},
|
||||
sourcePath: 'foo path',
|
||||
});
|
||||
}).then(() => {
|
||||
return addModule({
|
||||
bundle: otherBundle,
|
||||
code: 'transformed bar;\n',
|
||||
sourceCode: 'source bar',
|
||||
map: {name: 'sourcemap bar'},
|
||||
sourcePath: 'bar path',
|
||||
});
|
||||
}).then(() => {
|
||||
return addModule({
|
||||
bundle: otherBundle,
|
||||
code: 'image module;\nimage module;',
|
||||
virtual: true,
|
||||
sourceCode: 'image module;\nimage module;',
|
||||
sourcePath: 'image.png',
|
||||
});
|
||||
}).then(() => {
|
||||
otherBundle.setMainModuleId('foo');
|
||||
otherBundle.finalize({
|
||||
runBeforeMainModule: ['InitializeJavaScriptAppEngine'],
|
||||
runMainModule: true,
|
||||
});
|
||||
|
||||
const sourceMap = otherBundle.getSourceMap({dev: true});
|
||||
expect(sourceMap).toEqual({
|
||||
file: 'bundle.js',
|
||||
version: 3,
|
||||
sections: [
|
||||
{ offset: { line: 0, column: 0 }, map: { name: 'sourcemap foo' } },
|
||||
{ offset: { line: 2, column: 0 }, map: { name: 'sourcemap bar' } },
|
||||
{
|
||||
offset: {
|
||||
column: 0,
|
||||
line: 4
|
||||
},
|
||||
map: {
|
||||
file: 'image.png',
|
||||
mappings: 'AAAA;AACA;',
|
||||
names: [],
|
||||
sources: [ 'image.png' ],
|
||||
sourcesContent: ['image module;\nimage module;'],
|
||||
version: 3,
|
||||
}
|
||||
},
|
||||
{
|
||||
offset: {
|
||||
column: 0,
|
||||
line: 6
|
||||
},
|
||||
map: {
|
||||
file: 'require-InitializeJavaScriptAppEngine.js',
|
||||
mappings: 'AAAA;',
|
||||
names: [],
|
||||
sources: [ 'require-InitializeJavaScriptAppEngine.js' ],
|
||||
sourcesContent: [';require("InitializeJavaScriptAppEngine");'],
|
||||
version: 3,
|
||||
}
|
||||
},
|
||||
{
|
||||
offset: {
|
||||
column: 0,
|
||||
line: 7
|
||||
},
|
||||
map: {
|
||||
file: 'require-foo.js',
|
||||
mappings: 'AAAA;',
|
||||
names: [],
|
||||
sources: [ 'require-foo.js' ],
|
||||
sourcesContent: [';require("foo");'],
|
||||
version: 3,
|
||||
}
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAssets()', () => {
|
||||
it('should save and return asset objects', () => {
|
||||
var p = new Bundle('test_url');
|
||||
var asset1 = {};
|
||||
var asset2 = {};
|
||||
|
@ -249,22 +278,27 @@ describe('Bundle', function() {
|
|||
});
|
||||
});
|
||||
|
||||
describe('getJSModulePaths()', function() {
|
||||
it('should return module paths', function() {
|
||||
var p = new Bundle('test_url');
|
||||
p.addModule(new ModuleTransport({
|
||||
code: 'transformed foo;\n',
|
||||
sourceCode: 'source foo',
|
||||
sourcePath: 'foo path'
|
||||
}));
|
||||
p.addModule(new ModuleTransport({
|
||||
code: 'image module;\nimage module;',
|
||||
virtual: true,
|
||||
sourceCode: 'image module;\nimage module;',
|
||||
sourcePath: 'image.png',
|
||||
}));
|
||||
|
||||
expect(p.getJSModulePaths()).toEqual(['foo path']);
|
||||
describe('getJSModulePaths()', () => {
|
||||
pit('should return module paths', () => {
|
||||
var otherBundle = new Bundle('test_url');
|
||||
return Promise.resolve().then(() => {
|
||||
return addModule({
|
||||
bundle: otherBundle,
|
||||
code: 'transformed foo;\n',
|
||||
sourceCode: 'source foo',
|
||||
sourcePath: 'foo path',
|
||||
});
|
||||
}).then(() => {
|
||||
return addModule({
|
||||
bundle: otherBundle,
|
||||
code: 'image module;\nimage module;',
|
||||
virtual: true,
|
||||
sourceCode: 'image module;\nimage module;',
|
||||
sourcePath: 'image.png',
|
||||
});
|
||||
}).then(() => {
|
||||
expect(otherBundle.getJSModulePaths()).toEqual(['foo path']);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -302,3 +336,20 @@ function genSourceMap(modules) {
|
|||
}
|
||||
return sourceMapGen.toJSON();
|
||||
}
|
||||
|
||||
function resolverFor(code) {
|
||||
return {
|
||||
wrapModule: (response, module, sourceCode) => Promise.resolve(
|
||||
{name: 'name', code}
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
function addModule({bundle, code, sourceCode, sourcePath, map, virtual}) {
|
||||
return bundle.addModule(
|
||||
resolverFor(code),
|
||||
null,
|
||||
null,
|
||||
{sourceCode, sourcePath, map, virtual}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -161,46 +161,29 @@ describe('Bundler', function() {
|
|||
runBeforeMainModule: [],
|
||||
runModule: true,
|
||||
sourceMapUrl: 'source_map_url',
|
||||
}).then(function(p) {
|
||||
expect(p.addModule.mock.calls[0][0]).toEqual({
|
||||
name: 'foo',
|
||||
code: 'lol transformed /root/foo.js lol',
|
||||
map: 'sourcemap /root/foo.js',
|
||||
sourceCode: 'source /root/foo.js',
|
||||
sourcePath: '/root/foo.js',
|
||||
});
|
||||
}).then(bundle => {
|
||||
const ithAddedModule = (i) => bundle.addModule.mock.calls[i][2].path;
|
||||
|
||||
expect(p.addModule.mock.calls[1][0]).toEqual({
|
||||
name: 'bar',
|
||||
code: 'lol transformed /root/bar.js lol',
|
||||
map: 'sourcemap /root/bar.js',
|
||||
sourceCode: 'source /root/bar.js',
|
||||
sourcePath: '/root/bar.js'
|
||||
});
|
||||
expect(ithAddedModule(0)).toEqual('/root/foo.js');
|
||||
expect(ithAddedModule(1)).toEqual('/root/bar.js');
|
||||
expect(ithAddedModule(2)).toEqual('/root/img/img.png');
|
||||
expect(ithAddedModule(3)).toEqual('/root/img/new_image.png');
|
||||
expect(ithAddedModule(4)).toEqual('/root/file.json');
|
||||
|
||||
var imgModule_DEPRECATED = {
|
||||
expect(bundle.finalize.mock.calls[0]).toEqual([
|
||||
{runMainModule: true, runBeforeMainModule: []}
|
||||
]);
|
||||
|
||||
expect(bundle.addAsset.mock.calls).toContain([{
|
||||
__packager_asset: true,
|
||||
path: '/root/img/img.png',
|
||||
uri: 'img',
|
||||
width: 25,
|
||||
height: 50,
|
||||
deprecated: true,
|
||||
};
|
||||
}]);
|
||||
|
||||
expect(p.addModule.mock.calls[2][0]).toEqual({
|
||||
name: 'image!img',
|
||||
code: 'lol module.exports = ' +
|
||||
JSON.stringify(imgModule_DEPRECATED) +
|
||||
'; lol',
|
||||
sourceCode: 'module.exports = ' +
|
||||
JSON.stringify(imgModule_DEPRECATED) +
|
||||
';',
|
||||
sourcePath: '/root/img/img.png',
|
||||
virtual: true,
|
||||
map: undefined,
|
||||
});
|
||||
|
||||
var imgModule = {
|
||||
expect(bundle.addAsset.mock.calls).toContain([{
|
||||
__packager_asset: true,
|
||||
fileSystemLocation: '/root/img',
|
||||
httpServerLocation: '/assets/img',
|
||||
|
@ -215,41 +198,7 @@ describe('Bundler', function() {
|
|||
hash: 'i am a hash',
|
||||
name: 'img',
|
||||
type: 'png',
|
||||
};
|
||||
|
||||
expect(p.addModule.mock.calls[3][0]).toEqual({
|
||||
name: 'new_image.png',
|
||||
code: 'lol module.exports = require("AssetRegistry").registerAsset(' +
|
||||
JSON.stringify(imgModule) +
|
||||
'); lol',
|
||||
sourceCode: 'module.exports = require("AssetRegistry").registerAsset(' +
|
||||
JSON.stringify(imgModule) +
|
||||
');',
|
||||
sourcePath: '/root/img/new_image.png',
|
||||
virtual: true,
|
||||
map: undefined,
|
||||
});
|
||||
|
||||
expect(p.addModule.mock.calls[4][0]).toEqual({
|
||||
name: 'package/file.json',
|
||||
code: 'lol module.exports = {"json":true}; lol',
|
||||
sourceCode: 'module.exports = {"json":true};',
|
||||
sourcePath: '/root/file.json',
|
||||
map: undefined,
|
||||
virtual: true,
|
||||
});
|
||||
|
||||
expect(p.finalize.mock.calls[0]).toEqual([
|
||||
{runMainModule: true, runBeforeMainModule: []}
|
||||
]);
|
||||
|
||||
expect(p.addAsset.mock.calls).toContain([
|
||||
imgModule_DEPRECATED
|
||||
]);
|
||||
|
||||
expect(p.addAsset.mock.calls).toContain([
|
||||
imgModule
|
||||
]);
|
||||
}]);
|
||||
|
||||
// TODO(amasad) This fails with 0 != 5 in OSS
|
||||
//expect(ProgressBar.prototype.tick.mock.calls.length).toEqual(modules.length);
|
||||
|
|
|
@ -18,6 +18,7 @@ const Cache = require('../DependencyResolver/Cache');
|
|||
const Transformer = require('../JSTransformer');
|
||||
const Resolver = require('../Resolver');
|
||||
const Bundle = require('./Bundle');
|
||||
const HMRBundle = require('./HMRBundle');
|
||||
const PrepackBundle = require('./PrepackBundle');
|
||||
const Activity = require('../Activity');
|
||||
const ModuleTransport = require('../lib/ModuleTransport');
|
||||
|
@ -155,31 +156,54 @@ class Bundler {
|
|||
return this._bundlesLayout.generateLayout(main, isDev);
|
||||
}
|
||||
|
||||
bundle({
|
||||
bundle(options) {
|
||||
return this._bundle({
|
||||
bundle: new Bundle(options.sourceMapUrl),
|
||||
includeSystemDependencies: true,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
bundleForHMR(options) {
|
||||
return this._bundle({
|
||||
bundle: new HMRBundle(),
|
||||
hot: true,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
_bundle({
|
||||
bundle,
|
||||
modules,
|
||||
entryFile,
|
||||
runModule: runMainModule,
|
||||
runBeforeMainModule,
|
||||
sourceMapUrl,
|
||||
dev: isDev,
|
||||
includeSystemDependencies,
|
||||
platform,
|
||||
unbundle: isUnbundle,
|
||||
hot: hot,
|
||||
}) {
|
||||
// Const cannot have the same name as the method (babel/babel#2834)
|
||||
const bbundle = new Bundle(sourceMapUrl);
|
||||
const findEventId = Activity.startEvent('find dependencies');
|
||||
let transformEventId;
|
||||
|
||||
const moduleSystem = this._resolver.getModuleSystemDependencies(
|
||||
{ dev: isDev, platform, isUnbundle }
|
||||
);
|
||||
|
||||
return this.getDependencies(entryFile, isDev, platform).then((response) => {
|
||||
Activity.endEvent(findEventId);
|
||||
bundle.setMainModuleId(response.mainModuleId);
|
||||
transformEventId = Activity.startEvent('transform');
|
||||
|
||||
// Prepend the module system polyfill to the top of dependencies
|
||||
var dependencies = moduleSystem.concat(response.dependencies);
|
||||
const moduleSystemDeps = includeSystemDependencies
|
||||
? this._resolver.getModuleSystemDependencies(
|
||||
{ dev: isDev, platform, isUnbundle }
|
||||
)
|
||||
: [];
|
||||
|
||||
const modulesToProcess = modules || response.dependencies;
|
||||
const dependencies = moduleSystemDeps.concat(modulesToProcess);
|
||||
|
||||
bundle.setNumPrependedModules && bundle.setNumPrependedModules(
|
||||
response.numPrependedDependencies + moduleSystemDeps.length
|
||||
);
|
||||
|
||||
let bar;
|
||||
if (process.stdout.isTTY) {
|
||||
|
@ -191,34 +215,41 @@ class Bundler {
|
|||
});
|
||||
}
|
||||
|
||||
bbundle.setMainModuleId(response.mainModuleId);
|
||||
bbundle.setNumPrependedModules(
|
||||
response.numPrependedDependencies + moduleSystem.length);
|
||||
return Promise.all(
|
||||
dependencies.map(
|
||||
module => this._transformModule(
|
||||
bbundle,
|
||||
module => {
|
||||
return this._transformModule(
|
||||
bundle,
|
||||
response,
|
||||
module,
|
||||
platform,
|
||||
hot,
|
||||
).then(transformed => {
|
||||
if (bar) {
|
||||
bar.tick();
|
||||
}
|
||||
|
||||
return {
|
||||
module,
|
||||
transformed,
|
||||
};
|
||||
});
|
||||
}
|
||||
)
|
||||
).then(transformedModules => Promise.all(
|
||||
transformedModules.map(({module, transformed}) => {
|
||||
return bundle.addModule(
|
||||
this._resolver,
|
||||
response,
|
||||
module,
|
||||
platform,
|
||||
hot,
|
||||
).then(transformed => {
|
||||
if (bar) {
|
||||
bar.tick();
|
||||
}
|
||||
return this._wrapTransformedModule(response, module, transformed);
|
||||
})
|
||||
)
|
||||
);
|
||||
}).then((transformedModules) => {
|
||||
transformed,
|
||||
);
|
||||
})
|
||||
));
|
||||
}).then(() => {
|
||||
Activity.endEvent(transformEventId);
|
||||
|
||||
transformedModules.forEach(function(moduleTransport) {
|
||||
bbundle.addModule(moduleTransport);
|
||||
});
|
||||
|
||||
bbundle.finalize({runBeforeMainModule, runMainModule});
|
||||
return bbundle;
|
||||
bundle.finalize({runBeforeMainModule, runMainModule});
|
||||
return bundle;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -284,35 +315,6 @@ class Bundler {
|
|||
});
|
||||
}
|
||||
|
||||
bundleForHMR({entryFile, platform, modules}) {
|
||||
return this.getDependencies(entryFile, /*isDev*/true, platform)
|
||||
.then(response => {
|
||||
return Promise.all(
|
||||
modules.map(module => {
|
||||
return Promise.all([
|
||||
module.getName(),
|
||||
this._transformModuleForHMR(module, platform),
|
||||
]).then(([moduleName, transformed]) => {
|
||||
return this._resolver.resolveRequires(response,
|
||||
module,
|
||||
transformed.code,
|
||||
).then(({name, code}) => {
|
||||
return (`
|
||||
__accept(
|
||||
'${moduleName}',
|
||||
function(global, require, module, exports) {
|
||||
${code}
|
||||
}
|
||||
);
|
||||
`);
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
})
|
||||
.then(modules => modules.join('\n'));
|
||||
}
|
||||
|
||||
_transformModuleForHMR(module, platform) {
|
||||
if (module.isAsset()) {
|
||||
return this._generateAssetObjAndCode(module, platform).then(
|
||||
|
@ -401,23 +403,6 @@ class Bundler {
|
|||
}
|
||||
}
|
||||
|
||||
_wrapTransformedModule(response, module, transformed) {
|
||||
return this._resolver.wrapModule(
|
||||
response,
|
||||
module,
|
||||
transformed.code
|
||||
).then(
|
||||
({code, name}) => new ModuleTransport({
|
||||
code,
|
||||
name,
|
||||
map: transformed.map,
|
||||
sourceCode: transformed.sourceCode,
|
||||
sourcePath: transformed.sourcePath,
|
||||
virtual: transformed.virtual,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
getGraphDebugInfo() {
|
||||
return this._resolver.getDebugInfo();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue