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

Method jsFunc

src/type-extensions/function.ts:182–229  ·  view source on GitHub ↗
(...args: any[])

Source from the content-addressed store, hash-verified

180 const func = thread.lua.luaL_ref(thread.address, LUA_REGISTRYINDEX)
181
182 const jsFunc = (...args: any[]): any => {
183 // Calling a function would ideally be in the Lua context that's calling it. For example if the JS function
184 // setInterval were exposed to Lua then the calling thread would be created in that Lua context for executing
185 // the function call back to Lua through JS. However, if getValue were called in a thread, the thread then
186 // destroyed, and then this JS func were called it would be calling from a dead context. That means the safest
187 // thing to do is to have a thread you know will always exist.
188 if (this.callbackContext.isClosed()) {
189 console.warn('Tried to call a function after closing lua state')
190 return
191 }
192
193 // Function calls back to value should always be within a new thread because
194 // they can be left in inconsistent states.
195 const callThread = this.callbackContext.newThread()
196 try {
197 const internalType = callThread.lua.lua_rawgeti(callThread.address, LUA_REGISTRYINDEX, BigInt(func))
198 if (internalType !== LuaType.Function) {
199 const callMetafieldType = callThread.lua.luaL_getmetafield(callThread.address, -1, '__call')
200 callThread.pop()
201 if (callMetafieldType !== LuaType.Function) {
202 throw new Error(`A value of type '${internalType}' was pushed but it is not callable`)
203 }
204 }
205
206 for (const arg of args) {
207 callThread.pushValue(arg)
208 }
209
210 if (this.options?.functionTimeout) {
211 callThread.setTimeout(Date.now() + this.options.functionTimeout)
212 }
213
214 const status: LuaReturn = callThread.lua.lua_pcallk(callThread.address, args.length, 1, 0, 0, null)
215 if (status === LuaReturn.Yield) {
216 throw new Error('cannot yield in callbacks from javascript')
217 }
218 callThread.assertOk(status)
219
220 if (callThread.getTop() > 0) {
221 return callThread.getValue(-1)
222 }
223 return undefined
224 } finally {
225 callThread.close()
226 // Pop thread used for function call.
227 this.callbackContext.pop()
228 }
229 }
230
231 this.functionRegistry?.register(jsFunc, func)
232

Callers

nothing calls this directly

Calls 9

isClosedMethod · 0.80
newThreadMethod · 0.80
popMethod · 0.80
setTimeoutMethod · 0.80
assertOkMethod · 0.80
getTopMethod · 0.80
pushValueMethod · 0.45
getValueMethod · 0.45
closeMethod · 0.45

Tested by

no test coverage detected