diff options
-rw-r--r-- | deep_test/deeptest.lua | 5 | ||||
-rw-r--r-- | src/deep.cpp | 16 | ||||
-rw-r--r-- | src/tools.cpp | 31 | ||||
-rw-r--r-- | src/tools.h | 4 |
4 files changed, 29 insertions, 27 deletions
diff --git a/deep_test/deeptest.lua b/deep_test/deeptest.lua index 33de003..09b638c 100644 --- a/deep_test/deeptest.lua +++ b/deep_test/deeptest.lua | |||
@@ -7,7 +7,7 @@ local dt = lanes.require "deep_test" | |||
7 | local test_deep = true | 7 | local test_deep = true |
8 | local test_clonable = true | 8 | local test_clonable = true |
9 | local test_uvtype = "string" | 9 | local test_uvtype = "string" |
10 | local nupvals = _VERSION == "Lua 5.4" and 2 or 1 | 10 | local nupvals = _VERSION == "Lua 5.4" and 3 or 1 |
11 | 11 | ||
12 | local makeUserValue = function( obj_) | 12 | local makeUserValue = function( obj_) |
13 | if test_uvtype == "string" then | 13 | if test_uvtype == "string" then |
@@ -43,7 +43,8 @@ local performTest = function( obj_) | |||
43 | obj_:setuv( 1, makeUserValue( obj_)) | 43 | obj_:setuv( 1, makeUserValue( obj_)) |
44 | -- lua 5.4 supports multiple uservalues of arbitrary types | 44 | -- lua 5.4 supports multiple uservalues of arbitrary types |
45 | if nupvals > 1 then | 45 | if nupvals > 1 then |
46 | obj_:setuv( 2, "ENDUV") | 46 | -- keep uv #2 as nil |
47 | obj_:setuv( 3, "ENDUV") | ||
47 | end | 48 | end |
48 | 49 | ||
49 | local t = | 50 | local t = |
diff --git a/src/deep.cpp b/src/deep.cpp index a824f72..735a14c 100644 --- a/src/deep.cpp +++ b/src/deep.cpp | |||
@@ -381,7 +381,7 @@ DeepPrelude* DeepFactory::toDeep(lua_State* L_, int index_) const | |||
381 | STACK_CHECK_START_REL(L1, 0); | 381 | STACK_CHECK_START_REL(L1, 0); |
382 | STACK_CHECK_START_REL(L2, 0); | 382 | STACK_CHECK_START_REL(L2, 0); |
383 | 383 | ||
384 | // extract all uservalues of the source | 384 | // extract all uservalues of the source. unfortunately, the only way to know their count is to iterate until we fail |
385 | int nuv = 0; | 385 | int nuv = 0; |
386 | while (lua_getiuservalue(L1, L1_i, nuv + 1) != LUA_TNONE) { // L1: ... u [uv]* nil | 386 | while (lua_getiuservalue(L1, L1_i, nuv + 1) != LUA_TNONE) { // L1: ... u [uv]* nil |
387 | ++nuv; | 387 | ++nuv; |
@@ -391,7 +391,10 @@ DeepPrelude* DeepFactory::toDeep(lua_State* L_, int index_) const | |||
391 | STACK_CHECK(L1, nuv); | 391 | STACK_CHECK(L1, nuv); |
392 | 392 | ||
393 | DeepPrelude* const u{ *lua_tofulluserdata<DeepPrelude*>(L1, L1_i) }; | 393 | DeepPrelude* const u{ *lua_tofulluserdata<DeepPrelude*>(L1, L1_i) }; |
394 | char const* errmsg{ DeepFactory::PushDeepProxy(L2, u, nuv, mode) }; // L2: u | 394 | char const* errmsg{ DeepFactory::PushDeepProxy(L2, u, nuv, mode) }; // L1: ... u [uv]* L2: u |
395 | if (errmsg != nullptr) { | ||
396 | raise_luaL_error(getErrL(), errmsg); | ||
397 | } | ||
395 | 398 | ||
396 | // transfer all uservalues of the source in the destination | 399 | // transfer all uservalues of the source in the destination |
397 | { | 400 | { |
@@ -399,8 +402,8 @@ DeepPrelude* DeepFactory::toDeep(lua_State* L_, int index_) const | |||
399 | int const clone_i{ lua_gettop(L2) }; | 402 | int const clone_i{ lua_gettop(L2) }; |
400 | while (nuv) { | 403 | while (nuv) { |
401 | c.L1_i = SourceIndex{ lua_absindex(L1, -1) }; | 404 | c.L1_i = SourceIndex{ lua_absindex(L1, -1) }; |
402 | if (!c.inter_copy_one()) { // L2: u uv | 405 | if (!c.inter_copy_one()) { // L1: ... u [uv]* L2: u uv |
403 | raise_luaL_error(L1, "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); | 406 | raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); |
404 | } | 407 | } |
405 | lua_pop(L1, 1); // L1: ... u [uv]* | 408 | lua_pop(L1, 1); // L1: ... u [uv]* |
406 | // this pops the value from the stack | 409 | // this pops the value from the stack |
@@ -412,10 +415,5 @@ DeepPrelude* DeepFactory::toDeep(lua_State* L_, int index_) const | |||
412 | STACK_CHECK(L2, 1); | 415 | STACK_CHECK(L2, 1); |
413 | STACK_CHECK(L1, 0); | 416 | STACK_CHECK(L1, 0); |
414 | 417 | ||
415 | if (errmsg != nullptr) { | ||
416 | // raise the error in the proper state (not the keeper) | ||
417 | lua_State* const errL{ (mode == LookupMode::FromKeeper) ? L2 : L1 }; | ||
418 | raise_luaL_error(errL, errmsg); | ||
419 | } | ||
420 | return true; | 418 | return true; |
421 | } \ No newline at end of file | 419 | } \ No newline at end of file |
diff --git a/src/tools.cpp b/src/tools.cpp index 0495561..a55ee75 100644 --- a/src/tools.cpp +++ b/src/tools.cpp | |||
@@ -616,7 +616,7 @@ static constexpr RegistryUniqueKey kMtIdRegKey{ 0xA8895DCF4EC3FE3Cull }; | |||
616 | STACK_GROW(L2, 3); // up to 3 slots are necessary on error | 616 | STACK_GROW(L2, 3); // up to 3 slots are necessary on error |
617 | switch (mode) { | 617 | switch (mode) { |
618 | default: // shouldn't happen, in theory... | 618 | default: // shouldn't happen, in theory... |
619 | raise_luaL_error(L1, "internal error: unknown lookup mode"); | 619 | raise_luaL_error(getErrL(), "internal error: unknown lookup mode"); |
620 | break; | 620 | break; |
621 | 621 | ||
622 | case LookupMode::ToKeeper: | 622 | case LookupMode::ToKeeper: |
@@ -646,9 +646,8 @@ static constexpr RegistryUniqueKey kMtIdRegKey{ 0xA8895DCF4EC3FE3Cull }; | |||
646 | lua_getglobal(L2, "decoda_name"); // L1: ... t ... L2: {} t decoda_name | 646 | lua_getglobal(L2, "decoda_name"); // L1: ... t ... L2: {} t decoda_name |
647 | to = lua_tostring(L2, -1); | 647 | to = lua_tostring(L2, -1); |
648 | lua_pop(L2, 1); // L1: ... t ... L2: {} t | 648 | lua_pop(L2, 1); // L1: ... t ... L2: {} t |
649 | // when mode_ == LookupMode::FromKeeper, L1 is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error | ||
650 | raise_luaL_error( | 649 | raise_luaL_error( |
651 | (mode == LookupMode::FromKeeper) ? L2 : L1, | 650 | getErrL(), |
652 | "INTERNAL ERROR IN %s: table '%s' not found in %s destination transfer database.", | 651 | "INTERNAL ERROR IN %s: table '%s' not found in %s destination transfer database.", |
653 | from ? from : "main", | 652 | from ? from : "main", |
654 | fqn, | 653 | fqn, |
@@ -889,7 +888,7 @@ void InterCopyContext::lookup_native_func() const | |||
889 | STACK_GROW(L2, 3); // up to 3 slots are necessary on error | 888 | STACK_GROW(L2, 3); // up to 3 slots are necessary on error |
890 | switch (mode) { | 889 | switch (mode) { |
891 | default: // shouldn't happen, in theory... | 890 | default: // shouldn't happen, in theory... |
892 | raise_luaL_error(L1, "internal error: unknown lookup mode"); | 891 | raise_luaL_error(getErrL(), "internal error: unknown lookup mode"); |
893 | break; | 892 | break; |
894 | 893 | ||
895 | case LookupMode::ToKeeper: | 894 | case LookupMode::ToKeeper: |
@@ -916,7 +915,7 @@ void InterCopyContext::lookup_native_func() const | |||
916 | lua_pop(L2, 1); // L2: {} f | 915 | lua_pop(L2, 1); // L2: {} f |
917 | // when mode_ == LookupMode::FromKeeper, L is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error | 916 | // when mode_ == LookupMode::FromKeeper, L is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error |
918 | raise_luaL_error( | 917 | raise_luaL_error( |
919 | (mode == LookupMode::FromKeeper) ? L2 : L1 | 918 | getErrL() |
920 | , "%s%s: function '%s' not found in %s destination transfer database." | 919 | , "%s%s: function '%s' not found in %s destination transfer database." |
921 | , lua_isnil(L2, -1) ? "" : "INTERNAL ERROR IN " | 920 | , lua_isnil(L2, -1) ? "" : "INTERNAL ERROR IN " |
922 | , from ? from : "main" | 921 | , from ? from : "main" |
@@ -1010,7 +1009,7 @@ void InterCopyContext::copy_func() const | |||
1010 | luaL_Buffer B; | 1009 | luaL_Buffer B; |
1011 | B.L = nullptr; | 1010 | B.L = nullptr; |
1012 | if (lua504_dump(L1, buf_writer, &B, 0) != 0) { | 1011 | if (lua504_dump(L1, buf_writer, &B, 0) != 0) { |
1013 | raise_luaL_error(L1, "internal error: function dump failed."); | 1012 | raise_luaL_error(getErrL(), "internal error: function dump failed."); |
1014 | } | 1013 | } |
1015 | 1014 | ||
1016 | // pushes dumped string on 'L1' | 1015 | // pushes dumped string on 'L1' |
@@ -1054,7 +1053,7 @@ void InterCopyContext::copy_func() const | |||
1054 | // "Otherwise, it pushes an error message" | 1053 | // "Otherwise, it pushes an error message" |
1055 | // | 1054 | // |
1056 | STACK_GROW(L1, 1); | 1055 | STACK_GROW(L1, 1); |
1057 | raise_luaL_error(L1, "%s: %s", fname, lua_tostring(L2, -1)); | 1056 | raise_luaL_error(getErrL(), "%s: %s", fname, lua_tostring(L2, -1)); |
1058 | } | 1057 | } |
1059 | // remove the dumped string | 1058 | // remove the dumped string |
1060 | lua_pop(L1, 1); // ... | 1059 | lua_pop(L1, 1); // ... |
@@ -1094,7 +1093,7 @@ void InterCopyContext::copy_func() const | |||
1094 | DEBUGSPEW_CODE(fprintf(stderr, "copying value\n")); | 1093 | DEBUGSPEW_CODE(fprintf(stderr, "copying value\n")); |
1095 | c.L1_i = SourceIndex{ lua_gettop(L1) }; | 1094 | c.L1_i = SourceIndex{ lua_gettop(L1) }; |
1096 | if (!c.inter_copy_one()) { // L2: ... {cache} ... function <upvalues> | 1095 | if (!c.inter_copy_one()) { // L2: ... {cache} ... function <upvalues> |
1097 | raise_luaL_error(L1, "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); | 1096 | raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); |
1098 | } | 1097 | } |
1099 | } | 1098 | } |
1100 | lua_pop(L1, 1); // L1: ... _G | 1099 | lua_pop(L1, 1); // L1: ... _G |
@@ -1196,7 +1195,7 @@ void InterCopyContext::copy_cached_func() const | |||
1196 | lua_pop(L2, 1); // L2: _R[kMtIdRegKey] | 1195 | lua_pop(L2, 1); // L2: _R[kMtIdRegKey] |
1197 | InterCopyContext const c{ U, L2, L1, L2_cache_i, SourceIndex{ lua_gettop(L1) }, VT::METATABLE, mode, name }; | 1196 | InterCopyContext const c{ U, L2, L1, L2_cache_i, SourceIndex{ lua_gettop(L1) }, VT::METATABLE, mode, name }; |
1198 | if (!c.inter_copy_one()) { // L2: _R[kMtIdRegKey] mt? | 1197 | if (!c.inter_copy_one()) { // L2: _R[kMtIdRegKey] mt? |
1199 | raise_luaL_error(L1, "Error copying a metatable"); | 1198 | raise_luaL_error(getErrL(), "Error copying a metatable"); |
1200 | } | 1199 | } |
1201 | 1200 | ||
1202 | STACK_CHECK(L2, 2); // L2: _R[kMtIdRegKey] mt | 1201 | STACK_CHECK(L2, 2); // L2: _R[kMtIdRegKey] mt |
@@ -1275,7 +1274,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
1275 | LUA_ASSERT(L1, lua_istable(L2, -3)); | 1274 | LUA_ASSERT(L1, lua_istable(L2, -3)); |
1276 | lua_rawset(L2, -3); // add to table (pops key & val) | 1275 | lua_rawset(L2, -3); // add to table (pops key & val) |
1277 | } else { | 1276 | } else { |
1278 | raise_luaL_error(L1, "Unable to copy %s entry '%s' because of value is of type '%s'", (vt == VT::NORMAL) ? "table" : "metatable", valPath, luaL_typename(L1, val_i)); | 1277 | raise_luaL_error(getErrL(), "Unable to copy %s entry '%s' because of value is of type '%s'", (vt == VT::NORMAL) ? "table" : "metatable", valPath, luaL_typename(L1, val_i)); |
1279 | } | 1278 | } |
1280 | } | 1279 | } |
1281 | 1280 | ||
@@ -1342,7 +1341,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
1342 | } | 1341 | } |
1343 | STACK_CHECK(L2, 1); | 1342 | STACK_CHECK(L2, 1); |
1344 | } else { | 1343 | } else { |
1345 | raise_luaL_error(L1, "Error copying a metatable"); | 1344 | raise_luaL_error(getErrL(), "Error copying a metatable"); |
1346 | } | 1345 | } |
1347 | // first, add the entry in the cache (at this point it is either the actual userdata or the keeper sentinel | 1346 | // first, add the entry in the cache (at this point it is either the actual userdata or the keeper sentinel |
1348 | lua_pushlightuserdata(L2, source); // L2: ... u source | 1347 | lua_pushlightuserdata(L2, source); // L2: ... u source |
@@ -1356,7 +1355,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
1356 | while (uvi > 0) { | 1355 | while (uvi > 0) { |
1357 | c.L1_i = SourceIndex{ lua_absindex(L1, -1) }; | 1356 | c.L1_i = SourceIndex{ lua_absindex(L1, -1) }; |
1358 | if (!c.inter_copy_one()) { // L2: ... u uv | 1357 | if (!c.inter_copy_one()) { // L2: ... u uv |
1359 | raise_luaL_error(L1, "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); | 1358 | raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); |
1360 | } | 1359 | } |
1361 | lua_pop(L1, 1); // L1: ... mt __lanesclone [uv]* | 1360 | lua_pop(L1, 1); // L1: ... mt __lanesclone [uv]* |
1362 | // this pops the value from the stack | 1361 | // this pops the value from the stack |
@@ -1419,7 +1418,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
1419 | void* const lud{ lua_touserdata(L1, L1_i) }; | 1418 | void* const lud{ lua_touserdata(L1, L1_i) }; |
1420 | lua_pushlightuserdata(L2, lud); | 1419 | lua_pushlightuserdata(L2, lud); |
1421 | } else { // raise an error | 1420 | } else { // raise an error |
1422 | raise_luaL_error(L1, "can't copy non-deep full userdata across lanes"); | 1421 | raise_luaL_error(getErrL(), "can't copy non-deep full userdata across lanes"); |
1423 | } | 1422 | } |
1424 | 1423 | ||
1425 | STACK_CHECK(L2, 1); | 1424 | STACK_CHECK(L2, 1); |
@@ -1489,7 +1488,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
1489 | while (uvi > 0) { | 1488 | while (uvi > 0) { |
1490 | c.L1_i = SourceIndex{ lua_absindex(L1, -1) }; | 1489 | c.L1_i = SourceIndex{ lua_absindex(L1, -1) }; |
1491 | if (!c.inter_copy_one()) { // L2: ... mt u uv | 1490 | if (!c.inter_copy_one()) { // L2: ... mt u uv |
1492 | raise_luaL_error(L1, "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); | 1491 | raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); |
1493 | } | 1492 | } |
1494 | lua_pop(L1, 1); // L1: ... u [uv]* | 1493 | lua_pop(L1, 1); // L1: ... u [uv]* |
1495 | // this pops the value from the stack | 1494 | // this pops the value from the stack |
@@ -1827,7 +1826,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
1827 | STACK_CHECK(L1, 1); | 1826 | STACK_CHECK(L1, 1); |
1828 | // raise the error when copying from lane to lane, else just leave it on the stack to be raised later | 1827 | // raise the error when copying from lane to lane, else just leave it on the stack to be raised later |
1829 | if (mode == LookupMode::LaneBody) { | 1828 | if (mode == LookupMode::LaneBody) { |
1830 | raise_lua_error(L1); | 1829 | raise_lua_error(getErrL()); |
1831 | } | 1830 | } |
1832 | return InterCopyResult::Error; | 1831 | return InterCopyResult::Error; |
1833 | } | 1832 | } |
@@ -1864,7 +1863,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
1864 | lua_pushfstring(L1, "failed to copy package entry %s", entry); | 1863 | lua_pushfstring(L1, "failed to copy package entry %s", entry); |
1865 | // raise the error when copying from lane to lane, else just leave it on the stack to be raised later | 1864 | // raise the error when copying from lane to lane, else just leave it on the stack to be raised later |
1866 | if (mode == LookupMode::LaneBody) { | 1865 | if (mode == LookupMode::LaneBody) { |
1867 | raise_lua_error(L1); | 1866 | raise_lua_error(getErrL()); |
1868 | } | 1867 | } |
1869 | lua_pop(L1, 1); | 1868 | lua_pop(L1, 1); |
1870 | break; | 1869 | break; |
diff --git a/src/tools.h b/src/tools.h index f5fdabc..9d4ed4c 100644 --- a/src/tools.h +++ b/src/tools.h | |||
@@ -42,6 +42,10 @@ class InterCopyContext | |||
42 | char const* name; // that one can change when we reuse the context | 42 | char const* name; // that one can change when we reuse the context |
43 | 43 | ||
44 | private: | 44 | private: |
45 | // when mode == LookupMode::FromKeeper, L1 is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error | ||
46 | // whon mode != LookupMode::FromKeeper, L1 is not a keeper state, therefore L1 is the state where we want to raise the error | ||
47 | lua_State* getErrL() const { return (mode == LookupMode::FromKeeper) ? L2 : L1; } | ||
48 | |||
45 | // for use in copy_cached_func | 49 | // for use in copy_cached_func |
46 | void copy_func() const; | 50 | void copy_func() const; |
47 | void lookup_native_func() const; | 51 | void lookup_native_func() const; |