Use the new Graph object for returning the RAM bundle info

Reviewed By: mjesun

Differential Revision: D7275597

fbshipit-source-id: 5a30c83f9ce756f457796a08d10034d03cbc3b75
This commit is contained in:
Rafael Oleza 2018-03-20 06:53:25 -07:00 committed by Facebook Github Bot
parent 1b3d2e126d
commit 2a107aaafc
16 changed files with 575 additions and 618 deletions

View File

@ -1,46 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
* @format
*/
'use strict';
import type {GetTransformOptions} from '../../Bundler';
/**
* Returns the options needed to create a RAM bundle.
*/
async function getRamOptions(
entryFile: string,
options: {dev: boolean, platform: ?string},
getDependencies: string => Iterable<string>,
getTransformOptions: ?GetTransformOptions,
): Promise<{|
+preloadedModules: {[string]: true},
+ramGroups: Array<string>,
|}> {
if (getTransformOptions == null) {
return {
preloadedModules: {},
ramGroups: [],
};
}
const {preloadedModules, ramGroups} = await getTransformOptions(
[entryFile],
{dev: options.dev, hot: true, platform: options.platform},
async x => Array.from(getDependencies),
);
return {
preloadedModules: preloadedModules || {},
ramGroups: ramGroups || [],
};
}
exports.getRamOptions = getRamOptions;

View File

