Avoid losing deltas when unexpected errors happen on the DeltaTransformer

Reviewed By: jeanlauliac

Differential Revision: D6402261

fbshipit-source-id: 6a1a18c1bd7d4f7cecd5a5e9114f6eb493d40b4d
This commit is contained in:
Rafael Oleza 2017-11-23 08:05:35 -08:00 committed by Facebook Github Bot
parent 70dadc63f9
commit 6557272f8c
2 changed files with 44 additions and 29 deletions

View File

@ -74,6 +74,10 @@ class DeltaCalculator extends EventEmitter {
.getWatcher() .getWatcher()
.removeListener('change', this._handleMultipleFileChanges); .removeListener('change', this._handleMultipleFileChanges);
this.reset();
}
reset() {
// Clean up all the cache data structures to deallocate memory. // Clean up all the cache data structures to deallocate memory.
this._modifiedFiles = new Set(); this._modifiedFiles = new Set();
this._deletedFiles = new Set(); this._deletedFiles = new Set();

View File

@ -230,40 +230,51 @@ class DeltaTransformer extends EventEmitter {
const transformerOptions = await this._deltaCalculator.getTransformerOptions(); const transformerOptions = await this._deltaCalculator.getTransformerOptions();
const dependencyEdges = this._deltaCalculator.getDependencyEdges(); const dependencyEdges = this._deltaCalculator.getDependencyEdges();
// Return the source code that gets prepended to all the modules. This try {
// contains polyfills and startup code (like the require() implementation). // Return the source code that gets prepended to all the modules. This
const prependSources = reset // contains polyfills and startup code (like the require() implementation).
? await this._getPrepend(transformerOptions, dependencyEdges) const prependSources = reset
: new Map(); ? await this._getPrepend(transformerOptions, dependencyEdges)
: 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 { return {
pre: prependSources, pre: prependSources,
post: appendSources, post: appendSources,
delta: modifiedDelta, delta: modifiedDelta,
reset, 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;
}
} }
_getDependencies = (path: string): Set<string> => { _getDependencies = (path: string): Set<string> => {