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/build-wasm.sh b/build-wasm.sh
index 270616c..e461fcd 100755
--- a/build-wasm.sh
+++ b/build-wasm.sh
@@ -30,8 +30,3 @@ 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
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 98d3fb0..18568b3 100644
--- a/lib/argon2.js
+++ b/lib/argon2.js
@@ -1,366 +1,336 @@
-(function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- define([], factory);
- } else if (typeof module === 'object' && module.exports) {
- module.exports = factory();
- } else {
- root.argon2 = factory();
- }
-})(typeof self !== 'undefined' ? self : this, function () {
- const global = typeof self !== 'undefined' ? self : this;
+import genModule from '../dist/argon2';
+import wasmEncoded from '../dist/argon2.wasm';
- /**
- * @enum
- */
- const ArgonType = {
- Argon2d: 0,
- Argon2i: 1,
- Argon2id: 2,
- };
+/**
+ * @enum
+ */
+export 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 (
- global.process &&
- global.process.versions &&
- global.process.versions.node
- ) {
- promise = loadWasmModule().then(
- (Module) =>
- new Promise((resolve) => {
- Module.postRun = () => resolve(Module);
- })
- );
- } 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 loadModule(mem) {
+ if (loadModule._promise) {
+ return loadModule._promise;
}
-
- function initWasm(wasmBinary, wasmMemory) {
- return new Promise((resolve) => {
- global.Module = {
- wasmBinary,
- wasmMemory,
- postRun() {
- resolve(Module);
- },
- };
- return loadWasmModule();
+ if (loadModule._module) {
+ return Promise.resolve(loadModule._module);
+ }
+ let promise;
+ if (
+ !IS_WASM_INLINED &&
+ typeof process === 'object' &&
+ process.versions &&
+ 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();
- }
- if (typeof require === 'function') {
- return Promise.resolve(require('../dist/argon2.js'));
- }
- return import('../dist/argon2.js');
- }
+function initWasm(options) {
+ const module = genModule(options);
+ return new Promise(resolve => {
+ module.postRun = () => resolve(module);
+ });
+}
- 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));
+function loadWasmBinary() {
+ if (typeof loadArgon2WasmBinary === 'function') {
+ return loadArgon2WasmBinary();
+ }
+ const _wasmEncoded = IS_WASM_INLINED
+ ? wasmEncoded
+ : typeof __non_webpack_require__ === 'function'
+ && __non_webpack_require__('../dist/argon2.wasm');
+ if (_wasmEncoded) {
+ return Promise.resolve(decodeWasmBinary(_wasmEncoded));
}
+ 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));
+}
- 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))
+ */
+export function hash(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;
- }
- });
- }
-
- /**
- * 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;
- }
+ result = { message: err, code: res };
+ }
+ try {
+ Module._free(pwd);
+ Module._free(salt);
+ Module._free(hash);
+ Module._free(encoded);
+ if (ad) {
+ Module._free(ad);
}
- let err;
- let res;
- try {
- res = Module._argon2_verify_ext(
- enc,
- pwd,
- pwdlen,
- secret,
- secretlen,
- ad,
- adlen,
- argon2Type
- );
- } catch (e) {
- err = e;
+ if (secret) {
+ Module._free(secret);
}
- 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))
+ */
+export function verify(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;
}
+ });
+}
+
+export function unloadRuntime() {
+ if (loadModule._module) {
+ loadModule._module.unloadRuntime();
+ delete loadModule._promise;
+ delete loadModule._module;
}
+}
- return {
- ArgonType,
- hash: argon2Hash,
- verify: argon2Verify,
- unloadRuntime,
- };
-});
+export default {
+ ArgonType,
+ hash,
+ verify,
+ 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/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/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 1117441..9b2cc3b 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,6 +1,7 @@
const path = require('path');
+const webpack = require('webpack');
-module.exports = {
+const getConfig = (inlineWasm) => ({
mode: 'production',
entry: './lib/argon2.js',
output: {
@@ -11,22 +12,33 @@ 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',
- },
- ],
- },
- externals: {
- path: 'path',
- fs: 'fs',
+ rules: [{
+ test: /\.wasm$/,
+ loader: inlineWasm ? 'base64-loader' : 'null-loader',
+ type: 'javascript/auto',
+ }, {
+ test: /dist\/argon2\.js$/,
+ use: [{
+ loader: path.resolve('wrap-em.js'),
+ }]
+ }],
},
+ plugins: [
+ new webpack.DefinePlugin({
+ IS_WASM_INLINED: JSON.stringify(inlineWasm),
+ ...inlineWasm && { process: 'undefined' },
+ }),
+ ],
+ externals: inlineWasm
+ ? {}
+ : {
+ path: 'path',
+ fs: 'fs',
+ },
resolve: {
fallback: {
path: false,
@@ -35,4 +47,7 @@ module.exports = {
process: false,
},
},
-};
+ node: false,
+});
+
+module.exports = [getConfig(true), getConfig(false)];
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;
+}`;