From b5a719b8464d83d080a9f86e3cfa22b697d878d2 Mon Sep 17 00:00:00 2001 From: Georges-Antoine Assi <3247106+gantoine@users.noreply.github.com> Date: Sun, 17 Aug 2025 15:22:23 -0500 Subject: [PATCH] Add jsdoc comments to compression.js (#1062) * Add jsdoc to compression * undo formatting --- .gitignore | 1 + data/src/compression.js | 95 +++++++++++++++++++++++++++++++++++------ package.json | 14 +++--- 3 files changed, 93 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index 3b86629..953f7fc 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ data/cores/* .vscode/* *.tgz dist/ +jsdoc/ diff --git a/data/src/compression.js b/data/src/compression.js index 1db5fa2..e81b680 100644 --- a/data/src/compression.js +++ b/data/src/compression.js @@ -1,18 +1,55 @@ -class EJS_COMPRESSION { +/** + * Handles compression and decompression of various archive formats (ZIP, 7Z, RAR) + * for the EmulatorJS system. + * + * This class provides functionality to detect compressed file formats and extract + * their contents using web workers for better performance. + */ +class EJSCompression { + /** + * Creates a new compression handler instance. + * + * @param {Object} EJS - The main EmulatorJS instance + */ constructor(EJS) { this.EJS = EJS; } - isCompressed(data) { //https://www.garykessler.net/library/file_sigs.html - //todo. Use hex instead of numbers - if ((data[0] === 80 && data[1] === 75) && ((data[2] === 3 && data[3] === 4) || (data[2] === 5 && data[3] === 6) || (data[2] === 7 && data[3] === 8))) { - return "zip"; - } else if (data[0] === 55 && data[1] === 122 && data[2] === 188 && data[3] === 175 && data[4] === 39 && data[5] === 28) { - return "7z"; - } else if ((data[0] === 82 && data[1] === 97 && data[2] === 114 && data[3] === 33 && data[4] === 26 && data[5] === 7) && ((data[6] === 0) || (data[6] === 1 && data[7] == 0))) { - return "rar"; + + /** + * Detects if the given data represents a compressed archive format. + * + * @param {Uint8Array|ArrayBuffer} data - The binary data to analyze + * @returns {string|null} The detected compression format ('zip', '7z', 'rar') or null if not compressed + * + * @description + * Checks the file signature (magic bytes) at the beginning of the data to identify + * the compression format. Supports ZIP, 7Z, and RAR formats. + * + * @see {@link https://www.garykessler.net/library/file_sigs.html|File Signature Database} + */ + isCompressed(data) { + if ((data[0] === 0x50 && data[1] === 0x4B) && ((data[2] === 0x03 && data[3] === 0x04) || (data[2] === 0x05 && data[3] === 0x06) || (data[2] === 0x07 && data[3] === 0x08))) { + return "zip"; + } else if (data[0] === 0x37 && data[1] === 0x7A && data[2] === 0xBC && data[3] === 0xAF && data[4] === 0x27 && data[5] === 0x1C) { + return "7z"; + } else if ((data[0] === 0x52 && data[1] === 0x61 && data[2] === 0x72 && data[3] === 0x21 && data[4] === 0x1A && data[5] === 0x07) && ((data[6] === 0x00) || (data[6] === 0x01 && data[7] === 0x00))) { + return "rar"; + } + return null; } - return null; - } + + /** + * Decompresses the given data and extracts all files. + * + * @param {Uint8Array|ArrayBuffer} data - The compressed data to extract + * @param {Function} updateMsg - Callback function for progress updates (message, isProgress) + * @param {Function} fileCbFunc - Callback function called for each extracted file (filename, fileData) + * @returns {Promise} Promise that resolves to an object mapping filenames to file data + * + * @description + * Automatically detects the compression format and delegates to the appropriate + * decompression method. If the data is not compressed, returns it as-is. + */ decompress(data, updateMsg, fileCbFunc) { const compressed = this.isCompressed(data.slice(0, 10)); if (compressed === null) { @@ -23,6 +60,20 @@ class EJS_COMPRESSION { } return this.decompressFile(compressed, data, updateMsg, fileCbFunc); } + + /** + * Retrieves the appropriate worker script for the specified compression method. + * + * @param {string} method - The compression method ('7z', 'zip', or 'rar') + * @returns {Promise} Promise that resolves to a Blob containing the worker script + * + * @description + * Downloads the necessary worker script and WASM files for the specified compression + * method. For RAR files, also downloads the libunrar.wasm file and creates a custom + * worker script with the WASM binary embedded. + * + * @throws {Error} When network errors occur during file downloads + */ getWorkerFile(method) { return new Promise(async (resolve, reject) => { let path, obj; @@ -107,6 +158,26 @@ class EJS_COMPRESSION { } }) } + + /** + * Decompresses a file using the specified compression method. + * + * @param {string} method - The compression method ('7z', 'zip', or 'rar') + * @param {Uint8Array|ArrayBuffer} data - The compressed data to extract + * @param {Function} updateMsg - Callback function for progress updates (message, isProgress) + * @param {Function} fileCbFunc - Callback function called for each extracted file (filename, fileData) + * @returns {Promise} Promise that resolves to an object mapping filenames to file data + * + * @description + * Creates a web worker to handle the decompression process asynchronously. + * The worker communicates progress updates and extracted files back to the main thread. + * + * @example + * // Message types from worker: + * // t: 4 - Progress update (current, total, name) + * // t: 2 - File extracted (file, size, data) + * // t: 1 - Extraction complete + */ decompressFile(method, data, updateMsg, fileCbFunc) { return new Promise(async callback => { const file = await this.getWorkerFile(method); @@ -139,4 +210,4 @@ class EJS_COMPRESSION { } } -window.EJS_COMPRESSION = EJS_COMPRESSION; +window.EJS_COMPRESSION = EJSCompression; diff --git a/package.json b/package.json index 7662152..0a7c4d2 100644 --- a/package.json +++ b/package.json @@ -17,19 +17,23 @@ "start": "http-server", "minify": "node minify/minify.js", "build": "node build.js", - "update": "node update.js" + "update": "node update.js", + "docs": "jsdoc data/src/*.js -d jsdoc" }, "dependencies": { "@node-minify/clean-css": "^9.0.1", "@node-minify/core": "^9.0.2", "@node-minify/terser": "^9.0.1", "http-server": "^14.1.1", - "node-7z": "^3.0.0", - "node-fetch": "^3.3.2", - "nipplejs": "^0.10.2", - "socket.io": "^4.8.1" + "node-7z": "^3.0.0" }, "optionalDependencies": { "@emulatorjs/cores": "latest" + }, + "devDependencies": { + "jsdoc": "^4.0.4", + "nipplejs": "^0.10.2", + "node-fetch": "^3.3.2", + "socket.io": "^4.8.1" } }