printBacktrace = (middleIndex, func, funcs, globals, exceptions) => {
    console.log(`\x1B[35m\x1B[1mporffor backtrace\u001b[0m`);

    const surrounding = Prefs.backtraceSurrounding ?? 10;
    let min = middleIndex - surrounding;
    let max = middleIndex + surrounding + 1;
    if (Prefs.backtraceFunc || middleIndex === -1) {
      min = 0;
      max = func.wasm.length;
    }

    const disasm = disassemble(func.wasm.slice(min, max), func.name, 0, func.locals, func.params, func.returns, funcs, globals, exceptions)
      .slice(0, -1).split('\n').filter(x => !x.startsWith('\x1B[2m;;'));

    const noAnsi = s => s && s.replace(/\u001b\[[0-9]+m/g, '');
    let longest = 0;
    for (let j = 0; j < disasm.length; j++) {
      longest = Math.max(longest, noAnsi(disasm[j])?.length ?? 0);
    }

    if (middleIndex !== -1) {
      const middle = Math.floor(disasm.length / 2);
      disasm[middle] = `\x1B[47m\x1B[30m${noAnsi(disasm[middle])}${'\u00a0'.repeat(longest - noAnsi(disasm[middle]).length)}\x1B[0m`;
    }

    if (min != 0) console.log('\x1B[2m...\x1B[0m');
    console.log(disasm.join('\n'));
    if (max > func.wasm.length) console.log('\x1B[2m...\x1B[0m\n');
  }
Compile given JavaScript source code. // todo: more docs here (sorry)

@param {string} source - JavaScript source code to compile
@param {boolean} module - If the source is a module or not (default: false)
@param {object} customImports - Custom imports
@param {(str: string) => void} print - Function to use for printing (used by console.log etc)