mirror of https://github.com/status-im/metro.git
Make the delta protocol more robust by detecting when a client misses a delta
Reviewed By: davidaurelio Differential Revision: D7031664 fbshipit-source-id: 22985ba45aa330780c8ddc44c07f5557e9e0d9c4
This commit is contained in:
parent
a7fdc0f3c1
commit
ff6f6ef1cf
|
@ -12,6 +12,7 @@
|
|||
|
||||
const {
|
||||
initialTraverseDependencies,
|
||||
reorderDependencies,
|
||||
traverseDependencies,
|
||||
} = require('./traverseDependencies');
|
||||
const {EventEmitter} = require('events');
|
||||
|
@ -85,7 +86,7 @@ class DeltaCalculator extends EventEmitter {
|
|||
* Main method to calculate the delta of modules. It returns a DeltaResult,
|
||||
* which contain the modified/added modules and the removed modules.
|
||||
*/
|
||||
async getDelta(): Promise<DeltaResult> {
|
||||
async getDelta({reset}: {reset: boolean}): Promise<DeltaResult> {
|
||||
// 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).
|
||||
if (this._currentBuildPromise) {
|
||||
|
@ -134,6 +135,20 @@ class DeltaCalculator extends EventEmitter {
|
|||
this._currentBuildPromise = null;
|
||||
}
|
||||
|
||||
// Return all the modules if the client requested a reset delta.
|
||||
if (reset) {
|
||||
return {
|
||||
modified: reorderDependencies(
|
||||
this._dependencyEdges.get(
|
||||
this._dependencyGraph.getAbsolutePath(this._options.entryFile),
|
||||
),
|
||||
this._dependencyEdges,
|
||||
),
|
||||
deleted: new Set(),
|
||||
reset: true,
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ class DeltaPatcher {
|
|||
pre: new Map(),
|
||||
post: new Map(),
|
||||
modules: new Map(),
|
||||
id: undefined,
|
||||
};
|
||||
_initialized = false;
|
||||
_lastNumModifiedFiles = 0;
|
||||
|
@ -62,6 +63,7 @@ class DeltaPatcher {
|
|||
pre: new Map(),
|
||||
post: new Map(),
|
||||
modules: new Map(),
|
||||
id: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -76,9 +78,15 @@ class DeltaPatcher {
|
|||
this._patchMap(this._lastBundle.post, deltaBundle.post);
|
||||
this._patchMap(this._lastBundle.modules, deltaBundle.delta);
|
||||
|
||||
this._lastBundle.id = deltaBundle.id;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
getLastBundleId(): ?string {
|
||||
return this._lastBundle.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of modified files in the last received Delta. This is
|
||||
* currently used to populate the `X-Metro-Files-Changed-Count` HTTP header
|
||||
|
|
|
@ -14,6 +14,7 @@ const DeltaCalculator = require('./DeltaCalculator');
|
|||
|
||||
const addParamsToDefineCall = require('../lib/addParamsToDefineCall');
|
||||
const createModuleIdFactory = require('../lib/createModuleIdFactory');
|
||||
const crypto = require('crypto');
|
||||
const defaults = require('../defaults');
|
||||
const getPreludeCode = require('../lib/getPreludeCode');
|
||||
const nullthrows = require('fbjs/lib/nullthrows');
|
||||
|
@ -24,7 +25,8 @@ import type Bundler from '../Bundler';
|
|||
import type {Options as JSTransformerOptions} from '../JSTransformer/worker';
|
||||
import type DependencyGraph from '../node-haste/DependencyGraph';
|
||||
import type Module from '../node-haste/Module';
|
||||
import type {Options as BundleOptions, MainOptions} from './';
|
||||
import type {BundleOptions} from '../shared/types.flow';
|
||||
import type {MainOptions} from './';
|
||||
import type {DependencyEdge, DependencyEdges} from './traverseDependencies';
|
||||
import type {MetroSourceMapSegmentTuple} from 'metro-source-map';
|
||||
|
||||
|
@ -48,6 +50,7 @@ export type DeltaEntry = {|
|
|||
export type DeltaEntries = Map<number, ?DeltaEntry>;
|
||||
|
||||
export type DeltaTransformResponse = {|
|
||||
+id: string,
|
||||
+pre: DeltaEntries,
|
||||
+post: DeltaEntries,
|
||||
+delta: DeltaEntries,
|
||||
|
@ -82,6 +85,7 @@ class DeltaTransformer extends EventEmitter {
|
|||
_deltaCalculator: DeltaCalculator;
|
||||
_bundleOptions: BundleOptions;
|
||||
_currentBuildPromise: ?Promise<DeltaTransformResponse>;
|
||||
_lastSequenceId: ?string;
|
||||
|
||||
constructor(
|
||||
bundler: Bundler,
|
||||
|
@ -153,7 +157,7 @@ class DeltaTransformer extends EventEmitter {
|
|||
if (!this._deltaCalculator.getDependencyEdges().size) {
|
||||
// If by any means the dependency graph has not been initialized, call
|
||||
// getDelta() to initialize it.
|
||||
await this._getDelta();
|
||||
await this._getDelta({reset: false});
|
||||
}
|
||||
|
||||
return this._getDependencies;
|
||||
|
@ -167,7 +171,7 @@ class DeltaTransformer extends EventEmitter {
|
|||
if (!this._deltaCalculator.getDependencyEdges().size) {
|
||||
// If by any means the dependency graph has not been initialized, call
|
||||
// getDelta() to initialize it.
|
||||
await this._getDelta();
|
||||
await this._getDelta({reset: false});
|
||||
}
|
||||
|
||||
const dependencyEdges = this._deltaCalculator.getDependencyEdges();
|
||||
|
@ -204,7 +208,11 @@ class DeltaTransformer extends EventEmitter {
|
|||
* which contain the source code of the modified and added modules and the
|
||||
* list of removed modules.
|
||||
*/
|
||||
async getDelta(): Promise<DeltaTransformResponse> {
|
||||
async getDelta(sequenceId: ?string): Promise<DeltaTransformResponse> {
|
||||
// If the passed sequenceId is different than the last calculated one,
|
||||
// return a reset delta (since that means that the client is desynchronized)
|
||||
const reset = !!this._lastSequenceId && sequenceId !== this._lastSequenceId;
|
||||
|
||||
// If there is already a build in progress, wait until it finish to start
|
||||
// processing a new one (delta transformer doesn't support concurrent
|
||||
// builds).
|
||||
|
@ -212,7 +220,7 @@ class DeltaTransformer extends EventEmitter {
|
|||
await this._currentBuildPromise;
|
||||
}
|
||||
|
||||
this._currentBuildPromise = this._getDelta();
|
||||
this._currentBuildPromise = this._getDelta({reset});
|
||||
|
||||
let result;
|
||||
|
||||
|
@ -225,58 +233,57 @@ class DeltaTransformer extends EventEmitter {
|
|||
return result;
|
||||
}
|
||||
|
||||
async _getDelta(): Promise<DeltaTransformResponse> {
|
||||
async _getDelta({
|
||||
reset: resetDelta,
|
||||
}: {
|
||||
reset: boolean,
|
||||
}): Promise<DeltaTransformResponse> {
|
||||
// Calculate the delta of modules.
|
||||
const {modified, deleted, reset} = await this._deltaCalculator.getDelta();
|
||||
const {modified, deleted, reset} = await this._deltaCalculator.getDelta({
|
||||
reset: resetDelta,
|
||||
});
|
||||
|
||||
const transformerOptions = await this._deltaCalculator.getTransformerOptions();
|
||||
const dependencyEdges = this._deltaCalculator.getDependencyEdges();
|
||||
|
||||
try {
|
||||
// Return the source code that gets prepended to all the modules. This
|
||||
// contains polyfills and startup code (like the require() implementation).
|
||||
const prependSources = reset
|
||||
? await this._getPrepend(transformerOptions, dependencyEdges)
|
||||
: new Map();
|
||||
// Return the source code that gets prepended to all the modules. This
|
||||
// contains polyfills and startup code (like the require() implementation).
|
||||
const prependSources = reset
|
||||
? await this._getPrepend(transformerOptions, dependencyEdges)
|
||||
: new Map();
|
||||
|
||||
// Precalculate all module ids sequentially. We do this to be sure that the
|
||||
// mapping between module -> moduleId is deterministic between runs.
|
||||
const modules = Array.from(modified.values());
|
||||
modules.forEach(module => this._getModuleId(module.path));
|
||||
// Precalculate all module ids sequentially. We do this to be sure that the
|
||||
// mapping between module -> moduleId is deterministic between runs.
|
||||
const modules = Array.from(modified.values());
|
||||
modules.forEach(module => this._getModuleId(module.path));
|
||||
|
||||
// Get the transformed source code of each modified/added module.
|
||||
const modifiedDelta = await this._transformModules(
|
||||
modules,
|
||||
transformerOptions,
|
||||
dependencyEdges,
|
||||
);
|
||||
// Get the transformed source code of each modified/added module.
|
||||
const modifiedDelta = await this._transformModules(
|
||||
modules,
|
||||
transformerOptions,
|
||||
dependencyEdges,
|
||||
);
|
||||
|
||||
deleted.forEach(id => {
|
||||
modifiedDelta.set(this._getModuleId(id), null);
|
||||
});
|
||||
deleted.forEach(id => {
|
||||
modifiedDelta.set(this._getModuleId(id), null);
|
||||
});
|
||||
|
||||
// Return the source code that gets appended to all the modules. This
|
||||
// contains the require() calls to startup the execution of the modules.
|
||||
const appendSources = reset
|
||||
? await this._getAppend(dependencyEdges)
|
||||
: new Map();
|
||||
// Return the source code that gets appended to all the modules. This
|
||||
// contains the require() calls to startup the execution of the modules.
|
||||
const appendSources = reset
|
||||
? await this._getAppend(dependencyEdges)
|
||||
: new Map();
|
||||
|
||||
return {
|
||||
pre: prependSources,
|
||||
post: appendSources,
|
||||
delta: modifiedDelta,
|
||||
reset,
|
||||
};
|
||||
} catch (e) {
|
||||
// If any unexpected error happens while creating the bundle, the client
|
||||
// is going to lose that specific delta, while the DeltaCalulator has
|
||||
// already processed the changes. This will make that change to be lost,
|
||||
// which can cause the final bundle to be invalid. In order to avoid that,
|
||||
// we just reset the delta calculator when this happens.
|
||||
this._deltaCalculator.reset();
|
||||
// generate a random
|
||||
this._lastSequenceId = crypto.randomBytes(8).toString('hex');
|
||||
|
||||
throw e;
|
||||
}
|
||||
return {
|
||||
pre: prependSources,
|
||||
post: appendSources,
|
||||
delta: modifiedDelta,
|
||||
reset,
|
||||
id: this._lastSequenceId,
|
||||
};
|
||||
}
|
||||
|
||||
_getDependencies = (path: string): Set<string> => {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
const DeltaPatcher = require('./DeltaPatcher');
|
||||
|
||||
const stableHash = require('metro-cache/src/stableHash');
|
||||
const toLocalPath = require('../node-haste/lib/toLocalPath');
|
||||
|
||||
const {getAssetData} = require('../Assets');
|
||||
|
@ -19,16 +20,15 @@ const {createRamBundleGroups} = require('../Bundler/util');
|
|||
const {fromRawMappings} = require('metro-source-map');
|
||||
|
||||
import type {AssetData} from '../Assets';
|
||||
import type {BundleOptions} from '../shared/types.flow';
|
||||
import type {ModuleTransportLike} from '../shared/types.flow';
|
||||
import type DeltaBundler, {Options as BuildOptions} from './';
|
||||
import type {BundleOptions, ModuleTransportLike} from '../shared/types.flow';
|
||||
import type DeltaBundler from './';
|
||||
import type DeltaTransformer, {
|
||||
DeltaEntry,
|
||||
DeltaTransformResponse,
|
||||
} from './DeltaTransformer';
|
||||
import type {BabelSourceMap} from '@babel/core';
|
||||
|
||||
export type Options = BundleOptions & {
|
||||
export type DeltaOptions = BundleOptions & {
|
||||
deltaBundleId: ?string,
|
||||
};
|
||||
|
||||
|
@ -49,16 +49,17 @@ export type RamBundleInfo = {
|
|||
|
||||
async function deltaBundle(
|
||||
deltaBundler: DeltaBundler,
|
||||
options: Options,
|
||||
clientId: string,
|
||||
options: DeltaOptions,
|
||||
): Promise<{bundle: string, numModifiedFiles: number}> {
|
||||
const {id, delta} = await _build(deltaBundler, options);
|
||||
const {delta} = await _build(deltaBundler, clientId, options);
|
||||
|
||||
function stringifyModule([id, module]) {
|
||||
return [id, module ? module.code : undefined];
|
||||
}
|
||||
|
||||
const bundle = JSON.stringify({
|
||||
id,
|
||||
id: delta.id,
|
||||
pre: Array.from(delta.pre).map(stringifyModule),
|
||||
post: Array.from(delta.post).map(stringifyModule),
|
||||
delta: Array.from(delta.delta).map(stringifyModule),
|
||||
|
@ -73,7 +74,7 @@ async function deltaBundle(
|
|||
|
||||
async function fullSourceMap(
|
||||
deltaBundler: DeltaBundler,
|
||||
options: Options,
|
||||
options: BundleOptions,
|
||||
): Promise<string> {
|
||||
const {modules} = await _getAllModules(deltaBundler, options);
|
||||
|
||||
|
@ -84,7 +85,7 @@ async function fullSourceMap(
|
|||
|
||||
async function fullSourceMapObject(
|
||||
deltaBundler: DeltaBundler,
|
||||
options: Options,
|
||||
options: BundleOptions,
|
||||
): Promise<BabelSourceMap> {
|
||||
const {modules} = await _getAllModules(deltaBundler, options);
|
||||
|
||||
|
@ -98,7 +99,7 @@ async function fullSourceMapObject(
|
|||
*/
|
||||
async function fullBundle(
|
||||
deltaBundler: DeltaBundler,
|
||||
options: Options,
|
||||
options: BundleOptions,
|
||||
): Promise<{bundle: string, numModifiedFiles: number, lastModified: Date}> {
|
||||
const {modules, numModifiedFiles, lastModified} = await _getAllModules(
|
||||
deltaBundler,
|
||||
|
@ -116,7 +117,7 @@ async function fullBundle(
|
|||
|
||||
async function getAllModules(
|
||||
deltaBundler: DeltaBundler,
|
||||
options: Options,
|
||||
options: BundleOptions,
|
||||
): Promise<$ReadOnlyArray<DeltaEntry>> {
|
||||
const {modules} = await _getAllModules(deltaBundler, options);
|
||||
|
||||
|
@ -125,16 +126,30 @@ async function getAllModules(
|
|||
|
||||
async function _getAllModules(
|
||||
deltaBundler: DeltaBundler,
|
||||
options: Options,
|
||||
options: BundleOptions,
|
||||
): Promise<{
|
||||
modules: $ReadOnlyArray<DeltaEntry>,
|
||||
numModifiedFiles: number,
|
||||
lastModified: Date,
|
||||
deltaTransformer: DeltaTransformer,
|
||||
}> {
|
||||
const {id, delta, deltaTransformer} = await _build(deltaBundler, options);
|
||||
const hashedOptions = options;
|
||||
delete hashedOptions.sourceMapUrl;
|
||||
|
||||
const deltaPatcher = DeltaPatcher.get(id);
|
||||
const clientId = '__SERVER__' + stableHash(hashedOptions).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)
|
||||
|
@ -150,7 +165,7 @@ async function _getAllModules(
|
|||
|
||||
async function getRamBundleInfo(
|
||||
deltaBundler: DeltaBundler,
|
||||
options: Options,
|
||||
options: BundleOptions,
|
||||
): Promise<RamBundleInfo> {
|
||||
const {modules, deltaTransformer} = await _getAllModules(
|
||||
deltaBundler,
|
||||
|
@ -226,7 +241,7 @@ async function getRamBundleInfo(
|
|||
|
||||
async function getAssets(
|
||||
deltaBundler: DeltaBundler,
|
||||
options: Options,
|
||||
options: BundleOptions,
|
||||
): Promise<$ReadOnlyArray<AssetData>> {
|
||||
const {modules} = await _getAllModules(deltaBundler, options);
|
||||
|
||||
|
@ -254,20 +269,20 @@ async function getAssets(
|
|||
|
||||
async function _build(
|
||||
deltaBundler: DeltaBundler,
|
||||
options: BuildOptions,
|
||||
clientId: string,
|
||||
options: DeltaOptions,
|
||||
): Promise<{
|
||||
id: string,
|
||||
delta: DeltaTransformResponse,
|
||||
deltaTransformer: DeltaTransformer,
|
||||
}> {
|
||||
const {deltaTransformer, id} = await deltaBundler.getDeltaTransformer(
|
||||
const deltaTransformer = await deltaBundler.getDeltaTransformer(
|
||||
clientId,
|
||||
options,
|
||||
);
|
||||
|
||||
const delta = await deltaTransformer.getDelta();
|
||||
const delta = await deltaTransformer.getDelta(options.deltaBundleId);
|
||||
|
||||
return {
|
||||
id,
|
||||
delta,
|
||||
deltaTransformer,
|
||||
};
|
||||
|
|
|
@ -43,27 +43,27 @@ describe('DeltaBundler', () => {
|
|||
});
|
||||
|
||||
it('should create a new transformer the first time it gets called', async () => {
|
||||
await deltaBundler.getDeltaTransformer({deltaBundleId: 10});
|
||||
await deltaBundler.getDeltaTransformer('foo', {deltaBundleId: 10});
|
||||
|
||||
expect(DeltaTransformer.create.mock.calls.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should reuse the same transformer after a second call', async () => {
|
||||
await deltaBundler.getDeltaTransformer({deltaBundleId: 10});
|
||||
await deltaBundler.getDeltaTransformer({deltaBundleId: 10});
|
||||
await deltaBundler.getDeltaTransformer('foo', {deltaBundleId: 10});
|
||||
await deltaBundler.getDeltaTransformer('foo', {deltaBundleId: 20});
|
||||
|
||||
expect(DeltaTransformer.create.mock.calls.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should create different transformers when there is no delta bundle id', async () => {
|
||||
await deltaBundler.getDeltaTransformer({});
|
||||
await deltaBundler.getDeltaTransformer({});
|
||||
it('should create different transformers for different clients', async () => {
|
||||
await deltaBundler.getDeltaTransformer('foo', {});
|
||||
await deltaBundler.getDeltaTransformer('bar', {});
|
||||
|
||||
expect(DeltaTransformer.create.mock.calls.length).toBe(2);
|
||||
});
|
||||
|
||||
it('should reset everything after calling end()', async () => {
|
||||
await deltaBundler.getDeltaTransformer({deltaBundleId: 10});
|
||||
await deltaBundler.getDeltaTransformer('foo', {deltaBundleId: 10});
|
||||
|
||||
deltaBundler.end();
|
||||
|
||||
|
|
|
@ -13,15 +13,16 @@
|
|||
jest.mock('../../Bundler');
|
||||
jest.mock('../traverseDependencies');
|
||||
|
||||
const {
|
||||
initialTraverseDependencies,
|
||||
reorderDependencies,
|
||||
traverseDependencies,
|
||||
} = require('../traverseDependencies');
|
||||
|
||||
const Bundler = require('../../Bundler');
|
||||
const {EventEmitter} = require('events');
|
||||
|
||||
const DeltaCalculator = require('../DeltaCalculator');
|
||||
const {
|
||||
initialTraverseDependencies,
|
||||
traverseDependencies,
|
||||
} = require('../traverseDependencies');
|
||||
|
||||
const getTransformOptions = require('../../__fixtures__/getTransformOptions');
|
||||
|
||||
describe('DeltaCalculator', () => {
|
||||
|
@ -38,8 +39,7 @@ describe('DeltaCalculator', () => {
|
|||
let deltaCalculator;
|
||||
let fileWatcher;
|
||||
let mockedDependencies;
|
||||
|
||||
const bundlerMock = new Bundler();
|
||||
let bundlerMock;
|
||||
|
||||
const options = {
|
||||
assetPlugins: [],
|
||||
|
@ -72,6 +72,8 @@ describe('DeltaCalculator', () => {
|
|||
}
|
||||
|
||||
beforeEach(async () => {
|
||||
bundlerMock = new Bundler();
|
||||
|
||||
mockedDependencies = [entryModule, moduleFoo, moduleBar, moduleBaz];
|
||||
|
||||
fileWatcher = new EventEmitter();
|
||||
|
@ -90,10 +92,29 @@ describe('DeltaCalculator', () => {
|
|||
|
||||
initialTraverseDependencies.mockImplementationOnce(
|
||||
async (path, dg, opt, edges) => {
|
||||
edgeModule = {...entryModule};
|
||||
edgeFoo = {...moduleFoo, inverseDependencies: ['/bundle']};
|
||||
edgeBar = {...moduleBar, inverseDependencies: ['/bundle']};
|
||||
edgeBaz = {...moduleBaz, inverseDependencies: ['/bundle']};
|
||||
edgeModule = {
|
||||
...entryModule,
|
||||
dependencies: new Map([
|
||||
['foo', '/foo'],
|
||||
['bar', '/bar'],
|
||||
['baz', '/baz'],
|
||||
]),
|
||||
};
|
||||
edgeFoo = {
|
||||
...moduleFoo,
|
||||
dependencies: new Map(),
|
||||
inverseDependencies: ['/bundle'],
|
||||
};
|
||||
edgeBar = {
|
||||
...moduleBar,
|
||||
dependencies: new Map(),
|
||||
inverseDependencies: ['/bundle'],
|
||||
};
|
||||
edgeBaz = {
|
||||
...moduleBaz,
|
||||
dependencies: new Map(),
|
||||
inverseDependencies: ['/bundle'],
|
||||
};
|
||||
|
||||
edges.set('/bundle', edgeModule);
|
||||
edges.set('/foo', edgeFoo);
|
||||
|
@ -131,8 +152,10 @@ describe('DeltaCalculator', () => {
|
|||
});
|
||||
|
||||
afterEach(() => {
|
||||
initialTraverseDependencies.mockReset();
|
||||
deltaCalculator.end();
|
||||
|
||||
traverseDependencies.mockReset();
|
||||
initialTraverseDependencies.mockReset();
|
||||
});
|
||||
|
||||
it('should start listening for file changes after being initialized', async () => {
|
||||
|
@ -146,11 +169,44 @@ describe('DeltaCalculator', () => {
|
|||
});
|
||||
|
||||
it('should include the entry file when calculating the initial bundle', async () => {
|
||||
const result = await deltaCalculator.getDelta();
|
||||
const result = await deltaCalculator.getDelta({reset: false});
|
||||
|
||||
expect(result).toEqual({
|
||||
modified: new Map([
|
||||
['/bundle', entryModule],
|
||||
['/bundle', edgeModule],
|
||||
['/foo', edgeFoo],
|
||||
['/bar', edgeBar],
|
||||
['/baz', edgeBaz],
|
||||
]),
|
||||
deleted: new Set(),
|
||||
reset: true,
|
||||
});
|
||||
|
||||
jest.runAllTicks();
|
||||
});
|
||||
|
||||
it('should return an empty delta when there are no changes', async () => {
|
||||
await deltaCalculator.getDelta({reset: false});
|
||||
|
||||
expect(await deltaCalculator.getDelta({reset: false})).toEqual({
|
||||
modified: new Map(),
|
||||
deleted: new Set(),
|
||||
reset: false,
|
||||
});
|
||||
|
||||
expect(traverseDependencies.mock.calls.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should return a full delta when passing reset=true', async () => {
|
||||
reorderDependencies.mockImplementation((_, edges) => edges);
|
||||
|
||||
await deltaCalculator.getDelta({reset: false});
|
||||
|
||||
const result = await deltaCalculator.getDelta({reset: true});
|
||||
|
||||
expect(result).toEqual({
|
||||
modified: new Map([
|
||||
['/bundle', edgeModule],
|
||||
['/foo', edgeFoo],
|
||||
['/bar', edgeBar],
|
||||
['/baz', edgeBaz],
|
||||
|
@ -160,20 +216,8 @@ describe('DeltaCalculator', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should return an empty delta when there are no changes', async () => {
|
||||
await deltaCalculator.getDelta();
|
||||
|
||||
expect(await deltaCalculator.getDelta()).toEqual({
|
||||
modified: new Map(),
|
||||
deleted: new Set(),
|
||||
reset: false,
|
||||
});
|
||||
|
||||
expect(traverseDependencies.mock.calls.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should calculate a delta after a simple modification', async () => {
|
||||
await deltaCalculator.getDelta();
|
||||
await deltaCalculator.getDelta({reset: false});
|
||||
|
||||
fileWatcher.emit('change', {eventsQueue: [{filePath: '/foo'}]});
|
||||
|
||||
|
@ -184,7 +228,7 @@ describe('DeltaCalculator', () => {
|
|||
}),
|
||||
);
|
||||
|
||||
const result = await deltaCalculator.getDelta();
|
||||
const result = await deltaCalculator.getDelta({reset: false});
|
||||
|
||||
expect(result).toEqual({
|
||||
modified: new Map([['/foo', edgeFoo]]),
|
||||
|
@ -197,7 +241,7 @@ describe('DeltaCalculator', () => {
|
|||
|
||||
it('should calculate a delta after removing a dependency', async () => {
|
||||
// Get initial delta
|
||||
await deltaCalculator.getDelta();
|
||||
await deltaCalculator.getDelta({reset: false});
|
||||
|
||||
fileWatcher.emit('change', {eventsQueue: [{filePath: '/foo'}]});
|
||||
|
||||
|
@ -208,7 +252,7 @@ describe('DeltaCalculator', () => {
|
|||
}),
|
||||
);
|
||||
|
||||
const result = await deltaCalculator.getDelta();
|
||||
const result = await deltaCalculator.getDelta({reset: false});
|
||||
|
||||
expect(result).toEqual({
|
||||
modified: new Map([['/foo', edgeFoo]]),
|
||||
|
@ -221,7 +265,7 @@ describe('DeltaCalculator', () => {
|
|||
|
||||
it('should calculate a delta after adding/removing dependencies', async () => {
|
||||
// Get initial delta
|
||||
await deltaCalculator.getDelta();
|
||||
await deltaCalculator.getDelta({reset: false});
|
||||
|
||||
fileWatcher.emit('change', {eventsQueue: [{filePath: '/foo'}]});
|
||||
|
||||
|
@ -239,7 +283,7 @@ describe('DeltaCalculator', () => {
|
|||
};
|
||||
});
|
||||
|
||||
const result = await deltaCalculator.getDelta();
|
||||
const result = await deltaCalculator.getDelta({reset: false});
|
||||
expect(result).toEqual({
|
||||
modified: new Map([['/foo', edgeFoo], ['/qux', edgeQux]]),
|
||||
deleted: new Set(['/bar', '/baz']),
|
||||
|
@ -248,7 +292,7 @@ describe('DeltaCalculator', () => {
|
|||
});
|
||||
|
||||
it('should emit an event when there is a relevant file change', async done => {
|
||||
await deltaCalculator.getDelta();
|
||||
await deltaCalculator.getDelta({reset: false});
|
||||
|
||||
deltaCalculator.on('change', () => done());
|
||||
|
||||
|
@ -259,7 +303,7 @@ describe('DeltaCalculator', () => {
|
|||
jest.useFakeTimers();
|
||||
|
||||
const onChangeFile = jest.fn();
|
||||
await deltaCalculator.getDelta();
|
||||
await deltaCalculator.getDelta({reset: false});
|
||||
|
||||
deltaCalculator.on('delete', onChangeFile);
|
||||
|
||||
|
@ -273,20 +317,24 @@ describe('DeltaCalculator', () => {
|
|||
});
|
||||
|
||||
it('should retry to build the last delta after getting an error', async () => {
|
||||
await deltaCalculator.getDelta();
|
||||
await deltaCalculator.getDelta({reset: false});
|
||||
|
||||
fileWatcher.emit('change', {eventsQueue: [{filePath: '/foo'}]});
|
||||
|
||||
traverseDependencies.mockReturnValue(Promise.reject(new Error()));
|
||||
|
||||
await expect(deltaCalculator.getDelta()).rejects.toBeInstanceOf(Error);
|
||||
await expect(
|
||||
deltaCalculator.getDelta({reset: false}),
|
||||
).rejects.toBeInstanceOf(Error);
|
||||
|
||||
// This second time it should still throw an error.
|
||||
await expect(deltaCalculator.getDelta()).rejects.toBeInstanceOf(Error);
|
||||
await expect(
|
||||
deltaCalculator.getDelta({reset: false}),
|
||||
).rejects.toBeInstanceOf(Error);
|
||||
});
|
||||
|
||||
it('should never try to traverse a file after deleting it', async () => {
|
||||
await deltaCalculator.getDelta();
|
||||
await deltaCalculator.getDelta({reset: false});
|
||||
|
||||
// First modify the file
|
||||
fileWatcher.emit('change', {eventsQueue: [{filePath: '/foo'}]});
|
||||
|
@ -303,7 +351,7 @@ describe('DeltaCalculator', () => {
|
|||
}),
|
||||
);
|
||||
|
||||
expect(await deltaCalculator.getDelta()).toEqual({
|
||||
expect(await deltaCalculator.getDelta({reset: false})).toEqual({
|
||||
modified: new Map([['/bundle', edgeModule]]),
|
||||
deleted: new Set(['/foo']),
|
||||
reset: false,
|
||||
|
@ -314,7 +362,7 @@ describe('DeltaCalculator', () => {
|
|||
});
|
||||
|
||||
it('should not do unnecessary work when adding a file after deleting it', async () => {
|
||||
await deltaCalculator.getDelta();
|
||||
await deltaCalculator.getDelta({reset: false});
|
||||
|
||||
// First delete a file
|
||||
fileWatcher.emit('change', {
|
||||
|
@ -331,7 +379,7 @@ describe('DeltaCalculator', () => {
|
|||
}),
|
||||
);
|
||||
|
||||
await deltaCalculator.getDelta();
|
||||
await deltaCalculator.getDelta({reset: false});
|
||||
|
||||
expect(traverseDependencies).toHaveBeenCalledTimes(1);
|
||||
expect(traverseDependencies.mock.calls[0][0]).toEqual(['/foo']);
|
||||
|
|
|
@ -28,6 +28,7 @@ describe('Serializers', () => {
|
|||
let Serializers;
|
||||
|
||||
const deltaResponse = {
|
||||
id: '1234',
|
||||
pre: new Map([[1, {type: 'script', code: 'pre;', id: 1, path: '/pre.js'}]]),
|
||||
post: new Map([[2, {type: 'require', code: 'post;', id: 2, path: '/p'}]]),
|
||||
delta: new Map([
|
||||
|
@ -58,12 +59,9 @@ describe('Serializers', () => {
|
|||
deltaBundler = {
|
||||
async getDeltaTransformer() {
|
||||
return {
|
||||
id: '1234',
|
||||
deltaTransformer: {
|
||||
getDelta,
|
||||
getDependenciesFn,
|
||||
getRamOptions,
|
||||
},
|
||||
getDelta,
|
||||
getDependenciesFn,
|
||||
getRamOptions,
|
||||
};
|
||||
},
|
||||
getPostProcessModulesFn() {
|
||||
|
@ -91,12 +89,13 @@ describe('Serializers', () => {
|
|||
|
||||
it('should return the stringified delta bundle', async () => {
|
||||
expect(
|
||||
await Serializers.deltaBundle(deltaBundler, {deltaBundleId: 10}),
|
||||
await Serializers.deltaBundle(deltaBundler, 'foo', {deltaBundleId: 10}),
|
||||
).toMatchSnapshot();
|
||||
|
||||
// Simulate a delta with some changes now
|
||||
getDelta.mockReturnValueOnce(
|
||||
Promise.resolve({
|
||||
id: '1234',
|
||||
delta: new Map([[3, {code: 'modified module;'}], [4, null]]),
|
||||
pre: new Map(),
|
||||
post: new Map(),
|
||||
|
@ -105,17 +104,16 @@ describe('Serializers', () => {
|
|||
);
|
||||
|
||||
expect(
|
||||
await Serializers.deltaBundle(deltaBundler, {deltaBundleId: 10}),
|
||||
await Serializers.deltaBundle(deltaBundler, 'foo', {deltaBundleId: 10}),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should build the full JS bundle', async () => {
|
||||
expect(
|
||||
await Serializers.fullBundle(deltaBundler, {deltaBundleId: 10}),
|
||||
).toMatchSnapshot();
|
||||
expect(await Serializers.fullBundle(deltaBundler, {})).toMatchSnapshot();
|
||||
|
||||
getDelta.mockReturnValueOnce(
|
||||
Promise.resolve({
|
||||
id: '1234',
|
||||
delta: new Map([[3, {code: 'modified module;'}], [4, null]]),
|
||||
pre: new Map([[5, {code: 'more pre;'}]]),
|
||||
post: new Map([[6, {code: 'bananas;'}], [7, {code: 'apples;'}]]),
|
||||
|
@ -126,7 +124,6 @@ describe('Serializers', () => {
|
|||
|
||||
expect(
|
||||
await Serializers.fullBundle(deltaBundler, {
|
||||
deltaBundleId: 10,
|
||||
sourceMapUrl: 'http://localhost:8081/myBundle.js',
|
||||
}),
|
||||
).toMatchSnapshot();
|
||||
|
@ -135,12 +132,11 @@ describe('Serializers', () => {
|
|||
// This test actually does not test the sourcemaps generation logic, which
|
||||
// is already tested in the source-map file.
|
||||
it('should build the full Source Maps', async () => {
|
||||
expect(
|
||||
await Serializers.fullSourceMap(deltaBundler, {deltaBundleId: 10}),
|
||||
).toMatchSnapshot();
|
||||
expect(await Serializers.fullSourceMap(deltaBundler, {})).toMatchSnapshot();
|
||||
|
||||
getDelta.mockReturnValueOnce(
|
||||
Promise.resolve({
|
||||
id: '1234',
|
||||
delta: new Map([[3, {code: 'modified module;'}], [4, null]]),
|
||||
pre: new Map([[5, {code: 'more pre;'}]]),
|
||||
post: new Map([[6, {code: 'bananas;'}], [7, {code: 'apples;'}]]),
|
||||
|
@ -149,15 +145,11 @@ describe('Serializers', () => {
|
|||
);
|
||||
setCurrentTime(CURRENT_TIME + 5000);
|
||||
|
||||
expect(
|
||||
await Serializers.fullSourceMap(deltaBundler, {deltaBundleId: 10}),
|
||||
).toMatchSnapshot();
|
||||
expect(await Serializers.fullSourceMap(deltaBundler, {})).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should return all the bundle modules', async () => {
|
||||
expect(
|
||||
await Serializers.getAllModules(deltaBundler, {deltaBundleId: 10}),
|
||||
).toMatchSnapshot();
|
||||
expect(await Serializers.getAllModules(deltaBundler, {})).toMatchSnapshot();
|
||||
|
||||
getDelta.mockReturnValueOnce(
|
||||
Promise.resolve({
|
||||
|
@ -168,14 +160,12 @@ describe('Serializers', () => {
|
|||
}),
|
||||
);
|
||||
|
||||
expect(
|
||||
await Serializers.getAllModules(deltaBundler, {deltaBundleId: 10}),
|
||||
).toMatchSnapshot();
|
||||
expect(await Serializers.getAllModules(deltaBundler, {})).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should return the RAM bundle info', async () => {
|
||||
expect(
|
||||
await Serializers.getRamBundleInfo(deltaBundler, {deltaBundleId: 10}),
|
||||
await Serializers.getRamBundleInfo(deltaBundler, {}),
|
||||
).toMatchSnapshot();
|
||||
|
||||
getDelta.mockReturnValueOnce(
|
||||
|
@ -198,7 +188,7 @@ describe('Serializers', () => {
|
|||
);
|
||||
|
||||
expect(
|
||||
await Serializers.getRamBundleInfo(deltaBundler, {deltaBundleId: 10}),
|
||||
await Serializers.getRamBundleInfo(deltaBundler, {}),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
|
@ -241,14 +231,12 @@ describe('Serializers', () => {
|
|||
);
|
||||
|
||||
expect(
|
||||
await Serializers.getRamBundleInfo(deltaBundler, {deltaBundleId: 10}),
|
||||
await Serializers.getRamBundleInfo(deltaBundler, {}),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should return the bundle assets', async () => {
|
||||
expect(
|
||||
await Serializers.getAllModules(deltaBundler, {deltaBundleId: 10}),
|
||||
).toMatchSnapshot();
|
||||
expect(await Serializers.getAllModules(deltaBundler, {})).toMatchSnapshot();
|
||||
|
||||
getDelta.mockReturnValueOnce(
|
||||
Promise.resolve({
|
||||
|
@ -261,12 +249,12 @@ describe('Serializers', () => {
|
|||
pre: new Map([[5, {code: 'more pre;'}]]),
|
||||
post: new Map([[6, {code: 'bananas;'}]]),
|
||||
inverseDependencies: [],
|
||||
reset: true,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(
|
||||
await Serializers.getAssets(deltaBundler, {
|
||||
deltaBundleId: 10,
|
||||
platform: 'ios',
|
||||
}),
|
||||
).toMatchSnapshot();
|
||||
|
@ -279,10 +267,6 @@ describe('Serializers', () => {
|
|||
);
|
||||
});
|
||||
|
||||
expect(
|
||||
await Serializers.getAllModules(deltaBundler, {
|
||||
deltaBundleId: 10,
|
||||
}),
|
||||
).toMatchSnapshot();
|
||||
expect(await Serializers.getAllModules(deltaBundler, {})).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -27,16 +27,11 @@ export type MainOptions = {|
|
|||
postProcessModules?: PostProcessModules,
|
||||
|};
|
||||
|
||||
export type Options = BundleOptions & {
|
||||
+deltaBundleId: ?string,
|
||||
};
|
||||
|
||||
/**
|
||||
* `DeltaBundler` uses the `DeltaTransformer` to build bundle deltas. This
|
||||
* module handles all the transformer instances so it can support multiple
|
||||
* concurrent clients requesting their own deltas. This is done through the
|
||||
* `deltaBundleId` options param (which maps a client to a specific delta
|
||||
* transformer).
|
||||
* `clientId` param (which maps a client to a specific delta transformer).
|
||||
*/
|
||||
class DeltaBundler {
|
||||
_bundler: Bundler;
|
||||
|
@ -59,18 +54,10 @@ class DeltaBundler {
|
|||
}
|
||||
|
||||
async getDeltaTransformer(
|
||||
options: Options,
|
||||
): Promise<{deltaTransformer: DeltaTransformer, id: string}> {
|
||||
let bundleId = options.deltaBundleId;
|
||||
|
||||
// If no bundle id is passed, generate a new one (which is going to be
|
||||
// returned as part of the bundle, so the client can later ask for an actual
|
||||
// delta).
|
||||
if (!bundleId) {
|
||||
bundleId = String(this._currentId++);
|
||||
}
|
||||
|
||||
let deltaTransformer = this._deltaTransformers.get(bundleId);
|
||||
clientId: string,
|
||||
options: BundleOptions,
|
||||
): Promise<DeltaTransformer> {
|
||||
let deltaTransformer = this._deltaTransformers.get(clientId);
|
||||
|
||||
if (!deltaTransformer) {
|
||||
deltaTransformer = await DeltaTransformer.create(
|
||||
|
@ -79,13 +66,10 @@ class DeltaBundler {
|
|||
options,
|
||||
);
|
||||
|
||||
this._deltaTransformers.set(bundleId, deltaTransformer);
|
||||
this._deltaTransformers.set(clientId, deltaTransformer);
|
||||
}
|
||||
|
||||
return {
|
||||
deltaTransformer,
|
||||
id: bundleId,
|
||||
};
|
||||
return deltaTransformer;
|
||||
}
|
||||
|
||||
getPostProcessModulesFn(
|
||||
|
|
|
@ -431,4 +431,5 @@ function flatten<T>(input: Iterable<Iterable<T>>): Set<T> {
|
|||
module.exports = {
|
||||
initialTraverseDependencies,
|
||||
traverseDependencies,
|
||||
reorderDependencies,
|
||||
};
|
||||
|
|
|
@ -22,14 +22,12 @@ describe('HmrServer', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
deltaTransformerMock = new EventEmitter();
|
||||
deltaTransformerMock.getDelta = jest.fn();
|
||||
deltaTransformerMock.getDelta = jest.fn().mockReturnValue({id: '1234'});
|
||||
deltaTransformerMock.getInverseDependencies = jest.fn();
|
||||
|
||||
getDeltaTransformerMock = jest
|
||||
.fn()
|
||||
.mockReturnValue(
|
||||
Promise.resolve({deltaTransformer: deltaTransformerMock}),
|
||||
);
|
||||
.mockReturnValue(Promise.resolve(deltaTransformerMock));
|
||||
|
||||
deltaBundlerMock = {
|
||||
getDeltaTransformer: getDeltaTransformerMock,
|
||||
|
@ -55,6 +53,7 @@ describe('HmrServer', () => {
|
|||
);
|
||||
|
||||
expect(getDeltaTransformerMock).toBeCalledWith(
|
||||
'/hot?bundleEntry=EntryPoint.js&platform=ios',
|
||||
expect.objectContaining({
|
||||
deltaBundleId: null,
|
||||
dev: true,
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
import type {Options as BundleOptions} from '../DeltaBundler';
|
||||
import type {CustomTransformOptions} from '../JSTransformer/worker';
|
||||
import type {BundleOptions} from '../shared/types.flow';
|
||||
|
||||
/**
|
||||
* Module to easily create the needed configuration parameters needed for the
|
||||
|
|
|
@ -42,6 +42,7 @@ type Client = {|
|
|||
class HmrServer<TClient: Client> {
|
||||
_packagerServer: PackagerServer;
|
||||
_reporter: Reporter;
|
||||
_lastSequenceId: ?string;
|
||||
|
||||
constructor(packagerServer: PackagerServer) {
|
||||
this._packagerServer = packagerServer;
|
||||
|
@ -62,12 +63,15 @@ class HmrServer<TClient: Client> {
|
|||
// DeltaBundleId param through the WS connection and we'll be able to share
|
||||
// the same DeltaTransformer between the WS connection and the HTTP one.
|
||||
const deltaBundler = this._packagerServer.getDeltaBundler();
|
||||
const {deltaTransformer} = await deltaBundler.getDeltaTransformer(
|
||||
const deltaTransformer = await deltaBundler.getDeltaTransformer(
|
||||
clientUrl,
|
||||
getBundlingOptionsForHmr(bundleEntry, platform, customTransformOptions),
|
||||
);
|
||||
|
||||
// Trigger an initial build to start up the DeltaTransformer.
|
||||
await deltaTransformer.getDelta();
|
||||
const {id} = await deltaTransformer.getDelta();
|
||||
|
||||
this._lastSequenceId = id;
|
||||
|
||||
// Listen to file changes.
|
||||
const client = {sendFn, deltaTransformer};
|
||||
|
@ -113,7 +117,7 @@ class HmrServer<TClient: Client> {
|
|||
let result;
|
||||
|
||||
try {
|
||||
result = await client.deltaTransformer.getDelta();
|
||||
result = await client.deltaTransformer.getDelta(this._lastSequenceId);
|
||||
} catch (error) {
|
||||
const formattedError = formatBundlingError(error);
|
||||
|
||||
|
@ -138,6 +142,8 @@ class HmrServer<TClient: Client> {
|
|||
}
|
||||
}
|
||||
|
||||
this._lastSequenceId = result.id;
|
||||
|
||||
return {
|
||||
type: 'update',
|
||||
body: {
|
||||
|
|
|
@ -182,7 +182,6 @@ describe('processRequest', () => {
|
|||
assetPlugins: [],
|
||||
bundleType: 'bundle',
|
||||
customTransformOptions: {},
|
||||
deltaBundleId: expect.any(String),
|
||||
dev: true,
|
||||
entryFile: 'index.ios.js',
|
||||
entryModuleOnly: false,
|
||||
|
@ -214,7 +213,6 @@ describe('processRequest', () => {
|
|||
assetPlugins: [],
|
||||
bundleType: 'bundle',
|
||||
customTransformOptions: {},
|
||||
deltaBundleId: expect.any(String),
|
||||
dev: true,
|
||||
entryFile: 'index.js',
|
||||
entryModuleOnly: false,
|
||||
|
@ -246,7 +244,6 @@ describe('processRequest', () => {
|
|||
assetPlugins: ['assetPlugin1', 'assetPlugin2'],
|
||||
bundleType: 'bundle',
|
||||
customTransformOptions: {},
|
||||
deltaBundleId: expect.any(String),
|
||||
dev: true,
|
||||
entryFile: 'index.js',
|
||||
entryModuleOnly: false,
|
||||
|
@ -286,14 +283,17 @@ describe('processRequest', () => {
|
|||
});
|
||||
|
||||
it('should send the correct deltaBundlerId to the bundler', () => {
|
||||
Serializers.deltaBundle.mockImplementation(async (_, options) => {
|
||||
expect(options.deltaBundleId).toBe('1234');
|
||||
Serializers.deltaBundle.mockImplementation(
|
||||
async (_, clientId, options) => {
|
||||
expect(clientId).toMatchSnapshot();
|
||||
expect(options.deltaBundleId).toBe('1234');
|
||||
|
||||
return {
|
||||
bundle: '{"delta": "bundle"}',
|
||||
numModifiedFiles: 3,
|
||||
};
|
||||
});
|
||||
return {
|
||||
bundle: '{"delta": "bundle"}',
|
||||
numModifiedFiles: 3,
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
return makeRequest(
|
||||
requestHandler,
|
||||
|
@ -449,7 +449,6 @@ describe('processRequest', () => {
|
|||
{
|
||||
assetPlugins: [],
|
||||
customTransformOptions: {},
|
||||
deltaBundleId: null,
|
||||
dev: true,
|
||||
entryFile: 'foo file',
|
||||
entryModuleOnly: false,
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`processRequest Generate delta bundle endpoint should send the correct deltaBundlerId to the bundler 1`] = `"{\\"sourceMapUrl\\":null,\\"bundleType\\":\\"delta\\",\\"customTransformOptions\\":{},\\"entryFile\\":\\"index.js\\",\\"deltaBundleId\\":null,\\"dev\\":true,\\"minify\\":false,\\"excludeSource\\":null,\\"hot\\":true,\\"runBeforeMainModule\\":[\\"InitializeCore\\"],\\"runModule\\":true,\\"inlineSourceMap\\":false,\\"isolateModuleIDs\\":false,\\"platform\\":\\"ios\\",\\"resolutionResponse\\":null,\\"entryModuleOnly\\":false,\\"assetPlugins\\":[],\\"onProgress\\":null,\\"unbundle\\":false}"`;
|
|
@ -33,7 +33,7 @@ const resolveSync: ResolveSync = require('resolve').sync;
|
|||
import type {CustomError} from '../lib/formatBundlingError';
|
||||
import type {IncomingMessage, ServerResponse} from 'http';
|
||||
import type {Reporter} from '../lib/reporting';
|
||||
import type {Options as DeltaBundlerOptions} from '../DeltaBundler/Serializers';
|
||||
import type {DeltaOptions} from '../DeltaBundler/Serializers';
|
||||
import type {BundleOptions, Options} from '../shared/types.flow';
|
||||
import type {
|
||||
GetTransformOptions,
|
||||
|
@ -229,7 +229,6 @@ class Server {
|
|||
async build(options: BundleOptions): Promise<{code: string, map: string}> {
|
||||
options = {
|
||||
...options,
|
||||
deltaBundleId: null,
|
||||
runBeforeMainModule: this._opts.getModulesRunBeforeMainModule(
|
||||
options.entryFile,
|
||||
),
|
||||
|
@ -252,16 +251,11 @@ class Server {
|
|||
}
|
||||
|
||||
async getRamBundleInfo(options: BundleOptions): Promise<RamBundleInfo> {
|
||||
options = {...options, deltaBundleId: null};
|
||||
|
||||
return await Serializers.getRamBundleInfo(this._deltaBundler, options);
|
||||
}
|
||||
|
||||
async getAssets(options: BundleOptions): Promise<$ReadOnlyArray<AssetData>> {
|
||||
return await Serializers.getAssets(this._deltaBundler, {
|
||||
...options,
|
||||
deltaBundleId: null,
|
||||
});
|
||||
return await Serializers.getAssets(this._deltaBundler, options);
|
||||
}
|
||||
|
||||
async getOrderedDependencyPaths(options: {
|
||||
|
@ -274,7 +268,6 @@ class Server {
|
|||
...Server.DEFAULT_BUNDLE_OPTIONS,
|
||||
...options,
|
||||
bundleType: 'delta',
|
||||
deltaBundleId: null,
|
||||
};
|
||||
|
||||
if (!bundleOptions.platform) {
|
||||
|
@ -401,6 +394,7 @@ class Server {
|
|||
// can be ignored to calculate the options hash.
|
||||
const ignoredParams = {
|
||||
onProgress: null,
|
||||
deltaBundleId: null,
|
||||
excludeSource: null,
|
||||
sourceMapUrl: null,
|
||||
};
|
||||
|
@ -444,7 +438,7 @@ class Server {
|
|||
_prepareDeltaBundler(
|
||||
req: IncomingMessage,
|
||||
mres: MultipartResponse,
|
||||
): {options: DeltaBundlerOptions, buildID: string} {
|
||||
): {options: DeltaOptions, buildID: string} {
|
||||
const options = this._getOptionsFromUrl(
|
||||
url.format({
|
||||
...url.parse(req.url),
|
||||
|
@ -503,11 +497,14 @@ class Server {
|
|||
|
||||
let output;
|
||||
|
||||
const clientId = this._optionsHash(options);
|
||||
|
||||
try {
|
||||
output = await Serializers.deltaBundle(this._deltaBundler, {
|
||||
...options,
|
||||
deltaBundleId: options.deltaBundleId,
|
||||
});
|
||||
output = await Serializers.deltaBundle(
|
||||
this._deltaBundler,
|
||||
clientId,
|
||||
options,
|
||||
);
|
||||
} catch (error) {
|
||||
this._handleError(mres, this._optionsHash(options), error);
|
||||
|
||||
|
@ -552,10 +549,7 @@ class Server {
|
|||
let result;
|
||||
|
||||
try {
|
||||
result = await Serializers.fullBundle(this._deltaBundler, {
|
||||
...options,
|
||||
deltaBundleId: this._optionsHash(options),
|
||||
});
|
||||
result = await Serializers.fullBundle(this._deltaBundler, options);
|
||||
} catch (error) {
|
||||
this._handleError(mres, this._optionsHash(options), error);
|
||||
|
||||
|
@ -619,10 +613,7 @@ class Server {
|
|||
let sourceMap;
|
||||
|
||||
try {
|
||||
sourceMap = await Serializers.fullSourceMap(this._deltaBundler, {
|
||||
...options,
|
||||
deltaBundleId: this._optionsHash(options),
|
||||
});
|
||||
sourceMap = await Serializers.fullSourceMap(this._deltaBundler, options);
|
||||
} catch (error) {
|
||||
this._handleError(mres, this._optionsHash(options), error);
|
||||
|
||||
|
@ -751,12 +742,9 @@ class Server {
|
|||
}
|
||||
|
||||
async _sourceMapForURL(reqUrl: string): Promise<MetroSourceMap> {
|
||||
const options: DeltaBundlerOptions = this._getOptionsFromUrl(reqUrl);
|
||||
const options: DeltaOptions = this._getOptionsFromUrl(reqUrl);
|
||||
|
||||
return await Serializers.fullSourceMapObject(this._deltaBundler, {
|
||||
...options,
|
||||
deltaBundleId: this._optionsHash(options),
|
||||
});
|
||||
return await Serializers.fullSourceMapObject(this._deltaBundler, options);
|
||||
}
|
||||
|
||||
_handleError(res: ServerResponse, bundleID: string, error: CustomError) {
|
||||
|
@ -776,7 +764,7 @@ class Server {
|
|||
});
|
||||
}
|
||||
|
||||
_getOptionsFromUrl(reqUrl: string): BundleOptions & DeltaBundlerOptions {
|
||||
_getOptionsFromUrl(reqUrl: string): BundleOptions & DeltaOptions {
|
||||
// `true` to parse the query param as an object.
|
||||
const urlObj = nullthrows(url.parse(reqUrl, true));
|
||||
const urlQuery = nullthrows(urlObj.query);
|
||||
|
|
|
@ -14,12 +14,12 @@ const Serializers = require('../DeltaBundler/Serializers');
|
|||
|
||||
const {getAssetFiles} = require('../Assets');
|
||||
|
||||
import type {Options} from '../DeltaBundler/Serializers';
|
||||
import type DeltaBundler from '../DeltaBundler';
|
||||
import type {BundleOptions} from '../shared/types.flow';
|
||||
|
||||
async function getOrderedDependencyPaths(
|
||||
deltaBundler: DeltaBundler,
|
||||
options: Options,
|
||||
options: BundleOptions,
|
||||
): Promise<Array<string>> {
|
||||
const modules = await Serializers.getAllModules(deltaBundler, options);
|
||||
|
||||
|
|
Loading…
Reference in New Issue