ioredis-mock
ioredis-mock copied to clipboard
Bug: SCAN commands have results in lua script indexed at 0, missing first element when iterating
Reproduce
From the REPL (> node
)
Redis = require('ioredis-mock'); redis = new Redis()
redis.defineCommand('scanWrapper', { lua: `local res = redis.call('SCAN', '0') for idx, member in ipairs(res[2]) do print(idx, member) end return res[2]` })
await redis.mset('a', '1', 'b', '2'); await redis.scanWrapper()
prints
1 b
at index 0 (wrong) a
instead of expected
1 a
2 b
at index 0 (wrong) nil
and returns
['b']
instead of
['a', 'b']
Patch (dirty)
for bundled v8.9.0 (with npx patch-package ioredis-mock
)
diff --git a/node_modules/ioredis-mock/lib/index.js b/node_modules/ioredis-mock/lib/index.js
index a82c297..ac6fd63 100644
--- a/node_modules/ioredis-mock/lib/index.js
+++ b/node_modules/ioredis-mock/lib/index.js
@@ -3748,6 +3748,16 @@ var import_fengari = __toESM(require("fengari")), import_fengari_interop = __toE
}, makeReturnValue = (L) => {
if (!isTopArray(L)()) {
let retVal2 = import_fengari_interop.default.tojs(L, -1);
+ // hack to support *scan commands
+ if (lua.lua_istable(L, -1)) {
+ lua.lua_len(L, -1);
+ let length = lua.lua_tointeger(L, -1);
+ retValArray = []
+ for (let i = 1; i <= length; i++) {
+ retValArray.push(retVal2.get(i))
+ }
+ return retValArray
+ }
return Array.isArray(retVal2) ? retVal2.slice(1) : retVal2;
}
let arrayLength = getTopLength(L), table = import_fengari_interop.default.tojs(L, -1), retVal = [];
@@ -3830,9 +3840,15 @@ var { lua: lua2, to_luastring: toLuaString2 } = import_fengari2.default, defineR
throw err;
return import_fengari_interop2.default.push(vm.L, ["error", err.toString()]), 1;
}
- return result || result === 0 ? (Array.isArray(result) && (result.unshift(null), result[Symbol.for("__len")] = function() {
+ return result || result === 0 ? (
+ Array.isArray(result) && (result.unshift(null), result[Symbol.for("__len")] = function() {
+ return this.length - 1;
+ }),
+ Array.isArray(result[2]) && (result[2].unshift(null), result[2][Symbol.for("__len")] = function() {
return this.length - 1;
- }), import_fengari_interop2.default.push(vm.L, result), 1) : 0;
+ })
+ ,import_fengari_interop2.default.push(vm.L, result), 1
+) : 0;
};
function defineKeys(vm, numberOfKeys, commandArgs) {
let keys2 = commandArgs.slice(0, numberOfKeys);