Skip to content

Commit

Permalink
Convert to ES modules
Browse files Browse the repository at this point in the history
We expose an ES module version of the library for module bundlers to
use, and generate a CommonJS version for Node.

The motivation is that, for [1] I want to re-export this library from
ably-js as a tree-shakable module. Tree-shakability requires that we use
ES modules.

I’ve output the Node bundle to a new `build` directory, since I don’t
know whether the `dist` directory has some special meaning for the
`ably-env deploy` script and so didn’t want to put non-CDN stuff in
there.

The version of Node that the README tells us to use does not support ES
modules, so we generate a CommonJS bundle for the tests to use, which
includes all of the internal components so that they can be tested.

I tested these changes for regressions by:

1. running `npm run grunt -- test:node`
2. running `npm run grunt -- test:browser:local`
3. generating an NPM package using `npm pack`, installing it in ably-js,
   and running the delta tests there

[1] ably/ably-js#1492
  • Loading branch information
lawrence-forooghian committed Nov 24, 2023
1 parent b81c5ed commit 9d8aeb8
Show file tree
Hide file tree
Showing 16 changed files with 97 additions and 79 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ node_modules
npm-debug.log
local.log
browserstack.err
test/build/

46 changes: 31 additions & 15 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@ module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-mocha-test');
grunt.loadNpmTasks('grunt-karma');

function cdnWebpackTarget({ minify }) {
return {
entry: './lib/vcdiff_decoder.js',
output: {
path: path.resolve(__dirname, 'dist'),
library: 'vcdiffDecoder',
filename: minify ? 'vcdiff-decoder.min.js' : 'vcdiff-decoder.js'
},
mode: minify ? 'production' : 'none', // Opts out of any default optimization options
}
}