@ -10,19 +10,9 @@
'use strict';
const DeltaPatcher = require('../DeltaPatcher');
const RamBundle = require('./RamBundle');
const stableHash = require('metro-cache/src/stableHash');
const {createRamBundleGroups} = require('../../Bundler/util');
const {fromRawMappings} = require('metro-source-map');
import type {GetTransformOptions} from '../../Bundler';
import type {BundleOptions, ModuleTransportLike} from '../../shared/types.flow';
import type {BundleOptions} from '../../shared/types.flow';
import type DeltaBundler from '../';
import type DeltaTransformer, {
DeltaEntry,
DeltaTransformResponse,
} from '../DeltaTransformer';
@ -30,15 +20,6 @@ export type DeltaOptions = BundleOptions & {
deltaBundleId: ?string,
};
export type RamModule = ModuleTransportLike;
export type RamBundleInfo = {
getDependencies: string => Set<string>,
startupModules: $ReadOnlyArray<RamModule>,
lazyModules: $ReadOnlyArray<RamModule>,
groups: Map<number, Set<number>>,
};
/**
* This module contains many serializers for the Delta Bundler. Each serializer
* returns a string representation for any specific type of bundle, which can
@ -70,121 +51,6 @@ async function deltaBundle(
};
}
async function _getAllModules(
deltaBundler: DeltaBundler,
options: BundleOptions,
): Promise<{
modules: $ReadOnlyArray<DeltaEntry>,
numModifiedFiles: number,
lastModified: Date,
deltaTransformer: DeltaTransformer,
}> {
const clientId = '__SERVER__' + stableHash(options).toString('hex');
const deltaPatcher = DeltaPatcher.get(clientId);
options = {
...options,
deltaBundleId: deltaPatcher.getLastBundleId(),
};
const {delta, deltaTransformer} = await _build(
deltaBundler,
clientId,
options,
);
const modules = deltaPatcher
.applyDelta(delta)
.getAllModules(deltaBundler.getPostProcessModulesFn(options.entryFile));
return {
deltaTransformer,
lastModified: deltaPatcher.getLastModifiedDate(),
modules,
numModifiedFiles: deltaPatcher.getLastNumModifiedFiles(),
};
}
async function getRamBundleInfo(
deltaBundler: DeltaBundler,
options: BundleOptions,
getTransformOptions: ?GetTransformOptions,
): Promise<RamBundleInfo> {
const {modules, deltaTransformer} = await _getAllModules(
deltaBundler,
options,
);
const ramModules = modules.map(module => ({
id: module.id,
code: module.code,
map: fromRawMappings([module]).toMap(module.path, {
excludeSource: options.excludeSource,
}),
name: module.name,
sourcePath: module.path,
source: module.source,
type: module.type,
}));
const {preloadedModules, ramGroups} = await RamBundle.getRamOptions(
options.entryFile,
{
dev: options.dev,
platform: options.platform,
},
await deltaTransformer.getDependenciesFn(),
getTransformOptions,
);
const startupModules = [];
const lazyModules = [];
ramModules.forEach(module => {
if (preloadedModules.hasOwnProperty(module.sourcePath)) {
startupModules.push(module);
return;
}
if (module.type === 'script' || module.type === 'require') {
startupModules.push(module);
return;
}
if (module.type === 'asset' || module.type === 'module') {
lazyModules.push(module);
}
});
const getDependencies = await deltaTransformer.getDependenciesFn();
const groups = createRamBundleGroups(
ramGroups,
lazyModules,
(module: RamModule, dependenciesByPath: Map<string, RamModule>) => {
const deps = getDependencies(module.sourcePath);
const output = new Set();
for (const dependency of deps) {
const module = dependenciesByPath.get(dependency);
if (module) {
output.add(module.id);
}
}
return output;
},
);
return {
getDependencies,
groups,
lazyModules,
startupModules,
};
}
async function _build(
deltaBundler: DeltaBundler,
clientId: string,
@ -208,5 +74,4 @@ async function _build(
module.exports = {
deltaBundle,
getRamBundleInfo,
};

View File

@ -85,74 +85,4 @@ describe('Serializers', () => {
await Serializers.deltaBundle(deltaBundler, 'foo', {deltaBundleId: 10}),
).toMatchSnapshot();
});
it('should return the RAM bundle info', async () => {
expect(
await Serializers.getRamBundleInfo(deltaBundler, {}),
).toMatchSnapshot();
getDelta.mockReturnValueOnce(
Promise.resolve({
delta: new Map([
[3, {type: 'module', code: 'modified;', id: 3, path: '/foo/3.js'}],
[7, {type: 'asset', code: 'code', id: 7, path: '/foo/path.png'}],
[8, {type: 'module', code: 'code', id: 8, path: '/foo/8.js'}],
[9, {type: 'asset', code: 'code', id: 9, path: '/foo/path3.png'}],
]),
pre: new Map([
[5, {type: 'script', code: 'more pre;', id: 5, path: '/foo/5.js'}],
]),
post: new Map([
[6, {type: 'require', code: 'bananas;', id: 6, path: '/foo/6.js'}],
[10, {type: 'comment', code: 'bananas;', id: 10, path: '/foo/10.js'}],
]),
inverseDependencies: [],
}),
);
expect(
await Serializers.getRamBundleInfo(deltaBundler, {}),
).toMatchSnapshot();
});
it('should use the preloadedModules and ramGroup configs to build a RAM bundle', async () => {
getDelta.mockReset();
getDependenciesFn.mockReset();
getDelta.mockReturnValue(
Promise.resolve({
delta: new Map([
[3, {type: 'module', code: 'code', id: 3, path: '/foo/3.js'}],
[4, {type: 'module', code: 'code', id: 4, path: '/foo/4.js'}],
[5, {type: 'module', code: 'code', id: 5, path: '/foo/5.js'}],
[6, {type: 'module', code: 'code', id: 6, path: '/foo/6.js'}],
]),
pre: new Map([
[7, {type: 'script', code: 'more pre;', id: 7, path: '/foo/7.js'}],
]),
post: new Map([
[8, {type: 'require', code: 'bananas;', id: 8, path: '/foo/8.js'}],
]),
inverseDependencies: [],
reset: 1,
}),
);
getDependenciesFn.mockReturnValue(
Promise.resolve(path => {
expect(path).toBe('/foo/5.js');
return new Set(['/foo/6.js']);
}),
);
const getTransformOptions = async () => ({
preloadedModules: {'/foo/3.js': true},
ramGroups: ['/foo/5.js'],
});
expect(
await Serializers.getRamBundleInfo(deltaBundler, {}, getTransformOptions),
).toMatchSnapshot();
});
});

View File

@ -1,235 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Serializers should return the RAM bundle info 1`] = `
Object {
"getDependencies": [Function],
"groups": Map {},
"lazyModules": Array [
Object {
"code": "module3;",
"id": 3,
"map": Object {
"file": "/3.js",
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": undefined,
"source": undefined,
"sourcePath": "/3.js",
"type": "module",
},
Object {
"code": "another;",
"id": 4,
"map": Object {
"file": "/4.js",
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": undefined,
"source": undefined,
"sourcePath": "/4.js",
"type": "module",
},
],
"startupModules": Array [
Object {
"code": "pre;",
"id": 1,
"map": Object {
"file": "/pre.js",
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": undefined,
"source": undefined,
"sourcePath": "/pre.js",
"type": "script",
},
Object {
"code": "post;",
"id": 2,
"map": Object {
"file": "/p",
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": undefined,
"source": undefined,
"sourcePath": "/p",
"type": "require",
},
],
}
`;
exports[`Serializers should return the RAM bundle info 2`] = `
Object {
"getDependencies": [Function],
"groups": Map {},
"lazyModules": Array [
Object {
"code": "modified;",
"id": 3,
"map": Object {
"file": "/foo/3.js",
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": undefined,
"source": undefined,
"sourcePath": "/foo/3.js",
"type": "module",
},
Object {
"code": "another;",
"id": 4,
"map": Object {
"file": "/4.js",
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": undefined,
"source": undefined,
"sourcePath": "/4.js",
"type": "module",
},
Object {
"code": "code",
"id": 7,
"map": Object {
"file": "/foo/path.png",
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": undefined,
"source": undefined,
"sourcePath": "/foo/path.png",
"type": "asset",
},
Object {
"code": "code",
"id": 8,
"map": Object {
"file": "/foo/8.js",
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": undefined,
"source": undefined,
"sourcePath": "/foo/8.js",
"type": "module",
},
Object {
"code": "code",
"id": 9,
"map": Object {
"file": "/foo/path3.png",
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": undefined,
"source": undefined,
"sourcePath": "/foo/path3.png",
"type": "asset",
},
],
"startupModules": Array [
Object {
"code": "pre;",
"id": 1,
"map": Object {
"file": "/pre.js",
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": undefined,
"source": undefined,
"sourcePath": "/pre.js",
"type": "script",
},
Object {
"code": "more pre;",
"id": 5,
"map": Object {
"file": "/foo/5.js",
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": undefined,
"source": undefined,
"sourcePath": "/foo/5.js",
"type": "script",
},
Object {
"code": "post;",
"id": 2,
"map": Object {
"file": "/p",
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": undefined,
"source": undefined,
"sourcePath": "/p",
"type": "require",
},
Object {
"code": "bananas;",
"id": 6,
"map": Object {
"file": "/foo/6.js",
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": undefined,
"source": undefined,
"sourcePath": "/foo/6.js",
"type": "require",
},
],
}
`;
exports[`Serializers should return the stringified delta bundle 1`] = `
Object {
"bundle": "{\\"id\\":\\"1234\\",\\"pre\\":[[1,\\"pre;\\"]],\\"post\\":[[2,\\"post;\\"]],\\"delta\\":[[3,\\"module3;\\"],[4,\\"another;\\"]],\\"reset\\":true}",
@ -243,114 +13,3 @@ Object {
"numModifiedFiles": 2,
}
`;
exports[`Serializers should use the preloadedModules and ramGroup configs to build a RAM bundle 1`] = `
Object {
"getDependencies": [Function],
"groups": Map {
5 => Set {
6,
},
},
"lazyModules": Array [
Object {
"code": "code",
"id": 4,
"map": Object {
"file": "/foo/4.js",
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": undefined,
"source": undefined,
"sourcePath": "/foo/4.js",
"type": "module",
},
Object {
"code": "code",
"id": 5,
"map": Object {
"file": "/foo/5.js",
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": undefined,
"source": undefined,
"sourcePath": "/foo/5.js",
"type": "module",
},
Object {
"code": "code",
"id": 6,
"map": Object {
"file": "/foo/6.js",
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": undefined,
"source": undefined,
"sourcePath": "/foo/6.js",
"type": "module",
},
],
"startupModules": Array [
Object {
"code": "more pre;",
"id": 7,
"map": Object {
"file": "/foo/7.js",
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": undefined,
"source": undefined,
"sourcePath": "/foo/7.js",
"type": "script",
},
Object {
"code": "code",
"id": 3,
"map": Object {
"file": "/foo/3.js",
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": undefined,
"source": undefined,
"sourcePath": "/foo/3.js",
"type": "module",
},
Object {
"code": "bananas;",
"id": 8,
"map": Object {
"file": "/foo/8.js",
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": undefined,
"source": undefined,
"sourcePath": "/foo/8.js",
"type": "require",
},
],
}
`;

View File

@ -0,0 +1,180 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should return the RAM bundle info 1`] = `
Object {
"getDependencies": [Function],
"groups": Map {},
"lazyModules": Array [
Object {
"code": "__d(function() {entry()},\\"/root/entry.js\\",[\\"/root/foo.js\\",\\"/root/entry2.js\\"],\\"entry.js\\");",
"id": "/root/entry.js",
"map": Object {
"file": undefined,
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": "entry.js",
"source": undefined,
"sourcePath": "/root/entry.js",
"type": "module",
},
Object {
"code": "__d(function() {entry2()},\\"/root/entry2.js\\",[\\"/root/foo2.js\\"],\\"entry2.js\\");",
"id": "/root/entry2.js",
"map": Object {
"file": undefined,
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": "entry2.js",
"source": undefined,
"sourcePath": "/root/entry2.js",
"type": "module",
},
Object {
"code": "__d(function() {foo2()},\\"/root/foo2.js\\",[],\\"foo2.js\\");",
"id": "/root/foo2.js",
"map": Object {
"file": undefined,
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": "foo2.js",
"source": undefined,
"sourcePath": "/root/foo2.js",
"type": "module",
},
Object {
"code": "__d(function() {foo()},\\"/root/foo.js\\",[\\"/root/bar.js\\",\\"/root/baz.js\\",\\"/root/qux.js\\"],\\"foo.js\\");",
"id": "/root/foo.js",
"map": Object {
"file": undefined,
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": "foo.js",
"source": undefined,
"sourcePath": "/root/foo.js",
"type": "module",
},
Object {
"code": "__d(function() {baz()},\\"/root/baz.js\\",[],\\"baz.js\\");",
"id": "/root/baz.js",
"map": Object {
"file": undefined,
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": "baz.js",
"source": undefined,
"sourcePath": "/root/baz.js",
"type": "asset",
},
Object {
"code": "__d(function() {bar()},\\"/root/bar.js\\",[],\\"bar.js\\");",
"id": "/root/bar.js",
"map": Object {
"file": undefined,
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": "bar.js",
"source": undefined,
"sourcePath": "/root/bar.js",
"type": "module",
},
Object {
"code": "__d(function() {qux()},\\"/root/qux.js\\",[],\\"qux.js\\");",
"id": "/root/qux.js",
"map": Object {
"file": undefined,
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": "qux.js",
"source": undefined,
"sourcePath": "/root/qux.js",
"type": "module",
},
],
"startupModules": Array [
Object {
"code": "__d(function() {pre()});",
"id": "/root/pre.js",
"map": Object {
"file": undefined,
"mappings": "",
"names": Array [],
"sources": Array [],
"sourcesContent": Array [],
"version": 3,
},
"name": "pre.js",
"source": undefined,
"sourcePath": "/root/pre.js",
"type": "script",
},
Object {
"code": "require(\\"/root/entry.js\\");",
"id": "require-/root/entry.js",
"map": Object {
"file": undefined,
"mappings": "",
"names": Array [],
"sources": Array [
"require-/root/entry.js",
],
"sourcesContent": Array [
"",
],
"version": 3,
},
"name": "entry.js",
"source": "",
"sourcePath": "require-/root/entry.js",
"type": "script",
},
Object {
"code": "//# sourceMappingURL=http://localhost/bundle.map",
"id": "source-map",
"map": Object {
"file": undefined,
"mappings": "",
"names": Array [],
"sources": Array [
"source-map",
],
"sourcesContent": Array [
"",
],
"version": 3,
},
"name": "source-map",
"source": "",
"sourcePath": "source-map",
"type": "script",
},
],
}
`;

View File

@ -0,0 +1,97 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @emails oncall+javascript_foundation
* @format
*/
'use strict';
const getRamBundleInfo = require('../getRamBundleInfo');
function createModule(name, dependencies, type = 'module') {
return [
`/root/${name}.js`,
{
path: `/root/${name}.js`,
dependencies: new Map(dependencies.map(dep => [dep, `/root/${dep}.js`])),
output: {type, code: `__d(function() {${name}()});`},
},
];
}
const graph = {
dependencies: new Map([
createModule('entry', ['foo', 'entry2']),
createModule('entry2', ['foo2']),
createModule('foo2', []),
createModule('foo', ['bar', 'baz', 'qux']),
createModule('baz', [], 'asset'),
createModule('bar', []),
createModule('qux', []),
]),
};
const pre = [createModule('pre', [], 'script')[1]];
it('should return the RAM bundle info', async () => {
expect(
await getRamBundleInfo('/root/entry.js', pre, graph, {
createModuleId: path => path,
excludeSource: false,
getTransformOptions: () => ({
preloadedModules: {},
ramGroups: [],
}),
dev: true,
runBeforeMainModule: [],
runModule: true,
sourceMapUrl: 'http://localhost/bundle.map',
}),
).toMatchSnapshot();
});
it('should use the preloadedModules and ramGroup configs to build a RAM bundle', async () => {
const getTransformOptions = async () => ({
preloadedModules: {'/root/entry2.js': true},
ramGroups: ['/root/foo.js'],
});
const bundleInfo = await getRamBundleInfo('/root/entry.js', pre, graph, {
createModuleId: path => path,
excludeSource: false,
getTransformOptions,
dev: true,
runBeforeMainModule: [],
runModule: true,
sourceMapUrl: 'http://localhost/bundle.map',
});
expect(bundleInfo.startupModules.map(({id}) => id)).toEqual([
'/root/pre.js',
'/root/entry2.js',
'require-/root/entry.js',
'source-map',
]);
expect(bundleInfo.lazyModules.map(({id}) => id)).toEqual([
'/root/entry.js',
'/root/foo2.js',
'/root/foo.js',
'/root/baz.js',
'/root/bar.js',
'/root/qux.js',
]);
expect(bundleInfo.groups).toEqual(
new Map([
[
'/root/foo.js',
new Set(['/root/bar.js', '/root/baz.js', '/root/qux.js']),
],
]),
);
});

