2017-05-21 19:50:59 -04:00
|
|
|
use std::fmt;
|
2017-07-18 16:21:12 -04:00
|
|
|
use std::error;
|
2017-05-21 19:50:59 -04:00
|
|
|
use std::panic::catch_unwind;
|
2017-05-25 00:43:35 -04:00
|
|
|
use std::os::raw::c_void;
|
2017-05-21 19:50:59 -04:00
|
|
|
|
2017-07-20 05:33:15 -04:00
|
|
|
use String as LuaString;
|
2017-07-24 10:40:00 -04:00
|
|
|
use {Lua, Result, ExternalError, LightUserData, UserDataMethods, UserData, Table, Thread,
|
|
|
|
ThreadStatus, Error, Function, Value, Variadic, MetaMethod};
|
2017-05-21 19:50:59 -04:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_set_get() {
|
|
|
|
let lua = Lua::new();
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
let globals = lua.globals();
|
2017-06-11 01:12:25 -04:00
|
|
|
globals.set("foo", "bar").unwrap();
|
|
|
|
globals.set("baz", "baf").unwrap();
|
|
|
|
assert_eq!(globals.get::<_, String>("foo").unwrap(), "bar");
|
|
|
|
assert_eq!(globals.get::<_, String>("baz").unwrap(), "baf");
|
2017-05-21 19:50:59 -04:00
|
|
|
}
|
|
|
|
|
2017-06-21 20:38:58 -04:00
|
|
|
#[test]
|
|
|
|
fn test_load() {
|
|
|
|
let lua = Lua::new();
|
|
|
|
let func = lua.load("return 1+2", None).unwrap();
|
|
|
|
let result: i32 = func.call(()).unwrap();
|
|
|
|
assert_eq!(result, 3);
|
|
|
|
|
|
|
|
assert!(lua.load("§$%§&$%&", None).is_err());
|
|
|
|
}
|
|
|
|
|
2017-05-21 19:50:59 -04:00
|
|
|
#[test]
|
2017-06-21 18:13:49 -04:00
|
|
|
fn test_exec() {
|
2017-05-21 19:50:59 -04:00
|
|
|
let lua = Lua::new();
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
let globals = lua.globals();
|
2017-06-18 08:31:38 -04:00
|
|
|
lua.exec::<()>(
|
2017-06-05 00:03:39 -04:00
|
|
|
r#"
|
2017-05-21 19:50:59 -04:00
|
|
|
res = 'foo'..'bar'
|
|
|
|
"#,
|
2017-06-05 00:03:39 -04:00
|
|
|
None,
|
2017-06-11 01:12:25 -04:00
|
|
|
).unwrap();
|
|
|
|
assert_eq!(globals.get::<_, String>("res").unwrap(), "foobar");
|
|
|
|
|
2017-07-18 16:21:12 -04:00
|
|
|
let module: Table = lua.exec(
|
2017-06-11 01:12:25 -04:00
|
|
|
r#"
|
|
|
|
local module = {}
|
|
|
|
|
|
|
|
function module.func()
|
|
|
|
return "hello"
|
|
|
|
end
|
|
|
|
|
|
|
|
return module
|
|
|
|
"#,
|
|
|
|
None,
|
|
|
|
).unwrap();
|
2017-06-18 08:39:18 -04:00
|
|
|
assert!(module.contains_key("func").unwrap());
|
2017-06-15 10:26:39 -04:00
|
|
|
assert_eq!(
|
|
|
|
module
|
2017-07-18 16:21:12 -04:00
|
|
|
.get::<_, Function>("func")
|
2017-06-15 10:26:39 -04:00
|
|
|
.unwrap()
|
|
|
|
.call::<_, String>(())
|
|
|
|
.unwrap(),
|
|
|
|
"hello"
|
|
|
|
);
|
2017-05-21 19:50:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_eval() {
|
|
|
|
let lua = Lua::new();
|
2017-07-16 16:53:32 -04:00
|
|
|
assert_eq!(lua.eval::<i32>("1 + 1", None).unwrap(), 2);
|
|
|
|
assert_eq!(lua.eval::<bool>("false == false", None).unwrap(), true);
|
|
|
|
assert_eq!(lua.eval::<i32>("return 1 + 2", None).unwrap(), 3);
|
|
|
|
match lua.eval::<()>("if true then", None) {
|
2017-07-18 16:21:12 -04:00
|
|
|
Err(Error::IncompleteStatement(_)) => {}
|
2017-05-21 19:50:59 -04:00
|
|
|
r => panic!("expected IncompleteStatement, got {:?}", r),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_table() {
|
|
|
|
let lua = Lua::new();
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
let globals = lua.globals();
|
2017-05-21 19:50:59 -04:00
|
|
|
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
globals.set("table", lua.create_table()).unwrap();
|
2017-07-18 16:21:12 -04:00
|
|
|
let table1: Table = globals.get("table").unwrap();
|
|
|
|
let table2: Table = globals.get("table").unwrap();
|
2017-05-21 19:50:59 -04:00
|
|
|
|
|
|
|
table1.set("foo", "bar").unwrap();
|
|
|
|
table2.set("baz", "baf").unwrap();
|
|
|
|
|
|
|
|
assert_eq!(table2.get::<_, String>("foo").unwrap(), "bar");
|
|
|
|
assert_eq!(table1.get::<_, String>("baz").unwrap(), "baf");
|
|
|
|
|
2017-06-18 08:31:38 -04:00
|
|
|
lua.exec::<()>(
|
2017-06-05 00:03:39 -04:00
|
|
|
r#"
|
2017-05-21 19:50:59 -04:00
|
|
|
table1 = {1, 2, 3, 4, 5}
|
|
|
|
table2 = {}
|
|
|
|
table3 = {1, 2, nil, 4, 5}
|
|
|
|
"#,
|
2017-06-05 00:03:39 -04:00
|
|
|
None,
|
2017-06-11 01:12:25 -04:00
|
|
|
).unwrap();
|
2017-05-21 19:50:59 -04:00
|
|
|
|
2017-07-18 16:21:12 -04:00
|
|
|
let table1 = globals.get::<_, Table>("table1").unwrap();
|
|
|
|
let table2 = globals.get::<_, Table>("table2").unwrap();
|
|
|
|
let table3 = globals.get::<_, Table>("table3").unwrap();
|
2017-05-21 19:50:59 -04:00
|
|
|
|
2017-06-18 08:36:30 -04:00
|
|
|
assert_eq!(table1.len().unwrap(), 5);
|
2017-06-15 10:26:39 -04:00
|
|
|
assert_eq!(
|
2017-06-19 02:57:03 -04:00
|
|
|
table1
|
|
|
|
.clone()
|
|
|
|
.pairs()
|
2017-07-18 16:21:12 -04:00
|
|
|
.collect::<Result<Vec<(i64, i64)>>>()
|
2017-06-19 02:57:03 -04:00
|
|
|
.unwrap(),
|
2017-06-15 10:26:39 -04:00
|
|
|
vec![(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
|
|
|
|
);
|
2017-06-19 02:57:03 -04:00
|
|
|
assert_eq!(
|
|
|
|
table1
|
|
|
|
.clone()
|
2017-06-20 19:04:25 -04:00
|
|
|
.sequence_values()
|
2017-07-18 16:21:12 -04:00
|
|
|
.collect::<Result<Vec<i64>>>()
|
2017-06-19 02:57:03 -04:00
|
|
|
.unwrap(),
|
|
|
|
vec![1, 2, 3, 4, 5]
|
|
|
|
);
|
|
|
|
|
2017-06-18 08:36:30 -04:00
|
|
|
assert_eq!(table2.len().unwrap(), 0);
|
2017-06-15 10:26:39 -04:00
|
|
|
assert_eq!(
|
2017-06-19 02:57:03 -04:00
|
|
|
table2
|
|
|
|
.clone()
|
|
|
|
.pairs()
|
2017-07-18 16:21:12 -04:00
|
|
|
.collect::<Result<Vec<(i64, i64)>>>()
|
2017-06-19 02:57:03 -04:00
|
|
|
.unwrap(),
|
|
|
|
vec![]
|
|
|
|
);
|
|
|
|
assert_eq!(
|
2017-06-20 19:04:25 -04:00
|
|
|
table2
|
|
|
|
.sequence_values()
|
2017-07-18 16:21:12 -04:00
|
|
|
.collect::<Result<Vec<i64>>>()
|
2017-06-20 19:04:25 -04:00
|
|
|
.unwrap(),
|
2017-06-19 02:57:03 -04:00
|
|
|
vec![]
|
|
|
|
);
|
|
|
|
|
2017-06-20 19:04:25 -04:00
|
|
|
// sequence_values should only iterate until the first border
|
2017-06-19 02:57:03 -04:00
|
|
|
assert_eq!(
|
2017-06-20 19:04:25 -04:00
|
|
|
table3
|
|
|
|
.sequence_values()
|
2017-07-18 16:21:12 -04:00
|
|
|
.collect::<Result<Vec<i64>>>()
|
2017-06-20 19:04:25 -04:00
|
|
|
.unwrap(),
|
2017-06-19 02:57:03 -04:00
|
|
|
vec![1, 2]
|
2017-06-15 10:26:39 -04:00
|
|
|
);
|
2017-06-05 01:46:45 -04:00
|
|
|
|
2017-06-11 01:12:25 -04:00
|
|
|
globals
|
2017-06-15 10:26:39 -04:00
|
|
|
.set(
|
|
|
|
"table4",
|
2017-06-20 19:04:25 -04:00
|
|
|
lua.create_sequence_from(vec![1, 2, 3, 4, 5]).unwrap(),
|
2017-06-15 10:26:39 -04:00
|
|
|
)
|
2017-06-05 01:46:45 -04:00
|
|
|
.unwrap();
|
2017-07-18 16:21:12 -04:00
|
|
|
let table4 = globals.get::<_, Table>("table4").unwrap();
|
2017-06-15 10:26:39 -04:00
|
|
|
assert_eq!(
|
2017-07-24 10:40:00 -04:00
|
|
|
table4.pairs().collect::<Result<Vec<(i64, i64)>>>().unwrap(),
|
2017-06-15 10:26:39 -04:00
|
|
|
vec![(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
|
|
|
|
);
|
2017-05-21 19:50:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_function() {
|
|
|
|
let lua = Lua::new();
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
let globals = lua.globals();
|
2017-06-18 08:31:38 -04:00
|
|
|
lua.exec::<()>(
|
2017-06-05 00:03:39 -04:00
|
|
|
r#"
|
2017-05-21 19:50:59 -04:00
|
|
|
function concat(arg1, arg2)
|
|
|
|
return arg1 .. arg2
|
|
|
|
end
|
|
|
|
"#,
|
2017-06-05 00:03:39 -04:00
|
|
|
None,
|
2017-06-11 01:12:25 -04:00
|
|
|
).unwrap();
|
2017-05-21 19:50:59 -04:00
|
|
|
|
2017-07-18 16:21:12 -04:00
|
|
|
let concat = globals.get::<_, Function>("concat").unwrap();
|
2017-07-31 01:21:41 -04:00
|
|
|
assert_eq!(concat.call::<_, String>(("foo", "bar")).unwrap(), "foobar");
|
2017-05-21 19:50:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_bind() {
|
|
|
|
let lua = Lua::new();
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
let globals = lua.globals();
|
2017-06-18 08:31:38 -04:00
|
|
|
lua.exec::<()>(
|
2017-06-05 00:03:39 -04:00
|
|
|
r#"
|
2017-05-21 19:50:59 -04:00
|
|
|
function concat(...)
|
|
|
|
local res = ""
|
|
|
|
for _, s in pairs({...}) do
|
|
|
|
res = res..s
|
|
|
|
end
|
|
|
|
return res
|
|
|
|
end
|
|
|
|
"#,
|
2017-06-05 00:03:39 -04:00
|
|
|
None,
|
2017-06-11 01:12:25 -04:00
|
|
|
).unwrap();
|
2017-05-21 19:50:59 -04:00
|
|
|
|
2017-07-18 16:21:12 -04:00
|
|
|
let mut concat = globals.get::<_, Function>("concat").unwrap();
|
2017-05-21 19:50:59 -04:00
|
|
|
concat = concat.bind("foo").unwrap();
|
|
|
|
concat = concat.bind("bar").unwrap();
|
2017-07-31 01:21:41 -04:00
|
|
|
concat = concat.bind(("baz", "baf")).unwrap();
|
2017-06-15 10:26:39 -04:00
|
|
|
assert_eq!(
|
2017-07-31 01:21:41 -04:00
|
|
|
concat.call::<_, String>(("hi", "wut")).unwrap(),
|
2017-06-15 10:26:39 -04:00
|
|
|
"foobarbazbafhiwut"
|
|
|
|
);
|
2017-05-21 19:50:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_rust_function() {
|
2017-08-01 12:03:05 -04:00
|
|
|
let lua = Lua::new();
|
|
|
|
let globals = lua.globals();
|
|
|
|
lua.exec::<()>(
|
|
|
|
r#"
|
|
|
|
function lua_function()
|
|
|
|
return rust_function()
|
|
|
|
end
|
2017-05-21 19:50:59 -04:00
|
|
|
|
2017-08-01 12:03:05 -04:00
|
|
|
-- Test to make sure chunk return is ignored
|
|
|
|
return 1
|
|
|
|
"#,
|
|
|
|
None,
|
|
|
|
).unwrap();
|
2017-05-21 19:50:59 -04:00
|
|
|
|
2017-08-01 12:03:05 -04:00
|
|
|
let lua_function = globals.get::<_, Function>("lua_function").unwrap();
|
2017-08-01 14:09:47 -04:00
|
|
|
let rust_function = lua.create_function(|_, ()| Ok("hello"));
|
2017-05-21 19:50:59 -04:00
|
|
|
|
2017-08-01 12:03:05 -04:00
|
|
|
globals.set("rust_function", rust_function).unwrap();
|
|
|
|
assert_eq!(lua_function.call::<_, String>(()).unwrap(), "hello");
|
2017-05-21 19:50:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_user_data() {
|
|
|
|
struct UserData1(i64);
|
|
|
|
struct UserData2(Box<i64>);
|
|
|
|
|
2017-07-18 16:21:12 -04:00
|
|
|
impl UserData for UserData1 {};
|
|
|
|
impl UserData for UserData2 {};
|
2017-05-21 19:50:59 -04:00
|
|
|
|
|
|
|
let lua = Lua::new();
|
|
|
|
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
let userdata1 = lua.create_userdata(UserData1(1));
|
|
|
|
let userdata2 = lua.create_userdata(UserData2(Box::new(2)));
|
2017-05-21 19:50:59 -04:00
|
|
|
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
assert!(userdata1.is::<UserData1>());
|
|
|
|
assert!(!userdata1.is::<UserData2>());
|
|
|
|
assert!(userdata2.is::<UserData2>());
|
|
|
|
assert!(!userdata2.is::<UserData1>());
|
2017-05-21 19:50:59 -04:00
|
|
|
|
|
|
|
assert_eq!(userdata1.borrow::<UserData1>().unwrap().0, 1);
|
|
|
|
assert_eq!(*userdata2.borrow::<UserData2>().unwrap().0, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_methods() {
|
2017-07-18 16:21:12 -04:00
|
|
|
struct MyUserData(i64);
|
2017-05-21 19:50:59 -04:00
|
|
|
|
2017-07-18 16:21:12 -04:00
|
|
|
impl UserData for MyUserData {
|
|
|
|
fn add_methods(methods: &mut UserDataMethods<Self>) {
|
2017-08-01 14:09:47 -04:00
|
|
|
methods.add_method("get_value", |_, data, ()| Ok(data.0));
|
2017-07-31 01:21:41 -04:00
|
|
|
methods.add_method_mut("set_value", |_, data, args| {
|
|
|
|
data.0 = args;
|
|
|
|
Ok(())
|
2017-05-21 19:50:59 -04:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let lua = Lua::new();
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
let globals = lua.globals();
|
2017-07-18 16:21:12 -04:00
|
|
|
let userdata = lua.create_userdata(MyUserData(42));
|
2017-06-11 01:12:25 -04:00
|
|
|
globals.set("userdata", userdata.clone()).unwrap();
|
2017-06-18 08:31:38 -04:00
|
|
|
lua.exec::<()>(
|
2017-06-05 00:03:39 -04:00
|
|
|
r#"
|
2017-05-21 19:50:59 -04:00
|
|
|
function get_it()
|
|
|
|
return userdata:get_value()
|
|
|
|
end
|
|
|
|
|
|
|
|
function set_it(i)
|
|
|
|
return userdata:set_value(i)
|
|
|
|
end
|
|
|
|
"#,
|
2017-06-05 00:03:39 -04:00
|
|
|
None,
|
2017-06-11 01:12:25 -04:00
|
|
|
).unwrap();
|
2017-07-18 16:21:12 -04:00
|
|
|
let get = globals.get::<_, Function>("get_it").unwrap();
|
|
|
|
let set = globals.get::<_, Function>("set_it").unwrap();
|
2017-05-21 19:50:59 -04:00
|
|
|
assert_eq!(get.call::<_, i64>(()).unwrap(), 42);
|
2017-07-18 16:21:12 -04:00
|
|
|
userdata.borrow_mut::<MyUserData>().unwrap().0 = 64;
|
2017-05-21 19:50:59 -04:00
|
|
|
assert_eq!(get.call::<_, i64>(()).unwrap(), 64);
|
|
|
|
set.call::<_, ()>(100).unwrap();
|
|
|
|
assert_eq!(get.call::<_, i64>(()).unwrap(), 100);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_metamethods() {
|
|
|
|
#[derive(Copy, Clone)]
|
2017-07-18 16:21:12 -04:00
|
|
|
struct MyUserData(i64);
|
2017-05-21 19:50:59 -04:00
|
|
|
|
2017-07-18 16:21:12 -04:00
|
|
|
impl UserData for MyUserData {
|
|
|
|
fn add_methods(methods: &mut UserDataMethods<Self>) {
|
2017-08-01 14:09:47 -04:00
|
|
|
methods.add_method("get", |_, data, ()| Ok(data.0));
|
2017-07-31 01:21:41 -04:00
|
|
|
methods.add_meta_function(MetaMethod::Add, |_, (lhs, rhs): (MyUserData, MyUserData)| {
|
|
|
|
Ok(MyUserData(lhs.0 + rhs.0))
|
2017-05-21 19:50:59 -04:00
|
|
|
});
|
2017-07-31 01:21:41 -04:00
|
|
|
methods.add_meta_function(MetaMethod::Sub, |_, (lhs, rhs): (MyUserData, MyUserData)| {
|
|
|
|
Ok(MyUserData(lhs.0 - rhs.0))
|
2017-05-21 19:50:59 -04:00
|
|
|
});
|
2017-08-01 13:55:08 -04:00
|
|
|
methods.add_meta_method(
|
|
|
|
MetaMethod::Index,
|
|
|
|
|_, data, index: LuaString| if index.to_str()? == "inner" {
|
2017-07-31 01:21:41 -04:00
|
|
|
Ok(data.0)
|
2017-05-21 19:50:59 -04:00
|
|
|
} else {
|
Big API incompatible error change, remove dependency on error_chain
The current situation with error_chain is less than ideal, and there are lots of
conflicting interests that are impossible to meet at once. Here is an
unorganized brain dump of the current situation, stay awhile and listen!
This change was triggered ultimately by the desire to make LuaError implement
Clone, and this is currently impossible with error_chain. LuaError must
implement Clone to be a proper lua citizen that can live as userdata within a
lua runtime, because there is no way to limit what the lua runtime can do with a
received error. Currently, this is solved by there being a rule that the error
will "expire" if the error is passed back into rust, and this is very
sub-optimal. In fact, one could easily imagine a scenario where lua is for
example memoizing some function, and if the function has ever errored in the
past the function should continue returning the same error, and this situation
immediately fails with this restriciton in place.
Additionally, there are other more minor problems with error_chain which make
the API less good than it could be, or limit how we can use error_chain. This
change has already solved a small bug in a Chucklefish project, where the
conversion from an external error type (Borrow[Mut]Error) was allowed but not
intended for user code, and was accidentally used. Additionally, pattern
matching on error_chain errors, which should be common when dealing with Lua, is
less convenient than a hand rolled error type.
So, if we decide not to use error_chain, we now have a new set of problems if we
decide interoperability with error_chain is important. The first problem we run
into is that there are two natural bounds for wrapped errors that we would
pick, (Error + Send + Sync), or just Error, and neither of them will
interoperate well with error_chain. (Error + Send + Sync) means we can't wrap
error chain errors into LuaError::ExternalError (they're missing the Sync
bound), and having the bounds be just Error means the opposite, that we can't
hold a LuaError inside an error_chain error.
We could just decide that interoperability with error_chain is the most
important qualification, and pick (Error + Send), but this causes a DIFFERENT
set of problems. The rust ecosystem has the two primary error bounds as Error
or (Error + Send + Sync), and there are Into impls from &str / String to
Box<Error + Send + Sync> for example, but NOT (Error + Send). This means that
we are forced to manually recreate the conversions from &str / String to
LuaError rather than relying on a single Into<Box<Error + Send + Sync>> bound,
but this means that string conversions have a different set of methods than
other error types for external error conversion. I have not been able to figure
out an API that I am happy with that uses the (Error + Send) bound. Box<Error>
is obnoxious because not having errors implement Send causes needless problems
in a multithreaded context, so that leaves (Error + Send + Sync). This is
actually a completely reasonable bound for external errors, and has the nice
String Into impls that we would want, the ONLY problem is that it is a pain to
interoperate with the current version of error_chain.
It would be nice to be able to specify the traits that an error generated by the
error_chain macro would implement, and this is apparently in progress in the
error_chain library. This would solve both the problem with not being able to
implement Clone and the problems with (Error + Send) bounds. I am not convinced
that this library should go back to using error_chain when that functionality is
in stable error_chain though, because of the other minor usability problems with
using error_chain.
In that theoretical situation, the downside of NOT using error_chain is simply
that there would not be automatic stacktraces of LuaError. This is not a huge
problem, because stack traces of lua errors are not extremely useful, and for
external errors it is not too hard to create a different version of the
LuaExternalResult / LuaExternalError traits and do conversion from an
error_chain type into a type that will print the stacktrace on display, or
use downcasting in the error causes.
So in summary, this library is no longer using error_chain, and probably will
not use it again in the future. Currently this means that to interoperate with
error_chain, you should use error_chain 0.8.1, which derives Sync on errors, or
wait for a version that supports user defined trait derives. In the future
when error_chain supports user defined trait derives, users may have to take an
extra step to make wrapped external errors print the stacktrace that they
capture.
This change works, but is not entirely complete. There is no error
documentation yet, and the change brought to a head an ugly module organization
problem. There will be more commits for documentation and reorganization, then
a new stable version of rlua.
2017-06-24 18:11:56 -04:00
|
|
|
Err("no such custom index".to_lua_err())
|
2017-08-01 13:55:08 -04:00
|
|
|
},
|
|
|
|
);
|
2017-05-21 19:50:59 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let lua = Lua::new();
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
let globals = lua.globals();
|
2017-07-18 16:21:12 -04:00
|
|
|
globals.set("userdata1", MyUserData(7)).unwrap();
|
|
|
|
globals.set("userdata2", MyUserData(3)).unwrap();
|
2017-07-19 20:10:11 -04:00
|
|
|
assert_eq!(
|
2017-07-18 16:21:12 -04:00
|
|
|
lua.eval::<MyUserData>("userdata1 + userdata2", None)
|
2017-07-19 20:10:11 -04:00
|
|
|
.unwrap()
|
|
|
|
.0,
|
|
|
|
10
|
|
|
|
);
|
|
|
|
assert_eq!(
|
2017-07-18 16:21:12 -04:00
|
|
|
lua.eval::<MyUserData>("userdata1 - userdata2", None)
|
2017-07-19 20:10:11 -04:00
|
|
|
.unwrap()
|
|
|
|
.0,
|
|
|
|
4
|
|
|
|
);
|
2017-07-16 16:53:32 -04:00
|
|
|
assert_eq!(lua.eval::<i64>("userdata1:get()", None).unwrap(), 7);
|
|
|
|
assert_eq!(lua.eval::<i64>("userdata2.inner", None).unwrap(), 3);
|
|
|
|
assert!(lua.eval::<()>("userdata2.nonexist_field", None).is_err());
|
2017-05-21 19:50:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_scope() {
|
|
|
|
let lua = Lua::new();
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
let globals = lua.globals();
|
2017-06-18 08:31:38 -04:00
|
|
|
lua.exec::<()>(
|
2017-06-05 00:03:39 -04:00
|
|
|
r#"
|
2017-05-21 19:50:59 -04:00
|
|
|
touter = {
|
|
|
|
tin = {1, 2, 3}
|
|
|
|
}
|
|
|
|
"#,
|
2017-06-05 00:03:39 -04:00
|
|
|
None,
|
2017-06-11 01:12:25 -04:00
|
|
|
).unwrap();
|
2017-05-21 19:50:59 -04:00
|
|
|
|
|
|
|
// Make sure that table gets do not borrow the table, but instead just borrow lua.
|
|
|
|
let tin;
|
|
|
|
{
|
2017-07-18 16:21:12 -04:00
|
|
|
let touter = globals.get::<_, Table>("touter").unwrap();
|
|
|
|
tin = touter.get::<_, Table>("tin").unwrap();
|
2017-05-21 19:50:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
assert_eq!(tin.get::<_, i64>(1).unwrap(), 1);
|
|
|
|
assert_eq!(tin.get::<_, i64>(2).unwrap(), 2);
|
|
|
|
assert_eq!(tin.get::<_, i64>(3).unwrap(), 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_lua_multi() {
|
|
|
|
let lua = Lua::new();
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
let globals = lua.globals();
|
2017-06-18 08:31:38 -04:00
|
|
|
lua.exec::<()>(
|
2017-06-05 00:03:39 -04:00
|
|
|
r#"
|
2017-05-21 19:50:59 -04:00
|
|
|
function concat(arg1, arg2)
|
|
|
|
return arg1 .. arg2
|
|
|
|
end
|
|
|
|
|
|
|
|
function mreturn()
|
|
|
|
return 1, 2, 3, 4, 5, 6
|
|
|
|
end
|
|
|
|
"#,
|
2017-06-05 00:03:39 -04:00
|
|
|
None,
|
2017-06-11 01:12:25 -04:00
|
|
|
).unwrap();
|
2017-05-21 19:50:59 -04:00
|
|
|
|
2017-07-18 16:21:12 -04:00
|
|
|
let concat = globals.get::<_, Function>("concat").unwrap();
|
|
|
|
let mreturn = globals.get::<_, Function>("mreturn").unwrap();
|
2017-05-21 19:50:59 -04:00
|
|
|
|
2017-07-31 01:21:41 -04:00
|
|
|
assert_eq!(concat.call::<_, String>(("foo", "bar")).unwrap(), "foobar");
|
|
|
|
let (a, b) = mreturn.call::<_, (u64, u64)>(()).unwrap();
|
2017-05-21 19:50:59 -04:00
|
|
|
assert_eq!((a, b), (1, 2));
|
2017-08-01 13:55:08 -04:00
|
|
|
let (a, b, v) = mreturn.call::<_, (u64, u64, Variadic<u64>)>(()).unwrap();
|
2017-05-21 19:50:59 -04:00
|
|
|
assert_eq!((a, b), (1, 2));
|
2017-08-01 13:55:08 -04:00
|
|
|
assert_eq!(v[..], [3, 4, 5, 6]);
|
2017-05-21 19:50:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_coercion() {
|
|
|
|
let lua = Lua::new();
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
let globals = lua.globals();
|
2017-06-18 08:31:38 -04:00
|
|
|
lua.exec::<()>(
|
2017-06-05 00:03:39 -04:00
|
|
|
r#"
|
2017-05-21 19:50:59 -04:00
|
|
|
int = 123
|
|
|
|
str = "123"
|
|
|
|
num = 123.0
|
|
|
|
"#,
|
2017-06-05 00:03:39 -04:00
|
|
|
None,
|
2017-06-11 01:12:25 -04:00
|
|
|
).unwrap();
|
2017-05-21 19:50:59 -04:00
|
|
|
|
2017-06-11 01:12:25 -04:00
|
|
|
assert_eq!(globals.get::<_, String>("int").unwrap(), "123");
|
|
|
|
assert_eq!(globals.get::<_, i32>("str").unwrap(), 123);
|
|
|
|
assert_eq!(globals.get::<_, i32>("num").unwrap(), 123);
|
2017-05-21 19:50:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_error() {
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct TestError;
|
|
|
|
|
|
|
|
impl fmt::Display for TestError {
|
2017-07-18 16:21:12 -04:00
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
2017-05-21 19:50:59 -04:00
|
|
|
write!(fmt, "test error")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-18 16:21:12 -04:00
|
|
|
impl error::Error for TestError {
|
2017-05-21 19:50:59 -04:00
|
|
|
fn description(&self) -> &str {
|
|
|
|
"test error"
|
|
|
|
}
|
|
|
|
|
2017-07-18 16:21:12 -04:00
|
|
|
fn cause(&self) -> Option<&error::Error> {
|
2017-05-21 19:50:59 -04:00
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let lua = Lua::new();
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
let globals = lua.globals();
|
2017-06-18 08:31:38 -04:00
|
|
|
lua.exec::<()>(
|
2017-06-05 00:03:39 -04:00
|
|
|
r#"
|
2017-05-21 19:50:59 -04:00
|
|
|
function no_error()
|
|
|
|
end
|
|
|
|
|
|
|
|
function lua_error()
|
|
|
|
error("this is a lua error")
|
|
|
|
end
|
|
|
|
|
|
|
|
function rust_error()
|
|
|
|
rust_error_function()
|
|
|
|
end
|
|
|
|
|
2017-06-25 02:40:09 -04:00
|
|
|
function return_error()
|
|
|
|
local status, res = pcall(rust_error_function)
|
|
|
|
assert(not status)
|
|
|
|
return res
|
|
|
|
end
|
|
|
|
|
|
|
|
function return_string_error()
|
|
|
|
return "this should be converted to an error"
|
|
|
|
end
|
|
|
|
|
2017-05-21 19:50:59 -04:00
|
|
|
function test_pcall()
|
|
|
|
local testvar = 0
|
|
|
|
|
|
|
|
pcall(function(arg)
|
|
|
|
testvar = testvar + arg
|
|
|
|
error("should be ignored")
|
|
|
|
end, 3)
|
|
|
|
|
|
|
|
local function handler(err)
|
|
|
|
testvar = testvar + err
|
|
|
|
return "should be ignored"
|
|
|
|
end
|
|
|
|
|
2017-06-25 02:40:09 -04:00
|
|
|
local status, res = xpcall(function()
|
2017-05-21 19:50:59 -04:00
|
|
|
error(5)
|
|
|
|
end, handler)
|
2017-06-25 02:40:09 -04:00
|
|
|
assert(not status)
|
2017-05-21 19:50:59 -04:00
|
|
|
|
|
|
|
if testvar ~= 8 then
|
|
|
|
error("testvar had the wrong value, pcall / xpcall misbehaving "..testvar)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function understand_recursion()
|
|
|
|
understand_recursion()
|
|
|
|
end
|
|
|
|
"#,
|
2017-06-05 00:03:39 -04:00
|
|
|
None,
|
2017-06-11 01:12:25 -04:00
|
|
|
).unwrap();
|
2017-05-21 19:50:59 -04:00
|
|
|
|
2017-07-31 01:21:41 -04:00
|
|
|
let rust_error_function =
|
2017-08-01 14:09:47 -04:00
|
|
|
lua.create_function(|_, ()| -> Result<()> { Err(TestError.to_lua_err()) });
|
2017-06-11 01:12:25 -04:00
|
|
|
globals
|
|
|
|
.set("rust_error_function", rust_error_function)
|
|
|
|
.unwrap();
|
2017-05-21 19:50:59 -04:00
|
|
|
|
2017-07-18 16:21:12 -04:00
|
|
|
let no_error = globals.get::<_, Function>("no_error").unwrap();
|
|
|
|
let lua_error = globals.get::<_, Function>("lua_error").unwrap();
|
|
|
|
let rust_error = globals.get::<_, Function>("rust_error").unwrap();
|
|
|
|
let return_error = globals.get::<_, Function>("return_error").unwrap();
|
2017-07-24 10:40:00 -04:00
|
|
|
let return_string_error = globals.get::<_, Function>("return_string_error").unwrap();
|
2017-07-18 16:21:12 -04:00
|
|
|
let test_pcall = globals.get::<_, Function>("test_pcall").unwrap();
|
2017-07-24 10:40:00 -04:00
|
|
|
let understand_recursion = globals.get::<_, Function>("understand_recursion").unwrap();
|
2017-05-21 19:50:59 -04:00
|
|
|
|
|
|
|
assert!(no_error.call::<_, ()>(()).is_ok());
|
|
|
|
match lua_error.call::<_, ()>(()) {
|
2017-07-18 16:21:12 -04:00
|
|
|
Err(Error::RuntimeError(_)) => {}
|
2017-06-24 20:57:04 -04:00
|
|
|
Err(_) => panic!("error is not RuntimeError kind"),
|
2017-06-17 23:50:40 -04:00
|
|
|
_ => panic!("error not returned"),
|
2017-05-21 19:50:59 -04:00
|
|
|
}
|
|
|
|
match rust_error.call::<_, ()>(()) {
|
2017-07-18 16:21:12 -04:00
|
|
|
Err(Error::CallbackError(_, _)) => {}
|
2017-05-22 14:24:19 -04:00
|
|
|
Err(_) => panic!("error is not CallbackError kind"),
|
2017-06-17 23:50:40 -04:00
|
|
|
_ => panic!("error not returned"),
|
2017-05-21 19:50:59 -04:00
|
|
|
}
|
2017-06-25 02:40:09 -04:00
|
|
|
|
2017-07-18 16:21:12 -04:00
|
|
|
match return_error.call::<_, Value>(()) {
|
|
|
|
Ok(Value::Error(_)) => {}
|
|
|
|
_ => panic!("Value::Error not returned"),
|
2017-06-25 02:40:09 -04:00
|
|
|
}
|
|
|
|
|
2017-07-18 16:21:12 -04:00
|
|
|
assert!(return_string_error.call::<_, Error>(()).is_ok());
|
2017-06-25 02:40:09 -04:00
|
|
|
|
2017-07-16 16:53:32 -04:00
|
|
|
match lua.eval::<()>("if youre happy and you know it syntax error", None) {
|
2017-07-18 16:21:12 -04:00
|
|
|
Err(Error::SyntaxError(_)) => {}
|
2017-06-24 20:57:04 -04:00
|
|
|
Err(_) => panic!("error is not LuaSyntaxError::Syntax kind"),
|
|
|
|
_ => panic!("error not returned"),
|
|
|
|
}
|
2017-07-16 16:53:32 -04:00
|
|
|
match lua.eval::<()>("function i_will_finish_what_i()", None) {
|
2017-07-18 16:21:12 -04:00
|
|
|
Err(Error::IncompleteStatement(_)) => {}
|
2017-06-24 20:57:04 -04:00
|
|
|
Err(_) => panic!("error is not LuaSyntaxError::IncompleteStatement kind"),
|
|
|
|
_ => panic!("error not returned"),
|
|
|
|
}
|
2017-05-21 19:50:59 -04:00
|
|
|
|
|
|
|
test_pcall.call::<_, ()>(()).unwrap();
|
|
|
|
|
|
|
|
assert!(understand_recursion.call::<_, ()>(()).is_err());
|
|
|
|
|
2017-07-18 16:21:12 -04:00
|
|
|
match catch_unwind(|| -> Result<()> {
|
2017-05-21 19:50:59 -04:00
|
|
|
let lua = Lua::new();
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
let globals = lua.globals();
|
|
|
|
|
2017-06-18 08:31:38 -04:00
|
|
|
lua.exec::<()>(
|
2017-06-05 00:03:39 -04:00
|
|
|
r#"
|
2017-05-21 19:50:59 -04:00
|
|
|
function rust_panic()
|
|
|
|
pcall(function () rust_panic_function() end)
|
|
|
|
end
|
|
|
|
"#,
|
2017-06-05 00:03:39 -04:00
|
|
|
None,
|
|
|
|
)?;
|
2017-08-01 14:09:47 -04:00
|
|
|
let rust_panic_function = lua.create_function(|_, ()| -> Result<()> {
|
2017-05-21 19:50:59 -04:00
|
|
|
panic!("expected panic, this panic should be caught in rust")
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
});
|
2017-06-11 01:12:25 -04:00
|
|
|
globals.set("rust_panic_function", rust_panic_function)?;
|
2017-05-21 19:50:59 -04:00
|
|
|
|
2017-07-18 16:21:12 -04:00
|
|
|
let rust_panic = globals.get::<_, Function>("rust_panic")?;
|
2017-05-21 19:50:59 -04:00
|
|
|
|
|
|
|
rust_panic.call::<_, ()>(())
|
|
|
|
}) {
|
|
|
|
Ok(Ok(_)) => panic!("no panic was detected, pcall caught it!"),
|
|
|
|
Ok(Err(e)) => panic!("error during panic test {:?}", e),
|
|
|
|
Err(_) => {}
|
|
|
|
};
|
|
|
|
|
2017-07-18 16:21:12 -04:00
|
|
|
match catch_unwind(|| -> Result<()> {
|
2017-05-21 19:50:59 -04:00
|
|
|
let lua = Lua::new();
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
let globals = lua.globals();
|
|
|
|
|
2017-06-18 08:31:38 -04:00
|
|
|
lua.exec::<()>(
|
2017-06-05 00:03:39 -04:00
|
|
|
r#"
|
2017-05-21 19:50:59 -04:00
|
|
|
function rust_panic()
|
|
|
|
xpcall(function() rust_panic_function() end, function() end)
|
|
|
|
end
|
|
|
|
"#,
|
2017-06-05 00:03:39 -04:00
|
|
|
None,
|
|
|
|
)?;
|
2017-08-01 14:09:47 -04:00
|
|
|
let rust_panic_function = lua.create_function(|_, ()| -> Result<()> {
|
2017-05-21 19:50:59 -04:00
|
|
|
panic!("expected panic, this panic should be caught in rust")
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
});
|
2017-06-11 01:12:25 -04:00
|
|
|
globals.set("rust_panic_function", rust_panic_function)?;
|
2017-05-21 19:50:59 -04:00
|
|
|
|
2017-07-18 16:21:12 -04:00
|
|
|
let rust_panic = globals.get::<_, Function>("rust_panic")?;
|
2017-05-21 19:50:59 -04:00
|
|
|
|
|
|
|
rust_panic.call::<_, ()>(())
|
|
|
|
}) {
|
|
|
|
Ok(Ok(_)) => panic!("no panic was detected, xpcall caught it!"),
|
|
|
|
Ok(Err(e)) => panic!("error during panic test {:?}", e),
|
|
|
|
Err(_) => {}
|
|
|
|
};
|
|
|
|
}
|
2017-05-24 23:13:58 -04:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_thread() {
|
|
|
|
let lua = Lua::new();
|
2017-06-11 01:12:25 -04:00
|
|
|
let thread = lua.create_thread(
|
2017-07-18 16:21:12 -04:00
|
|
|
lua.eval::<Function>(
|
2017-06-17 22:40:09 -04:00
|
|
|
r#"
|
|
|
|
function (s)
|
|
|
|
local sum = s
|
|
|
|
for i = 1,4 do
|
|
|
|
sum = sum + coroutine.yield(sum)
|
|
|
|
end
|
|
|
|
return sum
|
|
|
|
end
|
|
|
|
"#,
|
2017-07-19 20:10:11 -04:00
|
|
|
None,
|
2017-06-11 01:12:25 -04:00
|
|
|
).unwrap(),
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
);
|
2017-05-24 23:13:58 -04:00
|
|
|
|
2017-07-18 16:21:12 -04:00
|
|
|
assert_eq!(thread.status(), ThreadStatus::Active);
|
2017-06-17 23:50:40 -04:00
|
|
|
assert_eq!(thread.resume::<_, i64>(0).unwrap(), 0);
|
2017-07-18 16:21:12 -04:00
|
|
|
assert_eq!(thread.status(), ThreadStatus::Active);
|
2017-06-17 23:50:40 -04:00
|
|
|
assert_eq!(thread.resume::<_, i64>(1).unwrap(), 1);
|
2017-07-18 16:21:12 -04:00
|
|
|
assert_eq!(thread.status(), ThreadStatus::Active);
|
2017-06-17 23:50:40 -04:00
|
|
|
assert_eq!(thread.resume::<_, i64>(2).unwrap(), 3);
|
2017-07-18 16:21:12 -04:00
|
|
|
assert_eq!(thread.status(), ThreadStatus::Active);
|
2017-06-17 23:50:40 -04:00
|
|
|
assert_eq!(thread.resume::<_, i64>(3).unwrap(), 6);
|
2017-07-18 16:21:12 -04:00
|
|
|
assert_eq!(thread.status(), ThreadStatus::Active);
|
2017-06-17 23:50:40 -04:00
|
|
|
assert_eq!(thread.resume::<_, i64>(4).unwrap(), 10);
|
2017-07-18 16:21:12 -04:00
|
|
|
assert_eq!(thread.status(), ThreadStatus::Dead);
|
2017-05-24 23:13:58 -04:00
|
|
|
|
2017-06-11 01:12:25 -04:00
|
|
|
let accumulate = lua.create_thread(
|
2017-07-18 16:21:12 -04:00
|
|
|
lua.eval::<Function>(
|
2017-06-17 22:40:09 -04:00
|
|
|
r#"
|
|
|
|
function (sum)
|
|
|
|
while true do
|
|
|
|
sum = sum + coroutine.yield(sum)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
"#,
|
2017-07-19 20:10:11 -04:00
|
|
|
None,
|
2017-06-11 01:12:25 -04:00
|
|
|
).unwrap(),
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
);
|
2017-05-24 23:13:58 -04:00
|
|
|
|
|
|
|
for i in 0..4 {
|
|
|
|
accumulate.resume::<_, ()>(i).unwrap();
|
|
|
|
}
|
2017-06-17 23:50:40 -04:00
|
|
|
assert_eq!(accumulate.resume::<_, i64>(4).unwrap(), 10);
|
2017-07-18 16:21:12 -04:00
|
|
|
assert_eq!(accumulate.status(), ThreadStatus::Active);
|
2017-05-24 23:13:58 -04:00
|
|
|
assert!(accumulate.resume::<_, ()>("error").is_err());
|
2017-07-18 16:21:12 -04:00
|
|
|
assert_eq!(accumulate.status(), ThreadStatus::Error);
|
2017-05-24 23:13:58 -04:00
|
|
|
|
2017-07-18 16:21:12 -04:00
|
|
|
let thread = lua.eval::<Thread>(
|
2017-06-17 22:40:09 -04:00
|
|
|
r#"
|
|
|
|
coroutine.create(function ()
|
|
|
|
while true do
|
|
|
|
coroutine.yield(42)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
"#,
|
2017-07-19 20:10:11 -04:00
|
|
|
None,
|
2017-06-11 01:12:25 -04:00
|
|
|
).unwrap();
|
2017-07-18 16:21:12 -04:00
|
|
|
assert_eq!(thread.status(), ThreadStatus::Active);
|
2017-06-17 23:50:40 -04:00
|
|
|
assert_eq!(thread.resume::<_, i64>(()).unwrap(), 42);
|
2017-06-17 22:40:09 -04:00
|
|
|
|
2017-07-18 16:21:12 -04:00
|
|
|
let thread: Thread = lua.eval(
|
2017-06-17 22:40:09 -04:00
|
|
|
r#"
|
|
|
|
coroutine.create(function(arg)
|
|
|
|
assert(arg == 42)
|
|
|
|
local yieldarg = coroutine.yield(123)
|
|
|
|
assert(yieldarg == 43)
|
|
|
|
return 987
|
|
|
|
end)
|
|
|
|
"#,
|
2017-07-19 20:10:11 -04:00
|
|
|
None,
|
2017-06-17 22:40:09 -04:00
|
|
|
).unwrap();
|
|
|
|
|
2017-06-17 23:50:40 -04:00
|
|
|
assert_eq!(thread.resume::<_, u32>(42).unwrap(), 123);
|
|
|
|
assert_eq!(thread.resume::<_, u32>(43).unwrap(), 987);
|
|
|
|
|
|
|
|
match thread.resume::<_, u32>(()) {
|
2017-07-18 16:21:12 -04:00
|
|
|
Err(Error::CoroutineInactive) => {}
|
2017-06-17 23:50:40 -04:00
|
|
|
Err(_) => panic!("resuming dead coroutine error is not CoroutineInactive kind"),
|
|
|
|
_ => panic!("resuming dead coroutine did not return error"),
|
|
|
|
}
|
2017-05-24 23:13:58 -04:00
|
|
|
}
|
2017-05-25 00:43:35 -04:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_lightuserdata() {
|
|
|
|
let lua = Lua::new();
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
let globals = lua.globals();
|
2017-06-18 08:31:38 -04:00
|
|
|
lua.exec::<()>(
|
2017-06-17 22:40:09 -04:00
|
|
|
r#"
|
|
|
|
function id(a)
|
|
|
|
return a
|
|
|
|
end
|
|
|
|
"#,
|
2017-06-05 00:03:39 -04:00
|
|
|
None,
|
2017-06-11 01:12:25 -04:00
|
|
|
).unwrap();
|
|
|
|
let res = globals
|
2017-07-18 16:21:12 -04:00
|
|
|
.get::<_, Function>("id")
|
2017-05-25 00:43:35 -04:00
|
|
|
.unwrap()
|
2017-07-18 16:21:12 -04:00
|
|
|
.call::<_, LightUserData>(LightUserData(42 as *mut c_void))
|
2017-05-25 00:43:35 -04:00
|
|
|
.unwrap();
|
2017-07-18 16:21:12 -04:00
|
|
|
assert_eq!(res, LightUserData(42 as *mut c_void));
|
2017-05-25 00:43:35 -04:00
|
|
|
}
|
2017-06-05 00:03:39 -04:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_table_error() {
|
|
|
|
let lua = Lua::new();
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
let globals = lua.globals();
|
2017-06-18 08:31:38 -04:00
|
|
|
lua.exec::<()>(
|
2017-06-05 00:03:39 -04:00
|
|
|
r#"
|
|
|
|
table = {}
|
|
|
|
setmetatable(table, {
|
|
|
|
__index = function()
|
|
|
|
error("lua error")
|
|
|
|
end,
|
|
|
|
__newindex = function()
|
|
|
|
error("lua error")
|
|
|
|
end,
|
|
|
|
__len = function()
|
|
|
|
error("lua error")
|
|
|
|
end
|
|
|
|
})
|
|
|
|
"#,
|
|
|
|
None,
|
2017-06-11 01:12:25 -04:00
|
|
|
).unwrap();
|
2017-06-05 00:03:39 -04:00
|
|
|
|
2017-07-18 16:21:12 -04:00
|
|
|
let bad_table: Table = globals.get("table").unwrap();
|
2017-06-05 00:41:48 -04:00
|
|
|
assert!(bad_table.set(1, 1).is_err());
|
|
|
|
assert!(bad_table.get::<_, i32>(1).is_err());
|
2017-06-18 08:36:30 -04:00
|
|
|
assert!(bad_table.len().is_err());
|
2017-06-05 00:41:48 -04:00
|
|
|
assert!(bad_table.raw_set(1, 1).is_ok());
|
|
|
|
assert!(bad_table.raw_get::<_, i32>(1).is_ok());
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
assert_eq!(bad_table.raw_len(), 1);
|
2017-06-05 00:03:39 -04:00
|
|
|
}
|
2017-06-13 19:17:41 -04:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_result_conversions() {
|
|
|
|
let lua = Lua::new();
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
let globals = lua.globals();
|
2017-06-13 19:17:41 -04:00
|
|
|
|
2017-08-01 14:09:47 -04:00
|
|
|
let err = lua.create_function(|_, ()| {
|
2017-07-31 01:21:41 -04:00
|
|
|
Ok(Err::<String, _>(
|
Big API incompatible error change, remove dependency on error_chain
The current situation with error_chain is less than ideal, and there are lots of
conflicting interests that are impossible to meet at once. Here is an
unorganized brain dump of the current situation, stay awhile and listen!
This change was triggered ultimately by the desire to make LuaError implement
Clone, and this is currently impossible with error_chain. LuaError must
implement Clone to be a proper lua citizen that can live as userdata within a
lua runtime, because there is no way to limit what the lua runtime can do with a
received error. Currently, this is solved by there being a rule that the error
will "expire" if the error is passed back into rust, and this is very
sub-optimal. In fact, one could easily imagine a scenario where lua is for
example memoizing some function, and if the function has ever errored in the
past the function should continue returning the same error, and this situation
immediately fails with this restriciton in place.
Additionally, there are other more minor problems with error_chain which make
the API less good than it could be, or limit how we can use error_chain. This
change has already solved a small bug in a Chucklefish project, where the
conversion from an external error type (Borrow[Mut]Error) was allowed but not
intended for user code, and was accidentally used. Additionally, pattern
matching on error_chain errors, which should be common when dealing with Lua, is
less convenient than a hand rolled error type.
So, if we decide not to use error_chain, we now have a new set of problems if we
decide interoperability with error_chain is important. The first problem we run
into is that there are two natural bounds for wrapped errors that we would
pick, (Error + Send + Sync), or just Error, and neither of them will
interoperate well with error_chain. (Error + Send + Sync) means we can't wrap
error chain errors into LuaError::ExternalError (they're missing the Sync
bound), and having the bounds be just Error means the opposite, that we can't
hold a LuaError inside an error_chain error.
We could just decide that interoperability with error_chain is the most
important qualification, and pick (Error + Send), but this causes a DIFFERENT
set of problems. The rust ecosystem has the two primary error bounds as Error
or (Error + Send + Sync), and there are Into impls from &str / String to
Box<Error + Send + Sync> for example, but NOT (Error + Send). This means that
we are forced to manually recreate the conversions from &str / String to
LuaError rather than relying on a single Into<Box<Error + Send + Sync>> bound,
but this means that string conversions have a different set of methods than
other error types for external error conversion. I have not been able to figure
out an API that I am happy with that uses the (Error + Send) bound. Box<Error>
is obnoxious because not having errors implement Send causes needless problems
in a multithreaded context, so that leaves (Error + Send + Sync). This is
actually a completely reasonable bound for external errors, and has the nice
String Into impls that we would want, the ONLY problem is that it is a pain to
interoperate with the current version of error_chain.
It would be nice to be able to specify the traits that an error generated by the
error_chain macro would implement, and this is apparently in progress in the
error_chain library. This would solve both the problem with not being able to
implement Clone and the problems with (Error + Send) bounds. I am not convinced
that this library should go back to using error_chain when that functionality is
in stable error_chain though, because of the other minor usability problems with
using error_chain.
In that theoretical situation, the downside of NOT using error_chain is simply
that there would not be automatic stacktraces of LuaError. This is not a huge
problem, because stack traces of lua errors are not extremely useful, and for
external errors it is not too hard to create a different version of the
LuaExternalResult / LuaExternalError traits and do conversion from an
error_chain type into a type that will print the stacktrace on display, or
use downcasting in the error causes.
So in summary, this library is no longer using error_chain, and probably will
not use it again in the future. Currently this means that to interoperate with
error_chain, you should use error_chain 0.8.1, which derives Sync on errors, or
wait for a version that supports user defined trait derives. In the future
when error_chain supports user defined trait derives, users may have to take an
extra step to make wrapped external errors print the stacktrace that they
capture.
This change works, but is not entirely complete. There is no error
documentation yet, and the change brought to a head an ugly module organization
problem. There will be more commits for documentation and reorganization, then
a new stable version of rlua.
2017-06-24 18:11:56 -04:00
|
|
|
"only through failure can we succeed".to_lua_err(),
|
2017-06-17 22:40:09 -04:00
|
|
|
))
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
});
|
2017-08-01 14:09:47 -04:00
|
|
|
let ok = lua.create_function(|_, ()| Ok(Ok::<_, Error>("!".to_owned())));
|
2017-06-13 19:17:41 -04:00
|
|
|
|
|
|
|
globals.set("err", err).unwrap();
|
|
|
|
globals.set("ok", ok).unwrap();
|
|
|
|
|
2017-06-18 08:31:38 -04:00
|
|
|
lua.exec::<()>(
|
2017-06-13 19:17:41 -04:00
|
|
|
r#"
|
2017-06-23 19:41:08 -04:00
|
|
|
local r, e = err()
|
|
|
|
assert(r == nil)
|
|
|
|
assert(tostring(e) == "only through failure can we succeed")
|
|
|
|
|
|
|
|
local r, e = ok()
|
|
|
|
assert(r == "!")
|
|
|
|
assert(e == nil)
|
2017-06-13 19:17:41 -04:00
|
|
|
"#,
|
|
|
|
None,
|
|
|
|
).unwrap();
|
|
|
|
}
|
2017-06-21 17:53:52 -04:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_num_conversion() {
|
|
|
|
let lua = Lua::new();
|
Another major API change, out of stack space is not an Err
It, ahem "should not" be possible to exhaust lua stack space in normal usage,
and causing stack errors to be Err is slightly obnoxious. I have been wanting
to make this change for a while, and removing the callback API from tables makes
this sensible *I think*.
I can think of a couple of ways that this is not technically true, but I think
that they are acceptable, or should be handled differently.
One, you can make arbitrarily sized LuaVariadic values. I think this is maybe a
bug already, because there is an argument limit in Lua which is lower than the
stack limit. I'm not sure what happens there, but if it is a stack based panic,
(or any panic?) it is a bug.
Two, I believe that if you recurse over and over between lua -> rust -> lua ->
rust etc, and call rlua API functions, you might get a stack panic. I think for
trusted lua code, this is morally equivalent to a regular stack overflow in
plain rust, which is already.. well it's not a panic but it's some kind of safe
crash I'm not sure, so I think this is acceptable. For *untrusted* lua code,
this could theoretically be a problem if the API provided a callback that would
call back into lua, then some lua script could force a stack based panic. There
are so many concerns with untrusted lua code, and this library is NOT safe
enough yet for untrusted code (it doesn't even provide an option to limit lua to
the safe API subset yet!), so this is not currently an issue. When the library
provides support for "safe lua", it should come with big warnings anyway, and
being able to force a stack panic is pretty minor in comparison.
I think if there are other ways to cause unbounded stack usage, that it is a
bug, or there can be an error just for that situation, like argument count
limits.
This commit also fixes several stupid bugs with tests, stack checking, and
panics.
2017-06-25 16:52:32 -04:00
|
|
|
let globals = lua.globals();
|
2017-06-21 17:53:52 -04:00
|
|
|
|
2017-06-23 00:51:16 -04:00
|
|
|
globals.set("n", "1.0").unwrap();
|
|
|
|
assert_eq!(globals.get::<_, i64>("n").unwrap(), 1);
|
|
|
|
assert_eq!(globals.get::<_, f64>("n").unwrap(), 1.0);
|
|
|
|
assert_eq!(globals.get::<_, String>("n").unwrap(), "1.0");
|
|
|
|
|
|
|
|
globals.set("n", "1.5").unwrap();
|
|
|
|
assert!(globals.get::<_, i64>("n").is_err());
|
|
|
|
assert_eq!(globals.get::<_, f64>("n").unwrap(), 1.5);
|
|
|
|
assert_eq!(globals.get::<_, String>("n").unwrap(), "1.5");
|
|
|
|
|
|
|
|
globals.set("n", 1.5).unwrap();
|
|
|
|
assert!(globals.get::<_, i64>("n").is_err());
|
|
|
|
assert_eq!(globals.get::<_, f64>("n").unwrap(), 1.5);
|
|
|
|
assert_eq!(globals.get::<_, String>("n").unwrap(), "1.5");
|
|
|
|
|
|
|
|
lua.exec::<()>("a = math.huge", None).unwrap();
|
|
|
|
assert!(globals.get::<_, i64>("n").is_err());
|
2017-06-21 17:53:52 -04:00
|
|
|
}
|
2017-07-23 01:00:33 -04:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[should_panic]
|
|
|
|
fn test_expired_userdata() {
|
2017-07-23 12:37:48 -04:00
|
|
|
struct MyUserdata {
|
2017-07-23 01:00:33 -04:00
|
|
|
id: u8,
|
|
|
|
}
|
|
|
|
|
2017-07-23 12:37:48 -04:00
|
|
|
impl UserData for MyUserdata {
|
|
|
|
fn add_methods(methods: &mut UserDataMethods<Self>) {
|
2017-08-01 14:09:47 -04:00
|
|
|
methods.add_method("access", |_, this, ()| {
|
2017-07-23 02:08:32 -04:00
|
|
|
assert!(this.id == 123);
|
2017-07-31 01:21:41 -04:00
|
|
|
Ok(())
|
2017-07-23 01:00:33 -04:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let lua = Lua::new();
|
|
|
|
{
|
|
|
|
let globals = lua.globals();
|
2017-07-23 12:37:48 -04:00
|
|
|
globals.set("userdata", MyUserdata { id: 123 }).unwrap();
|
2017-07-23 01:00:33 -04:00
|
|
|
}
|
|
|
|
|
2017-07-24 10:40:00 -04:00
|
|
|
lua.eval::<()>(
|
|
|
|
r#"
|
2017-07-23 01:00:33 -04:00
|
|
|
local tbl = setmetatable({
|
|
|
|
userdata = userdata
|
|
|
|
}, { __gc = function(self)
|
|
|
|
-- resurrect userdata
|
|
|
|
hatch = self.userdata
|
|
|
|
end })
|
|
|
|
|
|
|
|
tbl = nil
|
|
|
|
userdata = nil -- make table and userdata collectable
|
|
|
|
collectgarbage("collect")
|
|
|
|
hatch:access()
|
2017-07-24 10:40:00 -04:00
|
|
|
"#,
|
|
|
|
None,
|
|
|
|
).unwrap();
|
2017-07-23 01:00:33 -04:00
|
|
|
}
|
2017-07-23 06:50:42 -04:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn detroys_userdata() {
|
|
|
|
use std::sync::atomic::{Ordering, AtomicBool, ATOMIC_BOOL_INIT};
|
|
|
|
|
|
|
|
static DROPPED: AtomicBool = ATOMIC_BOOL_INIT;
|
|
|
|
|
2017-07-23 12:37:48 -04:00
|
|
|
struct MyUserdata;
|
2017-07-23 06:50:42 -04:00
|
|
|
|
2017-07-23 12:37:48 -04:00
|
|
|
impl UserData for MyUserdata {}
|
2017-07-23 06:50:42 -04:00
|
|
|
|
2017-07-23 12:37:48 -04:00
|
|
|
impl Drop for MyUserdata {
|
2017-07-23 06:50:42 -04:00
|
|
|
fn drop(&mut self) {
|
|
|
|
DROPPED.store(true, Ordering::SeqCst);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let lua = Lua::new();
|
|
|
|
{
|
|
|
|
let globals = lua.globals();
|
2017-07-23 12:37:48 -04:00
|
|
|
globals.set("userdata", MyUserdata).unwrap();
|
2017-07-23 06:50:42 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
assert_eq!(DROPPED.load(Ordering::SeqCst), false);
|
2017-07-24 10:40:00 -04:00
|
|
|
drop(lua); // should destroy all objects
|
2017-07-23 06:50:42 -04:00
|
|
|
assert_eq!(DROPPED.load(Ordering::SeqCst), true);
|
|
|
|
}
|
2017-07-24 18:37:37 -04:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn string_views() {
|
|
|
|
let lua = Lua::new();
|
2017-07-31 01:21:41 -04:00
|
|
|
lua.eval::<()>(
|
|
|
|
r#"
|
2017-07-24 18:37:37 -04:00
|
|
|
ok = "null bytes are valid utf-8, wh\0 knew?"
|
|
|
|
err = "but \xff isn't :("
|
2017-07-31 01:21:41 -04:00
|
|
|
"#,
|
|
|
|
None,
|
|
|
|
).unwrap();
|
2017-07-24 18:37:37 -04:00
|
|
|
|
|
|
|
let globals = lua.globals();
|
|
|
|
let ok: LuaString = globals.get("ok").unwrap();
|
|
|
|
let err: LuaString = globals.get("err").unwrap();
|
|
|
|
|
2017-07-31 01:21:41 -04:00
|
|
|
assert_eq!(
|
|
|
|
ok.to_str().unwrap(),
|
|
|
|
"null bytes are valid utf-8, wh\0 knew?"
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
ok.as_bytes(),
|
|
|
|
&b"null bytes are valid utf-8, wh\0 knew?"[..]
|
|
|
|
);
|
2017-07-24 18:37:37 -04:00
|
|
|
|
|
|
|
assert!(err.to_str().is_err());
|
|
|
|
assert_eq!(err.as_bytes(), &b"but \xff isn't :("[..]);
|
|
|
|
}
|
2017-07-27 16:47:06 -04:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn coroutine_from_closure() {
|
|
|
|
let lua = Lua::new();
|
2017-08-01 14:09:47 -04:00
|
|
|
let thrd_main = lua.create_function(|_, ()| Ok(()));
|
2017-07-27 16:47:06 -04:00
|
|
|
lua.globals().set("main", thrd_main).unwrap();
|
|
|
|
let thrd: Thread = lua.eval("coroutine.create(main)", None).unwrap();
|
|
|
|
thrd.resume::<_, ()>(()).unwrap();
|
|
|
|
}
|
2017-07-27 17:16:40 -04:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[should_panic]
|
|
|
|
fn coroutine_panic() {
|
|
|
|
let lua = Lua::new();
|
2017-08-01 14:09:47 -04:00
|
|
|
let thrd_main = lua.create_function(|lua, ()| {
|
2017-07-27 17:16:40 -04:00
|
|
|
// whoops, 'main' has a wrong type
|
|
|
|
let _coro: u32 = lua.globals().get("main").unwrap();
|
2017-07-31 01:21:41 -04:00
|
|
|
Ok(())
|
2017-07-27 17:16:40 -04:00
|
|
|
});
|
|
|
|
lua.globals().set("main", thrd_main.clone()).unwrap();
|
|
|
|
let thrd: Thread = lua.create_thread(thrd_main);
|
|
|
|
thrd.resume::<_, ()>(()).unwrap();
|
|
|
|
}
|
2017-08-01 12:03:05 -04:00
|
|
|
|
|
|
|
|
|
|
|
// Need to use compiletest-rs or similar to make sure these don't compile.
|
|
|
|
/*
|
|
|
|
#[test]
|
|
|
|
fn should_not_compile() {
|
|
|
|
let lua = Lua::new();
|
|
|
|
let globals = lua.globals();
|
|
|
|
|
|
|
|
// Should not allow userdata borrow to outlive lifetime of AnyUserData handle
|
|
|
|
struct MyUserData;
|
|
|
|
impl UserData for MyUserData {};
|
|
|
|
let userdata_ref;
|
|
|
|
{
|
|
|
|
let touter = globals.get::<_, Table>("touter").unwrap();
|
|
|
|
touter.set("userdata", lua.create_userdata(MyUserData)).unwrap();
|
|
|
|
let userdata = touter.get::<_, AnyUserData>("userdata").unwrap();
|
|
|
|
userdata_ref = userdata.borrow::<MyUserData>();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Should not allow self borrow of lua, it can change addresses
|
|
|
|
globals.set("boom", lua.create_function(|_, _| {
|
2017-08-01 18:35:09 -04:00
|
|
|
lua.eval::<i32>("1 + 1", None)
|
2017-08-01 12:03:05 -04:00
|
|
|
})).unwrap();
|
|
|
|
}
|
|
|
|
*/
|