hslua 0.8.0 → 0.9.0
raw patch · 9 files changed
+307/−15 lines, 9 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Foreign.Lua.Api: throwTopMessageAsError :: Lua a
+ Foreign.Lua.Api: throwTopMessageAsError' :: (String -> String) -> Lua a
+ Foreign.Lua.Types.FromLuaStack: instance Foreign.Lua.Types.FromLuaStack.FromLuaStack Data.ByteString.Lazy.Internal.ByteString
+ Foreign.Lua.Types.ToLuaStack: instance Foreign.Lua.Types.ToLuaStack.ToLuaStack Data.ByteString.Lazy.Internal.ByteString
Files
- CHANGELOG.md +15/−0
- README.md +36/−5
- hslua.cabal +10/−1
- src/Foreign/Lua/Api.hs +38/−3
- src/Foreign/Lua/Api/RawBindings.hsc +176/−0
- src/Foreign/Lua/FunctionCalling.hs +3/−4
- src/Foreign/Lua/Types/FromLuaStack.hs +4/−0
- src/Foreign/Lua/Types/ToLuaStack.hs +4/−0
- test/Foreign/Lua/ApiTest.hs +21/−2
CHANGELOG.md view
@@ -1,4 +1,19 @@ ## Changelog+### 0.9.0++- Added cabal flag to allow fully safe garbage collection: Lua garbage+ collection can occur in most of the API functions, even in those usually not+ calling back into haskell and hence marked as optimizable. The effect of this+ is that finalizers which call Haskell functions will cause the program to+ hang. A new flag `allow-unsafe-gc` is introduced and enabled by default.+ Disabling this flag will mark more C API functions as potentially calling back+ into Haskell. This has a serious performance impact.+- `FromLuaStack` and `ToLuaStack` instances for lazy ByteStrings are added.+- None-string error messages are handled properly: Lua allows error messages to+ be of any type, but the haskell error handlers expected string values. Tables,+ booleans, and other non-string values are now handled as well and converted to+ strings.+ ### 0.8.0 - Use newtype definitions instead of type aliases for LuaNumber and LuaInteger.
README.md view
@@ -14,16 +14,47 @@ [Hackage]: http://img.shields.io/hackage/v/hslua.svg -Using a different lua version------------------------------+Build flags+----------- -To use system-wide installed Lua/LuaJIT when linking hslua as a dependency,+The following cabal build flags are supported:++- `system-lua`: Use the locally installed Lua version instead of the version+ shipped as part of HsLua.++- `use-pkgconfig`: Use `pkg-config` to discover library and include paths. This+ is used only when the `system-lua` flag is set or implied.++- `lua501`: Build against Lua 5.1; this implies the flag `system-lua` as well.++- `lua502`: Build against Lua 5.2; this implies the flag `system-lua` as well.++- `luajit`: Build against LuaJIT; this implies the flag `system-lua` as well.++- `allow-unsafe-gc`: Allow optimizations which make Lua's garbage collection+ potentially unsafe; haskell finalizers must be handled with extreme care. This+ is *enabled* per default, as this is rarely a problem in practice.++- `apicheck`: Compile Lua with its API checks enabled.++- `lua_32bits`: Compile Lua for a 32-bits system (e.g., i386, PowerPC G4).+++### Example: using a different lua version++To use a system-wide installed Lua/LuaJIT when linking hslua as a dependency, build/install your package using `--constraint="hslua +system-lua"` or for-LuaJIT: `--constraint="hslua +system-lua +luajit"`. For example, you can install-Pandoc with hslua that uses system-wide LuaJIT like this:+LuaJIT: `--constraint="hslua +luajit"`. For example, you can install Pandoc with+hslua that uses system-wide LuaJIT like this: ``` sh cabal install pandoc --constraint="hslua +system-lua +luajit"+```++or with stack:++``` sh+stack install pandoc --flag=hslua:luajit ```
hslua.cabal view
@@ -1,5 +1,5 @@ name: hslua-version: 0.8.0+version: 0.9.0 stability: beta cabal-version: >= 1.8 license: MIT@@ -47,6 +47,12 @@ description: Compile Lua with -DLUA_32BITS default: False +flag allow-unsafe-gc+ description: Allow optimizations which make Lua's garbage collection+ potentially unsafe; haskell finalizers must be handled+ with extreme care.+ default: True+ flag luajit description: Link with LuaJIT. This implies flag system-lua as well. default: False@@ -171,6 +177,9 @@ if flag(lua_32bits) cc-options: "-DLUA_32BITS"++ if flag(allow-unsafe-gc)+ cc-options: "-DALLOW_UNSAFE_GC" if flag(apicheck) cc-options: "-DLUA_USE_APICHECK"
src/Foreign/Lua/Api.hs view
@@ -166,6 +166,9 @@ , newmetatable , ref , unref+ -- * Helper functions+ , throwTopMessageAsError+ , throwTopMessageAsError' ) where import Prelude hiding (EQ, LT, compare, concat)@@ -198,9 +201,41 @@ else return x throwTopMessageAsError :: Lua a-throwTopMessageAsError = do- msg <- tostring (-1) <* pop 1- throwLuaError (BC.unpack msg)+throwTopMessageAsError = throwTopMessageAsError' id++throwTopMessageAsError' :: (String -> String) -> Lua a+throwTopMessageAsError' msgMod = do+ ty <- ltype (-1)+ msg <- case ty of+ TypeNil -> return "nil"+ TypeBoolean -> show <$> toboolean (-1)+ TypeLightUserdata -> showPointer+ TypeNumber -> BC.unpack <$> tostring (-1)+ TypeString -> BC.unpack <$> tostring (-1)+ TypeTable -> tryTostringMetaMethod+ TypeFunction -> showPointer+ TypeThread -> showPointer+ TypeUserdata -> showPointer+ TypeNone -> error "Error while receiving the error message!"+ pop 1+ throwLuaError (msgMod msg)+ where+ showPointer = show <$> topointer (-1)+ tryTostringMetaMethod = do+ hasMT <- getmetatable (-1)+ if not hasMT+ then showPointer+ else do+ -- push getmetatable(t).__tostring+ pushstring (BC.pack "__tostring") *> rawget (-2)+ remove (-2) -- remove metatable from stack+ isFn <- isfunction (-1)+ if isFn+ then do+ insert (-2)+ call 1 1+ BC.unpack <$> tostring (-1)+ else pop 1 *> showPointer -- -- API functions
src/Foreign/Lua/Api/RawBindings.hsc view
@@ -72,37 +72,69 @@ lua_gettop :: LuaState -> IO StackIndex -- | See <https://www.lua.org/manual/5.3/manual.html#lua_settop lua_settop>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_settop"+#else+foreign import ccall safe "lua.h lua_settop"+#endif lua_settop :: LuaState -> StackIndex -> IO () -- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushvalue lua_pushvalue>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_pushvalue"+#else+foreign import ccall safe "lua.h lua_pushvalue"+#endif lua_pushvalue :: LuaState -> StackIndex -> IO () #if LUA_VERSION_NUMBER >= 503 -- | See <https://www.lua.org/manual/5.3/manual.html#lua_rotate lua_rotate>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_rotate"+#else+foreign import ccall "lua.h lua_rotate"+#endif lua_rotate :: LuaState -> StackIndex -> CInt -> IO () -- | See <https://www.lua.org/manual/5.3/manual.html#lua_copy lua_copy>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_copy"+#else+foreign import ccall "lua.h lua_copy"+#endif lua_copy :: LuaState -> StackIndex -> StackIndex -> IO () #else -- | See <https://www.lua.org/manual/5.2/manual.html#lua_remove lua_remove>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_remove"+#else+foreign import ccall safe "lua.h lua_remove"+#endif lua_remove :: LuaState -> StackIndex -> IO () -- | See <https://www.lua.org/manual/5.2/manual.html#lua_insert lua_insert>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_insert"+#else+foreign import ccall safe "lua.h lua_insert"+#endif lua_insert :: LuaState -> StackIndex -> IO () -- | See <https://www.lua.org/manual/5.2/manual.html#lua_replace lua_replace>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_replace"+#else+foreign import ccall safe "lua.h lua_replace"+#endif lua_replace :: LuaState -> StackIndex -> IO () #endif -- | See <https://www.lua.org/manual/5.3/manual.html#lua_checkstack lua_checkstack>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_checkstack"+#else+foreign import ccall safe "lua.h lua_checkstack"+#endif lua_checkstack :: LuaState -> StackIndex -> IO LuaBool -- lua_xmove is currently not supported.@@ -112,27 +144,51 @@ -- * Stack access functions -- | See <https://www.lua.org/manual/5.3/manual.html#lua_isnumber lua_isnumber>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_isnumber"+#else+foreign import ccall safe "lua.h lua_isnumber"+#endif lua_isnumber :: LuaState -> StackIndex -> IO LuaBool -- | See <https://www.lua.org/manual/5.3/manual.html#lua_isstring lua_isstring>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_isstring"+#else+foreign import ccall safe "lua.h lua_isstring"+#endif lua_isstring :: LuaState -> StackIndex -> IO LuaBool -- | See <https://www.lua.org/manual/5.3/manual.html#lua_iscfunction lua_iscfunction>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_iscfunction"+#else+foreign import ccall safe "lua.h lua_iscfunction"+#endif lua_iscfunction :: LuaState -> StackIndex -> IO LuaBool -- | See <https://www.lua.org/manual/5.3/manual.html#lua_isuserdata lua_isuserdata>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_isuserdata"+#else+foreign import ccall safe "lua.h lua_isuserdata"+#endif lua_isuserdata :: LuaState -> StackIndex -> IO LuaBool -- | See <https://www.lua.org/manual/5.3/manual.html#lua_type lua_type>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_type"+#else+foreign import ccall safe "lua.h lua_type"+#endif lua_type :: LuaState -> StackIndex -> IO TypeCode -- | See <https://www.lua.org/manual/5.3/manual.html#lua_typename lua_typename>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_typename"+#else+foreign import ccall safe "lua.h lua_typename"+#endif lua_typename :: LuaState -> TypeCode -> IO (Ptr CChar) -- lua_compare is unsafe (might cause a longjmp), use hslua_compare instead.@@ -153,52 +209,96 @@ #endif -- | See <https://www.lua.org/manual/5.3/manual.html#lua_rawequal lua_rawequal>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_rawequal"+#else+foreign import ccall safe "lua.h lua_rawequal"+#endif lua_rawequal :: LuaState -> StackIndex -> StackIndex -> IO LuaBool -- -- Type coercion -- -- | See <https://www.lua.org/manual/5.3/manual.html#lua_toboolean lua_toboolean>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_toboolean"+#else+foreign import ccall safe "lua.h lua_toboolean"+#endif lua_toboolean :: LuaState -> StackIndex -> IO StackIndex -- | See <https://www.lua.org/manual/5.3/manual.html#lua_tocfunction lua_tocfunction>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_tocfunction"+#else+foreign import ccall safe "lua.h lua_tocfunction"+#endif lua_tocfunction :: LuaState -> StackIndex -> IO CFunction #if LUA_VERSION_NUMBER >= 502 -- | See <https://www.lua.org/manual/5.3/manual.html#lua_tointegerx lua_tointegerx>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_tointegerx"+#else+foreign import ccall safe "lua.h lua_tointegerx"+#endif lua_tointegerx :: LuaState -> StackIndex -> Ptr LuaBool -> IO LuaInteger -- | See <https://www.lua.org/manual/5.3/manual.html#lua_tonumberx lua_tonumberx>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_tonumberx"+#else+foreign import ccall safe "lua.h lua_tonumberx"+#endif lua_tonumberx :: LuaState -> StackIndex -> Ptr LuaBool -> IO LuaNumber #else -- | See <https://www.lua.org/manual/5.1/manual.html#lua_tointeger lua_tointeger>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_tointeger"+#else+foreign import ccall safe "lua.h lua_tointeger"+#endif lua_tointeger :: LuaState -> StackIndex -> IO LuaInteger -- | See <https://www.lua.org/manual/5.1/manual.html#lua_tonumber lua_tonumber>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_tonumber"+#else+foreign import ccall safe "lua.h lua_tonumber"+#endif lua_tonumber :: LuaState -> StackIndex -> IO LuaNumber #endif -- | See <https://www.lua.org/manual/5.3/manual.html#lua_tolstring lua_tolstring>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_tolstring"+#else+foreign import ccall safe "lua.h lua_tolstring"+#endif lua_tolstring :: LuaState -> StackIndex -> Ptr CSize -> IO (Ptr CChar) -- | See <https://www.lua.org/manual/5.3/manual.html#lua_topointer lua_topointer>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_topointer"+#else+foreign import ccall safe "lua.h lua_topointer"+#endif lua_topointer :: LuaState -> StackIndex -> IO (Ptr ()) -- | See <https://www.lua.org/manual/5.3/manual.html#lua_tothread lua_tothread>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_tothread"+#else+foreign import ccall safe "lua.h lua_tothread"+#endif lua_tothread :: LuaState -> StackIndex -> IO LuaState -- | See <https://www.lua.org/manual/5.3/manual.html#lua_touserdata lua_touserdata>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_touserdata"+#else+foreign import ccall safe "lua.h lua_touserdata"+#endif lua_touserdata :: LuaState -> StackIndex -> IO (Ptr a) @@ -208,11 +308,19 @@ #if LUA_VERSION_NUMBER >= 502 -- | See <https://www.lua.org/manual/5.3/manual.html#lua_rawlen lua_rawlen>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_rawlen"+#else+foreign import ccall safe "lua.h lua_rawlen"+#endif lua_rawlen :: LuaState -> StackIndex -> IO CSize #else -- | See <https://www.lua.org/manual/5.1/manual.html#lua_objlen lua_objlen>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_objlen"+#else+foreign import ccall safe "lua.h lua_objlen"+#endif lua_objlen :: LuaState -> StackIndex -> IO CSize #endif @@ -221,38 +329,70 @@ -- * Push functions -- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushnil lua_pushnil>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_pushnil"+#else+foreign import ccall safe "lua.h lua_pushnil"+#endif lua_pushnil :: LuaState -> IO () -- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushnumber lua_pushnumber>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_pushnumber"+#else+foreign import ccall safe "lua.h lua_pushnumber"+#endif lua_pushnumber :: LuaState -> LuaNumber -> IO () -- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushinteger lua_pushinteger>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_pushinteger"+#else+foreign import ccall safe "lua.h lua_pushinteger"+#endif lua_pushinteger :: LuaState -> LuaInteger -> IO () -- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushlstring lua_pushlstring>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_pushlstring"+#else+foreign import ccall safe "lua.h lua_pushlstring"+#endif lua_pushlstring :: LuaState -> Ptr CChar -> CSize -> IO () -- lua_pushstring is currently not supported. It's difficult to use in a haskell -- context. -- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushcclosure lua_pushcclosure>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_pushcclosure"+#else+foreign import ccall safe "lua.h lua_pushcclosure"+#endif lua_pushcclosure :: LuaState -> CFunction -> NumArgs -> IO () -- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushboolean lua_pushboolean>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_pushboolean"+#else+foreign import ccall safe "lua.h lua_pushboolean"+#endif lua_pushboolean :: LuaState -> LuaBool -> IO () -- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushlightuserdata lua_pushlightuserdata>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_pushlightuserdata"+#else+foreign import ccall safe "lua.h lua_pushlightuserdata"+#endif lua_pushlightuserdata :: LuaState -> Ptr a -> IO () -- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushthread lua_pushthread>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_pushthread"+#else+foreign import ccall safe "lua.h lua_pushthread"+#endif lua_pushthread :: LuaState -> IO CInt @@ -275,23 +415,43 @@ hslua_getfield :: LuaState -> StackIndex -> Ptr CChar -> IO CInt -- | See <https://www.lua.org/manual/5.3/manual.html#lua_rawget lua_rawget>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_rawget"+#else+foreign import ccall safe "lua.h lua_rawget"+#endif lua_rawget :: LuaState -> StackIndex -> IO () -- | See <https://www.lua.org/manual/5.3/manual.html#lua_rawgeti lua_rawgeti>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_rawgeti"+#else+foreign import ccall safe "lua.h lua_rawgeti"+#endif lua_rawgeti :: LuaState -> StackIndex -> CInt -> IO () -- | See <https://www.lua.org/manual/5.3/manual.html#lua_createtable lua_createtable>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_createtable"+#else+foreign import ccall safe "lua.h lua_createtable"+#endif lua_createtable :: LuaState -> CInt -> CInt -> IO () -- | See <https://www.lua.org/manual/5.3/manual.html#lua_newuserdata lua_newuserdata>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_newuserdata"+#else+foreign import ccall safe "lua.h lua_newuserdata"+#endif lua_newuserdata :: LuaState -> CInt -> IO (Ptr ()) -- | See <https://www.lua.org/manual/5.3/manual.html#lua_getmetatable lua_getmetatable>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_getmetatable"+#else+foreign import ccall safe "lua.h lua_getmetatable"+#endif lua_getmetatable :: LuaState -> StackIndex -> IO CInt -- | Wrapper around <https://lua.org/manual/5.3/manual.html#lua_getglobal \@@ -319,15 +479,27 @@ hslua_setfield :: LuaState -> StackIndex -> Ptr CChar -> IO CInt -- | See <https://www.lua.org/manual/5.3/manual.html#lua_rawset lua_rawset>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_rawset"+#else+foreign import ccall safe "lua.h lua_rawset"+#endif lua_rawset :: LuaState -> StackIndex -> IO () -- | See <https://www.lua.org/manual/5.3/manual.html#lua_rawseti lua_rawseti>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_rawseti"+#else+foreign import ccall safe "lua.h lua_rawseti"+#endif lua_rawseti :: LuaState -> StackIndex -> CInt -> IO () -- | See <https://www.lua.org/manual/5.3/manual.html#lua_setmetatable lua_setmetatable>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lua.h lua_setmetatable"+#else+foreign import ccall safe "lua.h lua_setmetatable"+#endif lua_setmetatable :: LuaState -> StackIndex -> IO () -- | Wrapper around <https://lua.org/manual/5.3/manual.html#lua_setglobal \@@ -462,5 +634,9 @@ #endif -- | See <https://www.lua.org/manual/5.3/manual.html#luaL_loadstring luaL_loadstring>+#ifdef ALLOW_UNSAFE_GC foreign import ccall unsafe "lauxlib.h luaL_loadstring"+#else+foreign import ccall safe "lauxlib.h luaL_loadstring"+#endif luaL_loadstring :: LuaState -> Ptr CChar -> IO StatusCode
src/Foreign/Lua/FunctionCalling.hs view
@@ -56,7 +56,6 @@ ) where import Control.Monad (when)-import Data.ByteString.Char8 (unpack) import Foreign.C (CInt (..)) import Foreign.Lua.Api import Foreign.Lua.Types@@ -133,9 +132,9 @@ getglobal' fnName x z <- pcall nargs 1 Nothing- if z /= OK- then tostring (-1) >>= throwLuaError . unpack- else peek (-1) <* pop 1+ if z == OK+ then peek (-1) <* pop 1+ else throwTopMessageAsError instance (ToLuaStack a, LuaCallFunc b) => LuaCallFunc (a -> b) where callFunc' fnName pushArgs nargs x =
src/Foreign/Lua/Types/FromLuaStack.hs view
@@ -57,6 +57,7 @@ import qualified Data.Text as T import qualified Data.Text.Encoding as T+import qualified Data.ByteString.Lazy as BL -- | Result returned when trying to get a value from the lua stack. type Result a = Either String a@@ -115,6 +116,9 @@ instance FromLuaStack T.Text where peek = fmap T.decodeUtf8 . peek++instance FromLuaStack BL.ByteString where+ peek = fmap BL.fromStrict . peek #if MIN_VERSION_base(4,8,0) instance {-# OVERLAPS #-} FromLuaStack [Char] where
src/Foreign/Lua/Types/ToLuaStack.hs view
@@ -53,6 +53,7 @@ import qualified Data.Text as T import qualified Data.Text.Encoding as T+import qualified Data.ByteString.Lazy as BL -- | A value that can be pushed to the Lua stack. class ToLuaStack a where@@ -83,6 +84,9 @@ instance ToLuaStack T.Text where push = push . T.encodeUtf8++instance ToLuaStack BL.ByteString where+ push = push . BL.toStrict #if MIN_VERSION_base(4,8,0) instance {-# OVERLAPS #-} ToLuaStack [Char] where
test/Foreign/Lua/ApiTest.hs view
@@ -37,6 +37,7 @@ import Prelude hiding (compare) import Control.Monad (forM_)+import Data.Monoid ((<>)) import Foreign.Lua as Lua import Test.HsLua.Arbitrary () import Test.HsLua.Util (luaTestCase, pushLuaExpr)@@ -64,7 +65,7 @@ rawequal (-1) (-3) ] - , testGroup "insert" $+ , testGroup "insert" [ luaTestCase "inserts stack elements using negative indices" $ do pushLuaExpr "1, 2, 3, 4, 5, 6, 7, 8, 9" insert (-6)@@ -226,7 +227,7 @@ pushLuaExpr "function () error 'error in error handler' end" loadstring "error 'this fails'" *> pcall 0 0 (Just (-2)) - , testCase "garbage collection" . runLua $ do+ , testCase "garbage collection" . runLua $ -- test that gc can be called with all constructors of type GCCONTROL. forM_ [GCSTOP .. GCSETSTEPMUL] $ \what -> (gc what 23) @@ -247,6 +248,24 @@ let n1 = fromType lt1 n2 = fromType lt2 in Prelude.compare n1 n2 == Prelude.compare lt1 lt2++ , testCase "functions can throw a table as error message" $ do+ let mt = "{__tostring = function (e) return e.error_code end}"+ let err = "error(setmetatable({error_code = 23}," <> mt <> "))"+ res <- runLua . tryLua $ openbase *> loadstring err *> call 0 0+ assertEqual "wrong error message" (Left (LuaException "23")) res++ , testCase "handling table errors won't leak" $ do+ let mt = "{__tostring = function (e) return e.code end}"+ let err = "error(setmetatable({code = 5}," <> mt <> "))"+ let luaOp = do+ openbase+ oldtop <- gettop+ _ <- tryLua $ loadstring err *> call 0 0+ newtop <- gettop+ return (newtop - oldtop)+ res <- runLua luaOp+ assertEqual "error handling leaks values to the stack" 0 res ] compareWith :: (LuaInteger -> LuaInteger -> Bool)