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