Skip to content

Commit 88409f6

Browse files
davidaurelioMartin Konicek
authored andcommitted
ModuleGraph: Also call back with module objects of entry points
Summary: This changes the callback value of `Graph` function so that it also contains a separate property with `Module` instances of the entry points. Having references to the entry point modules allows to e.g. create require calls to them dynamically to kick of bundle execution. The commit also contains a refactoring of the `Graph` function and its helpers that reduces the need for extensive parameter passing and long nested functions. Reviewed By: cpojer Differential Revision: D4250772 fbshipit-source-id: 2edca77bbef2308d3176a62123b8cecd70e2c8c7
1 parent 8439a12 commit 88409f6

3 files changed

Lines changed: 104 additions & 52 deletions

File tree

packager/react-packager/src/ModuleGraph/Graph.js

Lines changed: 54 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import type {
2121
File,
2222
GraphFn,
2323
LoadFn,
24-
Module,
2524
ResolveFn,
2625
} from './types.flow';
2726

@@ -70,17 +69,16 @@ exports.create = function create(resolve: ResolveFn, load: LoadFn): GraphFn {
7069
return;
7170
}
7271

73-
const modules: Map<string | null, Module> = new Map();
74-
modules.set(null, createParentModule());
75-
7672
const loadQueue: LoadQueue = queue(seq(
7773
({id, parent}, cb) => resolve(id, parent, platform, options || NO_OPTIONS, cb),
7874
memoize((file, cb) => load(file, {log, optimize}, cb)),
7975
), Number.MAX_SAFE_INTEGER);
8076

77+
const {collect, loadModule} = createGraphHelpers(loadQueue, cwd, skip);
78+
8179
loadQueue.drain = () => {
8280
loadQueue.kill();
83-
callback(null, collect(null, modules));
81+
callback(null, collect());
8482
};
8583
loadQueue.error = error => {
8684
loadQueue.error = noop;
@@ -90,7 +88,7 @@ exports.create = function create(resolve: ResolveFn, load: LoadFn): GraphFn {
9088

9189
let i = 0;
9290
for (const entryPoint of entryPoints) {
93-
loadModule(entryPoint, null, i++, loadQueue, modules, skip, cwd, callback);
91+
loadModule(entryPoint, null, i++);
9492
}
9593

9694
if (i === 0) {
@@ -103,19 +101,50 @@ exports.create = function create(resolve: ResolveFn, load: LoadFn): GraphFn {
103101
return Graph;
104102
};
105103

106-
function loadModule(
107-
id: string,
108-
parent: string | null,
109-
parentDependencyIndex: number,
110-
loadQueue: LoadQueue,
111-
modules: Map<string | null, Module>,
112-
skip?: Set<string>,
113-
cwd: string,
114-
) {
104+
function createGraphHelpers(loadQueue, cwd, skip) {
105+
const modules = new Map([[null, createParentModule()]]);
106+
107+
function collect(
108+
path = null,
109+
serialized = {entryModules: [], modules: []},
110+
seen = new Set(),
111+
) {
112+
const module = modules.get(path);
113+
if (module == null || seen.has(path)) {
114+
return serialized;
115+
}
116+
117+
const {dependencies} = module;
118+
if (path === null) {
119+
serialized.entryModules =
120+
dependencies.map(dep => nullthrows(modules.get(dep.path)));
121+
} else {
122+
serialized.modules.push(module);
123+
seen.add(path);
124+
}
125+
126+
for (const dependency of dependencies) {
127+
collect(dependency.path, serialized, seen);
128+
}
129+
130+
return serialized;
131+
}
132+
133+
function loadModule(id, parent, parentDepIndex) {
134+
loadQueue.push(
135+
{id, parent: parent != null ? parent : cwd},
136+
(error, file, dependencyIDs) =>
137+
onFileLoaded(error, file, dependencyIDs, id, parent, parentDepIndex),
138+
);
139+
}
140+
115141
function onFileLoaded(
116-
error?: ?Error,
117-
file?: File,
118-
dependencyIDs?: Array<string>,
142+
error,
143+
file,
144+
dependencyIDs,
145+
id,
146+
parent,
147+
parentDependencyIndex,
119148
) {
120149
if (error) {
121150
return;
@@ -129,38 +158,16 @@ function loadModule(
129158
parentModule.dependencies[parentDependencyIndex] = {id, path};
130159

131160
if ((!skip || !skip.has(path)) && !modules.has(path)) {
132-
const dependencies = Array(dependencyIDs.length);
133-
modules.set(path, {dependencies, file: nullthrows(file)});
161+
const module = {
162+
dependencies: Array(dependencyIDs.length),
163+
file: nullthrows(file),
164+
};
165+
modules.set(path, module);
134166
for (let i = 0; i < dependencyIDs.length; ++i) {
135-
loadModule(dependencyIDs[i], path, i, loadQueue, modules, skip, cwd);
167+
loadModule(dependencyIDs[i], path, i);
136168
}
137169
}
138170
}
139171

140-
loadQueue.push(
141-
{id, parent: parent != null ? parent : cwd},
142-
onFileLoaded,
143-
);
144-
}
145-
146-
function collect(
147-
path,
148-
modules,
149-
serialized = [],
150-
seen: Set<string | null> = new Set(),
151-
): Array<Module> {
152-
const module = modules.get(path);
153-
if (!module || seen.has(path)) { return serialized; }
154-
155-
if (path !== null) {
156-
serialized.push(module);
157-
seen.add(path);
158-
}
159-
160-
const {dependencies} = module;
161-
for (var i = 0; i < dependencies.length; i++) {
162-
collect(dependencies[i].path, modules, serialized, seen);
163-
}
164-
165-
return serialized;
172+
return {collect, loadModule};
166173
}

packager/react-packager/src/ModuleGraph/__tests__/Graph-test.js

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ describe('Graph:', () => {
239239

240240
graph(['a'], anyPlatform, noOpts, (error, result) => {
241241
expect(error).toEqual(null);
242-
expect(result).toEqual([
242+
expect(result.modules).toEqual([
243243
createModule('a', ['b', 'e', 'h']),
244244
createModule('b', ['c', 'd']),
245245
createModule('c'),
@@ -253,6 +253,46 @@ describe('Graph:', () => {
253253
});
254254
});
255255

256+
it('calls back with the resolved modules of the entry points', done => {
257+
load.stub.reset();
258+
resolve.stub.reset();
259+
260+
load.stub.withArgs(idToPath('a')).yields(null, createFile('a'), ['b']);
261+
load.stub.withArgs(idToPath('b')).yields(null, createFile('b'), []);
262+
load.stub.withArgs(idToPath('c')).yields(null, createFile('c'), ['d']);
263+
load.stub.withArgs(idToPath('d')).yields(null, createFile('d'), []);
264+
265+
'abcd'.split('')
266+
.forEach(id => resolve.stub.withArgs(id).yields(null, idToPath(id)));
267+
268+
graph(['a', 'c'], anyPlatform, noOpts, (error, result) => {
269+
expect(result.entryModules).toEqual([
270+
createModule('a', ['b']),
271+
createModule('c', ['d']),
272+
]);
273+
done();
274+
});
275+
});
276+
277+
it('calls back with the resolved modules of the entry points if one entry point is a dependency of another', done => {
278+
load.stub.reset();
279+
resolve.stub.reset();
280+
281+
load.stub.withArgs(idToPath('a')).yields(null, createFile('a'), ['b']);
282+
load.stub.withArgs(idToPath('b')).yields(null, createFile('b'), []);
283+
284+
'ab'.split('')
285+
.forEach(id => resolve.stub.withArgs(id).yields(null, idToPath(id)));
286+
287+
graph(['a', 'b'], anyPlatform, noOpts, (error, result) => {
288+
expect(result.entryModules).toEqual([
289+
createModule('a', ['b']),
290+
createModule('b', []),
291+
]);
292+
done();
293+
});
294+
});
295+
256296
it('does not include dependencies more than once', done => {
257297
const ids = ['a', 'b', 'c', 'd'];
258298
ids.forEach(id => {
@@ -266,7 +306,7 @@ describe('Graph:', () => {
266306

267307
graph(['a', 'd', 'b'], anyPlatform, noOpts, (error, result) => {
268308
expect(error).toEqual(null);
269-
expect(result).toEqual([
309+
expect(result.modules).toEqual([
270310
createModule('a', ['b', 'c']),
271311
createModule('b'),
272312
createModule('c'),
@@ -287,7 +327,7 @@ describe('Graph:', () => {
287327
.withArgs(idToPath('c')).yields(null, createFile('c'), ['a']);
288328

289329
graph(['a'], anyPlatform, noOpts, (error, result) => {
290-
expect(result).toEqual([
330+
expect(result.modules).toEqual([
291331
createModule('a', ['b']),
292332
createModule('b', ['c']),
293333
createModule('c', ['a']),
@@ -307,7 +347,7 @@ describe('Graph:', () => {
307347
const skip = new Set([idToPath('b'), idToPath('c')]);
308348

309349
graph(['a'], anyPlatform, {skip}, (error, result) => {
310-
expect(result).toEqual([
350+
expect(result.modules).toEqual([
311351
createModule('a', ['b', 'c', 'd']),
312352
createModule('d', []),
313353
]);

packager/react-packager/src/ModuleGraph/types.flow.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,14 @@ export type GraphFn = (
5656
entryPoints: Iterable<string>,
5757
platform: string,
5858
options?: ?GraphOptions,
59-
callback?: Callback<Array<Module>>,
59+
callback?: Callback<GraphResult>,
6060
) => void;
6161

62+
type GraphResult = {
63+
entryModules: Array<Module>,
64+
modules: Array<Module>,
65+
};
66+
6267
export type ResolveFn = (
6368
id: string,
6469
source: string,

0 commit comments

Comments
 (0)