From d196a27f763e9b8ff71fa5054b0e4707157a1d7d Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Sat, 7 Jan 2012 23:02:57 +0000 Subject: [PATCH] Calling non exstent functions no longer crashes scripts. This is so that future scripts will still work with old libraries, and lets us add the "host can provide Lua API" feature soon. Also some more comments. SVN revision: 66961 --- legacy/edje/ChangeLog | 7 +++ legacy/edje/NEWS | 1 + legacy/edje/src/examples/lua_script.edc | 8 ++++ legacy/edje/src/lib/edje_lua2.c | 59 +++++++++++++++++++++++++ 4 files changed, 75 insertions(+) diff --git a/legacy/edje/ChangeLog b/legacy/edje/ChangeLog index 9dd1453701..505ce25584 100644 --- a/legacy/edje/ChangeLog +++ b/legacy/edje/ChangeLog @@ -271,3 +271,10 @@ * Unswallow object that are about to be swallowed if necessary. * Add EDJE_ASPECT_PREFER_SOURCE. + +2011-11-07 David Seikel (onefang) + + * Lua: Calling non exstent functions no longer crashes scripts. + This is so that future scripts will still work with old libraries, + and lets us add the "host can provide Lua API" feature soon. + diff --git a/legacy/edje/NEWS b/legacy/edje/NEWS index 1b38efb0b6..875a566b46 100644 --- a/legacy/edje/NEWS +++ b/legacy/edje/NEWS @@ -13,6 +13,7 @@ Improvements: * check existence of group at compile time also. * reduce number of call to stat during edje_object_file_set. * unswallow object about to be swallowed if necessary. + * Lua scripts now more resilient against API changes. Changes since Edje 1.0.0: ------------------------- diff --git a/legacy/edje/src/examples/lua_script.edc b/legacy/edje/src/examples/lua_script.edc index 24e8ebe4ce..2f2ea74757 100644 --- a/legacy/edje/src/examples/lua_script.edc +++ b/legacy/edje/src/examples/lua_script.edc @@ -168,6 +168,14 @@ collections { print(D.text:text()); D.text:show(); + --// Put a few bogus API calls here to test the bogus API protection, + --// If the bogus API protection works, these should get ignored, but everything else runs smoothly. + --// Otherwise, the map is not done, the bubbles are not done, but the timers keep runinng. + bogus.failme(1, "two", D.rect); + temp = bogus.failme2(); + D.text.bogus(); + edje.bogus2(); + --// Fun with maps! D.map = edje.map(4); --// 4 is the only supported map size at the moment. --// These all do the same thing. diff --git a/legacy/edje/src/lib/edje_lua2.c b/legacy/edje/src/lib/edje_lua2.c index 527d1bd8d8..2dbcb081a2 100644 --- a/legacy/edje/src/lib/edje_lua2.c +++ b/legacy/edje/src/lib/edje_lua2.c @@ -3724,25 +3724,80 @@ _elua_text_text(lua_State *L) // Stack usage [ //--------------------------------------------------------------------------// + +// A metatable and functions so that calling non existant API does not crash Lua scripts. + +static int _elua_bogan_nilfunc(lua_State *L); +static int _elua_bogan_index(lua_State *L); + +static const struct luaL_reg _elua_bogan_funcs [] = +{ + {"nilfunc", _elua_bogan_nilfunc}, // Just return a nil. + {"__index", _elua_bogan_index}, // Return the above func. + + {NULL, NULL} // end +}; + +static int +_elua_bogan_nilfunc(lua_State *L) +{ + lua_getglobal(L, "nil"); + return 1; +} + +static int +_elua_bogan_index(lua_State *L) +{ + const char *key; + + key = lua_tostring(L, 2); + LE("%s does not exist!", key); + lua_pushcfunction(L, _elua_bogan_nilfunc); + return 1; +} + +static void +_elua_bogan_protect(lua_State *L) // Stack usage [-3, +3, m] +{ + lua_pushnil(L); // Stack usage [-0, +1, -] + luaL_newmetatable(L, "bogan"); // Stack usage [-0, +1, m] + luaL_register(L, 0, _elua_bogan_funcs); // Stack usage [-1, +1, m] + lua_setmetatable(L, -2); // Stack usage [-1, +0, -] + lua_pop(L, 1); // Stack usage [-1, +0, -] +} + +//--------------------------------------------------------------------------// + // Brain dead inheritance thingy, built for speed. Kinda. Part 1. static void _elua_add_functions(lua_State *L, const char *api, const luaL_Reg *funcs, const char *meta, const char *parent, const char *base) // Stack usage [-3, +5, m] if inheriting [-6, +11, em] { + // Create an api table, fill it full of the methods. luaL_register(L, api, funcs); // Stack usage [-0, +1, m] + // Set the api metatable to the bogan metatable. + luaL_getmetatable(L, "bogan"); // Stack usage [-0, +1, -] + lua_setmetatable(L, -2); // Stack usage [-1, +0, -] + // Creat a meta metatable. luaL_newmetatable(L, meta); // Stack usage [-0, +1, m] + // Put the gc functions in the metatable. luaL_register(L, 0, _elua_edje_gc_funcs); // Stack usage [-1, +1, m] + // Create an __index entry in the metatable, make it point to the api table. lua_pushliteral(L, "__index"); // Stack usage [-0, +1, m] lua_pushvalue(L, -3); // Stack usage [-0, +1, -] lua_rawset(L, -3); // Stack usage [-2, +0, m] + // Later this metatable is used as the metatable for newly created objects of this class. if (base && parent) { // Inherit from base lua_getglobal(L, base); // Stack usage [-0, +1, e] + // Create a new parent metatable. luaL_newmetatable(L, parent); // Stack usage [-0, +1, m] + // Create an __index entry in the metatable, make it point to the base table. lua_pushliteral(L, "__index"); // Stack usage [-0, +1, m] lua_pushvalue(L, -3); // Stack usage [-0, +1, -] lua_rawset(L, -3); // Stack usage [-2, +0, m] + // Set the metatable for the api table to the parent metatable. lua_getglobal(L, api); // Stack usage [-0, +1, e] luaL_getmetatable(L, parent); // Stack usage [-0, +1, -] lua_setmetatable(L, -2); // Stack usage [-1, +0, -] @@ -3850,7 +3905,11 @@ _edje_lua2_script_init(Edje *ed) // Stack usage lua_call(L, 1, 0); // Stack usage [-2, +0, m] } + _elua_bogan_protect(L); // Stack usage [+3, -3, m] + luaL_register(L, _elua_edje_api, _elua_edje_funcs); // Stack usage [-0, +1, m] + luaL_getmetatable(L, "bogan"); // Stack usage [-0, +1, -] + lua_setmetatable(L, -2); // Stack usage [-1, +0, -] luaL_newmetatable(L, _elua_edje_meta); // Stack usage [-0, +1, m] luaL_register(L, 0, _elua_edje_gc_funcs); // Stack usage [-1, +1, m]