TypeScript Module Error: JavaScript functions cannot be inline

I am writing my server side code for my game in TypeScript, and built a base Game class with extending mini-games. Inside of each Game or mini game class is all the functions needed for registerMatch. When I attempt to run my code, I get this error:

{"level":"fatal","ts":"2022-11-30T01:31:18.121Z","caller":"main.go:158","msg":"Failed initializing runtime modules","error":"GoError: js match handler \"matchInit\" function for module \"ballgame\" global id could not be extracted: function literal found: javascript functions cannot be inlined\n\tat github.com/heroiclabs/nakama/v3/server.(*RuntimeJavascriptInitModule).registerMatch.func1 (native)\n\tat InitModule (index.js:407:26(39))\n\tat native\n"}

I am running Nakama 3.14 and am using TypeScript/JavaScript.

My code is setup as such:
Main.ts

import { Game } from './games'
import { BallGame } from './games/ball'

const InitModule = ... {
    const game: Game = new BallGame()
    initializer.registerMatch(game.id, {
        matchInit: game.matchInit,
        matchJoinAttempt: game.matchJoinAttempt,
        matchJoin: game.matchJoin,
        matchLeave: game.matchLeave,
        matchLoop: game.matchLoop,
        matchSignal: game.matchSignal,
        matchTerminate: game.matchTerminate,
    })
}

Games.ts

export abstract class Game {
    id: string
    ...

    matchInit(
        ctx: nkruntime.Context,
        logger: nkruntime.Logger,
        nk: nkruntime.Nakama,
        params: { [key: string]: string }
    ): { state: GameState; tickRate: number; label: string } {
        ...
        return {
            state: { ... },
            tickRate: this.tickRate,
            label: gameInviteCode,
        }
    }

    // ... (all other functions needed for registerMatch)
}

BallGame.ts

export class BallGame extends Game {
    id = 'ball-game'
    ...
    matchInit(
        ctx: nkruntime.Context,
        logger: nkruntime.Logger,
        nk: nkruntime.Nakama,
        params: { [key: string]: string }
    ): { state: BallGameState; tickRate: number; label: string } {
        const { state, tickRate, label } = super.matchInit(ctx, logger, nk, params)
        ...
        return {
            state: {
                ...state,
                ...
            },
            tickRate,
            label,
        }
    }
}

I see that this error is referencing me using functions that then get compiled to be inline, but is there anything I can do here to keep my functionality the same (ie using classes of some sort and hopefully calling super)? I tried converting to arrow functions without success (may have been doing it wrong).

Thanks for any help you may have.

Hello @hcopp, unfortunately there are some limitations on the JS engine and all the functions that are registered need to be at the top level scope. I believe that classes can be referenced within those functions, but not the other way around. Using classes anywhere else should work too.

You need to make sure that in the transpiled code the functions are not inlined but referenced by a top level identifier within the registration functions.

Hope this helps.

1 Like