From b68d24c4015294bc2b4a53e281c85ed61a4d9fe6 Mon Sep 17 00:00:00 2001 From: Denis Davidyuk Date: Sat, 5 Feb 2022 10:27:11 +0300 Subject: [PATCH 01/12] remove outdated argon2.js.mem replace patch Because can't find argon2.js.mem in dist/argon2.js --- build-wasm.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/build-wasm.sh b/build-wasm.sh index 270616c..7293c4d 100755 --- a/build-wasm.sh +++ b/build-wasm.sh @@ -31,7 +31,6 @@ cmake --build . shasum dist/argon2.js shasum dist/argon2.wasm -perl -pi -e 's/"argon2.js.mem"/null/g' dist/argon2.js perl -pi -e 's/$/if(typeof module!=="undefined")module.exports=Module;Module.unloadRuntime=function(){if(typeof self!=="undefined"){delete self.Module}Module=jsModule=wasmMemory=wasmTable=asm=buffer=HEAP8=HEAPU8=HEAP16=HEAPU16=HEAP32=HEAPU32=HEAPF32=HEAPF64=undefined;if(typeof module!=="undefined"){delete module.exports}};/' dist/argon2.js perl -pi -e 's/typeof Module!=="undefined"\?Module:\{};/typeof self!=="undefined"&&typeof self.Module!=="undefined"?self.Module:{};var jsModule=Module;/g' dist/argon2.js perl -pi -e 's/receiveInstantiatedSource\(output\)\{/receiveInstantiatedSource(output){Module=jsModule;if(typeof self!=="undefined")self.Module=Module;/g' dist/argon2.js From 81764cdf2be2d1ef1e52fba0f8de0a8087d2be7a Mon Sep 17 00:00:00 2001 From: Denis Davidyuk Date: Sat, 5 Feb 2022 10:30:01 +0300 Subject: [PATCH 02/12] move unloadRuntime replace patch to em-post.js --- .gitignore | 2 ++ CMakeLists.txt | 2 ++ build-wasm.sh | 1 - lib/em-post.js | 8 ++++++++ 4 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 lib/em-post.js diff --git a/.gitignore b/.gitignore index e946538..7c46178 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,5 @@ test/webpack/node_modules/ test/webpack/dist/ *.tgz package/ +em-post_js_tracker.c +libargon2_1_em-post_js.a diff --git a/CMakeLists.txt b/CMakeLists.txt index 839cfe4..7549b0b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,3 +31,5 @@ endif() add_executable(argon2 ${sources}) set_target_properties(argon2 PROPERTIES OUTPUT_NAME ${OUTPUT_NAME}) + +em_link_post_js(argon2 lib/em-post.js) diff --git a/build-wasm.sh b/build-wasm.sh index 7293c4d..8d17f10 100755 --- a/build-wasm.sh +++ b/build-wasm.sh @@ -31,6 +31,5 @@ cmake --build . shasum dist/argon2.js shasum dist/argon2.wasm -perl -pi -e 's/$/if(typeof module!=="undefined")module.exports=Module;Module.unloadRuntime=function(){if(typeof self!=="undefined"){delete self.Module}Module=jsModule=wasmMemory=wasmTable=asm=buffer=HEAP8=HEAPU8=HEAP16=HEAPU16=HEAP32=HEAPU32=HEAPF32=HEAPF64=undefined;if(typeof module!=="undefined"){delete module.exports}};/' dist/argon2.js perl -pi -e 's/typeof Module!=="undefined"\?Module:\{};/typeof self!=="undefined"&&typeof self.Module!=="undefined"?self.Module:{};var jsModule=Module;/g' dist/argon2.js perl -pi -e 's/receiveInstantiatedSource\(output\)\{/receiveInstantiatedSource(output){Module=jsModule;if(typeof self!=="undefined")self.Module=Module;/g' dist/argon2.js diff --git a/lib/em-post.js b/lib/em-post.js new file mode 100644 index 0000000..9fcbd54 --- /dev/null +++ b/lib/em-post.js @@ -0,0 +1,8 @@ +if (typeof module !== "undefined") module.exports = Module; + +Module.unloadRuntime = function() { + if (typeof self!=="undefined") delete self.Module; + Module = jsModule = wasmMemory = wasmTable = asm = buffer = HEAP8 = HEAPU8 = + HEAP16 = HEAPU16 = HEAP32 = HEAPU32 = HEAPF32 = HEAPF64 = undefined; + if (typeof module!=="undefined") delete module.exports; +}; From 692ee12b6c9132128ed10186631a1f1f0c9a0f71 Mon Sep 17 00:00:00 2001 From: Denis Davidyuk Date: Sat, 5 Feb 2022 10:44:00 +0300 Subject: [PATCH 03/12] remove outdated receiveInstantiatedSource replace patch Because can't find receiveInstantiatedSource in dist/argon2.js --- build-wasm.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/build-wasm.sh b/build-wasm.sh index 8d17f10..a0d26a4 100755 --- a/build-wasm.sh +++ b/build-wasm.sh @@ -32,4 +32,3 @@ shasum dist/argon2.js shasum dist/argon2.wasm perl -pi -e 's/typeof Module!=="undefined"\?Module:\{};/typeof self!=="undefined"&&typeof self.Module!=="undefined"?self.Module:{};var jsModule=Module;/g' dist/argon2.js -perl -pi -e 's/receiveInstantiatedSource\(output\)\{/receiveInstantiatedSource(output){Module=jsModule;if(typeof self!=="undefined")self.Module=Module;/g' dist/argon2.js From adfd860dbf0419d3fcb1a1dad3691a1ded7c3565 Mon Sep 17 00:00:00 2001 From: Denis Davidyuk Date: Sat, 5 Feb 2022 10:55:42 +0300 Subject: [PATCH 04/12] wrap emscripten module with a function to don't use globals --- .gitignore | 2 ++ CMakeLists.txt | 1 + build-wasm.sh | 2 -- lib/argon2.js | 25 ++++++++----------------- lib/em-post.js | 5 +++-- lib/em-pre.js | 3 +++ 6 files changed, 17 insertions(+), 21 deletions(-) create mode 100644 lib/em-pre.js diff --git a/.gitignore b/.gitignore index 7c46178..9994233 100644 --- a/.gitignore +++ b/.gitignore @@ -30,5 +30,7 @@ test/webpack/node_modules/ test/webpack/dist/ *.tgz package/ +em-pre_js_tracker.c +libargon2_1_em-pre_js.a em-post_js_tracker.c libargon2_1_em-post_js.a diff --git a/CMakeLists.txt b/CMakeLists.txt index 7549b0b..b886367 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,4 +32,5 @@ add_executable(argon2 ${sources}) set_target_properties(argon2 PROPERTIES OUTPUT_NAME ${OUTPUT_NAME}) +em_link_pre_js(argon2 lib/em-pre.js) em_link_post_js(argon2 lib/em-post.js) diff --git a/build-wasm.sh b/build-wasm.sh index a0d26a4..e461fcd 100755 --- a/build-wasm.sh +++ b/build-wasm.sh @@ -30,5 +30,3 @@ cmake --build . shasum dist/argon2.js shasum dist/argon2.wasm - -perl -pi -e 's/typeof Module!=="undefined"\?Module:\{};/typeof self!=="undefined"&&typeof self.Module!=="undefined"?self.Module:{};var jsModule=Module;/g' dist/argon2.js diff --git a/lib/argon2.js b/lib/argon2.js index 98d3fb0..37f66ef 100644 --- a/lib/argon2.js +++ b/lib/argon2.js @@ -31,16 +31,11 @@ global.process.versions && global.process.versions.node ) { - promise = loadWasmModule().then( - (Module) => - new Promise((resolve) => { - Module.postRun = () => resolve(Module); - }) - ); + promise = initWasm(); } else { promise = loadWasmBinary().then((wasmBinary) => { const wasmMemory = mem ? createWasmMemory(mem) : undefined; - return initWasm(wasmBinary, wasmMemory); + return initWasm({ wasmBinary, wasmMemory }); }); } loadModule._promise = promise; @@ -51,16 +46,12 @@ }); } - function initWasm(wasmBinary, wasmMemory) { - return new Promise((resolve) => { - global.Module = { - wasmBinary, - wasmMemory, - postRun() { - resolve(Module); - }, - }; - return loadWasmModule(); + function initWasm(options) { + return loadWasmModule().then(genModule => { + const module = genModule(options); + return new Promise(resolve => { + module.postRun = () => resolve(module); + }) }); } diff --git a/lib/em-post.js b/lib/em-post.js index 9fcbd54..2d623c2 100644 --- a/lib/em-post.js +++ b/lib/em-post.js @@ -1,8 +1,9 @@ -if (typeof module !== "undefined") module.exports = Module; - Module.unloadRuntime = function() { if (typeof self!=="undefined") delete self.Module; Module = jsModule = wasmMemory = wasmTable = asm = buffer = HEAP8 = HEAPU8 = HEAP16 = HEAPU16 = HEAP32 = HEAPU32 = HEAPF32 = HEAPF64 = undefined; if (typeof module!=="undefined") delete module.exports; }; + +return Module; +} diff --git a/lib/em-pre.js b/lib/em-pre.js new file mode 100644 index 0000000..c30a140 --- /dev/null +++ b/lib/em-pre.js @@ -0,0 +1,3 @@ +module.exports = function (Module) { + Module = Module || {}; + const module = undefined; From ee9d0c3eb67f008ffc0c26d020453c5736e7f85e Mon Sep 17 00:00:00 2001 From: Denis Davidyuk Date: Sat, 5 Feb 2022 10:56:46 +0300 Subject: [PATCH 05/12] use inlined wasm in nodejs --- lib/argon2.js | 1 + test/node-bundled.js | 12 ++++++++++++ test/node.js | 11 ++++++++--- webpack.config.js | 10 ++++++---- 4 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 test/node-bundled.js diff --git a/lib/argon2.js b/lib/argon2.js index 37f66ef..834ba32 100644 --- a/lib/argon2.js +++ b/lib/argon2.js @@ -27,6 +27,7 @@ } let promise; if ( + typeof IS_WASM_INLINED === 'undefined' && global.process && global.process.versions && global.process.versions.node diff --git a/test/node-bundled.js b/test/node-bundled.js new file mode 100644 index 0000000..f8e082e --- /dev/null +++ b/test/node-bundled.js @@ -0,0 +1,12 @@ +describe('Node.js bundled', function () { + global.chai = require('chai'); + + before(() => { + global.argon2 = require('../dist/argon2-bundled.min'); + }); + + ['./suite/hash', './suite/verify'].forEach((name) => { + delete require.cache[require.resolve(name)]; + require(name); + }); +}); diff --git a/test/node.js b/test/node.js index 8e2d58d..caa9760 100644 --- a/test/node.js +++ b/test/node.js @@ -1,7 +1,12 @@ describe('Node.js', function() { global.chai = require('chai'); - global.argon2 = require('..'); - require('./suite/hash'); - require('./suite/verify'); + before(() => { + global.argon2 = require('..'); + }); + + ['./suite/hash', './suite/verify'].forEach((name) => { + delete require.cache[require.resolve(name)]; + require(name); + }); }); diff --git a/webpack.config.js b/webpack.config.js index 1117441..ae21523 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,3 +1,4 @@ +const webpack = require('webpack'); const path = require('path'); module.exports = { @@ -23,10 +24,11 @@ module.exports = { }, ], }, - externals: { - path: 'path', - fs: 'fs', - }, + plugins: [ + new webpack.DefinePlugin({ + IS_WASM_INLINED: true, + }), + ], resolve: { fallback: { path: false, From 74a6f3c62b6d7bc839bd534a7a161e8d1f40cf1c Mon Sep 17 00:00:00 2001 From: Denis Davidyuk Date: Sun, 6 Feb 2022 15:56:04 +0300 Subject: [PATCH 06/12] remove module definition header in lib/argon2 --- lib/argon2.js | 630 +++++++++++++++++++++++++------------------------- 1 file changed, 309 insertions(+), 321 deletions(-) diff --git a/lib/argon2.js b/lib/argon2.js index 834ba32..fea1cd6 100644 --- a/lib/argon2.js +++ b/lib/argon2.js @@ -1,358 +1,346 @@ -(function (root, factory) { - if (typeof define === 'function' && define.amd) { - define([], factory); - } else if (typeof module === 'object' && module.exports) { - module.exports = factory(); +/** + * @enum + */ +const ArgonType = { + Argon2d: 0, + Argon2i: 1, + Argon2id: 2, +}; + +function loadModule(mem) { + if (loadModule._promise) { + return loadModule._promise; + } + if (loadModule._module) { + return Promise.resolve(loadModule._module); + } + let promise; + if ( + typeof IS_WASM_INLINED === 'undefined' && + global.process && + global.process.versions && + global.process.versions.node + ) { + promise = initWasm(); } else { - root.argon2 = factory(); + promise = loadWasmBinary().then((wasmBinary) => { + const wasmMemory = mem ? createWasmMemory(mem) : undefined; + return initWasm({ wasmBinary, wasmMemory }); + }); } -})(typeof self !== 'undefined' ? self : this, function () { - const global = typeof self !== 'undefined' ? self : this; + loadModule._promise = promise; + return promise.then((Module) => { + loadModule._module = Module; + delete loadModule._promise; + return Module; + }); +} - /** - * @enum - */ - const ArgonType = { - Argon2d: 0, - Argon2i: 1, - Argon2id: 2, - }; +function initWasm(options) { + return loadWasmModule().then(genModule => { + const module = genModule(options); + return new Promise(resolve => { + module.postRun = () => resolve(module); + }) + }); +} - function loadModule(mem) { - if (loadModule._promise) { - return loadModule._promise; - } - if (loadModule._module) { - return Promise.resolve(loadModule._module); - } - let promise; - if ( - typeof IS_WASM_INLINED === 'undefined' && - global.process && - global.process.versions && - global.process.versions.node - ) { - promise = initWasm(); - } else { - promise = loadWasmBinary().then((wasmBinary) => { - const wasmMemory = mem ? createWasmMemory(mem) : undefined; - return initWasm({ wasmBinary, wasmMemory }); - }); - } - loadModule._promise = promise; - return promise.then((Module) => { - loadModule._module = Module; - delete loadModule._promise; - return Module; - }); +function loadWasmModule() { + if (global.loadArgon2WasmModule) { + return global.loadArgon2WasmModule(); } - - function initWasm(options) { - return loadWasmModule().then(genModule => { - const module = genModule(options); - return new Promise(resolve => { - module.postRun = () => resolve(module); - }) - }); + if (typeof require === 'function') { + return Promise.resolve(require('../dist/argon2.js')); } + return import('../dist/argon2.js'); +} - function loadWasmModule() { - if (global.loadArgon2WasmModule) { - return global.loadArgon2WasmModule(); - } - if (typeof require === 'function') { - return Promise.resolve(require('../dist/argon2.js')); - } - return import('../dist/argon2.js'); +function loadWasmBinary() { + if (global.loadArgon2WasmBinary) { + return global.loadArgon2WasmBinary(); } - - function loadWasmBinary() { - if (global.loadArgon2WasmBinary) { - return global.loadArgon2WasmBinary(); - } - if (typeof require === 'function') { - return Promise.resolve(require('../dist/argon2.wasm')).then( - (wasmModule) => { - return decodeWasmBinary(wasmModule); - } - ); - } - const wasmPath = - global.argon2WasmPath || - 'node_modules/argon2-browser/dist/argon2.wasm'; - return fetch(wasmPath) - .then((response) => response.arrayBuffer()) - .then((ab) => new Uint8Array(ab)); + if (typeof require === 'function') { + return Promise.resolve(require('../dist/argon2.wasm')).then( + (wasmModule) => { + return decodeWasmBinary(wasmModule); + } + ); } + const wasmPath = + global.argon2WasmPath || + 'node_modules/argon2-browser/dist/argon2.wasm'; + return fetch(wasmPath) + .then((response) => response.arrayBuffer()) + .then((ab) => new Uint8Array(ab)); +} - function decodeWasmBinary(base64) { - if (typeof Buffer === 'function') { - return new Uint8Array(Buffer.from(base64, 'base64')); - } - const text = atob(base64); - const binary = new Uint8Array(new ArrayBuffer(text.length)); - for (let i = 0; i < text.length; i++) { - binary[i] = text.charCodeAt(i); - } - return binary; +function decodeWasmBinary(base64) { + if (typeof Buffer === 'function') { + return new Uint8Array(Buffer.from(base64, 'base64')); } + const text = atob(base64); + const binary = new Uint8Array(new ArrayBuffer(text.length)); + for (let i = 0; i < text.length; i++) { + binary[i] = text.charCodeAt(i); + } + return binary; +} - function createWasmMemory(mem) { - const KB = 1024; - const MB = 1024 * KB; - const GB = 1024 * MB; - const WASM_PAGE_SIZE = 64 * KB; +function createWasmMemory(mem) { + const KB = 1024; + const MB = 1024 * KB; + const GB = 1024 * MB; + const WASM_PAGE_SIZE = 64 * KB; - const totalMemory = (2 * GB - 64 * KB) / WASM_PAGE_SIZE; - const initialMemory = Math.min( - Math.max(Math.ceil((mem * KB) / WASM_PAGE_SIZE), 256) + 256, - totalMemory - ); + const totalMemory = (2 * GB - 64 * KB) / WASM_PAGE_SIZE; + const initialMemory = Math.min( + Math.max(Math.ceil((mem * KB) / WASM_PAGE_SIZE), 256) + 256, + totalMemory + ); - return new WebAssembly.Memory({ - initial: initialMemory, - maximum: totalMemory, - }); - } + return new WebAssembly.Memory({ + initial: initialMemory, + maximum: totalMemory, + }); +} - function allocateArray(Module, arr) { - return Module.allocate(arr, 'i8', Module.ALLOC_NORMAL); - } +function allocateArray(Module, arr) { + return Module.allocate(arr, 'i8', Module.ALLOC_NORMAL); +} - function allocateArrayStr(Module, arr) { - const nullTerminatedArray = new Uint8Array([...arr, 0]); - return allocateArray(Module, nullTerminatedArray); - } +function allocateArrayStr(Module, arr) { + const nullTerminatedArray = new Uint8Array([...arr, 0]); + return allocateArray(Module, nullTerminatedArray); +} - function encodeUtf8(str) { - if (typeof str !== 'string') { - return str; - } - if (typeof TextEncoder === 'function') { - return new TextEncoder().encode(str); - } else if (typeof Buffer === 'function') { - return Buffer.from(str); - } else { - throw new Error("Don't know how to encode UTF8"); - } +function encodeUtf8(str) { + if (typeof str !== 'string') { + return str; + } + if (typeof TextEncoder === 'function') { + return new TextEncoder().encode(str); + } else if (typeof Buffer === 'function') { + return Buffer.from(str); + } else { + throw new Error("Don't know how to encode UTF8"); } +} - /** - * Argon2 hash - * @param {string|Uint8Array} params.pass - password string - * @param {string|Uint8Array} params.salt - salt string - * @param {number} [params.time=1] - the number of iterations - * @param {number} [params.mem=1024] - used memory, in KiB - * @param {number} [params.hashLen=24] - desired hash length - * @param {number} [params.parallelism=1] - desired parallelism - * @param {number} [params.type=argon2.ArgonType.Argon2d] - hash type: - * argon2.ArgonType.Argon2d - * argon2.ArgonType.Argon2i - * argon2.ArgonType.Argon2id - * - * @return Promise - * - * @example - * argon2.hash({ pass: 'password', salt: 'somesalt' }) - * .then(h => console.log(h.hash, h.hashHex, h.encoded)) - * .catch(e => console.error(e.message, e.code)) - */ - function argon2Hash(params) { - const mCost = params.mem || 1024; - return loadModule(mCost).then((Module) => { - const tCost = params.time || 1; - const parallelism = params.parallelism || 1; - const pwdEncoded = encodeUtf8(params.pass); - const pwd = allocateArrayStr(Module, pwdEncoded); - const pwdlen = pwdEncoded.length; - const saltEncoded = encodeUtf8(params.salt); - const salt = allocateArrayStr(Module, saltEncoded); - const saltlen = saltEncoded.length; - const argon2Type = params.type || ArgonType.Argon2d; - const hash = Module.allocate( - new Array(params.hashLen || 24), - 'i8', - Module.ALLOC_NORMAL - ); - const secret = params.secret - ? allocateArray(Module, params.secret) - : 0; - const secretlen = params.secret ? params.secret.byteLength : 0; - const ad = params.ad ? allocateArray(Module, params.ad) : 0; - const adlen = params.ad ? params.ad.byteLength : 0; - const hashlen = params.hashLen || 24; - const encodedlen = Module._argon2_encodedlen( +/** + * Argon2 hash + * @param {string|Uint8Array} params.pass - password string + * @param {string|Uint8Array} params.salt - salt string + * @param {number} [params.time=1] - the number of iterations + * @param {number} [params.mem=1024] - used memory, in KiB + * @param {number} [params.hashLen=24] - desired hash length + * @param {number} [params.parallelism=1] - desired parallelism + * @param {number} [params.type=argon2.ArgonType.Argon2d] - hash type: + * argon2.ArgonType.Argon2d + * argon2.ArgonType.Argon2i + * argon2.ArgonType.Argon2id + * + * @return Promise + * + * @example + * argon2.hash({ pass: 'password', salt: 'somesalt' }) + * .then(h => console.log(h.hash, h.hashHex, h.encoded)) + * .catch(e => console.error(e.message, e.code)) + */ +function argon2Hash(params) { + const mCost = params.mem || 1024; + return loadModule(mCost).then((Module) => { + const tCost = params.time || 1; + const parallelism = params.parallelism || 1; + const pwdEncoded = encodeUtf8(params.pass); + const pwd = allocateArrayStr(Module, pwdEncoded); + const pwdlen = pwdEncoded.length; + const saltEncoded = encodeUtf8(params.salt); + const salt = allocateArrayStr(Module, saltEncoded); + const saltlen = saltEncoded.length; + const argon2Type = params.type || ArgonType.Argon2d; + const hash = Module.allocate( + new Array(params.hashLen || 24), + 'i8', + Module.ALLOC_NORMAL + ); + const secret = params.secret + ? allocateArray(Module, params.secret) + : 0; + const secretlen = params.secret ? params.secret.byteLength : 0; + const ad = params.ad ? allocateArray(Module, params.ad) : 0; + const adlen = params.ad ? params.ad.byteLength : 0; + const hashlen = params.hashLen || 24; + const encodedlen = Module._argon2_encodedlen( + tCost, + mCost, + parallelism, + saltlen, + hashlen, + argon2Type + ); + const encoded = Module.allocate( + new Array(encodedlen + 1), + 'i8', + Module.ALLOC_NORMAL + ); + const version = 0x13; + let err; + let res; + try { + res = Module._argon2_hash_ext( tCost, mCost, parallelism, + pwd, + pwdlen, + salt, saltlen, + hash, hashlen, - argon2Type - ); - const encoded = Module.allocate( - new Array(encodedlen + 1), - 'i8', - Module.ALLOC_NORMAL + encoded, + encodedlen, + argon2Type, + secret, + secretlen, + ad, + adlen, + version ); - const version = 0x13; - let err; - let res; - try { - res = Module._argon2_hash_ext( - tCost, - mCost, - parallelism, - pwd, - pwdlen, - salt, - saltlen, - hash, - hashlen, - encoded, - encodedlen, - argon2Type, - secret, - secretlen, - ad, - adlen, - version - ); - } catch (e) { - err = e; - } - let result; - if (res === 0 && !err) { - let hashStr = ''; - const hashArr = new Uint8Array(hashlen); - for (let i = 0; i < hashlen; i++) { - const byte = Module.HEAP8[hash + i]; - hashArr[i] = byte; - hashStr += ('0' + (0xff & byte).toString(16)).slice(-2); - } - const encodedStr = Module.UTF8ToString(encoded); - result = { - hash: hashArr, - hashHex: hashStr, - encoded: encodedStr, - }; - } else { - try { - if (!err) { - err = Module.UTF8ToString( - Module._argon2_error_message(res) - ); - } - } catch (e) {} - result = { message: err, code: res }; + } catch (e) { + err = e; + } + let result; + if (res === 0 && !err) { + let hashStr = ''; + const hashArr = new Uint8Array(hashlen); + for (let i = 0; i < hashlen; i++) { + const byte = Module.HEAP8[hash + i]; + hashArr[i] = byte; + hashStr += ('0' + (0xff & byte).toString(16)).slice(-2); } + const encodedStr = Module.UTF8ToString(encoded); + result = { + hash: hashArr, + hashHex: hashStr, + encoded: encodedStr, + }; + } else { try { - Module._free(pwd); - Module._free(salt); - Module._free(hash); - Module._free(encoded); - if (ad) { - Module._free(ad); - } - if (secret) { - Module._free(secret); + if (!err) { + err = Module.UTF8ToString( + Module._argon2_error_message(res) + ); } } catch (e) {} - if (err) { - throw result; - } else { - return result; + result = { message: err, code: res }; + } + try { + Module._free(pwd); + Module._free(salt); + Module._free(hash); + Module._free(encoded); + if (ad) { + Module._free(ad); } - }); - } - - /** - * Argon2 verify function - * @param {string} params.pass - password string - * @param {string|Uint8Array} params.encoded - encoded hash - * @param {number} [params.type=argon2.ArgonType.Argon2d] - hash type: - * argon2.ArgonType.Argon2d - * argon2.ArgonType.Argon2i - * argon2.ArgonType.Argon2id - * - * @returns Promise - * - * @example - * argon2.verify({ pass: 'password', encoded: 'encoded-hash' }) - * .then(() => console.log('OK')) - * .catch(e => console.error(e.message, e.code)) - */ - function argon2Verify(params) { - return loadModule().then((Module) => { - const pwdEncoded = encodeUtf8(params.pass); - const pwd = allocateArrayStr(Module, pwdEncoded); - const pwdlen = pwdEncoded.length; - const secret = params.secret - ? allocateArray(Module, params.secret) - : 0; - const secretlen = params.secret ? params.secret.byteLength : 0; - const ad = params.ad ? allocateArray(Module, params.ad) : 0; - const adlen = params.ad ? params.ad.byteLength : 0; - const encEncoded = encodeUtf8(params.encoded); - const enc = allocateArrayStr(Module, encEncoded); - let argon2Type = params.type; - if (argon2Type === undefined) { - let typeStr = params.encoded.split('$')[1]; - if (typeStr) { - typeStr = typeStr.replace('a', 'A'); - argon2Type = ArgonType[typeStr] || ArgonType.Argon2d; - } + if (secret) { + Module._free(secret); } - let err; - let res; - try { - res = Module._argon2_verify_ext( - enc, - pwd, - pwdlen, - secret, - secretlen, - ad, - adlen, - argon2Type - ); - } catch (e) { - err = e; - } - let result; - if (res || err) { - try { - if (!err) { - err = Module.UTF8ToString( - Module._argon2_error_message(res) - ); - } - } catch (e) {} - result = { message: err, code: res }; + } catch (e) {} + if (err) { + throw result; + } else { + return result; + } + }); +} + +/** + * Argon2 verify function + * @param {string} params.pass - password string + * @param {string|Uint8Array} params.encoded - encoded hash + * @param {number} [params.type=argon2.ArgonType.Argon2d] - hash type: + * argon2.ArgonType.Argon2d + * argon2.ArgonType.Argon2i + * argon2.ArgonType.Argon2id + * + * @returns Promise + * + * @example + * argon2.verify({ pass: 'password', encoded: 'encoded-hash' }) + * .then(() => console.log('OK')) + * .catch(e => console.error(e.message, e.code)) + */ +function argon2Verify(params) { + return loadModule().then((Module) => { + const pwdEncoded = encodeUtf8(params.pass); + const pwd = allocateArrayStr(Module, pwdEncoded); + const pwdlen = pwdEncoded.length; + const secret = params.secret + ? allocateArray(Module, params.secret) + : 0; + const secretlen = params.secret ? params.secret.byteLength : 0; + const ad = params.ad ? allocateArray(Module, params.ad) : 0; + const adlen = params.ad ? params.ad.byteLength : 0; + const encEncoded = encodeUtf8(params.encoded); + const enc = allocateArrayStr(Module, encEncoded); + let argon2Type = params.type; + if (argon2Type === undefined) { + let typeStr = params.encoded.split('$')[1]; + if (typeStr) { + typeStr = typeStr.replace('a', 'A'); + argon2Type = ArgonType[typeStr] || ArgonType.Argon2d; } + } + let err; + let res; + try { + res = Module._argon2_verify_ext( + enc, + pwd, + pwdlen, + secret, + secretlen, + ad, + adlen, + argon2Type + ); + } catch (e) { + err = e; + } + let result; + if (res || err) { try { - Module._free(pwd); - Module._free(enc); + if (!err) { + err = Module.UTF8ToString( + Module._argon2_error_message(res) + ); + } } catch (e) {} - if (err) { - throw result; - } else { - return result; - } - }); - } - - function unloadRuntime() { - if (loadModule._module) { - loadModule._module.unloadRuntime(); - delete loadModule._promise; - delete loadModule._module; + result = { message: err, code: res }; + } + try { + Module._free(pwd); + Module._free(enc); + } catch (e) {} + if (err) { + throw result; + } else { + return result; } + }); +} + +function unloadRuntime() { + if (loadModule._module) { + loadModule._module.unloadRuntime(); + delete loadModule._promise; + delete loadModule._module; } +} - return { - ArgonType, - hash: argon2Hash, - verify: argon2Verify, - unloadRuntime, - }; -}); +module.exports = { + ArgonType, + hash: argon2Hash, + verify: argon2Verify, + unloadRuntime, +}; From 8012af73faf60ad095b3667ea21ec2490a8933ca Mon Sep 17 00:00:00 2001 From: Denis Davidyuk Date: Sun, 6 Feb 2022 16:09:18 +0300 Subject: [PATCH 07/12] build lib/argon2 using webpack to fix importing of em module in browser --- .github/workflows/build.yaml | 4 +- README.md | 4 +- examples/vanilla/index.html | 2 +- lib/argon2.js | 66 ++++++++------------- package-lock.json | 111 +++++++++++++++++++++++++++++++++++ package.json | 5 +- test/vanilla/index.html | 2 +- webpack.config.js | 31 +++++----- 8 files changed, 160 insertions(+), 65 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 7915977..18db7a6 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -25,10 +25,10 @@ jobs: run: npm ci - name: Build run: source emsdk/emsdk_env.sh && ./build.sh + - name: Bundle + run: npm run build - name: Test run: npm test - - name: Bundle - run: npm run build-bundle - name: Package run: npm pack - name: Publish to npm diff --git a/README.md b/README.md index c18a323..67505df 100644 --- a/README.md +++ b/README.md @@ -77,12 +77,12 @@ npm install argon2-browser Then add this script to your HTML or use your favorite bundler: ```html - + ``` Alternatively, you can use the bundled version, this way you can include just one script: ```html - + ``` Calculate the hash: diff --git a/examples/vanilla/index.html b/examples/vanilla/index.html index 1785a47..e9d7ebf 100644 --- a/examples/vanilla/index.html +++ b/examples/vanilla/index.html @@ -3,7 +3,7 @@ Argon2 Browser VanillaJS Demo - +

Argon2-Browser WebPack Demo

diff --git a/lib/argon2.js b/lib/argon2.js index fea1cd6..aa226af 100644 --- a/lib/argon2.js +++ b/lib/argon2.js @@ -1,12 +1,17 @@ +import genModule from '../dist/argon2'; +import wasmEncoded from '../dist/argon2.wasm'; + /** * @enum */ -const ArgonType = { +export const ArgonType = { Argon2d: 0, Argon2i: 1, Argon2id: 2, }; +const isWasmInlined = typeof wasmEncoded === 'string'; + function loadModule(mem) { if (loadModule._promise) { return loadModule._promise; @@ -16,10 +21,10 @@ function loadModule(mem) { } let promise; if ( - typeof IS_WASM_INLINED === 'undefined' && - global.process && - global.process.versions && - global.process.versions.node + !isWasmInlined && + typeof process === 'object' && + process.versions && + process.versions.node ) { promise = initWasm(); } else { @@ -37,38 +42,24 @@ function loadModule(mem) { } function initWasm(options) { - return loadWasmModule().then(genModule => { - const module = genModule(options); - return new Promise(resolve => { - module.postRun = () => resolve(module); - }) + const module = genModule(options); + return new Promise(resolve => { + module.postRun = () => resolve(module); }); } -function loadWasmModule() { - if (global.loadArgon2WasmModule) { - return global.loadArgon2WasmModule(); - } - if (typeof require === 'function') { - return Promise.resolve(require('../dist/argon2.js')); - } - return import('../dist/argon2.js'); -} - function loadWasmBinary() { - if (global.loadArgon2WasmBinary) { - return global.loadArgon2WasmBinary(); + if (typeof loadArgon2WasmBinary === 'function') { + return loadArgon2WasmBinary(); } - if (typeof require === 'function') { - return Promise.resolve(require('../dist/argon2.wasm')).then( - (wasmModule) => { - return decodeWasmBinary(wasmModule); - } - ); + const _wasmEncoded = isWasmInlined && wasmEncoded + || typeof __non_webpack_require__ === 'function' + && __non_webpack_require__('../dist/argon2.wasm'); + if (_wasmEncoded) { + return Promise.resolve(decodeWasmBinary(_wasmEncoded)); } - const wasmPath = - global.argon2WasmPath || - 'node_modules/argon2-browser/dist/argon2.wasm'; + const wasmPath = typeof argon2WasmPath === 'string' + ? argon2WasmPath : 'node_modules/argon2-browser/dist/argon2.wasm'; return fetch(wasmPath) .then((response) => response.arrayBuffer()) .then((ab) => new Uint8Array(ab)); @@ -146,7 +137,7 @@ function encodeUtf8(str) { * .then(h => console.log(h.hash, h.hashHex, h.encoded)) * .catch(e => console.error(e.message, e.code)) */ -function argon2Hash(params) { +export function hash(params) { const mCost = params.mem || 1024; return loadModule(mCost).then((Module) => { const tCost = params.time || 1; @@ -270,7 +261,7 @@ function argon2Hash(params) { * .then(() => console.log('OK')) * .catch(e => console.error(e.message, e.code)) */ -function argon2Verify(params) { +export function verify(params) { return loadModule().then((Module) => { const pwdEncoded = encodeUtf8(params.pass); const pwd = allocateArrayStr(Module, pwdEncoded); @@ -330,17 +321,10 @@ function argon2Verify(params) { }); } -function unloadRuntime() { +export function unloadRuntime() { if (loadModule._module) { loadModule._module.unloadRuntime(); delete loadModule._promise; delete loadModule._module; } } - -module.exports = { - ArgonType, - hash: argon2Hash, - verify: argon2Verify, - unloadRuntime, -}; diff --git a/package-lock.json b/package-lock.json index f1df357..dccb8a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,6 +5,7 @@ "requires": true, "packages": { "": { + "name": "argon2-browser", "version": "1.18.0", "license": "MIT", "devDependencies": { @@ -12,6 +13,7 @@ "chai": "^4.3.4", "http-server": "^0.12.3", "mocha": "^8.4.0", + "null-loader": "^4.0.1", "prettier": "^2.3.0", "puppeteer": "^9.1.1", "webpack": "^5.37.1", @@ -435,6 +437,15 @@ "node": ">= 0.6" } }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -816,6 +827,15 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -1482,6 +1502,21 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, + "node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -1500,6 +1535,20 @@ "node": ">=6.11.5" } }, + "node_modules/loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -1762,6 +1811,26 @@ "node": ">=8" } }, + "node_modules/null-loader": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/null-loader/-/null-loader-4.0.1.tgz", + "integrity": "sha512-pxqVbi4U6N26lq+LmgIbB5XATP0VdZKOG25DhHi8btMmJJefGArFyDg1yc4U3hWCJbMqSrw0qyrz1UQX+qYXqg==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3238,6 +3307,12 @@ "integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=", "dev": true }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -3545,6 +3620,12 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, "end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -4051,6 +4132,15 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -4063,6 +4153,17 @@ "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", "dev": true }, + "loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -4262,6 +4363,16 @@ "path-key": "^3.0.0" } }, + "null-loader": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/null-loader/-/null-loader-4.0.1.tgz", + "integrity": "sha512-pxqVbi4U6N26lq+LmgIbB5XATP0VdZKOG25DhHi8btMmJJefGArFyDg1yc4U3hWCJbMqSrw0qyrz1UQX+qYXqg==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", diff --git a/package.json b/package.json index 51ff9b4..2ead52f 100644 --- a/package.json +++ b/package.json @@ -2,14 +2,14 @@ "name": "argon2-browser", "version": "1.18.0", "description": "Argon2 library compiled for browser runtime", - "main": "lib/argon2.js", + "main": "dist/argon2.min.js", "directories": { "doc": "docs", "lib": "lib" }, "scripts": { "test": "mocha", - "build-bundle": "webpack" + "build": "webpack" }, "repository": { "type": "git", @@ -26,6 +26,7 @@ "chai": "^4.3.4", "http-server": "^0.12.3", "mocha": "^8.4.0", + "null-loader": "^4.0.1", "prettier": "^2.3.0", "puppeteer": "^9.1.1", "webpack": "^5.37.1", diff --git a/test/vanilla/index.html b/test/vanilla/index.html index d1fb12b..7319a86 100644 --- a/test/vanilla/index.html +++ b/test/vanilla/index.html @@ -13,7 +13,7 @@ - + diff --git a/webpack.config.js b/webpack.config.js index ae21523..49b76bc 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,7 +1,6 @@ -const webpack = require('webpack'); const path = require('path'); -module.exports = { +const getConfig = (inlineWasm) => ({ mode: 'production', entry: './lib/argon2.js', output: { @@ -12,23 +11,20 @@ module.exports = { globalObject: 'this', path: path.resolve(__dirname, 'dist'), publicPath: 'dist/', - filename: 'argon2-bundled.min.js', + filename: inlineWasm ? 'argon2-bundled.min.js' : 'argon2.min.js', }, module: { noParse: /\.wasm$/, - rules: [ - { - test: /\.wasm$/, - loader: 'base64-loader', - type: 'javascript/auto', - }, - ], + rules: [{ + test: /\.wasm$/, + loader: inlineWasm ? 'base64-loader' : 'null-loader', + type: 'javascript/auto', + }], + }, + externals: { + path: 'path', + fs: 'fs', }, - plugins: [ - new webpack.DefinePlugin({ - IS_WASM_INLINED: true, - }), - ], resolve: { fallback: { path: false, @@ -37,4 +33,7 @@ module.exports = { process: false, }, }, -}; + node: false, +}); + +module.exports = [getConfig(true), getConfig(false)]; From 82c3eb234d4fc5725cdba0ddb6e1524b5a0deb1c Mon Sep 17 00:00:00 2001 From: Denis Davidyuk Date: Sun, 6 Feb 2022 17:32:22 +0300 Subject: [PATCH 08/12] fix docs by wrapping emscripten module with custom webpack loader --- .gitignore | 4 ---- CMakeLists.txt | 3 --- lib/em-post.js | 9 --------- lib/em-pre.js | 3 --- webpack.config.js | 5 +++++ wrap-em.js | 16 ++++++++++++++++ 6 files changed, 21 insertions(+), 19 deletions(-) delete mode 100644 lib/em-post.js delete mode 100644 lib/em-pre.js create mode 100644 wrap-em.js diff --git a/.gitignore b/.gitignore index 9994233..e946538 100644 --- a/.gitignore +++ b/.gitignore @@ -30,7 +30,3 @@ test/webpack/node_modules/ test/webpack/dist/ *.tgz package/ -em-pre_js_tracker.c -libargon2_1_em-pre_js.a -em-post_js_tracker.c -libargon2_1_em-post_js.a diff --git a/CMakeLists.txt b/CMakeLists.txt index b886367..839cfe4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,3 @@ endif() add_executable(argon2 ${sources}) set_target_properties(argon2 PROPERTIES OUTPUT_NAME ${OUTPUT_NAME}) - -em_link_pre_js(argon2 lib/em-pre.js) -em_link_post_js(argon2 lib/em-post.js) diff --git a/lib/em-post.js b/lib/em-post.js deleted file mode 100644 index 2d623c2..0000000 --- a/lib/em-post.js +++ /dev/null @@ -1,9 +0,0 @@ -Module.unloadRuntime = function() { - if (typeof self!=="undefined") delete self.Module; - Module = jsModule = wasmMemory = wasmTable = asm = buffer = HEAP8 = HEAPU8 = - HEAP16 = HEAPU16 = HEAP32 = HEAPU32 = HEAPF32 = HEAPF64 = undefined; - if (typeof module!=="undefined") delete module.exports; -}; - -return Module; -} diff --git a/lib/em-pre.js b/lib/em-pre.js deleted file mode 100644 index c30a140..0000000 --- a/lib/em-pre.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = function (Module) { - Module = Module || {}; - const module = undefined; diff --git a/webpack.config.js b/webpack.config.js index 49b76bc..1186836 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -19,6 +19,11 @@ const getConfig = (inlineWasm) => ({ test: /\.wasm$/, loader: inlineWasm ? 'base64-loader' : 'null-loader', type: 'javascript/auto', + }, { + test: /dist\/argon2\.js$/, + use: [{ + loader: path.resolve('wrap-em.js'), + }] }], }, externals: { diff --git a/wrap-em.js b/wrap-em.js new file mode 100644 index 0000000..08c76da --- /dev/null +++ b/wrap-em.js @@ -0,0 +1,16 @@ +module.exports = (em) => ` +module.exports = function (Module) { + Module = Module || {}; + const module = undefined; + +${em} + + Module.unloadRuntime = function() { + if (typeof self!=="undefined") delete self.Module; + Module = jsModule = wasmMemory = wasmTable = asm = buffer = HEAP8 = HEAPU8 = + HEAP16 = HEAPU16 = HEAP32 = HEAPU32 = HEAPF32 = HEAPF64 = undefined; + if (typeof module!=="undefined") delete module.exports; + }; + + return Module; +}`; From a60d2cfdc6c63f1e697b2cbe1f3b53087396c970 Mon Sep 17 00:00:00 2001 From: Denis Davidyuk Date: Mon, 7 Feb 2022 09:54:19 +0300 Subject: [PATCH 09/12] use webpack.DefinePlugin to remove bare require of wasm in bundled --- lib/argon2.js | 11 +++++------ webpack.config.js | 6 ++++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/argon2.js b/lib/argon2.js index aa226af..82a1c8d 100644 --- a/lib/argon2.js +++ b/lib/argon2.js @@ -10,8 +10,6 @@ export const ArgonType = { Argon2id: 2, }; -const isWasmInlined = typeof wasmEncoded === 'string'; - function loadModule(mem) { if (loadModule._promise) { return loadModule._promise; @@ -21,7 +19,7 @@ function loadModule(mem) { } let promise; if ( - !isWasmInlined && + !IS_WASM_INLINED && typeof process === 'object' && process.versions && process.versions.node @@ -52,9 +50,10 @@ function loadWasmBinary() { if (typeof loadArgon2WasmBinary === 'function') { return loadArgon2WasmBinary(); } - const _wasmEncoded = isWasmInlined && wasmEncoded - || typeof __non_webpack_require__ === 'function' - && __non_webpack_require__('../dist/argon2.wasm'); + const _wasmEncoded = IS_WASM_INLINED + ? wasmEncoded + : typeof __non_webpack_require__ === 'function' + && __non_webpack_require__('../dist/argon2.wasm'); if (_wasmEncoded) { return Promise.resolve(decodeWasmBinary(_wasmEncoded)); } diff --git a/webpack.config.js b/webpack.config.js index 1186836..217783a 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,4 +1,5 @@ const path = require('path'); +const webpack = require('webpack'); const getConfig = (inlineWasm) => ({ mode: 'production', @@ -26,6 +27,11 @@ const getConfig = (inlineWasm) => ({ }] }], }, + plugins: [ + new webpack.DefinePlugin({ + IS_WASM_INLINED: JSON.stringify(inlineWasm), + }), + ], externals: { path: 'path', fs: 'fs', From abc208814558b03a46bead5971c0774eb33cddb8 Mon Sep 17 00:00:00 2001 From: Denis Davidyuk Date: Mon, 7 Feb 2022 09:59:04 +0300 Subject: [PATCH 10/12] don't require path package in bundled version --- webpack.config.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/webpack.config.js b/webpack.config.js index 217783a..1d507e5 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -32,10 +32,12 @@ const getConfig = (inlineWasm) => ({ IS_WASM_INLINED: JSON.stringify(inlineWasm), }), ], - externals: { - path: 'path', - fs: 'fs', - }, + externals: inlineWasm + ? {} + : { + path: 'path', + fs: 'fs', + }, resolve: { fallback: { path: false, From 84917cba15df06a2587fa64e953781bb541ec6c6 Mon Sep 17 00:00:00 2001 From: Denis Davidyuk Date: Mon, 7 Feb 2022 10:21:28 +0300 Subject: [PATCH 11/12] don't refer to "process" in bundled version --- webpack.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/webpack.config.js b/webpack.config.js index 1d507e5..9b2cc3b 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -30,6 +30,7 @@ const getConfig = (inlineWasm) => ({ plugins: [ new webpack.DefinePlugin({ IS_WASM_INLINED: JSON.stringify(inlineWasm), + ...inlineWasm && { process: 'undefined' }, }), ], externals: inlineWasm From 0820ce63436dbaaa2e6c9c23b08790f0cfc3ae19 Mon Sep 17 00:00:00 2001 From: Denis Davidyuk Date: Sat, 12 Feb 2022 09:44:20 +0300 Subject: [PATCH 12/12] add default export to fix if interpret as cjs module --- lib/argon2.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/argon2.js b/lib/argon2.js index 82a1c8d..18568b3 100644 --- a/lib/argon2.js +++ b/lib/argon2.js @@ -327,3 +327,10 @@ export function unloadRuntime() { delete loadModule._module; } } + +export default { + ArgonType, + hash, + verify, + unloadRuntime, +}