wplua: allow exchanging arguments and results with scripts
This commit is contained in:
@@ -80,7 +80,7 @@ if SANDBOX_CONFIG["isolate_env"] then
|
||||
-- store all of them in a global table so that they are not garbage collected
|
||||
SANDBOX_ENV_LIST = {}
|
||||
|
||||
function sandbox(chunk)
|
||||
function sandbox(chunk, ...)
|
||||
-- chunk's environment will be an empty table with __index
|
||||
-- to access our SANDBOX_ENV (without being able to write it)
|
||||
local env = setmetatable({}, {
|
||||
@@ -91,7 +91,7 @@ if SANDBOX_CONFIG["isolate_env"] then
|
||||
-- set it as the chunk's 1st upvalue (__ENV)
|
||||
debug.setupvalue(chunk, 1, env)
|
||||
-- execute the chunk
|
||||
chunk()
|
||||
chunk(...)
|
||||
end
|
||||
else
|
||||
-- in common_env mode, use the same environment for all loaded chunks
|
||||
@@ -101,10 +101,10 @@ else
|
||||
__index = SANDBOX_ENV,
|
||||
})
|
||||
|
||||
function sandbox(chunk)
|
||||
function sandbox(chunk, ...)
|
||||
-- set it as the chunk's 1st upvalue (__ENV)
|
||||
debug.setupvalue(chunk, 1, SANDBOX_COMMON_ENV)
|
||||
-- execute the chunk
|
||||
chunk()
|
||||
chunk(...)
|
||||
end
|
||||
end
|
||||
|
@@ -129,7 +129,7 @@ wplua_enable_sandbox (lua_State * L, WpLuaSandboxFlags flags)
|
||||
lua_settable (L, -3);
|
||||
lua_setglobal (L, "SANDBOX_CONFIG");
|
||||
|
||||
if (!wplua_load_uri (L, URI_SANDBOX, &error)) {
|
||||
if (!wplua_load_uri (L, URI_SANDBOX, 0, 0, &error)) {
|
||||
wp_critical ("Failed to load sandbox: %s", error->message);
|
||||
}
|
||||
}
|
||||
@@ -180,10 +180,11 @@ wplua_register_type_methods (lua_State * L, GType type,
|
||||
|
||||
static gboolean
|
||||
_wplua_load_buffer (lua_State * L, const gchar *buf, gsize size,
|
||||
const gchar * name, GError **error)
|
||||
const gchar * name, int nargs, int nres, GError **error)
|
||||
{
|
||||
int ret;
|
||||
int sandbox = 0;
|
||||
int args_top = lua_gettop (L);
|
||||
|
||||
/* wrap with sandbox() if it's loaded */
|
||||
if (lua_getglobal (L, "sandbox") == LUA_TFUNCTION)
|
||||
@@ -195,11 +196,14 @@ _wplua_load_buffer (lua_State * L, const gchar *buf, gsize size,
|
||||
if (ret != LUA_OK) {
|
||||
g_set_error (error, WP_DOMAIN_LUA, WP_LUA_ERROR_COMPILATION,
|
||||
"Failed to compile: %s", lua_tostring (L, -1));
|
||||
lua_pop (L, sandbox + 1);
|
||||
lua_pop (L, nargs + sandbox + 1);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ret = _wplua_pcall (L, sandbox, 0);
|
||||
/* push sandbox() and the chunk below the arguments */
|
||||
lua_rotate (L, args_top, -nargs);
|
||||
|
||||
ret = _wplua_pcall (L, nargs + sandbox, nres);
|
||||
if (ret != LUA_OK) {
|
||||
g_set_error (error, WP_DOMAIN_LUA, WP_LUA_ERROR_RUNTIME,
|
||||
"Runtime error while loading '%s'", name);
|
||||
@@ -210,7 +214,8 @@ _wplua_load_buffer (lua_State * L, const gchar *buf, gsize size,
|
||||
}
|
||||
|
||||
gboolean
|
||||
wplua_load_buffer (lua_State * L, const gchar *buf, gsize size, GError **error)
|
||||
wplua_load_buffer (lua_State * L, const gchar *buf, gsize size,
|
||||
int nargs, int nres, GError **error)
|
||||
{
|
||||
g_return_val_if_fail (L != NULL, FALSE);
|
||||
g_return_val_if_fail (buf != NULL, FALSE);
|
||||
@@ -218,11 +223,12 @@ wplua_load_buffer (lua_State * L, const gchar *buf, gsize size, GError **error)
|
||||
|
||||
g_autofree gchar *name =
|
||||
g_strdup_printf ("buffer@%p;size=%" G_GSIZE_FORMAT, buf, size);
|
||||
return _wplua_load_buffer (L, buf, size, name, error);
|
||||
return _wplua_load_buffer (L, buf, size, name, nargs, nres, error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
wplua_load_uri (lua_State * L, const gchar *uri, GError **error)
|
||||
wplua_load_uri (lua_State * L, const gchar *uri, int nargs, int nres,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr (GFile) file = NULL;
|
||||
g_autoptr (GBytes) bytes = NULL;
|
||||
@@ -243,11 +249,12 @@ wplua_load_uri (lua_State * L, const gchar *uri, GError **error)
|
||||
|
||||
name = g_path_get_basename (uri);
|
||||
data = g_bytes_get_data (bytes, &size);
|
||||
return _wplua_load_buffer (L, data, size, name, error);
|
||||
return _wplua_load_buffer (L, data, size, name, nargs, nres, error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
wplua_load_path (lua_State * L, const gchar *path, GError **error)
|
||||
wplua_load_path (lua_State * L, const gchar *path, int nargs, int nres,
|
||||
GError **error)
|
||||
{
|
||||
g_autofree gchar *abs_path = NULL;
|
||||
g_autofree gchar *uri = NULL;
|
||||
@@ -263,5 +270,5 @@ wplua_load_path (lua_State * L, const gchar *path, GError **error)
|
||||
if (!(uri = g_filename_to_uri (abs_path ? abs_path : path, NULL, error)))
|
||||
return FALSE;
|
||||
|
||||
return wplua_load_uri (L, uri, error);
|
||||
return wplua_load_uri (L, uri, nargs, nres, error);
|
||||
}
|
||||
|
@@ -76,9 +76,11 @@ GVariant * wplua_table_to_asv (lua_State *L, int idx);
|
||||
void wplua_asv_to_table (lua_State *L, GVariant *p);
|
||||
|
||||
gboolean wplua_load_buffer (lua_State * L, const gchar *buf, gsize size,
|
||||
int nargs, int nres, GError **error);
|
||||
gboolean wplua_load_uri (lua_State * L, const gchar *uri, int nargs, int nres,
|
||||
GError **error);
|
||||
gboolean wplua_load_path (lua_State * L, const gchar *path, int nargs, int nres,
|
||||
GError **error);
|
||||
gboolean wplua_load_uri (lua_State * L, const gchar *uri, GError **error);
|
||||
gboolean wplua_load_path (lua_State * L, const gchar *path, GError **error);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(lua_State, wplua_free)
|
||||
|
||||
|
@@ -79,7 +79,7 @@ wp_lua_scripting_plugin_enable (WpPlugin * plugin, WpTransition * transition)
|
||||
/* execute scripts that were queued in for loading */
|
||||
for (guint i = 0; i < self->scripts->len; i++) {
|
||||
GError * error = NULL;
|
||||
if (!wplua_load_path (self->L, g_ptr_array_index (self->scripts, i), &error)) {
|
||||
if (!wplua_load_path (self->L, g_ptr_array_index (self->scripts, i), 0, 0, &error)) {
|
||||
wp_transition_return_error (transition, error);
|
||||
return;
|
||||
}
|
||||
@@ -163,7 +163,7 @@ wp_lua_scripting_plugin_load (WpComponentLoader * cl, const gchar * component,
|
||||
|
||||
/* keep in a list and delay loading until the plugin is enabled */
|
||||
g_ptr_array_add (self->scripts, file);
|
||||
return self->L ? wplua_load_path (self->L, file, error) : TRUE;
|
||||
return self->L ? wplua_load_path (self->L, file, 0, 0, error) : TRUE;
|
||||
}
|
||||
/* interpret component as a configuration file */
|
||||
else if (!g_strcmp0 (type, "config/lua")) {
|
||||
|
@@ -835,7 +835,7 @@ wp_lua_scripting_api_init (lua_State *L)
|
||||
wplua_register_type_methods (L, WP_TYPE_SESSION_ITEM,
|
||||
session_item_new, session_item_methods);
|
||||
|
||||
wplua_load_uri (L, URI_API, &error);
|
||||
wplua_load_uri (L, URI_API, 0, 0, &error);
|
||||
if (G_UNLIKELY (error))
|
||||
wp_critical ("Failed to load api: %s", error->message);
|
||||
}
|
||||
|
@@ -140,7 +140,7 @@ wp_lua_scripting_load_configuration (const gchar * conf_file,
|
||||
path = g_build_filename (wp_get_config_dir (), conf_file, NULL);
|
||||
if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
|
||||
wp_info ("loading config file: %s", path);
|
||||
if (!wplua_load_path (L, path, error))
|
||||
if (!wplua_load_path (L, path, 0, 0, error))
|
||||
return FALSE;
|
||||
found = TRUE;
|
||||
}
|
||||
@@ -160,7 +160,7 @@ wp_lua_scripting_load_configuration (const gchar * conf_file,
|
||||
if (g_str_has_suffix (filename, ".lua")) {
|
||||
g_autofree gchar * file = g_build_filename (path, filename, NULL);
|
||||
wp_info ("loading config file: %s", file);
|
||||
if (!wplua_load_path (L, file, error))
|
||||
if (!wplua_load_path (L, file, 0, 0, error))
|
||||
return FALSE;
|
||||
found = TRUE;
|
||||
}
|
||||
|
@@ -260,7 +260,7 @@ test_wplua_construct ()
|
||||
const gchar code[] =
|
||||
"o = TestObject_new()\n"
|
||||
"assert (type(o) == 'userdata')\n";
|
||||
wplua_load_buffer (L, code, sizeof (code) - 1, &error);
|
||||
wplua_load_buffer (L, code, sizeof (code) - 1, 0, 0, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_cmpint (lua_getglobal (L, "o"), ==, LUA_TUSERDATA);
|
||||
@@ -293,7 +293,7 @@ test_wplua_properties ()
|
||||
"o['test-float'] = 3.1415\n"
|
||||
"o['test-double'] = 0.123456789\n"
|
||||
"o['test-boolean'] = true\n";
|
||||
wplua_load_buffer (L, code, sizeof (code) - 1, &error);
|
||||
wplua_load_buffer (L, code, sizeof (code) - 1, 0, 0, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_cmpint (lua_getglobal (L, "o"), ==, LUA_TUSERDATA);
|
||||
@@ -318,7 +318,7 @@ test_wplua_properties ()
|
||||
"assert (math.abs (o['test-float'] - 3.1415) < 0.00001)\n"
|
||||
"assert (math.abs (o['test-double'] - 0.123456789) < 0.0000000001)\n"
|
||||
"assert (o['test-boolean'] == true)\n";
|
||||
wplua_load_buffer (L, code2, sizeof (code2) - 1, &error);
|
||||
wplua_load_buffer (L, code2, sizeof (code2) - 1, 0, 0, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
wplua_free (L);
|
||||
@@ -340,7 +340,7 @@ test_wplua_closure ()
|
||||
" assert(s == expected_str)\n"
|
||||
" f_was_called = true\n"
|
||||
"end\n";
|
||||
wplua_load_buffer (L, code, sizeof (code) - 1, &error);
|
||||
wplua_load_buffer (L, code, sizeof (code) - 1, 0, 0, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
lua_getglobal (L, "f");
|
||||
@@ -398,7 +398,7 @@ test_wplua_signals ()
|
||||
"o['test-boolean'] = true\n"
|
||||
"o:toggle()\n"
|
||||
"assert(o['test-boolean'] == false)\n";
|
||||
wplua_load_buffer (L, code, sizeof (code) - 1, &error);
|
||||
wplua_load_buffer (L, code, sizeof (code) - 1, 0, 0, &error);
|
||||
g_assert_no_error (error);
|
||||
wplua_free (L);
|
||||
}
|
||||
@@ -417,14 +417,14 @@ test_wplua_sandbox_script ()
|
||||
" Test = TestObject_new,\n"
|
||||
" Table = { test = 'foobar' }\n"
|
||||
"}\n";
|
||||
wplua_load_buffer (L, code, sizeof (code) - 1, &error);
|
||||
wplua_load_buffer (L, code, sizeof (code) - 1, 0, 0, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
wplua_enable_sandbox (L, WP_LUA_SANDBOX_ISOLATE_ENV);
|
||||
|
||||
const gchar code2[] =
|
||||
"o = TestObject_new()\n";
|
||||
wplua_load_buffer (L, code2, sizeof (code2) - 1, &error);
|
||||
wplua_load_buffer (L, code2, sizeof (code2) - 1, 0, 0, &error);
|
||||
g_debug ("expected error: %s", error ? error->message : "null");
|
||||
g_assert_error (error, WP_DOMAIN_LUA, WP_LUA_ERROR_RUNTIME);
|
||||
g_clear_error (&error);
|
||||
@@ -432,31 +432,31 @@ test_wplua_sandbox_script ()
|
||||
const gchar code3[] =
|
||||
"o = Test()\n"
|
||||
"o:toggle()\n";
|
||||
wplua_load_buffer (L, code3, sizeof (code3) - 1, &error);
|
||||
wplua_load_buffer (L, code3, sizeof (code3) - 1, 0, 0, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
const gchar code4[] =
|
||||
"assert(string.len(Table.test) == 6)\n";
|
||||
wplua_load_buffer (L, code4, sizeof (code4) - 1, &error);
|
||||
wplua_load_buffer (L, code4, sizeof (code4) - 1, 0, 0, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
const gchar code5[] =
|
||||
"o:call('change', 'by Lua', 55)\n";
|
||||
wplua_load_buffer (L, code5, sizeof (code5) - 1, &error);
|
||||
wplua_load_buffer (L, code5, sizeof (code5) - 1, 0, 0, &error);
|
||||
g_debug ("expected error: %s", error ? error->message : "null");
|
||||
g_assert_error (error, WP_DOMAIN_LUA, WP_LUA_ERROR_RUNTIME);
|
||||
g_clear_error (&error);
|
||||
|
||||
const gchar code6[] =
|
||||
"string.test = 'hello world'\n";
|
||||
wplua_load_buffer (L, code6, sizeof (code6) - 1, &error);
|
||||
wplua_load_buffer (L, code6, sizeof (code6) - 1, 0, 0, &error);
|
||||
g_debug ("expected error: %s", error ? error->message : "null");
|
||||
g_assert_error (error, WP_DOMAIN_LUA, WP_LUA_ERROR_RUNTIME);
|
||||
g_clear_error (&error);
|
||||
|
||||
const gchar code7[] =
|
||||
"Table.test = 'hello world'\n";
|
||||
wplua_load_buffer (L, code7, sizeof (code7) - 1, &error);
|
||||
wplua_load_buffer (L, code7, sizeof (code7) - 1, 0, 0, &error);
|
||||
g_debug ("expected error: %s", error ? error->message : "null");
|
||||
g_assert_error (error, WP_DOMAIN_LUA, WP_LUA_ERROR_RUNTIME);
|
||||
g_clear_error (&error);
|
||||
@@ -474,7 +474,7 @@ test_wplua_sandbox_config ()
|
||||
|
||||
const gchar code3[] =
|
||||
"o = { answer = 42 }\n";
|
||||
wplua_load_buffer (L, code3, sizeof (code3) - 1, &error);
|
||||
wplua_load_buffer (L, code3, sizeof (code3) - 1, 0, 0, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
/* no assert() in minimal_std mode, resort to other means of failure */
|
||||
@@ -482,13 +482,13 @@ test_wplua_sandbox_config ()
|
||||
"if (o.answer ~= 42) then\n"
|
||||
" non_existent_function()\n"
|
||||
"end\n";
|
||||
wplua_load_buffer (L, code4, sizeof (code4) - 1, &error);
|
||||
wplua_load_buffer (L, code4, sizeof (code4) - 1, 0, 0, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
/* string.* is protected */
|
||||
const gchar code6[] =
|
||||
"string.test = 'hello world'\n";
|
||||
wplua_load_buffer (L, code6, sizeof (code6) - 1, &error);
|
||||
wplua_load_buffer (L, code6, sizeof (code6) - 1, 0, 0, &error);
|
||||
g_debug ("expected error: %s", error ? error->message : "null");
|
||||
g_assert_error (error, WP_DOMAIN_LUA, WP_LUA_ERROR_RUNTIME);
|
||||
g_clear_error (&error);
|
||||
@@ -496,7 +496,7 @@ test_wplua_sandbox_config ()
|
||||
/* this would be an error if the assert function was exported, but it's not */
|
||||
const gchar code7[] =
|
||||
"assert = 'hello world'\n";
|
||||
wplua_load_buffer (L, code7, sizeof (code7) - 1, &error);
|
||||
wplua_load_buffer (L, code7, sizeof (code7) - 1, 0, 0, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
wplua_free (L);
|
||||
@@ -524,7 +524,7 @@ test_wplua_convert_asv ()
|
||||
"assert (math.abs (o['test-double'] - 3.14) < 0.0000000001)\n"
|
||||
"assert (o['test-boolean'] == true)\n"
|
||||
"assert (o['nested-table']['string'] == 'baz')\n";
|
||||
wplua_load_buffer (L, code2, sizeof (code2) - 1, &error);
|
||||
wplua_load_buffer (L, code2, sizeof (code2) - 1, 0, 0, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
lua_getglobal (L, "o");
|
||||
@@ -558,6 +558,40 @@ test_wplua_convert_asv ()
|
||||
wplua_free (L);
|
||||
}
|
||||
|
||||
static void
|
||||
test_wplua_script_arguments ()
|
||||
{
|
||||
g_autoptr (GError) error = NULL;
|
||||
lua_State *L = wplua_new ();
|
||||
|
||||
g_autoptr (GVariant) v = g_variant_new_parsed ("@a{sv} { "
|
||||
"'test-int': <42>, "
|
||||
"'test-double': <3.14>, "
|
||||
"'test-string': <'foobar'>, "
|
||||
"'test-boolean': <true>, "
|
||||
"'nested-table': <@a{sv} { 'string': <'baz'> }> "
|
||||
"}");
|
||||
wplua_asv_to_table (L, v);
|
||||
|
||||
const gchar code2[] =
|
||||
"local o = ...\n"
|
||||
"assert (o['test-string'] == 'foobar')\n"
|
||||
"assert (o['test-int'] == 42)\n"
|
||||
"assert (math.abs (o['test-double'] - 3.14) < 0.0000000001)\n"
|
||||
"assert (o['test-boolean'] == true)\n"
|
||||
"assert (o['nested-table']['string'] == 'baz')\n";
|
||||
wplua_load_buffer (L, code2, sizeof (code2) - 1, 1, 0, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
/* same test, but with sandbox enabled */
|
||||
wplua_enable_sandbox (L, WP_LUA_SANDBOX_ISOLATE_ENV);
|
||||
wplua_asv_to_table (L, v);
|
||||
wplua_load_buffer (L, code2, sizeof (code2) - 1, 1, 0, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
wplua_free (L);
|
||||
}
|
||||
|
||||
gint
|
||||
main (gint argc, gchar *argv[])
|
||||
{
|
||||
@@ -572,6 +606,7 @@ main (gint argc, gchar *argv[])
|
||||
g_test_add_func ("/wplua/sandbox/script", test_wplua_sandbox_script);
|
||||
g_test_add_func ("/wplua/sandbox/config", test_wplua_sandbox_config);
|
||||
g_test_add_func ("/wplua/convert/asv", test_wplua_convert_asv);
|
||||
g_test_add_func ("/wplua/script_arguments", test_wplua_script_arguments);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
Reference in New Issue
Block a user