View File

@ -0,0 +1,165 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
* @format
*/
'use strict';
const fullSourceMapObject = require('./sourceMapObject');
const getAppendScripts = require('../../lib/getAppendScripts');
const getTransitiveDependencies = require('./helpers/getTransitiveDependencies');
const path = require('path');
const {createRamBundleGroups} = require('../../Bundler/util');
const {wrapModule} = require('./helpers/js');
import type {GetTransformOptions} from '../../Bundler';
import type {ModuleTransportLike} from '../../shared/types.flow';
import type {Graph} from '../DeltaCalculator';
import type {DependencyEdge} from '../traverseDependencies';
type Options = {|
createModuleId: string => number,
+dev: boolean,
+excludeSource: boolean,
getTransformOptions: ?GetTransformOptions,
+platform: ?string,
+runBeforeMainModule: $ReadOnlyArray<string>,
+runModule: boolean,
+sourceMapUrl: ?string,
|};
export type RamBundleInfo = {|
getDependencies: string => Set<string>,
startupModules: $ReadOnlyArray<ModuleTransportLike>,
lazyModules: $ReadOnlyArray<ModuleTransportLike>,
groups: Map<number, Set<number>>,
|};
async function getRamBundleInfo(
entryPoint: string,
pre: $ReadOnlyArray<DependencyEdge>,
graph: Graph,
options: Options,
): Promise<RamBundleInfo> {
const modules = [
...pre,
...graph.dependencies.values(),
...getAppendScripts(entryPoint, graph, options),
];
modules.forEach(module => options.createModuleId(module.path));
const ramModules = modules.map(module => ({
id: options.createModuleId(module.path),
code: wrapModule(module, options),
map: fullSourceMapObject(
[module],
{dependencies: new Map(), entryPoints: []},
{
excludeSource: options.excludeSource,
},
),
name: path.basename(module.path),
sourcePath: module.path,
source: module.output.source,
type: module.output.type,
}));
const {preloadedModules, ramGroups} = await _getRamOptions(
entryPoint,
{
dev: options.dev,
platform: options.platform,
},
filePath => getTransitiveDependencies(filePath, graph),
options.getTransformOptions,
);
const startupModules = [];
const lazyModules = [];
ramModules.forEach(module => {
if (preloadedModules.hasOwnProperty(module.sourcePath)) {
startupModules.push(module);
return;
}
if (module.type === 'script' || module.type === 'require') {
startupModules.push(module);
return;
}
if (module.type === 'asset' || module.type === 'module') {
lazyModules.push(module);
}
});
const groups = createRamBundleGroups(
ramGroups,
lazyModules,
(
module: ModuleTransportLike,
dependenciesByPath: Map<string, ModuleTransportLike>,
) => {
const deps = getTransitiveDependencies(module.sourcePath, graph);
const output = new Set();
for (const dependency of deps) {
const module = dependenciesByPath.get(dependency);
if (module) {
output.add(module.id);
}
}
return output;
},
);
return {
getDependencies: (filePath: string) =>
getTransitiveDependencies(filePath, graph),
groups,
lazyModules,
startupModules,
};
}
/**
* Returns the options needed to create a RAM bundle.
*/
async function _getRamOptions(
entryFile: string,
options: {dev: boolean, platform: ?string},
getDependencies: string => Iterable<string>,
getTransformOptions: ?GetTransformOptions,
): Promise<{|
+preloadedModules: {[string]: true},
+ramGroups: Array<string>,
|}> {
if (getTransformOptions == null) {
return {
preloadedModules: {},
ramGroups: [],
};
}
const {preloadedModules, ramGroups} = await getTransformOptions(
[entryFile],
{dev: options.dev, hot: true, platform: options.platform},
async x => Array.from(getDependencies),
);
return {
preloadedModules: preloadedModules || {},
ramGroups: ramGroups || [],
};
}
module.exports = getRamBundleInfo;

