From 8b6d69b645d87302ce47dd76ad0be8905e1525b2 Mon Sep 17 00:00:00 2001 From: Rafael Oleza Date: Tue, 5 Sep 2017 07:10:40 -0700 Subject: [PATCH] Return the inverseDependencies from the Delta Bundler to support HMR Reviewed By: jeanlauliac Differential Revision: D5763905 fbshipit-source-id: 6b95c8dfded5fc30ec2e7a558ab25550d9a1c333 --- .../src/DeltaBundler/DeltaTransformer.js | 58 +++++++++++++++---- .../metro-bundler/src/DeltaBundler/index.js | 16 ++++- packages/metro-bundler/src/Server/index.js | 14 +++-- 3 files changed, 67 insertions(+), 21 deletions(-) diff --git a/packages/metro-bundler/src/DeltaBundler/DeltaTransformer.js b/packages/metro-bundler/src/DeltaBundler/DeltaTransformer.js index 33315e10..d2836de2 100644 --- a/packages/metro-bundler/src/DeltaBundler/DeltaTransformer.js +++ b/packages/metro-bundler/src/DeltaBundler/DeltaTransformer.js @@ -17,14 +17,15 @@ const DeltaCalculator = require('./DeltaCalculator'); import type Bundler from '../Bundler'; import type {Options as JSTransformerOptions} from '../JSTransformer/worker'; import type Resolver from '../Resolver'; -import type {BundleOptions} from '../Server'; import type {MappingsMap} from '../lib/SourceMap'; import type Module from '../node-haste/Module'; +import type {Options as BundleOptions} from './'; export type DeltaTransformResponse = { +pre: ?string, +post: ?string, +delta: {[key: string]: ?string}, + +inverseDependencies: {[key: string]: $ReadOnlyArray}, }; type Options = {| @@ -159,10 +160,16 @@ class DeltaTransformer { ) : null; + // Inverse dependencies are needed for HMR. + const inverseDependencies = this._getInverseDependencies( + this._deltaCalculator.getInverseDependencies(), + ); + return { pre: prependSources, post: appendSources, delta: {...modifiedDelta, ...deletedDelta}, + inverseDependencies, reset, }; } @@ -237,6 +244,23 @@ class DeltaTransformer { return sources.join('\n'); } + /** + * Converts the paths in the inverse dependendencies to module ids. + */ + _getInverseDependencies( + inverseDependencies: Map>, + ): {[key: string]: $ReadOnlyArray} { + const output = Object.create(null); + + for (const [key, dependencies] of inverseDependencies) { + output[this._getModuleId({path: key})] = Array.from( + dependencies, + ).map(dep => this._getModuleId({path: dep})); + } + + return output; + } + async _transformModules( modules: Map, resolver: Resolver, @@ -275,17 +299,27 @@ class DeltaTransformer { const dependencyPairsForModule = dependencyPairs.get(module.path) || []; - const wrapped = await resolver.wrapModule({ - module, - getModuleId: this._getModuleId, - dependencyPairs: dependencyPairsForModule, - dependencyOffsets: metadata.dependencyOffsets || [], - name, - code: metadata.code, - map: metadata.map, - minify: this._bundleOptions.minify, - dev: this._bundleOptions.dev, - }); + const wrapped = this._bundleOptions.wrapModules + ? await resolver.wrapModule({ + module, + getModuleId: this._getModuleId, + dependencyPairs: dependencyPairsForModule, + dependencyOffsets: metadata.dependencyOffsets || [], + name, + code: metadata.code, + map: metadata.map, + minify: this._bundleOptions.minify, + dev: this._bundleOptions.dev, + }) + : { + code: resolver.resolveRequires( + module, + this._getModuleId, + metadata.code, + dependencyPairsForModule, + metadata.dependencyOffsets || [], + ), + }; return [this._getModuleId(module), wrapped.code]; } diff --git a/packages/metro-bundler/src/DeltaBundler/index.js b/packages/metro-bundler/src/DeltaBundler/index.js index 8aaaef83..21c06552 100644 --- a/packages/metro-bundler/src/DeltaBundler/index.js +++ b/packages/metro-bundler/src/DeltaBundler/index.js @@ -23,6 +23,7 @@ export type DeltaBundle = { pre: ?string, post: ?string, delta: {[key: string]: ?string}, + inverseDependencies: {[key: string]: $ReadOnlyArray}, }; type MainOptions = {| @@ -30,7 +31,13 @@ type MainOptions = {| polyfillModuleNames: $ReadOnlyArray, |}; -type Options = BundleOptions & {+deltaBundleId: ?string}; +type FullBuildOptions = BundleOptions & { + +deltaBundleId: ?string, +}; + +export type Options = FullBuildOptions & { + +wrapModules: boolean, +}; /** * `DeltaBundler` uses the `DeltaTransformer` to build bundle deltas. This @@ -84,8 +91,11 @@ class DeltaBundler { }; } - async buildFullBundle(options: Options): Promise { - const deltaBundle = await this.build(options); + async buildFullBundle(options: FullBuildOptions): Promise { + const deltaBundle = await this.build({ + ...options, + wrapModules: true, + }); let deltaPatcher = this._deltaPatchers.get(deltaBundle.id); diff --git a/packages/metro-bundler/src/Server/index.js b/packages/metro-bundler/src/Server/index.js index 6d2c1cd1..12617e5c 100644 --- a/packages/metro-bundler/src/Server/index.js +++ b/packages/metro-bundler/src/Server/index.js @@ -291,12 +291,10 @@ class Server { this._symbolicateInWorker = symbolicate.createWorker(); this._nextBundleBuildID = 1; - if (this._opts.useDeltaBundler) { - this._deltaBundler = new DeltaBundler(this._bundler, { - getPolyfills: this._opts.getPolyfills, - polyfillModuleNames: this._opts.polyfillModuleNames, - }); - } + this._deltaBundler = new DeltaBundler(this._bundler, { + getPolyfills: this._opts.getPolyfills, + polyfillModuleNames: this._opts.polyfillModuleNames, + }); } end(): mixed { @@ -315,6 +313,10 @@ class Server { } } + getDeltaBundler(): DeltaBundler { + return this._deltaBundler; + } + async buildBundle(options: BundleOptions): Promise { const bundle = await this._bundler.bundle(options); const modules = bundle.getModules();