@@ -2348,11 +2348,22 @@ pub const Lua = opaque {
23482348 /// Stack Behavior: `[-0, +0, v]`
23492349 pub fn checkArgument (lua : * Lua , condition : bool , arg_n : i32 , extra_message : ? [:0 ]const u8 ) void {
23502350 if (condition ) {
2351- const ptr : [* c ]const u8 = @ptrCast (if (extra_message ) | m | m else null );
2352- _ = c .luaL_argerror (asState (lua ), arg_n , ptr );
2351+ _ = c .luaL_argerror (asState (lua ), arg_n , if (extra_message ) | m | m else null );
23532352 }
23542353 }
23552354
2355+ /// Raises an error with the message "bad argument #<arg_n> to <func> (<extra_message>)". The function
2356+ /// func is retrieved from the call stack. This function never returns, but it is an idiom
2357+ /// to use it as a return statement.
2358+ ///
2359+ /// From: `int luaL_argerror(lua_State *L, int narg, const char *extramsg);`
2360+ /// Refer to: https://www.lua.org/manual/5.1/manual.html#luaL_argerror
2361+ /// Stack Behavior: `[-0, +0, v]`
2362+ pub fn raiseErrorArgument (lua : * Lua , arg_n : i32 , extra_message : ? [:0 ]const u8 ) noreturn {
2363+ _ = c .luaL_argerror (asState (lua ), arg_n , if (extra_message ) | m | m .ptr else null );
2364+ unreachable ;
2365+ }
2366+
23562367 /// Represents named functions that belong to a library that can be registered by a call to the `registerLibrary()`
23572368 /// function.
23582369 ///
@@ -4227,7 +4238,7 @@ test "checkType should validate argument type" {
42274238 try std .testing .expectEqualSlices (u8 , "bad argument #1 to '?' (string expected, got number)" , try lua .toLString (-1 ));
42284239}
42294240
4230- test "checkArgument should return error when argument is invalid and succeed when argument is OK" {
4241+ test "checkArgument() should return error when argument is invalid and succeed when argument is OK" {
42314242 const lua = try Lua .init (std .testing .allocator );
42324243 defer lua .deinit ();
42334244
@@ -4255,6 +4266,52 @@ test "checkArgument should return error when argument is invalid and succeed whe
42554266 try std .testing .expectEqualSlices (u8 , "bad argument #1 to '?' (FOOBAR)" , message );
42564267}
42574268
4269+ test "checkArgument() should return handle null message" {
4270+ const lua = try Lua .init (std .testing .allocator );
4271+ defer lua .deinit ();
4272+
4273+ const T = struct {
4274+ fn EchoInteger (l : * Lua ) callconv (.c ) i32 {
4275+ const val = l .toInteger (1 );
4276+ l .checkArgument (val != 42 , 1 , null );
4277+ l .pushInteger (val );
4278+ return 1 ;
4279+ }
4280+ };
4281+
4282+ lua .pushCFunction (T .EchoInteger );
4283+ lua .pushInteger (1 );
4284+ const actual = lua .callProtected (1 , 1 , 0 );
4285+ try std .testing .expectError (error .Runtime , actual );
4286+
4287+ const message = try lua .toLString (-1 );
4288+ try std .testing .expectEqualSlices (u8 , "bad argument #1 to '?' ((null))" , message );
4289+ }
4290+
4291+ test "raiseErrorArgument() should return correct error messages" {
4292+ const lua = try Lua .init (std .testing .allocator );
4293+ defer lua .deinit ();
4294+
4295+ const T = struct {
4296+ fn FullError (l : * Lua ) callconv (.c ) i32 {
4297+ return l .raiseErrorArgument (1 , "FOO" );
4298+ }
4299+ fn NullError (l : * Lua ) callconv (.c ) i32 {
4300+ return l .raiseErrorArgument (1 , null );
4301+ }
4302+ };
4303+
4304+ lua .pushCFunction (T .FullError );
4305+ lua .pushInteger (1 );
4306+ try std .testing .expectError (error .Runtime , lua .callProtected (1 , 1 , 0 ));
4307+ try std .testing .expectEqualSlices (u8 , "bad argument #1 to '?' (FOO)" , try lua .toLString (-1 ));
4308+
4309+ lua .pushCFunction (T .NullError );
4310+ lua .pushInteger (1 );
4311+ try std .testing .expectError (error .Runtime , lua .callProtected (1 , 1 , 0 ));
4312+ try std .testing .expectEqualSlices (u8 , "bad argument #1 to '?' ((null))" , try lua .toLString (-1 ));
4313+ }
4314+
42584315test "ref and unref in user table" {
42594316 const lua = try Lua .init (std .testing .allocator );
42604317 defer lua .deinit ();
0 commit comments