Don't hang on using luaToString on recursive data structures
parent
83550c1623
commit
ae20b81126
|
@ -50,4 +50,8 @@ Deno.test("Test Lua Rutime", async () => {
|
||||||
assertEquals(await luaToString([{ a: 1 }]), "{{a = 1}}");
|
assertEquals(await luaToString([{ a: 1 }]), "{{a = 1}}");
|
||||||
// Ensure simple cases are not returning promises
|
// Ensure simple cases are not returning promises
|
||||||
assertEquals(luaToString(10), "10");
|
assertEquals(luaToString(10), "10");
|
||||||
|
// Test circular references
|
||||||
|
const circular: any = {};
|
||||||
|
circular.self = circular;
|
||||||
|
assertEquals(await luaToString(circular), "{self = <circular reference>}");
|
||||||
});
|
});
|
||||||
|
|
|
@ -689,18 +689,29 @@ export function luaTruthy(value: any): boolean {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function luaToString(value: any): string | Promise<string> {
|
export function luaToString(
|
||||||
|
value: any,
|
||||||
|
visited: Set<any> = new Set(),
|
||||||
|
): string | Promise<string> {
|
||||||
if (value === null || value === undefined) {
|
if (value === null || value === undefined) {
|
||||||
return "nil";
|
return "nil";
|
||||||
}
|
}
|
||||||
if (value instanceof Promise) {
|
if (value instanceof Promise) {
|
||||||
return value.then(luaToString);
|
return value.then((v) => luaToString(v, visited));
|
||||||
|
}
|
||||||
|
// Check for circular references
|
||||||
|
if (typeof value === "object" && visited.has(value)) {
|
||||||
|
return "<circular reference>";
|
||||||
}
|
}
|
||||||
if (value.toStringAsync) {
|
if (value.toStringAsync) {
|
||||||
|
// Add to visited before recursing
|
||||||
|
visited.add(value);
|
||||||
return value.toStringAsync();
|
return value.toStringAsync();
|
||||||
}
|
}
|
||||||
// Handle plain JavaScript objects in a Lua-like format
|
// Handle plain JavaScript objects in a Lua-like format
|
||||||
if (typeof value === "object") {
|
if (typeof value === "object") {
|
||||||
|
// Add to visited before recursing
|
||||||
|
visited.add(value);
|
||||||
return (async () => {
|
return (async () => {
|
||||||
let result = "{";
|
let result = "{";
|
||||||
let first = true;
|
let first = true;
|
||||||
|
@ -713,8 +724,8 @@ export function luaToString(value: any): string | Promise<string> {
|
||||||
} else {
|
} else {
|
||||||
result += ", ";
|
result += ", ";
|
||||||
}
|
}
|
||||||
// Recursively stringify the value
|
// Recursively stringify the value, passing the visited set
|
||||||
const strVal = await luaToString(val);
|
const strVal = await luaToString(val, visited);
|
||||||
result += strVal;
|
result += strVal;
|
||||||
}
|
}
|
||||||
return result + "}";
|
return result + "}";
|
||||||
|
@ -732,8 +743,8 @@ export function luaToString(value: any): string | Promise<string> {
|
||||||
} else {
|
} else {
|
||||||
result += `["${key}"] = `;
|
result += `["${key}"] = `;
|
||||||
}
|
}
|
||||||
// Recursively stringify the value
|
// Recursively stringify the value, passing the visited set
|
||||||
const strVal = await luaToString(val);
|
const strVal = await luaToString(val, visited);
|
||||||
result += strVal;
|
result += strVal;
|
||||||
}
|
}
|
||||||
result += "}";
|
result += "}";
|
||||||
|
|
Loading…
Reference in New Issue