diff --git a/core/src/main/java/org/luaj/vm2/LuaValue$None.class b/core/src/main/java/org/luaj/vm2/LuaValue$None.class index afbf0c29..6770609f 100644 Binary files a/core/src/main/java/org/luaj/vm2/LuaValue$None.class and b/core/src/main/java/org/luaj/vm2/LuaValue$None.class differ diff --git a/core/src/main/java/org/luaj/vm2/LuaValue.class b/core/src/main/java/org/luaj/vm2/LuaValue.class index 50c3a02a..c020ef9b 100644 Binary files a/core/src/main/java/org/luaj/vm2/LuaValue.class and b/core/src/main/java/org/luaj/vm2/LuaValue.class differ diff --git a/core/src/main/java/org/luaj/vm2/LuaValue.java b/core/src/main/java/org/luaj/vm2/LuaValue.java index 1862f206..7c43794f 100644 --- a/core/src/main/java/org/luaj/vm2/LuaValue.java +++ b/core/src/main/java/org/luaj/vm2/LuaValue.java @@ -99,7 +99,7 @@ package org.luaj.vm2; * {@link #INDEX}, {@link #NEWINDEX}, {@link #CALL}, {@link #MODE}, {@link #METATABLE}, * {@link #ADD}, {@link #SUB}, {@link #DIV}, {@link #MUL}, {@link #POW}, * {@link #MOD}, {@link #UNM}, {@link #LEN}, {@link #EQ}, {@link #LT}, - * {@link #LE}, {@link #TOSTRING}, and {@link #CONCAT}. + * {@link #LE}, {@link #TOSTRING}, {@link #CONCAT}, {@link #PAIRS}, and {@link #IPAIRS}. * * @see org.luaj.vm2.libs.jse.JsePlatform * @see org.luaj.vm2.libs.jme.JmePlatform @@ -263,6 +263,12 @@ public class LuaValue extends Varargs { /** LuaString constant with value "__concat" for use as metatag */ public static final LuaString CONCAT = valueOf("__concat"); + + /** LuaString constant with value "__pairs" for use as metatag */ + public static final LuaString PAIRS = valueOf("__pairs"); + + /** LuaString constant with value "__ipairs" for use as metatag */ + public static final LuaString IPAIRS = valueOf("__ipairs"); /** LuaString constant with value "" */ public static final LuaString EMPTYSTRING = valueOf(""); diff --git a/core/src/main/java/org/luaj/vm2/libs/BaseLib$StringInputStream.class b/core/src/main/java/org/luaj/vm2/libs/BaseLib$StringInputStream.class index a3c1f1dc..f1a3445b 100644 Binary files a/core/src/main/java/org/luaj/vm2/libs/BaseLib$StringInputStream.class and b/core/src/main/java/org/luaj/vm2/libs/BaseLib$StringInputStream.class differ diff --git a/core/src/main/java/org/luaj/vm2/libs/BaseLib$inext.class b/core/src/main/java/org/luaj/vm2/libs/BaseLib$inext.class index 8027c609..347d2372 100644 Binary files a/core/src/main/java/org/luaj/vm2/libs/BaseLib$inext.class and b/core/src/main/java/org/luaj/vm2/libs/BaseLib$inext.class differ diff --git a/core/src/main/java/org/luaj/vm2/libs/BaseLib$ipairs.class b/core/src/main/java/org/luaj/vm2/libs/BaseLib$ipairs.class index b1cf8fba..96d51952 100644 Binary files a/core/src/main/java/org/luaj/vm2/libs/BaseLib$ipairs.class and b/core/src/main/java/org/luaj/vm2/libs/BaseLib$ipairs.class differ diff --git a/core/src/main/java/org/luaj/vm2/libs/BaseLib$next.class b/core/src/main/java/org/luaj/vm2/libs/BaseLib$next.class index f3051898..816fed3d 100644 Binary files a/core/src/main/java/org/luaj/vm2/libs/BaseLib$next.class and b/core/src/main/java/org/luaj/vm2/libs/BaseLib$next.class differ diff --git a/core/src/main/java/org/luaj/vm2/libs/BaseLib$pairs.class b/core/src/main/java/org/luaj/vm2/libs/BaseLib$pairs.class index c0bea42b..ad6fa8bb 100644 Binary files a/core/src/main/java/org/luaj/vm2/libs/BaseLib$pairs.class and b/core/src/main/java/org/luaj/vm2/libs/BaseLib$pairs.class differ diff --git a/core/src/main/java/org/luaj/vm2/libs/BaseLib.class b/core/src/main/java/org/luaj/vm2/libs/BaseLib.class index e913d9e4..2b24d276 100644 Binary files a/core/src/main/java/org/luaj/vm2/libs/BaseLib.class and b/core/src/main/java/org/luaj/vm2/libs/BaseLib.class differ diff --git a/core/src/main/java/org/luaj/vm2/libs/BaseLib.java b/core/src/main/java/org/luaj/vm2/libs/BaseLib.java index c94bc753..9be315bd 100644 --- a/core/src/main/java/org/luaj/vm2/libs/BaseLib.java +++ b/core/src/main/java/org/luaj/vm2/libs/BaseLib.java @@ -399,7 +399,9 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { this.next = next; } public Varargs invoke(Varargs args) { - return varargsOf( next, args.checktable(1), NIL ); + LuaValue table = args.arg1(); + LuaValue h = table.metatag(PAIRS); + return h.isnil()? varargsOf(next, table.checktable(), NIL): h.invoke(table); } } @@ -407,7 +409,9 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { static final class ipairs extends VarArgFunction { inext inext = new inext(); public Varargs invoke(Varargs args) { - return varargsOf( inext, args.checktable(1), ZERO ); + LuaValue table = args.arg1(); + LuaValue h = table.metatag(IPAIRS); + return h.isnil()? varargsOf(inext, table.checktable(), ZERO): h.invoke(table); } } diff --git a/jse/src/test/java/org/luaj/vm2/FragmentsTest.java b/jse/src/test/java/org/luaj/vm2/FragmentsTest.java index c491c2cc..58c6c656 100644 --- a/jse/src/test/java/org/luaj/vm2/FragmentsTest.java +++ b/jse/src/test/java/org/luaj/vm2/FragmentsTest.java @@ -331,6 +331,48 @@ public class FragmentsTest extends TestSuite { } } + public void testPairsUsesMetatableOverride() { + runFragment( + LuaValue.varargsOf(new LuaValue[] { + LuaValue.valueOf("k"), + LuaValue.valueOf("v") + }), + "local t = setmetatable({}, {\n" + + " __pairs = function(self)\n" + + " local done = false\n" + + " return function()\n" + + " if done then return nil end\n" + + " done = true\n" + + " return 'k', 'v'\n" + + " end, self, nil\n" + + " end\n" + + "})\n" + + "for k, v in pairs(t) do\n" + + " return k, v\n" + + "end\n"); + } + + public void testIpairsUsesMetatableOverride() { + runFragment( + LuaValue.varargsOf(new LuaValue[] { + LuaValue.valueOf(7), + LuaValue.valueOf("x") + }), + "local t = setmetatable({}, {\n" + + " __ipairs = function(self)\n" + + " local done = false\n" + + " return function()\n" + + " if done then return nil end\n" + + " done = true\n" + + " return 7, 'x'\n" + + " end, self, 0\n" + + " end\n" + + "})\n" + + "for i, v in ipairs(t) do\n" + + " return i, v\n" + + "end\n"); + } + public void testTableMove() { runFragment( LuaValue.varargsOf(new LuaValue[] {