From 459c66ed8d32dc2e57796f88ff67c9ad794e756b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 24 Apr 2026 22:07:55 +0000 Subject: [PATCH 1/4] Migrate from NAN to Node-API (node-addon-api) - Replace nan dependency with node-addon-api ^8.7.0 - Update binding.gyp to use node-addon-api includes and NAPI_CPP_EXCEPTIONS - Rewrite src/node_murmurhash3.cc using napi.h: - Napi::AsyncWorker replaces Nan::AsyncWorker - Napi::Value functions replace NAN_METHOD macros - Napi::Object Init + NODE_API_MODULE replaces NAN_MODULE_INIT + NODE_MODULE - Preserve all argument validation and error messages - All 96 tests pass Agent-Logs-Url: https://github.com/mjradwin/node-murmurhash3/sessions/5d544747-c0a4-4974-9ba5-8d54470c91a4 Co-authored-by: mjradwin <3769045+mjradwin@users.noreply.github.com> --- binding.gyp | 3 +- package-lock.json | 288 +++++++++++++++++++++++++------------- package.json | 2 +- src/node_murmurhash3.cc | 297 ++++++++++++++++------------------------ 4 files changed, 311 insertions(+), 279 deletions(-) diff --git a/binding.gyp b/binding.gyp index ef6bd7e..1d2e2c2 100644 --- a/binding.gyp +++ b/binding.gyp @@ -8,8 +8,9 @@ 'cflags!': ['-fno-exceptions'], 'cflags_cc!': ['-fno-exception'], "include_dirs" : [ - "=0.12.0" + } + }, + "node_modules/async": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" }, - "balanced-match": { + "node_modules/balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, - "brace-expansion": { + "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { + "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, - "browser-stdout": { + "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, - "commander": { + "node_modules/commander": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", - "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==" + "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", + "engines": { + "node": ">= 6" + } }, - "concat-map": { + "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, - "debug": { + "node_modules/debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, - "requires": { + "dependencies": { "ms": "2.0.0" } }, - "diff": { + "node_modules/diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.3.1" + } }, - "escape-string-regexp": { + "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "dev": true, + "engines": { + "node": ">=0.8.0" + } }, - "fs.realpath": { + "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, - "glob": { + "node_modules/glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "requires": { + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "growl": { + "node_modules/growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true + "dev": true, + "engines": { + "node": ">=4.x" + } }, - "has-flag": { + "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "he": { + "node_modules/he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true + "dev": true, + "bin": { + "he": "bin/he" + } }, - "inflight": { + "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, - "inherits": { + "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "js-beautify-node": { + "node_modules/js-beautify-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/js-beautify-node/-/js-beautify-node-1.0.0.tgz", - "integrity": "sha1-NTK2FEgEhNa7prK5v9NCf3Seo8g=" + "integrity": "sha1-NTK2FEgEhNa7prK5v9NCf3Seo8g=", + "engines": [ + "node >= 0.3.0" + ], + "bin": { + "jsbeautify": "beautify-node.js" + } }, - "minimatch": { + "node_modules/minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { + "dependencies": { "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "minimist": { + "node_modules/minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, - "mkdirp": { + "node_modules/mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { + "dependencies": { "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" } }, - "mocha": { + "node_modules/mocha": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", "dev": true, - "requires": { + "dependencies": { "browser-stdout": "1.3.1", "commander": "2.15.1", "debug": "3.1.0", @@ -154,118 +207,157 @@ "mkdirp": "0.5.1", "supports-color": "5.4.0" }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/mocha/node_modules/commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, + "node_modules/mocha/node_modules/glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, "dependencies": { - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - } + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" } }, - "ms": { + "node_modules/mocha/node_modules/minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "node_modules/mocha/node_modules/mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dev": true, + "dependencies": { + "minimist": "0.0.8" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "nan": { - "version": "2.14.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", - "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==" + "node_modules/node-addon-api": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.7.0.tgz", + "integrity": "sha512-9MdFxmkKaOYVTV+XVRG8ArDwwQ77XIgIPyKASB1k3JPq3M8fGQQQE3YpMOrKm6g//Ktx8ivZr8xo1Qmtqub+GA==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } }, - "once": { + "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { + "dependencies": { "wrappy": "1" } }, - "path-is-absolute": { + "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } }, - "rimraf": { + "node_modules/rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "requires": { + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dependencies": { "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" } }, - "semver": { + "node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } }, - "shipitjs": { + "node_modules/shipitjs": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/shipitjs/-/shipitjs-0.3.2.tgz", "integrity": "sha512-uLtgZP2PBzxwoCDfEhARWpuQewMwRLGhkrD8O/rqXHdyYjaV8LY0F4aMi5Lr3l4XWm5YiHINsCMhzD0scu7GzQ==", - "requires": { - "async": "^3.2.0", + "dependencies": { + "async": "", "commander": ">=0.6.1", - "js-beautify-node": "^1.0.0", + "js-beautify-node": "", "semver": "^5.5.1", - "temp": "^0.9.2", - "underscore": "^1.11.0" + "temp": "", + "underscore": "" + }, + "bin": { + "shipitjs": "bin/shipitjs" + }, + "engines": { + "node": ">=0.4.x" } }, - "supports-color": { + "node_modules/supports-color": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", "dev": true, - "requires": { + "dependencies": { "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "temp": { + "node_modules/temp": { "version": "0.9.2", "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.2.tgz", "integrity": "sha512-KLVd6CXeUYsqmI/LBWDLg3bFkdZPg0Xr/Gn79GUuPNiISzp6v/EKUaCOrxqeH1w/wVNmrljyDRgKxhZV9JzyJA==", - "requires": { + "dependencies": { "mkdirp": "^0.5.1", "rimraf": "~2.6.2" + }, + "engines": { + "node": ">=6.0.0" } }, - "underscore": { + "node_modules/underscore": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.11.0.tgz", "integrity": "sha512-xY96SsN3NA461qIRKZ/+qox37YXPtSBswMGfiNptr+wrt6ds4HaMw23TP612fEyGekRE6LNRiLYr/aqbHXNedw==" }, - "wrappy": { + "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" diff --git a/package.json b/package.json index 6c22f9b..bc25545 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ ], "author": "Hideaki Ohno ", "dependencies": { - "nan": "^2.14.2", + "node-addon-api": "^8.7.0", "shipitjs": "^0.3.2" }, "devDependencies": { diff --git a/src/node_murmurhash3.cc b/src/node_murmurhash3.cc index 2c73d10..169126f 100644 --- a/src/node_murmurhash3.cc +++ b/src/node_murmurhash3.cc @@ -3,277 +3,216 @@ * Copyright(c) 2013 Hideaki Ohno * MIT Licensed */ -#ifndef BUILDING_NODE_EXTENSION -#define BUILDING_NODE_EXTENSION -#endif -#include -#include +#include #include #include -#include #include "MurmurHash3.h" -// validate the arguments count and type -#define REQ_ARG_COUNT_AND_TYPE(I, TYPE) \ - if (info.Length() < (I + 1) ) { \ - std::stringstream __ss; \ - __ss << "A least " << I + 1 << " arguments are required"; \ - return Nan::ThrowRangeError(__ss.str().c_str()); \ - } else if (!info[I]->Is##TYPE()) { \ - std::stringstream __ss; \ - __ss << "Argument " << I + 1 << " must be a " #TYPE; \ - return Nan::ThrowTypeError(__ss.str().c_str()); \ - } - -// validate the argument type is 'function' or not. -#define REQ_FUN_ARG(I, VAR) \ - REQ_ARG_COUNT_AND_TYPE(I, Function) \ - Local VAR = Local::Cast(info[I]); - -// validate the argument type is 'string' or not. -#define REQ_STR_ARG(I) REQ_ARG_COUNT_AND_TYPE(I, String) - -// validate the argument type is 'boolean' or not. -#define REQ_BOOL_ARG(I) REQ_ARG_COUNT_AND_TYPE(I, Boolean) - -// validate the argument type is 'unsigned int' or not. -#define REQ_UINT32_ARG(I) REQ_ARG_COUNT_AND_TYPE(I, Uint32) - -#define isolate v8::Isolate::GetCurrent() +/** + * @brief Validate argument count and type, throwing on failure. + * @param info CallbackInfo + * @param index Argument index + * @param typeName Name of expected type (for error message) + * @param checker Lambda that returns true if argument is valid + */ +static void ValidateArg(const Napi::CallbackInfo& info, size_t index, + const char* typeName, + bool (*checker)(const Napi::Value&)) { + Napi::Env env = info.Env(); + if (info.Length() < index + 1) { + std::stringstream ss; + ss << "A least " << index + 1 << " arguments are required"; + throw Napi::RangeError::New(env, ss.str()); + } + if (!checker(info[index])) { + std::stringstream ss; + ss << "Argument " << index + 1 << " must be a " << typeName; + throw Napi::TypeError::New(env, ss.str()); + } +} -#if NODE_VERSION_AT_LEAST(12, 0, 0) -#define TO_UTF8VALUE(str) *String::Utf8Value(isolate, str); -#define ToBoolean(bool) bool->BooleanValue(isolate); -#elif NODE_VERSION_AT_LEAST(9, 0, 0) -#define TO_UTF8VALUE(str) *String::Utf8Value(isolate, str); -#define ToBoolean(bool) bool->BooleanValue(); -#else -#define TO_UTF8VALUE(str) *String::Utf8Value(str); -#define ToBoolean(bool) bool->BooleanValue(); -#endif +static bool IsString(const Napi::Value& v) { return v.IsString(); } +static bool IsBoolean(const Napi::Value& v) { return v.IsBoolean(); } +static bool IsFunction(const Napi::Value& v) { return v.IsFunction(); } -using namespace v8; -using namespace node; +/** + * @brief Check if value is a valid Uint32 (number, non-negative, integer, <= UINT32_MAX) + */ +static bool IsUint32(const Napi::Value& v) { + if (!v.IsNumber()) return false; + double d = v.As().DoubleValue(); + return d >= 0 && d <= 4294967295.0 && d == (double)(uint32_t)d; +} /** * @brief Make return value of murmur32 - * @param ret[out] Return value - * @param hashValue[in] hash value - * @param hexMode[in] hexadecimal string mode flag */ -static NAN_INLINE void MakeReturnValue_murmur32(Local& ret, uint32_t hashValue, bool hexMode) { +static Napi::Value MakeReturnValue_murmur32(Napi::Env env, uint32_t hashValue, bool hexMode) { if (hexMode) { std::stringstream ss; ss << std::hex << std::setfill('0') << std::setw(8) << hashValue; - ret = Nan::New(ss.str().c_str()).ToLocalChecked();; + return Napi::String::New(env, ss.str()); } else { - ret = Nan::New(hashValue); + return Napi::Number::New(env, hashValue); } } /** * @brief Make return value of murmur128 - * @param ret[out] Return value - * @param hashValue[in] hash value - * @param hexMode[in] hexadecimal string mode flag */ -static NAN_INLINE void MakeReturnValue_murmur128(Local& ret, uint32_t* hashValue, bool hexMode) { +static Napi::Value MakeReturnValue_murmur128(Napi::Env env, uint32_t* hashValue, bool hexMode) { if (hexMode) { std::stringstream ss; ss << std::hex << std::setfill('0'); for (int i = 0; i < 4; i++) { ss << std::setw(8) << hashValue[i]; } - ret = Nan::New(ss.str().c_str()).ToLocalChecked();; + return Napi::String::New(env, ss.str()); } else { - Local context = isolate->GetCurrentContext(); - Local values = Nan::New(4); + Napi::Array values = Napi::Array::New(env, 4); for (int i = 0; i < 4; i++) { - values->Set(context, Nan::New(i), Nan::New(hashValue[i])); + values.Set((uint32_t)i, Napi::Number::New(env, hashValue[i])); } - ret = values; + return values; } } /** - * @brief UV queue worker for murmur32 + * @brief Async worker for murmur32 */ -class Murmur32Worker : public Nan::AsyncWorker { +class Murmur32Worker : public Napi::AsyncWorker { public: - /** - * @brief Constructor - * @param callback[in] Callback functio object - * @param key[in] hash key - * @param seed[in] hash seed - * @param hexMode[in] hexadecimal string mode flag - */ - Murmur32Worker(Nan::Callback *callback, std::string& key, uint32_t seed, bool hexMode) - : Nan::AsyncWorker(callback), key_(key), seed_(seed), hexMode_(hexMode) { + Murmur32Worker(Napi::Function& callback, std::string key, uint32_t seed, bool hexMode) + : Napi::AsyncWorker(callback), key_(key), seed_(seed), hexMode_(hexMode), hashValue_(0) { } - /** - * @brief Calculate MurmurHash3(32bit) - */ - void Execute() { + void Execute() override { MurmurHash3_x86_32(key_.c_str(), (int) key_.length(), seed_, &hashValue_); } - /** - * @brief Invoke callback function - */ - void HandleOKCallback() { - Nan::HandleScope scope; - Local res[2]; - res[0] = Nan::Null(); - MakeReturnValue_murmur32(res[1], hashValue_, hexMode_); - callback->Call(2, res, async_resource); + void OnOK() override { + Napi::Env env = Env(); + Callback().Call({env.Null(), MakeReturnValue_murmur32(env, hashValue_, hexMode_)}); } private: - std::string key_; /// hash key - uint32_t seed_; /// hash seed - uint32_t hashValue_;/// hash value - bool hexMode_; /// hexadecimal string mode flag + std::string key_; + uint32_t seed_; + bool hexMode_; + uint32_t hashValue_; }; /** - * @brief UV queue worker for murmur128 + * @brief Async worker for murmur128 */ -class Murmur128Worker : public Nan::AsyncWorker { +class Murmur128Worker : public Napi::AsyncWorker { public: - /** - * @brief Constructor - * @param callback[in] Callback functio object - * @param key[in] hash key - * @param seed[in] hash seed - * @param hexMode[in] hexadecimal string mode flag - */ - Murmur128Worker(Nan::Callback *callback, std::string& key, uint32_t seed, bool hexMode) - : Nan::AsyncWorker(callback), key_(key), seed_(seed), hexMode_(hexMode) { + Murmur128Worker(Napi::Function& callback, std::string key, uint32_t seed, bool hexMode) + : Napi::AsyncWorker(callback), key_(key), seed_(seed), hexMode_(hexMode) { + memset(hashValue_, 0, sizeof(hashValue_)); } - /** - * @brief Calculate MurmurHash3(128bit) - */ - void Execute() { + void Execute() override { MurmurHash3_x86_128(key_.c_str(), (int) key_.length(), seed_, &hashValue_); } - /** - * @brief Invoke callback function - */ - void HandleOKCallback() { - Nan::HandleScope scope; - Local res[2]; - res[0] = Nan::Null(); - MakeReturnValue_murmur128(res[1], hashValue_, hexMode_); - callback->Call(2, res, async_resource); + void OnOK() override { + Napi::Env env = Env(); + Callback().Call({env.Null(), MakeReturnValue_murmur128(env, hashValue_, hexMode_)}); } private: - std::string key_; /// hash key - uint32_t seed_; /// hash seed - uint32_t hashValue_[4]; /// hash value - bool hexMode_; /// hexadecimal string mode flag + std::string key_; + uint32_t seed_; + bool hexMode_; + uint32_t hashValue_[4]; }; /** * @brief Calculate MurmurHash3(32bit) with async interface */ -NAN_METHOD(murmur32_async) { - Nan::HandleScope scope; - - REQ_STR_ARG(0); - REQ_UINT32_ARG(1); - REQ_BOOL_ARG(2); - REQ_FUN_ARG(3, cb); +Napi::Value murmur32_async(const Napi::CallbackInfo& info) { + ValidateArg(info, 0, "String", IsString); + ValidateArg(info, 1, "Uint32", IsUint32); + ValidateArg(info, 2, "Boolean", IsBoolean); + ValidateArg(info, 3, "Function", IsFunction); - std::string key = TO_UTF8VALUE(info[0]); - uint32_t seed = Nan::To(info[1]).FromJust(); + std::string key = info[0].As().Utf8Value(); + uint32_t seed = info[1].As().Uint32Value(); + bool hexMode = info[2].As().Value(); + Napi::Function cb = info[3].As(); - Nan::Callback *callback = new Nan::Callback(cb); - bool hexMode = ToBoolean(info[2]); - Nan::AsyncQueueWorker(new Murmur32Worker(callback, key, seed, hexMode)); + Murmur32Worker* worker = new Murmur32Worker(cb, key, seed, hexMode); + worker->Queue(); - info.GetReturnValue().Set(Nan::Undefined()); + return info.Env().Undefined(); } /** * @brief Calculate MurmurHash3(128bit) with async interface */ -NAN_METHOD(murmur128_async) { - Nan::HandleScope scope; +Napi::Value murmur128_async(const Napi::CallbackInfo& info) { + ValidateArg(info, 0, "String", IsString); + ValidateArg(info, 1, "Uint32", IsUint32); + ValidateArg(info, 2, "Boolean", IsBoolean); + ValidateArg(info, 3, "Function", IsFunction); - REQ_STR_ARG(0); - REQ_UINT32_ARG(1); - REQ_BOOL_ARG(2); - REQ_FUN_ARG(3, cb); + std::string key = info[0].As().Utf8Value(); + uint32_t seed = info[1].As().Uint32Value(); + bool hexMode = info[2].As().Value(); + Napi::Function cb = info[3].As(); - std::string key = TO_UTF8VALUE(info[0]); - uint32_t seed = Nan::To(info[1]).FromJust(); + Murmur128Worker* worker = new Murmur128Worker(cb, key, seed, hexMode); + worker->Queue(); - Nan::Callback *callback = new Nan::Callback(cb); - bool hexMode = ToBoolean(info[2]); - Nan::AsyncQueueWorker(new Murmur128Worker(callback, key, seed, hexMode)); - - info.GetReturnValue().Set(Nan::Undefined()); + return info.Env().Undefined(); } /** * @brief Calculate MurmurHash3(32bit) with sync interface */ -NAN_METHOD(murmur32_sync) { - Nan::HandleScope scope; - uint32_t out; +Napi::Value murmur32_sync(const Napi::CallbackInfo& info) { + ValidateArg(info, 0, "String", IsString); + ValidateArg(info, 1, "Uint32", IsUint32); + ValidateArg(info, 2, "Boolean", IsBoolean); - REQ_STR_ARG(0); - REQ_UINT32_ARG(1); - REQ_BOOL_ARG(2); - - std::string key = TO_UTF8VALUE(info[0]); - uint32_t seed = Nan::To(info[1]).FromJust(); - bool hexMode = ToBoolean(info[2]); + std::string key = info[0].As().Utf8Value(); + uint32_t seed = info[1].As().Uint32Value(); + bool hexMode = info[2].As().Value(); + uint32_t out; MurmurHash3_x86_32(key.c_str(), (int) key.length(), seed, &out); - Local ret; - MakeReturnValue_murmur32(ret, out, hexMode); - info.GetReturnValue().Set(ret); - + return MakeReturnValue_murmur32(info.Env(), out, hexMode); } /** * @brief Calculate MurmurHash3(128bit) with sync interface */ -NAN_METHOD(murmur128_sync) { - Nan::HandleScope scope; - uint32_t out[4]; - - REQ_STR_ARG(0); - REQ_UINT32_ARG(1); - REQ_BOOL_ARG(2); +Napi::Value murmur128_sync(const Napi::CallbackInfo& info) { + ValidateArg(info, 0, "String", IsString); + ValidateArg(info, 1, "Uint32", IsUint32); + ValidateArg(info, 2, "Boolean", IsBoolean); - std::string key = TO_UTF8VALUE(info[0]); - uint32_t seed = Nan::To(info[1]).FromJust(); - bool hexMode = ToBoolean(info[2]); + std::string key = info[0].As().Utf8Value(); + uint32_t seed = info[1].As().Uint32Value(); + bool hexMode = info[2].As().Value(); + uint32_t out[4]; MurmurHash3_x86_128(key.c_str(), (int) key.length(), seed, &out); - Local ret; - MakeReturnValue_murmur128(ret, out, hexMode); - info.GetReturnValue().Set(ret); + return MakeReturnValue_murmur128(info.Env(), out, hexMode); } /** - * @brief Initialize - * @param exports[in,out] exports object + * @brief Initialize module */ +Napi::Object Init(Napi::Env env, Napi::Object exports) { + exports.Set("murmur32", Napi::Function::New(env, murmur32_async)); + exports.Set("murmur128", Napi::Function::New(env, murmur128_async)); + exports.Set("murmur32Sync", Napi::Function::New(env, murmur32_sync)); + exports.Set("murmur128Sync", Napi::Function::New(env, murmur128_sync)); + return exports; +} -NAN_MODULE_INIT(init) { - Nan::Export(target, "murmur32", murmur32_async); - Nan::Export(target, "murmur128", murmur128_async); - Nan::Export(target, "murmur32Sync", murmur32_sync); - Nan::Export(target, "murmur128Sync", murmur128_sync); -}; - -NODE_MODULE(murmurhash3, init) +NODE_API_MODULE(murmurhash3, Init) From b2848db13c513dd69590ea77bfa4f817f639cb42 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 24 Apr 2026 22:09:13 +0000 Subject: [PATCH 2/4] Fix typo: 'A least' -> 'At least' in argument validation Agent-Logs-Url: https://github.com/mjradwin/node-murmurhash3/sessions/5d544747-c0a4-4974-9ba5-8d54470c91a4 Co-authored-by: mjradwin <3769045+mjradwin@users.noreply.github.com> --- src/node_murmurhash3.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node_murmurhash3.cc b/src/node_murmurhash3.cc index 169126f..11b1489 100644 --- a/src/node_murmurhash3.cc +++ b/src/node_murmurhash3.cc @@ -21,7 +21,7 @@ static void ValidateArg(const Napi::CallbackInfo& info, size_t index, Napi::Env env = info.Env(); if (info.Length() < index + 1) { std::stringstream ss; - ss << "A least " << index + 1 << " arguments are required"; + ss << "At least " << index + 1 << " arguments are required"; throw Napi::RangeError::New(env, ss.str()); } if (!checker(info[index])) { From 213694b8b239185f30d232925fc13bedc4758692 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 24 Apr 2026 22:14:14 +0000 Subject: [PATCH 3/4] Upgrade to ES module packaging with TypeScript typings, bump to v0.6.0 - Convert lib/murmurhash3.js from CommonJS to ES module (import/export) - Add "type": "module" to package.json - Replace "main" with "module" and "exports" fields - Add TypeScript declaration file lib/murmurhash3.d.ts - Add "types" field to package.json - Update test/test.js to use ES module imports - Upgrade mocha to v10 for ESM support - Bump version to 0.6.0 - Update engines to node >= 16.0.0 Agent-Logs-Url: https://github.com/mjradwin/node-murmurhash3/sessions/54d77b95-208e-4ab5-8300-44507cd831e1 Co-authored-by: mjradwin <3769045+mjradwin@users.noreply.github.com> --- lib/murmurhash3.d.ts | 10 + lib/murmurhash3.js | 58 +-- package-lock.json | 875 +++++++++++++++++++++++++++++++++++++++---- package.json | 13 +- test/test.js | 8 +- 5 files changed, 848 insertions(+), 116 deletions(-) create mode 100644 lib/murmurhash3.d.ts diff --git a/lib/murmurhash3.d.ts b/lib/murmurhash3.d.ts new file mode 100644 index 0000000..b211d81 --- /dev/null +++ b/lib/murmurhash3.d.ts @@ -0,0 +1,10 @@ +declare module 'murmurhash3' { + /** return 32bit integer value */ + export function murmur32Sync(key: string, seed?: number): number; + /** return 32bit hexadecimal string */ + export function murmur32HexSync(key: string, seed?: number): string; + /** return array that have 4 elements of 32bit integer */ + export function murmur128Sync(key: string, seed?: number): number[]; + /** return 128bit hexadecimal string */ + export function murmur128HexSync(key: string, seed?: number): string; +} diff --git a/lib/murmurhash3.js b/lib/murmurhash3.js index 629e91d..7ae167d 100644 --- a/lib/murmurhash3.js +++ b/lib/murmurhash3.js @@ -4,24 +4,26 @@ * MIT Licensed */ +import { createRequire } from 'module'; +const require = createRequire(import.meta.url); + /** * Library version. */ +export const version = '0.6.0'; -exports.version = '0.5.0'; - -var binding; +let binding; try { - binding = require(__dirname + '/../build/Release/murmurhash3'); + binding = require('../build/Release/murmurhash3'); } catch(e) { - binding = require(__dirname + '/../build/default/murmurhash3'); + binding = require('../build/default/murmurhash3'); } -var E_CALLBACK_MISSING = "Callback function is missing"; +const E_CALLBACK_MISSING = "Callback function is missing"; -//Aync interface +//Async interface -exports.murmur32 = function(key, seed, cb) { +export function murmur32(key, seed, cb) { if ( typeof seed == 'function') { cb = seed; seed = 0; @@ -29,14 +31,14 @@ exports.murmur32 = function(key, seed, cb) { if (cb === undefined || typeof cb != 'function') { throw new Error(E_CALLBACK_MISSING); } - var res = binding.murmur32(key, seed, false, function(err, res) { + const res = binding.murmur32(key, seed, false, function(err, res) { // Cast signed integer to unsigned integer cb(err, res >>> 0); }); return res; -}; +} -exports.murmur32Hex = function(key, seed, cb) { +export function murmur32Hex(key, seed, cb) { if ( typeof seed == 'function') { cb = seed; seed = 0; @@ -45,9 +47,9 @@ exports.murmur32Hex = function(key, seed, cb) { throw new Error(E_CALLBACK_MISSING); } return binding.murmur32(key, seed, true, cb); -}; +} -exports.murmur128 = function(key, seed, cb) { +export function murmur128(key, seed, cb) { if ( typeof seed == 'function') { cb = seed; seed = 0; @@ -56,15 +58,15 @@ exports.murmur128 = function(key, seed, cb) { throw new Error(E_CALLBACK_MISSING); } binding.murmur128(key, seed, false, function(err, res) { - for (var i = 0; i < res.length; i++) { + for (let i = 0; i < res.length; i++) { // Cast signed integer to unsigned integer res[i] = res[i] >>> 0; } cb(err, res); }); -}; +} -exports.murmur128Hex = function(key, seed, cb) { +export function murmur128Hex(key, seed, cb) { if ( typeof seed == 'function') { cb = seed; seed = 0; @@ -73,42 +75,42 @@ exports.murmur128Hex = function(key, seed, cb) { throw new Error(E_CALLBACK_MISSING); } return binding.murmur128(key, seed, true, cb); -}; +} //Sync interface -exports.murmur32Sync = function(key, seed) { +export function murmur32Sync(key, seed) { // Cast signed integer to unsigned integer if (seed === undefined) { seed = 0; } - var res = binding.murmur32Sync(key, seed, false) >>> 0; + const res = binding.murmur32Sync(key, seed, false) >>> 0; return res; -}; +} -exports.murmur32HexSync = function(key, seed) { +export function murmur32HexSync(key, seed) { if (seed === undefined) { seed = 0; } return binding.murmur32Sync(key, seed, true); -}; +} -exports.murmur128Sync = function(key, seed) { +export function murmur128Sync(key, seed) { if (seed === undefined) { seed = 0; } - var res = binding.murmur128Sync(key, seed, false); - for (var i = 0; i < res.length; i++) { + const res = binding.murmur128Sync(key, seed, false); + for (let i = 0; i < res.length; i++) { // Cast signed integer to unsigned integer res[i] = res[i] >>> 0; } return res; -}; +} -exports.murmur128HexSync = function(key, seed) { +export function murmur128HexSync(key, seed) { if (seed === undefined) { seed = 0; } return binding.murmur128Sync(key, seed, true); -}; +} diff --git a/package-lock.json b/package-lock.json index bde760e..6fbb41e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,24 +1,81 @@ { "name": "murmurhash3", - "version": "0.5.0", + "version": "0.6.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "murmurhash3", - "version": "0.5.0", + "version": "0.6.0", "license": "MIT", "dependencies": { "node-addon-api": "^8.7.0", "shipitjs": "^0.3.2" }, "devDependencies": { - "mocha": "^5.2.0" + "mocha": "^10.8.2" }, "engines": { - "node": ">=0.12.0" + "node": ">=16.0.0" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, "node_modules/async": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", @@ -29,6 +86,19 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -38,12 +108,125 @@ "concat-map": "0.0.1" } }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, "node_modules/commander": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", @@ -58,30 +241,114 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.0.0" + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", + "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, "engines": { - "node": ">=0.8.0" + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" } }, "node_modules/fs.realpath": { @@ -89,6 +356,31 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -109,29 +401,35 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, "engines": { - "node": ">=4.x" + "node": ">= 6" } }, "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, + "license": "MIT", "bin": { "he": "bin/he" } @@ -151,6 +449,85 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/js-beautify-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/js-beautify-node/-/js-beautify-node-1.0.0.tgz", @@ -162,6 +539,52 @@ "jsbeautify": "beautify-node.js" } }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -190,79 +613,91 @@ } }, "node_modules/mocha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", - "dev": true, - "dependencies": { - "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.5", - "he": "1.1.1", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", + "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^8.1.0", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" }, "bin": { "_mocha": "bin/_mocha", - "mocha": "bin/mocha" + "mocha": "bin/mocha.js" }, "engines": { - "node": ">= 4.0.0" + "node": ">= 14.0.0" } }, - "node_modules/mocha/node_modules/commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } }, "node_modules/mocha/node_modules/glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "minimatch": "^5.0.1", + "once": "^1.3.0" }, "engines": { - "node": "*" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mocha/node_modules/minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "node_modules/mocha/node_modules/mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "node_modules/mocha/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "dev": true, + "license": "ISC", "dependencies": { - "minimist": "0.0.8" + "brace-expansion": "^2.0.1" }, - "bin": { - "mkdirp": "bin/cmd.js" + "engines": { + "node": ">=10" } }, "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" }, "node_modules/node-addon-api": { "version": "8.7.0", @@ -273,6 +708,16 @@ "node": "^18 || ^20 || >= 21" } }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -281,6 +726,48 @@ "wrappy": "1" } }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -289,6 +776,52 @@ "node": ">=0.10.0" } }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", @@ -301,6 +834,27 @@ "rimraf": "bin.js" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -309,6 +863,16 @@ "semver": "bin/semver" } }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, "node_modules/shipitjs": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/shipitjs/-/shipitjs-0.3.2.tgz", @@ -328,16 +892,61 @@ "node": ">=0.4.x" } }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/temp": { @@ -352,15 +961,121 @@ "node": ">=6.0.0" } }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/underscore": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.11.0.tgz", "integrity": "sha512-xY96SsN3NA461qIRKZ/+qox37YXPtSBswMGfiNptr+wrt6ds4HaMw23TP612fEyGekRE6LNRiLYr/aqbHXNedw==" }, + "node_modules/workerpool": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index bc25545..783cf00 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,8 @@ { "name": "murmurhash3", - "version": "0.5.0", + "version": "0.6.0", "description": "Node binding of MurmurHash3", + "type": "module", "repository": "https://github.com/hideo55/node-murmurhash3", "bugs": { "url": "https://github.com/hideo55/node-murmurhash3/issues" @@ -18,11 +19,15 @@ "shipitjs": "^0.3.2" }, "devDependencies": { - "mocha": "^5.2.0" + "mocha": "^10.8.2" }, - "main": "./lib/murmurhash3.js", + "module": "./lib/murmurhash3.js", + "exports": { + ".": "./lib/murmurhash3.js" + }, + "types": "./lib/murmurhash3.d.ts", "engines": { - "node": ">=0.12.0" + "node": ">=16.0.0" }, "scripts": { "test": "mocha -R spec test/test.js" diff --git a/test/test.js b/test/test.js index 457741b..a0b0284 100644 --- a/test/test.js +++ b/test/test.js @@ -1,5 +1,5 @@ -var mmh3 = require('../lib/murmurhash3'); -var testData = [["Hello", 0x12da77c8, [0x2360ae46, 0x5e6336c6, 0xad45b3f4, 0xad45b3f4]], ["Hello1", 0x6357e0a6, [0x8eb0cf41, 0x641b2401, 0xbc4c0dfc, 0xbc4c0dfc]], ["Hello2", 0xe5ce223e, [0xd3bcfc45, 0x66782162, 0x4beab2d1, 0x4beab2d1]], ["2", 0x0129e217, [0x9dd4f4e7, 0x3df769b3, 0x3df769b3, 0x3df769b3]], ["88", 0x7a0040a5, [0x28979fa9, 0x0b1b1a58, 0x0b1b1a58, 0x0b1b1a58]]]; +import * as mmh3 from '../lib/murmurhash3.js'; +const testData = [["Hello", 0x12da77c8, [0x2360ae46, 0x5e6336c6, 0xad45b3f4, 0xad45b3f4]], ["Hello1", 0x6357e0a6, [0x8eb0cf41, 0x641b2401, 0xbc4c0dfc, 0xbc4c0dfc]], ["Hello2", 0xe5ce223e, [0xd3bcfc45, 0x66782162, 0x4beab2d1, 0x4beab2d1]], ["2", 0x0129e217, [0x9dd4f4e7, 0x3df769b3, 0x3df769b3, 0x3df769b3]], ["88", 0x7a0040a5, [0x28979fa9, 0x0b1b1a58, 0x0b1b1a58, 0x0b1b1a58]]]; function zeroFill(number, width) { width -= number.toString().length; @@ -10,8 +10,8 @@ function zeroFill(number, width) { // always return a string } -var assert = require('assert'); -var i = 0; +import assert from 'assert'; +let i = 0; for (; i < testData.length; i++) { var val = testData[i]; describe('Pattern:' + (i + 1 ), function() { From ac6b19f080feed3843760891a3ed95697745c088 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 24 Apr 2026 22:36:05 +0000 Subject: [PATCH 4/4] Add async API typings and modernize README examples Extend the TypeScript declarations to cover the async callback-based functions (murmur32, murmur32Hex, murmur128, murmur128Hex) and the exported `version` constant. Update the README to use ES module imports and arrow-function callbacks, and document a util.promisify pattern for async/await usage. --- README.md | 48 ++++++++++++++++++++++++++++---------------- lib/murmurhash3.d.ts | 24 ++++++++++++++++++++++ 2 files changed, 55 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 32405ad..b5e0bcc 100644 --- a/README.md +++ b/README.md @@ -18,38 +18,52 @@ or ## Usage ```javascript -var mmh3 = require('murmurhash3'); - -mmh3.murmur32('key', function(err, hashValue){ +import { murmur32, murmur128Hex } from 'murmurhash3'; + +murmur32('key', (err, hashValue) => { if (err) throw err; - ... + // ... }); -mmh3.murmur128Hex('key', function(err, hashValue){ + +murmur128Hex('key', (err, hashValue) => { if (err) throw err; - ... + // ... }); ``` +You can also wrap the async functions with `util.promisify` for `async`/`await`: + +```javascript +import { promisify } from 'node:util'; +import { murmur32, murmur128Hex } from 'murmurhash3'; + +const murmur32Async = promisify(murmur32); +const murmur128HexAsync = promisify(murmur128Hex); + +const hash32 = await murmur32Async('key'); +const hash128 = await murmur128HexAsync('key'); +``` + ## Functions ### Async interfaces - murmur32(key [,seed], callback); // return 32bit integer value - murmur32Hex(key [,seed], callback); // return 32bit hexadecimal string - murmur128(key [,seed], callback); // return array that have 4 elements of 32bit integer - murmur128Hex(key [,seed], callback);// return 128bit hexadecimal string + murmur32(key [, seed], callback); // returns 32bit integer value + murmur32Hex(key [, seed], callback); // returns 32bit hexadecimal string + murmur128(key [, seed], callback); // returns array of 4 32bit integers + murmur128Hex(key [, seed], callback); // returns 128bit hexadecimal string -- `seed` is optional argument. (unsigned integer) -- The callback gets two arguments `(error, hashValue)`. +- `seed` is an optional argument. (unsigned integer) +- The callback receives two arguments `(error, hashValue)`. ### Sync interfaces - murmur32Sync(key [,seed]); // return 32bit integer value - murmur32HexSync(key, [,seed]); // return 32bit hexadecimal string - murmur128Sync(key [,seed]); // return array that have 4 elements of 32bit integer - murmur128HexSync(key [,seed]);// return 128bit hexadecimal string + murmur32Sync(key [, seed]); // returns 32bit integer value + murmur32HexSync(key [, seed]); // returns 32bit hexadecimal string + murmur128Sync(key [, seed]); // returns array of 4 32bit integers + murmur128HexSync(key [, seed]);// returns 128bit hexadecimal string -- `seed` is optional argument. (unsigned integer) +- `seed` is an optional argument. (unsigned integer) ## Requirement diff --git a/lib/murmurhash3.d.ts b/lib/murmurhash3.d.ts index b211d81..266964a 100644 --- a/lib/murmurhash3.d.ts +++ b/lib/murmurhash3.d.ts @@ -1,4 +1,28 @@ declare module 'murmurhash3' { + /** Library version. */ + export const version: string; + + type Murmur32Callback = (err: Error | null, hash: number) => void; + type Murmur32HexCallback = (err: Error | null, hash: string) => void; + type Murmur128Callback = (err: Error | null, hash: number[]) => void; + type Murmur128HexCallback = (err: Error | null, hash: string) => void; + + /** return 32bit integer value */ + export function murmur32(key: string, seed: number, callback: Murmur32Callback): void; + export function murmur32(key: string, callback: Murmur32Callback): void; + + /** return 32bit hexadecimal string */ + export function murmur32Hex(key: string, seed: number, callback: Murmur32HexCallback): void; + export function murmur32Hex(key: string, callback: Murmur32HexCallback): void; + + /** return array that have 4 elements of 32bit integer */ + export function murmur128(key: string, seed: number, callback: Murmur128Callback): void; + export function murmur128(key: string, callback: Murmur128Callback): void; + + /** return 128bit hexadecimal string */ + export function murmur128Hex(key: string, seed: number, callback: Murmur128HexCallback): void; + export function murmur128Hex(key: string, callback: Murmur128HexCallback): void; + /** return 32bit integer value */ export function murmur32Sync(key: string, seed?: number): number; /** return 32bit hexadecimal string */