Add DeltaPatcher module to handle Delta bundles

Reviewed By: jeanlauliac

Differential Revision: D5761096

fbshipit-source-id: 8c8ef5fb720b08e3f4f097c5a76f793dc4f1c1da
This commit is contained in:
Rafael Oleza 2017-09-04 13:42:39 -07:00 committed by Facebook Github Bot
parent 52fcaf4a10
commit 7b17ca335d
3 changed files with 222 additions and 0 deletions

View File

@ -0,0 +1,89 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
* @format
*/
'use strict';
import type {DeltaBundle} from './';
/**
* This is a reference client for the Delta Bundler: it maintains cached the
* last patched bundle delta and it's capable of applying new Deltas received
* from the Bundler and stringify them to convert them into a full bundle.
*/
class DeltaPatcher {
_lastBundle = {
pre: '',
post: '',
modules: {},
};
_initialized = false;
/**
* Applies a Delta Bundle to the current bundle.
*/
applyDelta(deltaBundle: DeltaBundle) {
// Make sure that the first received delta is a fresh one.
if (!this._initialized && !deltaBundle.reset) {
throw new Error(
'DeltaPatcher should receive a fresh Delta when being initialized',
);
}
this._initialized = true;
// Reset the current delta when we receive a fresh delta.
if (deltaBundle.reset) {
this._lastBundle = {
pre: '',
post: '',
modules: {},
};
}
// Override the prepended sources.
if (deltaBundle.pre) {
this._lastBundle.pre = deltaBundle.pre;
}
// Override the appended sources.
if (deltaBundle.post) {
this._lastBundle.post = deltaBundle.post;
}
// Patch the received modules.
for (const i in deltaBundle.delta) {
if (deltaBundle.delta[i] == null) {
delete this._lastBundle.modules[i];
} else {
this._lastBundle.modules[i] = deltaBundle.delta[i];
}
}
return this;
}
/**
* Converts the current delta bundle to a standard string bundle, ready to
* be interpreted by any JS VM.
*/
stringify() {
return []
.concat(
this._lastBundle.pre,
Object.values(this._lastBundle.modules),
this._lastBundle.post,
)
.join('\n;');
}
}
module.exports = DeltaPatcher;

View File

@ -0,0 +1,105 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @emails oncall+javascript_tools
* @format
*/
'use strict';
const DeltaPatcher = require('../DeltaPatcher');
describe('DeltaPatcher', () => {
let deltaPatcher;
beforeEach(() => {
deltaPatcher = new DeltaPatcher();
});
it('should throw if received a non-reset delta as the initial one', () => {
expect(() =>
deltaPatcher.applyDelta({
pre: 'pre',
post: 'post',
delta: {},
}),
).toThrow();
});
it('should apply an initial delta correctly', () => {
const result = deltaPatcher
.applyDelta({
reset: 1,
pre: 'pre',
post: 'post',
delta: {
1: 'middle',
},
})
.stringify();
expect(result).toMatchSnapshot();
});
it('should apply many different patches correctly', () => {
const result = deltaPatcher
.applyDelta({
reset: 1,
pre: 'pre',
post: 'post',
delta: {
1: 'middle',
},
})
.applyDelta({
delta: {
2: 'another',
},
})
.applyDelta({
delta: {
2: 'another',
87: 'third',
},
})
.stringify();
expect(result).toMatchSnapshot();
const anotherResult = deltaPatcher
.applyDelta({
pre: 'new pre',
delta: {
2: 'another',
1: null,
},
})
.applyDelta({
delta: {
2: null,
12: 'twelve',
},
})
.stringify();
expect(anotherResult).toMatchSnapshot();
expect(
deltaPatcher
.applyDelta({
pre: '1',
post: '1',
delta: {
12: 'ten',
},
reset: true,
})
.stringify(),
).toMatchSnapshot();
});
});

View File

@ -0,0 +1,28 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`DeltaPatcher should apply an initial delta correctly 1`] = `
"pre
;middle
;post"
`;
exports[`DeltaPatcher should apply many different patches correctly 1`] = `
"pre
;middle
;another
;third
;post"
`;
exports[`DeltaPatcher should apply many different patches correctly 2`] = `
"new pre
;twelve
;third
;post"
`;
exports[`DeltaPatcher should apply many different patches correctly 3`] = `
"1
;ten
;1"
`;