mirror of
https://github.com/status-im/metro.git
synced 2025-01-21 16:39:43 +00:00
Expose Graph object from the delta bundler
Reviewed By: davidaurelio Differential Revision: D7158629 fbshipit-source-id: bb10ad8449cc8f1566f02568adaaecbc54c76d2e
This commit is contained in:
parent
21ccd2b269
commit
935b6b5e32
@ -21,6 +21,7 @@ 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 {BundleOptions} from '../shared/types.flow';
|
import type {BundleOptions} from '../shared/types.flow';
|
||||||
|
import type {DependencyEdge, DependencyEdges} from './traverseDependencies';
|
||||||
|
|
||||||
export type DeltaResult = {|
|
export type DeltaResult = {|
|
||||||
+modified: Map<string, DependencyEdge>,
|
+modified: Map<string, DependencyEdge>,
|
||||||
@ -28,7 +29,10 @@ export type DeltaResult = {|
|
|||||||
+reset: boolean,
|
+reset: boolean,
|
||||||
|};
|
|};
|
||||||
|
|
||||||
import type {DependencyEdge, DependencyEdges} from './traverseDependencies';
|
export type Graph = {|
|
||||||
|
dependencies: DependencyEdges,
|
||||||
|
entryFile: string,
|
||||||
|
|};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
@ -46,7 +50,7 @@ class DeltaCalculator extends EventEmitter {
|
|||||||
_deletedFiles: Set<string> = new Set();
|
_deletedFiles: Set<string> = new Set();
|
||||||
_modifiedFiles: Set<string> = new Set();
|
_modifiedFiles: Set<string> = new Set();
|
||||||
|
|
||||||
_dependencyEdges: DependencyEdges = new Map();
|
_graph: Graph;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
bundler: Bundler,
|
bundler: Bundler,
|
||||||
@ -59,6 +63,15 @@ class DeltaCalculator extends EventEmitter {
|
|||||||
this._options = options;
|
this._options = options;
|
||||||
this._dependencyGraph = dependencyGraph;
|
this._dependencyGraph = dependencyGraph;
|
||||||
|
|
||||||
|
const entryFilePath = this._dependencyGraph.getAbsolutePath(
|
||||||
|
this._options.entryFile,
|
||||||
|
);
|
||||||
|
|
||||||
|
this._graph = {
|
||||||
|
dependencies: new Map(),
|
||||||
|
entryFile: entryFilePath,
|
||||||
|
};
|
||||||
|
|
||||||
this._dependencyGraph
|
this._dependencyGraph
|
||||||
.getWatcher()
|
.getWatcher()
|
||||||
.on('change', this._handleMultipleFileChanges);
|
.on('change', this._handleMultipleFileChanges);
|
||||||
@ -72,14 +85,15 @@ class DeltaCalculator extends EventEmitter {
|
|||||||
.getWatcher()
|
.getWatcher()
|
||||||
.removeListener('change', this._handleMultipleFileChanges);
|
.removeListener('change', this._handleMultipleFileChanges);
|
||||||
|
|
||||||
this.reset();
|
this.removeAllListeners();
|
||||||
}
|
|
||||||
|
|
||||||
reset() {
|
|
||||||
// Clean up all the cache data structures to deallocate memory.
|
// Clean up all the cache data structures to deallocate memory.
|
||||||
|
this._graph = {
|
||||||
|
dependencies: new Map(),
|
||||||
|
entryFile: this._options.entryFile,
|
||||||
|
};
|
||||||
this._modifiedFiles = new Set();
|
this._modifiedFiles = new Set();
|
||||||
this._deletedFiles = new Set();
|
this._deletedFiles = new Set();
|
||||||
this._dependencyEdges = new Map();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -111,7 +125,7 @@ class DeltaCalculator extends EventEmitter {
|
|||||||
|
|
||||||
let result;
|
let result;
|
||||||
|
|
||||||
const numDependencies = this._dependencyEdges.size;
|
const numDependencies = this._graph.dependencies.size;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
result = await this._currentBuildPromise;
|
result = await this._currentBuildPromise;
|
||||||
@ -126,8 +140,8 @@ class DeltaCalculator extends EventEmitter {
|
|||||||
// If after an error the number of edges has changed, we could be in
|
// If after an error the number of edges has changed, we could be in
|
||||||
// a weird state. As a safe net we clean the dependency edges to force
|
// a weird state. As a safe net we clean the dependency edges to force
|
||||||
// a clean traversal of the graph next time.
|
// a clean traversal of the graph next time.
|
||||||
if (this._dependencyEdges.size !== numDependencies) {
|
if (this._graph.dependencies.size !== numDependencies) {
|
||||||
this._dependencyEdges = new Map();
|
this._graph.dependencies = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
@ -137,13 +151,13 @@ class DeltaCalculator extends EventEmitter {
|
|||||||
|
|
||||||
// Return all the modules if the client requested a reset delta.
|
// Return all the modules if the client requested a reset delta.
|
||||||
if (reset) {
|
if (reset) {
|
||||||
|
this._graph.dependencies = reorderDependencies(
|
||||||
|
this._graph.dependencies.get(this._graph.entryFile),
|
||||||
|
this._graph.dependencies,
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
modified: reorderDependencies(
|
modified: this._graph.dependencies,
|
||||||
this._dependencyEdges.get(
|
|
||||||
this._dependencyGraph.getAbsolutePath(this._options.entryFile),
|
|
||||||
),
|
|
||||||
this._dependencyEdges,
|
|
||||||
),
|
|
||||||
deleted: new Set(),
|
deleted: new Set(),
|
||||||
reset: true,
|
reset: true,
|
||||||
};
|
};
|
||||||
@ -207,12 +221,12 @@ class DeltaCalculator extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all the dependency edges from the graph. Each edge contains the
|
* Returns the graph with all the dependency edges. Each edge contains the
|
||||||
* needed information to do the traversing (dependencies, inverseDependencies)
|
* needed information to do the traversing (dependencies, inverseDependencies)
|
||||||
* plus some metadata.
|
* plus some metadata.
|
||||||
*/
|
*/
|
||||||
getDependencyEdges(): DependencyEdges {
|
getGraph(): Graph {
|
||||||
return this._dependencyEdges;
|
return this._graph;
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleMultipleFileChanges = ({eventsQueue}) => {
|
_handleMultipleFileChanges = ({eventsQueue}) => {
|
||||||
@ -250,16 +264,12 @@ class DeltaCalculator extends EventEmitter {
|
|||||||
): Promise<DeltaResult> {
|
): Promise<DeltaResult> {
|
||||||
const transformerOptions = await this.getTransformerOptions();
|
const transformerOptions = await this.getTransformerOptions();
|
||||||
|
|
||||||
if (!this._dependencyEdges.size) {
|
if (!this._graph.dependencies.size) {
|
||||||
const path = this._dependencyGraph.getAbsolutePath(
|
|
||||||
this._options.entryFile,
|
|
||||||
);
|
|
||||||
|
|
||||||
const {added} = await initialTraverseDependencies(
|
const {added} = await initialTraverseDependencies(
|
||||||
path,
|
this._graph.entryFile,
|
||||||
this._dependencyGraph,
|
this._dependencyGraph,
|
||||||
transformerOptions,
|
transformerOptions,
|
||||||
this._dependencyEdges,
|
this._graph.dependencies,
|
||||||
this._options.onProgress || undefined,
|
this._options.onProgress || undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -273,7 +283,7 @@ class DeltaCalculator extends EventEmitter {
|
|||||||
// If a file has been deleted, we want to invalidate any other file that
|
// If a file has been deleted, we want to invalidate any other file that
|
||||||
// depends on it, so we can process it and correctly return an error.
|
// depends on it, so we can process it and correctly return an error.
|
||||||
deletedFiles.forEach(filePath => {
|
deletedFiles.forEach(filePath => {
|
||||||
const edge = this._dependencyEdges.get(filePath);
|
const edge = this._graph.dependencies.get(filePath);
|
||||||
|
|
||||||
if (edge) {
|
if (edge) {
|
||||||
edge.inverseDependencies.forEach(path => modifiedFiles.add(path));
|
edge.inverseDependencies.forEach(path => modifiedFiles.add(path));
|
||||||
@ -282,7 +292,7 @@ class DeltaCalculator extends EventEmitter {
|
|||||||
|
|
||||||
// We only want to process files that are in the bundle.
|
// We only want to process files that are in the bundle.
|
||||||
const modifiedDependencies = Array.from(modifiedFiles).filter(filePath =>
|
const modifiedDependencies = Array.from(modifiedFiles).filter(filePath =>
|
||||||
this._dependencyEdges.has(filePath),
|
this._graph.dependencies.has(filePath),
|
||||||
);
|
);
|
||||||
|
|
||||||
// No changes happened. Return empty delta.
|
// No changes happened. Return empty delta.
|
||||||
@ -294,7 +304,7 @@ class DeltaCalculator extends EventEmitter {
|
|||||||
modifiedDependencies,
|
modifiedDependencies,
|
||||||
this._dependencyGraph,
|
this._dependencyGraph,
|
||||||
transformerOptions,
|
transformerOptions,
|
||||||
this._dependencyEdges,
|
this._graph.dependencies,
|
||||||
this._options.onProgress || undefined,
|
this._options.onProgress || undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ class DeltaTransformer extends EventEmitter {
|
|||||||
* transitive dependencies of any given file within the dependency graph.
|
* transitive dependencies of any given file within the dependency graph.
|
||||||
**/
|
**/
|
||||||
async getDependenciesFn(): Promise<(string) => Set<string>> {
|
async getDependenciesFn(): Promise<(string) => Set<string>> {
|
||||||
if (!this._deltaCalculator.getDependencyEdges().size) {
|
if (!this._deltaCalculator.getGraph().dependencies.size) {
|
||||||
// If by any means the dependency graph has not been initialized, call
|
// If by any means the dependency graph has not been initialized, call
|
||||||
// getDelta() to initialize it.
|
// getDelta() to initialize it.
|
||||||
await this._getDelta({reset: false});
|
await this._getDelta({reset: false});
|
||||||
@ -168,16 +168,17 @@ class DeltaTransformer extends EventEmitter {
|
|||||||
* transitive dependencies of any given file within the dependency graph.
|
* transitive dependencies of any given file within the dependency graph.
|
||||||
**/
|
**/
|
||||||
async getInverseDependencies(): Promise<Map<number, $ReadOnlyArray<number>>> {
|
async getInverseDependencies(): Promise<Map<number, $ReadOnlyArray<number>>> {
|
||||||
if (!this._deltaCalculator.getDependencyEdges().size) {
|
const graph = this._deltaCalculator.getGraph();
|
||||||
|
|
||||||
|
if (!graph.dependencies.size) {
|
||||||
// If by any means the dependency graph has not been initialized, call
|
// If by any means the dependency graph has not been initialized, call
|
||||||
// getDelta() to initialize it.
|
// getDelta() to initialize it.
|
||||||
await this._getDelta({reset: false});
|
await this._getDelta({reset: false});
|
||||||
}
|
}
|
||||||
|
|
||||||
const dependencyEdges = this._deltaCalculator.getDependencyEdges();
|
|
||||||
const output = new Map();
|
const output = new Map();
|
||||||
|
|
||||||
for (const [path, {inverseDependencies}] of dependencyEdges.entries()) {
|
for (const [path, {inverseDependencies}] of graph.dependencies.entries()) {
|
||||||
output.set(
|
output.set(
|
||||||
this._getModuleId(path),
|
this._getModuleId(path),
|
||||||
Array.from(inverseDependencies).map(dep => this._getModuleId(dep)),
|
Array.from(inverseDependencies).map(dep => this._getModuleId(dep)),
|
||||||
@ -226,14 +227,14 @@ class DeltaTransformer extends EventEmitter {
|
|||||||
const {modified, deleted, reset} = await this._deltaCalculator.getDelta({
|
const {modified, deleted, reset} = await this._deltaCalculator.getDelta({
|
||||||
reset: resetDelta,
|
reset: resetDelta,
|
||||||
});
|
});
|
||||||
|
const graph = this._deltaCalculator.getGraph();
|
||||||
|
|
||||||
const transformerOptions = await this._deltaCalculator.getTransformerOptions();
|
const transformerOptions = await this._deltaCalculator.getTransformerOptions();
|
||||||
const dependencyEdges = this._deltaCalculator.getDependencyEdges();
|
|
||||||
|
|
||||||
// Return the source code that gets prepended to all the modules. This
|
// Return the source code that gets prepended to all the modules. This
|
||||||
// contains polyfills and startup code (like the require() implementation).
|
// contains polyfills and startup code (like the require() implementation).
|
||||||
const prependSources = reset
|
const prependSources = reset
|
||||||
? await this._getPrepend(transformerOptions, dependencyEdges)
|
? await this._getPrepend(transformerOptions, graph.dependencies)
|
||||||
: new Map();
|
: new Map();
|
||||||
|
|
||||||
// Precalculate all module ids sequentially. We do this to be sure that the
|
// Precalculate all module ids sequentially. We do this to be sure that the
|
||||||
@ -245,7 +246,7 @@ class DeltaTransformer extends EventEmitter {
|
|||||||
const modifiedDelta = await this._transformModules(
|
const modifiedDelta = await this._transformModules(
|
||||||
modules,
|
modules,
|
||||||
transformerOptions,
|
transformerOptions,
|
||||||
dependencyEdges,
|
graph.dependencies,
|
||||||
);
|
);
|
||||||
|
|
||||||
deleted.forEach(id => {
|
deleted.forEach(id => {
|
||||||
@ -255,7 +256,7 @@ class DeltaTransformer extends EventEmitter {
|
|||||||
// Return the source code that gets appended to all the modules. This
|
// Return the source code that gets appended to all the modules. This
|
||||||
// contains the require() calls to startup the execution of the modules.
|
// contains the require() calls to startup the execution of the modules.
|
||||||
const appendSources = reset
|
const appendSources = reset
|
||||||
? await this._getAppend(dependencyEdges)
|
? await this._getAppend(graph.dependencies)
|
||||||
: new Map();
|
: new Map();
|
||||||
|
|
||||||
// generate a random
|
// generate a random
|
||||||
@ -271,11 +272,9 @@ class DeltaTransformer extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_getDependencies = (path: string): Set<string> => {
|
_getDependencies = (path: string): Set<string> => {
|
||||||
const dependencies = this._getDeps(
|
const graph = this._deltaCalculator.getGraph();
|
||||||
path,
|
|
||||||
this._deltaCalculator.getDependencyEdges(),
|
const dependencies = this._getDeps(path, graph.dependencies, new Set());
|
||||||
new Set(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Remove the main entry point, since this method only returns the
|
// Remove the main entry point, since this method only returns the
|
||||||
// dependencies.
|
// dependencies.
|
||||||
|
@ -385,6 +385,17 @@ describe('DeltaCalculator', () => {
|
|||||||
expect(traverseDependencies.mock.calls[0][0]).toEqual(['/foo']);
|
expect(traverseDependencies.mock.calls[0][0]).toEqual(['/foo']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not mutate an existing graph when calling end()', async () => {
|
||||||
|
await deltaCalculator.getDelta({reset: false});
|
||||||
|
const graph = deltaCalculator.getGraph();
|
||||||
|
|
||||||
|
const numDependencies = graph.dependencies.size;
|
||||||
|
|
||||||
|
deltaCalculator.end();
|
||||||
|
|
||||||
|
expect(graph.dependencies.size).toEqual(numDependencies);
|
||||||
|
});
|
||||||
|
|
||||||
describe('getTransformerOptions()', () => {
|
describe('getTransformerOptions()', () => {
|
||||||
it('should calculate the transform options correctly', async () => {
|
it('should calculate the transform options correctly', async () => {
|
||||||
expect(await deltaCalculator.getTransformerOptions()).toEqual({
|
expect(await deltaCalculator.getTransformerOptions()).toEqual({
|
||||||
|
@ -32,6 +32,9 @@ async function getTransformOptions(): Promise<JSTransformerOptions> {
|
|||||||
getWatcher() {
|
getWatcher() {
|
||||||
return {on() {}};
|
return {on() {}};
|
||||||
},
|
},
|
||||||
|
getAbsolutePath(path) {
|
||||||
|
return '/' + path;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
const options = {
|
const options = {
|
||||||
assetPlugins: [],
|
assetPlugins: [],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user