From 935b6b5e3200e4f67e2725dabfa9dbbc472e3b6e Mon Sep 17 00:00:00 2001 From: Rafael Oleza Date: Mon, 19 Mar 2018 10:04:39 -0700 Subject: [PATCH] Expose Graph object from the delta bundler Reviewed By: davidaurelio Differential Revision: D7158629 fbshipit-source-id: bb10ad8449cc8f1566f02568adaaecbc54c76d2e --- .../metro/src/DeltaBundler/DeltaCalculator.js | 66 +++++++++++-------- .../src/DeltaBundler/DeltaTransformer.js | 25 ++++--- .../__tests__/DeltaCalculator-test.js | 11 ++++ .../src/__fixtures__/getTransformOptions.js | 3 + 4 files changed, 64 insertions(+), 41 deletions(-) diff --git a/packages/metro/src/DeltaBundler/DeltaCalculator.js b/packages/metro/src/DeltaBundler/DeltaCalculator.js index 0a4668cc..c925f22a 100644 --- a/packages/metro/src/DeltaBundler/DeltaCalculator.js +++ b/packages/metro/src/DeltaBundler/DeltaCalculator.js @@ -21,6 +21,7 @@ import type Bundler from '../Bundler'; import type {Options as JSTransformerOptions} from '../JSTransformer/worker'; import type DependencyGraph from '../node-haste/DependencyGraph'; import type {BundleOptions} from '../shared/types.flow'; +import type {DependencyEdge, DependencyEdges} from './traverseDependencies'; export type DeltaResult = {| +modified: Map, @@ -28,7 +29,10 @@ export type DeltaResult = {| +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 @@ -46,7 +50,7 @@ class DeltaCalculator extends EventEmitter { _deletedFiles: Set = new Set(); _modifiedFiles: Set = new Set(); - _dependencyEdges: DependencyEdges = new Map(); + _graph: Graph; constructor( bundler: Bundler, @@ -59,6 +63,15 @@ class DeltaCalculator extends EventEmitter { this._options = options; this._dependencyGraph = dependencyGraph; + const entryFilePath = this._dependencyGraph.getAbsolutePath( + this._options.entryFile, + ); + + this._graph = { + dependencies: new Map(), + entryFile: entryFilePath, + }; + this._dependencyGraph .getWatcher() .on('change', this._handleMultipleFileChanges); @@ -72,14 +85,15 @@ class DeltaCalculator extends EventEmitter { .getWatcher() .removeListener('change', this._handleMultipleFileChanges); - this.reset(); - } + this.removeAllListeners(); - reset() { // Clean up all the cache data structures to deallocate memory. + this._graph = { + dependencies: new Map(), + entryFile: this._options.entryFile, + }; this._modifiedFiles = new Set(); this._deletedFiles = new Set(); - this._dependencyEdges = new Map(); } /** @@ -111,7 +125,7 @@ class DeltaCalculator extends EventEmitter { let result; - const numDependencies = this._dependencyEdges.size; + const numDependencies = this._graph.dependencies.size; try { 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 // a weird state. As a safe net we clean the dependency edges to force // a clean traversal of the graph next time. - if (this._dependencyEdges.size !== numDependencies) { - this._dependencyEdges = new Map(); + if (this._graph.dependencies.size !== numDependencies) { + this._graph.dependencies = new Map(); } throw error; @@ -137,13 +151,13 @@ class DeltaCalculator extends EventEmitter { // Return all the modules if the client requested a reset delta. if (reset) { + this._graph.dependencies = reorderDependencies( + this._graph.dependencies.get(this._graph.entryFile), + this._graph.dependencies, + ); + return { - modified: reorderDependencies( - this._dependencyEdges.get( - this._dependencyGraph.getAbsolutePath(this._options.entryFile), - ), - this._dependencyEdges, - ), + modified: this._graph.dependencies, deleted: new Set(), 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) * plus some metadata. */ - getDependencyEdges(): DependencyEdges { - return this._dependencyEdges; + getGraph(): Graph { + return this._graph; } _handleMultipleFileChanges = ({eventsQueue}) => { @@ -250,16 +264,12 @@ class DeltaCalculator extends EventEmitter { ): Promise { const transformerOptions = await this.getTransformerOptions(); - if (!this._dependencyEdges.size) { - const path = this._dependencyGraph.getAbsolutePath( - this._options.entryFile, - ); - + if (!this._graph.dependencies.size) { const {added} = await initialTraverseDependencies( - path, + this._graph.entryFile, this._dependencyGraph, transformerOptions, - this._dependencyEdges, + this._graph.dependencies, 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 // depends on it, so we can process it and correctly return an error. deletedFiles.forEach(filePath => { - const edge = this._dependencyEdges.get(filePath); + const edge = this._graph.dependencies.get(filePath); if (edge) { 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. const modifiedDependencies = Array.from(modifiedFiles).filter(filePath => - this._dependencyEdges.has(filePath), + this._graph.dependencies.has(filePath), ); // No changes happened. Return empty delta. @@ -294,7 +304,7 @@ class DeltaCalculator extends EventEmitter { modifiedDependencies, this._dependencyGraph, transformerOptions, - this._dependencyEdges, + this._graph.dependencies, this._options.onProgress || undefined, ); diff --git a/packages/metro/src/DeltaBundler/DeltaTransformer.js b/packages/metro/src/DeltaBundler/DeltaTransformer.js index d5ab5cd5..f84c1dd9 100644 --- a/packages/metro/src/DeltaBundler/DeltaTransformer.js +++ b/packages/metro/src/DeltaBundler/DeltaTransformer.js @@ -154,7 +154,7 @@ class DeltaTransformer extends EventEmitter { * transitive dependencies of any given file within the dependency graph. **/ async getDependenciesFn(): Promise<(string) => Set> { - if (!this._deltaCalculator.getDependencyEdges().size) { + if (!this._deltaCalculator.getGraph().dependencies.size) { // If by any means the dependency graph has not been initialized, call // getDelta() to initialize it. await this._getDelta({reset: false}); @@ -168,16 +168,17 @@ class DeltaTransformer extends EventEmitter { * transitive dependencies of any given file within the dependency graph. **/ async getInverseDependencies(): Promise>> { - 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 // getDelta() to initialize it. await this._getDelta({reset: false}); } - const dependencyEdges = this._deltaCalculator.getDependencyEdges(); const output = new Map(); - for (const [path, {inverseDependencies}] of dependencyEdges.entries()) { + for (const [path, {inverseDependencies}] of graph.dependencies.entries()) { output.set( this._getModuleId(path), Array.from(inverseDependencies).map(dep => this._getModuleId(dep)), @@ -226,14 +227,14 @@ class DeltaTransformer extends EventEmitter { const {modified, deleted, reset} = await this._deltaCalculator.getDelta({ reset: resetDelta, }); + const graph = this._deltaCalculator.getGraph(); const transformerOptions = await this._deltaCalculator.getTransformerOptions(); - const dependencyEdges = this._deltaCalculator.getDependencyEdges(); // Return the source code that gets prepended to all the modules. This // contains polyfills and startup code (like the require() implementation). const prependSources = reset - ? await this._getPrepend(transformerOptions, dependencyEdges) + ? await this._getPrepend(transformerOptions, graph.dependencies) : new Map(); // 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( modules, transformerOptions, - dependencyEdges, + graph.dependencies, ); deleted.forEach(id => { @@ -255,7 +256,7 @@ class DeltaTransformer extends EventEmitter { // Return the source code that gets appended to all the modules. This // contains the require() calls to startup the execution of the modules. const appendSources = reset - ? await this._getAppend(dependencyEdges) + ? await this._getAppend(graph.dependencies) : new Map(); // generate a random @@ -271,11 +272,9 @@ class DeltaTransformer extends EventEmitter { } _getDependencies = (path: string): Set => { - const dependencies = this._getDeps( - path, - this._deltaCalculator.getDependencyEdges(), - new Set(), - ); + const graph = this._deltaCalculator.getGraph(); + + const dependencies = this._getDeps(path, graph.dependencies, new Set()); // Remove the main entry point, since this method only returns the // dependencies. diff --git a/packages/metro/src/DeltaBundler/__tests__/DeltaCalculator-test.js b/packages/metro/src/DeltaBundler/__tests__/DeltaCalculator-test.js index f6021471..49bdeddd 100644 --- a/packages/metro/src/DeltaBundler/__tests__/DeltaCalculator-test.js +++ b/packages/metro/src/DeltaBundler/__tests__/DeltaCalculator-test.js @@ -385,6 +385,17 @@ describe('DeltaCalculator', () => { 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()', () => { it('should calculate the transform options correctly', async () => { expect(await deltaCalculator.getTransformerOptions()).toEqual({ diff --git a/packages/metro/src/__fixtures__/getTransformOptions.js b/packages/metro/src/__fixtures__/getTransformOptions.js index f7774640..00ea8e74 100644 --- a/packages/metro/src/__fixtures__/getTransformOptions.js +++ b/packages/metro/src/__fixtures__/getTransformOptions.js @@ -32,6 +32,9 @@ async function getTransformOptions(): Promise { getWatcher() { return {on() {}}; }, + getAbsolutePath(path) { + return '/' + path; + }, }; const options = { assetPlugins: [],