diff options
| author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-05-29 11:23:21 +0200 |
|---|---|---|
| committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-05-29 11:23:21 +0200 |
| commit | 05921ccb8205a4dcf1897dd8be9aa30a09e9a379 (patch) | |
| tree | 9bb3c3139fbdf1ca8b409163877f6a3f69a81260 /src | |
| parent | 6b836d54fdbea502f47c546f8f04c347eba46d5c (diff) | |
| download | lanes-05921ccb8205a4dcf1897dd8be9aa30a09e9a379.tar.gz lanes-05921ccb8205a4dcf1897dd8be9aa30a09e9a379.tar.bz2 lanes-05921ccb8205a4dcf1897dd8be9aa30a09e9a379.zip | |
PushDeepProxy internal change
Diffstat (limited to 'src')
| -rw-r--r-- | src/deep.cpp | 87 | ||||
| -rw-r--r-- | src/deep.h | 2 | ||||
| -rw-r--r-- | src/intercopycontext.cpp | 9 | ||||
| -rw-r--r-- | src/lanes.cpp | 12 |
4 files changed, 48 insertions, 62 deletions
diff --git a/src/deep.cpp b/src/deep.cpp index a39e0f8..dfa3579 100644 --- a/src/deep.cpp +++ b/src/deep.cpp | |||
| @@ -177,28 +177,29 @@ void DeepFactory::DeleteDeepObject(lua_State* L_, DeepPrelude* o_) | |||
| 177 | 177 | ||
| 178 | /* | 178 | /* |
| 179 | * Push a proxy userdata on the stack. | 179 | * Push a proxy userdata on the stack. |
| 180 | * returns nullptr if ok, else some error string related to bad factory behavior or module require problem | 180 | * raises an error in case of problem (error cannot happen with mode_ == LookupMode::ToKeeper) |
| 181 | * (error cannot happen with mode_ == LookupMode::ToKeeper) | ||
| 182 | * | 181 | * |
| 183 | * Initializes necessary structures if it's the first time 'factory' is being | 182 | * Initializes necessary structures if it's the first time 'factory' is being used in |
| 184 | * used in this Lua state (metatable, registring it). Otherwise, increments the | 183 | * this Lua state (metatable, registring it). Otherwise, increments the reference count. |
| 185 | * reference count. | ||
| 186 | */ | 184 | */ |
| 187 | std::string_view DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, int nuv_, LookupMode mode_) | 185 | void DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, int nuv_, LookupMode mode_, lua_State* errL_) |
| 188 | { | 186 | { |
| 189 | // Check if a proxy already exists | 187 | STACK_CHECK_START_REL(L_, 0); |
| 190 | kDeepProxyCacheRegKey.getSubTableMode(L_, "v"); // L_: DPC | 188 | kDeepProxyCacheRegKey.getSubTableMode(L_, "v"); // L_: DPC |
| 189 | |||
| 190 | // Check if a proxy already exists | ||
| 191 | lua_pushlightuserdata(L_, prelude_); // L_: DPC deep | 191 | lua_pushlightuserdata(L_, prelude_); // L_: DPC deep |
| 192 | lua_rawget(L_, -2); // L_: DPC proxy | 192 | lua_rawget(L_, -2); // L_: DPC proxy |
| 193 | if (!lua_isnil(L_, -1)) { | 193 | if (!lua_isnil(L_, -1)) { |
| 194 | lua_remove(L_, -2); // L_: proxy | 194 | lua_remove(L_, -2); // L_: proxy |
| 195 | return std::string_view{}; | 195 | STACK_CHECK(L_, 1); |
| 196 | return; | ||
| 196 | } else { | 197 | } else { |
| 197 | lua_pop(L_, 1); // L_: DPC | 198 | lua_pop(L_, 1); // L_: DPC |
| 198 | } | 199 | } |
| 200 | STACK_CHECK(L_, 1); | ||
| 199 | 201 | ||
| 200 | STACK_GROW(L_, 7); | 202 | STACK_GROW(L_, 7); |
| 201 | STACK_CHECK_START_REL(L_, 0); | ||
| 202 | 203 | ||
| 203 | // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) | 204 | // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) |
| 204 | DeepPrelude** const _proxy{ lua_newuserdatauv<DeepPrelude*>(L_, nuv_) }; // L_: DPC proxy | 205 | DeepPrelude** const _proxy{ lua_newuserdatauv<DeepPrelude*>(L_, nuv_) }; // L_: DPC proxy |
| @@ -219,9 +220,7 @@ std::string_view DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, | |||
| 219 | factory.createMetatable(L_); // L_: DPC proxy metatable | 220 | factory.createMetatable(L_); // L_: DPC proxy metatable |
| 220 | if (lua_gettop(L_) - _oldtop != 1 || !lua_istable(L_, -1)) { | 221 | if (lua_gettop(L_) - _oldtop != 1 || !lua_istable(L_, -1)) { |
| 221 | // factory didn't push exactly 1 value, or the value it pushed is not a table: ERROR! | 222 | // factory didn't push exactly 1 value, or the value it pushed is not a table: ERROR! |
| 222 | lua_settop(L_, _oldtop); // L_: DPC proxy X | 223 | raise_luaL_error(errL_, "Bad DeepFactory::createMetatable overload: unexpected pushed value"); |
| 223 | lua_pop(L_, 3); // L_: | ||
| 224 | return "Bad DeepFactory::createMetatable overload: unexpected pushed value"; | ||
| 225 | } | 224 | } |
| 226 | // if the metatable contains a __gc, we will call it from our own | 225 | // if the metatable contains a __gc, we will call it from our own |
| 227 | std::ignore = luaG_getfield(L_, -1, "__gc"); // L_: DPC proxy metatable __gc | 226 | std::ignore = luaG_getfield(L_, -1, "__gc"); // L_: DPC proxy metatable __gc |
| @@ -248,40 +247,42 @@ std::string_view DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, | |||
| 248 | // L.registry._LOADED exists without having registered the 'package' library. | 247 | // L.registry._LOADED exists without having registered the 'package' library. |
| 249 | lua_getglobal(L_, "require"); // L_: DPC proxy metatable require() | 248 | lua_getglobal(L_, "require"); // L_: DPC proxy metatable require() |
| 250 | // check that the module is already loaded (or being loaded, we are happy either way) | 249 | // check that the module is already loaded (or being loaded, we are happy either way) |
| 251 | if (lua_isfunction(L_, -1)) { | 250 | if (!lua_isfunction(L_, -1)) { // a module name, but no require() function :-( |
| 252 | std::ignore = lua_pushstringview(L_, _modname); // L_: DPC proxy metatable require() "module" | 251 | raise_luaL_error(errL_, "lanes receiving deep userdata should register the 'package' library"); |
| 253 | if (luaG_getfield(L_, LUA_REGISTRYINDEX, LUA_LOADED_TABLE) == LuaType::TABLE) { // L_: DPC proxy metatable require() "module" _R._LOADED | 252 | } |
| 254 | lua_pushvalue(L_, -2); // L_: DPC proxy metatable require() "module" _R._LOADED "module" | 253 | |
| 255 | lua_rawget(L_, -2); // L_: DPC proxy metatable require() "module" _R._LOADED module | 254 | std::ignore = lua_pushstringview(L_, _modname); // L_: DPC proxy metatable require() "module" |
| 256 | int const _alreadyloaded{ lua_toboolean(L_, -1) }; | 255 | if (luaG_getfield(L_, LUA_REGISTRYINDEX, LUA_LOADED_TABLE) != LuaType::TABLE) { // L_: DPC proxy metatable require() "module" _R._LOADED |
| 257 | if (!_alreadyloaded) { // not loaded | 256 | // no L.registry._LOADED; can this ever happen? |
| 258 | lua_pop(L_, 2); // L_: DPC proxy metatable require() "module" | 257 | lua_pop(L_, 6); // L_: |
| 259 | // require "modname" | 258 | raise_luaL_error(errL_, "unexpected error while requiring a module identified by DeepFactory::moduleName"); |
| 260 | LuaError const _require_result{ lua_pcall(L_, 1, 0, 0) }; // L_: DPC proxy metatable error? | 259 | } |
| 261 | if (_require_result != LuaError::OK) { | 260 | |
| 262 | // failed, return the error message | 261 | lua_pushvalue(L_, -2); // L_: DPC proxy metatable require() "module" _R._LOADED "module" |
| 263 | lua_pushfstring(L_, "error while requiring '" STRINGVIEW_FMT "' identified by DeepFactory::moduleName: ", _modname.size(), _modname.data()); | 262 | lua_rawget(L_, -2); // L_: DPC proxy metatable require() "module" _R._LOADED module |
| 264 | lua_insert(L_, -2); // L_: DPC proxy metatable prefix error | 263 | int const _alreadyloaded{ lua_toboolean(L_, -1) }; |
| 265 | lua_concat(L_, 2); // L_: DPC proxy metatable error | 264 | if (!_alreadyloaded) { // not loaded |
| 266 | return lua_tostringview(L_, -1); | 265 | lua_pop(L_, 2); // L_: DPC proxy metatable require() "module" |
| 267 | } | 266 | // require "modname". in case of error, raise it in errL_ |
| 268 | } else { // already loaded, we are happy | 267 | if (L_ == errL_) { |
| 269 | lua_pop(L_, 4); // L_: DPC proxy metatable | 268 | lua_call(L_, 1, 0); // L_: DPC proxy metatable module |
| 269 | } else { | ||
| 270 | LuaError const _require_result{ lua_pcall(L_, 1, 0, 0) }; // L_: DPC proxy metatable error? | ||
| 271 | if (_require_result != LuaError::OK) { | ||
| 272 | // failed, raise the error in the proper state | ||
| 273 | std::ignore = lua_pushstringview(errL_, lua_tostringview(L_, -1)); | ||
| 274 | raise_lua_error(errL_); | ||
| 270 | } | 275 | } |
| 271 | } else { // no L.registry._LOADED; can this ever happen? | ||
| 272 | lua_pop(L_, 6); // L_: | ||
| 273 | return std::string_view{ "unexpected error while requiring a module identified by DeepFactory::moduleName" }; | ||
| 274 | } | 276 | } |
| 275 | } else { // a module name, but no require() function :-( | 277 | } else { // already loaded, we are happy |
| 276 | lua_pop(L_, 4); // L_: | 278 | lua_pop(L_, 4); // L_: DPC proxy metatable |
| 277 | return std::string_view{ "lanes receiving deep userdata should register the 'package' library" }; | ||
| 278 | } | 279 | } |
| 279 | } | 280 | } |
| 280 | } | 281 | } |
| 281 | STACK_CHECK(L_, 2); // DPC proxy metatable | 282 | STACK_CHECK(L_, 3); // DPC proxy metatable |
| 282 | LUA_ASSERT(L_, lua_type_as_enum(L_, -2) == LuaType::USERDATA); | 283 | LUA_ASSERT(L_, lua_type_as_enum(L_, -2) == LuaType::USERDATA); |
| 283 | LUA_ASSERT(L_, lua_istable(L_, -1)); | 284 | LUA_ASSERT(L_, lua_istable(L_, -1)); |
| 284 | lua_setmetatable(L_, -2); // DPC proxy | 285 | lua_setmetatable(L_, -2); // DPC proxy |
| 285 | 286 | ||
| 286 | // If we're here, we obviously had to create a new proxy, so cache it. | 287 | // If we're here, we obviously had to create a new proxy, so cache it. |
| 287 | lua_pushlightuserdata(L_, prelude_); // L_: DPC proxy deep | 288 | lua_pushlightuserdata(L_, prelude_); // L_: DPC proxy deep |
| @@ -289,8 +290,7 @@ std::string_view DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, | |||
| 289 | lua_rawset(L_, -4); // L_: DPC proxy | 290 | lua_rawset(L_, -4); // L_: DPC proxy |
| 290 | lua_remove(L_, -2); // L_: proxy | 291 | lua_remove(L_, -2); // L_: proxy |
| 291 | LUA_ASSERT(L_, lua_type_as_enum(L_, -1) == LuaType::USERDATA); | 292 | LUA_ASSERT(L_, lua_type_as_enum(L_, -1) == LuaType::USERDATA); |
| 292 | STACK_CHECK(L_, 0); | 293 | STACK_CHECK(L_, 1); |
| 293 | return std::string_view{}; | ||
| 294 | } | 294 | } |
| 295 | 295 | ||
| 296 | // ################################################################################################# | 296 | // ################################################################################################# |
| @@ -335,10 +335,7 @@ int DeepFactory::pushDeepUserdata(DestState L_, int nuv_) const | |||
| 335 | raise_luaL_error(L_, "Bad DeepFactory::newDeepObjectInternal overload: should not push anything on the stack"); | 335 | raise_luaL_error(L_, "Bad DeepFactory::newDeepObjectInternal overload: should not push anything on the stack"); |
| 336 | } | 336 | } |
| 337 | 337 | ||
| 338 | std::string_view const _err{ DeepFactory::PushDeepProxy(L_, _prelude, nuv_, LookupMode::LaneBody) }; // proxy | 338 | DeepFactory::PushDeepProxy(L_, _prelude, nuv_, LookupMode::LaneBody, L_); // proxy |
| 339 | if (!_err.empty()) { | ||
| 340 | raise_luaL_error(L_, _err.data()); | ||
| 341 | } | ||
| 342 | STACK_CHECK(L_, 1); | 339 | STACK_CHECK(L_, 1); |
| 343 | return 1; | 340 | return 1; |
| 344 | } | 341 | } |
| @@ -75,7 +75,7 @@ class DeepFactory | |||
| 75 | [[nodiscard]] int pushDeepUserdata(DestState L_, int nuv_) const; | 75 | [[nodiscard]] int pushDeepUserdata(DestState L_, int nuv_) const; |
| 76 | [[nodiscard]] DeepPrelude* toDeep(lua_State* L_, int index_) const; | 76 | [[nodiscard]] DeepPrelude* toDeep(lua_State* L_, int index_) const; |
| 77 | static void DeleteDeepObject(lua_State* L_, DeepPrelude* o_); | 77 | static void DeleteDeepObject(lua_State* L_, DeepPrelude* o_); |
| 78 | [[nodiscard]] static std::string_view PushDeepProxy(DestState L_, DeepPrelude* o_, int nuv_, LookupMode mode_); | 78 | static void PushDeepProxy(DestState L_, DeepPrelude* o_, int nuv_, LookupMode mode_, lua_State* errL_); |
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | // ################################################################################################# | 81 | // ################################################################################################# |
diff --git a/src/intercopycontext.cpp b/src/intercopycontext.cpp index 978a69b..8058838 100644 --- a/src/intercopycontext.cpp +++ b/src/intercopycontext.cpp | |||
| @@ -731,7 +731,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
| 731 | STACK_CHECK_START_REL(L2, 0); | 731 | STACK_CHECK_START_REL(L2, 0); |
| 732 | 732 | ||
| 733 | // extract all uservalues of the source. unfortunately, the only way to know their count is to iterate until we fail | 733 | // extract all uservalues of the source. unfortunately, the only way to know their count is to iterate until we fail |
| 734 | int _nuv = 0; | 734 | int _nuv{ 0 }; |
| 735 | while (lua_getiuservalue(L1, L1_i, _nuv + 1) != LUA_TNONE) { // L1: ... u [uv]* nil | 735 | while (lua_getiuservalue(L1, L1_i, _nuv + 1) != LUA_TNONE) { // L1: ... u [uv]* nil |
| 736 | ++_nuv; | 736 | ++_nuv; |
| 737 | } | 737 | } |
| @@ -739,11 +739,8 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
| 739 | lua_pop(L1, 1); // L1: ... u [uv]* | 739 | lua_pop(L1, 1); // L1: ... u [uv]* |
| 740 | STACK_CHECK(L1, _nuv); | 740 | STACK_CHECK(L1, _nuv); |
| 741 | 741 | ||
| 742 | DeepPrelude* const u{ *lua_tofulluserdata<DeepPrelude*>(L1, L1_i) }; | 742 | DeepPrelude* const _u{ *lua_tofulluserdata<DeepPrelude*>(L1, L1_i) }; |
| 743 | std::string_view const errmsg{ DeepFactory::PushDeepProxy(L2, u, _nuv, mode) }; // L1: ... u [uv]* L2: u | 743 | DeepFactory::PushDeepProxy(L2, _u, _nuv, mode, getErrL()); // L1: ... u [uv]* L2: u |
| 744 | if (!errmsg.empty()) { | ||
| 745 | raise_luaL_error(getErrL(), errmsg.data()); | ||
| 746 | } | ||
| 747 | 744 | ||
| 748 | // transfer all uservalues of the source in the destination | 745 | // transfer all uservalues of the source in the destination |
| 749 | { | 746 | { |
diff --git a/src/lanes.cpp b/src/lanes.cpp index 109fba4..bd5f69e 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
| @@ -701,16 +701,8 @@ LUAG_FUNC(configure) | |||
| 701 | } | 701 | } |
| 702 | 702 | ||
| 703 | STACK_CHECK(L_, 2); | 703 | STACK_CHECK(L_, 2); |
| 704 | 704 | DeepFactory::PushDeepProxy(DestState{ L_ }, _U->timerLinda, 0, LookupMode::LaneBody, L_); // L_: settings M timerLinda | |
| 705 | { | 705 | lua_setfield(L_, -2, "timer_gateway"); // L_: settings M |
| 706 | std::string_view const _errmsg{ | ||
| 707 | DeepFactory::PushDeepProxy(DestState{ L_ }, _U->timerLinda, 0, LookupMode::LaneBody) | ||
| 708 | }; // L_: settings M timerLinda | ||
| 709 | if (!_errmsg.empty()) { | ||
| 710 | raise_luaL_error(L_, _errmsg.data()); | ||
| 711 | } | ||
| 712 | lua_setfield(L_, -2, "timer_gateway"); // L_: settings M | ||
| 713 | } | ||
| 714 | STACK_CHECK(L_, 2); | 706 | STACK_CHECK(L_, 2); |
| 715 | 707 | ||
| 716 | // prepare the metatable for threads | 708 | // prepare the metatable for threads |
