| 7 | export type TableType = Record<any, any> | any[] |
| 8 | |
| 9 | class TableTypeExtension extends TypeExtension<TableType> { |
| 10 | public constructor(thread: Global) { |
| 11 | super(thread, 'js_table') |
| 12 | } |
| 13 | |
| 14 | public close(): void { |
| 15 | // Nothing to do |
| 16 | } |
| 17 | |
| 18 | public isType(_thread: Thread, _index: number, type: LuaType): boolean { |
| 19 | return type === LuaType.Table |
| 20 | } |
| 21 | |
| 22 | public getValue(thread: Thread, index: number, userdata?: any): TableType { |
| 23 | // This is a map of Lua pointers to JS objects. |
| 24 | const seenMap: Map<number, TableType> = userdata || new Map() |
| 25 | const pointer = thread.lua.lua_topointer(thread.address, index) |
| 26 | |
| 27 | let table = seenMap.get(pointer) |
| 28 | if (!table) { |
| 29 | const keys = this.readTableKeys(thread, index) |
| 30 | |
| 31 | const isSequential = keys.length > 0 && keys.every((key, index) => key === String(index + 1)) |
| 32 | table = isSequential ? [] : {} |
| 33 | |
| 34 | seenMap.set(pointer, table) |
| 35 | this.readTableValues(thread, index, seenMap, table) |
| 36 | } |
| 37 | |
| 38 | return table |
| 39 | } |
| 40 | |
| 41 | public pushValue(thread: Thread, { target }: Decoration<TableType>, userdata?: Map<any, number>): boolean { |
| 42 | if (typeof target !== 'object' || target === null) { |
| 43 | return false |
| 44 | } |
| 45 | |
| 46 | // This is a map of JS objects to luaL references. |
| 47 | const seenMap = userdata || new Map<any, number>() |
| 48 | const existingReference = seenMap.get(target) |
| 49 | if (existingReference !== undefined) { |
| 50 | thread.lua.lua_rawgeti(thread.address, LUA_REGISTRYINDEX, BigInt(existingReference)) |
| 51 | return true |
| 52 | } |
| 53 | |
| 54 | try { |
| 55 | const tableIndex = thread.getTop() + 1 |
| 56 | |
| 57 | const createTable = (arrayCount: number, keyCount: number): void => { |
| 58 | thread.lua.lua_createtable(thread.address, arrayCount, keyCount) |
| 59 | const ref = thread.lua.luaL_ref(thread.address, LUA_REGISTRYINDEX) |
| 60 | seenMap.set(target, ref) |
| 61 | thread.lua.lua_rawgeti(thread.address, LUA_REGISTRYINDEX, BigInt(ref)) |
| 62 | } |
| 63 | |
| 64 | if (Array.isArray(target)) { |
| 65 | createTable(target.length, 0) |
| 66 |
nothing calls this directly
no outgoing calls
no test coverage detected