mirror of https://github.com/status-im/metro.git
Make metro rely much less in the ModuleCache system
Reviewed By: jeanlauliac Differential Revision: D6949157 fbshipit-source-id: cb5ef25aa582935f7c624375392be7fceefd87b6
This commit is contained in:
parent
03c3b3d219
commit
a5307e986e
|
@ -19,16 +19,15 @@ const {EventEmitter} = require('events');
|
||||||
import type Bundler from '../Bundler';
|
import type Bundler from '../Bundler';
|
||||||
import type {Options as JSTransformerOptions} from '../JSTransformer/worker';
|
import type {Options as JSTransformerOptions} from '../JSTransformer/worker';
|
||||||
import type DependencyGraph from '../node-haste/DependencyGraph';
|
import type DependencyGraph from '../node-haste/DependencyGraph';
|
||||||
import type Module from '../node-haste/Module';
|
|
||||||
import type {BundleOptions} from '../shared/types.flow';
|
import type {BundleOptions} from '../shared/types.flow';
|
||||||
|
|
||||||
export type DeltaResult = {|
|
export type DeltaResult = {|
|
||||||
+modified: Map<string, Module>,
|
+modified: Map<string, DependencyEdge>,
|
||||||
+deleted: Set<string>,
|
+deleted: Set<string>,
|
||||||
+reset: boolean,
|
+reset: boolean,
|
||||||
|};
|
|};
|
||||||
|
|
||||||
import type {DependencyEdges} from './traverseDependencies';
|
import type {DependencyEdge, DependencyEdges} from './traverseDependencies';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is in charge of calculating the delta of changed modules that
|
* This class is in charge of calculating the delta of changed modules that
|
||||||
|
@ -181,7 +180,7 @@ class DeltaCalculator extends EventEmitter {
|
||||||
new Map(),
|
new Map(),
|
||||||
);
|
);
|
||||||
|
|
||||||
return [path, ...added];
|
return Array.from(added.keys());
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -240,10 +239,6 @@ class DeltaCalculator extends EventEmitter {
|
||||||
this._options.entryFile,
|
this._options.entryFile,
|
||||||
);
|
);
|
||||||
|
|
||||||
const modified = new Map([
|
|
||||||
[path, this._dependencyGraph.getModuleForPath(path)],
|
|
||||||
]);
|
|
||||||
|
|
||||||
const {added} = await initialTraverseDependencies(
|
const {added} = await initialTraverseDependencies(
|
||||||
path,
|
path,
|
||||||
this._dependencyGraph,
|
this._dependencyGraph,
|
||||||
|
@ -252,12 +247,8 @@ class DeltaCalculator extends EventEmitter {
|
||||||
this._options.onProgress || undefined,
|
this._options.onProgress || undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const path of added) {
|
|
||||||
modified.set(path, this._dependencyGraph.getModuleForPath(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
modified,
|
modified: added,
|
||||||
deleted: new Set(),
|
deleted: new Set(),
|
||||||
reset: true,
|
reset: true,
|
||||||
};
|
};
|
||||||
|
@ -291,18 +282,8 @@ class DeltaCalculator extends EventEmitter {
|
||||||
this._options.onProgress || undefined,
|
this._options.onProgress || undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
const modified = new Map();
|
|
||||||
|
|
||||||
for (const path of modifiedDependencies) {
|
|
||||||
modified.set(path, this._dependencyGraph.getModuleForPath(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const path of added) {
|
|
||||||
modified.set(path, this._dependencyGraph.getModuleForPath(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
modified,
|
modified: added,
|
||||||
deleted,
|
deleted,
|
||||||
reset: false,
|
reset: false,
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,7 +17,6 @@ const createModuleIdFactory = require('../lib/createModuleIdFactory');
|
||||||
const defaults = require('../defaults');
|
const defaults = require('../defaults');
|
||||||
const getPreludeCode = require('../lib/getPreludeCode');
|
const getPreludeCode = require('../lib/getPreludeCode');
|
||||||
const nullthrows = require('fbjs/lib/nullthrows');
|
const nullthrows = require('fbjs/lib/nullthrows');
|
||||||
const removeInlineRequiresBlacklistFromOptions = require('../lib/removeInlineRequiresBlacklistFromOptions');
|
|
||||||
|
|
||||||
const {EventEmitter} = require('events');
|
const {EventEmitter} = require('events');
|
||||||
|
|
||||||
|
@ -26,7 +25,7 @@ import type {Options as JSTransformerOptions} from '../JSTransformer/worker';
|
||||||
import type DependencyGraph from '../node-haste/DependencyGraph';
|
import type DependencyGraph from '../node-haste/DependencyGraph';
|
||||||
import type Module from '../node-haste/Module';
|
import type Module from '../node-haste/Module';
|
||||||
import type {Options as BundleOptions, MainOptions} from './';
|
import type {Options as BundleOptions, MainOptions} from './';
|
||||||
import type {DependencyEdges} from './traverseDependencies';
|
import type {DependencyEdge, DependencyEdges} from './traverseDependencies';
|
||||||
import type {MetroSourceMapSegmentTuple} from 'metro-source-map';
|
import type {MetroSourceMapSegmentTuple} from 'metro-source-map';
|
||||||
|
|
||||||
export type DeltaEntryType =
|
export type DeltaEntryType =
|
||||||
|
@ -342,8 +341,14 @@ class DeltaTransformer extends EventEmitter {
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const edges = await Promise.all(
|
||||||
|
modules.map(module =>
|
||||||
|
this._createEdgeFromScript(module, transformOptions),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
const transformedModules = await this._transformModules(
|
const transformedModules = await this._transformModules(
|
||||||
modules,
|
edges,
|
||||||
transformOptions,
|
transformOptions,
|
||||||
dependencyEdges,
|
dependencyEdges,
|
||||||
);
|
);
|
||||||
|
@ -416,7 +421,7 @@ class DeltaTransformer extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
async _transformModules(
|
async _transformModules(
|
||||||
modules: Array<Module>,
|
modules: Array<DependencyEdge>,
|
||||||
transformOptions: JSTransformerOptions,
|
transformOptions: JSTransformerOptions,
|
||||||
dependencyEdges: DependencyEdges,
|
dependencyEdges: DependencyEdges,
|
||||||
): Promise<DeltaEntries> {
|
): Promise<DeltaEntries> {
|
||||||
|
@ -429,15 +434,34 @@ class DeltaTransformer extends EventEmitter {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _transformModule(
|
async _createEdgeFromScript(
|
||||||
module: Module,
|
module: Module,
|
||||||
transformOptions: JSTransformerOptions,
|
transformOptions: JSTransformerOptions,
|
||||||
|
): Promise<DependencyEdge> {
|
||||||
|
const result = await module.read(transformOptions);
|
||||||
|
|
||||||
|
const edge = {
|
||||||
|
dependencies: new Map(),
|
||||||
|
inverseDependencies: new Set(),
|
||||||
|
path: module.path,
|
||||||
|
output: {
|
||||||
|
code: result.code,
|
||||||
|
map: result.map,
|
||||||
|
source: result.source,
|
||||||
|
type: 'script',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return edge;
|
||||||
|
}
|
||||||
|
|
||||||
|
async _transformModule(
|
||||||
|
edge: DependencyEdge,
|
||||||
|
transformOptions: JSTransformerOptions,
|
||||||
dependencyEdges: DependencyEdges,
|
dependencyEdges: DependencyEdges,
|
||||||
): Promise<[number, ?DeltaEntry]> {
|
): Promise<[number, ?DeltaEntry]> {
|
||||||
const name = module.getName();
|
const name = this._dependencyGraph.getHasteName(edge.path);
|
||||||
const metadata = await this._getMetadata(module, transformOptions);
|
|
||||||
|
|
||||||
const edge = dependencyEdges.get(module.path);
|
|
||||||
const dependencyPairs = edge ? edge.dependencies : new Map();
|
const dependencyPairs = edge ? edge.dependencies : new Map();
|
||||||
|
|
||||||
let wrappedCode;
|
let wrappedCode;
|
||||||
|
@ -445,26 +469,30 @@ class DeltaTransformer extends EventEmitter {
|
||||||
// Get the absolute path of each of the module dependencies from the
|
// Get the absolute path of each of the module dependencies from the
|
||||||
// dependency edges. The module dependencies ensure correct order, while
|
// dependency edges. The module dependencies ensure correct order, while
|
||||||
// the dependency edges do not ensure the same order between rebuilds.
|
// the dependency edges do not ensure the same order between rebuilds.
|
||||||
const dependencies = metadata.dependencies.map(dependency =>
|
const dependencies = Array.from(edge.dependencies.keys()).map(dependency =>
|
||||||
nullthrows(dependencyPairs.get(dependency)),
|
nullthrows(dependencyPairs.get(dependency)),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!module.isPolyfill()) {
|
if (edge.output.type !== 'script') {
|
||||||
wrappedCode = this._addDependencyMap({
|
wrappedCode = this._addDependencyMap({
|
||||||
code: metadata.code,
|
code: edge.output.code,
|
||||||
dependencies,
|
dependencies,
|
||||||
name,
|
name,
|
||||||
path: module.path,
|
path: edge.path,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
wrappedCode = metadata.code;
|
wrappedCode = edge.output.code;
|
||||||
}
|
}
|
||||||
|
|
||||||
const {code, map} = transformOptions.minify
|
const {code, map} = transformOptions.minify
|
||||||
? await this._bundler.minifyModule(module.path, wrappedCode, metadata.map)
|
? await this._bundler.minifyModule(
|
||||||
: {code: wrappedCode, map: metadata.map};
|
edge.path,
|
||||||
|
wrappedCode,
|
||||||
|
edge.output.map,
|
||||||
|
)
|
||||||
|
: {code: wrappedCode, map: edge.output.map};
|
||||||
|
|
||||||
const id = this._getModuleId(module.path);
|
const id = this._getModuleId(edge.path);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
id,
|
id,
|
||||||
|
@ -473,9 +501,9 @@ class DeltaTransformer extends EventEmitter {
|
||||||
id,
|
id,
|
||||||
map,
|
map,
|
||||||
name,
|
name,
|
||||||
source: metadata.source,
|
source: edge.output.source,
|
||||||
path: module.path,
|
path: edge.path,
|
||||||
type: this._getModuleType(module),
|
type: edge.output.type,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -509,32 +537,6 @@ class DeltaTransformer extends EventEmitter {
|
||||||
return addParamsToDefineCall(code, ...params);
|
return addParamsToDefineCall(code, ...params);
|
||||||
}
|
}
|
||||||
|
|
||||||
_getModuleType(module: Module): DeltaEntryType {
|
|
||||||
if (module.isAsset()) {
|
|
||||||
return 'asset';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (module.isPolyfill()) {
|
|
||||||
return 'script';
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'module';
|
|
||||||
}
|
|
||||||
|
|
||||||
async _getMetadata(
|
|
||||||
module: Module,
|
|
||||||
transformOptions: JSTransformerOptions,
|
|
||||||
): Promise<{
|
|
||||||
+code: string,
|
|
||||||
+dependencies: Array<string>,
|
|
||||||
+map: Array<MetroSourceMapSegmentTuple>,
|
|
||||||
+source: string,
|
|
||||||
}> {
|
|
||||||
return await module.read(
|
|
||||||
removeInlineRequiresBlacklistFromOptions(module.path, transformOptions),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_onFileChange = () => {
|
_onFileChange = () => {
|
||||||
this.emit('change');
|
this.emit('change');
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,6 +30,11 @@ describe('DeltaCalculator', () => {
|
||||||
const moduleBar = createModule({path: '/bar', name: 'bar'});
|
const moduleBar = createModule({path: '/bar', name: 'bar'});
|
||||||
const moduleBaz = createModule({path: '/baz', name: 'baz'});
|
const moduleBaz = createModule({path: '/baz', name: 'baz'});
|
||||||
|
|
||||||
|
let edgeModule;
|
||||||
|
let edgeFoo;
|
||||||
|
let edgeBar;
|
||||||
|
let edgeBaz;
|
||||||
|
|
||||||
let deltaCalculator;
|
let deltaCalculator;
|
||||||
let fileWatcher;
|
let fileWatcher;
|
||||||
let mockedDependencies;
|
let mockedDependencies;
|
||||||
|
@ -85,13 +90,23 @@ describe('DeltaCalculator', () => {
|
||||||
|
|
||||||
initialTraverseDependencies.mockImplementationOnce(
|
initialTraverseDependencies.mockImplementationOnce(
|
||||||
async (path, dg, opt, edges) => {
|
async (path, dg, opt, edges) => {
|
||||||
edges.set('/bundle', entryModule);
|
edgeModule = {...entryModule};
|
||||||
edges.set('/foo', {...moduleFoo, inverseDependencies: ['/bundle']});
|
edgeFoo = {...moduleFoo, inverseDependencies: ['/bundle']};
|
||||||
edges.set('/bar', {...moduleBar, inverseDependencies: ['/bundle']});
|
edgeBar = {...moduleBar, inverseDependencies: ['/bundle']};
|
||||||
edges.set('/baz', {...moduleBaz, inverseDependencies: ['/bundle']});
|
edgeBaz = {...moduleBaz, inverseDependencies: ['/bundle']};
|
||||||
|
|
||||||
|
edges.set('/bundle', edgeModule);
|
||||||
|
edges.set('/foo', edgeFoo);
|
||||||
|
edges.set('/bar', edgeBar);
|
||||||
|
edges.set('/baz', edgeBaz);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
added: new Set(['/bundle', '/foo', '/bar', '/baz']),
|
added: new Map([
|
||||||
|
['/bundle', edgeModule],
|
||||||
|
['/foo', edgeFoo],
|
||||||
|
['/bar', edgeBar],
|
||||||
|
['/baz', edgeBaz],
|
||||||
|
]),
|
||||||
deleted: new Set(),
|
deleted: new Set(),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -136,9 +151,9 @@ describe('DeltaCalculator', () => {
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
modified: new Map([
|
modified: new Map([
|
||||||
['/bundle', entryModule],
|
['/bundle', entryModule],
|
||||||
['/foo', moduleFoo],
|
['/foo', edgeFoo],
|
||||||
['/bar', moduleBar],
|
['/bar', edgeBar],
|
||||||
['/baz', moduleBaz],
|
['/baz', edgeBaz],
|
||||||
]),
|
]),
|
||||||
deleted: new Set(),
|
deleted: new Set(),
|
||||||
reset: true,
|
reset: true,
|
||||||
|
@ -164,7 +179,7 @@ describe('DeltaCalculator', () => {
|
||||||
|
|
||||||
traverseDependencies.mockReturnValue(
|
traverseDependencies.mockReturnValue(
|
||||||
Promise.resolve({
|
Promise.resolve({
|
||||||
added: new Set(),
|
added: new Map([['/foo', edgeFoo]]),
|
||||||
deleted: new Set(),
|
deleted: new Set(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
@ -172,7 +187,7 @@ describe('DeltaCalculator', () => {
|
||||||
const result = await deltaCalculator.getDelta();
|
const result = await deltaCalculator.getDelta();
|
||||||
|
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
modified: new Map([['/foo', moduleFoo]]),
|
modified: new Map([['/foo', edgeFoo]]),
|
||||||
deleted: new Set(),
|
deleted: new Set(),
|
||||||
reset: false,
|
reset: false,
|
||||||
});
|
});
|
||||||
|
@ -188,7 +203,7 @@ describe('DeltaCalculator', () => {
|
||||||
|
|
||||||
traverseDependencies.mockReturnValue(
|
traverseDependencies.mockReturnValue(
|
||||||
Promise.resolve({
|
Promise.resolve({
|
||||||
added: new Set(),
|
added: new Map([['/foo', edgeFoo]]),
|
||||||
deleted: new Set(['/baz']),
|
deleted: new Set(['/baz']),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
@ -196,7 +211,7 @@ describe('DeltaCalculator', () => {
|
||||||
const result = await deltaCalculator.getDelta();
|
const result = await deltaCalculator.getDelta();
|
||||||
|
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
modified: new Map([['/foo', moduleFoo]]),
|
modified: new Map([['/foo', edgeFoo]]),
|
||||||
deleted: new Set(['/baz']),
|
deleted: new Set(['/baz']),
|
||||||
reset: false,
|
reset: false,
|
||||||
});
|
});
|
||||||
|
@ -211,19 +226,22 @@ describe('DeltaCalculator', () => {
|
||||||
fileWatcher.emit('change', {eventsQueue: [{filePath: '/foo'}]});
|
fileWatcher.emit('change', {eventsQueue: [{filePath: '/foo'}]});
|
||||||
|
|
||||||
const moduleQux = createModule({path: '/qux', name: 'qux'});
|
const moduleQux = createModule({path: '/qux', name: 'qux'});
|
||||||
|
const edgeQux = {...moduleQux, inverseDependencies: []};
|
||||||
|
|
||||||
mockedDependencies.push(moduleQux);
|
mockedDependencies.push(moduleQux);
|
||||||
|
|
||||||
traverseDependencies.mockReturnValue(
|
traverseDependencies.mockImplementation(async (path, dg, opt, edges) => {
|
||||||
Promise.resolve({
|
edges.set('/qux', edgeQux);
|
||||||
added: new Set([moduleQux.path]),
|
|
||||||
|
return {
|
||||||
|
added: new Map([['/foo', edgeFoo], ['/qux', edgeQux]]),
|
||||||
deleted: new Set(['/bar', '/baz']),
|
deleted: new Set(['/bar', '/baz']),
|
||||||
}),
|
};
|
||||||
);
|
});
|
||||||
|
|
||||||
const result = await deltaCalculator.getDelta();
|
const result = await deltaCalculator.getDelta();
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
modified: new Map([['/foo', moduleFoo], ['/qux', moduleQux]]),
|
modified: new Map([['/foo', edgeFoo], ['/qux', edgeQux]]),
|
||||||
deleted: new Set(['/bar', '/baz']),
|
deleted: new Set(['/bar', '/baz']),
|
||||||
reset: false,
|
reset: false,
|
||||||
});
|
});
|
||||||
|
@ -280,17 +298,18 @@ describe('DeltaCalculator', () => {
|
||||||
|
|
||||||
traverseDependencies.mockReturnValue(
|
traverseDependencies.mockReturnValue(
|
||||||
Promise.resolve({
|
Promise.resolve({
|
||||||
added: new Set(),
|
added: new Map([['/bundle', edgeModule]]),
|
||||||
deleted: new Set(['/foo']),
|
deleted: new Set(['/foo']),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(await deltaCalculator.getDelta()).toEqual({
|
expect(await deltaCalculator.getDelta()).toEqual({
|
||||||
modified: new Map([['/bundle', entryModule]]),
|
modified: new Map([['/bundle', edgeModule]]),
|
||||||
deleted: new Set(['/foo']),
|
deleted: new Set(['/foo']),
|
||||||
reset: false,
|
reset: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
expect(traverseDependencies).toHaveBeenCalledTimes(1);
|
||||||
expect(traverseDependencies.mock.calls[0][0]).toEqual(['/bundle']);
|
expect(traverseDependencies.mock.calls[0][0]).toEqual(['/bundle']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -69,11 +69,11 @@ describe('traverseDependencies', function() {
|
||||||
);
|
);
|
||||||
|
|
||||||
const dependencies = recursive
|
const dependencies = recursive
|
||||||
? added
|
? [...added.values()].map(edge => edge.path)
|
||||||
: edges.get(entryPath).dependencies.values();
|
: edges.get(entryPath).dependencies.values();
|
||||||
|
|
||||||
return await Promise.all(
|
return await Promise.all(
|
||||||
[entryPath, ...dependencies].map(async path => {
|
[...dependencies].map(async path => {
|
||||||
const dep = dgraph.getModuleForPath(path);
|
const dep = dgraph.getModuleForPath(path);
|
||||||
const moduleDependencies = await dep.getDependencies();
|
const moduleDependencies = await dep.getDependencies();
|
||||||
|
|
||||||
|
@ -224,13 +224,6 @@ describe('traverseDependencies', function() {
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
expect(deps).toEqual([
|
expect(deps).toEqual([
|
||||||
{
|
|
||||||
id: 'index',
|
|
||||||
path: '/root/index.js',
|
|
||||||
dependencies: ['a'],
|
|
||||||
isAsset: false,
|
|
||||||
isPolyfill: false,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: 'a',
|
id: 'a',
|
||||||
path: '/root/a.js',
|
path: '/root/a.js',
|
||||||
|
|
|
@ -31,16 +31,36 @@ function deferred(value) {
|
||||||
return {promise, resolve: () => resolve(value)};
|
return {promise, resolve: () => resolve(value)};
|
||||||
}
|
}
|
||||||
|
|
||||||
function createModule({path, name, isAsset}) {
|
function createModule({path, name, isAsset, isPolyfill}) {
|
||||||
return {
|
return {
|
||||||
path,
|
path,
|
||||||
name,
|
name,
|
||||||
async getName() {
|
|
||||||
return name;
|
|
||||||
},
|
|
||||||
isAsset() {
|
isAsset() {
|
||||||
return !!isAsset;
|
return !!isAsset;
|
||||||
},
|
},
|
||||||
|
isPolyfill() {
|
||||||
|
return !!isPolyfill;
|
||||||
|
},
|
||||||
|
async read() {
|
||||||
|
const deps = mockedDependencyTree.get(path);
|
||||||
|
const dependencies = deps ? deps.map(dep => dep.name) : [];
|
||||||
|
|
||||||
|
return {
|
||||||
|
code: '// code',
|
||||||
|
map: [],
|
||||||
|
source: '// source',
|
||||||
|
dependencies,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPaths({added, deleted}) {
|
||||||
|
const addedPaths = [...added.values()].map(edge => edge.path);
|
||||||
|
|
||||||
|
return {
|
||||||
|
added: new Set(addedPaths),
|
||||||
|
deleted,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,10 +78,6 @@ beforeEach(async () => {
|
||||||
getModuleForPath(path) {
|
getModuleForPath(path) {
|
||||||
return Array.from(mockedDependencies).find(dep => dep.path === path);
|
return Array.from(mockedDependencies).find(dep => dep.path === path);
|
||||||
},
|
},
|
||||||
async getShallowDependencies(path) {
|
|
||||||
const deps = mockedDependencyTree.get(path);
|
|
||||||
return deps ? await Promise.all(deps.map(dep => dep.getName())) : [];
|
|
||||||
},
|
|
||||||
resolveDependency(module, relativePath) {
|
resolveDependency(module, relativePath) {
|
||||||
const deps = mockedDependencyTree.get(module.path);
|
const deps = mockedDependencyTree.get(module.path);
|
||||||
const dependency = deps.filter(dep => dep.name === relativePath)[0];
|
const dependency = deps.filter(dep => dep.name === relativePath)[0];
|
||||||
|
@ -83,8 +99,8 @@ it('should do the initial traversal correctly', async () => {
|
||||||
edges,
|
edges,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result).toEqual({
|
expect(getPaths(result)).toEqual({
|
||||||
added: new Set(['/foo', '/bar', '/baz']),
|
added: new Set(['/bundle', '/foo', '/bar', '/baz']),
|
||||||
deleted: new Set(),
|
deleted: new Set(),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -94,9 +110,11 @@ it('should return an empty result when there are no changes', async () => {
|
||||||
await initialTraverseDependencies('/bundle', dependencyGraph, {}, edges);
|
await initialTraverseDependencies('/bundle', dependencyGraph, {}, edges);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await traverseDependencies(['/bundle'], dependencyGraph, {}, edges),
|
getPaths(
|
||||||
|
await traverseDependencies(['/bundle'], dependencyGraph, {}, edges),
|
||||||
|
),
|
||||||
).toEqual({
|
).toEqual({
|
||||||
added: new Set(),
|
added: new Set(['/bundle']),
|
||||||
deleted: new Set(),
|
deleted: new Set(),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -109,9 +127,9 @@ it('should return a removed dependency', async () => {
|
||||||
mockedDependencyTree.set(moduleFoo.path, [moduleBaz]);
|
mockedDependencyTree.set(moduleFoo.path, [moduleBaz]);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await traverseDependencies(['/foo'], dependencyGraph, {}, edges),
|
getPaths(await traverseDependencies(['/foo'], dependencyGraph, {}, edges)),
|
||||||
).toEqual({
|
).toEqual({
|
||||||
added: new Set(),
|
added: new Set(['/foo']),
|
||||||
deleted: new Set(['/bar']),
|
deleted: new Set(['/bar']),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -126,9 +144,9 @@ it('should return added/removed dependencies', async () => {
|
||||||
mockedDependencies.add(moduleQux);
|
mockedDependencies.add(moduleQux);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await traverseDependencies(['/foo'], dependencyGraph, {}, edges),
|
getPaths(await traverseDependencies(['/foo'], dependencyGraph, {}, edges)),
|
||||||
).toEqual({
|
).toEqual({
|
||||||
added: new Set(['/qux']),
|
added: new Set(['/foo', '/qux']),
|
||||||
deleted: new Set(['/bar', '/baz']),
|
deleted: new Set(['/bar', '/baz']),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -159,19 +177,20 @@ describe('edge cases', () => {
|
||||||
const moduleQux = createModule({path: '/qux', name: 'qux'});
|
const moduleQux = createModule({path: '/qux', name: 'qux'});
|
||||||
mockedDependencyTree.set(moduleFoo.path, [moduleQux, moduleBar]);
|
mockedDependencyTree.set(moduleFoo.path, [moduleQux, moduleBar]);
|
||||||
mockedDependencies.add(moduleQux);
|
mockedDependencies.add(moduleQux);
|
||||||
mockedDependencies.delete(moduleBaz);
|
|
||||||
|
|
||||||
// Call traverseDependencies with /foo, /qux and /baz, simulating that the
|
// Call traverseDependencies with /foo, /qux and /baz, simulating that the
|
||||||
// user has modified the 3 files.
|
// user has modified the 3 files.
|
||||||
expect(
|
expect(
|
||||||
await traverseDependencies(
|
getPaths(
|
||||||
['/foo', '/qux', '/baz'],
|
await traverseDependencies(
|
||||||
dependencyGraph,
|
['/foo', '/qux', '/baz'],
|
||||||
{},
|
dependencyGraph,
|
||||||
edges,
|
{},
|
||||||
|
edges,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
).toEqual({
|
).toEqual({
|
||||||
added: new Set(['/qux']),
|
added: new Set(['/foo', '/qux']),
|
||||||
deleted: new Set(['/baz']),
|
deleted: new Set(['/baz']),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -193,9 +212,11 @@ describe('edge cases', () => {
|
||||||
// Call traverseDependencies with /foo, /qux and /baz, simulating that the
|
// Call traverseDependencies with /foo, /qux and /baz, simulating that the
|
||||||
// user has modified the 3 files.
|
// user has modified the 3 files.
|
||||||
expect(
|
expect(
|
||||||
await traverseDependencies(['/bundle'], dependencyGraph, {}, edges),
|
getPaths(
|
||||||
|
await traverseDependencies(['/bundle'], dependencyGraph, {}, edges),
|
||||||
|
),
|
||||||
).toEqual({
|
).toEqual({
|
||||||
added: new Set(['/foo-renamed']),
|
added: new Set(['/bundle', '/foo-renamed']),
|
||||||
deleted: new Set(['/foo']),
|
deleted: new Set(['/foo']),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -205,13 +226,19 @@ describe('edge cases', () => {
|
||||||
await initialTraverseDependencies('/bundle', dependencyGraph, {}, edges);
|
await initialTraverseDependencies('/bundle', dependencyGraph, {}, edges);
|
||||||
|
|
||||||
mockedDependencyTree.set(moduleFoo.path, [moduleBar]);
|
mockedDependencyTree.set(moduleFoo.path, [moduleBar]);
|
||||||
mockedDependencies.delete(moduleBaz);
|
|
||||||
|
|
||||||
// Modify /baz, rename it to /qux and modify it again.
|
// Modify /baz, rename it to /qux and modify it again.
|
||||||
expect(
|
expect(
|
||||||
await traverseDependencies(['/baz', '/foo'], dependencyGraph, {}, edges),
|
getPaths(
|
||||||
|
await traverseDependencies(
|
||||||
|
['/baz', '/foo'],
|
||||||
|
dependencyGraph,
|
||||||
|
{},
|
||||||
|
edges,
|
||||||
|
),
|
||||||
|
),
|
||||||
).toEqual({
|
).toEqual({
|
||||||
added: new Set(),
|
added: new Set(['/foo']),
|
||||||
deleted: new Set(['/baz']),
|
deleted: new Set(['/baz']),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -227,9 +254,11 @@ describe('edge cases', () => {
|
||||||
|
|
||||||
// Modify /baz, rename it to /qux and modify it again.
|
// Modify /baz, rename it to /qux and modify it again.
|
||||||
expect(
|
expect(
|
||||||
await traverseDependencies(['/foo'], dependencyGraph, {}, edges),
|
getPaths(
|
||||||
|
await traverseDependencies(['/foo'], dependencyGraph, {}, edges),
|
||||||
|
),
|
||||||
).toEqual({
|
).toEqual({
|
||||||
added: new Set(['/baz-moved']),
|
added: new Set(['/foo', '/baz-moved']),
|
||||||
deleted: new Set(['/baz']),
|
deleted: new Set(['/baz']),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -273,14 +302,16 @@ describe('edge cases', () => {
|
||||||
async function assertOrder() {
|
async function assertOrder() {
|
||||||
expect(
|
expect(
|
||||||
Array.from(
|
Array.from(
|
||||||
(await initialTraverseDependencies(
|
getPaths(
|
||||||
'/bundle',
|
await initialTraverseDependencies(
|
||||||
dependencyGraph,
|
'/bundle',
|
||||||
{},
|
dependencyGraph,
|
||||||
new Map(),
|
{},
|
||||||
)).added,
|
new Map(),
|
||||||
|
),
|
||||||
|
).added,
|
||||||
),
|
),
|
||||||
).toEqual(['/foo', '/baz', '/bar']);
|
).toEqual(['/bundle', '/foo', '/baz', '/bar']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a dependency tree where moduleBaz has two inverse dependencies.
|
// Create a dependency tree where moduleBaz has two inverse dependencies.
|
||||||
|
@ -300,7 +331,10 @@ describe('edge cases', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should simplify inlineRequires transform option', async () => {
|
it('should simplify inlineRequires transform option', async () => {
|
||||||
jest.spyOn(dependencyGraph, 'getShallowDependencies');
|
jest.spyOn(entryModule, 'read');
|
||||||
|
jest.spyOn(moduleFoo, 'read');
|
||||||
|
jest.spyOn(moduleBar, 'read');
|
||||||
|
jest.spyOn(moduleBaz, 'read');
|
||||||
|
|
||||||
const edges = new Map();
|
const edges = new Map();
|
||||||
const transformOptions = {
|
const transformOptions = {
|
||||||
|
@ -318,14 +352,12 @@ describe('edge cases', () => {
|
||||||
edges,
|
edges,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(dependencyGraph.getShallowDependencies.mock.calls).toEqual([
|
expect(entryModule.read).toHaveBeenCalledWith({inlineRequires: true});
|
||||||
['/bundle', {inlineRequires: true}],
|
expect(moduleFoo.read).toHaveBeenCalledWith({inlineRequires: true});
|
||||||
['/foo', {inlineRequires: true}],
|
expect(moduleBar.read).toHaveBeenCalledWith({inlineRequires: true});
|
||||||
['/bar', {inlineRequires: true}],
|
expect(moduleBaz.read).toHaveBeenCalledWith({inlineRequires: false});
|
||||||
['/baz', {inlineRequires: false}],
|
|
||||||
]);
|
|
||||||
|
|
||||||
dependencyGraph.getShallowDependencies.mockClear();
|
moduleFoo.read.mockClear();
|
||||||
|
|
||||||
await traverseDependencies(
|
await traverseDependencies(
|
||||||
['/foo'],
|
['/foo'],
|
||||||
|
@ -334,8 +366,6 @@ describe('edge cases', () => {
|
||||||
edges,
|
edges,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(dependencyGraph.getShallowDependencies.mock.calls).toEqual([
|
expect(moduleFoo.read).toHaveBeenCalledWith({inlineRequires: true});
|
||||||
['/foo', {inlineRequires: true}],
|
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,16 +14,26 @@ const removeInlineRequiresBlacklistFromOptions = require('../lib/removeInlineReq
|
||||||
|
|
||||||
import type {Options as JSTransformerOptions} from '../JSTransformer/worker';
|
import type {Options as JSTransformerOptions} from '../JSTransformer/worker';
|
||||||
import type DependencyGraph from '../node-haste/DependencyGraph';
|
import type DependencyGraph from '../node-haste/DependencyGraph';
|
||||||
|
import type Module from '../node-haste/Module';
|
||||||
|
import type {MetroSourceMapSegmentTuple} from 'metro-source-map';
|
||||||
|
|
||||||
|
export type DependencyType = 'module' | 'script' | 'asset';
|
||||||
|
|
||||||
export type DependencyEdge = {|
|
export type DependencyEdge = {|
|
||||||
dependencies: Map<string, string>,
|
dependencies: Map<string, string>,
|
||||||
inverseDependencies: Set<string>,
|
inverseDependencies: Set<string>,
|
||||||
path: string,
|
path: string,
|
||||||
|
output: {
|
||||||
|
code: string,
|
||||||
|
map: Array<MetroSourceMapSegmentTuple>,
|
||||||
|
source: string,
|
||||||
|
type: DependencyType,
|
||||||
|
},
|
||||||
|};
|
|};
|
||||||
|
|
||||||
export type DependencyEdges = Map<string, DependencyEdge>;
|
export type DependencyEdges = Map<string, DependencyEdge>;
|
||||||
|
|
||||||
type Result = {added: Set<string>, deleted: Set<string>};
|
type Result = {added: Map<string, DependencyEdge>, deleted: Set<string>};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dependency Traversal logic for the Delta Bundler. This method calculates
|
* Dependency Traversal logic for the Delta Bundler. This method calculates
|
||||||
|
@ -58,12 +68,12 @@ async function traverseDependencies(
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
const added = new Set();
|
const added = new Map();
|
||||||
const deleted = new Set();
|
const deleted = new Set();
|
||||||
|
|
||||||
for (const change of changes) {
|
for (const change of changes) {
|
||||||
for (const path of change.added) {
|
for (const [path, edge] of change.added) {
|
||||||
added.add(path);
|
added.set(path, edge);
|
||||||
}
|
}
|
||||||
for (const path of change.deleted) {
|
for (const path of change.deleted) {
|
||||||
// If a path has been marked both as added and deleted, it means that this
|
// If a path has been marked both as added and deleted, it means that this
|
||||||
|
@ -90,8 +100,8 @@ async function initialTraverseDependencies(
|
||||||
transformOptions: JSTransformerOptions,
|
transformOptions: JSTransformerOptions,
|
||||||
edges: DependencyEdges,
|
edges: DependencyEdges,
|
||||||
onProgress?: (numProcessed: number, total: number) => mixed = () => {},
|
onProgress?: (numProcessed: number, total: number) => mixed = () => {},
|
||||||
) {
|
): Promise<Result> {
|
||||||
createEdge(path, edges);
|
createEdge(dependencyGraph.getModuleForPath(path), edges);
|
||||||
|
|
||||||
return await traverseDependenciesForSingleFile(
|
return await traverseDependenciesForSingleFile(
|
||||||
path,
|
path,
|
||||||
|
@ -113,13 +123,18 @@ async function traverseDependenciesForSingleFile(
|
||||||
|
|
||||||
// If the passed edge does not exist does not exist in the graph, ignore it.
|
// If the passed edge does not exist does not exist in the graph, ignore it.
|
||||||
if (!edge) {
|
if (!edge) {
|
||||||
return {added: new Set(), deleted: new Set()};
|
return {added: new Map(), deleted: new Set()};
|
||||||
}
|
}
|
||||||
|
|
||||||
const shallow = await dependencyGraph.getShallowDependencies(
|
const result = await dependencyGraph
|
||||||
path,
|
.getModuleForPath(path)
|
||||||
removeInlineRequiresBlacklistFromOptions(path, transformOptions),
|
.read(removeInlineRequiresBlacklistFromOptions(path, transformOptions));
|
||||||
);
|
|
||||||
|
edge.output.code = result.code;
|
||||||
|
edge.output.map = result.map;
|
||||||
|
edge.output.source = result.source;
|
||||||
|
|
||||||
|
const shallow = result.dependencies;
|
||||||
|
|
||||||
// Get the absolute path of all sub-dependencies (some of them could have been
|
// Get the absolute path of all sub-dependencies (some of them could have been
|
||||||
// moved but maintain the same relative path).
|
// moved but maintain the same relative path).
|
||||||
|
@ -132,8 +147,6 @@ async function traverseDependenciesForSingleFile(
|
||||||
|
|
||||||
const previousDependencies = new Set(edge.dependencies.values());
|
const previousDependencies = new Set(edge.dependencies.values());
|
||||||
|
|
||||||
const nonNullEdge = edge;
|
|
||||||
|
|
||||||
let numProcessed = 0;
|
let numProcessed = 0;
|
||||||
let total = 1;
|
let total = 1;
|
||||||
onProgress(numProcessed, total);
|
onProgress(numProcessed, total);
|
||||||
|
@ -141,7 +154,7 @@ async function traverseDependenciesForSingleFile(
|
||||||
const deleted = Array.from(edge.dependencies.entries())
|
const deleted = Array.from(edge.dependencies.entries())
|
||||||
.map(([relativePath, absolutePath]) => {
|
.map(([relativePath, absolutePath]) => {
|
||||||
if (!currentDependencies.has(absolutePath)) {
|
if (!currentDependencies.has(absolutePath)) {
|
||||||
return removeDependency(nonNullEdge, relativePath, edges);
|
return removeDependency(edge, relativePath, edges);
|
||||||
} else {
|
} else {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
@ -151,15 +164,15 @@ async function traverseDependenciesForSingleFile(
|
||||||
// Check all the module dependencies and start traversing the tree from each
|
// Check all the module dependencies and start traversing the tree from each
|
||||||
// added and removed dependency, to get all the modules that have to be added
|
// added and removed dependency, to get all the modules that have to be added
|
||||||
// and removed from the dependency graph.
|
// and removed from the dependency graph.
|
||||||
const added = await Promise.all(
|
const addedDependencies = await Promise.all(
|
||||||
Array.from(currentDependencies).map(
|
Array.from(currentDependencies).map(
|
||||||
async ([absolutePath, relativePath]) => {
|
async ([absolutePath, relativePath]) => {
|
||||||
if (previousDependencies.has(absolutePath)) {
|
if (previousDependencies.has(absolutePath)) {
|
||||||
return new Set();
|
return new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
return await addDependency(
|
return await addDependency(
|
||||||
nonNullEdge,
|
edge,
|
||||||
relativePath,
|
relativePath,
|
||||||
dependencyGraph,
|
dependencyGraph,
|
||||||
transformOptions,
|
transformOptions,
|
||||||
|
@ -177,11 +190,13 @@ async function traverseDependenciesForSingleFile(
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const added = [new Map([[edge.path, edge]])].concat(addedDependencies);
|
||||||
|
|
||||||
numProcessed++;
|
numProcessed++;
|
||||||
onProgress(numProcessed, total);
|
onProgress(numProcessed, total);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
added: flatten(reorderDependencies(added, edges)),
|
added: flattenMap(reorderDependencies(added, edges)),
|
||||||
deleted: flatten(deleted),
|
deleted: flatten(deleted),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -194,7 +209,7 @@ async function addDependency(
|
||||||
edges: DependencyEdges,
|
edges: DependencyEdges,
|
||||||
onDependencyAdd: () => mixed,
|
onDependencyAdd: () => mixed,
|
||||||
onDependencyAdded: () => mixed,
|
onDependencyAdded: () => mixed,
|
||||||
): Promise<Set<string>> {
|
): Promise<Map<string, DependencyEdge>> {
|
||||||
const parentModule = dependencyGraph.getModuleForPath(parentEdge.path);
|
const parentModule = dependencyGraph.getModuleForPath(parentEdge.path);
|
||||||
const module = dependencyGraph.resolveDependency(
|
const module = dependencyGraph.resolveDependency(
|
||||||
parentModule,
|
parentModule,
|
||||||
|
@ -205,35 +220,36 @@ async function addDependency(
|
||||||
// Update the parent edge to keep track of the new dependency.
|
// Update the parent edge to keep track of the new dependency.
|
||||||
parentEdge.dependencies.set(relativePath, module.path);
|
parentEdge.dependencies.set(relativePath, module.path);
|
||||||
|
|
||||||
let dependencyEdge = edges.get(module.path);
|
const existingEdge = edges.get(module.path);
|
||||||
|
|
||||||
// The new dependency was already in the graph, we don't need to do anything.
|
// The new dependency was already in the graph, we don't need to do anything.
|
||||||
if (dependencyEdge) {
|
if (existingEdge) {
|
||||||
dependencyEdge.inverseDependencies.add(parentEdge.path);
|
existingEdge.inverseDependencies.add(parentEdge.path);
|
||||||
|
|
||||||
return new Set();
|
return new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
onDependencyAdd();
|
onDependencyAdd();
|
||||||
|
|
||||||
// Create the new edge and traverse all its subdependencies, looking for new
|
// Create the new edge and traverse all its subdependencies, looking for new
|
||||||
// subdependencies recursively.
|
// subdependencies recursively.
|
||||||
dependencyEdge = createEdge(module.path, edges);
|
const edge = createEdge(module, edges);
|
||||||
dependencyEdge.inverseDependencies.add(parentEdge.path);
|
edge.inverseDependencies.add(parentEdge.path);
|
||||||
|
|
||||||
const addedDependencies = new Set([dependencyEdge.path]);
|
const addedDependencies = new Map([[edge.path, edge]]);
|
||||||
|
|
||||||
const shallowDeps = await dependencyGraph.getShallowDependencies(
|
const result = await module.read(
|
||||||
dependencyEdge.path,
|
removeInlineRequiresBlacklistFromOptions(edge.path, transformOptions),
|
||||||
removeInlineRequiresBlacklistFromOptions(module.path, transformOptions),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const nonNullDependencyEdge = dependencyEdge;
|
edge.output.code = result.code;
|
||||||
|
edge.output.map = result.map;
|
||||||
|
edge.output.source = result.source;
|
||||||
|
|
||||||
const added = await Promise.all(
|
const added = await Promise.all(
|
||||||
shallowDeps.map(dep =>
|
result.dependencies.map(dep =>
|
||||||
addDependency(
|
addDependency(
|
||||||
nonNullDependencyEdge,
|
edge,
|
||||||
dep,
|
dep,
|
||||||
dependencyGraph,
|
dependencyGraph,
|
||||||
transformOptions,
|
transformOptions,
|
||||||
|
@ -244,8 +260,8 @@ async function addDependency(
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const newDependency of flatten(added)) {
|
for (const [newDepPath, newDepEdge] of flattenMap(added)) {
|
||||||
addedDependencies.add(newDependency);
|
addedDependencies.set(newDepPath, newDepEdge);
|
||||||
}
|
}
|
||||||
|
|
||||||
onDependencyAdded();
|
onDependencyAdded();
|
||||||
|
@ -294,17 +310,35 @@ function removeDependency(
|
||||||
return removedDependencies;
|
return removedDependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createEdge(path: string, edges: DependencyEdges): DependencyEdge {
|
function createEdge(module: Module, edges: DependencyEdges): DependencyEdge {
|
||||||
const edge = {
|
const edge = {
|
||||||
dependencies: new Map(),
|
dependencies: new Map(),
|
||||||
inverseDependencies: new Set(),
|
inverseDependencies: new Set(),
|
||||||
path,
|
path: module.path,
|
||||||
|
output: {
|
||||||
|
code: '',
|
||||||
|
map: [],
|
||||||
|
source: '',
|
||||||
|
type: getType(module),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
edges.set(path, edge);
|
edges.set(module.path, edge);
|
||||||
|
|
||||||
return edge;
|
return edge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getType(module: Module): DependencyType {
|
||||||
|
if (module.isAsset()) {
|
||||||
|
return 'asset';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (module.isPolyfill()) {
|
||||||
|
return 'script';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'module';
|
||||||
|
}
|
||||||
|
|
||||||
function destroyEdge(edge: DependencyEdge, edges: DependencyEdges) {
|
function destroyEdge(edge: DependencyEdge, edges: DependencyEdges) {
|
||||||
edges.delete(edge.path);
|
edges.delete(edge.path);
|
||||||
}
|
}
|
||||||
|
@ -347,29 +381,36 @@ function resolveDependencies(
|
||||||
* guarantee the same order between runs.
|
* guarantee the same order between runs.
|
||||||
*/
|
*/
|
||||||
function reorderDependencies(
|
function reorderDependencies(
|
||||||
dependencies: Array<Set<string>>,
|
dependencies: Array<Map<string, DependencyEdge>>,
|
||||||
edges: DependencyEdges,
|
edges: DependencyEdges,
|
||||||
): Array<Set<string>> {
|
): Array<Map<string, DependencyEdge>> {
|
||||||
const flatDependencies = flatten(dependencies);
|
const flatDependencies = flattenMap(dependencies);
|
||||||
|
|
||||||
return dependencies.map(dependencies =>
|
return dependencies.map(dependencies => {
|
||||||
reorderDependency(Array.from(dependencies)[0], flatDependencies, edges),
|
if (dependencies.size === 0) {
|
||||||
);
|
return new Map();
|
||||||
|
}
|
||||||
|
return reorderDependency(
|
||||||
|
Array.from(dependencies)[0][0],
|
||||||
|
flatDependencies,
|
||||||
|
edges,
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function reorderDependency(
|
function reorderDependency(
|
||||||
path: string,
|
path: string,
|
||||||
dependencies: Set<string>,
|
dependencies: Map<string, DependencyEdge>,
|
||||||
edges: DependencyEdges,
|
edges: DependencyEdges,
|
||||||
orderedDependencies?: Set<string> = new Set(),
|
orderedDependencies?: Map<string, DependencyEdge> = new Map(),
|
||||||
): Set<string> {
|
): Map<string, DependencyEdge> {
|
||||||
const edge = edges.get(path);
|
const edge = edges.get(path);
|
||||||
|
|
||||||
if (!edge || !dependencies.has(path) || orderedDependencies.has(path)) {
|
if (!edge || !dependencies.has(path) || orderedDependencies.has(path)) {
|
||||||
return orderedDependencies;
|
return orderedDependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
orderedDependencies.add(path);
|
orderedDependencies.set(path, edge);
|
||||||
|
|
||||||
edge.dependencies.forEach(path =>
|
edge.dependencies.forEach(path =>
|
||||||
reorderDependency(path, dependencies, edges, orderedDependencies),
|
reorderDependency(path, dependencies, edges, orderedDependencies),
|
||||||
|
@ -390,6 +431,18 @@ function flatten<T>(input: Iterable<Iterable<T>>): Set<T> {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function flattenMap<K, V>(input: Iterable<Map<K, V>>): Map<K, V> {
|
||||||
|
const output = new Map();
|
||||||
|
|
||||||
|
for (const items of input) {
|
||||||
|
for (const [key, value] of items.entries()) {
|
||||||
|
output.set(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
initialTraverseDependencies,
|
initialTraverseDependencies,
|
||||||
traverseDependencies,
|
traverseDependencies,
|
||||||
|
|
|
@ -22,6 +22,7 @@ const fs = require('fs');
|
||||||
const isAbsolutePath = require('absolute-path');
|
const isAbsolutePath = require('absolute-path');
|
||||||
const parsePlatformFilePath = require('./lib/parsePlatformFilePath');
|
const parsePlatformFilePath = require('./lib/parsePlatformFilePath');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const toLocalPath = require('../node-haste/lib/toLocalPath');
|
||||||
const util = require('util');
|
const util = require('util');
|
||||||
|
|
||||||
const {ModuleResolver} = require('./DependencyGraph/ModuleResolution');
|
const {ModuleResolver} = require('./DependencyGraph/ModuleResolution');
|
||||||
|
@ -274,6 +275,16 @@ class DependencyGraph extends EventEmitter {
|
||||||
return platform;
|
return platform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getHasteName(filePath: string): string {
|
||||||
|
const hasteName = this._hasteFS.getModuleName(filePath);
|
||||||
|
|
||||||
|
if (hasteName) {
|
||||||
|
return hasteName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return toLocalPath(this._opts.projectRoots, filePath);
|
||||||
|
}
|
||||||
|
|
||||||
getAbsolutePath(filePath: string) {
|
getAbsolutePath(filePath: string) {
|
||||||
if (isAbsolutePath(filePath)) {
|
if (isAbsolutePath(filePath)) {
|
||||||
return path.resolve(filePath);
|
return path.resolve(filePath);
|
||||||
|
|
|
@ -14,5 +14,6 @@
|
||||||
export type HasteFS = {
|
export type HasteFS = {
|
||||||
exists(filePath: string): boolean,
|
exists(filePath: string): boolean,
|
||||||
getAllFiles(): Array<string>,
|
getAllFiles(): Array<string>,
|
||||||
|
getModuleName(filePath: string): ?string,
|
||||||
matchFiles(pattern: RegExp | string): Array<string>,
|
matchFiles(pattern: RegExp | string): Array<string>,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue