MCPcopy Create free account
hub / github.com/ceifa/wasmoon / FunctionTypeExtension

Class FunctionTypeExtension

src/type-extensions/function.ts:25–235  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

23}
24
25class FunctionTypeExtension extends TypeExtension<FunctionType, FunctionDecoration> {
26 private readonly functionRegistry =
27 typeof FinalizationRegistry !== 'undefined'
28 ? new FinalizationRegistry((func: number) => {
29 if (!this.thread.isClosed()) {
30 this.thread.lua.luaL_unref(this.thread.address, LUA_REGISTRYINDEX, func)
31 }
32 })
33 : undefined
34
35 private gcPointer: number
36 private functionWrapper: number
37 private callbackContext: Thread
38 private callbackContextIndex: number
39 private options?: FunctionTypeExtensionOptions
40
41 public constructor(thread: Global, options?: FunctionTypeExtensionOptions) {
42 super(thread, 'js_function')
43
44 this.options = options
45 // Create a thread off of the global thread to be used to create function call threads without
46 // interfering with the global context. This creates a callback context that will always exist
47 // even if the thread that called getValue() has been destroyed.
48 this.callbackContext = thread.newThread()
49 // Pops it from the global stack but keeps it alive
50 this.callbackContextIndex = this.thread.lua.luaL_ref(thread.address, LUA_REGISTRYINDEX)
51
52 if (!this.functionRegistry) {
53 console.warn('FunctionTypeExtension: FinalizationRegistry not found. Memory leaks likely.')
54 }
55
56 this.gcPointer = thread.lua.module.addFunction((calledL: LuaState) => {
57 // Throws a lua error which does a jump if it does not match.
58 thread.lua.luaL_checkudata(calledL, 1, this.name)
59
60 const userDataPointer = thread.lua.luaL_checkudata(calledL, 1, this.name)
61 const referencePointer = thread.lua.module.getValue(userDataPointer, '*')
62 thread.lua.unref(referencePointer)
63
64 return LuaReturn.Ok
65 }, 'ii')
66
67 // Creates metatable if it doesn't exist, always pushes it onto the stack.
68 if (thread.lua.luaL_newmetatable(thread.address, this.name)) {
69 thread.lua.lua_pushstring(thread.address, '__gc')
70 thread.lua.lua_pushcclosure(thread.address, this.gcPointer, 0)
71 thread.lua.lua_settable(thread.address, -3)
72
73 thread.lua.lua_pushstring(thread.address, '__metatable')
74 thread.lua.lua_pushstring(thread.address, 'protected metatable')
75 thread.lua.lua_settable(thread.address, -3)
76 }
77 // Pop the metatable from the stack.
78 thread.lua.lua_pop(thread.address, 1)
79
80 this.functionWrapper = thread.lua.module.addFunction((calledL: LuaState) => {
81 const calledThread = thread.stateToThread(calledL)
82

Callers

nothing calls this directly

Calls 1

isClosedMethod · 0.80

Tested by

no test coverage detected