Bundler.js: @flow

Reviewed By: davidaurelio

Differential Revision: D4036964

fbshipit-source-id: dceb81299d076493d12b2ade13354e927c10ea7c
This commit is contained in:
Jean Lauliac 2016-10-19 04:42:26 -07:00 committed by Facebook Github Bot
parent 7fbb46c316
commit 2e06e708fe
2 changed files with 72 additions and 21 deletions

View File

@ -5,19 +5,41 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
*/
'use strict';
const BundleBase = require('./BundleBase');
const ModuleTransport = require('../lib/ModuleTransport');
const _ = require('lodash');
const base64VLQ = require('./base64-vlq');
const BundleBase = require('./BundleBase');
const ModuleTransport = require('../lib/ModuleTransport');
const crypto = require('crypto');
import type {GetSourceOptions, FinalizeOptions} from './BundleBase';
const SOURCEMAPPING_URL = '\n\/\/# sourceMappingURL=';
class Bundle extends BundleBase {
constructor({sourceMapUrl, dev, minify, ramGroups} = {}) {
_dev: boolean | void;
_inlineSourceMap: string | void;
_minify: boolean | void;
_numRequireCalls: number;
_ramBundle: mixed | void;
_ramGroups: Array<string> | void;
_shouldCombineSourceMaps: boolean;
_sourceMap: boolean;
_sourceMapUrl: string | void;
constructor({sourceMapUrl, dev, minify, ramGroups}: {
sourceMapUrl?: string,
dev?: boolean,
minify?: boolean,
ramGroups?: Array<string>,
} = {}) {
super();
this._sourceMap = false;
this._sourceMapUrl = sourceMapUrl;
@ -30,7 +52,16 @@ class Bundle extends BundleBase {
this._ramBundle = null; // cached RAM Bundle
}
addModule(resolver, resolutionResponse, module, moduleTransport) {
addModule(
resolver: {wrapModule: (options: any) => Promise<{code: any, map: any}>},
resolutionResponse: mixed,
module: mixed,
moduleTransport: ModuleTransport,
/* $FlowFixMe: this code is inherently incorrect, because it modifies the
* signature of the base class function "addModule", originally returning
* a number. That means callsites using an instance typed as the base class
* would be broken. This must be refactored. */
): Promise<void> {
const index = super.addModule(moduleTransport);
return resolver.wrapModule({
resolutionResponse,
@ -53,17 +84,21 @@ class Bundle extends BundleBase {
});
}
finalize(options) {
finalize(options: FinalizeOptions) {
options = options || {};
if (options.runMainModule) {
/* $FlowFixMe: this is unsound, as nothing enforces runBeforeMainModule
* to be available if `runMainModule` is true. Refactor. */
options.runBeforeMainModule.forEach(this._addRequireCall, this);
/* $FlowFixMe: this is unsound, as nothing enforces the module ID to have
* been set beforehand. */
this._addRequireCall(super.getMainModuleId());
}
super.finalize(options);
}
_addRequireCall(moduleId) {
_addRequireCall(moduleId: string) {
const code = `;require(${JSON.stringify(moduleId)});`;
const name = 'require-' + moduleId;
super.addModule(new ModuleTransport({
@ -88,12 +123,12 @@ class Bundle extends BundleBase {
return this._inlineSourceMap;
}
getSource(options) {
getSource(options: GetSourceOptions) {
super.assertFinalized();
options = options || {};
let source = super.getSource();
let source = super.getSource(options);
if (options.inlineSourceMap) {
source += SOURCEMAPPING_URL + this._getInlineSourceMap(options.dev);
@ -104,7 +139,7 @@ class Bundle extends BundleBase {
return source;
}
getUnbundle(type) {
getUnbundle() {
this.assertFinalized();
if (!this._ramBundle) {
const modules = this.getModules().slice();
@ -122,7 +157,7 @@ class Bundle extends BundleBase {
groups = createGroups(ramGroups || [], lazyModules);
}
return groups;
}
},
};
}
@ -166,7 +201,7 @@ class Bundle extends BundleBase {
return result;
}
getSourceMap(options) {
getSourceMap(options: {excludeSource?: boolean}) {
super.assertFinalized();
if (this._shouldCombineSourceMaps) {
@ -182,12 +217,14 @@ class Bundle extends BundleBase {
names: [],
mappings: mappings,
sourcesContent: options.excludeSource
? [] : modules.map(module => module.sourceCode)
? [] : modules.map(module => module.sourceCode),
};
return map;
}
getEtag() {
/* $FlowFixMe: we must pass options, or rename the
* base `getSource` function, as it does not actually need options. */
var eTag = crypto.createHash('md5').update(this.getSource()).digest('hex');
return eTag;
}
@ -254,6 +291,7 @@ class Bundle extends BundleBase {
getDebugInfo() {
return [
/* $FlowFixMe: this is unsound as the module ID could be unset. */
'<div><h3>Main Module:</h3> ' + super.getMainModuleId() + '</div>',
'<style>',
'pre.collapsed {',
@ -274,7 +312,7 @@ class Bundle extends BundleBase {
].join('\n');
}
setRamGroups(ramGroups) {
setRamGroups(ramGroups: Array<string>) {
this._ramGroups = ramGroups;
}
@ -339,7 +377,7 @@ function * filter(iterator, predicate) {
}
}
function * subtree(moduleTransport, moduleTransportsByPath, seen = new Set()) {
function * subtree(moduleTransport: ModuleTransport, moduleTransportsByPath, seen = new Set()) {
seen.add(moduleTransport.id);
for (const [, {path}] of moduleTransport.meta.dependencyPairs || []) {
const dependency = moduleTransportsByPath.get(path);
@ -361,7 +399,7 @@ class ArrayMap extends Map {
}
}
function createGroups(ramGroups, lazyModules) {
function createGroups(ramGroups: Array<string>, lazyModules) {
// build two maps that allow to lookup module data
// by path or (numeric) module id;
const byPath = new Map();
@ -400,12 +438,14 @@ function createGroups(ramGroups, lazyModules) {
const doubles = filter(all, ([, parents]) => parents.length > 1);
for (const [moduleId, parents] of doubles) {
// remove them from their groups
/* $FlowFixMe: this assumes the element exists. */
parents.forEach(p => result.get(p).delete(moduleId));
// print a warning for each removed module
const parentNames = parents.map(byId.get, byId);
const lastName = parentNames.pop();
console.warn(
/* $FlowFixMe: this assumes the element exists. */
`Module ${byId.get(moduleId)} belongs to groups ${
parentNames.join(', ')}, and ${lastName
}. Removing it from all groups.`

View File

@ -12,11 +12,22 @@
const ModuleTransport = require('../lib/ModuleTransport');
export type FinalizeOptions = {
allowUpdates?: boolean,
runBeforeMainModule?: Array<mixed>,
runMainModule?: boolean,
};
export type GetSourceOptions = {
inlineSourceMap: boolean,
dev: boolean,
};
class BundleBase {
_assets: Array<mixed>;
_finalized: boolean;
_mainModuleId: mixed | void;
_mainModuleId: string | void;
_modules: Array<ModuleTransport>;
_source: ?string;
@ -35,7 +46,7 @@ class BundleBase {
return this._mainModuleId;
}
setMainModuleId(moduleId: mixed) {
setMainModuleId(moduleId: string) {
this._mainModuleId = moduleId;
}
@ -67,7 +78,7 @@ class BundleBase {
this._assets.push(asset);
}
finalize(options: {allowUpdates?: boolean}) {
finalize(options: FinalizeOptions) {
if (!options.allowUpdates) {
Object.freeze(this._modules);
Object.freeze(this._assets);
@ -76,7 +87,7 @@ class BundleBase {
this._finalized = true;
}
getSource() {
getSource(options: GetSourceOptions) {
this.assertFinalized();
if (this._source) {
@ -97,9 +108,9 @@ class BundleBase {
}
}
setRamGroups() {}
setRamGroups(ramGroups: Array<string>) {}
toJSON() {
toJSON(): mixed {
return {
modules: this._modules,
assets: this._assets,