Skip to content

Commit cf56679

Browse files
committed
util: fix a crash & fix FancyJSONToTable not being removed on shutdown
1 parent 7b7056a commit cf56679

File tree

3 files changed

+108
-9
lines changed

3 files changed

+108
-9
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
return {
2+
groupName = "util.FancyJSONToTable",
3+
cases = {
4+
{
5+
name = "Function exists on meta table",
6+
when = HolyLib_IsModuleEnabled("util"),
7+
func = function()
8+
expect( util.FancyJSONToTable ).to.beA( "function" )
9+
end
10+
},
11+
{
12+
name = "Metatable doesn't exist",
13+
when = not HolyLib_IsModuleEnabled("util"),
14+
func = function()
15+
expect( util.FancyJSONToTable ).to.beA( "nil" ) -- util table always exists since its created by gmod
16+
end
17+
},
18+
{ -- This one is a former crash: https://github.com/RaphaelIT7/gmod-holylib/issues/101
19+
name = "Returns a proper result",
20+
when = HolyLib_IsModuleEnabled("util"),
21+
func = function()
22+
local expectedTable = {
23+
{
24+
[1] = 1,
25+
[2] = 2,
26+
[3] = 3,
27+
}
28+
}
29+
30+
local actualTable = util.FancyJSONToTable( "[[1, 2, 3]]" )
31+
32+
expect( actualTable ).to.deepEqual( expectedTable )
33+
end
34+
},
35+
{
36+
name = "Performance",
37+
when = HolyLib_IsModuleEnabled("util"),
38+
func = function()
39+
HolyLib_RunPerformanceTest("util.FancyJSONToTable", util.FancyJSONToTable, "[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [\"Hello World\", \"World2\", \"World3\"]]")
40+
end
41+
},
42+
}
43+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
return {
2+
groupName = "util.FancyTableToJSON",
3+
cases = {
4+
{
5+
name = "Function exists on meta table",
6+
when = HolyLib_IsModuleEnabled("util"),
7+
func = function()
8+
expect( util.FancyTableToJSON ).to.beA( "function" )
9+
end
10+
},
11+
{
12+
name = "Metatable doesn't exist",
13+
when = not HolyLib_IsModuleEnabled("util"),
14+
func = function()
15+
expect( util.FancyTableToJSON ).to.beA( "nil" ) -- util table always exists since its created by gmod
16+
end
17+
},
18+
{
19+
name = "Returns a proper result",
20+
when = HolyLib_IsModuleEnabled("util"),
21+
func = function()
22+
local tab = {
23+
[1] = 1,
24+
[2] = 2,
25+
[3] = 3,
26+
["Test"] = "Hello World", -- Stuff like that once crashed:
27+
[4] = 4,
28+
[5] = 5,
29+
[6] = {
30+
[1] = Vector(1, 2, 3),
31+
[2] = Vector(4, 5, 6),
32+
[3] = Vector(7, 8, 9),
33+
},
34+
[7] = math.huge,
35+
}
36+
37+
local actualTable = util.FancyJSONToTable( "[[1, 2, 3]]" )
38+
39+
expect( actualTable ).to.equal( "{\"1\":1,\"2\":2,\"3\":3,\"4\":4,\"5\":5,\"6\":[\"[1 2 3]\",\"[4 5 6]\",\"[7 8 9]\"],\"7\":,\"Test\":\"Hello World\"" )
40+
end
41+
},
42+
{
43+
name = "Performance",
44+
when = HolyLib_IsModuleEnabled("util"),
45+
func = function()
46+
HolyLib_RunPerformanceTest("util.FancyTableToJSON", util.FancyTableToJSON, _G)
47+
end
48+
},
49+
}
50+
}

source/modules/util.cpp

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ void TableToJSONRecursive(GarrysMod::Lua::ILuaInterface* pLua, LuaUtilModuleData
291291
//}
292292

293293
while (pLua->Next(-2)) {
294-
// In bootil, you just don't give a child a name to indicate that it's sequentail.
294+
// In bootil, you just don't give a child a name to indicate that it's sequential.
295295
// so we need to support that.
296296
bool isSequential = false;
297297
int iKeyType = pLua->GetType(-2);
@@ -340,10 +340,14 @@ void TableToJSONRecursive(GarrysMod::Lua::ILuaInterface* pLua, LuaUtilModuleData
340340
case GarrysMod::Lua::Type::Number:
341341
{
342342
double pNumber = pLua->GetNumber(-1);
343-
if (IsInt(pNumber))
344-
value.SetInt(pNumber);
345-
else
346-
value.SetDouble(pNumber);
343+
if (isfinite(pNumber)) { // Needed for math.huge
344+
if (IsInt(pNumber))
345+
value.SetInt(pNumber);
346+
else
347+
value.SetDouble(pNumber);
348+
} else {
349+
value.SetNull();
350+
}
347351
}
348352
break;
349353
case GarrysMod::Lua::Type::Bool:
@@ -483,6 +487,9 @@ void PushJSONValue(GarrysMod::Lua::ILuaInterface* pLua, const rapidjson::Value&
483487
void JSONToTableRecursive(GarrysMod::Lua::ILuaInterface* pLua, const rapidjson::Value& jsonValue, bool noSet)
484488
{
485489
if (jsonValue.IsObject()) {
490+
if (!noSet)
491+
pLua->PreCreateTable(0, jsonValue.MemberCount());
492+
486493
for (rapidjson::Value::ConstMemberIterator itr = jsonValue.MemberBegin(); itr != jsonValue.MemberEnd(); ++itr) {
487494
const rapidjson::Value& value = itr->value;
488495

@@ -500,12 +507,11 @@ void JSONToTableRecursive(GarrysMod::Lua::ILuaInterface* pLua, const rapidjson::
500507
PushJSONValue(pLua, itr->value);
501508

502509
if (!noSet)
503-
{
504510
pLua->SetTable(-3);
505-
}
506511
}
507512
} else if (jsonValue.IsArray()) {
508513
int idx = 0;
514+
pLua->PreCreateTable(jsonValue.Size(), 0);
509515
for (rapidjson::SizeType i = 0; i < jsonValue.Size(); ++i)
510516
{
511517
JSONToTableRecursive(pLua, jsonValue[i], true);
@@ -528,7 +534,6 @@ LUA_FUNCTION_STATIC(util_JSONToTable)
528534
return 0;
529535
}
530536

531-
LUA->CreateTable();
532537
JSONToTableRecursive(LUA, doc);
533538
return 1;
534539
}
@@ -790,10 +795,11 @@ void CUtilModule::LuaShutdown(GarrysMod::Lua::ILuaInterface* pLua)
790795
Util::RemoveField(pLua, "AsyncCompress");
791796
Util::RemoveField(pLua, "AsyncDecompress");
792797
Util::RemoveField(pLua, "FancyTableToJSON");
798+
Util::RemoveField(pLua, "FancyJSONToTable");
793799
Util::RemoveField(pLua, "CompressLZ4");
794800
Util::RemoveField(pLua, "DecompressLZ4");
795801
Util::RemoveField(pLua, "AsyncTableToJSON");
796-
Util::RemoveField(pLua, "AsyncJSONToTable");
802+
// Util::RemoveField(pLua, "AsyncJSONToTable");
797803
Util::PopTable(pLua);
798804
}
799805
}

0 commit comments

Comments
 (0)