View File

@ -0,0 +1,55 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @emails oncall+javascript_foundation
* @format
*/
'use strict';
const getTransitiveDependencies = require('../getTransitiveDependencies');
function createModule(name, dependencies, type = 'module') {
return [
`/root/${name}.js`,
{
path: `/root/${name}.js`,
dependencies: new Map(dependencies.map(dep => [dep, `/root/${dep}.js`])),
output: {type, code: `__d(function() {${name}()});`},
},
];
}
const graph = {
dependencies: new Map([
createModule('entry', ['entry2', 'foo']),
createModule('entry2', ['foo2']),
createModule('foo2', []),
createModule('foo', ['bar', 'baz', 'qux']),
createModule('baz', [], 'asset'),
createModule('bar', []),
createModule('qux', []),
]),
};
it('should find the transitive dependencies correctly', () => {
expect(getTransitiveDependencies('/root/entry.js', graph)).toEqual(
new Set([
'/root/entry2.js',
'/root/foo2.js',
'/root/foo.js',
'/root/bar.js',
'/root/baz.js',
'/root/qux.js',
]),
);
expect(getTransitiveDependencies('/root/bar.js', graph)).toEqual(new Set());
expect(getTransitiveDependencies('/root/foo.js', graph)).toEqual(
new Set(['/root/bar.js', '/root/baz.js', '/root/qux.js']),
);
});

