Make output types from Delta Bundler generic

Reviewed By: jeanlauliac

Differential Revision: D7894080

fbshipit-source-id: 0f560c4600b4931bcc8f32ded10a7933d1ead984
This commit is contained in:
Rafael Oleza 2018-05-11 15:05:13 -07:00 committed by Facebook Github Bot
parent 095426d038
commit cdbacc96b7
20 changed files with 154 additions and 130 deletions

View File

@ -13,14 +13,9 @@
const DeltaCalculator = require('./DeltaBundler/DeltaCalculator'); const DeltaCalculator = require('./DeltaBundler/DeltaCalculator');
import type Bundler from './Bundler'; import type Bundler from './Bundler';
import type { import type {DeltaResult, Graph, Options} from './DeltaBundler/DeltaCalculator';
DeltaResult,
Graph as CalculatorGraph,
Options,
} from './DeltaBundler/DeltaCalculator';
export type Delta = DeltaResult; export type {DeltaResult, Graph} from './DeltaBundler/DeltaCalculator';
export type Graph = CalculatorGraph;
/** /**
* `DeltaBundler` uses the `DeltaTransformer` to build bundle deltas. This * `DeltaBundler` uses the `DeltaTransformer` to build bundle deltas. This
@ -28,9 +23,9 @@ export type Graph = CalculatorGraph;
* concurrent clients requesting their own deltas. This is done through the * concurrent clients requesting their own deltas. This is done through the
* `clientId` param (which maps a client to a specific delta transformer). * `clientId` param (which maps a client to a specific delta transformer).
*/ */
class DeltaBundler { class DeltaBundler<T> {
_bundler: Bundler; _bundler: Bundler;
_deltaCalculators: Map<Graph, DeltaCalculator> = new Map(); _deltaCalculators: Map<Graph<T>, DeltaCalculator<T>> = new Map();
constructor(bundler: Bundler) { constructor(bundler: Bundler) {
this._bundler = bundler; this._bundler = bundler;
@ -43,8 +38,8 @@ class DeltaBundler {
async buildGraph( async buildGraph(
entryPoints: $ReadOnlyArray<string>, entryPoints: $ReadOnlyArray<string>,
options: Options, options: Options<T>,
): Promise<Graph> { ): Promise<Graph<T>> {
const depGraph = await this._bundler.getDependencyGraph(); const depGraph = await this._bundler.getDependencyGraph();
const deltaCalculator = new DeltaCalculator(entryPoints, depGraph, options); const deltaCalculator = new DeltaCalculator(entryPoints, depGraph, options);
@ -57,7 +52,10 @@ class DeltaBundler {
return graph; return graph;
} }
async getDelta(graph: Graph, {reset}: {reset: boolean}): Promise<Delta> { async getDelta(
graph: Graph<T>,
{reset}: {reset: boolean},
): Promise<DeltaResult<T>> {
const deltaCalculator = this._deltaCalculators.get(graph); const deltaCalculator = this._deltaCalculators.get(graph);
if (!deltaCalculator) { if (!deltaCalculator) {
@ -67,7 +65,7 @@ class DeltaBundler {
return await deltaCalculator.getDelta({reset}); return await deltaCalculator.getDelta({reset});
} }
listen(graph: Graph, callback: () => mixed) { listen(graph: Graph<T>, callback: () => mixed) {
const deltaCalculator = this._deltaCalculators.get(graph); const deltaCalculator = this._deltaCalculators.get(graph);
if (!deltaCalculator) { if (!deltaCalculator) {
@ -77,7 +75,7 @@ class DeltaBundler {
deltaCalculator.on('change', callback); deltaCalculator.on('change', callback);
} }
endGraph(graph: Graph) { endGraph(graph: Graph<T>) {
const deltaCalculator = this._deltaCalculators.get(graph); const deltaCalculator = this._deltaCalculators.get(graph);
if (!deltaCalculator) { if (!deltaCalculator) {

View File

@ -20,8 +20,8 @@ const {EventEmitter} = require('events');
import type DependencyGraph from '../node-haste/DependencyGraph'; import type DependencyGraph from '../node-haste/DependencyGraph';
import type {Graph, Module, Options} from './traverseDependencies'; import type {Graph, Module, Options} from './traverseDependencies';
export type DeltaResult = {| export type DeltaResult<T> = {|
+modified: Map<string, Module>, +modified: Map<string, Module<T>>,
+deleted: Set<string>, +deleted: Set<string>,
+reset: boolean, +reset: boolean,
|}; |};
@ -34,20 +34,20 @@ export type {Graph, Options} from './traverseDependencies';
* traverse the files that have been changed between calls and avoid having to * traverse the files that have been changed between calls and avoid having to
* traverse the whole dependency tree for trivial small changes. * traverse the whole dependency tree for trivial small changes.
*/ */
class DeltaCalculator extends EventEmitter { class DeltaCalculator<T> extends EventEmitter {
_dependencyGraph: DependencyGraph; _dependencyGraph: DependencyGraph;
_options: Options; _options: Options<T>;
_currentBuildPromise: ?Promise<DeltaResult>; _currentBuildPromise: ?Promise<DeltaResult<T>>;
_deletedFiles: Set<string> = new Set(); _deletedFiles: Set<string> = new Set();
_modifiedFiles: Set<string> = new Set(); _modifiedFiles: Set<string> = new Set();
_graph: Graph; _graph: Graph<T>;
constructor( constructor(
entryPoints: $ReadOnlyArray<string>, entryPoints: $ReadOnlyArray<string>,
dependencyGraph: DependencyGraph, dependencyGraph: DependencyGraph,
options: Options, options: Options<T>,
) { ) {
super(); super();
@ -87,7 +87,7 @@ class DeltaCalculator extends EventEmitter {
* Main method to calculate the delta of modules. It returns a DeltaResult, * Main method to calculate the delta of modules. It returns a DeltaResult,
* which contain the modified/added modules and the removed modules. * which contain the modified/added modules and the removed modules.
*/ */
async getDelta({reset}: {reset: boolean}): Promise<DeltaResult> { async getDelta({reset}: {reset: boolean}): Promise<DeltaResult<T>> {
// If there is already a build in progress, wait until it finish to start // If there is already a build in progress, wait until it finish to start
// processing a new one (delta server doesn't support concurrent builds). // processing a new one (delta server doesn't support concurrent builds).
if (this._currentBuildPromise) { if (this._currentBuildPromise) {
@ -155,7 +155,7 @@ class DeltaCalculator extends EventEmitter {
* needed information to do the traversing (dependencies, inverseDependencies) * needed information to do the traversing (dependencies, inverseDependencies)
* plus some metadata. * plus some metadata.
*/ */
getGraph(): Graph { getGraph(): Graph<T> {
return this._graph; return this._graph;
} }
@ -191,7 +191,7 @@ class DeltaCalculator extends EventEmitter {
async _getChangedDependencies( async _getChangedDependencies(
modifiedFiles: Set<string>, modifiedFiles: Set<string>,
deletedFiles: Set<string>, deletedFiles: Set<string>,
): Promise<DeltaResult> { ): Promise<DeltaResult<T>> {
if (!this._graph.dependencies.size) { if (!this._graph.dependencies.size) {
const {added} = await initialTraverseDependencies( const {added} = await initialTraverseDependencies(
this._graph, this._graph,

View File

@ -15,7 +15,9 @@ const getAppendScripts = require('../../lib/getAppendScripts');
const {wrapModule} = require('./helpers/js'); const {wrapModule} = require('./helpers/js');
const {getJsOutput, isJsModule} = require('./helpers/js'); const {getJsOutput, isJsModule} = require('./helpers/js');
import type {Delta, Graph} from '../../DeltaBundler'; import type {DeltaResult} from '../../DeltaBundler/DeltaCalculator';
import type {Graph} from '../../DeltaBundler';
import type {JsOutput} from '../../JSTransformer/worker';
import type {Module} from '../traverseDependencies'; import type {Module} from '../traverseDependencies';
type Options = {| type Options = {|
@ -29,10 +31,10 @@ type Options = {|
function deltaJSBundle( function deltaJSBundle(
entryPoint: string, entryPoint: string,
pre: $ReadOnlyArray<Module>, pre: $ReadOnlyArray<Module<JsOutput>>,
delta: Delta, delta: DeltaResult<JsOutput>,
sequenceId: string, sequenceId: string,
graph: Graph, graph: Graph<JsOutput>,
options: Options, options: Options,
): string { ): string {
const outputPre = []; const outputPre = [];

View File

@ -13,6 +13,7 @@
const {getAssetFiles} = require('../../Assets'); const {getAssetFiles} = require('../../Assets');
const {getJsOutput, isJsModule} = require('./helpers/js'); const {getJsOutput, isJsModule} = require('./helpers/js');
import type {JsOutput} from '../../JSTransformer/worker';
import type {Graph} from '../DeltaCalculator'; import type {Graph} from '../DeltaCalculator';
import type {Module} from '../traverseDependencies'; import type {Module} from '../traverseDependencies';
@ -21,8 +22,8 @@ type Options = {|
|}; |};
async function getAllFiles( async function getAllFiles(
pre: $ReadOnlyArray<Module>, pre: $ReadOnlyArray<Module<JsOutput>>,
graph: Graph, graph: Graph<JsOutput>,
options: Options, options: Options,
): Promise<$ReadOnlyArray<string>> { ): Promise<$ReadOnlyArray<string>> {
const modules = graph.dependencies; const modules = graph.dependencies;

View File

@ -16,6 +16,7 @@ const {getAssetData} = require('../../Assets');
const {getJsOutput, isJsModule} = require('./helpers/js'); const {getJsOutput, isJsModule} = require('./helpers/js');
import type {AssetData} from '../../Assets'; import type {AssetData} from '../../Assets';
import type {JsOutput} from '../../JSTransformer/worker';
import type {Graph} from '../DeltaCalculator'; import type {Graph} from '../DeltaCalculator';
type Options = {| type Options = {|
@ -25,7 +26,7 @@ type Options = {|
|}; |};
async function getAssets( async function getAssets(
graph: Graph, graph: Graph<JsOutput>,
options: Options, options: Options,
): Promise<$ReadOnlyArray<AssetData>> { ): Promise<$ReadOnlyArray<AssetData>> {
const promises = []; const promises = [];

View File

@ -20,6 +20,7 @@ const {createRamBundleGroups} = require('../../Bundler/util');
const {isJsModule, wrapModule} = require('./helpers/js'); const {isJsModule, wrapModule} = require('./helpers/js');
import type {GetTransformOptions} from '../../Bundler'; import type {GetTransformOptions} from '../../Bundler';
import type {JsOutput} from '../../JSTransformer/worker';
import type {ModuleTransportLike} from '../../shared/types.flow'; import type {ModuleTransportLike} from '../../shared/types.flow';
import type {Graph} from '../DeltaCalculator'; import type {Graph} from '../DeltaCalculator';
import type {Module} from '../traverseDependencies'; import type {Module} from '../traverseDependencies';
@ -45,8 +46,8 @@ export type RamBundleInfo = {|
async function getRamBundleInfo( async function getRamBundleInfo(
entryPoint: string, entryPoint: string,
pre: $ReadOnlyArray<Module>, pre: $ReadOnlyArray<Module<JsOutput>>,
graph: Graph, graph: Graph<JsOutput>,
options: Options, options: Options,
): Promise<RamBundleInfo> { ): Promise<RamBundleInfo> {
const modules = [ const modules = [

View File

@ -12,7 +12,10 @@
import type {Graph} from '../../DeltaCalculator'; import type {Graph} from '../../DeltaCalculator';
function getTransitiveDependencies(path: string, graph: Graph): Set<string> { function getTransitiveDependencies<T>(
path: string,
graph: Graph<T>,
): Set<string> {
const dependencies = _getDeps(path, graph, new Set()); const dependencies = _getDeps(path, graph, new Set());
// Remove the main entry point, since this method only returns the // Remove the main entry point, since this method only returns the
@ -22,7 +25,11 @@ function getTransitiveDependencies(path: string, graph: Graph): Set<string> {
return dependencies; return dependencies;
} }
function _getDeps(path: string, graph: Graph, deps: Set<string>): Set<string> { function _getDeps<T>(
path: string,
graph: Graph<T>,
deps: Set<string>,
): Set<string> {
if (deps.has(path)) { if (deps.has(path)) {
return deps; return deps;
} }

View File

@ -14,6 +14,7 @@ const addParamsToDefineCall = require('../../../lib/addParamsToDefineCall');
const invariant = require('fbjs/lib/invariant'); const invariant = require('fbjs/lib/invariant');
const path = require('path'); const path = require('path');
import type {JsOutput} from '../../../JSTransformer/worker';
import type {Module} from '../../traverseDependencies'; import type {Module} from '../../traverseDependencies';
export type Options = { export type Options = {
@ -26,7 +27,7 @@ export type Options = {
// Make sure to set PRINT_REQUIRE_PATHS = true too, and restart Metro // Make sure to set PRINT_REQUIRE_PATHS = true too, and restart Metro
const PASS_MODULE_PATHS_TO_DEFINE = false; const PASS_MODULE_PATHS_TO_DEFINE = false;
function wrapModule(module: Module, options: Options) { function wrapModule(module: Module<JsOutput>, options: Options) {
const output = getJsOutput(module); const output = getJsOutput(module);
if (output.type.startsWith('js/script')) { if (output.type.startsWith('js/script')) {
return output.data.code; return output.data.code;
@ -54,7 +55,7 @@ function wrapModule(module: Module, options: Options) {
return addParamsToDefineCall(output.data.code, ...params); return addParamsToDefineCall(output.data.code, ...params);
} }
function getJsOutput(module: Module) { function getJsOutput(module: Module<JsOutput>) {
const jsModules = module.output.filter(({type}) => type.startsWith('js/')); const jsModules = module.output.filter(({type}) => type.startsWith('js/'));
invariant( invariant(
@ -67,8 +68,10 @@ function getJsOutput(module: Module) {
return jsModules[0]; return jsModules[0];
} }
function isJsModule(module: Module) { function isJsModule(module: Module<JsOutput>) {
return module.output.some(output => output.type.startsWith('js/')); const jsModules = module.output.filter(({type}) => type.startsWith('js/'));
return jsModules.length > 0;
} }
module.exports = { module.exports = {

View File

@ -14,7 +14,9 @@ const addParamsToDefineCall = require('../../lib/addParamsToDefineCall');
const {isJsModule, wrapModule} = require('./helpers/js'); const {isJsModule, wrapModule} = require('./helpers/js');
import type {Delta, Graph} from '../../DeltaBundler'; import type {DeltaResult} from '../../DeltaBundler/DeltaCalculator';
import type {Graph} from '../../DeltaBundler';
import type {JsOutput} from '../../JSTransformer/worker';
import type {Module} from '../traverseDependencies'; import type {Module} from '../traverseDependencies';
type Options = { type Options = {
@ -30,7 +32,11 @@ export type Result = {
}, },
}; };
function hmrJSBundle(delta: Delta, graph: Graph, options: Options): Result { function hmrJSBundle(
delta: DeltaResult<JsOutput>,
graph: Graph<JsOutput>,
options: Options,
): Result {
const modules = []; const modules = [];
for (const module of delta.modified.values()) { for (const module of delta.modified.values()) {
@ -50,8 +56,8 @@ function hmrJSBundle(delta: Delta, graph: Graph, options: Options): Result {
} }
function _prepareModule( function _prepareModule(
module: Module, module: Module<JsOutput>,
graph: Graph, graph: Graph<JsOutput>,
options: Options, options: Options,
): {|+id: number, +code: string|} { ): {|+id: number, +code: string|} {
const code = wrapModule(module, { const code = wrapModule(module, {
@ -83,7 +89,7 @@ function _prepareModule(
*/ */
function _getInverseDependencies( function _getInverseDependencies(
path: string, path: string,
graph: Graph, graph: Graph<JsOutput>,
inverseDependencies: {[key: string]: Array<string>} = {}, inverseDependencies: {[key: string]: Array<string>} = {},
): {[key: string]: Array<string>} { ): {[key: string]: Array<string>} {
// Dependency alredy traversed. // Dependency alredy traversed.

View File

@ -14,6 +14,7 @@ const getAppendScripts = require('../../lib/getAppendScripts');
const {isJsModule, wrapModule} = require('./helpers/js'); const {isJsModule, wrapModule} = require('./helpers/js');
import type {JsOutput} from '../../JSTransformer/worker';
import type {Graph} from '../DeltaCalculator'; import type {Graph} from '../DeltaCalculator';
import type {Module} from '../traverseDependencies'; import type {Module} from '../traverseDependencies';
@ -28,8 +29,8 @@ type Options = {|
function plainJSBundle( function plainJSBundle(
entryPoint: string, entryPoint: string,
pre: $ReadOnlyArray<Module>, pre: $ReadOnlyArray<Module<JsOutput>>,
graph: Graph, graph: Graph<JsOutput>,
options: Options, options: Options,
): string { ): string {
for (const module of graph.dependencies.values()) { for (const module of graph.dependencies.values()) {

View File

@ -13,13 +13,14 @@
const {isJsModule, getJsOutput} = require('./helpers/js'); const {isJsModule, getJsOutput} = require('./helpers/js');
const {fromRawMappings} = require('metro-source-map'); const {fromRawMappings} = require('metro-source-map');
import type {JsOutput} from '../../JSTransformer/worker';
import type {Graph} from '../DeltaCalculator'; import type {Graph} from '../DeltaCalculator';
import type {Module} from '../traverseDependencies'; import type {Module} from '../traverseDependencies';
import type {BabelSourceMap} from '@babel/core'; import type {BabelSourceMap} from '@babel/core';
function fullSourceMapObject( function fullSourceMapObject(
pre: $ReadOnlyArray<Module>, pre: $ReadOnlyArray<Module<JsOutput>>,
graph: Graph, graph: Graph<JsOutput>,
options: {|+excludeSource: boolean|}, options: {|+excludeSource: boolean|},
): BabelSourceMap { ): BabelSourceMap {
const modules = [...pre, ...graph.dependencies.values()] const modules = [...pre, ...graph.dependencies.values()]

View File

@ -13,12 +13,13 @@
const {isJsModule, getJsOutput} = require('./helpers/js'); const {isJsModule, getJsOutput} = require('./helpers/js');
const {fromRawMappings} = require('metro-source-map'); const {fromRawMappings} = require('metro-source-map');
import type {JsOutput} from '../../JSTransformer/worker';
import type {Graph} from '../DeltaCalculator'; import type {Graph} from '../DeltaCalculator';
import type {Module} from '../traverseDependencies'; import type {Module} from '../traverseDependencies';
function fullSourceMap( function fullSourceMap(
pre: $ReadOnlyArray<Module>, pre: $ReadOnlyArray<Module<JsOutput>>,
graph: Graph, graph: Graph<JsOutput>,
options: {|+excludeSource: boolean|}, options: {|+excludeSource: boolean|},
): string { ): string {
const modules = [...pre, ...graph.dependencies.values()] const modules = [...pre, ...graph.dependencies.values()]

View File

@ -11,27 +11,26 @@
'use strict'; 'use strict';
import type {TransformResultDependency} from '../ModuleGraph/types.flow'; import type {TransformResultDependency} from '../ModuleGraph/types.flow';
import type {MetroSourceMapSegmentTuple} from 'metro-source-map';
export type Dependency = {| export type Dependency = {|
absolutePath: string, absolutePath: string,
data: TransformResultDependency, data: TransformResultDependency,
|}; |};
export type Module = {| export type Module<T> = {|
dependencies: Map<string, Dependency>, dependencies: Map<string, Dependency>,
inverseDependencies: Set<string>, inverseDependencies: Set<string>,
output: TransformOutput, output: $ReadOnlyArray<T>,
path: string, path: string,
getSource: () => string, getSource: () => string,
|}; |};
export type Graph = {| export type Graph<T> = {|
dependencies: Map<string, Module>, dependencies: Map<string, Module<T>>,
entryPoints: $ReadOnlyArray<string>, entryPoints: $ReadOnlyArray<string>,
|}; |};
type Result = {added: Map<string, Module>, deleted: Set<string>}; type Result<T> = {added: Map<string, Module<T>>, deleted: Set<string>};
/** /**
* Internal data structure that the traversal logic uses to know which of the * Internal data structure that the traversal logic uses to know which of the
@ -39,29 +38,21 @@ type Result = {added: Map<string, Module>, deleted: Set<string>};
* (a file should not be deleted if it has been added, but it should if it * (a file should not be deleted if it has been added, but it should if it
* just has been modified). * just has been modified).
**/ **/
type Delta = { type Delta<T> = {
added: Map<string, Module>, added: Map<string, Module<T>>,
modified: Map<string, Module>, modified: Map<string, Module<T>>,
deleted: Set<string>, deleted: Set<string>,
}; };
export type TransformOutput = $ReadOnlyArray<{| export type TransformFn<T> = string => Promise<{|
+data: {
+code: string,
+map: Array<MetroSourceMapSegmentTuple>,
},
+type: string,
|}>;
export type TransformFn = string => Promise<{|
dependencies: $ReadOnlyArray<TransformResultDependency>, dependencies: $ReadOnlyArray<TransformResultDependency>,
output: TransformOutput, output: $ReadOnlyArray<T>,
+getSource: () => string, +getSource: () => string,
|}>; |}>;
export type Options = {| export type Options<T> = {|
resolve: (from: string, to: string) => string, resolve: (from: string, to: string) => string,
transform: TransformFn, transform: TransformFn<T>,
onProgress: ?(numProcessed: number, total: number) => mixed, onProgress: ?(numProcessed: number, total: number) => mixed,
|}; |};
@ -76,11 +67,11 @@ export type Options = {|
* method should traverse. Normally, these paths should be the modified files * method should traverse. Normally, these paths should be the modified files
* since the last traversal. * since the last traversal.
*/ */
async function traverseDependencies( async function traverseDependencies<T>(
paths: $ReadOnlyArray<string>, paths: $ReadOnlyArray<string>,
graph: Graph, graph: Graph<T>,
options: Options, options: Options<T>,
): Promise<Result> { ): Promise<Result<T>> {
const delta = { const delta = {
added: new Map(), added: new Map(),
modified: new Map(), modified: new Map(),
@ -134,10 +125,10 @@ async function traverseDependencies(
}; };
} }
async function initialTraverseDependencies( async function initialTraverseDependencies<T>(
graph: Graph, graph: Graph<T>,
options: Options, options: Options<T>,
): Promise<Result> { ): Promise<Result<T>> {
graph.entryPoints.forEach(entryPoint => createModule(entryPoint, graph)); graph.entryPoints.forEach(entryPoint => createModule(entryPoint, graph));
await traverseDependencies(graph.entryPoints, graph, options); await traverseDependencies(graph.entryPoints, graph, options);
@ -150,11 +141,11 @@ async function initialTraverseDependencies(
}; };
} }
async function traverseDependenciesForSingleFile( async function traverseDependenciesForSingleFile<T>(
module: Module, module: Module<T>,
graph: Graph, graph: Graph<T>,
delta: Delta, delta: Delta<T>,
options: Options, options: Options<T>,
): Promise<void> { ): Promise<void> {
let numProcessed = 0; let numProcessed = 0;
let total = 1; let total = 1;
@ -179,11 +170,11 @@ async function traverseDependenciesForSingleFile(
options.onProgress && options.onProgress(numProcessed, total); options.onProgress && options.onProgress(numProcessed, total);
} }
async function processModule( async function processModule<T>(
module: Module, module: Module<T>,
graph: Graph, graph: Graph<T>,
delta: Delta, delta: Delta<T>,
options: Options, options: Options<T>,
onDependencyAdd: () => mixed, onDependencyAdd: () => mixed,
onDependencyAdded: () => mixed, onDependencyAdded: () => mixed,
): Promise<void> { ): Promise<void> {
@ -239,12 +230,12 @@ async function processModule(
await Promise.all(promises); await Promise.all(promises);
} }
async function addDependency( async function addDependency<T>(
parentModule: Module, parentModule: Module<T>,
path: string, path: string,
graph: Graph, graph: Graph<T>,
delta: Delta, delta: Delta<T>,
options: Options, options: Options<T>,
onDependencyAdd: () => mixed, onDependencyAdd: () => mixed,
onDependencyAdded: () => mixed, onDependencyAdded: () => mixed,
): Promise<void> { ): Promise<void> {
@ -276,11 +267,11 @@ async function addDependency(
onDependencyAdded(); onDependencyAdded();
} }
function removeDependency( function removeDependency<T>(
parentModule: Module, parentModule: Module<T>,
absolutePath: string, absolutePath: string,
graph: Graph, graph: Graph<T>,
delta: Delta, delta: Delta<T>,
): void { ): void {
const module = graph.dependencies.get(absolutePath); const module = graph.dependencies.get(absolutePath);
@ -309,7 +300,7 @@ function removeDependency(
graph.dependencies.delete(module.path); graph.dependencies.delete(module.path);
} }
function createModule(filePath: string, graph: Graph): Module { function createModule<T>(filePath: string, graph: Graph<T>): Module<T> {
const module = { const module = {
dependencies: new Map(), dependencies: new Map(),
inverseDependencies: new Set(), inverseDependencies: new Set(),
@ -323,10 +314,10 @@ function createModule(filePath: string, graph: Graph): Module {
return module; return module;
} }
function resolveDependencies( function resolveDependencies<T>(
parentPath: string, parentPath: string,
dependencies: $ReadOnlyArray<TransformResultDependency>, dependencies: $ReadOnlyArray<TransformResultDependency>,
options: Options, options: Options<T>,
): Map<string, Dependency> { ): Map<string, Dependency> {
return new Map( return new Map(
dependencies.map(result => { dependencies.map(result => {
@ -346,7 +337,7 @@ function resolveDependencies(
* Re-traverse the dependency graph in DFS order to reorder the modules and * Re-traverse the dependency graph in DFS order to reorder the modules and
* guarantee the same order between runs. This method mutates the passed graph. * guarantee the same order between runs. This method mutates the passed graph.
*/ */
function reorderGraph(graph: Graph) { function reorderGraph<T>(graph: Graph<T>) {
const orderedDependencies = new Map(); const orderedDependencies = new Map();
graph.entryPoints.forEach(entryPoint => { graph.entryPoints.forEach(entryPoint => {
@ -362,10 +353,10 @@ function reorderGraph(graph: Graph) {
graph.dependencies = orderedDependencies; graph.dependencies = orderedDependencies;
} }
function reorderDependencies( function reorderDependencies<T>(
graph: Graph, graph: Graph<T>,
module: Module, module: Module<T>,
orderedDependencies: Map<string, Module>, orderedDependencies: Map<string, Module<T>>,
): void { ): void {
if (module.path) { if (module.path) {
if (orderedDependencies.has(module.path)) { if (orderedDependencies.has(module.path)) {

View File

@ -21,12 +21,11 @@ const {
Logger: {createActionStartEntry, createActionEndEntry, log}, Logger: {createActionStartEntry, createActionEndEntry, log},
} = require('metro-core'); } = require('metro-core');
import type {Graph} from './DeltaBundler/DeltaCalculator'; import type PackagerServer, {JsGraph} from './Server';
import type PackagerServer from './Server';
import type {Reporter} from './lib/reporting'; import type {Reporter} from './lib/reporting';
type Client = {| type Client = {|
graph: Graph, graph: JsGraph,
sendFn: (data: string) => mixed, sendFn: (data: string) => mixed,
|}; |};

View File

@ -37,10 +37,17 @@ import type {Ast} from '@babel/core';
import type {Plugins as BabelPlugins} from 'babel-core'; import type {Plugins as BabelPlugins} from 'babel-core';
import type {LogEntry} from 'metro-core/src/Logger'; import type {LogEntry} from 'metro-core/src/Logger';
import type {MetroSourceMapSegmentTuple} from 'metro-source-map'; import type {MetroSourceMapSegmentTuple} from 'metro-source-map';
import type {TransformOutput} from '../DeltaBundler/traverseDependencies';
export type JsOutput = {|
data: {
+code: string,
+map: Array<MetroSourceMapSegmentTuple>,
},
type: string,
|};
export type TransformedCode = {| export type TransformedCode = {|
output: TransformOutput, output: $ReadOnlyArray<JsOutput>,
dependencies: $ReadOnlyArray<TransformResultDependency>, dependencies: $ReadOnlyArray<TransformResultDependency>,
|}; |};

View File

@ -53,13 +53,15 @@ import type {
PostProcessBundleSourcemap, PostProcessBundleSourcemap,
} from './Bundler'; } from './Bundler';
import type {CacheStore} from 'metro-cache'; import type {CacheStore} from 'metro-cache';
import type {Delta, Graph} from './DeltaBundler'; import type {Graph} from './DeltaBundler';
import type {DeltaResult} from './DeltaBundler/DeltaCalculator';
import type {CustomResolver} from 'metro-resolver'; import type {CustomResolver} from 'metro-resolver';
import type {MetroSourceMap} from 'metro-source-map'; import type {MetroSourceMap} from 'metro-source-map';
import type {Symbolicate} from './Server/symbolicate/symbolicate'; import type {Symbolicate} from './Server/symbolicate/symbolicate';
import type {AssetData} from './Assets'; import type {AssetData} from './Assets';
import type { import type {
CustomTransformOptions, CustomTransformOptions,
JsOutput,
TransformedCode, TransformedCode,
} from './JSTransformer/worker'; } from './JSTransformer/worker';
@ -70,8 +72,8 @@ const {
type ResolveSync = (path: string, opts: ?{baseDir?: string}) => string; type ResolveSync = (path: string, opts: ?{baseDir?: string}) => string;
type GraphInfo = {| type GraphInfo = {|
graph: Graph, graph: Graph<JsOutput>,
prepend: $ReadOnlyArray<Module>, prepend: $ReadOnlyArray<Module<JsOutput>>,
lastModified: Date, lastModified: Date,
+sequenceId: string, +sequenceId: string,
|}; |};
@ -87,6 +89,8 @@ export type BuildGraphOptions = {|
+type: 'module' | 'script', +type: 'module' | 'script',
|}; |};
export type JsGraph = Graph<JsOutput>;
type DeltaOptions = BundleOptions & { type DeltaOptions = BundleOptions & {
deltaBundleId: ?string, deltaBundleId: ?string,
}; };
@ -143,7 +147,7 @@ class Server {
_symbolicateInWorker: Symbolicate; _symbolicateInWorker: Symbolicate;
_platforms: Set<string>; _platforms: Set<string>;
_nextBundleBuildID: number; _nextBundleBuildID: number;
_deltaBundler: DeltaBundler; _deltaBundler: DeltaBundler<JsOutput>;
_graphs: Map<string, Promise<GraphInfo>> = new Map(); _graphs: Map<string, Promise<GraphInfo>> = new Map();
_deltaGraphs: Map<string, Promise<GraphInfo>> = new Map(); _deltaGraphs: Map<string, Promise<GraphInfo>> = new Map();
@ -256,7 +260,7 @@ class Server {
this._bundler.end(); this._bundler.end();
} }
getDeltaBundler(): DeltaBundler { getDeltaBundler(): DeltaBundler<JsOutput> {
return this._deltaBundler; return this._deltaBundler;
} }
@ -286,7 +290,7 @@ class Server {
async buildGraph( async buildGraph(
entryFiles: $ReadOnlyArray<string>, entryFiles: $ReadOnlyArray<string>,
options: BuildGraphOptions, options: BuildGraphOptions,
): Promise<Graph> { ): Promise<JsGraph> {
entryFiles = entryFiles.map(entryFile => entryFiles = entryFiles.map(entryFile =>
getAbsolutePath(entryFile, this._opts.projectRoots), getAbsolutePath(entryFile, this._opts.projectRoots),
); );
@ -445,7 +449,7 @@ class Server {
async _getDeltaInfo( async _getDeltaInfo(
options: DeltaOptions, options: DeltaOptions,
): Promise<{...GraphInfo, delta: Delta}> { ): Promise<{...GraphInfo, delta: DeltaResult<JsOutput>}> {
const id = this._optionsHash(options); const id = this._optionsHash(options);
let graphPromise = this._deltaGraphs.get(id); let graphPromise = this._deltaGraphs.get(id);
let graphInfo; let graphInfo;

View File

@ -31,7 +31,7 @@ const {readFile} = require('fs-extra');
const {Terminal} = require('metro-core'); const {Terminal} = require('metro-core');
import type {ConfigT} from './Config'; import type {ConfigT} from './Config';
import type {Graph} from './DeltaBundler'; import type {JsGraph} from './Server';
import type {Reporter} from './lib/reporting'; import type {Reporter} from './lib/reporting';
import type {RequestOptions, OutputOptions} from './shared/types.flow.js'; import type {RequestOptions, OutputOptions} from './shared/types.flow.js';
import type {Options as ServerOptions} from './shared/types.flow'; import type {Options as ServerOptions} from './shared/types.flow';
@ -381,7 +381,7 @@ exports.buildGraph = async function({
platform = `web`, platform = `web`,
type = 'module', type = 'module',
...rest ...rest
}: BuildGraphOptions): Promise<Graph> { }: BuildGraphOptions): Promise<JsGraph> {
const metroServer = await runMetro({ const metroServer = await runMetro({
...rest, ...rest,
config, config,

View File

@ -12,6 +12,7 @@
import type {Graph} from '../DeltaBundler/DeltaCalculator'; import type {Graph} from '../DeltaBundler/DeltaCalculator';
import type {Module} from '../DeltaBundler/traverseDependencies'; import type {Module} from '../DeltaBundler/traverseDependencies';
import type {JsOutput} from '../JSTransformer/worker';
type Options<T: number | string> = { type Options<T: number | string> = {
+createModuleId: string => T, +createModuleId: string => T,
@ -23,9 +24,9 @@ type Options<T: number | string> = {
function getAppendScripts<T: number | string>( function getAppendScripts<T: number | string>(
entryPoint: string, entryPoint: string,
graph: Graph, graph: Graph<JsOutput>,
options: Options<T>, options: Options<T>,
): $ReadOnlyArray<Module> { ): $ReadOnlyArray<Module<JsOutput>> {
const output = []; const output = [];
if (options.runModule) { if (options.runModule) {

View File

@ -17,7 +17,7 @@ const transformHelpers = require('./transformHelpers');
import type Bundler from '../Bundler'; import type Bundler from '../Bundler';
import type {Module} from '../DeltaBundler/traverseDependencies'; import type {Module} from '../DeltaBundler/traverseDependencies';
import type DeltaBundler from '../DeltaBundler'; import type DeltaBundler from '../DeltaBundler';
import type {CustomTransformOptions} from '../JSTransformer/worker'; import type {CustomTransformOptions, JsOutput} from '../JSTransformer/worker';
type Options = { type Options = {
getPolyfills: ({platform: ?string}) => $ReadOnlyArray<string>, getPolyfills: ({platform: ?string}) => $ReadOnlyArray<string>,
@ -36,8 +36,8 @@ async function getPrependedScripts(
options: Options, options: Options,
bundleOptions: BundleOptions, bundleOptions: BundleOptions,
bundler: Bundler, bundler: Bundler,
deltaBundler: DeltaBundler, deltaBundler: DeltaBundler<JsOutput>,
): Promise<Array<Module>> { ): Promise<Array<Module<JsOutput>>> {
// Get all the polyfills from the relevant option params (the // Get all the polyfills from the relevant option params (the
// `getPolyfills()` method and the `polyfillModuleNames` variable). // `getPolyfills()` method and the `polyfillModuleNames` variable).
const polyfillModuleNames = options const polyfillModuleNames = options
@ -80,7 +80,7 @@ async function getPrependedScripts(
]; ];
} }
function _getPrelude({dev}: {dev: boolean}): Module { function _getPrelude({dev}: {dev: boolean}): Module<JsOutput> {
const code = getPreludeCode({isDev: dev}); const code = getPreludeCode({isDev: dev});
const name = '__prelude__'; const name = '__prelude__';

View File

@ -13,7 +13,7 @@
import type Bundler from '../Bundler'; import type Bundler from '../Bundler';
import type {TransformFn} from '../DeltaBundler/traverseDependencies'; import type {TransformFn} from '../DeltaBundler/traverseDependencies';
import type DeltaBundler from '../DeltaBundler'; import type DeltaBundler from '../DeltaBundler';
import type {TransformOptions} from '../JSTransformer/worker'; import type {JsOutput, TransformOptions} from '../JSTransformer/worker';
import type {BuildGraphOptions} from '../Server'; import type {BuildGraphOptions} from '../Server';
type InlineRequiresRaw = {+blacklist: {[string]: true}} | boolean; type InlineRequiresRaw = {+blacklist: {[string]: true}} | boolean;
@ -21,7 +21,7 @@ type InlineRequiresRaw = {+blacklist: {[string]: true}} | boolean;
async function calcTransformerOptions( async function calcTransformerOptions(
entryFiles: $ReadOnlyArray<string>, entryFiles: $ReadOnlyArray<string>,
bundler: Bundler, bundler: Bundler,
deltaBundler: DeltaBundler, deltaBundler: DeltaBundler<JsOutput>,
options: BuildGraphOptions, options: BuildGraphOptions,
): Promise<{...TransformOptions, inlineRequires: InlineRequiresRaw}> { ): Promise<{...TransformOptions, inlineRequires: InlineRequiresRaw}> {
const { const {
@ -85,9 +85,9 @@ function removeInlineRequiresBlacklistFromOptions(
async function getTransformFn( async function getTransformFn(
entryFiles: $ReadOnlyArray<string>, entryFiles: $ReadOnlyArray<string>,
bundler: Bundler, bundler: Bundler,
deltaBundler: DeltaBundler, deltaBundler: DeltaBundler<JsOutput>,
options: BuildGraphOptions, options: BuildGraphOptions,
): Promise<TransformFn> { ): Promise<TransformFn<JsOutput>> {
const dependencyGraph = await bundler.getDependencyGraph(); const dependencyGraph = await bundler.getDependencyGraph();
const {inlineRequires, ...transformerOptions} = await calcTransformerOptions( const {inlineRequires, ...transformerOptions} = await calcTransformerOptions(
entryFiles, entryFiles,