diff --git a/README.html b/README.html index c92dbef4..e477ccb8 100644 --- a/README.html +++ b/README.html @@ -967,6 +967,7 @@ Files are no longer hosted at LuaForge.
  • Fix __len metatag processing for tables.
  • Add fallback to __lt when pocessing __le metatag.
  • Convert anonymous classes to inner classes (gradle build support).
  • +
  • Allow error() function to pass any lua object including non-strings.
  • diff --git a/src/core/org/luaj/vm2/LuaError.java b/src/core/org/luaj/vm2/LuaError.java index cbe68eb8..13f52323 100644 --- a/src/core/org/luaj/vm2/LuaError.java +++ b/src/core/org/luaj/vm2/LuaError.java @@ -32,7 +32,11 @@ package org.luaj.vm2; * Java method signatures do notdeclare this exception, althoug it can * be thrown on almost any luaj Java operation. * This is analagous to the fact that any lua script can throw a lua error at any time. - *

    + *

    + * The LuaError may be constructed with a message object, in which case the message + * is the string representation of that object. getMessageObject will get the object + * supplied at construct time, or a LuaString containing the message of an object + * was not supplied. */ public class LuaError extends RuntimeException { private static final long serialVersionUID = 1L; @@ -45,6 +49,11 @@ public class LuaError extends RuntimeException { protected Throwable cause; + private LuaValue object; + + /** Get the string message if it was supplied, or a string + * representation of the message object if that was supplied. + */ public String getMessage() { if (traceback != null) return traceback; @@ -56,6 +65,17 @@ public class LuaError extends RuntimeException { return m; } + /** Get the LuaValue that was provided in the constructor, or + * a LuaString containing the message if it was a string error argument. + * @return LuaValue which was used in the constructor, or a LuaString + * containing the message. + */ + public LuaValue getMessageObject() { + if (object != null) return object; + String m = getMessage(); + return m != null ? LuaValue.valueOf(m): null; + } + /** Construct LuaError when a program exception occurs. *

    * All errors generated from lua code should throw LuaError(String) instead. @@ -87,6 +107,18 @@ public class LuaError extends RuntimeException { this.level = level; } + /** + * Construct a LuaError with a LuaValue as the message object, + * and level to draw line number information from. + * @param message message to supply + * @param level where to supply line info from in call stack + */ + public LuaError(LuaValue message_object) { + super( message_object.tojstring() ); + this.object = message_object; + this.level = 1; + } + /** * Get the cause, if any. diff --git a/src/core/org/luaj/vm2/lib/BaseLib.java b/src/core/org/luaj/vm2/lib/BaseLib.java index 06f622e5..9dd3be98 100644 --- a/src/core/org/luaj/vm2/lib/BaseLib.java +++ b/src/core/org/luaj/vm2/lib/BaseLib.java @@ -167,7 +167,9 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { // "error", // ( message [,level] ) -> ERR static final class error extends TwoArgFunction { public LuaValue call(LuaValue arg1, LuaValue arg2) { - throw new LuaError( arg1.isnil()? null: arg1.tojstring(), arg2.optint(1) ); + throw arg1.isnil()? new LuaError(null, arg2.optint(1)): + arg1.isstring()? new LuaError(arg1.tojstring(), arg2.optint(1)): + new LuaError(arg1); } } @@ -216,8 +218,8 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { try { return varargsOf(TRUE, func.invoke(args.subargs(2))); } catch ( LuaError le ) { - final String m = le.getMessage(); - return varargsOf(FALSE, m!=null? valueOf(m): NIL); + final LuaValue m = le.getMessageObject(); + return varargsOf(FALSE, m!=null? m: NIL); } catch ( Exception e ) { final String m = e.getMessage(); return varargsOf(FALSE, valueOf(m!=null? m: e.toString())); @@ -369,8 +371,8 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { try { return varargsOf(TRUE, args.arg1().invoke(args.subargs(3))); } catch ( LuaError le ) { - final String m = le.getMessage(); - return varargsOf(FALSE, m!=null? valueOf(m): NIL); + final LuaValue m = le.getMessageObject(); + return varargsOf(FALSE, m!=null? m: NIL); } catch ( Exception e ) { final String m = e.getMessage(); return varargsOf(FALSE, valueOf(m!=null? m: e.toString())); diff --git a/test/junit/org/luaj/vm2/FragmentsTest.java b/test/junit/org/luaj/vm2/FragmentsTest.java index c8784f24..0b6f0c17 100644 --- a/test/junit/org/luaj/vm2/FragmentsTest.java +++ b/test/junit/org/luaj/vm2/FragmentsTest.java @@ -563,7 +563,6 @@ public class FragmentsTest extends TestSuite { "return pcall(error)\n"); } - public void testFindWithOffset() { runFragment(LuaValue.varargsOf(LuaValue.valueOf(8), LuaValue.valueOf(5)), "string = \"abcdef:ghi\"\n" + @@ -571,5 +570,26 @@ public class FragmentsTest extends TestSuite { "idx = substring:find(\":\")\n" + "return #substring, idx\n"); } + + public void testErrorArgIsString() { + runFragment(LuaValue.varargsOf(LuaValue.valueOf("string"), LuaValue.valueOf("c")), + "a,b = pcall(error, 'c'); return type(b), b\n"); + } + public void testErrorArgIsNil() { + runFragment(LuaValue.varargsOf(LuaValue.valueOf("nil"), LuaValue.NIL), + "a,b = pcall(error); return type(b), b\n"); + } + public void testErrorArgIsTable() { + runFragment(LuaValue.varargsOf(LuaValue.valueOf("table"), LuaValue.valueOf("d")), + "a,b = pcall(error, {c='d'}); return type(b), b.c\n"); + } + public void testErrorArgIsNumber() { + runFragment(LuaValue.varargsOf(LuaValue.valueOf("string"), LuaValue.valueOf("1")), + "a,b = pcall(error, 1); return type(b), b\n"); + } + public void testErrorArgIsBool() { + runFragment(LuaValue.varargsOf(LuaValue.valueOf("boolean"), LuaValue.TRUE), + "a,b = pcall(error, true); return type(b), b\n"); + } } }