grunt.initConfig({
bump: {
options: {
Expand All @@ -26,11 +38,6 @@ module.exports = function (grunt) {
},
webpack: {
options: {
entry: './lib/vcdiff_decoder.js',
output: {
path: path.resolve(__dirname, 'dist'),
library: 'vcdiffDecoder'
},
module: {
rules: [
{
Expand All @@ -57,17 +64,25 @@ module.exports = function (grunt) {
]
}
},
'vcdiff-decoder.js': {
mode: 'none', // Opts out of any default optimization options
'cdn': cdnWebpackTarget({ minify: false }),
'cdn-min': cdnWebpackTarget({ minify: true }),
'cjs': {
entry: './lib/vcdiff_decoder.js',
output: {
path: path.resolve(__dirname, 'build', 'cjs'),
libraryTarget: 'commonjs',
filename: 'vcdiff-decoder.js'
}
},
mode: 'none', // Opts out of any default optimization options
},
'vcdiff-decoder.min.js': {
mode: 'production',
'node-test-support': {
entry: './test/support/node/with-internal-exports.js',
output: {
filename: 'vcdiff-decoder.min.js'
}
path: path.resolve(__dirname, 'test', 'build', 'node'),
libraryTarget: 'commonjs',
filename: 'with-internal-exports.js'
},
mode: 'none',
}
},
karma: {
Expand Down Expand Up @@ -148,13 +163,13 @@ module.exports = function (grunt) {
}
});

grunt.registerTask('build', 'webpack');
grunt.registerTask('build', ['webpack:cdn', 'webpack:cdn-min', 'webpack:cjs']);

grunt.registerTask('test:all', ['test', 'test:browser:remote']);

grunt.registerTask('test', ['test:node', 'test:browser:local']);

grunt.registerTask('test:node', 'mochaTest');
grunt.registerTask('test:node', ['webpack:node-test-support', 'mochaTest']);

grunt.registerTask('test:browser',
'Runs browser tests in given context. Run as "grunt test:browser:<context>", where <context> is "local" or "remote"',
Expand Down Expand Up @@ -240,7 +255,8 @@ module.exports = function (grunt) {
var generatedFiles = [
'package.json',
'dist/vcdiff-decoder.js',
'dist/vcdiff-decoder.min.js'
'dist/vcdiff-decoder.min.js',
'build/cjs/vcdiff-decoder.js',
];

var cmd = 'git add -A ' + generatedFiles.join(' ');
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ You can trigger a build using Webpack with:

npm run grunt -- build

which creates `vcdiff-decoder.js` and `vcdiff-decoder.min.js` in the `dist` folder.
which creates `vcdiff-decoder.js` and `vcdiff-decoder.min.js` in the `dist` folder, and `vcdiff-decoder.js` in the `build/cjs` folder.

### Testing

Expand All @@ -130,7 +130,7 @@ for which you will need to configure environment variables for `BROWSERSTACK_USE

On the `main` branch:

1. Increment the version, regenerate from source (a.k.a. build / bundle) and make a tagged commit which includes the built output from the `/dist` folder by running `npm run grunt -- release:patch` (or "major", "minor" or "prepatch" as appropriate - see [grunt-bump Usage Examples](https://github.com/vojtajina/grunt-bump#usage-examples))
1. Increment the version, regenerate from source (a.k.a. build / bundle) and make a tagged commit which includes the built output from the `/dist` and `/build` folders by running `npm run grunt -- release:patch` (or "major", "minor" or "prepatch" as appropriate - see [grunt-bump Usage Examples](https://github.com/vojtajina/grunt-bump#usage-examples))
2. Release the tagged commit to Github using `git push origin main --follow-tags`
3. Release to NPM using `npm publish . --access public` ([this package](https://www.npmjs.com/package/@ably/vcdiff-decoder) is configured to require that [2FA](https://docs.npmjs.com/configuring-two-factor-authentication) is used by publishers)
4. Release to Ably's CDN using `npm run grunt -- publish-cdn` (operable by Ably staff only)
Expand Down
4 changes: 1 addition & 3 deletions lib/address_caches/near.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

function NearCache(size) {
export default function NearCache(size) {
this.size = size;
this.near = new Array(this.size).fill(0);
this.nextSlot = 0;
Expand All @@ -17,5 +17,3 @@ NearCache.prototype.get = function(m, offset) {
let address = this.near[m] + offset;
return address;
};

module.exports = NearCache;
4 changes: 1 addition & 3 deletions lib/address_caches/same.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

function SameCache(size) {
export default function SameCache(size) {
this.size = size;
this.same = new Array(this.size * 256).fill(0);
}
Expand All @@ -15,5 +15,3 @@ SameCache.prototype.get = function(m, offset) {
let address = this.same[m * 256 + offset];
return address;
};

module.exports = SameCache;
11 changes: 4 additions & 7 deletions lib/deserialize/delta.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
'use strict';

const errors = require('../errors');
const deserializeInteger = require('./integer');
const tokenizeInstructions = require('../tokenize_instructions');
import errors from '../errors';
import deserializeInteger from './integer';
import tokenizeInstructions from '../tokenize_instructions';

function delta(delta, position) {
export default function delta(delta, position) {

let targetWindowLength, dataLength, instructionsLength, addressesLength;

Expand Down Expand Up @@ -45,6 +45,3 @@ function delta(delta, position) {

return window;
}

module.exports = delta;

4 changes: 1 addition & 3 deletions lib/deserialize/integer.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @param position {Number}
* @returns {{position: {Number}, value: {Number}}}
*/
function integer(buffer, position) {
export default function integer(buffer, position) {
const result = { position, value: 0 };

do {
Expand All @@ -23,5 +23,3 @@ function integer(buffer, position) {

return result;
}

module.exports = integer;
2 changes: 1 addition & 1 deletion lib/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ function CustomErrors(names) {
return errors;
}

module.exports = CustomErrors(['NotImplemented', 'InvalidDelta']);
export default CustomErrors(['NotImplemented', 'InvalidDelta']);
6 changes: 3 additions & 3 deletions lib/instructions.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';

const deserializeInteger = require('./deserialize/integer');
const TypedArray = require('./typed_array_util');
import deserializeInteger from './deserialize/integer';
import * as TypedArray from './typed_array_util';

function ADD(size) {
this.size = size;
Expand Down Expand Up @@ -75,4 +75,4 @@ let instructions = {
RUN
};

module.exports = instructions;
export default instructions;
8 changes: 3 additions & 5 deletions lib/tokenize_instructions.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
'use strict';

const instructions = require('./instructions');
const deserializeInteger = require('./deserialize/integer');
import instructions from './instructions';
import deserializeInteger from './deserialize/integer';

function tokenizeInstructions(instructionsBuffer) {
export default function tokenizeInstructions(instructionsBuffer) {
let deserializedInstructions = [];

let instructionsPosition = 0;
Expand Down Expand Up @@ -162,5 +162,3 @@ function ADD_COPY(index, baseIndex) {

return {addSize, copySize};
}

module.exports = tokenizeInstructions;
16 changes: 4 additions & 12 deletions lib/typed_array_util.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
'use strict';

function uint8ArrayToString(uintArray) {
export function uint8ArrayToString(uintArray) {
let encodedString = String.fromCharCode.apply(null, uintArray);
let decodedString = decodeURIComponent(escape(encodedString));
return decodedString;
}

function stringToUint8Array(str) {
export function stringToUint8Array(str) {
var buf = new Uint8Array(str.length);
for (var i=0, strLen=str.length; i < strLen; i++) {
buf[i] = str.charCodeAt(i);
}
return buf;
}

function equal(typedArray1, typedArray2) {
export function equal(typedArray1, typedArray2) {
if (typedArray1.length !== typedArray2.length) {
return false;
}
Expand All @@ -26,7 +26,7 @@ function equal(typedArray1, typedArray2) {
return true;
}

function TypedArrayList() {
export function TypedArrayList() {
this.typedArrays = [];
this.startIndexes = [];
this.length = 0;
Expand Down Expand Up @@ -103,11 +103,3 @@ function getIndex(arr, element) {
return high;
}
}

module.exports = {
uint8ArrayToString,
stringToUint8Array,
equal,
TypedArrayList
};

16 changes: 7 additions & 9 deletions lib/vcdiff.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
'use strict';

const errors = require('./errors');
const TypedArray = require('./typed_array_util');
const deserializeInteger = require('./deserialize/integer');
const deserializeDelta = require('./deserialize/delta');
const NearCache = require('./address_caches/near');
const SameCache = require('./address_caches/same');
import errors from './errors';
import * as TypedArray from './typed_array_util';
import deserializeInteger from './deserialize/integer';
import deserializeDelta from './deserialize/delta';
import NearCache from './address_caches/near';
import SameCache from './address_caches/same';

/**
*
* @param delta {Uint8Array}
* @param source {Uint8Array}
* @constructor
*/
function VCDiff(delta, source) {
export default function VCDiff(delta, source) {
this.delta = delta;
this.position = 0;
this.source = source;
Expand Down Expand Up @@ -153,5 +153,3 @@ Delta.prototype.getNextAddressByte = function() {
let value = this.addresses[this.addressesPosition++];
return value;
};

module.exports = VCDiff;
8 changes: 2 additions & 6 deletions lib/vcdiff_decoder.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

const VCDiff = require('./vcdiff');
import VCDiff from './vcdiff';

/**
* Vcdiff decode, applying delta to source and returning the result.
Expand All @@ -9,11 +9,7 @@ const VCDiff = require('./vcdiff');
* @param source {Uint8Array} The source to apply the delta diff/patch to.
* @returns {Uint8Array} The result of applying delta to source.
*/
function decode(delta, source) {
export function decode(delta, source) {
let vcdiff = new VCDiff(delta, source);
return vcdiff.decode();
}

module.exports = {
decode
};
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"description": "Pure JavaScript Vcdiff decoder that works with binary deltas from Google's open-vcdiff",
"license": "Apache-2.0",
"homepage": "https://ably.io/",
"main": "lib/vcdiff_decoder.js",
"main": "build/cjs/vcdiff-decoder.js",
"module": "lib/vcdiff_decoder.js",
"typings": "typings.d.ts",
"scripts": {
"grunt": "grunt",
Expand All @@ -30,6 +31,7 @@
"files": [
"lib",
"dist",
"build",
"typings.d.ts"
],
"devDependencies": {
Expand Down
20 changes: 11 additions & 9 deletions test/node-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@ const fs = require('fs');
const assert = require('chai').assert;
const vcd = require('vcdiff');

const vcdiffDecoder = require('../');
const errors = require('../lib/errors');
const VCDiff = require('../lib/vcdiff');
const TypedArray = require('../lib/typed_array_util');
const instructions = require('../lib/instructions');
const deserializeInteger = require('../lib/deserialize/integer');
const deserializeDelta = require('../lib/deserialize/delta');
const NearCache = require('../lib/address_caches/near');
const SameCache = require('../lib/address_caches/same');
const {
vcdiffDecoder,
errors,
VCDiff,
TypedArray,
instructions,
deserializeInteger,
deserializeDelta,
NearCache,
SameCache,
} = require('./build/node/with-internal-exports');

describe('vcdiffDecoder', function() {

Expand Down
22 changes: 22 additions & 0 deletions test/support/node/with-internal-exports.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const vcdiffDecoder = require('../../../');

import errors from '../../../lib/errors';
import VCDiff from '../../../lib/vcdiff';
import * as TypedArray from '../../../lib/typed_array_util';
import instructions from '../../../lib/instructions';
import deserializeInteger from '../../../lib/deserialize/integer';
import deserializeDelta from '../../../lib/deserialize/delta';
import NearCache from '../../../lib/address_caches/near';
import SameCache from '../../../lib/address_caches/same';

export {
vcdiffDecoder,
errors,
VCDiff,
TypedArray,
instructions,
deserializeInteger,
deserializeDelta,
NearCache,
SameCache,
}

0 comments on commit 9d8aeb8

Please sign in to comment.