metro-bundler: Resolver @format

Reviewed By: cpojer

Differential Revision: D5514920

fbshipit-source-id: 59b8ab3555aca1703b22049382f39d1d67401c4f
This commit is contained in:
Jean Lauliac 2017-07-28 12:45:25 -07:00 committed by Facebook Github Bot
parent 2dda50893f
commit f332dbee47
5 changed files with 259 additions and 175 deletions

View File

@ -5,7 +5,10 @@
* This source code is licensed under the BSD-style license found in the * 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 * 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. * of patent rights can be found in the PATENTS file in the same directory.
*
* @format
*/ */
'use strict'; 'use strict';
jest.useRealTimers(); jest.useRealTimers();
@ -37,9 +40,9 @@ describe('Resolver', function() {
return polyfill; return polyfill;
}); });
DependencyGraph.load = jest.fn().mockImplementation( DependencyGraph.load = jest
opts => Promise.resolve(new DependencyGraph(opts)), .fn()
); .mockImplementation(opts => Promise.resolve(new DependencyGraph(opts)));
DependencyGraph.prototype.createPolyfill = jest.fn(); DependencyGraph.prototype.createPolyfill = jest.fn();
DependencyGraph.prototype.getDependencies = jest.fn(); DependencyGraph.prototype.getDependencies = jest.fn();
@ -73,7 +76,9 @@ describe('Resolver', function() {
var module = new Module({}); var module = new Module({});
module.path = id; module.path = id;
module.getName.mockImplementation(() => Promise.resolve(id)); module.getName.mockImplementation(() => Promise.resolve(id));
module.getDependencies.mockImplementation(() => Promise.resolve(dependencies)); module.getDependencies.mockImplementation(() =>
Promise.resolve(dependencies),
);
return module; return module;
} }
@ -86,8 +91,7 @@ describe('Resolver', function() {
function createPolyfill(id, dependencies) { function createPolyfill(id, dependencies) {
var polyfill = new Polyfill({}); var polyfill = new Polyfill({});
polyfill.getName = jest.fn(() => Promise.resolve(id)); polyfill.getName = jest.fn(() => Promise.resolve(id));
polyfill.getDependencies = polyfill.getDependencies = jest.fn(() => Promise.resolve(dependencies));
jest.fn(() => Promise.resolve(dependencies));
return polyfill; return polyfill;
} }
@ -98,8 +102,9 @@ describe('Resolver', function() {
const platform = 'ios'; const platform = 'ios';
const entry = '/root/index.js'; const entry = '/root/index.js';
DependencyGraph.prototype.getDependencies.mockImplementation( DependencyGraph.prototype.getDependencies.mockImplementation(() =>
() => Promise.reject()); Promise.reject(),
);
return Resolver.load({projectRoot: '/root'}) return Resolver.load({projectRoot: '/root'})
.then(r => r.getDependencies(entry, {platform}, transformOptions)) .then(r => r.getDependencies(entry, {platform}, transformOptions))
.catch(() => { .catch(() => {
@ -114,7 +119,8 @@ describe('Resolver', function() {
it('passes custom platforms to the dependency graph', function() { it('passes custom platforms to the dependency graph', function() {
expect.assertions(1); expect.assertions(1);
return Resolver.load({ // eslint-disable-line no-new return Resolver.load({
// eslint-disable-line no-new
projectRoot: '/root', projectRoot: '/root',
platforms: ['ios', 'windows', 'vr'], platforms: ['ios', 'windows', 'vr'],
}).then(() => { }).then(() => {
@ -135,36 +141,45 @@ describe('Resolver', function() {
}); });
DependencyGraph.prototype.getDependencies.mockImplementation(function() { DependencyGraph.prototype.getDependencies.mockImplementation(function() {
return Promise.resolve(new ResolutionResponseMock({ return Promise.resolve(
new ResolutionResponseMock({
dependencies: deps, dependencies: deps,
mainModuleId: 'index', mainModuleId: 'index',
})); }),
);
}); });
return depResolverPromise return depResolverPromise
.then(r => r.getDependencies( .then(r =>
r.getDependencies(
'/root/index.js', '/root/index.js',
{dev: false}, {dev: false},
undefined, undefined,
undefined, undefined,
createGetModuleId() createGetModuleId(),
)).then(result => { ),
)
.then(result => {
expect(result.mainModuleId).toEqual('index'); expect(result.mainModuleId).toEqual('index');
const calls = DependencyGraph.prototype.createPolyfill.mock.calls; const calls = DependencyGraph.prototype.createPolyfill.mock.calls;
const callPolyfill1 = calls[result.dependencies.length - 3]; const callPolyfill1 = calls[result.dependencies.length - 3];
const callPolyfill2 = calls[result.dependencies.length - 2]; const callPolyfill2 = calls[result.dependencies.length - 2];
expect(callPolyfill1).toEqual([{ expect(callPolyfill1).toEqual([
{
file: 'custom-polyfill-1', file: 'custom-polyfill-1',
id: 'custom-polyfill-1', id: 'custom-polyfill-1',
dependencies: [], dependencies: [],
}]); },
]);
expect(callPolyfill2).toEqual([{ expect(callPolyfill2).toEqual([
{
file: 'custom-polyfill-2', file: 'custom-polyfill-2',
id: 'custom-polyfill-2', id: 'custom-polyfill-2',
dependencies: ['custom-polyfill-1'], dependencies: ['custom-polyfill-1'],
}]); },
]);
}); });
}); });
}); });
@ -174,7 +189,9 @@ describe('Resolver', function() {
beforeEach(() => { beforeEach(() => {
return Resolver.load({ return Resolver.load({
projectRoot: '/root', projectRoot: '/root',
}).then(r => { depResolver = r; }); }).then(r => {
depResolver = r;
});
}); });
it('should resolve modules', function() { it('should resolve modules', function() {
@ -185,7 +202,7 @@ describe('Resolver', function() {
// require // require
'require("x")', 'require("x")',
'require("y");require(\'abc\');', 'require("y");require(\'abc\');',
'require( \'z\' )', "require( 'z' )",
'require( "a")', 'require( "a")',
'require("b" )', 'require("b" )',
].join('\n'); ].join('\n');
@ -206,42 +223,54 @@ describe('Resolver', function() {
mainModuleId: 'test module', mainModuleId: 'test module',
}); });
resolutionResponse.getResolvedDependencyPairs = (module) => { resolutionResponse.getResolvedDependencyPairs = module => {
return [ return [
['x', createModule('changed')], ['x', createModule('changed')],
['y', createModule('Y')], ['y', createModule('Y')],
['abc', createModule('abc')] ['abc', createModule('abc')],
]; ];
} };
const moduleIds = new Map( const moduleIds = new Map(
resolutionResponse resolutionResponse
.getResolvedDependencyPairs() .getResolvedDependencyPairs()
.map(([importId, module]) => [ .map(([importId, module]) => [
importId, importId,
padRight(resolutionResponse.getModuleId(module), importId.length + 2), padRight(
]) resolutionResponse.getModuleId(module),
importId.length + 2,
),
]),
); );
return depResolver.wrapModule({ return depResolver
.wrapModule({
resolutionResponse, resolutionResponse,
module: module, module: module,
name: 'test module', name: 'test module',
code, code,
meta: {dependencyOffsets}, meta: {dependencyOffsets},
dev: false, dev: false,
}).then(({code: processedCode}) => { })
expect(processedCode).toEqual([ .then(({code: processedCode}) => {
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')}) // ${moduleIds.get('x').trim()} = x`, `require(${moduleIds.get('x')}) // ${moduleIds
`require(${moduleIds.get('y')});require(${moduleIds.get('abc') .get('x')
}); // ${moduleIds.get('abc').trim()} = abc // ${moduleIds.get('y').trim()} = y`, .trim()} = x`,
'require( \'z\' )', `require(${moduleIds.get('y')});require(${moduleIds.get(
'abc',
)}); // ${moduleIds.get('abc').trim()} = abc // ${moduleIds
.get('y')
.trim()} = y`,
"require( 'z' )",
'require( "a")', 'require( "a")',
'require("b" )', 'require("b" )',
`}, ${resolutionResponse.getModuleId(module)});`, `}, ${resolutionResponse.getModuleId(module)});`,
].join('\n')); ].join('\n'),
);
}); });
}); });
@ -249,23 +278,29 @@ describe('Resolver', function() {
expect.assertions(1); expect.assertions(1);
const module = createModule('test module'); const module = createModule('test module');
const code = 'arbitrary(code)' const code = 'arbitrary(code)';
const resolutionResponse = new ResolutionResponseMock({ const resolutionResponse = new ResolutionResponseMock({
dependencies: [module], dependencies: [module],
mainModuleId: 'test module', mainModuleId: 'test module',
}); });
return depResolver.wrapModule({ return depResolver
.wrapModule({
resolutionResponse, resolutionResponse,
code, code,
module, module,
name: 'test module', name: 'test module',
dev: true, dev: true,
}).then(({code: processedCode}) => })
expect(processedCode).toEqual([ .then(({code: processedCode}) =>
expect(processedCode).toEqual(
[
'__d(/* test module */function(global, require, module, exports) {' + '__d(/* test module */function(global, require, module, exports) {' +
code, code,
`}, ${resolutionResponse.getModuleId(module)}, null, "test module");` `}, ${resolutionResponse.getModuleId(
].join('\n')) module,
)}, null, "test module");`,
].join('\n'),
),
); );
}); });
@ -277,40 +312,44 @@ describe('Resolver', function() {
mainModuleId: 'test module', mainModuleId: 'test module',
}); });
const inputMap = {version: 3, mappings: 'ARBITRARY'}; const inputMap = {version: 3, mappings: 'ARBITRARY'};
return depResolver.wrapModule({ return depResolver
.wrapModule({
resolutionResponse, resolutionResponse,
module, module,
name: 'test module', name: 'test module',
code: 'arbitrary(code)', code: 'arbitrary(code)',
map: inputMap, map: inputMap,
}).then(({map}) => expect(map).toBe(inputMap)); })
.then(({map}) => expect(map).toBe(inputMap));
}); });
it('should resolve polyfills', function() { it('should resolve polyfills', function() {
expect.assertions(1); expect.assertions(1);
return Resolver.load({ return Resolver.load({
projectRoot: '/root', projectRoot: '/root',
}).then(depResolver => {; }).then(depResolver => {
const polyfill = createPolyfill('test polyfill', []); const polyfill = createPolyfill('test polyfill', []);
const code = [ const code = ['global.fetch = () => 1;'].join('');
'global.fetch = () => 1;', return depResolver
].join(''); .wrapModule({
return depResolver.wrapModule({
module: polyfill, module: polyfill,
code code,
}).then(({code: processedCode}) => { })
expect(processedCode).toEqual([ .then(({code: processedCode}) => {
expect(processedCode).toEqual(
[
'(function(global) {', '(function(global) {',
'global.fetch = () => 1;', 'global.fetch = () => 1;',
'\n})' + '\n})' +
"(typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this);", "(typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this);",
].join('')); ].join(''),
);
}); });
}); });
}); });
describe('JSON files:', () => { describe('JSON files:', () => {
const code = JSON.stringify({arbitrary: "data"}); const code = JSON.stringify({arbitrary: 'data'});
const id = 'arbitrary.json'; const id = 'arbitrary.json';
let depResolver, module, resolutionResponse; let depResolver, module, resolutionResponse;
@ -330,10 +369,15 @@ describe('Resolver', function() {
return depResolver return depResolver
.wrapModule({resolutionResponse, module, name: id, code, dev: false}) .wrapModule({resolutionResponse, module, name: id, code, dev: false})
.then(({code: processedCode}) => .then(({code: processedCode}) =>
expect(processedCode).toEqual([ expect(processedCode).toEqual(
[
`__d(/* ${id} */function(global, require, module, exports) {`, `__d(/* ${id} */function(global, require, module, exports) {`,
`module.exports = ${code}\n}, ${resolutionResponse.getModuleId(module)});`, `module.exports = ${code}\n}, ${resolutionResponse.getModuleId(
].join(''))); module,
)});`,
].join(''),
),
);
}); });
}); });
@ -344,7 +388,8 @@ describe('Resolver', function() {
beforeEach(() => { beforeEach(() => {
minifyCode = jest.fn((filename, code, map) => minifyCode = jest.fn((filename, code, map) =>
Promise.resolve({code, map})); Promise.resolve({code, map}),
);
module = createModule(id); module = createModule(id);
module.path = '/arbitrary/path.js'; module.path = '/arbitrary/path.js';
resolutionResponse = new ResolutionResponseMock({ resolutionResponse = new ResolutionResponseMock({
@ -355,14 +400,16 @@ describe('Resolver', function() {
return Resolver.load({ return Resolver.load({
projectRoot: '/root', projectRoot: '/root',
minifyCode, minifyCode,
}).then(r => { depResolver = r; }); }).then(r => {
depResolver = r;
});
}); });
it('should invoke the minifier with the wrapped code', () => { it('should invoke the minifier with the wrapped code', () => {
expect.assertions(1); expect.assertions(1);
const wrappedCode = const wrappedCode = `__d(/* ${id} */function(global, require, module, exports) {${code}\n}, ${resolutionResponse.getModuleId(
`__d(/* ${id} */function(global, require, module, exports) {${ module,
code}\n}, ${resolutionResponse.getModuleId(module)});` )});`;
return depResolver return depResolver
.wrapModule({ .wrapModule({
resolutionResponse, resolutionResponse,
@ -372,8 +419,13 @@ describe('Resolver', function() {
map: sourceMap, map: sourceMap,
minify: true, minify: true,
dev: false, dev: false,
}).then(() => { })
expect(minifyCode).toBeCalledWith(module.path, wrappedCode, sourceMap); .then(() => {
expect(minifyCode).toBeCalledWith(
module.path,
wrappedCode,
sourceMap,
);
}); });
}); });
@ -381,9 +433,17 @@ describe('Resolver', function() {
expect.assertions(2); expect.assertions(2);
const minifiedCode = 'minified(code)'; const minifiedCode = 'minified(code)';
const minifiedMap = {version: 3, file: ['minified']}; const minifiedMap = {version: 3, file: ['minified']};
minifyCode.mockReturnValue(Promise.resolve({code: minifiedCode, map: minifiedMap})); minifyCode.mockReturnValue(
Promise.resolve({code: minifiedCode, map: minifiedMap}),
);
return depResolver return depResolver
.wrapModule({resolutionResponse, module, name: id, code, minify: true}) .wrapModule({
resolutionResponse,
module,
name: id,
code,
minify: true,
})
.then(({code, map}) => { .then(({code, map}) => {
expect(code).toEqual(minifiedCode); expect(code).toEqual(minifiedCode);
expect(map).toEqual(minifiedMap); expect(map).toEqual(minifiedMap);

View File

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
* *
* @flow * @flow
* @format
*/ */
'use strict'; 'use strict';
@ -22,13 +23,19 @@ import type {MappingsMap} from '../lib/SourceMap';
import type {PostMinifyProcess} from '../Bundler'; import type {PostMinifyProcess} from '../Bundler';
import type {Options as JSTransformerOptions} from '../JSTransformer/worker'; import type {Options as JSTransformerOptions} from '../JSTransformer/worker';
import type {Reporter} from '../lib/reporting'; import type {Reporter} from '../lib/reporting';
import type {TransformCache, GetTransformCacheKey} from '../lib/TransformCaching'; import type {
TransformCache,
GetTransformCacheKey,
} from '../lib/TransformCaching';
import type {GlobalTransformCache} from '../lib/GlobalTransformCache'; import type {GlobalTransformCache} from '../lib/GlobalTransformCache';
type MinifyCode = (filePath: string, code: string, map: MappingsMap) => type MinifyCode = (
Promise<{code: string, map: MappingsMap}>; filePath: string,
code: string,
map: MappingsMap,
) => Promise<{code: string, map: MappingsMap}>;
type ContainsTransformerOptions = {+transformer: JSTransformerOptions} type ContainsTransformerOptions = {+transformer: JSTransformerOptions};
type Options = {| type Options = {|
+assetExts: Array<string>, +assetExts: Array<string>,
@ -55,7 +62,6 @@ type Options = {|
|}; |};
class Resolver { class Resolver {
_depGraph: DependencyGraph; _depGraph: DependencyGraph;
_getPolyfills: ({platform: ?string}) => $ReadOnlyArray<string>; _getPolyfills: ({platform: ?string}) => $ReadOnlyArray<string>;
_minifyCode: MinifyCode; _minifyCode: MinifyCode;
@ -119,16 +125,18 @@ class Resolver {
getModuleId: mixed, getModuleId: mixed,
): Promise<ResolutionResponse<Module, T>> { ): Promise<ResolutionResponse<Module, T>> {
const {platform, recursive = true} = options; const {platform, recursive = true} = options;
return this._depGraph.getDependencies({ return this._depGraph
.getDependencies({
entryPath, entryPath,
platform, platform,
options: bundlingOptions, options: bundlingOptions,
recursive, recursive,
onProgress, onProgress,
}).then(resolutionResponse => { })
this._getPolyfillDependencies(platform).reverse().forEach( .then(resolutionResponse => {
polyfill => resolutionResponse.prependDependency(polyfill) this._getPolyfillDependencies(platform)
); .reverse()
.forEach(polyfill => resolutionResponse.prependDependency(polyfill));
/* $FlowFixMe: monkey patching */ /* $FlowFixMe: monkey patching */
resolutionResponse.getModuleId = getModuleId; resolutionResponse.getModuleId = getModuleId;
@ -137,33 +145,32 @@ class Resolver {
} }
getModuleSystemDependencies({dev = true}: {dev?: boolean}): Array<Module> { getModuleSystemDependencies({dev = true}: {dev?: boolean}): Array<Module> {
const prelude = dev const prelude = dev
? pathJoin(__dirname, 'polyfills/prelude_dev.js') ? pathJoin(__dirname, 'polyfills/prelude_dev.js')
: pathJoin(__dirname, 'polyfills/prelude.js'); : pathJoin(__dirname, 'polyfills/prelude.js');
const moduleSystem = defaults.moduleSystem; const moduleSystem = defaults.moduleSystem;
return [ return [prelude, moduleSystem].map(moduleName =>
prelude, this._depGraph.createPolyfill({
moduleSystem,
].map(moduleName => this._depGraph.createPolyfill({
file: moduleName, file: moduleName,
id: moduleName, id: moduleName,
dependencies: [], dependencies: [],
})); }),
);
} }
_getPolyfillDependencies(platform: ?string): Array<Module> { _getPolyfillDependencies(platform: ?string): Array<Module> {
const polyfillModuleNames = this._getPolyfills({platform}) const polyfillModuleNames = this._getPolyfills({platform}).concat(
.concat(this._polyfillModuleNames); this._polyfillModuleNames,
);
return polyfillModuleNames.map( return polyfillModuleNames.map((polyfillModuleName, idx) =>
(polyfillModuleName, idx) => this._depGraph.createPolyfill({ this._depGraph.createPolyfill({
file: polyfillModuleName, file: polyfillModuleName,
id: polyfillModuleName, id: polyfillModuleName,
dependencies: polyfillModuleNames.slice(0, idx), dependencies: polyfillModuleNames.slice(0, idx),
}) }),
); );
} }
@ -177,7 +184,8 @@ class Resolver {
// here, we build a map of all require strings (relative and absolute) // here, we build a map of all require strings (relative and absolute)
// to the canonical ID of the module they reference // to the canonical ID of the module they reference
resolutionResponse.getResolvedDependencyPairs(module) resolutionResponse
.getResolvedDependencyPairs(module)
.forEach(([depName, depModule]) => { .forEach(([depName, depModule]) => {
if (depModule) { if (depModule) {
/* $FlowFixMe: `getModuleId` is monkey-patched so may not exist */ /* $FlowFixMe: `getModuleId` is monkey-patched so may not exist */
@ -193,13 +201,15 @@ 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);
return dependencyOffsets.reduceRight( return dependencyOffsets
.reduceRight(
([unhandled, handled], offset) => [ ([unhandled, handled], offset) => [
unhandled.slice(0, offset), unhandled.slice(0, offset),
replaceDependencyID(unhandled.slice(offset) + handled, resolvedDeps), replaceDependencyID(unhandled.slice(offset) + handled, resolvedDeps),
], ],
[code, ''], [code, ''],
).join(''); )
.join('');
} }
wrapModule<T: ContainsTransformerOptions>({ wrapModule<T: ContainsTransformerOptions>({
@ -236,7 +246,7 @@ class Resolver {
resolutionResponse, resolutionResponse,
module, module,
code, code,
meta.dependencyOffsets meta.dependencyOffsets,
); );
code = defineModuleCode(moduleId, code, name, dev); code = defineModuleCode(moduleId, code, name, dev);
} }
@ -246,9 +256,15 @@ class Resolver {
: Promise.resolve({code, map}); : Promise.resolve({code, map});
} }
minifyModule( minifyModule({
{path, code, map}: {path: string, code: string, map: MappingsMap}, path,
): Promise<{code: string, map: MappingsMap}> { code,
map,
}: {
path: string,
code: string,
map: MappingsMap,
}): Promise<{code: string, map: MappingsMap}> {
return this._minifyCode(path, code, map); return this._minifyCode(path, code, map);
} }

View File

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
* *
* @polyfill * @polyfill
* @format
*/ */
/* eslint-disable strict */ /* eslint-disable strict */

View File

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
* *
* @polyfill * @polyfill
* @format
*/ */
/* eslint-disable strict */ /* eslint-disable strict */

View File

@ -8,6 +8,7 @@
* *
* @polyfill * @polyfill
* @flow * @flow
* @format
*/ */
'use strict'; 'use strict';
@ -43,8 +44,7 @@ type ModuleDefinition = {|
isInitialized: boolean, isInitialized: boolean,
verboseName?: string, verboseName?: string,
|}; |};
type ModuleMap = type ModuleMap = {[key: ModuleID]: ModuleDefinition};
{[key: ModuleID]: (ModuleDefinition)};
type RequireFn = (id: ModuleID | VerboseModuleNameForDev) => Exports; type RequireFn = (id: ModuleID | VerboseModuleNameForDev) => Exports;
type VerboseModuleNameForDev = string; type VerboseModuleNameForDev = string;
@ -97,7 +97,7 @@ function require(moduleId: ModuleID | VerboseModuleNameForDev) {
} else { } else {
console.warn( console.warn(
`Requiring module '${verboseName}' by name is only supported for ` + `Requiring module '${verboseName}' by name is only supported for ` +
'debugging purposes and will BREAK IN PRODUCTION!' 'debugging purposes and will BREAK IN PRODUCTION!',
); );
} }
} }
@ -155,7 +155,7 @@ function loadModuleImplementation(moduleId, module) {
// factory to keep any require cycles inside the factory from causing an // factory to keep any require cycles inside the factory from causing an
// infinite require loop. // infinite require loop.
module.isInitialized = true; module.isInitialized = true;
const exports = module.exports = {}; const exports = (module.exports = {});
const {factory, dependencyMap} = module; const {factory, dependencyMap} = module;
try { try {
if (__DEV__) { if (__DEV__) {
@ -205,8 +205,13 @@ function unknownModuleError(id) {
} }
function moduleThrewError(id, error: any) { function moduleThrewError(id, error: any) {
const displayName = __DEV__ && modules[id] && modules[id].verboseName || id; const displayName = (__DEV__ && modules[id] && modules[id].verboseName) || id;
return Error('Requiring module "' + displayName + '", which threw an exception: ' + error); return Error(
'Requiring module "' +
displayName +
'", which threw an exception: ' +
error,
);
} }
if (__DEV__) { if (__DEV__) {
@ -216,21 +221,21 @@ if (__DEV__) {
var createHotReloadingObject = function() { var createHotReloadingObject = function() {
const hot: HotModuleReloadingData = { const hot: HotModuleReloadingData = {
acceptCallback: null, acceptCallback: null,
accept: callback => { hot.acceptCallback = callback; }, accept: callback => {
hot.acceptCallback = callback;
},
}; };
return hot; return hot;
}; };
const acceptAll = function( const acceptAll = function(dependentModules, inverseDependencies) {
dependentModules,
inverseDependencies,
) {
if (!dependentModules || dependentModules.length === 0) { if (!dependentModules || dependentModules.length === 0) {
return true; return true;
} }
const notAccepted = dependentModules.filter( const notAccepted = dependentModules.filter(
module => !accept(module, /*factory*/ undefined, inverseDependencies)); module => !accept(module, /*factory*/ undefined, inverseDependencies),
);
const parents = []; const parents = [];
for (let i = 0; i < notAccepted.length; i++) { for (let i = 0; i < notAccepted.length; i++) {
@ -252,7 +257,8 @@ if (__DEV__) {
) { ) {
const mod = modules[id]; const mod = modules[id];
if (!mod && factory) { // new modules need a factory if (!mod && factory) {
// new modules need a factory
define(factory, id); define(factory, id);
return true; // new modules don't need to be accepted return true; // new modules don't need to be accepted
} }
@ -261,7 +267,7 @@ if (__DEV__) {
if (!hot) { if (!hot) {
console.warn( console.warn(
'Cannot accept module because Hot Module Replacement ' + 'Cannot accept module because Hot Module Replacement ' +
'API was not installed.' 'API was not installed.',
); );
return false; return false;
} }