1
0
Fork 0
mirror of https://github.com/codedread/bitjs synced 2025-10-03 17:49:16 +02:00

Fix compress after previous refactor and add a unit test.

This commit is contained in:
Jeff Schiller 2023-12-22 13:18:36 -08:00
parent 65db5bdbd2
commit 8e1a7f3d0f
5 changed files with 81 additions and 10 deletions

View file

@ -29,13 +29,12 @@ or
yarn add @codedread/bitjs yarn add @codedread/bitjs
``` ```
### Using in Node ### CommonJS/ESM in Node
This module is an ES Module, which should work as expected in other projects using ES Modules. This module is an ES Module, which should work as expected in other projects using ES Modules.
However, if you are using a project that uses CommonJs modules, it's a little tricker to use. One However, if you are using CommonJS modules, it's a little trickier to use. One example of this is
example of this is if a TypeScript project compiles to CommonJS, it will try to turn imports into if a TypeScript project compiles to CommonJS, it will try to turn imports into require() statements,
require() statements, which will break. The fix for this (unfortunately) is to update your which will break. The fix for this (unfortunately) is to update your tsconfig.json:
tsconfig.json:
```json ```json
"moduleResolution": "Node16", "moduleResolution": "Node16",

View file

@ -16,7 +16,7 @@ import { getConnectedPort } from './common.js';
* @typedef FileInfo An object that is sent to the implementation to represent a file to zip. * @typedef FileInfo An object that is sent to the implementation to represent a file to zip.
* @property {string} fileName The name of the file. TODO: Includes the path? * @property {string} fileName The name of the file. TODO: Includes the path?
* @property {number} lastModTime The number of ms since the Unix epoch (1970-01-01 at midnight). * @property {number} lastModTime The number of ms since the Unix epoch (1970-01-01 at midnight).
* @property {ArrayBuffer} fileData The bytes of the file. * @property {Uint8Array} fileData The bytes of the file.
*/ */
/** /**
@ -75,6 +75,13 @@ export class Zipper {
*/ */
port_; port_;
/**
* A function to call to disconnect the implementation from the host.
* @type {Function}
* @private
*/
disconnectFn_;
/** /**
* @param {CompressorOptions} options * @param {CompressorOptions} options
*/ */
@ -124,7 +131,9 @@ export class Zipper {
* of bytes. * of bytes.
*/ */
async start(files, isLastFile) { async start(files, isLastFile) {
this.port_ = await getConnectedPort('./zip.js'); const impl = await getConnectedPort('./zip.js');
this.port_ = impl.hostPort;
this.disconnectFn_ = impl.disconnectFn;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.port_.onerror = (evt) => { this.port_.onerror = (evt) => {
console.log('Impl error: message = ' + evt.message); console.log('Impl error: message = ' + evt.message);
@ -142,6 +151,10 @@ export class Zipper {
break; break;
case 'finish': case 'finish':
this.compressState = CompressStatus.COMPLETE; this.compressState = CompressStatus.COMPLETE;
this.port_.close();
this.disconnectFn_();
this.port_ = null;
this.disconnectFn_ = null;
resolve(this.byteArray); resolve(this.byteArray);
break; break;
case 'compress': case 'compress':

View file

@ -155,7 +155,7 @@ function zipOneFile(file) {
const fileHeaderSize = 30 + file.fileName.length; const fileHeaderSize = 30 + file.fileName.length;
/** @type {ByteBuffer} */ /** @type {ByteBuffer} */
const buffer = new ByteBuffer(fileHeaderSize + file.fileData.length); const buffer = new ByteBuffer(fileHeaderSize + file.fileData.byteLength);
buffer.writeNumber(zLocalFileHeaderSignature, 4); // Magic number. buffer.writeNumber(zLocalFileHeaderSignature, 4); // Magic number.
buffer.writeNumber(0x0A, 2); // Version. buffer.writeNumber(0x0A, 2); // Version.
@ -292,8 +292,8 @@ export function disconnect() {
hostPort = null; hostPort = null;
filesCompressed = [];
centralDirectoryInfos = []; centralDirectoryInfos = [];
numBytesWritten = 0; numBytesWritten = 0;
state = CompressorState.NOT_STARTED; state = CompressorState.NOT_STARTED;
lastFileReceived = false;
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "@codedread/bitjs", "name": "@codedread/bitjs",
"version": "1.1.7", "version": "1.1.8",
"description": "Binary Tools for JavaScript", "description": "Binary Tools for JavaScript",
"homepage": "https://github.com/codedread/bitjs", "homepage": "https://github.com/codedread/bitjs",
"author": "Jeff Schiller", "author": "Jeff Schiller",

59
tests/compress.spec.js Normal file
View file

@ -0,0 +1,59 @@
import * as fs from 'node:fs';
import 'mocha';
import { expect } from 'chai';
import { Unarchiver, getUnarchiver } from '../archive/decompress.js';
import { CompressStatus, Zipper, ZipCompressionMethod } from '../archive/compress.js';
/**
* @typedef {import('./archive/compress.js').FileInfo} FileInfo
*/
const PATH = `tests/archive-testfiles/`;
const INPUT_FILENAMES = [
'sample-1.txt',
'sample-2.csv',
'sample-3.json',
];
describe('bitjs.archive.compress', () => {
/** @type {Map<string, FileInfo>} */
let inputFileInfos = new Map();
let decompressedFileSize = 0;
before(() => {
for (const fileName of INPUT_FILENAMES) {
const fullFilename = `${PATH}${fileName}`;
const fd = fs.openSync(fullFilename, 'r');
const lastModTime = fs.fstatSync(fd).mtimeMs;
const nodeBuf = fs.readFileSync(fullFilename);
const fileData = new Uint8Array(
nodeBuf.buffer.slice(nodeBuf.byteOffset, nodeBuf.byteOffset + nodeBuf.length));
inputFileInfos.set(fileName, {fileName, lastModTime, fileData});
decompressedFileSize += fileData.byteLength;
fs.closeSync(fd);
}
});
it('zipper works', (done) => {
const files = new Map(inputFileInfos);
const zipper = new Zipper({zipCompressionMethod: ZipCompressionMethod.STORE});
zipper.start(Array.from(files.values()), true).then(byteArray => {
expect(zipper.compressState).equals(CompressStatus.COMPLETE);
expect(byteArray.byteLength > decompressedFileSize).equals(true);
const unarchiver = getUnarchiver(byteArray.buffer);
unarchiver.addEventListener('extract', evt => {
const {filename, fileData} = evt.unarchivedFile;
expect(files.has(filename)).equals(true);
const inputFile = files.get(filename).fileData;
expect(inputFile.byteLength).equals(fileData.byteLength);
for (let b = 0; b < inputFile.byteLength; ++b) {
expect(inputFile[b]).equals(fileData[b]);
}
});
unarchiver.addEventListener('finish', evt => done());
unarchiver.start();
});
});
});