View File

@ -0,0 +1,45 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
* @format
*/
'use strict';
import type {Graph} from '../../DeltaCalculator';
function getTransitiveDependencies(path: string, graph: Graph): Set<string> {
const dependencies = _getDeps(path, graph, new Set());
// Remove the main entry point, since this method only returns the
// dependencies.
dependencies.delete(path);
return dependencies;
}
function _getDeps(path: string, graph: Graph, deps: Set<string>): Set<string> {
if (deps.has(path)) {
return deps;
}
const module = graph.dependencies.get(path);
if (!module) {
return deps;
}
deps.add(path);
for (const dependencyPath of module.dependencies.values()) {
_getDeps(dependencyPath, graph, deps);
}
return deps;
}
module.exports = getTransitiveDependencies;

View File

@ -27,6 +27,8 @@ jest
.mock('../../lib/GlobalTransformCache')
.mock('../../DeltaBundler/Serializers/Serializers');
const NativeDate = global.Date;
describe('processRequest', () => {
let Bundler;
let Server;
@ -36,11 +38,12 @@ describe('processRequest', () => {
let Serializers;
let DeltaBundler;
const NativeDate = global.Date;
beforeEach(() => {
jest.useFakeTimers();
jest.resetModules();
global.Date = NativeDate;
Bundler = require('../../Bundler');
Server = require('../');
getAsset = require('../../Assets').getAsset;
@ -89,8 +92,6 @@ describe('processRequest', () => {
let requestHandler;
beforeEach(() => {
global.Date = NativeDate;
DeltaBundler.prototype.buildGraph.mockReturnValue(
Promise.resolve({
entryPoints: ['/root/mybundle.js'],

View File

@ -18,6 +18,7 @@ const Serializers = require('../DeltaBundler/Serializers/Serializers');
const defaultCreateModuleIdFactory = require('../lib/createModuleIdFactory');
const getAllFiles = require('../DeltaBundler/Serializers/getAllFiles');
const getAssets = require('../DeltaBundler/Serializers/getAssets');
const getRamBundleInfo = require('../DeltaBundler/Serializers/getRamBundleInfo');
const plainJSBundle = require('../DeltaBundler/Serializers/plainJSBundle');
const sourceMapObject = require('../DeltaBundler/Serializers/sourceMapObject');
const sourceMapString = require('../DeltaBundler/Serializers/sourceMapString');
@ -43,10 +44,8 @@ import type {CustomError} from '../lib/formatBundlingError';
import type {DependencyEdge} from '../DeltaBundler/traverseDependencies';
import type {IncomingMessage, ServerResponse} from 'http';
import type {Reporter} from '../lib/reporting';
import type {
DeltaOptions,
RamBundleInfo,
} from '../DeltaBundler/Serializers/Serializers';
import type {DeltaOptions} from '../DeltaBundler/Serializers/Serializers';
import type {RamBundleInfo} from '../DeltaBundler/Serializers/getRamBundleInfo';
import type {BundleOptions, Options} from '../shared/types.flow';
import type {
GetTransformOptions,
@ -275,14 +274,23 @@ class Server {
}
async getRamBundleInfo(options: BundleOptions): Promise<RamBundleInfo> {
return await Serializers.getRamBundleInfo(
this._deltaBundler,
{
...options,
entryFile: getAbsolutePath(options.entryFile, this._opts.projectRoots),
},
this._opts.getTransformOptions,
const {prepend, graph} = await this._buildGraph(options);
const entryPoint = getAbsolutePath(
options.entryFile,
this._opts.projectRoots,
);
return await getRamBundleInfo(entryPoint, prepend, graph, {
createModuleId: this._opts.createModuleId,
dev: options.dev,
excludeSource: options.excludeSource,
getTransformOptions: this._opts.getTransformOptions,
platform: options.platform,
runBeforeMainModule: options.runBeforeMainModule,
runModule: options.runModule,
sourceMapUrl: options.sourceMapUrl,
});
}
async getAssets(options: BundleOptions): Promise<$ReadOnlyArray<AssetData>> {

View File

@ -20,7 +20,7 @@ const writeSourceMap = require('./write-sourcemap');
const {joinModules} = require('./util');
import type {RamBundleInfo} from '../../../DeltaBundler/Serializers/Serializers';
import type {RamBundleInfo} from '../../../DeltaBundler/Serializers/getRamBundleInfo';
import type {OutputOptions} from '../../types.flow';
// must not start with a dot, as that won't go into the apk

View File

@ -18,7 +18,7 @@ const writeSourceMap = require('./write-sourcemap');
const {joinModules} = require('./util');
import type {RamBundleInfo} from '../../../DeltaBundler/Serializers/Serializers';
import type {RamBundleInfo} from '../../../DeltaBundler/Serializers/getRamBundleInfo';
import type {
ModuleGroups,
ModuleTransportLike,

View File

@ -15,14 +15,13 @@ const {
joinModules,
} = require('./util');
import type {RamModule} from '../../../DeltaBundler/Serializers/Serializers';
import type {ModuleGroups, ModuleTransportLike} from '../../types.flow';
type Params = {|
fixWrapperOffset: boolean,
lazyModules: $ReadOnlyArray<ModuleTransportLike | RamModule>,
lazyModules: $ReadOnlyArray<ModuleTransportLike>,
moduleGroups: ?ModuleGroups,
startupModules: $ReadOnlyArray<ModuleTransportLike | RamModule>,
startupModules: $ReadOnlyArray<ModuleTransportLike>,
|};
module.exports = ({

View File

@ -16,7 +16,7 @@ const asAssets = require('./as-assets');
const asIndexedFile = require('./as-indexed-file').save;
import type {OutputOptions, RequestOptions} from '../../types.flow';
import type {RamBundleInfo} from '../../../DeltaBundler/Serializers/Serializers';
import type {RamBundleInfo} from '../../../DeltaBundler/Serializers/getRamBundleInfo';
async function buildBundle(
packagerClient: Server,

View File

@ -11,7 +11,6 @@
const invariant = require('fbjs/lib/invariant');
import type {RamModule} from '../../../DeltaBundler/Serializers/Serializers';
import type {ModuleGroups, ModuleTransportLike} from '../../types.flow';
import type {BabelSourceMap} from '@babel/core';
import type {FBIndexMap, IndexMap, MetroSourceMap} from 'metro-source-map';
@ -50,7 +49,7 @@ const Section = (line: number, column: number, map: MetroSourceMap) => ({
type CombineOptions = {fixWrapperOffset: boolean};
function combineSourceMaps(
modules: $ReadOnlyArray<ModuleTransportLike | RamModule>,
modules: $ReadOnlyArray<ModuleTransportLike>,
moduleGroups?: ModuleGroups,
options?: ?CombineOptions,
): IndexMap {
@ -59,7 +58,7 @@ function combineSourceMaps(
}
function combineSourceMapsAddingOffsets(
modules: $ReadOnlyArray<ModuleTransportLike | RamModule>,
modules: $ReadOnlyArray<ModuleTransportLike>,
x_metro_module_paths: Array<string>,
moduleGroups?: ?ModuleGroups,
options?: ?CombineOptions,
@ -75,7 +74,7 @@ function combineSourceMapsAddingOffsets(
}
function combineMaps(
modules: $ReadOnlyArray<ModuleTransportLike | RamModule>,
modules: $ReadOnlyArray<ModuleTransportLike>,
offsets: ?Array<number>,
moduleGroups,
options,