var Module = typeof Module != "undefined" ? Module : {};
var moduleOverrides = Object.assign({}, Module);
var arguments_ = [];
var thisProgram = "./this.program";
var quit_ = (status, toThrow) => {
  throw toThrow;
};
var ENVIRONMENT_IS_WEB = typeof window == "object";
var ENVIRONMENT_IS_WORKER = typeof importScripts == "function";
var ENVIRONMENT_IS_NODE =
  typeof process == "object" &&
  typeof process.versions == "object" &&
  typeof process.versions.node == "string";
var ENVIRONMENT_IS_SHELL =
  !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
if (Module["ENVIRONMENT"]) {
  throw new Error(
    "Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)"
  );
}
var scriptDirectory = "";
function locateFile(path) {
  if (Module["locateFile"]) {
    return Module["locateFile"](path, scriptDirectory);
  }
  return scriptDirectory + path;
}
var read_, readAsync, readBinary;
if (ENVIRONMENT_IS_NODE) {
  if (
    typeof process == "undefined" ||
    !process.release ||
    process.release.name !== "node"
  )
    throw new Error(
      "not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)"
    );
  var nodeVersion = process.versions.node;
  var numericVersion = nodeVersion.split(".").slice(0, 3);
  numericVersion =
    numericVersion[0] * 1e4 +
    numericVersion[1] * 100 +
    numericVersion[2].split("-")[0] * 1;
  if (numericVersion < 16e4) {
    throw new Error(
      "This emscripten-generated code requires node v16.0.0 (detected v" +
        nodeVersion +
        ")"
    );
  }
  var fs = require("fs");
  var nodePath = require("path");
  if (ENVIRONMENT_IS_WORKER) {
    scriptDirectory = nodePath.dirname(scriptDirectory) + "/";
  } else {
    scriptDirectory = __dirname + "/";
  }
  read_ = (filename, binary) => {
    filename = isFileURI(filename)
      ? new URL(filename)
      : nodePath.normalize(filename);
    return fs.readFileSync(filename, binary ? undefined : "utf8");
  };
  readBinary = (filename) => {
    var ret = read_(filename, true);
    if (!ret.buffer) {
      ret = new Uint8Array(ret);
    }
    assert(ret.buffer);
    return ret;
  };
  readAsync = (filename, onload, onerror, binary = true) => {
    filename = isFileURI(filename)
      ? new URL(filename)
      : nodePath.normalize(filename);
    fs.readFile(filename, binary ? undefined : "utf8", (err, data) => {
      if (err) onerror(err);
      else onload(binary ? data.buffer : data);
    });
  };
  if (!Module["thisProgram"] && process.argv.length > 1) {
    thisProgram = process.argv[1].replace(/\\/g, "/");
  }
  arguments_ = process.argv.slice(2);
  if (typeof module != "undefined") {
    module["exports"] = Module;
  }
  process.on("uncaughtException", (ex) => {
    if (
      ex !== "unwind" &&
      !(ex instanceof ExitStatus) &&
      !(ex.context instanceof ExitStatus)
    ) {
      throw ex;
    }
  });
  quit_ = (status, toThrow) => {
    process.exitCode = status;
    throw toThrow;
  };
  Module["inspect"] = () => "[Emscripten Module object]";
} else if (ENVIRONMENT_IS_SHELL) {
  if (
    (typeof process == "object" && typeof require === "function") ||
    typeof window == "object" ||
    typeof importScripts == "function"
  )
    throw new Error(
      "not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)"
    );
  if (typeof read != "undefined") {
    read_ = read;
  }
  readBinary = (f) => {
    if (typeof readbuffer == "function") {
      return new Uint8Array(readbuffer(f));
    }
    let data = read(f, "binary");
    assert(typeof data == "object");
    return data;
  };
  readAsync = (f, onload, onerror) => {
    setTimeout(() => onload(readBinary(f)));
  };
  if (typeof clearTimeout == "undefined") {
    globalThis.clearTimeout = (id) => {};
  }
  if (typeof setTimeout == "undefined") {
    globalThis.setTimeout = (f) => (typeof f == "function" ? f() : abort());
  }

  if (typeof quit == "function") {
    quit_ = (status, toThrow) => {
      setTimeout(() => {
        if (!(toThrow instanceof ExitStatus)) {
          let toLog = toThrow;
          if (toThrow && typeof toThrow == "object" && toThrow.stack) {
            toLog = [toThrow, toThrow.stack];
          }
          err(`exiting due to exception: ${toLog}`);
        }
        quit(status);
      });
      throw toThrow;
    };
  }
  if (typeof print != "undefined") {
    if (typeof console == "undefined") console = {};
    console.log = print;
    console.warn = console.error =
      typeof printErr != "undefined" ? printErr : print;
  }
} else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
  if (ENVIRONMENT_IS_WORKER) {
    scriptDirectory = self.location.href;
  } else if (typeof document != "undefined" && document.currentScript) {
    scriptDirectory = document.currentScript.src;
  }
  if (scriptDirectory.indexOf("blob:") !== 0) {
    scriptDirectory = scriptDirectory.substr(
      0,
      scriptDirectory.replace(/[?#].*/, "").lastIndexOf("/") + 1
    );
  } else {
    scriptDirectory = "";
  }
  if (!(typeof window == "object" || typeof importScripts == "function"))
    throw new Error(
      "not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)"
    );
  {
    read_ = (url) => {
      var xhr = new XMLHttpRequest();
      xhr.open("GET", url, false);
      xhr.send(null);
      return xhr.responseText;
    };
    if (ENVIRONMENT_IS_WORKER) {
      readBinary = (url) => {
        var xhr = new XMLHttpRequest();
        xhr.open("GET", url, false);
        xhr.responseType = "arraybuffer";
        xhr.send(null);
        return new Uint8Array(xhr.response);
      };
    }
    readAsync = (url, onload, onerror) => {
      var xhr = new XMLHttpRequest();
      xhr.open("GET", url, true);
      xhr.responseType = "arraybuffer";
      xhr.onload = () => {
        if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) {
          onload(xhr.response);
          return;
        }
        onerror();
      };
      xhr.onerror = onerror;
      xhr.send(null);
    };
  }
} else {
  throw new Error("environment detection error");
}
var out = Module["print"] || console.log.bind(console);
var err = Module["printErr"] || console.error.bind(console);
Object.assign(Module, moduleOverrides);
moduleOverrides = null;
checkIncomingModuleAPI();
if (Module["arguments"]) arguments_ = Module["arguments"];
legacyModuleProp("arguments", "arguments_");
if (Module["thisProgram"]) thisProgram = Module["thisProgram"];
legacyModuleProp("thisProgram", "thisProgram");
if (Module["quit"]) quit_ = Module["quit"];
legacyModuleProp("quit", "quit_");
assert(
  typeof Module["memoryInitializerPrefixURL"] == "undefined",
  "Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead"
);
assert(
  typeof Module["pthreadMainPrefixURL"] == "undefined",
  "Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead"
);
assert(
  typeof Module["cdInitializerPrefixURL"] == "undefined",
  "Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead"
);
assert(
  typeof Module["filePackagePrefixURL"] == "undefined",
  "Module.filePackagePrefixURL option was removed, use Module.locateFile instead"
);
assert(
  typeof Module["read"] == "undefined",
  "Module.read option was removed (modify read_ in JS)"
);
assert(
  typeof Module["readAsync"] == "undefined",
  "Module.readAsync option was removed (modify readAsync in JS)"
);
assert(
  typeof Module["readBinary"] == "undefined",
  "Module.readBinary option was removed (modify readBinary in JS)"
);
assert(
  typeof Module["setWindowTitle"] == "undefined",
  "Module.setWindowTitle option was removed (modify emscripten_set_window_title in JS)"
);
assert(
  typeof Module["TOTAL_MEMORY"] == "undefined",
  "Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY"
);
legacyModuleProp("asm", "wasmExports");
legacyModuleProp("read", "read_");
legacyModuleProp("readAsync", "readAsync");
legacyModuleProp("readBinary", "readBinary");
legacyModuleProp("setWindowTitle", "setWindowTitle");
var wasmBinary;
if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"];
legacyModuleProp("wasmBinary", "wasmBinary");
var noExitRuntime = Module["noExitRuntime"] || true;
legacyModuleProp("noExitRuntime", "noExitRuntime");
if (typeof WXWebAssembly != "object") {
  abort("no native wasm support detected");
}
var wasmMemory;
var ABORT = false;
var EXITSTATUS;
function assert(condition, text) {
  if (!condition) {
    abort("Assertion failed" + (text ? ": " + text : ""));
  }
}
var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;
function updateMemoryViews() {
  var b = wasmMemory.buffer;
  Module["HEAP8"] = HEAP8 = new Int8Array(b);
  Module["HEAP16"] = HEAP16 = new Int16Array(b);
  Module["HEAPU8"] = HEAPU8 = new Uint8Array(b);
  Module["HEAPU16"] = HEAPU16 = new Uint16Array(b);
  Module["HEAP32"] = HEAP32 = new Int32Array(b);
  Module["HEAPU32"] = HEAPU32 = new Uint32Array(b);
  Module["HEAPF32"] = HEAPF32 = new Float32Array(b);
  Module["HEAPF64"] = HEAPF64 = new Float64Array(b);
}
assert(
  !Module["STACK_SIZE"],
  "STACK_SIZE can no longer be set at runtime.  Use -sSTACK_SIZE at link time"
);
assert(
  typeof Int32Array != "undefined" &&
    typeof Float64Array !== "undefined" &&
    Int32Array.prototype.subarray != undefined &&
    Int32Array.prototype.set != undefined,
  "JS engine does not provide full typed array support"
);
assert(
  !Module["wasmMemory"],
  "Use of `wasmMemory` detected.  Use -sIMPORTED_MEMORY to define wasmMemory externally"
);
assert(
  !Module["INITIAL_MEMORY"],
  "Detected runtime INITIAL_MEMORY setting.  Use -sIMPORTED_MEMORY to define wasmMemory dynamically"
);
function writeStackCookie() {
  var max = _emscripten_stack_get_end();
  assert((max & 3) == 0);
  if (max == 0) {
    max += 4;
  }
  HEAPU32[max >> 2] = 34821223;
  HEAPU32[(max + 4) >> 2] = 2310721022;
  HEAPU32[0 >> 2] = 1668509029;
}
function checkStackCookie() {
  if (ABORT) return;
  var max = _emscripten_stack_get_end();
  if (max == 0) {
    max += 4;
  }
  var cookie1 = HEAPU32[max >> 2];
  var cookie2 = HEAPU32[(max + 4) >> 2];
  if (cookie1 != 34821223 || cookie2 != 2310721022) {
    abort(
      `Stack overflow! Stack cookie has been overwritten at ${ptrToString(
        max
      )}, expected hex dwords 0x89BACDFE and 0x2135467, but received ${ptrToString(
        cookie2
      )} ${ptrToString(cookie1)}`
    );
  }
  if (HEAPU32[0 >> 2] != 1668509029) {
    abort(
      "Runtime error: The application has corrupted its heap memory area (address zero)!"
    );
  }
}
(function () {
  var h16 = new Int16Array(1);
  var h8 = new Int8Array(h16.buffer);
  h16[0] = 25459;
  if (h8[0] !== 115 || h8[1] !== 99)
    throw "Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)";
})();
var __ATPRERUN__ = [];
var __ATINIT__ = [];
var __ATEXIT__ = [];
var __ATPOSTRUN__ = [];
var runtimeInitialized = false;
var runtimeKeepaliveCounter = 0;
function keepRuntimeAlive() {
  return noExitRuntime || runtimeKeepaliveCounter > 0;
}
function preRun() {
  if (Module["preRun"]) {
    if (typeof Module["preRun"] == "function")
      Module["preRun"] = [Module["preRun"]];
    while (Module["preRun"].length) {
      addOnPreRun(Module["preRun"].shift());
    }
  }
  callRuntimeCallbacks(__ATPRERUN__);
}
function initRuntime() {
  assert(!runtimeInitialized);
  runtimeInitialized = true;
  checkStackCookie();
  if (!Module["noFSInit"] && !FS.init.initialized) FS.init();
  FS.ignorePermissions = false;
  TTY.init();
  callRuntimeCallbacks(__ATINIT__);
}
function postRun() {
  checkStackCookie();
  if (Module["postRun"]) {
    if (typeof Module["postRun"] == "function")
      Module["postRun"] = [Module["postRun"]];
    while (Module["postRun"].length) {
      addOnPostRun(Module["postRun"].shift());
    }
  }
  callRuntimeCallbacks(__ATPOSTRUN__);
}
function addOnPreRun(cb) {
  __ATPRERUN__.unshift(cb);
}
function addOnInit(cb) {
  __ATINIT__.unshift(cb);
}
function addOnPostRun(cb) {
  __ATPOSTRUN__.unshift(cb);
}
assert(
  Math.imul,
  "This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill"
);
assert(
  Math.fround,
  "This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill"
);
assert(
  Math.clz32,
  "This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill"
);
assert(
  Math.trunc,
  "This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill"
);
var runDependencies = 0;
var runDependencyWatcher = null;
var dependenciesFulfilled = null;
var runDependencyTracking = {};
function getUniqueRunDependency(id) {
  var orig = id;
  while (1) {
    if (!runDependencyTracking[id]) return id;
    id = orig + Math.random();
  }
}
function addRunDependency(id) {
  runDependencies++;
  if (Module["monitorRunDependencies"]) {
    Module["monitorRunDependencies"](runDependencies);
  }
  if (id) {
    assert(!runDependencyTracking[id]);
    runDependencyTracking[id] = 1;
    if (runDependencyWatcher === null && typeof setInterval != "undefined") {
      runDependencyWatcher = setInterval(() => {
        if (ABORT) {
          clearInterval(runDependencyWatcher);
          runDependencyWatcher = null;
          return;
        }
        var shown = false;
        for (var dep in runDependencyTracking) {
          if (!shown) {
            shown = true;
            err("still waiting on run dependencies:");
          }
          err(`dependency: ${dep}`);
        }
        if (shown) {
          err("(end of list)");
        }
      }, 1e4);
    }
  } else {
    err("warning: run dependency added without ID");
  }
}
function removeRunDependency(id) {
  runDependencies--;
  if (Module["monitorRunDependencies"]) {
    Module["monitorRunDependencies"](runDependencies);
  }
  if (id) {
    assert(runDependencyTracking[id]);
    delete runDependencyTracking[id];
  } else {
    err("warning: run dependency removed without ID");
  }
  if (runDependencies == 0) {
    if (runDependencyWatcher !== null) {
      clearInterval(runDependencyWatcher);
      runDependencyWatcher = null;
    }
    if (dependenciesFulfilled) {
      var callback = dependenciesFulfilled;
      dependenciesFulfilled = null;
      callback();
    }
  }
}
function abort(what) {
  if (Module["onAbort"]) {
    Module["onAbort"](what);
  }
  what = "Aborted(" + what + ")";
  err(what);
  ABORT = true;
  EXITSTATUS = 1;
  if (what.indexOf("RuntimeError: unreachable") >= 0) {
    what +=
      '. "unreachable" may be due to ASYNCIFY_STACK_SIZE not being large enough (try increasing it)';
  }
  throw what;
}
function isFileURI(filename) {
  return filename.startsWith("file://");
}
function createExportWrapper(name) {
  return function () {
    assert(
      runtimeInitialized,
      `native function \`${name}\` called before runtime initialization`
    );
    var f = wasmExports[name];
    assert(f, `exported native function \`${name}\` not found`);
    return f.apply(null, arguments);
  };
}
class EmscriptenEH extends Error {}
class EmscriptenSjLj extends EmscriptenEH {}
class CppException extends EmscriptenEH {
  constructor(excPtr) {
    super(excPtr);
    this.excPtr = excPtr;
    const excInfo = getExceptionMessage(excPtr);
    this.name = excInfo[0];
    this.message = excInfo[1];
  }
}
var tempDouble;
var tempI64;
function legacyModuleProp(prop, newName, incomming = true) {
  if (!Object.getOwnPropertyDescriptor(Module, prop)) {
    Object.defineProperty(Module, prop, {
      configurable: true,
      get() {
        let extra = incomming
          ? " (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)"
          : "";
        abort(`\`Module.${prop}\` has been replaced by \`${newName}\`` + extra);
      },
    });
  }
}
function ignoredModuleProp(prop) {
  if (Object.getOwnPropertyDescriptor(Module, prop)) {
    abort(
      `\`Module.${prop}\` was supplied but \`${prop}\` not included in INCOMING_MODULE_JS_API`
    );
  }
}
function isExportedByForceFilesystem(name) {
  return (
    name === "FS_createPath" ||
    name === "FS_createDataFile" ||
    name === "FS_createPreloadedFile" ||
    name === "FS_unlink" ||
    name === "addRunDependency" ||
    name === "FS_createLazyFile" ||
    name === "FS_createDevice" ||
    name === "removeRunDependency"
  );
}
function missingGlobal(sym, msg) {
  if (typeof globalThis !== "undefined") {
    Object.defineProperty(globalThis, sym, {
      configurable: true,
      get() {
        warnOnce("`" + sym + "` is not longer defined by emscripten. " + msg);
        return undefined;
      },
    });
  }
}
missingGlobal("buffer", "Please use HEAP8.buffer or wasmMemory.buffer");
missingGlobal("asm", "Please use wasmExports instead");
function missingLibrarySymbol(sym) {
  if (
    typeof globalThis !== "undefined" &&
    !Object.getOwnPropertyDescriptor(globalThis, sym)
  ) {
    Object.defineProperty(globalThis, sym, {
      configurable: true,
      get() {
        var msg =
          "`" +
          sym +
          "` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line";
        var librarySymbol = sym;
        if (!librarySymbol.startsWith("_")) {
          librarySymbol = "$" + sym;
        }
        msg +=
          " (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='" + librarySymbol + "')";
        if (isExportedByForceFilesystem(sym)) {
          msg +=
            ". Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you";
        }
        warnOnce(msg);
        return undefined;
      },
    });
  }
  unexportedRuntimeSymbol(sym);
}
function unexportedRuntimeSymbol(sym) {
  if (!Object.getOwnPropertyDescriptor(Module, sym)) {
    Object.defineProperty(Module, sym, {
      configurable: true,
      get() {
        var msg =
          "'" +
          sym +
          "' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the Emscripten FAQ)";
        if (isExportedByForceFilesystem(sym)) {
          msg +=
            ". Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you";
        }
        abort(msg);
      },
    });
  }
}
function ExitStatus(status) {
  this.name = "ExitStatus";
  this.message = `Program terminated with exit(${status})`;
  this.status = status;
}
var callRuntimeCallbacks = (callbacks) => {
  while (callbacks.length > 0) {
    callbacks.shift()(Module);
  }
};
var withStackSave = (f) => {
  var stack = stackSave();
  var ret = f();
  stackRestore(stack);
  return ret;
};
var UTF8Decoder =
  typeof TextDecoder != "undefined" ? new TextDecoder("utf8") : undefined;
var UTF8ArrayToString = (heapOrArray, idx, maxBytesToRead) => {
  var endIdx = idx + maxBytesToRead;
  var endPtr = idx;
  while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr;
  if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
    return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));
  }
  var str = "";
  while (idx < endPtr) {
    var u0 = heapOrArray[idx++];
    if (!(u0 & 128)) {
      str += String.fromCharCode(u0);
      continue;
    }
    var u1 = heapOrArray[idx++] & 63;
    if ((u0 & 224) == 192) {
      str += String.fromCharCode(((u0 & 31) << 6) | u1);
      continue;
    }
    var u2 = heapOrArray[idx++] & 63;
    if ((u0 & 240) == 224) {
      u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
    } else {
      if ((u0 & 248) != 240)
        warnOnce(
          "Invalid UTF-8 leading byte " +
            ptrToString(u0) +
            " encountered when deserializing a UTF-8 string in wasm memory to a JS string!"
        );
      u0 =
        ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63);
    }
    if (u0 < 65536) {
      str += String.fromCharCode(u0);
    } else {
      var ch = u0 - 65536;
      str += String.fromCharCode(55296 | (ch >> 10), 56320 | (ch & 1023));
    }
  }
  return str;
};
var UTF8ToString = (ptr, maxBytesToRead) => {
  assert(typeof ptr == "number");
  return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : "";
};
var getExceptionMessageCommon = (ptr) =>
  withStackSave(() => {
    var type_addr_addr = stackAlloc(4);
    var message_addr_addr = stackAlloc(4);
    ___get_exception_message(ptr, type_addr_addr, message_addr_addr);
    var type_addr = HEAPU32[type_addr_addr >> 2];
    var message_addr = HEAPU32[message_addr_addr >> 2];
    var type = UTF8ToString(type_addr);
    _free(type_addr);
    var message;
    if (message_addr) {
      message = UTF8ToString(message_addr);
      _free(message_addr);
    }
    return [type, message];
  });
var getExceptionMessage = (ptr) => getExceptionMessageCommon(ptr);
Module["getExceptionMessage"] = getExceptionMessage;
var ptrToString = (ptr) => {
  assert(typeof ptr === "number");
  ptr >>>= 0;
  return "0x" + ptr.toString(16).padStart(8, "0");
};
var warnOnce = (text) => {
  if (!warnOnce.shown) warnOnce.shown = {};
  if (!warnOnce.shown[text]) {
    warnOnce.shown[text] = 1;
    if (ENVIRONMENT_IS_NODE) text = "warning: " + text;
    err(text);
  }
};
var ___assert_fail = (condition, filename, line, func) => {
  abort(
    `Assertion failed: ${UTF8ToString(condition)}, at: ` +
      [
        filename ? UTF8ToString(filename) : "unknown filename",
        line,
        func ? UTF8ToString(func) : "unknown function",
      ]
  );
};
var exceptionCaught = [];
var uncaughtExceptionCount = 0;
var ___cxa_begin_catch = (ptr) => {
  var info = new ExceptionInfo(ptr);
  if (!info.get_caught()) {
    info.set_caught(true);
    uncaughtExceptionCount--;
  }
  info.set_rethrown(false);
  exceptionCaught.push(info);
  ___cxa_increment_exception_refcount(info.excPtr);
  return info.get_exception_ptr();
};
var exceptionLast = 0;
var ___cxa_end_catch = () => {
  _setThrew(0, 0);
  assert(exceptionCaught.length > 0);
  var info = exceptionCaught.pop();
  ___cxa_decrement_exception_refcount(info.excPtr);
  exceptionLast = 0;
};
function ExceptionInfo(excPtr) {
  this.excPtr = excPtr;
  this.ptr = excPtr - 24;
  this.set_type = function (type) {
    HEAPU32[(this.ptr + 4) >> 2] = type;
  };
  this.get_type = function () {
    return HEAPU32[(this.ptr + 4) >> 2];
  };
  this.set_destructor = function (destructor) {
    HEAPU32[(this.ptr + 8) >> 2] = destructor;
  };
  this.get_destructor = function () {
    return HEAPU32[(this.ptr + 8) >> 2];
  };
  this.set_caught = function (caught) {
    caught = caught ? 1 : 0;
    HEAP8[(this.ptr + 12) >> 0] = caught;
  };
  this.get_caught = function () {
    return HEAP8[(this.ptr + 12) >> 0] != 0;
  };
  this.set_rethrown = function (rethrown) {
    rethrown = rethrown ? 1 : 0;
    HEAP8[(this.ptr + 13) >> 0] = rethrown;
  };
  this.get_rethrown = function () {
    return HEAP8[(this.ptr + 13) >> 0] != 0;
  };
  this.init = function (type, destructor) {
    this.set_adjusted_ptr(0);
    this.set_type(type);
    this.set_destructor(destructor);
  };
  this.set_adjusted_ptr = function (adjustedPtr) {
    HEAPU32[(this.ptr + 16) >> 2] = adjustedPtr;
  };
  this.get_adjusted_ptr = function () {
    return HEAPU32[(this.ptr + 16) >> 2];
  };
  this.get_exception_ptr = function () {
    var isPointer = ___cxa_is_pointer_type(this.get_type());
    if (isPointer) {
      return HEAPU32[this.excPtr >> 2];
    }
    var adjusted = this.get_adjusted_ptr();
    if (adjusted !== 0) return adjusted;
    return this.excPtr;
  };
}
var ___resumeException = (ptr) => {
  if (!exceptionLast) {
    exceptionLast = new CppException(ptr);
  }
  throw exceptionLast;
};
var findMatchingCatch = (args) => {
  var thrown = exceptionLast && exceptionLast.excPtr;
  if (!thrown) {
    setTempRet0(0);
    return 0;
  }
  var info = new ExceptionInfo(thrown);
  info.set_adjusted_ptr(thrown);
  var thrownType = info.get_type();
  if (!thrownType) {
    setTempRet0(0);
    return thrown;
  }
  for (var arg in args) {
    var caughtType = args[arg];
    if (caughtType === 0 || caughtType === thrownType) {
      break;
    }
    var adjusted_ptr_addr = info.ptr + 16;
    if (___cxa_can_catch(caughtType, thrownType, adjusted_ptr_addr)) {
      setTempRet0(caughtType);
      return thrown;
    }
  }
  setTempRet0(thrownType);
  return thrown;
};
var ___cxa_find_matching_catch_2 = () => findMatchingCatch([]);
var ___cxa_find_matching_catch_3 = (arg0) => findMatchingCatch([arg0]);
var ___cxa_rethrow = () => {
  var info = exceptionCaught.pop();
  if (!info) {
    abort("no exception to throw");
  }
  var ptr = info.excPtr;
  if (!info.get_rethrown()) {
    exceptionCaught.push(info);
    info.set_rethrown(true);
    info.set_caught(false);
    uncaughtExceptionCount++;
  }
  exceptionLast = new CppException(ptr);
  throw exceptionLast;
};
var ___cxa_rethrow_primary_exception = (ptr) => {
  if (!ptr) return;
  var info = new ExceptionInfo(ptr);
  exceptionCaught.push(info);
  info.set_rethrown(true);
  ___cxa_rethrow();
};
var ___cxa_throw = (ptr, type, destructor) => {
  var info = new ExceptionInfo(ptr);
  info.init(type, destructor);
  exceptionLast = new CppException(ptr);
  uncaughtExceptionCount++;
  throw exceptionLast;
};
var ___cxa_uncaught_exceptions = () => uncaughtExceptionCount;
var PATH = {
  isAbs: (path) => path.charAt(0) === "/",
  splitPath: (filename) => {
    var splitPathRe =
      /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
    return splitPathRe.exec(filename).slice(1);
  },
  normalizeArray: (parts, allowAboveRoot) => {
    var up = 0;
    for (var i = parts.length - 1; i >= 0; i--) {
      var last = parts[i];
      if (last === ".") {
        parts.splice(i, 1);
      } else if (last === "..") {
        parts.splice(i, 1);
        up++;
      } else if (up) {
        parts.splice(i, 1);
        up--;
      }
    }
    if (allowAboveRoot) {
      for (; up; up--) {
        parts.unshift("..");
      }
    }
    return parts;
  },
  normalize: (path) => {
    var isAbsolute = PATH.isAbs(path),
      trailingSlash = path.substr(-1) === "/";
    path = PATH.normalizeArray(
      path.split("/").filter((p) => !!p),
      !isAbsolute
    ).join("/");
    if (!path && !isAbsolute) {
      path = ".";
    }
    if (path && trailingSlash) {
      path += "/";
    }
    return (isAbsolute ? "/" : "") + path;
  },
  dirname: (path) => {
    var result = PATH.splitPath(path),
      root = result[0],
      dir = result[1];
    if (!root && !dir) {
      return ".";
    }
    if (dir) {
      dir = dir.substr(0, dir.length - 1);
    }
    return root + dir;
  },
  basename: (path) => {
    if (path === "/") return "/";
    path = PATH.normalize(path);
    path = path.replace(/\/$/, "");
    var lastSlash = path.lastIndexOf("/");
    if (lastSlash === -1) return path;
    return path.substr(lastSlash + 1);
  },
  join: function () {
    var paths = Array.prototype.slice.call(arguments);
    return PATH.normalize(paths.join("/"));
  },
  join2: (l, r) => PATH.normalize(l + "/" + r),
};
var initRandomFill = () => {
  if (
    typeof crypto == "object" &&
    typeof crypto["getRandomValues"] == "function"
  ) {
    return (view) => crypto.getRandomValues(view);
  } else if (ENVIRONMENT_IS_NODE) {
    try {
      var crypto_module = require("crypto");
      var randomFillSync = crypto_module["randomFillSync"];
      if (randomFillSync) {
        return (view) => crypto_module["randomFillSync"](view);
      }
      var randomBytes = crypto_module["randomBytes"];
      return (view) => (view.set(randomBytes(view.byteLength)), view);
    } catch (e) {}
  }
  abort(
    "no cryptographic support found for randomDevice. consider polyfilling it if you want to use something insecure like Math.random(), e.g. put this in a --pre-js: var crypto = { getRandomValues: (array) => { for (var i = 0; i < array.length; i++) array[i] = (Math.random()*256)|0 } };"
  );
};
var randomFill = (view) => (randomFill = initRandomFill())(view);
var PATH_FS = {
  resolve: function () {
    var resolvedPath = "",
      resolvedAbsolute = false;
    for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
      var path = i >= 0 ? arguments[i] : FS.cwd();
      if (typeof path != "string") {
        throw new TypeError("Arguments to path.resolve must be strings");
      } else if (!path) {
        return "";
      }
      resolvedPath = path + "/" + resolvedPath;
      resolvedAbsolute = PATH.isAbs(path);
    }
    resolvedPath = PATH.normalizeArray(
      resolvedPath.split("/").filter((p) => !!p),
      !resolvedAbsolute
    ).join("/");
    return (resolvedAbsolute ? "/" : "") + resolvedPath || ".";
  },
  relative: (from, to) => {
    from = PATH_FS.resolve(from).substr(1);
    to = PATH_FS.resolve(to).substr(1);
    function trim(arr) {
      var start = 0;
      for (; start < arr.length; start++) {
        if (arr[start] !== "") break;
      }
      var end = arr.length - 1;
      for (; end >= 0; end--) {
        if (arr[end] !== "") break;
      }
      if (start > end) return [];
      return arr.slice(start, end - start + 1);
    }
    var fromParts = trim(from.split("/"));
    var toParts = trim(to.split("/"));
    var length = Math.min(fromParts.length, toParts.length);
    var samePartsLength = length;
    for (var i = 0; i < length; i++) {
      if (fromParts[i] !== toParts[i]) {
        samePartsLength = i;
        break;
      }
    }
    var outputParts = [];
    for (var i = samePartsLength; i < fromParts.length; i++) {
      outputParts.push("..");
    }
    outputParts = outputParts.concat(toParts.slice(samePartsLength));
    return outputParts.join("/");
  },
};
var FS_stdin_getChar_buffer = [];
var lengthBytesUTF8 = (str) => {
  var len = 0;
  for (var i = 0; i < str.length; ++i) {
    var c = str.charCodeAt(i);
    if (c <= 127) {
      len++;
    } else if (c <= 2047) {
      len += 2;
    } else if (c >= 55296 && c <= 57343) {
      len += 4;
      ++i;
    } else {
      len += 3;
    }
  }
  return len;
};
var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
  assert(typeof str === "string");
  if (!(maxBytesToWrite > 0)) return 0;
  var startIdx = outIdx;
  var endIdx = outIdx + maxBytesToWrite - 1;
  for (var i = 0; i < str.length; ++i) {
    var u = str.charCodeAt(i);
    if (u >= 55296 && u <= 57343) {
      var u1 = str.charCodeAt(++i);
      u = (65536 + ((u & 1023) << 10)) | (u1 & 1023);
    }
    if (u <= 127) {
      if (outIdx >= endIdx) break;
      heap[outIdx++] = u;
    } else if (u <= 2047) {
      if (outIdx + 1 >= endIdx) break;
      heap[outIdx++] = 192 | (u >> 6);
      heap[outIdx++] = 128 | (u & 63);
    } else if (u <= 65535) {
      if (outIdx + 2 >= endIdx) break;
      heap[outIdx++] = 224 | (u >> 12);
      heap[outIdx++] = 128 | ((u >> 6) & 63);
      heap[outIdx++] = 128 | (u & 63);
    } else {
      if (outIdx + 3 >= endIdx) break;
      if (u > 1114111)
        warnOnce(
          "Invalid Unicode code point " +
            ptrToString(u) +
            " encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF)."
        );
      heap[outIdx++] = 240 | (u >> 18);
      heap[outIdx++] = 128 | ((u >> 12) & 63);
      heap[outIdx++] = 128 | ((u >> 6) & 63);
      heap[outIdx++] = 128 | (u & 63);
    }
  }
  heap[outIdx] = 0;
  return outIdx - startIdx;
};
function intArrayFromString(stringy, dontAddNull, length) {
  var len = length > 0 ? length : lengthBytesUTF8(stringy) + 1;
  var u8array = new Array(len);
  var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length);
  if (dontAddNull) u8array.length = numBytesWritten;
  return u8array;
}
var FS_stdin_getChar = () => {
  if (!FS_stdin_getChar_buffer.length) {
    var result = null;
    if (ENVIRONMENT_IS_NODE) {
      var BUFSIZE = 256;
      var buf = Buffer.alloc(BUFSIZE);
      var bytesRead = 0;
      var fd = process.stdin.fd;
      try {
        bytesRead = fs.readSync(fd, buf);
      } catch (e) {
        if (e.toString().includes("EOF")) bytesRead = 0;
        else throw e;
      }
      if (bytesRead > 0) {
        result = buf.slice(0, bytesRead).toString("utf-8");
      } else {
        result = null;
      }
    } else if (
      typeof window != "undefined" &&
      typeof window.prompt == "function"
    ) {
      result = window.prompt("Input: ");
      if (result !== null) {
        result += "\n";
      }
    } else if (typeof readline == "function") {
      result = readline();
      if (result !== null) {
        result += "\n";
      }
    }
    if (!result) {
      return null;
    }
    FS_stdin_getChar_buffer = intArrayFromString(result, true);
  }
  return FS_stdin_getChar_buffer.shift();
};
var TTY = {
  ttys: [],
  init() {},
  shutdown() {},
  register(dev, ops) {
    TTY.ttys[dev] = { input: [], output: [], ops: ops };
    FS.registerDevice(dev, TTY.stream_ops);
  },
  stream_ops: {
    open(stream) {
      var tty = TTY.ttys[stream.node.rdev];
      if (!tty) {
        throw new FS.ErrnoError(43);
      }
      stream.tty = tty;
      stream.seekable = false;
    },
    close(stream) {
      stream.tty.ops.fsync(stream.tty);
    },
    fsync(stream) {
      stream.tty.ops.fsync(stream.tty);
    },
    read(stream, buffer, offset, length, pos) {
      if (!stream.tty || !stream.tty.ops.get_char) {
        throw new FS.ErrnoError(60);
      }
      var bytesRead = 0;
      for (var i = 0; i < length; i++) {
        var result;
        try {
          result = stream.tty.ops.get_char(stream.tty);
        } catch (e) {
          throw new FS.ErrnoError(29);
        }
        if (result === undefined && bytesRead === 0) {
          throw new FS.ErrnoError(6);
        }
        if (result === null || result === undefined) break;
        bytesRead++;
        buffer[offset + i] = result;
      }
      if (bytesRead) {
        stream.node.timestamp = Date.now();
      }
      return bytesRead;
    },
    write(stream, buffer, offset, length, pos) {
      if (!stream.tty || !stream.tty.ops.put_char) {
        throw new FS.ErrnoError(60);
      }
      try {
        for (var i = 0; i < length; i++) {
          stream.tty.ops.put_char(stream.tty, buffer[offset + i]);
        }
      } catch (e) {
        throw new FS.ErrnoError(29);
      }
      if (length) {
        stream.node.timestamp = Date.now();
      }
      return i;
    },
  },
  default_tty_ops: {
    get_char(tty) {
      return FS_stdin_getChar();
    },
    put_char(tty, val) {
      if (val === null || val === 10) {
        out(UTF8ArrayToString(tty.output, 0));
        tty.output = [];
      } else {
        if (val != 0) tty.output.push(val);
      }
    },
    fsync(tty) {
      if (tty.output && tty.output.length > 0) {
        out(UTF8ArrayToString(tty.output, 0));
        tty.output = [];
      }
    },
    ioctl_tcgets(tty) {
      return {
        c_iflag: 25856,
        c_oflag: 5,
        c_cflag: 191,
        c_lflag: 35387,
        c_cc: [
          3, 28, 127, 21, 4, 0, 1, 0, 17, 19, 26, 0, 18, 15, 23, 22, 0, 0, 0, 0,
          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        ],
      };
    },
    ioctl_tcsets(tty, optional_actions, data) {
      return 0;
    },
    ioctl_tiocgwinsz(tty) {
      return [24, 80];
    },
  },
  default_tty1_ops: {
    put_char(tty, val) {
      if (val === null || val === 10) {
        err(UTF8ArrayToString(tty.output, 0));
        tty.output = [];
      } else {
        if (val != 0) tty.output.push(val);
      }
    },
    fsync(tty) {
      if (tty.output && tty.output.length > 0) {
        err(UTF8ArrayToString(tty.output, 0));
        tty.output = [];
      }
    },
  },
};
var zeroMemory = (address, size) => {
  HEAPU8.fill(0, address, address + size);
  return address;
};
var alignMemory = (size, alignment) => {
  assert(alignment, "alignment argument is required");
  return Math.ceil(size / alignment) * alignment;
};
var mmapAlloc = (size) => {
  size = alignMemory(size, 65536);
  var ptr = _emscripten_builtin_memalign(65536, size);
  if (!ptr) return 0;
  return zeroMemory(ptr, size);
};
var MEMFS = {
  ops_table: null,
  mount(mount) {
    return MEMFS.createNode(null, "/", 16384 | 511, 0);
  },
  createNode(parent, name, mode, dev) {
    if (FS.isBlkdev(mode) || FS.isFIFO(mode)) {
      throw new FS.ErrnoError(63);
    }
    if (!MEMFS.ops_table) {
      MEMFS.ops_table = {
        dir: {
          node: {
            getattr: MEMFS.node_ops.getattr,
            setattr: MEMFS.node_ops.setattr,
            lookup: MEMFS.node_ops.lookup,
            mknod: MEMFS.node_ops.mknod,
            rename: MEMFS.node_ops.rename,
            unlink: MEMFS.node_ops.unlink,
            rmdir: MEMFS.node_ops.rmdir,
            readdir: MEMFS.node_ops.readdir,
            symlink: MEMFS.node_ops.symlink,
          },
          stream: { llseek: MEMFS.stream_ops.llseek },
        },
        file: {
          node: {
            getattr: MEMFS.node_ops.getattr,
            setattr: MEMFS.node_ops.setattr,
          },
          stream: {
            llseek: MEMFS.stream_ops.llseek,
            read: MEMFS.stream_ops.read,
            write: MEMFS.stream_ops.write,
            allocate: MEMFS.stream_ops.allocate,
            mmap: MEMFS.stream_ops.mmap,
            msync: MEMFS.stream_ops.msync,
          },
        },
        link: {
          node: {
            getattr: MEMFS.node_ops.getattr,
            setattr: MEMFS.node_ops.setattr,
            readlink: MEMFS.node_ops.readlink,
          },
          stream: {},
        },
        chrdev: {
          node: {
            getattr: MEMFS.node_ops.getattr,
            setattr: MEMFS.node_ops.setattr,
          },
          stream: FS.chrdev_stream_ops,
        },
      };
    }
    var node = FS.createNode(parent, name, mode, dev);
    if (FS.isDir(node.mode)) {
      node.node_ops = MEMFS.ops_table.dir.node;
      node.stream_ops = MEMFS.ops_table.dir.stream;
      node.contents = {};
    } else if (FS.isFile(node.mode)) {
      node.node_ops = MEMFS.ops_table.file.node;
      node.stream_ops = MEMFS.ops_table.file.stream;
      node.usedBytes = 0;
      node.contents = null;
    } else if (FS.isLink(node.mode)) {
      node.node_ops = MEMFS.ops_table.link.node;
      node.stream_ops = MEMFS.ops_table.link.stream;
    } else if (FS.isChrdev(node.mode)) {
      node.node_ops = MEMFS.ops_table.chrdev.node;
      node.stream_ops = MEMFS.ops_table.chrdev.stream;
    }
    node.timestamp = Date.now();
    if (parent) {
      parent.contents[name] = node;
      parent.timestamp = node.timestamp;
    }
    return node;
  },
  getFileDataAsTypedArray(node) {
    if (!node.contents) return new Uint8Array(0);
    if (node.contents.subarray)
      return node.contents.subarray(0, node.usedBytes);
    return new Uint8Array(node.contents);
  },
  expandFileStorage(node, newCapacity) {
    var prevCapacity = node.contents ? node.contents.length : 0;
    if (prevCapacity >= newCapacity) return;
    var CAPACITY_DOUBLING_MAX = 1024 * 1024;
    newCapacity = Math.max(
      newCapacity,
      (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2 : 1.125)) >>> 0
    );
    if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256);
    var oldContents = node.contents;
    node.contents = new Uint8Array(newCapacity);
    if (node.usedBytes > 0)
      node.contents.set(oldContents.subarray(0, node.usedBytes), 0);
  },
  resizeFileStorage(node, newSize) {
    if (node.usedBytes == newSize) return;
    if (newSize == 0) {
      node.contents = null;
      node.usedBytes = 0;
    } else {
      var oldContents = node.contents;
      node.contents = new Uint8Array(newSize);
      if (oldContents) {
        node.contents.set(
          oldContents.subarray(0, Math.min(newSize, node.usedBytes))
        );
      }
      node.usedBytes = newSize;
    }
  },
  node_ops: {
    getattr(node) {
      var attr = {};
      attr.dev = FS.isChrdev(node.mode) ? node.id : 1;
      attr.ino = node.id;
      attr.mode = node.mode;
      attr.nlink = 1;
      attr.uid = 0;
      attr.gid = 0;
      attr.rdev = node.rdev;
      if (FS.isDir(node.mode)) {
        attr.size = 4096;
      } else if (FS.isFile(node.mode)) {
        attr.size = node.usedBytes;
      } else if (FS.isLink(node.mode)) {
        attr.size = node.link.length;
      } else {
        attr.size = 0;
      }
      attr.atime = new Date(node.timestamp);
      attr.mtime = new Date(node.timestamp);
      attr.ctime = new Date(node.timestamp);
      attr.blksize = 4096;
      attr.blocks = Math.ceil(attr.size / attr.blksize);
      return attr;
    },
    setattr(node, attr) {
      if (attr.mode !== undefined) {
        node.mode = attr.mode;
      }
      if (attr.timestamp !== undefined) {
        node.timestamp = attr.timestamp;
      }
      if (attr.size !== undefined) {
        MEMFS.resizeFileStorage(node, attr.size);
      }
    },
    lookup(parent, name) {
      throw FS.genericErrors[44];
    },
    mknod(parent, name, mode, dev) {
      return MEMFS.createNode(parent, name, mode, dev);
    },
    rename(old_node, new_dir, new_name) {
      if (FS.isDir(old_node.mode)) {
        var new_node;
        try {
          new_node = FS.lookupNode(new_dir, new_name);
        } catch (e) {}
        if (new_node) {
          for (var i in new_node.contents) {
            throw new FS.ErrnoError(55);
          }
        }
      }
      delete old_node.parent.contents[old_node.name];
      old_node.parent.timestamp = Date.now();
      old_node.name = new_name;
      new_dir.contents[new_name] = old_node;
      new_dir.timestamp = old_node.parent.timestamp;
      old_node.parent = new_dir;
    },
    unlink(parent, name) {
      delete parent.contents[name];
      parent.timestamp = Date.now();
    },
    rmdir(parent, name) {
      var node = FS.lookupNode(parent, name);
      for (var i in node.contents) {
        throw new FS.ErrnoError(55);
      }
      delete parent.contents[name];
      parent.timestamp = Date.now();
    },
    readdir(node) {
      var entries = [".", ".."];
      for (var key in node.contents) {
        if (!node.contents.hasOwnProperty(key)) {
          continue;
        }
        entries.push(key);
      }
      return entries;
    },
    symlink(parent, newname, oldpath) {
      var node = MEMFS.createNode(parent, newname, 511 | 40960, 0);
      node.link = oldpath;
      return node;
    },
    readlink(node) {
      if (!FS.isLink(node.mode)) {
        throw new FS.ErrnoError(28);
      }
      return node.link;
    },
  },
  stream_ops: {
    read(stream, buffer, offset, length, position) {
      var contents = stream.node.contents;
      if (position >= stream.node.usedBytes) return 0;
      var size = Math.min(stream.node.usedBytes - position, length);
      assert(size >= 0);
      if (size > 8 && contents.subarray) {
        buffer.set(contents.subarray(position, position + size), offset);
      } else {
        for (var i = 0; i < size; i++)
          buffer[offset + i] = contents[position + i];
      }
      return size;
    },
    write(stream, buffer, offset, length, position, canOwn) {
      assert(!(buffer instanceof ArrayBuffer));
      if (buffer.buffer === HEAP8.buffer) {
        canOwn = false;
      }
      if (!length) return 0;
      var node = stream.node;
      node.timestamp = Date.now();
      if (buffer.subarray && (!node.contents || node.contents.subarray)) {
        if (canOwn) {
          assert(
            position === 0,
            "canOwn must imply no weird position inside the file"
          );
          node.contents = buffer.subarray(offset, offset + length);
          node.usedBytes = length;
          return length;
        } else if (node.usedBytes === 0 && position === 0) {
          node.contents = buffer.slice(offset, offset + length);
          node.usedBytes = length;
          return length;
        } else if (position + length <= node.usedBytes) {
          node.contents.set(buffer.subarray(offset, offset + length), position);
          return length;
        }
      }
      MEMFS.expandFileStorage(node, position + length);
      if (node.contents.subarray && buffer.subarray) {
        node.contents.set(buffer.subarray(offset, offset + length), position);
      } else {
        for (var i = 0; i < length; i++) {
          node.contents[position + i] = buffer[offset + i];
        }
      }
      node.usedBytes = Math.max(node.usedBytes, position + length);
      return length;
    },
    llseek(stream, offset, whence) {
      var position = offset;
      if (whence === 1) {
        position += stream.position;
      } else if (whence === 2) {
        if (FS.isFile(stream.node.mode)) {
          position += stream.node.usedBytes;
        }
      }
      if (position < 0) {
        throw new FS.ErrnoError(28);
      }
      return position;
    },
    allocate(stream, offset, length) {
      MEMFS.expandFileStorage(stream.node, offset + length);
      stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length);
    },
    mmap(stream, length, position, prot, flags) {
      if (!FS.isFile(stream.node.mode)) {
        throw new FS.ErrnoError(43);
      }
      var ptr;
      var allocated;
      var contents = stream.node.contents;
      if (!(flags & 2) && contents.buffer === HEAP8.buffer) {
        allocated = false;
        ptr = contents.byteOffset;
      } else {
        if (position > 0 || position + length < contents.length) {
          if (contents.subarray) {
            contents = contents.subarray(position, position + length);
          } else {
            contents = Array.prototype.slice.call(
              contents,
              position,
              position + length
            );
          }
        }
        allocated = true;
        ptr = mmapAlloc(length);
        if (!ptr) {
          throw new FS.ErrnoError(48);
        }
        HEAP8.set(contents, ptr);
      }
      return { ptr: ptr, allocated: allocated };
    },
    msync(stream, buffer, offset, length, mmapFlags) {
      MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false);
      return 0;
    },
  },
};
var asyncLoad = (url, onload, onerror, noRunDep) => {
  var dep = !noRunDep ? getUniqueRunDependency(`al ${url}`) : "";
  readAsync(
    url,
    (arrayBuffer) => {
      assert(
        arrayBuffer,
        `Loading data file "${url}" failed (no arrayBuffer).`
      );
      onload(new Uint8Array(arrayBuffer));
      if (dep) removeRunDependency(dep);
    },
    (event) => {
      if (onerror) {
        onerror();
      } else {
        throw `Loading data file "${url}" failed.`;
      }
    }
  );
  if (dep) addRunDependency(dep);
};
var FS_createDataFile = (parent, name, fileData, canRead, canWrite, canOwn) =>
  FS.createDataFile(parent, name, fileData, canRead, canWrite, canOwn);
var preloadPlugins = Module["preloadPlugins"] || [];
var FS_handledByPreloadPlugin = (byteArray, fullname, finish, onerror) => {
  if (typeof Browser != "undefined") Browser.init();
  var handled = false;
  preloadPlugins.forEach((plugin) => {
    if (handled) return;
    if (plugin["canHandle"](fullname)) {
      plugin["handle"](byteArray, fullname, finish, onerror);
      handled = true;
    }
  });
  return handled;
};
var FS_createPreloadedFile = (
  parent,
  name,
  url,
  canRead,
  canWrite,
  onload,
  onerror,
  dontCreateFile,
  canOwn,
  preFinish
) => {
  var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent;
  var dep = getUniqueRunDependency(`cp ${fullname}`);
  function processData(byteArray) {
    function finish(byteArray) {
      if (preFinish) preFinish();
      if (!dontCreateFile) {
        FS_createDataFile(parent, name, byteArray, canRead, canWrite, canOwn);
      }
      if (onload) onload();
      removeRunDependency(dep);
    }
    if (
      FS_handledByPreloadPlugin(byteArray, fullname, finish, () => {
        if (onerror) onerror();
        removeRunDependency(dep);
      })
    ) {
      return;
    }
    finish(byteArray);
  }
  addRunDependency(dep);
  if (typeof url == "string") {
    asyncLoad(url, (byteArray) => processData(byteArray), onerror);
  } else {
    processData(url);
  }
};
var FS_modeStringToFlags = (str) => {
  var flagModes = {
    r: 0,
    "r+": 2,
    w: 512 | 64 | 1,
    "w+": 512 | 64 | 2,
    a: 1024 | 64 | 1,
    "a+": 1024 | 64 | 2,
  };
  var flags = flagModes[str];
  if (typeof flags == "undefined") {
    throw new Error(`Unknown file open mode: ${str}`);
  }
  return flags;
};
var FS_getMode = (canRead, canWrite) => {
  var mode = 0;
  if (canRead) mode |= 292 | 73;
  if (canWrite) mode |= 146;
  return mode;
};
var ERRNO_MESSAGES = {
  0: "Success",
  1: "Arg list too long",
  2: "Permission denied",
  3: "Address already in use",
  4: "Address not available",
  5: "Address family not supported by protocol family",
  6: "No more processes",
  7: "Socket already connected",
  8: "Bad file number",
  9: "Trying to read unreadable message",
  10: "Mount device busy",
  11: "Operation canceled",
  12: "No children",
  13: "Connection aborted",
  14: "Connection refused",
  15: "Connection reset by peer",
  16: "File locking deadlock error",
  17: "Destination address required",
  18: "Math arg out of domain of func",
  19: "Quota exceeded",
  20: "File exists",
  21: "Bad address",
  22: "File too large",
  23: "Host is unreachable",
  24: "Identifier removed",
  25: "Illegal byte sequence",
  26: "Connection already in progress",
  27: "Interrupted system call",
  28: "Invalid argument",
  29: "I/O error",
  30: "Socket is already connected",
  31: "Is a directory",
  32: "Too many symbolic links",
  33: "Too many open files",
  34: "Too many links",
  35: "Message too long",
  36: "Multihop attempted",
  37: "File or path name too long",
  38: "Network interface is not configured",
  39: "Connection reset by network",
  40: "Network is unreachable",
  41: "Too many open files in system",
  42: "No buffer space available",
  43: "No such device",
  44: "No such file or directory",
  45: "Exec format error",
  46: "No record locks available",
  47: "The link has been severed",
  48: "Not enough core",
  49: "No message of desired type",
  50: "Protocol not available",
  51: "No space left on device",
  52: "Function not implemented",
  53: "Socket is not connected",
  54: "Not a directory",
  55: "Directory not empty",
  56: "State not recoverable",
  57: "Socket operation on non-socket",
  59: "Not a typewriter",
  60: "No such device or address",
  61: "Value too large for defined data type",
  62: "Previous owner died",
  63: "Not super-user",
  64: "Broken pipe",
  65: "Protocol error",
  66: "Unknown protocol",
  67: "Protocol wrong type for socket",
  68: "Math result not representable",
  69: "Read only file system",
  70: "Illegal seek",
  71: "No such process",
  72: "Stale file handle",
  73: "Connection timed out",
  74: "Text file busy",
  75: "Cross-device link",
  100: "Device not a stream",
  101: "Bad font file fmt",
  102: "Invalid slot",
  103: "Invalid request code",
  104: "No anode",
  105: "Block device required",
  106: "Channel number out of range",
  107: "Level 3 halted",
  108: "Level 3 reset",
  109: "Link number out of range",
  110: "Protocol driver not attached",
  111: "No CSI structure available",
  112: "Level 2 halted",
  113: "Invalid exchange",
  114: "Invalid request descriptor",
  115: "Exchange full",
  116: "No data (for no delay io)",
  117: "Timer expired",
  118: "Out of streams resources",
  119: "Machine is not on the network",
  120: "Package not installed",
  121: "The object is remote",
  122: "Advertise error",
  123: "Srmount error",
  124: "Communication error on send",
  125: "Cross mount point (not really error)",
  126: "Given log. name not unique",
  127: "f.d. invalid for this operation",
  128: "Remote address changed",
  129: "Can   access a needed shared lib",
  130: "Accessing a corrupted shared lib",
  131: ".lib section in a.out corrupted",
  132: "Attempting to link in too many libs",
  133: "Attempting to exec a shared library",
  135: "Streams pipe error",
  136: "Too many users",
  137: "Socket type not supported",
  138: "Not supported",
  139: "Protocol family not supported",
  140: "Can't send after socket shutdown",
  141: "Too many references",
  142: "Host is down",
  148: "No medium (in tape drive)",
  156: "Level 2 not synchronized",
};
var ERRNO_CODES = {};
var demangle = (func) => {
  warnOnce(
    "warning: build with -sDEMANGLE_SUPPORT to link in libcxxabi demangling"
  );
  return func;
};
var demangleAll = (text) => {
  var regex = /\b_Z[\w\d_]+/g;
  return text.replace(regex, function (x) {
    var y = demangle(x);
    return x === y ? x : y + " [" + x + "]";
  });
};
var FS = {
  root: null,
  mounts: [],
  devices: {},
  streams: [],
  nextInode: 1,
  nameTable: null,
  currentPath: "/",
  initialized: false,
  ignorePermissions: true,
  ErrnoError: null,
  genericErrors: {},
  filesystems: null,
  syncFSRequests: 0,
  lookupPath(path, opts = {}) {
    path = PATH_FS.resolve(path);
    if (!path) return { path: "", node: null };
    var defaults = { follow_mount: true, recurse_count: 0 };
    opts = Object.assign(defaults, opts);
    if (opts.recurse_count > 8) {
      throw new FS.ErrnoError(32);
    }
    var parts = path.split("/").filter((p) => !!p);
    var current = FS.root;
    var current_path = "/";
    for (var i = 0; i < parts.length; i++) {
      var islast = i === parts.length - 1;
      if (islast && opts.parent) {
        break;
      }
      current = FS.lookupNode(current, parts[i]);
      current_path = PATH.join2(current_path, parts[i]);
      if (FS.isMountpoint(current)) {
        if (!islast || (islast && opts.follow_mount)) {
          current = current.mounted.root;
        }
      }
      if (!islast || opts.follow) {
        var count = 0;
        while (FS.isLink(current.mode)) {
          var link = FS.readlink(current_path);
          current_path = PATH_FS.resolve(PATH.dirname(current_path), link);
          var lookup = FS.lookupPath(current_path, {
            recurse_count: opts.recurse_count + 1,
          });
          current = lookup.node;
          if (count++ > 40) {
            throw new FS.ErrnoError(32);
          }
        }
      }
    }
    return { path: current_path, node: current };
  },
  getPath(node) {
    var path;
    while (true) {
      if (FS.isRoot(node)) {
        var mount = node.mount.mountpoint;
        if (!path) return mount;
        return mount[mount.length - 1] !== "/"
          ? `${mount}/${path}`
          : mount + path;
      }
      path = path ? `${node.name}/${path}` : node.name;
      node = node.parent;
    }
  },
  hashName(parentid, name) {
    var hash = 0;
    for (var i = 0; i < name.length; i++) {
      hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0;
    }
    return ((parentid + hash) >>> 0) % FS.nameTable.length;
  },
  hashAddNode(node) {
    var hash = FS.hashName(node.parent.id, node.name);
    node.name_next = FS.nameTable[hash];
    FS.nameTable[hash] = node;
  },
  hashRemoveNode(node) {
    var hash = FS.hashName(node.parent.id, node.name);
    if (FS.nameTable[hash] === node) {
      FS.nameTable[hash] = node.name_next;
    } else {
      var current = FS.nameTable[hash];
      while (current) {
        if (current.name_next === node) {
          current.name_next = node.name_next;
          break;
        }
        current = current.name_next;
      }
    }
  },
  lookupNode(parent, name) {
    var errCode = FS.mayLookup(parent);
    if (errCode) {
      throw new FS.ErrnoError(errCode, parent);
    }
    var hash = FS.hashName(parent.id, name);
    for (var node = FS.nameTable[hash]; node; node = node.name_next) {
      var nodeName = node.name;
      if (node.parent.id === parent.id && nodeName === name) {
        return node;
      }
    }
    return FS.lookup(parent, name);
  },
  createNode(parent, name, mode, rdev) {
    assert(typeof parent == "object");
    var node = new FS.FSNode(parent, name, mode, rdev);
    FS.hashAddNode(node);
    return node;
  },
  destroyNode(node) {
    FS.hashRemoveNode(node);
  },
  isRoot(node) {
    return node === node.parent;
  },
  isMountpoint(node) {
    return !!node.mounted;
  },
  isFile(mode) {
    return (mode & 61440) === 32768;
  },
  isDir(mode) {
    return (mode & 61440) === 16384;
  },
  isLink(mode) {
    return (mode & 61440) === 40960;
  },
  isChrdev(mode) {
    return (mode & 61440) === 8192;
  },
  isBlkdev(mode) {
    return (mode & 61440) === 24576;
  },
  isFIFO(mode) {
    return (mode & 61440) === 4096;
  },
  isSocket(mode) {
    return (mode & 49152) === 49152;
  },
  flagsToPermissionString(flag) {
    var perms = ["r", "w", "rw"][flag & 3];
    if (flag & 512) {
      perms += "w";
    }
    return perms;
  },
  nodePermissions(node, perms) {
    if (FS.ignorePermissions) {
      return 0;
    }
    if (perms.includes("r") && !(node.mode & 292)) {
      return 2;
    } else if (perms.includes("w") && !(node.mode & 146)) {
      return 2;
    } else if (perms.includes("x") && !(node.mode & 73)) {
      return 2;
    }
    return 0;
  },
  mayLookup(dir) {
    var errCode = FS.nodePermissions(dir, "x");
    if (errCode) return errCode;
    if (!dir.node_ops.lookup) return 2;
    return 0;
  },
  mayCreate(dir, name) {
    try {
      var node = FS.lookupNode(dir, name);
      return 20;
    } catch (e) {}
    return FS.nodePermissions(dir, "wx");
  },
  mayDelete(dir, name, isdir) {
    var node;
    try {
      node = FS.lookupNode(dir, name);
    } catch (e) {
      return e.errno;
    }
    var errCode = FS.nodePermissions(dir, "wx");
    if (errCode) {
      return errCode;
    }
    if (isdir) {
      if (!FS.isDir(node.mode)) {
        return 54;
      }
      if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) {
        return 10;
      }
    } else {
      if (FS.isDir(node.mode)) {
        return 31;
      }
    }
    return 0;
  },
  mayOpen(node, flags) {
    if (!node) {
      return 44;
    }
    if (FS.isLink(node.mode)) {
      return 32;
    } else if (FS.isDir(node.mode)) {
      if (FS.flagsToPermissionString(flags) !== "r" || flags & 512) {
        return 31;
      }
    }
    return FS.nodePermissions(node, FS.flagsToPermissionString(flags));
  },
  MAX_OPEN_FDS: 4096,
  nextfd() {
    for (var fd = 0; fd <= FS.MAX_OPEN_FDS; fd++) {
      if (!FS.streams[fd]) {
        return fd;
      }
    }
    throw new FS.ErrnoError(33);
  },
  getStreamChecked(fd) {
    var stream = FS.getStream(fd);
    if (!stream) {
      throw new FS.ErrnoError(8);
    }
    return stream;
  },
  getStream: (fd) => FS.streams[fd],
  createStream(stream, fd = -1) {
    if (!FS.FSStream) {
      FS.FSStream = function () {
        this.shared = {};
      };
      FS.FSStream.prototype = {};
      Object.defineProperties(FS.FSStream.prototype, {
        object: {
          get() {
            return this.node;
          },
          set(val) {
            this.node = val;
          },
        },
        isRead: {
          get() {
            return (this.flags & 2097155) !== 1;
          },
        },
        isWrite: {
          get() {
            return (this.flags & 2097155) !== 0;
          },
        },
        isAppend: {
          get() {
            return this.flags & 1024;
          },
        },
        flags: {
          get() {
            return this.shared.flags;
          },
          set(val) {
            this.shared.flags = val;
          },
        },
        position: {
          get() {
            return this.shared.position;
          },
          set(val) {
            this.shared.position = val;
          },
        },
      });
    }
    stream = Object.assign(new FS.FSStream(), stream);
    if (fd == -1) {
      fd = FS.nextfd();
    }
    stream.fd = fd;
    FS.streams[fd] = stream;
    return stream;
  },
  closeStream(fd) {
    FS.streams[fd] = null;
  },
  chrdev_stream_ops: {
    open(stream) {
      var device = FS.getDevice(stream.node.rdev);
      stream.stream_ops = device.stream_ops;
      if (stream.stream_ops.open) {
        stream.stream_ops.open(stream);
      }
    },
    llseek() {
      throw new FS.ErrnoError(70);
    },
  },
  major: (dev) => dev >> 8,
  minor: (dev) => dev & 255,
  makedev: (ma, mi) => (ma << 8) | mi,
  registerDevice(dev, ops) {
    FS.devices[dev] = { stream_ops: ops };
  },
  getDevice: (dev) => FS.devices[dev],
  getMounts(mount) {
    var mounts = [];
    var check = [mount];
    while (check.length) {
      var m = check.pop();
      mounts.push(m);
      check.push.apply(check, m.mounts);
    }
    return mounts;
  },
  syncfs(populate, callback) {
    if (typeof populate == "function") {
      callback = populate;
      populate = false;
    }
    FS.syncFSRequests++;
    if (FS.syncFSRequests > 1) {
      err(
        `warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`
      );
    }
    var mounts = FS.getMounts(FS.root.mount);
    var completed = 0;
    function doCallback(errCode) {
      assert(FS.syncFSRequests > 0);
      FS.syncFSRequests--;
      return callback(errCode);
    }
    function done(errCode) {
      if (errCode) {
        if (!done.errored) {
          done.errored = true;
          return doCallback(errCode);
        }
        return;
      }
      if (++completed >= mounts.length) {
        doCallback(null);
      }
    }
    mounts.forEach((mount) => {
      if (!mount.type.syncfs) {
        return done(null);
      }
      mount.type.syncfs(mount, populate, done);
    });
  },
  mount(type, opts, mountpoint) {
    if (typeof type == "string") {
      throw type;
    }
    var root = mountpoint === "/";
    var pseudo = !mountpoint;
    var node;
    if (root && FS.root) {
      throw new FS.ErrnoError(10);
    } else if (!root && !pseudo) {
      var lookup = FS.lookupPath(mountpoint, { follow_mount: false });
      mountpoint = lookup.path;
      node = lookup.node;
      if (FS.isMountpoint(node)) {
        throw new FS.ErrnoError(10);
      }
      if (!FS.isDir(node.mode)) {
        throw new FS.ErrnoError(54);
      }
    }
    var mount = { type: type, opts: opts, mountpoint: mountpoint, mounts: [] };
    var mountRoot = type.mount(mount);
    mountRoot.mount = mount;
    mount.root = mountRoot;
    if (root) {
      FS.root = mountRoot;
    } else if (node) {
      node.mounted = mount;
      if (node.mount) {
        node.mount.mounts.push(mount);
      }
    }
    return mountRoot;
  },
  unmount(mountpoint) {
    var lookup = FS.lookupPath(mountpoint, { follow_mount: false });
    if (!FS.isMountpoint(lookup.node)) {
      throw new FS.ErrnoError(28);
    }
    var node = lookup.node;
    var mount = node.mounted;
    var mounts = FS.getMounts(mount);
    Object.keys(FS.nameTable).forEach((hash) => {
      var current = FS.nameTable[hash];
      while (current) {
        var next = current.name_next;
        if (mounts.includes(current.mount)) {
          FS.destroyNode(current);
        }
        current = next;
      }
    });
    node.mounted = null;
    var idx = node.mount.mounts.indexOf(mount);
    assert(idx !== -1);
    node.mount.mounts.splice(idx, 1);
  },
  lookup(parent, name) {
    return parent.node_ops.lookup(parent, name);
  },
  mknod(path, mode, dev) {
    var lookup = FS.lookupPath(path, { parent: true });
    var parent = lookup.node;
    var name = PATH.basename(path);
    if (!name || name === "." || name === "..") {
      throw new FS.ErrnoError(28);
    }
    var errCode = FS.mayCreate(parent, name);
    if (errCode) {
      throw new FS.ErrnoError(errCode);
    }
    if (!parent.node_ops.mknod) {
      throw new FS.ErrnoError(63);
    }
    return parent.node_ops.mknod(parent, name, mode, dev);
  },
  create(path, mode) {
    mode = mode !== undefined ? mode : 438;
    mode &= 4095;
    mode |= 32768;
    return FS.mknod(path, mode, 0);
  },
  mkdir(path, mode) {
    mode = mode !== undefined ? mode : 511;
    mode &= 511 | 512;
    mode |= 16384;
    return FS.mknod(path, mode, 0);
  },
  mkdirTree(path, mode) {
    var dirs = path.split("/");
    var d = "";
    for (var i = 0; i < dirs.length; ++i) {
      if (!dirs[i]) continue;
      d += "/" + dirs[i];
      try {
        FS.mkdir(d, mode);
      } catch (e) {
        if (e.errno != 20) throw e;
      }
    }
  },
  mkdev(path, mode, dev) {
    if (typeof dev == "undefined") {
      dev = mode;
      mode = 438;
    }
    mode |= 8192;
    return FS.mknod(path, mode, dev);
  },
  symlink(oldpath, newpath) {
    if (!PATH_FS.resolve(oldpath)) {
      throw new FS.ErrnoError(44);
    }
    var lookup = FS.lookupPath(newpath, { parent: true });
    var parent = lookup.node;
    if (!parent) {
      throw new FS.ErrnoError(44);
    }
    var newname = PATH.basename(newpath);
    var errCode = FS.mayCreate(parent, newname);
    if (errCode) {
      throw new FS.ErrnoError(errCode);
    }
    if (!parent.node_ops.symlink) {
      throw new FS.ErrnoError(63);
    }
    return parent.node_ops.symlink(parent, newname, oldpath);
  },
  rename(old_path, new_path) {
    var old_dirname = PATH.dirname(old_path);
    var new_dirname = PATH.dirname(new_path);
    var old_name = PATH.basename(old_path);
    var new_name = PATH.basename(new_path);
    var lookup, old_dir, new_dir;
    lookup = FS.lookupPath(old_path, { parent: true });
    old_dir = lookup.node;
    lookup = FS.lookupPath(new_path, { parent: true });
    new_dir = lookup.node;
    if (!old_dir || !new_dir) throw new FS.ErrnoError(44);
    if (old_dir.mount !== new_dir.mount) {
      throw new FS.ErrnoError(75);
    }
    var old_node = FS.lookupNode(old_dir, old_name);
    var relative = PATH_FS.relative(old_path, new_dirname);
    if (relative.charAt(0) !== ".") {
      throw new FS.ErrnoError(28);
    }
    relative = PATH_FS.relative(new_path, old_dirname);
    if (relative.charAt(0) !== ".") {
      throw new FS.ErrnoError(55);
    }
    var new_node;
    try {
      new_node = FS.lookupNode(new_dir, new_name);
    } catch (e) {}
    if (old_node === new_node) {
      return;
    }
    var isdir = FS.isDir(old_node.mode);
    var errCode = FS.mayDelete(old_dir, old_name, isdir);
    if (errCode) {
      throw new FS.ErrnoError(errCode);
    }
    errCode = new_node
      ? FS.mayDelete(new_dir, new_name, isdir)
      : FS.mayCreate(new_dir, new_name);
    if (errCode) {
      throw new FS.ErrnoError(errCode);
    }
    if (!old_dir.node_ops.rename) {
      throw new FS.ErrnoError(63);
    }
    if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) {
      throw new FS.ErrnoError(10);
    }
    if (new_dir !== old_dir) {
      errCode = FS.nodePermissions(old_dir, "w");
      if (errCode) {
        throw new FS.ErrnoError(errCode);
      }
    }
    FS.hashRemoveNode(old_node);
    try {
      old_dir.node_ops.rename(old_node, new_dir, new_name);
    } catch (e) {
      throw e;
    } finally {
      FS.hashAddNode(old_node);
    }
  },
  rmdir(path) {
    var lookup = FS.lookupPath(path, { parent: true });
    var parent = lookup.node;
    var name = PATH.basename(path);
    var node = FS.lookupNode(parent, name);
    var errCode = FS.mayDelete(parent, name, true);
    if (errCode) {
      throw new FS.ErrnoError(errCode);
    }
    if (!parent.node_ops.rmdir) {
      throw new FS.ErrnoError(63);
    }
    if (FS.isMountpoint(node)) {
      throw new FS.ErrnoError(10);
    }
    parent.node_ops.rmdir(parent, name);
    FS.destroyNode(node);
  },
  readdir(path) {
    var lookup = FS.lookupPath(path, { follow: true });
    var node = lookup.node;
    if (!node.node_ops.readdir) {
      throw new FS.ErrnoError(54);
    }
    return node.node_ops.readdir(node);
  },
  unlink(path) {
    var lookup = FS.lookupPath(path, { parent: true });
    var parent = lookup.node;
    if (!parent) {
      throw new FS.ErrnoError(44);
    }
    var name = PATH.basename(path);
    var node = FS.lookupNode(parent, name);
    var errCode = FS.mayDelete(parent, name, false);
    if (errCode) {
      throw new FS.ErrnoError(errCode);
    }
    if (!parent.node_ops.unlink) {
      throw new FS.ErrnoError(63);
    }
    if (FS.isMountpoint(node)) {
      throw new FS.ErrnoError(10);
    }
    parent.node_ops.unlink(parent, name);
    FS.destroyNode(node);
  },
  readlink(path) {
    var lookup = FS.lookupPath(path);
    var link = lookup.node;
    if (!link) {
      throw new FS.ErrnoError(44);
    }
    if (!link.node_ops.readlink) {
      throw new FS.ErrnoError(28);
    }
    return PATH_FS.resolve(
      FS.getPath(link.parent),
      link.node_ops.readlink(link)
    );
  },
  stat(path, dontFollow) {
    var lookup = FS.lookupPath(path, { follow: !dontFollow });
    var node = lookup.node;
    if (!node) {
      throw new FS.ErrnoError(44);
    }
    if (!node.node_ops.getattr) {
      throw new FS.ErrnoError(63);
    }
    return node.node_ops.getattr(node);
  },
  lstat(path) {
    return FS.stat(path, true);
  },
  chmod(path, mode, dontFollow) {
    var node;
    if (typeof path == "string") {
      var lookup = FS.lookupPath(path, { follow: !dontFollow });
      node = lookup.node;
    } else {
      node = path;
    }
    if (!node.node_ops.setattr) {
      throw new FS.ErrnoError(63);
    }
    node.node_ops.setattr(node, {
      mode: (mode & 4095) | (node.mode & ~4095),
      timestamp: Date.now(),
    });
  },
  lchmod(path, mode) {
    FS.chmod(path, mode, true);
  },
  fchmod(fd, mode) {
    var stream = FS.getStreamChecked(fd);
    FS.chmod(stream.node, mode);
  },
  chown(path, uid, gid, dontFollow) {
    var node;
    if (typeof path == "string") {
      var lookup = FS.lookupPath(path, { follow: !dontFollow });
      node = lookup.node;
    } else {
      node = path;
    }
    if (!node.node_ops.setattr) {
      throw new FS.ErrnoError(63);
    }
    node.node_ops.setattr(node, { timestamp: Date.now() });
  },
  lchown(path, uid, gid) {
    FS.chown(path, uid, gid, true);
  },
  fchown(fd, uid, gid) {
    var stream = FS.getStreamChecked(fd);
    FS.chown(stream.node, uid, gid);
  },
  truncate(path, len) {
    if (len < 0) {
      throw new FS.ErrnoError(28);
    }
    var node;
    if (typeof path == "string") {
      var lookup = FS.lookupPath(path, { follow: true });
      node = lookup.node;
    } else {
      node = path;
    }
    if (!node.node_ops.setattr) {
      throw new FS.ErrnoError(63);
    }
    if (FS.isDir(node.mode)) {
      throw new FS.ErrnoError(31);
    }
    if (!FS.isFile(node.mode)) {
      throw new FS.ErrnoError(28);
    }
    var errCode = FS.nodePermissions(node, "w");
    if (errCode) {
      throw new FS.ErrnoError(errCode);
    }
    node.node_ops.setattr(node, { size: len, timestamp: Date.now() });
  },
  ftruncate(fd, len) {
    var stream = FS.getStreamChecked(fd);
    if ((stream.flags & 2097155) === 0) {
      throw new FS.ErrnoError(28);
    }
    FS.truncate(stream.node, len);
  },
  utime(path, atime, mtime) {
    var lookup = FS.lookupPath(path, { follow: true });
    var node = lookup.node;
    node.node_ops.setattr(node, { timestamp: Math.max(atime, mtime) });
  },
  open(path, flags, mode) {
    if (path === "") {
      throw new FS.ErrnoError(44);
    }
    flags = typeof flags == "string" ? FS_modeStringToFlags(flags) : flags;
    mode = typeof mode == "undefined" ? 438 : mode;
    if (flags & 64) {
      mode = (mode & 4095) | 32768;
    } else {
      mode = 0;
    }
    var node;
    if (typeof path == "object") {
      node = path;
    } else {
      path = PATH.normalize(path);
      try {
        var lookup = FS.lookupPath(path, { follow: !(flags & 131072) });
        node = lookup.node;
      } catch (e) {}
    }
    var created = false;
    if (flags & 64) {
      if (node) {
        if (flags & 128) {
          throw new FS.ErrnoError(20);
        }
      } else {
        node = FS.mknod(path, mode, 0);
        created = true;
      }
    }
    if (!node) {
      throw new FS.ErrnoError(44);
    }
    if (FS.isChrdev(node.mode)) {
      flags &= ~512;
    }
    if (flags & 65536 && !FS.isDir(node.mode)) {
      throw new FS.ErrnoError(54);
    }
    if (!created) {
      var errCode = FS.mayOpen(node, flags);
      if (errCode) {
        throw new FS.ErrnoError(errCode);
      }
    }
    if (flags & 512 && !created) {
      FS.truncate(node, 0);
    }
    flags &= ~(128 | 512 | 131072);
    var stream = FS.createStream({
      node: node,
      path: FS.getPath(node),
      flags: flags,
      seekable: true,
      position: 0,
      stream_ops: node.stream_ops,
      ungotten: [],
      error: false,
    });
    if (stream.stream_ops.open) {
      stream.stream_ops.open(stream);
    }
    if (Module["logReadFiles"] && !(flags & 1)) {
      if (!FS.readFiles) FS.readFiles = {};
      if (!(path in FS.readFiles)) {
        FS.readFiles[path] = 1;
      }
    }
    return stream;
  },
  close(stream) {
    if (FS.isClosed(stream)) {
      throw new FS.ErrnoError(8);
    }
    if (stream.getdents) stream.getdents = null;
    try {
      if (stream.stream_ops.close) {
        stream.stream_ops.close(stream);
      }
    } catch (e) {
      throw e;
    } finally {
      FS.closeStream(stream.fd);
    }
    stream.fd = null;
  },
  isClosed(stream) {
    return stream.fd === null;
  },
  llseek(stream, offset, whence) {
    if (FS.isClosed(stream)) {
      throw new FS.ErrnoError(8);
    }
    if (!stream.seekable || !stream.stream_ops.llseek) {
      throw new FS.ErrnoError(70);
    }
    if (whence != 0 && whence != 1 && whence != 2) {
      throw new FS.ErrnoError(28);
    }
    stream.position = stream.stream_ops.llseek(stream, offset, whence);
    stream.ungotten = [];
    return stream.position;
  },
  read(stream, buffer, offset, length, position) {
    assert(offset >= 0);
    if (length < 0 || position < 0) {
      throw new FS.ErrnoError(28);
    }
    if (FS.isClosed(stream)) {
      throw new FS.ErrnoError(8);
    }
    if ((stream.flags & 2097155) === 1) {
      throw new FS.ErrnoError(8);
    }
    if (FS.isDir(stream.node.mode)) {
      throw new FS.ErrnoError(31);
    }
    if (!stream.stream_ops.read) {
      throw new FS.ErrnoError(28);
    }
    var seeking = typeof position != "undefined";
    if (!seeking) {
      position = stream.position;
    } else if (!stream.seekable) {
      throw new FS.ErrnoError(70);
    }
    var bytesRead = stream.stream_ops.read(
      stream,
      buffer,
      offset,
      length,
      position
    );
    if (!seeking) stream.position += bytesRead;
    return bytesRead;
  },
  write(stream, buffer, offset, length, position, canOwn) {
    assert(offset >= 0);
    if (length < 0 || position < 0) {
      throw new FS.ErrnoError(28);
    }
    if (FS.isClosed(stream)) {
      throw new FS.ErrnoError(8);
    }
    if ((stream.flags & 2097155) === 0) {
      throw new FS.ErrnoError(8);
    }
    if (FS.isDir(stream.node.mode)) {
      throw new FS.ErrnoError(31);
    }
    if (!stream.stream_ops.write) {
      throw new FS.ErrnoError(28);
    }
    if (stream.seekable && stream.flags & 1024) {
      FS.llseek(stream, 0, 2);
    }
    var seeking = typeof position != "undefined";
    if (!seeking) {
      position = stream.position;
    } else if (!stream.seekable) {
      throw new FS.ErrnoError(70);
    }
    var bytesWritten = stream.stream_ops.write(
      stream,
      buffer,
      offset,
      length,
      position,
      canOwn
    );
    if (!seeking) stream.position += bytesWritten;
    return bytesWritten;
  },
  allocate(stream, offset, length) {
    if (FS.isClosed(stream)) {
      throw new FS.ErrnoError(8);
    }
    if (offset < 0 || length <= 0) {
      throw new FS.ErrnoError(28);
    }
    if ((stream.flags & 2097155) === 0) {
      throw new FS.ErrnoError(8);
    }
    if (!FS.isFile(stream.node.mode) && !FS.isDir(stream.node.mode)) {
      throw new FS.ErrnoError(43);
    }
    if (!stream.stream_ops.allocate) {
      throw new FS.ErrnoError(138);
    }
    stream.stream_ops.allocate(stream, offset, length);
  },
  mmap(stream, length, position, prot, flags) {
    if (
      (prot & 2) !== 0 &&
      (flags & 2) === 0 &&
      (stream.flags & 2097155) !== 2
    ) {
      throw new FS.ErrnoError(2);
    }
    if ((stream.flags & 2097155) === 1) {
      throw new FS.ErrnoError(2);
    }
    if (!stream.stream_ops.mmap) {
      throw new FS.ErrnoError(43);
    }
    return stream.stream_ops.mmap(stream, length, position, prot, flags);
  },
  msync(stream, buffer, offset, length, mmapFlags) {
    assert(offset >= 0);
    if (!stream.stream_ops.msync) {
      return 0;
    }
    return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags);
  },
  munmap: (stream) => 0,
  ioctl(stream, cmd, arg) {
    if (!stream.stream_ops.ioctl) {
      throw new FS.ErrnoError(59);
    }
    return stream.stream_ops.ioctl(stream, cmd, arg);
  },
  readFile(path, opts = {}) {
    opts.flags = opts.flags || 0;
    opts.encoding = opts.encoding || "binary";
    if (opts.encoding !== "utf8" && opts.encoding !== "binary") {
      throw new Error(`Invalid encoding type "${opts.encoding}"`);
    }
    var ret;
    var stream = FS.open(path, opts.flags);
    var stat = FS.stat(path);
    var length = stat.size;
    var buf = new Uint8Array(length);
    FS.read(stream, buf, 0, length, 0);
    if (opts.encoding === "utf8") {
      ret = UTF8ArrayToString(buf, 0);
    } else if (opts.encoding === "binary") {
      ret = buf;
    }
    FS.close(stream);
    return ret;
  },
  writeFile(path, data, opts = {}) {
    opts.flags = opts.flags || 577;
    var stream = FS.open(path, opts.flags, opts.mode);
    if (typeof data == "string") {
      var buf = new Uint8Array(lengthBytesUTF8(data) + 1);
      var actualNumBytes = stringToUTF8Array(data, buf, 0, buf.length);
      FS.write(stream, buf, 0, actualNumBytes, undefined, opts.canOwn);
    } else if (ArrayBuffer.isView(data)) {
      FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
    } else {
      throw new Error("Unsupported data type");
    }
    FS.close(stream);
  },
  cwd: () => FS.currentPath,
  chdir(path) {
    var lookup = FS.lookupPath(path, { follow: true });
    if (lookup.node === null) {
      throw new FS.ErrnoError(44);
    }
    if (!FS.isDir(lookup.node.mode)) {
      throw new FS.ErrnoError(54);
    }
    var errCode = FS.nodePermissions(lookup.node, "x");
    if (errCode) {
      throw new FS.ErrnoError(errCode);
    }
    FS.currentPath = lookup.path;
  },
  createDefaultDirectories() {
    FS.mkdir("/tmp");
    FS.mkdir("/home");
    FS.mkdir("/home/web_user");
  },
  createDefaultDevices() {
    FS.mkdir("/dev");
    FS.registerDevice(FS.makedev(1, 3), {
      read: () => 0,
      write: (stream, buffer, offset, length, pos) => length,
    });
    FS.mkdev("/dev/null", FS.makedev(1, 3));
    TTY.register(FS.makedev(5, 0), TTY.default_tty_ops);
    TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops);
    FS.mkdev("/dev/tty", FS.makedev(5, 0));
    FS.mkdev("/dev/tty1", FS.makedev(6, 0));
    var randomBuffer = new Uint8Array(1024),
      randomLeft = 0;
    var randomByte = () => {
      if (randomLeft === 0) {
        randomLeft = randomFill(randomBuffer).byteLength;
      }
      return randomBuffer[--randomLeft];
    };
    FS.createDevice("/dev", "random", randomByte);
    FS.createDevice("/dev", "urandom", randomByte);
    FS.mkdir("/dev/shm");
    FS.mkdir("/dev/shm/tmp");
  },
  createSpecialDirectories() {
    FS.mkdir("/proc");
    var proc_self = FS.mkdir("/proc/self");
    FS.mkdir("/proc/self/fd");
    FS.mount(
      {
        mount() {
          var node = FS.createNode(proc_self, "fd", 16384 | 511, 73);
          node.node_ops = {
            lookup(parent, name) {
              var fd = +name;
              var stream = FS.getStreamChecked(fd);
              var ret = {
                parent: null,
                mount: { mountpoint: "fake" },
                node_ops: { readlink: () => stream.path },
              };
              ret.parent = ret;
              return ret;
            },
          };
          return node;
        },
      },
      {},
      "/proc/self/fd"
    );
  },
  createStandardStreams() {
    if (Module["stdin"]) {
      FS.createDevice("/dev", "stdin", Module["stdin"]);
    } else {
      FS.symlink("/dev/tty", "/dev/stdin");
    }
    if (Module["stdout"]) {
      FS.createDevice("/dev", "stdout", null, Module["stdout"]);
    } else {
      FS.symlink("/dev/tty", "/dev/stdout");
    }
    if (Module["stderr"]) {
      FS.createDevice("/dev", "stderr", null, Module["stderr"]);
    } else {
      FS.symlink("/dev/tty1", "/dev/stderr");
    }
    var stdin = FS.open("/dev/stdin", 0);
    var stdout = FS.open("/dev/stdout", 1);
    var stderr = FS.open("/dev/stderr", 1);
    assert(stdin.fd === 0, `invalid handle for stdin (${stdin.fd})`);
    assert(stdout.fd === 1, `invalid handle for stdout (${stdout.fd})`);
    assert(stderr.fd === 2, `invalid handle for stderr (${stderr.fd})`);
  },
  ensureErrnoError() {
    if (FS.ErrnoError) return;
    FS.ErrnoError = function ErrnoError(errno, node) {
      this.name = "ErrnoError";
      this.node = node;
      this.setErrno = function (errno) {
        this.errno = errno;
        for (var key in ERRNO_CODES) {
          if (ERRNO_CODES[key] === errno) {
            this.code = key;
            break;
          }
        }
      };
      this.setErrno(errno);
      this.message = ERRNO_MESSAGES[errno];
      if (this.stack) {
        Object.defineProperty(this, "stack", {
          value: new Error().stack,
          writable: true,
        });
        this.stack = demangleAll(this.stack);
      }
    };
    FS.ErrnoError.prototype = new Error();
    FS.ErrnoError.prototype.constructor = FS.ErrnoError;
    [44].forEach((code) => {
      FS.genericErrors[code] = new FS.ErrnoError(code);
      FS.genericErrors[code].stack = "<generic error, no stack>";
    });
  },
  staticInit() {
    FS.ensureErrnoError();
    FS.nameTable = new Array(4096);
    FS.mount(MEMFS, {}, "/");
    FS.createDefaultDirectories();
    FS.createDefaultDevices();
    FS.createSpecialDirectories();
    FS.filesystems = { MEMFS: MEMFS };
  },
  init(input, output, error) {
    assert(
      !FS.init.initialized,
      "FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)"
    );
    FS.init.initialized = true;
    FS.ensureErrnoError();
    Module["stdin"] = input || Module["stdin"];
    Module["stdout"] = output || Module["stdout"];
    Module["stderr"] = error || Module["stderr"];
    FS.createStandardStreams();
  },
  quit() {
    FS.init.initialized = false;
    _fflush(0);
    for (var i = 0; i < FS.streams.length; i++) {
      var stream = FS.streams[i];
      if (!stream) {
        continue;
      }
      FS.close(stream);
    }
  },
  findObject(path, dontResolveLastLink) {
    var ret = FS.analyzePath(path, dontResolveLastLink);
    if (!ret.exists) {
      return null;
    }
    return ret.object;
  },
  analyzePath(path, dontResolveLastLink) {
    try {
      var lookup = FS.lookupPath(path, { follow: !dontResolveLastLink });
      path = lookup.path;
    } catch (e) {}
    var ret = {
      isRoot: false,
      exists: false,
      error: 0,
      name: null,
      path: null,
      object: null,
      parentExists: false,
      parentPath: null,
      parentObject: null,
    };
    try {
      var lookup = FS.lookupPath(path, { parent: true });
      ret.parentExists = true;
      ret.parentPath = lookup.path;
      ret.parentObject = lookup.node;
      ret.name = PATH.basename(path);
      lookup = FS.lookupPath(path, { follow: !dontResolveLastLink });
      ret.exists = true;
      ret.path = lookup.path;
      ret.object = lookup.node;
      ret.name = lookup.node.name;
      ret.isRoot = lookup.path === "/";
    } catch (e) {
      ret.error = e.errno;
    }
    return ret;
  },
  createPath(parent, path, canRead, canWrite) {
    parent = typeof parent == "string" ? parent : FS.getPath(parent);
    var parts = path.split("/").reverse();
    while (parts.length) {
      var part = parts.pop();
      if (!part) continue;
      var current = PATH.join2(parent, part);
      try {
        FS.mkdir(current);
      } catch (e) {}
      parent = current;
    }
    return current;
  },
  createFile(parent, name, properties, canRead, canWrite) {
    var path = PATH.join2(
      typeof parent == "string" ? parent : FS.getPath(parent),
      name
    );
    var mode = FS_getMode(canRead, canWrite);
    return FS.create(path, mode);
  },
  createDataFile(parent, name, data, canRead, canWrite, canOwn) {
    var path = name;
    if (parent) {
      parent = typeof parent == "string" ? parent : FS.getPath(parent);
      path = name ? PATH.join2(parent, name) : parent;
    }
    var mode = FS_getMode(canRead, canWrite);
    var node = FS.create(path, mode);
    if (data) {
      if (typeof data == "string") {
        var arr = new Array(data.length);
        for (var i = 0, len = data.length; i < len; ++i)
          arr[i] = data.charCodeAt(i);
        data = arr;
      }
      FS.chmod(node, mode | 146);
      var stream = FS.open(node, 577);
      FS.write(stream, data, 0, data.length, 0, canOwn);
      FS.close(stream);
      FS.chmod(node, mode);
    }
    return node;
  },
  createDevice(parent, name, input, output) {
    var path = PATH.join2(
      typeof parent == "string" ? parent : FS.getPath(parent),
      name
    );
    var mode = FS_getMode(!!input, !!output);
    if (!FS.createDevice.major) FS.createDevice.major = 64;
    var dev = FS.makedev(FS.createDevice.major++, 0);
    FS.registerDevice(dev, {
      open(stream) {
        stream.seekable = false;
      },
      close(stream) {
        if (output && output.buffer && output.buffer.length) {
          output(10);
        }
      },
      read(stream, buffer, offset, length, pos) {
        var bytesRead = 0;
        for (var i = 0; i < length; i++) {
          var result;
          try {
            result = input();
          } catch (e) {
            throw new FS.ErrnoError(29);
          }
          if (result === undefined && bytesRead === 0) {
            throw new FS.ErrnoError(6);
          }
          if (result === null || result === undefined) break;
          bytesRead++;
          buffer[offset + i] = result;
        }
        if (bytesRead) {
          stream.node.timestamp = Date.now();
        }
        return bytesRead;
      },
      write(stream, buffer, offset, length, pos) {
        for (var i = 0; i < length; i++) {
          try {
            output(buffer[offset + i]);
          } catch (e) {
            throw new FS.ErrnoError(29);
          }
        }
        if (length) {
          stream.node.timestamp = Date.now();
        }
        return i;
      },
    });
    return FS.mkdev(path, mode, dev);
  },
  forceLoadFile(obj) {
    if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true;
    if (typeof XMLHttpRequest != "undefined") {
      throw new Error(
        "Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread."
      );
    } else if (read_) {
      try {
        obj.contents = intArrayFromString(read_(obj.url), true);
        obj.usedBytes = obj.contents.length;
      } catch (e) {
        throw new FS.ErrnoError(29);
      }
    } else {
      throw new Error("Cannot load without read() or XMLHttpRequest.");
    }
  },
  createLazyFile(parent, name, url, canRead, canWrite) {
    function LazyUint8Array() {
      this.lengthKnown = false;
      this.chunks = [];
    }
    LazyUint8Array.prototype.get = function LazyUint8Array_get(idx) {
      if (idx > this.length - 1 || idx < 0) {
        return undefined;
      }
      var chunkOffset = idx % this.chunkSize;
      var chunkNum = (idx / this.chunkSize) | 0;
      return this.getter(chunkNum)[chunkOffset];
    };
    LazyUint8Array.prototype.setDataGetter =
      function LazyUint8Array_setDataGetter(getter) {
        this.getter = getter;
      };
    LazyUint8Array.prototype.cacheLength =
      function LazyUint8Array_cacheLength() {
        var xhr = new XMLHttpRequest();
        xhr.open("HEAD", url, false);
        xhr.send(null);
        if (!((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304))
          throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
        var datalength = Number(xhr.getResponseHeader("Content-length"));
        var header;
        var hasByteServing =
          (header = xhr.getResponseHeader("Accept-Ranges")) &&
          header === "bytes";
        var usesGzip =
          (header = xhr.getResponseHeader("Content-Encoding")) &&
          header === "gzip";
        var chunkSize = 1024 * 1024;
        if (!hasByteServing) chunkSize = datalength;
        var doXHR = (from, to) => {
          if (from > to)
            throw new Error(
              "invalid range (" + from + ", " + to + ") or no bytes requested!"
            );
          if (to > datalength - 1)
            throw new Error(
              "only " + datalength + " bytes available! programmer error!"
            );
          var xhr = new XMLHttpRequest();
          xhr.open("GET", url, false);
          if (datalength !== chunkSize)
            xhr.setRequestHeader("Range", "bytes=" + from + "-" + to);
          xhr.responseType = "arraybuffer";
          if (xhr.overrideMimeType) {
            xhr.overrideMimeType("text/plain; charset=x-user-defined");
          }
          xhr.send(null);
          if (!((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304))
            throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
          if (xhr.response !== undefined) {
            return new Uint8Array(xhr.response || []);
          }
          return intArrayFromString(xhr.responseText || "", true);
        };
        var lazyArray = this;
        lazyArray.setDataGetter((chunkNum) => {
          var start = chunkNum * chunkSize;
          var end = (chunkNum + 1) * chunkSize - 1;
          end = Math.min(end, datalength - 1);
          if (typeof lazyArray.chunks[chunkNum] == "undefined") {
            lazyArray.chunks[chunkNum] = doXHR(start, end);
          }
          if (typeof lazyArray.chunks[chunkNum] == "undefined")
            throw new Error("doXHR failed!");
          return lazyArray.chunks[chunkNum];
        });
        if (usesGzip || !datalength) {
          chunkSize = datalength = 1;
          datalength = this.getter(0).length;
          chunkSize = datalength;
          out(
            "LazyFiles on gzip forces download of the whole file when length is accessed"
          );
        }
        this._length = datalength;
        this._chunkSize = chunkSize;
        this.lengthKnown = true;
      };
    if (typeof XMLHttpRequest != "undefined") {
      if (!ENVIRONMENT_IS_WORKER)
        throw "Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";
      var lazyArray = new LazyUint8Array();
      Object.defineProperties(lazyArray, {
        length: {
          get: function () {
            if (!this.lengthKnown) {
              this.cacheLength();
            }
            return this._length;
          },
        },
        chunkSize: {
          get: function () {
            if (!this.lengthKnown) {
              this.cacheLength();
            }
            return this._chunkSize;
          },
        },
      });
      var properties = { isDevice: false, contents: lazyArray };
    } else {
      var properties = { isDevice: false, url: url };
    }
    var node = FS.createFile(parent, name, properties, canRead, canWrite);
    if (properties.contents) {
      node.contents = properties.contents;
    } else if (properties.url) {
      node.contents = null;
      node.url = properties.url;
    }
    Object.defineProperties(node, {
      usedBytes: {
        get: function () {
          return this.contents.length;
        },
      },
    });
    var stream_ops = {};
    var keys = Object.keys(node.stream_ops);
    keys.forEach((key) => {
      var fn = node.stream_ops[key];
      stream_ops[key] = function forceLoadLazyFile() {
        FS.forceLoadFile(node);
        return fn.apply(null, arguments);
      };
    });
    function writeChunks(stream, buffer, offset, length, position) {
      var contents = stream.node.contents;
      if (position >= contents.length) return 0;
      var size = Math.min(contents.length - position, length);
      assert(size >= 0);
      if (contents.slice) {
        for (var i = 0; i < size; i++) {
          buffer[offset + i] = contents[position + i];
        }
      } else {
        for (var i = 0; i < size; i++) {
          buffer[offset + i] = contents.get(position + i);
        }
      }
      return size;
    }
    stream_ops.read = (stream, buffer, offset, length, position) => {
      FS.forceLoadFile(node);
      return writeChunks(stream, buffer, offset, length, position);
    };
    stream_ops.mmap = (stream, length, position, prot, flags) => {
      FS.forceLoadFile(node);
      var ptr = mmapAlloc(length);
      if (!ptr) {
        throw new FS.ErrnoError(48);
      }
      writeChunks(stream, HEAP8, ptr, length, position);
      return { ptr: ptr, allocated: true };
    };
    node.stream_ops = stream_ops;
    return node;
  },
  absolutePath() {
    abort("FS.absolutePath has been removed; use PATH_FS.resolve instead");
  },
  createFolder() {
    abort("FS.createFolder has been removed; use FS.mkdir instead");
  },
  createLink() {
    abort("FS.createLink has been removed; use FS.symlink instead");
  },
  joinPath() {
    abort("FS.joinPath has been removed; use PATH.join instead");
  },
  mmapAlloc() {
    abort("FS.mmapAlloc has been replaced by the top level function mmapAlloc");
  },
  standardizePath() {
    abort("FS.standardizePath has been removed; use PATH.normalize instead");
  },
};
var SYSCALLS = {
  DEFAULT_POLLMASK: 5,
  calculateAt(dirfd, path, allowEmpty) {
    if (PATH.isAbs(path)) {
      return path;
    }
    var dir;
    if (dirfd === -100) {
      dir = FS.cwd();
    } else {
      var dirstream = SYSCALLS.getStreamFromFD(dirfd);
      dir = dirstream.path;
    }
    if (path.length == 0) {
      if (!allowEmpty) {
        throw new FS.ErrnoError(44);
      }
      return dir;
    }
    return PATH.join2(dir, path);
  },
  doStat(func, path, buf) {
    try {
      var stat = func(path);
    } catch (e) {
      if (
        e &&
        e.node &&
        PATH.normalize(path) !== PATH.normalize(FS.getPath(e.node))
      ) {
        return -54;
      }
      throw e;
    }
    HEAP32[buf >> 2] = stat.dev;
    HEAP32[(buf + 4) >> 2] = stat.mode;
    HEAPU32[(buf + 8) >> 2] = stat.nlink;
    HEAP32[(buf + 12) >> 2] = stat.uid;
    HEAP32[(buf + 16) >> 2] = stat.gid;
    HEAP32[(buf + 20) >> 2] = stat.rdev;
    (tempI64 = [
      stat.size >>> 0,
      ((tempDouble = stat.size),
      +Math.abs(tempDouble) >= 1
        ? tempDouble > 0
          ? +Math.floor(tempDouble / 4294967296) >>> 0
          : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>>
            0
        : 0),
    ]),
      (HEAP32[(buf + 24) >> 2] = tempI64[0]),
      (HEAP32[(buf + 28) >> 2] = tempI64[1]);
    HEAP32[(buf + 32) >> 2] = 4096;
    HEAP32[(buf + 36) >> 2] = stat.blocks;
    var atime = stat.atime.getTime();
    var mtime = stat.mtime.getTime();
    var ctime = stat.ctime.getTime();
    (tempI64 = [
      Math.floor(atime / 1e3) >>> 0,
      ((tempDouble = Math.floor(atime / 1e3)),
      +Math.abs(tempDouble) >= 1
        ? tempDouble > 0
          ? +Math.floor(tempDouble / 4294967296) >>> 0
          : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>>
            0
        : 0),
    ]),
      (HEAP32[(buf + 40) >> 2] = tempI64[0]),
      (HEAP32[(buf + 44) >> 2] = tempI64[1]);
    HEAPU32[(buf + 48) >> 2] = (atime % 1e3) * 1e3;
    (tempI64 = [
      Math.floor(mtime / 1e3) >>> 0,
      ((tempDouble = Math.floor(mtime / 1e3)),
      +Math.abs(tempDouble) >= 1
        ? tempDouble > 0
          ? +Math.floor(tempDouble / 4294967296) >>> 0
          : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>>
            0
        : 0),
    ]),
      (HEAP32[(buf + 56) >> 2] = tempI64[0]),
      (HEAP32[(buf + 60) >> 2] = tempI64[1]);
    HEAPU32[(buf + 64) >> 2] = (mtime % 1e3) * 1e3;
    (tempI64 = [
      Math.floor(ctime / 1e3) >>> 0,
      ((tempDouble = Math.floor(ctime / 1e3)),
      +Math.abs(tempDouble) >= 1
        ? tempDouble > 0
          ? +Math.floor(tempDouble / 4294967296) >>> 0
          : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>>
            0
        : 0),
    ]),
      (HEAP32[(buf + 72) >> 2] = tempI64[0]),
      (HEAP32[(buf + 76) >> 2] = tempI64[1]);
    HEAPU32[(buf + 80) >> 2] = (ctime % 1e3) * 1e3;
    (tempI64 = [
      stat.ino >>> 0,
      ((tempDouble = stat.ino),
      +Math.abs(tempDouble) >= 1
        ? tempDouble > 0
          ? +Math.floor(tempDouble / 4294967296) >>> 0
          : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>>
            0
        : 0),
    ]),
      (HEAP32[(buf + 88) >> 2] = tempI64[0]),
      (HEAP32[(buf + 92) >> 2] = tempI64[1]);
    return 0;
  },
  doMsync(addr, stream, len, flags, offset) {
    if (!FS.isFile(stream.node.mode)) {
      throw new FS.ErrnoError(43);
    }
    if (flags & 2) {
      return 0;
    }
    var buffer = HEAPU8.slice(addr, addr + len);
    FS.msync(stream, buffer, offset, len, flags);
  },
  varargs: undefined,
  get() {
    assert(SYSCALLS.varargs != undefined);
    var ret = HEAP32[+SYSCALLS.varargs >> 2];
    SYSCALLS.varargs += 4;
    return ret;
  },
  getp() {
    return SYSCALLS.get();
  },
  getStr(ptr) {
    var ret = UTF8ToString(ptr);
    return ret;
  },
  getStreamFromFD(fd) {
    var stream = FS.getStreamChecked(fd);
    return stream;
  },
};
function ___syscall_chmod(path, mode) {
  try {
    path = SYSCALLS.getStr(path);
    FS.chmod(path, mode);
    return 0;
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return -e.errno;
  }
}
function ___syscall_dup3(fd, newfd, flags) {
  try {
    var old = SYSCALLS.getStreamFromFD(fd);
    assert(!flags);
    if (old.fd === newfd) return -28;
    var existing = FS.getStream(newfd);
    if (existing) FS.close(existing);
    return FS.createStream(old, newfd).fd;
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return -e.errno;
  }
}
function ___syscall_faccessat(dirfd, path, amode, flags) {
  try {
    path = SYSCALLS.getStr(path);
    assert(flags === 0);
    path = SYSCALLS.calculateAt(dirfd, path);
    if (amode & ~7) {
      return -28;
    }
    var lookup = FS.lookupPath(path, { follow: true });
    var node = lookup.node;
    if (!node) {
      return -44;
    }
    var perms = "";
    if (amode & 4) perms += "r";
    if (amode & 2) perms += "w";
    if (amode & 1) perms += "x";
    if (perms && FS.nodePermissions(node, perms)) {
      return -2;
    }
    return 0;
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return -e.errno;
  }
}
var setErrNo = (value) => {
  HEAP32[___errno_location() >> 2] = value;
  return value;
};
function ___syscall_fcntl64(fd, cmd, varargs) {
  SYSCALLS.varargs = varargs;
  try {
    var stream = SYSCALLS.getStreamFromFD(fd);
    switch (cmd) {
      case 0: {
        var arg = SYSCALLS.get();
        if (arg < 0) {
          return -28;
        }
        while (FS.streams[arg]) {
          arg++;
        }
        var newStream;
        newStream = FS.createStream(stream, arg);
        return newStream.fd;
      }
      case 1:
      case 2:
        return 0;
      case 3:
        return stream.flags;
      case 4: {
        var arg = SYSCALLS.get();
        stream.flags |= arg;
        return 0;
      }
      case 5: {
        var arg = SYSCALLS.getp();
        var offset = 0;
        HEAP16[(arg + offset) >> 1] = 2;
        return 0;
      }
      case 6:
      case 7:
        return 0;
      case 16:
      case 8:
        return -28;
      case 9:
        setErrNo(28);
        return -1;
      default: {
        return -28;
      }
    }
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return -e.errno;
  }
}
function ___syscall_fstat64(fd, buf) {
  try {
    var stream = SYSCALLS.getStreamFromFD(fd);
    return SYSCALLS.doStat(FS.stat, stream.path, buf);
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return -e.errno;
  }
}
var stringToUTF8 = (str, outPtr, maxBytesToWrite) => {
  assert(
    typeof maxBytesToWrite == "number",
    "stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!"
  );
  return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
};
function ___syscall_getcwd(buf, size) {
  try {
    if (size === 0) return -28;
    var cwd = FS.cwd();
    var cwdLengthInBytes = lengthBytesUTF8(cwd) + 1;
    if (size < cwdLengthInBytes) return -68;
    stringToUTF8(cwd, buf, size);
    return cwdLengthInBytes;
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return -e.errno;
  }
}
function ___syscall_getdents64(fd, dirp, count) {
  try {
    var stream = SYSCALLS.getStreamFromFD(fd);
    if (!stream.getdents) {
      stream.getdents = FS.readdir(stream.path);
    }
    var struct_size = 280;
    var pos = 0;
    var off = FS.llseek(stream, 0, 1);
    var idx = Math.floor(off / struct_size);
    while (idx < stream.getdents.length && pos + struct_size <= count) {
      var id;
      var type;
      var name = stream.getdents[idx];
      if (name === ".") {
        id = stream.node.id;
        type = 4;
      } else if (name === "..") {
        var lookup = FS.lookupPath(stream.path, { parent: true });
        id = lookup.node.id;
        type = 4;
      } else {
        var child = FS.lookupNode(stream.node, name);
        id = child.id;
        type = FS.isChrdev(child.mode)
          ? 2
          : FS.isDir(child.mode)
          ? 4
          : FS.isLink(child.mode)
          ? 10
          : 8;
      }
      assert(id);
      (tempI64 = [
        id >>> 0,
        ((tempDouble = id),
        +Math.abs(tempDouble) >= 1
          ? tempDouble > 0
            ? +Math.floor(tempDouble / 4294967296) >>> 0
            : ~~+Math.ceil(
                (tempDouble - +(~~tempDouble >>> 0)) / 4294967296
              ) >>> 0
          : 0),
      ]),
        (HEAP32[(dirp + pos) >> 2] = tempI64[0]),
        (HEAP32[(dirp + pos + 4) >> 2] = tempI64[1]);
      (tempI64 = [
        ((idx + 1) * struct_size) >>> 0,
        ((tempDouble = (idx + 1) * struct_size),
        +Math.abs(tempDouble) >= 1
          ? tempDouble > 0
            ? +Math.floor(tempDouble / 4294967296) >>> 0
            : ~~+Math.ceil(
                (tempDouble - +(~~tempDouble >>> 0)) / 4294967296
              ) >>> 0
          : 0),
      ]),
        (HEAP32[(dirp + pos + 8) >> 2] = tempI64[0]),
        (HEAP32[(dirp + pos + 12) >> 2] = tempI64[1]);
      HEAP16[(dirp + pos + 16) >> 1] = 280;
      HEAP8[(dirp + pos + 18) >> 0] = type;
      stringToUTF8(name, dirp + pos + 19, 256);
      pos += struct_size;
      idx += 1;
    }
    FS.llseek(stream, idx * struct_size, 0);
    return pos;
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return -e.errno;
  }
}
function ___syscall_ioctl(fd, op, varargs) {
  SYSCALLS.varargs = varargs;
  try {
    var stream = SYSCALLS.getStreamFromFD(fd);
    switch (op) {
      case 21509: {
        if (!stream.tty) return -59;
        return 0;
      }
      case 21505: {
        if (!stream.tty) return -59;
        if (stream.tty.ops.ioctl_tcgets) {
          var termios = stream.tty.ops.ioctl_tcgets(stream);
          var argp = SYSCALLS.getp();
          HEAP32[argp >> 2] = termios.c_iflag || 0;
          HEAP32[(argp + 4) >> 2] = termios.c_oflag || 0;
          HEAP32[(argp + 8) >> 2] = termios.c_cflag || 0;
          HEAP32[(argp + 12) >> 2] = termios.c_lflag || 0;
          for (var i = 0; i < 32; i++) {
            HEAP8[(argp + i + 17) >> 0] = termios.c_cc[i] || 0;
          }
          return 0;
        }
        return 0;
      }
      case 21510:
      case 21511:
      case 21512: {
        if (!stream.tty) return -59;
        return 0;
      }
      case 21506:
      case 21507:
      case 21508: {
        if (!stream.tty) return -59;
        if (stream.tty.ops.ioctl_tcsets) {
          var argp = SYSCALLS.getp();
          var c_iflag = HEAP32[argp >> 2];
          var c_oflag = HEAP32[(argp + 4) >> 2];
          var c_cflag = HEAP32[(argp + 8) >> 2];
          var c_lflag = HEAP32[(argp + 12) >> 2];
          var c_cc = [];
          for (var i = 0; i < 32; i++) {
            c_cc.push(HEAP8[(argp + i + 17) >> 0]);
          }
          return stream.tty.ops.ioctl_tcsets(stream.tty, op, {
            c_iflag: c_iflag,
            c_oflag: c_oflag,
            c_cflag: c_cflag,
            c_lflag: c_lflag,
            c_cc: c_cc,
          });
        }
        return 0;
      }
      case 21519: {
        if (!stream.tty) return -59;
        var argp = SYSCALLS.getp();
        HEAP32[argp >> 2] = 0;
        return 0;
      }
      case 21520: {
        if (!stream.tty) return -59;
        return -28;
      }
      case 21531: {
        var argp = SYSCALLS.getp();
        return FS.ioctl(stream, op, argp);
      }
      case 21523: {
        if (!stream.tty) return -59;
        if (stream.tty.ops.ioctl_tiocgwinsz) {
          var winsize = stream.tty.ops.ioctl_tiocgwinsz(stream.tty);
          var argp = SYSCALLS.getp();
          HEAP16[argp >> 1] = winsize[0];
          HEAP16[(argp + 2) >> 1] = winsize[1];
        }
        return 0;
      }
      case 21524: {
        if (!stream.tty) return -59;
        return 0;
      }
      case 21515: {
        if (!stream.tty) return -59;
        return 0;
      }
      default:
        return -28;
    }
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return -e.errno;
  }
}
function ___syscall_lstat64(path, buf) {
  try {
    path = SYSCALLS.getStr(path);
    return SYSCALLS.doStat(FS.lstat, path, buf);
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return -e.errno;
  }
}
function ___syscall_mkdirat(dirfd, path, mode) {
  try {
    path = SYSCALLS.getStr(path);
    path = SYSCALLS.calculateAt(dirfd, path);
    path = PATH.normalize(path);
    if (path[path.length - 1] === "/") path = path.substr(0, path.length - 1);
    FS.mkdir(path, mode, 0);
    return 0;
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return -e.errno;
  }
}
function ___syscall_newfstatat(dirfd, path, buf, flags) {
  try {
    path = SYSCALLS.getStr(path);
    var nofollow = flags & 256;
    var allowEmpty = flags & 4096;
    flags = flags & ~6400;
    assert(!flags, `unknown flags in __syscall_newfstatat: ${flags}`);
    path = SYSCALLS.calculateAt(dirfd, path, allowEmpty);
    return SYSCALLS.doStat(nofollow ? FS.lstat : FS.stat, path, buf);
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return -e.errno;
  }
}
function ___syscall_openat(dirfd, path, flags, varargs) {
  SYSCALLS.varargs = varargs;
  try {
    path = SYSCALLS.getStr(path);
    path = SYSCALLS.calculateAt(dirfd, path);
    var mode = varargs ? SYSCALLS.get() : 0;
    return FS.open(path, flags, mode).fd;
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return -e.errno;
  }
}
function ___syscall_readlinkat(dirfd, path, buf, bufsize) {
  try {
    path = SYSCALLS.getStr(path);
    path = SYSCALLS.calculateAt(dirfd, path);
    if (bufsize <= 0) return -28;
    var ret = FS.readlink(path);
    var len = Math.min(bufsize, lengthBytesUTF8(ret));
    var endChar = HEAP8[buf + len];
    stringToUTF8(ret, buf, bufsize + 1);
    HEAP8[buf + len] = endChar;
    return len;
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return -e.errno;
  }
}
function ___syscall_renameat(olddirfd, oldpath, newdirfd, newpath) {
  try {
    oldpath = SYSCALLS.getStr(oldpath);
    newpath = SYSCALLS.getStr(newpath);
    oldpath = SYSCALLS.calculateAt(olddirfd, oldpath);
    newpath = SYSCALLS.calculateAt(newdirfd, newpath);
    FS.rename(oldpath, newpath);
    return 0;
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return -e.errno;
  }
}
function ___syscall_rmdir(path) {
  try {
    path = SYSCALLS.getStr(path);
    FS.rmdir(path);
    return 0;
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return -e.errno;
  }
}
function ___syscall_stat64(path, buf) {
  try {
    path = SYSCALLS.getStr(path);
    return SYSCALLS.doStat(FS.stat, path, buf);
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return -e.errno;
  }
}
function ___syscall_unlinkat(dirfd, path, flags) {
  try {
    path = SYSCALLS.getStr(path);
    path = SYSCALLS.calculateAt(dirfd, path);
    if (flags === 0) {
      FS.unlink(path);
    } else if (flags === 512) {
      FS.rmdir(path);
    } else {
      abort("Invalid flags passed to unlinkat");
    }
    return 0;
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return -e.errno;
  }
}
var __embind_register_bigint = (
  primitiveType,
  name,
  size,
  minRange,
  maxRange
) => {};
var embind_init_charCodes = () => {
  var codes = new Array(256);
  for (var i = 0; i < 256; ++i) {
    codes[i] = String.fromCharCode(i);
  }
  embind_charCodes = codes;
};
var embind_charCodes;
var readLatin1String = (ptr) => {
  var ret = "";
  var c = ptr;
  while (HEAPU8[c]) {
    ret += embind_charCodes[HEAPU8[c++]];
  }
  return ret;
};
var awaitingDependencies = {};
var registeredTypes = {};
var typeDependencies = {};
var BindingError;
var throwBindingError = (message) => {
  throw new BindingError(message);
};
var InternalError;
var throwInternalError = (message) => {
  throw new InternalError(message);
};
var whenDependentTypesAreResolved = (
  myTypes,
  dependentTypes,
  getTypeConverters
) => {
  myTypes.forEach(function (type) {
    typeDependencies[type] = dependentTypes;
  });
  function onComplete(typeConverters) {
    var myTypeConverters = getTypeConverters(typeConverters);
    if (myTypeConverters.length !== myTypes.length) {
      throwInternalError("Mismatched type converter count");
    }
    for (var i = 0; i < myTypes.length; ++i) {
      registerType(myTypes[i], myTypeConverters[i]);
    }
  }
  var typeConverters = new Array(dependentTypes.length);
  var unregisteredTypes = [];
  var registered = 0;
  dependentTypes.forEach((dt, i) => {
    if (registeredTypes.hasOwnProperty(dt)) {
      typeConverters[i] = registeredTypes[dt];
    } else {
      unregisteredTypes.push(dt);
      if (!awaitingDependencies.hasOwnProperty(dt)) {
        awaitingDependencies[dt] = [];
      }
      awaitingDependencies[dt].push(() => {
        typeConverters[i] = registeredTypes[dt];
        ++registered;
        if (registered === unregisteredTypes.length) {
          onComplete(typeConverters);
        }
      });
    }
  });
  if (0 === unregisteredTypes.length) {
    onComplete(typeConverters);
  }
};
function sharedRegisterType(rawType, registeredInstance, options = {}) {
  var name = registeredInstance.name;
  if (!rawType) {
    throwBindingError(
      `type "${name}" must have a positive integer typeid pointer`
    );
  }
  if (registeredTypes.hasOwnProperty(rawType)) {
    if (options.ignoreDuplicateRegistrations) {
      return;
    } else {
      throwBindingError(`Cannot register type '${name}' twice`);
    }
  }
  registeredTypes[rawType] = registeredInstance;
  delete typeDependencies[rawType];
  if (awaitingDependencies.hasOwnProperty(rawType)) {
    var callbacks = awaitingDependencies[rawType];
    delete awaitingDependencies[rawType];
    callbacks.forEach((cb) => cb());
  }
}
function registerType(rawType, registeredInstance, options = {}) {
  if (!("argPackAdvance" in registeredInstance)) {
    throw new TypeError(
      "registerType registeredInstance requires argPackAdvance"
    );
  }
  return sharedRegisterType(rawType, registeredInstance, options);
}
var GenericWireTypeSize = 8;
var __embind_register_bool = (rawType, name, trueValue, falseValue) => {
  name = readLatin1String(name);
  registerType(rawType, {
    name: name,
    fromWireType: function (wt) {
      return !!wt;
    },
    toWireType: function (destructors, o) {
      return o ? trueValue : falseValue;
    },
    argPackAdvance: GenericWireTypeSize,
    readValueFromPointer: function (pointer) {
      return this["fromWireType"](HEAPU8[pointer]);
    },
    destructorFunction: null,
  });
};
var shallowCopyInternalPointer = (o) => ({
  count: o.count,
  deleteScheduled: o.deleteScheduled,
  preservePointerOnDelete: o.preservePointerOnDelete,
  ptr: o.ptr,
  ptrType: o.ptrType,
  smartPtr: o.smartPtr,
  smartPtrType: o.smartPtrType,
});
var throwInstanceAlreadyDeleted = (obj) => {
  function getInstanceTypeName(handle) {
    return handle.$$.ptrType.registeredClass.name;
  }
  throwBindingError(getInstanceTypeName(obj) + " instance already deleted");
};
var finalizationRegistry = false;
var detachFinalizer = (handle) => {};
var runDestructor = ($$) => {
  if ($$.smartPtr) {
    $$.smartPtrType.rawDestructor($$.smartPtr);
  } else {
    $$.ptrType.registeredClass.rawDestructor($$.ptr);
  }
};
var releaseClassHandle = ($$) => {
  $$.count.value -= 1;
  var toDelete = 0 === $$.count.value;
  if (toDelete) {
    runDestructor($$);
  }
};
var downcastPointer = (ptr, ptrClass, desiredClass) => {
  if (ptrClass === desiredClass) {
    return ptr;
  }
  if (undefined === desiredClass.baseClass) {
    return null;
  }
  var rv = downcastPointer(ptr, ptrClass, desiredClass.baseClass);
  if (rv === null) {
    return null;
  }
  return desiredClass.downcast(rv);
};
var registeredPointers = {};
var getInheritedInstanceCount = () => Object.keys(registeredInstances).length;
var getLiveInheritedInstances = () => {
  var rv = [];
  for (var k in registeredInstances) {
    if (registeredInstances.hasOwnProperty(k)) {
      rv.push(registeredInstances[k]);
    }
  }
  return rv;
};
var deletionQueue = [];
var flushPendingDeletes = () => {
  while (deletionQueue.length) {
    var obj = deletionQueue.pop();
    obj.$$.deleteScheduled = false;
    obj["delete"]();
  }
};
var delayFunction;
var setDelayFunction = (fn) => {
  delayFunction = fn;
  if (deletionQueue.length && delayFunction) {
    delayFunction(flushPendingDeletes);
  }
};
var init_embind = () => {
  Module["getInheritedInstanceCount"] = getInheritedInstanceCount;
  Module["getLiveInheritedInstances"] = getLiveInheritedInstances;
  Module["flushPendingDeletes"] = flushPendingDeletes;
  Module["setDelayFunction"] = setDelayFunction;
};
var registeredInstances = {};
var getBasestPointer = (class_, ptr) => {
  if (ptr === undefined) {
    throwBindingError("ptr should not be undefined");
  }
  while (class_.baseClass) {
    ptr = class_.upcast(ptr);
    class_ = class_.baseClass;
  }
  return ptr;
};
var getInheritedInstance = (class_, ptr) => {
  ptr = getBasestPointer(class_, ptr);
  return registeredInstances[ptr];
};
var makeClassHandle = (prototype, record) => {
  if (!record.ptrType || !record.ptr) {
    throwInternalError("makeClassHandle requires ptr and ptrType");
  }
  var hasSmartPtrType = !!record.smartPtrType;
  var hasSmartPtr = !!record.smartPtr;
  if (hasSmartPtrType !== hasSmartPtr) {
    throwInternalError("Both smartPtrType and smartPtr must be specified");
  }
  record.count = { value: 1 };
  return attachFinalizer(Object.create(prototype, { $$: { value: record } }));
};
function RegisteredPointer_fromWireType(ptr) {
  var rawPointer = this.getPointee(ptr);
  if (!rawPointer) {
    this.destructor(ptr);
    return null;
  }
  var registeredInstance = getInheritedInstance(
    this.registeredClass,
    rawPointer
  );
  if (undefined !== registeredInstance) {
    if (0 === registeredInstance.$$.count.value) {
      registeredInstance.$$.ptr = rawPointer;
      registeredInstance.$$.smartPtr = ptr;
      return registeredInstance["clone"]();
    } else {
      var rv = registeredInstance["clone"]();
      this.destructor(ptr);
      return rv;
    }
  }
  function makeDefaultHandle() {
    if (this.isSmartPointer) {
      return makeClassHandle(this.registeredClass.instancePrototype, {
        ptrType: this.pointeeType,
        ptr: rawPointer,
        smartPtrType: this,
        smartPtr: ptr,
      });
    } else {
      return makeClassHandle(this.registeredClass.instancePrototype, {
        ptrType: this,
        ptr: ptr,
      });
    }
  }
  var actualType = this.registeredClass.getActualType(rawPointer);
  var registeredPointerRecord = registeredPointers[actualType];
  if (!registeredPointerRecord) {
    return makeDefaultHandle.call(this);
  }
  var toType;
  if (this.isConst) {
    toType = registeredPointerRecord.constPointerType;
  } else {
    toType = registeredPointerRecord.pointerType;
  }
  var dp = downcastPointer(
    rawPointer,
    this.registeredClass,
    toType.registeredClass
  );
  if (dp === null) {
    return makeDefaultHandle.call(this);
  }
  if (this.isSmartPointer) {
    return makeClassHandle(toType.registeredClass.instancePrototype, {
      ptrType: toType,
      ptr: dp,
      smartPtrType: this,
      smartPtr: ptr,
    });
  } else {
    return makeClassHandle(toType.registeredClass.instancePrototype, {
      ptrType: toType,
      ptr: dp,
    });
  }
}
var attachFinalizer = (handle) => {
  if ("undefined" === typeof FinalizationRegistry) {
    attachFinalizer = (handle) => handle;
    return handle;
  }
  finalizationRegistry = new FinalizationRegistry((info) => {
    console.warn(info.leakWarning.stack.replace(/^Error: /, ""));
    releaseClassHandle(info.$$);
  });
  attachFinalizer = (handle) => {
    var $$ = handle.$$;
    var hasSmartPtr = !!$$.smartPtr;
    if (hasSmartPtr) {
      var info = { $$: $$ };
      var cls = $$.ptrType.registeredClass;
      info.leakWarning = new Error(
        `Embind found a leaked C++ instance ${cls.name} <${ptrToString(
          $$.ptr
        )}>.\n` +
          "We'll free it automatically in this case, but this functionality is not reliable across various environments.\n" +
          "Make sure to invoke .delete() manually once you're done with the instance instead.\n" +
          "Originally allocated"
      );
      if ("captureStackTrace" in Error) {
        Error.captureStackTrace(
          info.leakWarning,
          RegisteredPointer_fromWireType
        );
      }
      finalizationRegistry.register(handle, info, handle);
    }
    return handle;
  };
  detachFinalizer = (handle) => finalizationRegistry.unregister(handle);
  return attachFinalizer(handle);
};
var init_ClassHandle = () => {
  Object.assign(ClassHandle.prototype, {
    isAliasOf(other) {
      if (!(this instanceof ClassHandle)) {
        return false;
      }
      if (!(other instanceof ClassHandle)) {
        return false;
      }
      var leftClass = this.$$.ptrType.registeredClass;
      var left = this.$$.ptr;
      other.$$ = other.$$;
      var rightClass = other.$$.ptrType.registeredClass;
      var right = other.$$.ptr;
      while (leftClass.baseClass) {
        left = leftClass.upcast(left);
        leftClass = leftClass.baseClass;
      }
      while (rightClass.baseClass) {
        right = rightClass.upcast(right);
        rightClass = rightClass.baseClass;
      }
      return leftClass === rightClass && left === right;
    },
    clone() {
      if (!this.$$.ptr) {
        throwInstanceAlreadyDeleted(this);
      }
      if (this.$$.preservePointerOnDelete) {
        this.$$.count.value += 1;
        return this;
      } else {
        var clone = attachFinalizer(
          Object.create(Object.getPrototypeOf(this), {
            $$: { value: shallowCopyInternalPointer(this.$$) },
          })
        );
        clone.$$.count.value += 1;
        clone.$$.deleteScheduled = false;
        return clone;
      }
    },
    delete() {
      if (!this.$$.ptr) {
        throwInstanceAlreadyDeleted(this);
      }
      if (this.$$.deleteScheduled && !this.$$.preservePointerOnDelete) {
        throwBindingError("Object already scheduled for deletion");
      }
      detachFinalizer(this);
      releaseClassHandle(this.$$);
      if (!this.$$.preservePointerOnDelete) {
        this.$$.smartPtr = undefined;
        this.$$.ptr = undefined;
      }
    },
    isDeleted() {
      return !this.$$.ptr;
    },
    deleteLater() {
      if (!this.$$.ptr) {
        throwInstanceAlreadyDeleted(this);
      }
      if (this.$$.deleteScheduled && !this.$$.preservePointerOnDelete) {
        throwBindingError("Object already scheduled for deletion");
      }
      deletionQueue.push(this);
      if (deletionQueue.length === 1 && delayFunction) {
        delayFunction(flushPendingDeletes);
      }
      this.$$.deleteScheduled = true;
      return this;
    },
  });
};
function ClassHandle() {}
var char_0 = 48;
var char_9 = 57;
var makeLegalFunctionName = (name) => {
  if (undefined === name) {
    return "_unknown";
  }
  name = name.replace(/[^a-zA-Z0-9_]/g, "$");
  var f = name.charCodeAt(0);
  if (f >= char_0 && f <= char_9) {
    return `_${name}`;
  }
  return name;
};
function createNamedFunction(name, body) {
  name = makeLegalFunctionName(name);
  return {
    [name]: function () {
      return body.apply(this, arguments);
    },
  }[name];
}
var ensureOverloadTable = (proto, methodName, humanName) => {
  if (undefined === proto[methodName].overloadTable) {
    var prevFunc = proto[methodName];
    proto[methodName] = function () {
      if (!proto[methodName].overloadTable.hasOwnProperty(arguments.length)) {
        throwBindingError(
          `Function '${humanName}' called with an invalid number of arguments (${arguments.length}) - expects one of (${proto[methodName].overloadTable})!`
        );
      }
      return proto[methodName].overloadTable[arguments.length].apply(
        this,
        arguments
      );
    };
    proto[methodName].overloadTable = [];
    proto[methodName].overloadTable[prevFunc.argCount] = prevFunc;
  }
};
var exposePublicSymbol = (name, value, numArguments) => {
  if (Module.hasOwnProperty(name)) {
    if (
      undefined === numArguments ||
      (undefined !== Module[name].overloadTable &&
        undefined !== Module[name].overloadTable[numArguments])
    ) {
      throwBindingError(`Cannot register public name '${name}' twice`);
    }
    ensureOverloadTable(Module, name, name);
    if (Module.hasOwnProperty(numArguments)) {
      throwBindingError(
        `Cannot register multiple overloads of a function with the same number of arguments (${numArguments})!`
      );
    }
    Module[name].overloadTable[numArguments] = value;
  } else {
    Module[name] = value;
    if (undefined !== numArguments) {
      Module[name].numArguments = numArguments;
    }
  }
};
function RegisteredClass(
  name,
  constructor,
  instancePrototype,
  rawDestructor,
  baseClass,
  getActualType,
  upcast,
  downcast
) {
  this.name = name;
  this.constructor = constructor;
  this.instancePrototype = instancePrototype;
  this.rawDestructor = rawDestructor;
  this.baseClass = baseClass;
  this.getActualType = getActualType;
  this.upcast = upcast;
  this.downcast = downcast;
  this.pureVirtualFunctions = [];
}
var upcastPointer = (ptr, ptrClass, desiredClass) => {
  while (ptrClass !== desiredClass) {
    if (!ptrClass.upcast) {
      throwBindingError(
        `Expected null or instance of ${desiredClass.name}, got an instance of ${ptrClass.name}`
      );
    }
    ptr = ptrClass.upcast(ptr);
    ptrClass = ptrClass.baseClass;
  }
  return ptr;
};
function constNoSmartPtrRawPointerToWireType(destructors, handle) {
  if (handle === null) {
    if (this.isReference) {
      throwBindingError(`null is not a valid ${this.name}`);
    }
    return 0;
  }
  if (!handle.$$) {
    throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`);
  }
  if (!handle.$$.ptr) {
    throwBindingError(
      `Cannot pass deleted object as a pointer of type ${this.name}`
    );
  }
  var handleClass = handle.$$.ptrType.registeredClass;
  var ptr = upcastPointer(handle.$$.ptr, handleClass, this.registeredClass);
  return ptr;
}
function genericPointerToWireType(destructors, handle) {
  var ptr;
  if (handle === null) {
    if (this.isReference) {
      throwBindingError(`null is not a valid ${this.name}`);
    }
    if (this.isSmartPointer) {
      ptr = this.rawConstructor();
      if (destructors !== null) {
        destructors.push(this.rawDestructor, ptr);
      }
      return ptr;
    } else {
      return 0;
    }
  }
  if (!handle.$$) {
    throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`);
  }
  if (!handle.$$.ptr) {
    throwBindingError(
      `Cannot pass deleted object as a pointer of type ${this.name}`
    );
  }
  if (!this.isConst && handle.$$.ptrType.isConst) {
    throwBindingError(
      `Cannot convert argument of type ${
        handle.$$.smartPtrType
          ? handle.$$.smartPtrType.name
          : handle.$$.ptrType.name
      } to parameter type ${this.name}`
    );
  }
  var handleClass = handle.$$.ptrType.registeredClass;
  ptr = upcastPointer(handle.$$.ptr, handleClass, this.registeredClass);
  if (this.isSmartPointer) {
    if (undefined === handle.$$.smartPtr) {
      throwBindingError("Passing raw pointer to smart pointer is illegal");
    }
    switch (this.sharingPolicy) {
      case 0:
        if (handle.$$.smartPtrType === this) {
          ptr = handle.$$.smartPtr;
        } else {
          throwBindingError(
            `Cannot convert argument of type ${
              handle.$$.smartPtrType
                ? handle.$$.smartPtrType.name
                : handle.$$.ptrType.name
            } to parameter type ${this.name}`
          );
        }
        break;
      case 1:
        ptr = handle.$$.smartPtr;
        break;
      case 2:
        if (handle.$$.smartPtrType === this) {
          ptr = handle.$$.smartPtr;
        } else {
          var clonedHandle = handle["clone"]();
          ptr = this.rawShare(
            ptr,
            Emval.toHandle(() => clonedHandle["delete"]())
          );
          if (destructors !== null) {
            destructors.push(this.rawDestructor, ptr);
          }
        }
        break;
      default:
        throwBindingError("Unsupporting sharing policy");
    }
  }
  return ptr;
}
function nonConstNoSmartPtrRawPointerToWireType(destructors, handle) {
  if (handle === null) {
    if (this.isReference) {
      throwBindingError(`null is not a valid ${this.name}`);
    }
    return 0;
  }
  if (!handle.$$) {
    throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`);
  }
  if (!handle.$$.ptr) {
    throwBindingError(
      `Cannot pass deleted object as a pointer of type ${this.name}`
    );
  }
  if (handle.$$.ptrType.isConst) {
    throwBindingError(
      `Cannot convert argument of type ${handle.$$.ptrType.name} to parameter type ${this.name}`
    );
  }
  var handleClass = handle.$$.ptrType.registeredClass;
  var ptr = upcastPointer(handle.$$.ptr, handleClass, this.registeredClass);
  return ptr;
}
function readPointer(pointer) {
  return this["fromWireType"](HEAPU32[pointer >> 2]);
}
var init_RegisteredPointer = () => {
  Object.assign(RegisteredPointer.prototype, {
    getPointee(ptr) {
      if (this.rawGetPointee) {
        ptr = this.rawGetPointee(ptr);
      }
      return ptr;
    },
    destructor(ptr) {
      if (this.rawDestructor) {
        this.rawDestructor(ptr);
      }
    },
    argPackAdvance: GenericWireTypeSize,
    readValueFromPointer: readPointer,
    deleteObject(handle) {
      if (handle !== null) {
        handle["delete"]();
      }
    },
    fromWireType: RegisteredPointer_fromWireType,
  });
};
function RegisteredPointer(
  name,
  registeredClass,
  isReference,
  isConst,
  isSmartPointer,
  pointeeType,
  sharingPolicy,
  rawGetPointee,
  rawConstructor,
  rawShare,
  rawDestructor
) {
  this.name = name;
  this.registeredClass = registeredClass;
  this.isReference = isReference;
  this.isConst = isConst;
  this.isSmartPointer = isSmartPointer;
  this.pointeeType = pointeeType;
  this.sharingPolicy = sharingPolicy;
  this.rawGetPointee = rawGetPointee;
  this.rawConstructor = rawConstructor;
  this.rawShare = rawShare;
  this.rawDestructor = rawDestructor;
  if (!isSmartPointer && registeredClass.baseClass === undefined) {
    if (isConst) {
      this["toWireType"] = constNoSmartPtrRawPointerToWireType;
      this.destructorFunction = null;
    } else {
      this["toWireType"] = nonConstNoSmartPtrRawPointerToWireType;
      this.destructorFunction = null;
    }
  } else {
    this["toWireType"] = genericPointerToWireType;
  }
}
var replacePublicSymbol = (name, value, numArguments) => {
  if (!Module.hasOwnProperty(name)) {
    throwInternalError("Replacing nonexistant public symbol");
  }
  if (undefined !== Module[name].overloadTable && undefined !== numArguments) {
    Module[name].overloadTable[numArguments] = value;
  } else {
    Module[name] = value;
    Module[name].argCount = numArguments;
  }
};
var dynCallLegacy = (sig, ptr, args) => {
  assert(
    "dynCall_" + sig in Module,
    `bad function pointer type - dynCall function not found for sig '${sig}'`
  );
  if (args && args.length) {
    assert(args.length === sig.substring(1).replace(/j/g, "--").length);
  } else {
    assert(sig.length == 1);
  }
  var f = Module["dynCall_" + sig];
  return args && args.length
    ? f.apply(null, [ptr].concat(args))
    : f.call(null, ptr);
};
var wasmTableMirror = [];
var wasmTable;
var dynCall = (sig, ptr, args) => {
  var rtn = dynCallLegacy(sig, ptr, args);
  return rtn;
};
var getDynCaller = (sig, ptr) => {
  var argCache = [];
  return function () {
    argCache.length = 0;
    Object.assign(argCache, arguments);
    return dynCall(sig, ptr, argCache);
  };
};
var embind__requireFunction = (signature, rawFunction) => {
  signature = readLatin1String(signature);
  function makeDynCaller() {
    return getDynCaller(signature, rawFunction);
  }
  var fp = makeDynCaller();
  if (typeof fp != "function") {
    throwBindingError(
      `unknown function pointer with signature ${signature}: ${rawFunction}`
    );
  }
  return fp;
};
var extendError = (baseErrorType, errorName) => {
  var errorClass = createNamedFunction(errorName, function (message) {
    this.name = errorName;
    this.message = message;
    var stack = new Error(message).stack;
    if (stack !== undefined) {
      this.stack =
        this.toString() + "\n" + stack.replace(/^Error(:[^\n]*)?\n/, "");
    }
  });
  errorClass.prototype = Object.create(baseErrorType.prototype);
  errorClass.prototype.constructor = errorClass;
  errorClass.prototype.toString = function () {
    if (this.message === undefined) {
      return this.name;
    } else {
      return `${this.name}: ${this.message}`;
    }
  };
  return errorClass;
};
var UnboundTypeError;
var getTypeName = (type) => {
  var ptr = ___getTypeName(type);
  var rv = readLatin1String(ptr);
  _free(ptr);
  return rv;
};
var throwUnboundTypeError = (message, types) => {
  var unboundTypes = [];
  var seen = {};
  function visit(type) {
    if (seen[type]) {
      return;
    }
    if (registeredTypes[type]) {
      return;
    }
    if (typeDependencies[type]) {
      typeDependencies[type].forEach(visit);
      return;
    }
    unboundTypes.push(type);
    seen[type] = true;
  }
  types.forEach(visit);
  throw new UnboundTypeError(
    `${message}: ` + unboundTypes.map(getTypeName).join([", "])
  );
};
var __embind_register_class = (
  rawType,
  rawPointerType,
  rawConstPointerType,
  baseClassRawType,
  getActualTypeSignature,
  getActualType,
  upcastSignature,
  upcast,
  downcastSignature,
  downcast,
  name,
  destructorSignature,
  rawDestructor
) => {
  name = readLatin1String(name);
  getActualType = embind__requireFunction(
    getActualTypeSignature,
    getActualType
  );
  if (upcast) {
    upcast = embind__requireFunction(upcastSignature, upcast);
  }
  if (downcast) {
    downcast = embind__requireFunction(downcastSignature, downcast);
  }
  rawDestructor = embind__requireFunction(destructorSignature, rawDestructor);
  var legalFunctionName = makeLegalFunctionName(name);
  exposePublicSymbol(legalFunctionName, function () {
    throwUnboundTypeError(`Cannot construct ${name} due to unbound types`, [
      baseClassRawType,
    ]);
  });
  whenDependentTypesAreResolved(
    [rawType, rawPointerType, rawConstPointerType],
    baseClassRawType ? [baseClassRawType] : [],
    function (base) {
      base = base[0];
      var baseClass;
      var basePrototype;
      if (baseClassRawType) {
        baseClass = base.registeredClass;
        basePrototype = baseClass.instancePrototype;
      } else {
        basePrototype = ClassHandle.prototype;
      }
      var constructor = createNamedFunction(legalFunctionName, function () {
        if (Object.getPrototypeOf(this) !== instancePrototype) {
          throw new BindingError("Use 'new' to construct " + name);
        }
        if (undefined === registeredClass.constructor_body) {
          throw new BindingError(name + " has no accessible constructor");
        }
        var body = registeredClass.constructor_body[arguments.length];
        if (undefined === body) {
          throw new BindingError(
            `Tried to invoke ctor of ${name} with invalid number of parameters (${
              arguments.length
            }) - expected (${Object.keys(
              registeredClass.constructor_body
            ).toString()}) parameters instead!`
          );
        }
        return body.apply(this, arguments);
      });
      var instancePrototype = Object.create(basePrototype, {
        constructor: { value: constructor },
      });
      constructor.prototype = instancePrototype;
      var registeredClass = new RegisteredClass(
        name,
        constructor,
        instancePrototype,
        rawDestructor,
        baseClass,
        getActualType,
        upcast,
        downcast
      );
      if (registeredClass.baseClass) {
        if (registeredClass.baseClass.__derivedClasses === undefined) {
          registeredClass.baseClass.__derivedClasses = [];
        }
        registeredClass.baseClass.__derivedClasses.push(registeredClass);
      }
      var referenceConverter = new RegisteredPointer(
        name,
        registeredClass,
        true,
        false,
        false
      );
      var pointerConverter = new RegisteredPointer(
        name + "*",
        registeredClass,
        false,
        false,
        false
      );
      var constPointerConverter = new RegisteredPointer(
        name + " const*",
        registeredClass,
        false,
        true,
        false
      );
      registeredPointers[rawType] = {
        pointerType: pointerConverter,
        constPointerType: constPointerConverter,
      };
      replacePublicSymbol(legalFunctionName, constructor);
      return [referenceConverter, pointerConverter, constPointerConverter];
    }
  );
};
var heap32VectorToArray = (count, firstElement) => {
  var array = [];
  for (var i = 0; i < count; i++) {
    array.push(HEAPU32[(firstElement + i * 4) >> 2]);
  }
  return array;
};
var runDestructors = (destructors) => {
  while (destructors.length) {
    var ptr = destructors.pop();
    var del = destructors.pop();
    del(ptr);
  }
};
function newFunc(constructor, argumentList) {
  if (!(constructor instanceof Function)) {
    throw new TypeError(
      `new_ called with constructor type ${typeof constructor} which is not a function`
    );
  }
  var dummy = createNamedFunction(
    constructor.name || "unknownFunctionName",
    function () {}
  );
  dummy.prototype = constructor.prototype;
  var obj = new dummy();
  var r = constructor.apply(obj, argumentList);
  return r instanceof Object ? r : obj;
}
var runAndAbortIfError = (func) => {
  try {
    return func();
  } catch (e) {
    abort(e);
  }
};
var handleException = (e) => {
  if (e instanceof ExitStatus || e == "unwind") {
    return EXITSTATUS;
  }
  checkStackCookie();
  if (e instanceof WXWebAssembly.RuntimeError) {
    if (_emscripten_stack_get_current() <= 0) {
      err(
        "Stack overflow detected.  You can try increasing -sSTACK_SIZE (currently set to 65536)"
      );
    }
  }
  quit_(1, e);
};
var _proc_exit = (code) => {
  EXITSTATUS = code;
  if (!keepRuntimeAlive()) {
    if (Module["onExit"]) Module["onExit"](code);
    ABORT = true;
  }
  quit_(code, new ExitStatus(code));
};
var exitJS = (status, implicit) => {
  EXITSTATUS = status;
  checkUnflushedContent();
  if (keepRuntimeAlive() && !implicit) {
    var msg = `program exited (with status: ${status}), but keepRuntimeAlive() is set (counter=${runtimeKeepaliveCounter}) due to an async operation, so halting execution but not exiting the runtime or preventing further async execution (you can use emscripten_force_exit, if you want to force a true shutdown)`;
    err(msg);
  }
  _proc_exit(status);
};
var _exit = exitJS;
var maybeExit = () => {
  if (!keepRuntimeAlive()) {
    try {
      _exit(EXITSTATUS);
    } catch (e) {
      handleException(e);
    }
  }
};
var callUserCallback = (func) => {
  if (ABORT) {
    err(
      "user callback triggered after runtime exited or application aborted.  Ignoring."
    );
    return;
  }
  try {
    func();
    maybeExit();
  } catch (e) {
    handleException(e);
  }
};

var __embind_register_class_constructor = (
  rawClassType,
  argCount,
  rawArgTypesAddr,
  invokerSignature,
  invoker,
  rawConstructor
) => {
  assert(argCount > 0);
  var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr);
  invoker = embind__requireFunction(invokerSignature, invoker);
  whenDependentTypesAreResolved([], [rawClassType], function (classType) {
    classType = classType[0];
    var humanName = `constructor ${classType.name}`;
    if (undefined === classType.registeredClass.constructor_body) {
      classType.registeredClass.constructor_body = [];
    }
    if (
      undefined !== classType.registeredClass.constructor_body[argCount - 1]
    ) {
      throw new BindingError(
        `Cannot register multiple constructors with identical number of parameters (${
          argCount - 1
        }) for class '${
          classType.name
        }'! Overload resolution is currently only performed using the parameter count, not actual type info!`
      );
    }
    classType.registeredClass.constructor_body[argCount - 1] = () => {
      throwUnboundTypeError(
        `Cannot construct ${classType.name} due to unbound types`,
        rawArgTypes
      );
    };
    whenDependentTypesAreResolved([], rawArgTypes, (argTypes) => {
      argTypes.splice(1, 0, null);
      classType.registeredClass.constructor_body[argCount - 1] =
        craftInvokerFunction(
          humanName,
          argTypes,
          null,
          invoker,
          rawConstructor
        );
      return [];
    });
    return [];
  });
};
var __embind_register_class_function = (
  rawClassType,
  methodName,
  argCount,
  rawArgTypesAddr,
  invokerSignature,
  rawInvoker,
  context,
  isPureVirtual,
  isAsync
) => {
  var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr);
  methodName = readLatin1String(methodName);
  rawInvoker = embind__requireFunction(invokerSignature, rawInvoker);
  whenDependentTypesAreResolved([], [rawClassType], function (classType) {
    classType = classType[0];
    var humanName = `${classType.name}.${methodName}`;
    if (methodName.startsWith("@@")) {
      methodName = Symbol[methodName.substring(2)];
    }
    if (isPureVirtual) {
      classType.registeredClass.pureVirtualFunctions.push(methodName);
    }
    function unboundTypesHandler() {
      throwUnboundTypeError(
        `Cannot call ${humanName} due to unbound types`,
        rawArgTypes
      );
    }
    var proto = classType.registeredClass.instancePrototype;
    var method = proto[methodName];
    if (
      undefined === method ||
      (undefined === method.overloadTable &&
        method.className !== classType.name &&
        method.argCount === argCount - 2)
    ) {
      unboundTypesHandler.argCount = argCount - 2;
      unboundTypesHandler.className = classType.name;
      proto[methodName] = unboundTypesHandler;
    } else {
      ensureOverloadTable(proto, methodName, humanName);
      proto[methodName].overloadTable[argCount - 2] = unboundTypesHandler;
    }
    whenDependentTypesAreResolved([], rawArgTypes, function (argTypes) {
      var memberFunction = craftInvokerFunction(
        humanName,
        argTypes,
        classType,
        rawInvoker,
        context,
        isAsync
      );
      if (undefined === proto[methodName].overloadTable) {
        memberFunction.argCount = argCount - 2;
        proto[methodName] = memberFunction;
      } else {
        proto[methodName].overloadTable[argCount - 2] = memberFunction;
      }
      return [];
    });
    return [];
  });
};
function handleAllocatorInit() {
  Object.assign(HandleAllocator.prototype, {
    get(id) {
      assert(this.allocated[id] !== undefined, `invalid handle: ${id}`);
      return this.allocated[id];
    },
    has(id) {
      return this.allocated[id] !== undefined;
    },
    allocate(handle) {
      var id = this.freelist.pop() || this.allocated.length;
      this.allocated[id] = handle;
      return id;
    },
    free(id) {
      assert(this.allocated[id] !== undefined);
      this.allocated[id] = undefined;
      this.freelist.push(id);
    },
  });
}
function HandleAllocator() {
  this.allocated = [undefined];
  this.freelist = [];
}
var emval_handles = new HandleAllocator();
var __emval_decref = (handle) => {
  if (
    handle >= emval_handles.reserved &&
    0 === --emval_handles.get(handle).refcount
  ) {
    emval_handles.free(handle);
  }
};
var count_emval_handles = () => {
  var count = 0;
  for (
    var i = emval_handles.reserved;
    i < emval_handles.allocated.length;
    ++i
  ) {
    if (emval_handles.allocated[i] !== undefined) {
      ++count;
    }
  }
  return count;
};
var init_emval = () => {
  emval_handles.allocated.push(
    { value: undefined },
    { value: null },
    { value: true },
    { value: false }
  );
  emval_handles.reserved = emval_handles.allocated.length;
  Module["count_emval_handles"] = count_emval_handles;
};
var Emval = {
  toValue: (handle) => {
    if (!handle) {
      throwBindingError("Cannot use deleted val. handle = " + handle);
    }
    return emval_handles.get(handle).value;
  },
  toHandle: (value) => {
    switch (value) {
      case undefined:
        return 1;
      case null:
        return 2;
      case true:
        return 3;
      case false:
        return 4;
      default: {
        return emval_handles.allocate({ refcount: 1, value: value });
      }
    }
  },
};
function simpleReadValueFromPointer(pointer) {
  return this["fromWireType"](HEAP32[pointer >> 2]);
}
var __embind_register_emval = (rawType, name) => {
  name = readLatin1String(name);
  registerType(rawType, {
    name: name,
    fromWireType: (handle) => {
      var rv = Emval.toValue(handle);
      __emval_decref(handle);
      return rv;
    },
    toWireType: (destructors, value) => Emval.toHandle(value),
    argPackAdvance: GenericWireTypeSize,
    readValueFromPointer: simpleReadValueFromPointer,
    destructorFunction: null,
  });
};
var embindRepr = (v) => {
  if (v === null) {
    return "null";
  }
  var t = typeof v;
  if (t === "object" || t === "array" || t === "function") {
    return v.toString();
  } else {
    return "" + v;
  }
};
var floatReadValueFromPointer = (name, width) => {
  switch (width) {
    case 4:
      return function (pointer) {
        return this["fromWireType"](HEAPF32[pointer >> 2]);
      };
    case 8:
      return function (pointer) {
        return this["fromWireType"](HEAPF64[pointer >> 3]);
      };
    default:
      throw new TypeError(`invalid float width (${width}): ${name}`);
  }
};
var __embind_register_float = (rawType, name, size) => {
  name = readLatin1String(name);
  registerType(rawType, {
    name: name,
    fromWireType: (value) => value,
    toWireType: (destructors, value) => {
      if (typeof value != "number" && typeof value != "boolean") {
        throw new TypeError(
          `Cannot convert ${embindRepr(value)} to ${this.name}`
        );
      }
      return value;
    },
    argPackAdvance: GenericWireTypeSize,
    readValueFromPointer: floatReadValueFromPointer(name, size),
    destructorFunction: null,
  });
};
var __embind_register_function = (
  name,
  argCount,
  rawArgTypesAddr,
  signature,
  rawInvoker,
  fn,
  isAsync
) => {
  var argTypes = heap32VectorToArray(argCount, rawArgTypesAddr);
  name = readLatin1String(name);
  rawInvoker = embind__requireFunction(signature, rawInvoker);
  exposePublicSymbol(
    name,
    function () {
      throwUnboundTypeError(
        `Cannot call ${name} due to unbound types`,
        argTypes
      );
    },
    argCount - 1
  );
  whenDependentTypesAreResolved([], argTypes, function (argTypes) {
    var invokerArgsArray = [argTypes[0], null].concat(argTypes.slice(1));
    replacePublicSymbol(
      name,
      craftInvokerFunction(
        name,
        invokerArgsArray,
        null,
        rawInvoker,
        fn,
        isAsync
      ),
      argCount - 1
    );
    return [];
  });
};
var integerReadValueFromPointer = (name, width, signed) => {
  switch (width) {
    case 1:
      return signed
        ? (pointer) => HEAP8[pointer >> 0]
        : (pointer) => HEAPU8[pointer >> 0];
    case 2:
      return signed
        ? (pointer) => HEAP16[pointer >> 1]
        : (pointer) => HEAPU16[pointer >> 1];
    case 4:
      return signed
        ? (pointer) => HEAP32[pointer >> 2]
        : (pointer) => HEAPU32[pointer >> 2];
    default:
      throw new TypeError(`invalid integer width (${width}): ${name}`);
  }
};
var __embind_register_integer = (
  primitiveType,
  name,
  size,
  minRange,
  maxRange
) => {
  name = readLatin1String(name);
  if (maxRange === -1) {
    maxRange = 4294967295;
  }
  var fromWireType = (value) => value;
  if (minRange === 0) {
    var bitshift = 32 - 8 * size;
    fromWireType = (value) => (value << bitshift) >>> bitshift;
  }
  var isUnsignedType = name.includes("unsigned");
  var checkAssertions = (value, toTypeName) => {
    if (typeof value != "number" && typeof value != "boolean") {
      throw new TypeError(
        `Cannot convert "${embindRepr(value)}" to ${toTypeName}`
      );
    }
    if (value < minRange || value > maxRange) {
      throw new TypeError(
        `Passing a number "${embindRepr(
          value
        )}" from JS side to C/C++ side to an argument of type "${name}", which is outside the valid range [${minRange}, ${maxRange}]!`
      );
    }
  };
  var toWireType;
  if (isUnsignedType) {
    toWireType = function (destructors, value) {
      checkAssertions(value, this.name);
      return value >>> 0;
    };
  } else {
    toWireType = function (destructors, value) {
      checkAssertions(value, this.name);
      return value;
    };
  }
  registerType(primitiveType, {
    name: name,
    fromWireType: fromWireType,
    toWireType: toWireType,
    argPackAdvance: GenericWireTypeSize,
    readValueFromPointer: integerReadValueFromPointer(
      name,
      size,
      minRange !== 0
    ),
    destructorFunction: null,
  });
};
var __embind_register_memory_view = (rawType, dataTypeIndex, name) => {
  var typeMapping = [
    Int8Array,
    Uint8Array,
    Int16Array,
    Uint16Array,
    Int32Array,
    Uint32Array,
    Float32Array,
    Float64Array,
  ];
  var TA = typeMapping[dataTypeIndex];
  function decodeMemoryView(handle) {
    var size = HEAPU32[handle >> 2];
    var data = HEAPU32[(handle + 4) >> 2];
    return new TA(HEAP8.buffer, data, size);
  }
  name = readLatin1String(name);
  registerType(
    rawType,
    {
      name: name,
      fromWireType: decodeMemoryView,
      argPackAdvance: GenericWireTypeSize,
      readValueFromPointer: decodeMemoryView,
    },
    { ignoreDuplicateRegistrations: true }
  );
};
var __embind_register_std_string = (rawType, name) => {
  name = readLatin1String(name);
  var stdStringIsUTF8 = name === "std::string";
  registerType(rawType, {
    name: name,
    fromWireType(value) {
      var length = HEAPU32[value >> 2];
      var payload = value + 4;
      var str;
      if (stdStringIsUTF8) {
        var decodeStartPtr = payload;
        for (var i = 0; i <= length; ++i) {
          var currentBytePtr = payload + i;
          if (i == length || HEAPU8[currentBytePtr] == 0) {
            var maxRead = currentBytePtr - decodeStartPtr;
            var stringSegment = UTF8ToString(decodeStartPtr, maxRead);
            if (str === undefined) {
              str = stringSegment;
            } else {
              str += String.fromCharCode(0);
              str += stringSegment;
            }
            decodeStartPtr = currentBytePtr + 1;
          }
        }
      } else {
        var a = new Array(length);
        for (var i = 0; i < length; ++i) {
          a[i] = String.fromCharCode(HEAPU8[payload + i]);
        }
        str = a.join("");
      }
      _free(value);
      return str;
    },
    toWireType(destructors, value) {
      if (value instanceof ArrayBuffer) {
        value = new Uint8Array(value);
      }
      var length;
      var valueIsOfTypeString = typeof value == "string";
      if (
        !(
          valueIsOfTypeString ||
          value instanceof Uint8Array ||
          value instanceof Uint8ClampedArray ||
          value instanceof Int8Array
        )
      ) {
        throwBindingError("Cannot pass non-string to std::string");
      }
      if (stdStringIsUTF8 && valueIsOfTypeString) {
        length = lengthBytesUTF8(value);
      } else {
        length = value.length;
      }
      var base = _malloc(4 + length + 1);
      var ptr = base + 4;
      HEAPU32[base >> 2] = length;
      if (stdStringIsUTF8 && valueIsOfTypeString) {
        stringToUTF8(value, ptr, length + 1);
      } else {
        if (valueIsOfTypeString) {
          for (var i = 0; i < length; ++i) {
            var charCode = value.charCodeAt(i);
            if (charCode > 255) {
              _free(ptr);
              throwBindingError(
                "String has UTF-16 code units that do not fit in 8 bits"
              );
            }
            HEAPU8[ptr + i] = charCode;
          }
        } else {
          for (var i = 0; i < length; ++i) {
            HEAPU8[ptr + i] = value[i];
          }
        }
      }
      if (destructors !== null) {
        destructors.push(_free, base);
      }
      return base;
    },
    argPackAdvance: GenericWireTypeSize,
    readValueFromPointer: readPointer,
    destructorFunction(ptr) {
      _free(ptr);
    },
  });
};
var UTF16Decoder =
  typeof TextDecoder != "undefined" ? new TextDecoder("utf-16le") : undefined;
var UTF16ToString = (ptr, maxBytesToRead) => {
  assert(
    ptr % 2 == 0,
    "Pointer passed to UTF16ToString must be aligned to two bytes!"
  );
  var endPtr = ptr;
  var idx = endPtr >> 1;
  var maxIdx = idx + maxBytesToRead / 2;
  while (!(idx >= maxIdx) && HEAPU16[idx]) ++idx;
  endPtr = idx << 1;
  if (endPtr - ptr > 32 && UTF16Decoder)
    return UTF16Decoder.decode(HEAPU8.subarray(ptr, endPtr));
  var str = "";
  for (var i = 0; !(i >= maxBytesToRead / 2); ++i) {
    var codeUnit = HEAP16[(ptr + i * 2) >> 1];
    if (codeUnit == 0) break;
    str += String.fromCharCode(codeUnit);
  }
  return str;
};
var stringToUTF16 = (str, outPtr, maxBytesToWrite) => {
  assert(
    outPtr % 2 == 0,
    "Pointer passed to stringToUTF16 must be aligned to two bytes!"
  );
  assert(
    typeof maxBytesToWrite == "number",
    "stringToUTF16(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!"
  );
  if (maxBytesToWrite === undefined) {
    maxBytesToWrite = 2147483647;
  }
  if (maxBytesToWrite < 2) return 0;
  maxBytesToWrite -= 2;
  var startPtr = outPtr;
  var numCharsToWrite =
    maxBytesToWrite < str.length * 2 ? maxBytesToWrite / 2 : str.length;
  for (var i = 0; i < numCharsToWrite; ++i) {
    var codeUnit = str.charCodeAt(i);
    HEAP16[outPtr >> 1] = codeUnit;
    outPtr += 2;
  }
  HEAP16[outPtr >> 1] = 0;
  return outPtr - startPtr;
};
var lengthBytesUTF16 = (str) => str.length * 2;
var UTF32ToString = (ptr, maxBytesToRead) => {
  assert(
    ptr % 4 == 0,
    "Pointer passed to UTF32ToString must be aligned to four bytes!"
  );
  var i = 0;
  var str = "";
  while (!(i >= maxBytesToRead / 4)) {
    var utf32 = HEAP32[(ptr + i * 4) >> 2];
    if (utf32 == 0) break;
    ++i;
    if (utf32 >= 65536) {
      var ch = utf32 - 65536;
      str += String.fromCharCode(55296 | (ch >> 10), 56320 | (ch & 1023));
    } else {
      str += String.fromCharCode(utf32);
    }
  }
  return str;
};
var stringToUTF32 = (str, outPtr, maxBytesToWrite) => {
  assert(
    outPtr % 4 == 0,
    "Pointer passed to stringToUTF32 must be aligned to four bytes!"
  );
  assert(
    typeof maxBytesToWrite == "number",
    "stringToUTF32(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!"
  );
  if (maxBytesToWrite === undefined) {
    maxBytesToWrite = 2147483647;
  }
  if (maxBytesToWrite < 4) return 0;
  var startPtr = outPtr;
  var endPtr = startPtr + maxBytesToWrite - 4;
  for (var i = 0; i < str.length; ++i) {
    var codeUnit = str.charCodeAt(i);
    if (codeUnit >= 55296 && codeUnit <= 57343) {
      var trailSurrogate = str.charCodeAt(++i);
      codeUnit = (65536 + ((codeUnit & 1023) << 10)) | (trailSurrogate & 1023);
    }
    HEAP32[outPtr >> 2] = codeUnit;
    outPtr += 4;
    if (outPtr + 4 > endPtr) break;
  }
  HEAP32[outPtr >> 2] = 0;
  return outPtr - startPtr;
};
var lengthBytesUTF32 = (str) => {
  var len = 0;
  for (var i = 0; i < str.length; ++i) {
    var codeUnit = str.charCodeAt(i);
    if (codeUnit >= 55296 && codeUnit <= 57343) ++i;
    len += 4;
  }
  return len;
};
var __embind_register_std_wstring = (rawType, charSize, name) => {
  name = readLatin1String(name);
  var decodeString, encodeString, getHeap, lengthBytesUTF, shift;
  if (charSize === 2) {
    decodeString = UTF16ToString;
    encodeString = stringToUTF16;
    lengthBytesUTF = lengthBytesUTF16;
    getHeap = () => HEAPU16;
    shift = 1;
  } else if (charSize === 4) {
    decodeString = UTF32ToString;
    encodeString = stringToUTF32;
    lengthBytesUTF = lengthBytesUTF32;
    getHeap = () => HEAPU32;
    shift = 2;
  }
  registerType(rawType, {
    name: name,
    fromWireType: (value) => {
      var length = HEAPU32[value >> 2];
      var HEAP = getHeap();
      var str;
      var decodeStartPtr = value + 4;
      for (var i = 0; i <= length; ++i) {
        var currentBytePtr = value + 4 + i * charSize;
        if (i == length || HEAP[currentBytePtr >> shift] == 0) {
          var maxReadBytes = currentBytePtr - decodeStartPtr;
          var stringSegment = decodeString(decodeStartPtr, maxReadBytes);
          if (str === undefined) {
            str = stringSegment;
          } else {
            str += String.fromCharCode(0);
            str += stringSegment;
          }
          decodeStartPtr = currentBytePtr + charSize;
        }
      }
      _free(value);
      return str;
    },
    toWireType: (destructors, value) => {
      if (!(typeof value == "string")) {
        throwBindingError(`Cannot pass non-string to C++ string type ${name}`);
      }
      var length = lengthBytesUTF(value);
      var ptr = _malloc(4 + length + charSize);
      HEAPU32[ptr >> 2] = length >> shift;
      encodeString(value, ptr + 4, length + charSize);
      if (destructors !== null) {
        destructors.push(_free, ptr);
      }
      return ptr;
    },
    argPackAdvance: GenericWireTypeSize,
    readValueFromPointer: simpleReadValueFromPointer,
    destructorFunction(ptr) {
      _free(ptr);
    },
  });
};
var __embind_register_void = (rawType, name) => {
  name = readLatin1String(name);
  registerType(rawType, {
    isVoid: true,
    name: name,
    argPackAdvance: 0,
    fromWireType: () => undefined,
    toWireType: (destructors, o) => undefined,
  });
};
var nowIsMonotonic = true;
var __emscripten_get_now_is_monotonic = () => nowIsMonotonic;
var __emscripten_throw_longjmp = () => {
  throw new EmscriptenSjLj();
};
var __emval_incref = (handle) => {
  if (handle > 4) {
    emval_handles.get(handle).refcount += 1;
  }
};
var requireRegisteredType = (rawType, humanName) => {
  var impl = registeredTypes[rawType];
  if (undefined === impl) {
    throwBindingError(humanName + " has unknown type " + getTypeName(rawType));
  }
  return impl;
};
var __emval_take_value = (type, arg) => {
  type = requireRegisteredType(type, "_emval_take_value");
  var v = type["readValueFromPointer"](arg);
  return Emval.toHandle(v);
};
var convertI32PairToI53Checked = (lo, hi) => {
  assert(lo == lo >>> 0 || lo == (lo | 0));
  assert(hi === (hi | 0));
  return (hi + 2097152) >>> 0 < 4194305 - !!lo
    ? (lo >>> 0) + hi * 4294967296
    : NaN;
};
function __gmtime_js(time_low, time_high, tmPtr) {
  var time = convertI32PairToI53Checked(time_low, time_high);
  var date = new Date(time * 1e3);
  HEAP32[tmPtr >> 2] = date.getUTCSeconds();
  HEAP32[(tmPtr + 4) >> 2] = date.getUTCMinutes();
  HEAP32[(tmPtr + 8) >> 2] = date.getUTCHours();
  HEAP32[(tmPtr + 12) >> 2] = date.getUTCDate();
  HEAP32[(tmPtr + 16) >> 2] = date.getUTCMonth();
  HEAP32[(tmPtr + 20) >> 2] = date.getUTCFullYear() - 1900;
  HEAP32[(tmPtr + 24) >> 2] = date.getUTCDay();
  var start = Date.UTC(date.getUTCFullYear(), 0, 1, 0, 0, 0, 0);
  var yday = ((date.getTime() - start) / (1e3 * 60 * 60 * 24)) | 0;
  HEAP32[(tmPtr + 28) >> 2] = yday;
}
var isLeapYear = (year) =>
  year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
var MONTH_DAYS_LEAP_CUMULATIVE = [
  0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335,
];
var MONTH_DAYS_REGULAR_CUMULATIVE = [
  0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
];
var ydayFromDate = (date) => {
  var leap = isLeapYear(date.getFullYear());
  var monthDaysCumulative = leap
    ? MONTH_DAYS_LEAP_CUMULATIVE
    : MONTH_DAYS_REGULAR_CUMULATIVE;
  var yday = monthDaysCumulative[date.getMonth()] + date.getDate() - 1;
  return yday;
};
function __localtime_js(time_low, time_high, tmPtr) {
  var time = convertI32PairToI53Checked(time_low, time_high);
  var date = new Date(time * 1e3);
  HEAP32[tmPtr >> 2] = date.getSeconds();
  HEAP32[(tmPtr + 4) >> 2] = date.getMinutes();
  HEAP32[(tmPtr + 8) >> 2] = date.getHours();
  HEAP32[(tmPtr + 12) >> 2] = date.getDate();
  HEAP32[(tmPtr + 16) >> 2] = date.getMonth();
  HEAP32[(tmPtr + 20) >> 2] = date.getFullYear() - 1900;
  HEAP32[(tmPtr + 24) >> 2] = date.getDay();
  var yday = ydayFromDate(date) | 0;
  HEAP32[(tmPtr + 28) >> 2] = yday;
  HEAP32[(tmPtr + 36) >> 2] = -(date.getTimezoneOffset() * 60);
  var start = new Date(date.getFullYear(), 0, 1);
  var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
  var winterOffset = start.getTimezoneOffset();
  var dst =
    (summerOffset != winterOffset &&
      date.getTimezoneOffset() == Math.min(winterOffset, summerOffset)) | 0;
  HEAP32[(tmPtr + 32) >> 2] = dst;
}
var __mktime_js = function (tmPtr) {
  var ret = (() => {
    var date = new Date(
      HEAP32[(tmPtr + 20) >> 2] + 1900,
      HEAP32[(tmPtr + 16) >> 2],
      HEAP32[(tmPtr + 12) >> 2],
      HEAP32[(tmPtr + 8) >> 2],
      HEAP32[(tmPtr + 4) >> 2],
      HEAP32[tmPtr >> 2],
      0
    );
    var dst = HEAP32[(tmPtr + 32) >> 2];
    var guessedOffset = date.getTimezoneOffset();
    var start = new Date(date.getFullYear(), 0, 1);
    var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
    var winterOffset = start.getTimezoneOffset();
    var dstOffset = Math.min(winterOffset, summerOffset);
    if (dst < 0) {
      HEAP32[(tmPtr + 32) >> 2] = Number(
        summerOffset != winterOffset && dstOffset == guessedOffset
      );
    } else if (dst > 0 != (dstOffset == guessedOffset)) {
      var nonDstOffset = Math.max(winterOffset, summerOffset);
      var trueOffset = dst > 0 ? dstOffset : nonDstOffset;
      date.setTime(date.getTime() + (trueOffset - guessedOffset) * 6e4);
    }
    HEAP32[(tmPtr + 24) >> 2] = date.getDay();
    var yday = ydayFromDate(date) | 0;
    HEAP32[(tmPtr + 28) >> 2] = yday;
    HEAP32[tmPtr >> 2] = date.getSeconds();
    HEAP32[(tmPtr + 4) >> 2] = date.getMinutes();
    HEAP32[(tmPtr + 8) >> 2] = date.getHours();
    HEAP32[(tmPtr + 12) >> 2] = date.getDate();
    HEAP32[(tmPtr + 16) >> 2] = date.getMonth();
    HEAP32[(tmPtr + 20) >> 2] = date.getYear();
    return date.getTime() / 1e3;
  })();
  return (
    setTempRet0(
      ((tempDouble = ret),
      +Math.abs(tempDouble) >= 1
        ? tempDouble > 0
          ? +Math.floor(tempDouble / 4294967296) >>> 0
          : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>>
            0
        : 0)
    ),
    ret >>> 0
  );
};
function __mmap_js(
  len,
  prot,
  flags,
  fd,
  offset_low,
  offset_high,
  allocated,
  addr
) {
  var offset = convertI32PairToI53Checked(offset_low, offset_high);
  try {
    if (isNaN(offset)) return 61;
    var stream = SYSCALLS.getStreamFromFD(fd);
    var res = FS.mmap(stream, len, offset, prot, flags);
    var ptr = res.ptr;
    HEAP32[allocated >> 2] = res.allocated;
    HEAPU32[addr >> 2] = ptr;
    return 0;
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return -e.errno;
  }
}
function __munmap_js(addr, len, prot, flags, fd, offset_low, offset_high) {
  var offset = convertI32PairToI53Checked(offset_low, offset_high);
  try {
    if (isNaN(offset)) return 61;
    var stream = SYSCALLS.getStreamFromFD(fd);
    if (prot & 2) {
      SYSCALLS.doMsync(addr, stream, len, flags, offset);
    }
    FS.munmap(stream);
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return -e.errno;
  }
}
var stringToNewUTF8 = (str) => {
  var size = lengthBytesUTF8(str) + 1;
  var ret = _malloc(size);
  if (ret) stringToUTF8(str, ret, size);
  return ret;
};
var __tzset_js = (timezone, daylight, tzname) => {
  var currentYear = new Date().getFullYear();
  var winter = new Date(currentYear, 0, 1);
  var summer = new Date(currentYear, 6, 1);
  var winterOffset = winter.getTimezoneOffset();
  var summerOffset = summer.getTimezoneOffset();
  var stdTimezoneOffset = Math.max(winterOffset, summerOffset);
  HEAPU32[timezone >> 2] = stdTimezoneOffset * 60;
  HEAP32[daylight >> 2] = Number(winterOffset != summerOffset);
  function extractZone(date) {
    var match = date.toTimeString().match(/\(([A-Za-z ]+)\)$/);
    return match ? match[1] : "GMT";
  }
  var winterName = extractZone(winter);
  var summerName = extractZone(summer);
  var winterNamePtr = stringToNewUTF8(winterName);
  var summerNamePtr = stringToNewUTF8(summerName);
  if (summerOffset < winterOffset) {
    HEAPU32[tzname >> 2] = winterNamePtr;
    HEAPU32[(tzname + 4) >> 2] = summerNamePtr;
  } else {
    HEAPU32[tzname >> 2] = summerNamePtr;
    HEAPU32[(tzname + 4) >> 2] = winterNamePtr;
  }
};
var _abort = () => {
  abort("native code called abort()");
};
var _emscripten_date_now = () => Date.now();
var JSEvents = {
  inEventHandler: 0,
  removeAllEventListeners() {
    for (var i = JSEvents.eventHandlers.length - 1; i >= 0; --i) {
      JSEvents._removeHandler(i);
    }
    JSEvents.eventHandlers = [];
    JSEvents.deferredCalls = [];
  },
  registerRemoveEventListeners() {
    if (!JSEvents.removeEventListenersRegistered) {
      __ATEXIT__.push(JSEvents.removeAllEventListeners);
      JSEvents.removeEventListenersRegistered = true;
    }
  },
  deferredCalls: [],
  deferCall(targetFunction, precedence, argsList) {
    function arraysHaveEqualContent(arrA, arrB) {
      if (arrA.length != arrB.length) return false;
      for (var i in arrA) {
        if (arrA[i] != arrB[i]) return false;
      }
      return true;
    }
    for (var i in JSEvents.deferredCalls) {
      var call = JSEvents.deferredCalls[i];
      if (
        call.targetFunction == targetFunction &&
        arraysHaveEqualContent(call.argsList, argsList)
      ) {
        return;
      }
    }
    JSEvents.deferredCalls.push({
      targetFunction: targetFunction,
      precedence: precedence,
      argsList: argsList,
    });
    JSEvents.deferredCalls.sort((x, y) => x.precedence < y.precedence);
  },
  removeDeferredCalls(targetFunction) {
    for (var i = 0; i < JSEvents.deferredCalls.length; ++i) {
      if (JSEvents.deferredCalls[i].targetFunction == targetFunction) {
        JSEvents.deferredCalls.splice(i, 1);
        --i;
      }
    }
  },
  canPerformEventHandlerRequests() {
    if (navigator.userActivation) {
      return navigator.userActivation.isActive;
    }
    return (
      JSEvents.inEventHandler &&
      JSEvents.currentEventHandler.allowsDeferredCalls
    );
  },
  runDeferredCalls() {
    if (!JSEvents.canPerformEventHandlerRequests()) {
      return;
    }
    for (var i = 0; i < JSEvents.deferredCalls.length; ++i) {
      var call = JSEvents.deferredCalls[i];
      JSEvents.deferredCalls.splice(i, 1);
      --i;
      call.targetFunction.apply(null, call.argsList);
    }
  },
  eventHandlers: [],
  removeAllHandlersOnTarget: (target, eventTypeString) => {
    for (var i = 0; i < JSEvents.eventHandlers.length; ++i) {
      if (
        JSEvents.eventHandlers[i].target == target &&
        (!eventTypeString ||
          eventTypeString == JSEvents.eventHandlers[i].eventTypeString)
      ) {
        JSEvents._removeHandler(i--);
      }
    }
  },
  _removeHandler(i) {
    var h = JSEvents.eventHandlers[i];
    h.target.removeEventListener(
      h.eventTypeString,
      h.eventListenerFunc,
      h.useCapture
    );
    JSEvents.eventHandlers.splice(i, 1);
  },
  registerOrRemoveHandler(eventHandler) {
    if (!eventHandler.target) {
      err(
        "registerOrRemoveHandler: the target element for event handler registration does not exist, when processing the following event handler registration:"
      );
      console.dir(eventHandler);
      return -4;
    }
    var jsEventHandler = function jsEventHandler(event) {
      ++JSEvents.inEventHandler;
      JSEvents.currentEventHandler = eventHandler;
      JSEvents.runDeferredCalls();
      eventHandler.handlerFunc(event);
      JSEvents.runDeferredCalls();
      --JSEvents.inEventHandler;
    };
    if (eventHandler.callbackfunc) {
      eventHandler.eventListenerFunc = jsEventHandler;
      eventHandler.target.addEventListener(
        eventHandler.eventTypeString,
        jsEventHandler,
        eventHandler.useCapture
      );
      JSEvents.eventHandlers.push(eventHandler);
      JSEvents.registerRemoveEventListeners();
    } else {
      for (var i = 0; i < JSEvents.eventHandlers.length; ++i) {
        if (
          JSEvents.eventHandlers[i].target == eventHandler.target &&
          JSEvents.eventHandlers[i].eventTypeString ==
            eventHandler.eventTypeString
        ) {
          JSEvents._removeHandler(i--);
        }
      }
    }
    return 0;
  },
  getNodeNameForTarget(target) {
    if (!target) return "";
    if (target == window) return "#window";
    if (target == screen) return "#screen";
    return target && target.nodeName ? target.nodeName : "";
  },
  fullscreenEnabled() {
    return document.fullscreenEnabled || document.webkitFullscreenEnabled;
  },
};
var maybeCStringToJsString = (cString) =>
  cString > 2 ? UTF8ToString(cString) : cString;
var specialHTMLTargets = [
  0,
  typeof document != "undefined" ? document : 0,
  typeof window != "undefined" ? window : 0,
];
var findEventTarget = (target) => {
  return Module['canvas'];
};
var findCanvasEventTarget = (target) => findEventTarget(target);
var _emscripten_get_canvas_element_size = (target, width, height) => {
  var canvas = findCanvasEventTarget(target);
  if (!canvas) return -4;
  HEAP32[width >> 2] = canvas.width;
  HEAP32[height >> 2] = canvas.height;
};
var getBoundingClientRect = (e) =>
  specialHTMLTargets.indexOf(e) < 0
    ? e.getBoundingClientRect()
    : { left: 0, top: 0 };
var _emscripten_get_element_css_size = (target, width, height) => {
  target = findEventTarget(target);
  if (!target) return -4;
  HEAPF64[width >> 3] = target.width;
  HEAPF64[height >> 3] = target.height;
  return 0;
};
var _emscripten_get_now;
_emscripten_get_now = () => wx.getPerformance().now();
var _emscripten_memcpy_js = (dest, src, num) =>
  HEAPU8.copyWithin(dest, src, src + num);
var getHeapMax = () => 2147483648;
var growMemory = (size) => {
  var b = wasmMemory.buffer;
  var pages = (size - b.byteLength + 65535) / 65536;
  try {
    wasmMemory.grow(pages);
    updateMemoryViews();
    return 1;
  } catch (e) {
    err(
      `growMemory: Attempted to grow heap from ${b.byteLength} bytes to ${size} bytes, but got error: ${e}`
    );
  }
};
var _emscripten_resize_heap = (requestedSize) => {
  var oldSize = HEAPU8.length;
  requestedSize >>>= 0;
  assert(requestedSize > oldSize);
  var maxHeapSize = getHeapMax();
  if (requestedSize > maxHeapSize) {
    err(
      `Cannot enlarge memory, requested ${requestedSize} bytes, but the limit is ${maxHeapSize} bytes!`
    );
    return false;
  }
  var alignUp = (x, multiple) => x + ((multiple - (x % multiple)) % multiple);
  for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {
    var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown);
    overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296);
    var newSize = Math.min(
      maxHeapSize,
      alignUp(Math.max(requestedSize, overGrownHeapSize), 65536)
    );
    var replacement = growMemory(newSize);
    if (replacement) {
      return true;
    }
  }
  err(
    `Failed to grow the heap from ${oldSize} bytes to ${newSize} bytes, not enough memory!`
  );
  return false;
};
var webgl_enable_ANGLE_instanced_arrays = (ctx) => {
  var ext = ctx.getExtension("ANGLE_instanced_arrays");
  if (ext) {
    ctx["vertexAttribDivisor"] = (index, divisor) =>
      ext["vertexAttribDivisorANGLE"](index, divisor);
    ctx["drawArraysInstanced"] = (mode, first, count, primcount) =>
      ext["drawArraysInstancedANGLE"](mode, first, count, primcount);
    ctx["drawElementsInstanced"] = (mode, count, type, indices, primcount) =>
      ext["drawElementsInstancedANGLE"](mode, count, type, indices, primcount);
    return 1;
  }
};
var webgl_enable_OES_vertex_array_object = (ctx) => {
  var ext = ctx.getExtension("OES_vertex_array_object");
  if (ext) {
    ctx["createVertexArray"] = () => ext["createVertexArrayOES"]();
    ctx["deleteVertexArray"] = (vao) => ext["deleteVertexArrayOES"](vao);
    ctx["bindVertexArray"] = (vao) => ext["bindVertexArrayOES"](vao);
    ctx["isVertexArray"] = (vao) => ext["isVertexArrayOES"](vao);
    return 1;
  }
};
var webgl_enable_WEBGL_draw_buffers = (ctx) => {
  var ext = ctx.getExtension("WEBGL_draw_buffers");
  if (ext) {
    ctx["drawBuffers"] = (n, bufs) => ext["drawBuffersWEBGL"](n, bufs);
    return 1;
  }
};
var webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance = (ctx) =>
  !!(ctx.dibvbi = ctx.getExtension(
    "WEBGL_draw_instanced_base_vertex_base_instance"
  ));
var webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance = (ctx) =>
  !!(ctx.mdibvbi = ctx.getExtension(
    "WEBGL_multi_draw_instanced_base_vertex_base_instance"
  ));
var webgl_enable_WEBGL_multi_draw = (ctx) =>
  !!(ctx.multiDrawWebgl = ctx.getExtension("WEBGL_multi_draw"));

var emscripten_webgl_power_preferences = [
  "default",
  "low-power",
  "high-performance",
];
var _emscripten_webgl_do_create_context = (target, attributes) => {
  assert(attributes);
  var a = attributes >> 2;
  var powerPreference = HEAP32[a + (24 >> 2)];
  var contextAttributes = {
    alpha: !!HEAP32[a + (0 >> 2)],
    depth: !!HEAP32[a + (4 >> 2)],
    stencil: !!HEAP32[a + (8 >> 2)],
    antialias: !!HEAP32[a + (12 >> 2)],
    premultipliedAlpha: !!HEAP32[a + (16 >> 2)],
    preserveDrawingBuffer: !!HEAP32[a + (20 >> 2)],
    powerPreference: emscripten_webgl_power_preferences[powerPreference],
    failIfMajorPerformanceCaveat: !!HEAP32[a + (28 >> 2)],
    majorVersion: HEAP32[a + (32 >> 2)],
    minorVersion: HEAP32[a + (36 >> 2)],
    enableExtensionsByDefault: HEAP32[a + (40 >> 2)],
    explicitSwapControl: HEAP32[a + (44 >> 2)],
    proxyContextToMainThread: HEAP32[a + (48 >> 2)],
    renderViaOffscreenBackBuffer: HEAP32[a + (52 >> 2)],
  };
  var canvas = findCanvasEventTarget(target);
  if (!canvas) {
    return 0;
  }
  if (contextAttributes.explicitSwapControl) {
    return 0;
  }
  var contextHandle = GL.createContext(canvas, contextAttributes);
  return contextHandle;
};
var _emscripten_webgl_create_context = _emscripten_webgl_do_create_context;
var _emscripten_webgl_destroy_context = (contextHandle) => {
  if (GL.currentContext == contextHandle) GL.currentContext = 0;
  GL.deleteContext(contextHandle);
};
var _emscripten_webgl_do_get_current_context = () =>
  GL.currentContext ? GL.currentContext.handle : 0;
var _emscripten_webgl_get_current_context =
  _emscripten_webgl_do_get_current_context;
var _emscripten_webgl_init_context_attributes = (attributes) => {
  assert(attributes);
  var a = attributes >> 2;
  for (var i = 0; i < 56 >> 2; ++i) {
    HEAP32[a + i] = 0;
  }
  HEAP32[a + (0 >> 2)] =
    HEAP32[a + (4 >> 2)] =
    HEAP32[a + (12 >> 2)] =
    HEAP32[a + (16 >> 2)] =
    HEAP32[a + (32 >> 2)] =
    HEAP32[a + (40 >> 2)] =
      1;
};
var _emscripten_webgl_make_context_current = (contextHandle) => {
  var success = GL.makeContextCurrent(contextHandle);
  return success ? 0 : -5;
};
var ENV = {};
var getExecutableName = () => thisProgram || "./this.program";
var getEnvStrings = () => {
  if (!getEnvStrings.strings) {
    var lang =
      (
        (typeof navigator == "object" &&
          navigator.languages &&
          navigator.languages[0]) ||
        "C"
      ).replace("-", "_") + ".UTF-8";
    var env = {
      USER: "web_user",
      LOGNAME: "web_user",
      PATH: "/",
      PWD: "/",
      HOME: "/home/web_user",
      LANG: lang,
      _: getExecutableName(),
    };
    for (var x in ENV) {
      if (ENV[x] === undefined) delete env[x];
      else env[x] = ENV[x];
    }
    var strings = [];
    for (var x in env) {
      strings.push(`${x}=${env[x]}`);
    }
    getEnvStrings.strings = strings;
  }
  return getEnvStrings.strings;
};
var stringToAscii = (str, buffer) => {
  for (var i = 0; i < str.length; ++i) {
    assert(str.charCodeAt(i) === (str.charCodeAt(i) & 255));
    HEAP8[buffer++ >> 0] = str.charCodeAt(i);
  }
  HEAP8[buffer >> 0] = 0;
};
var _environ_get = (__environ, environ_buf) => {
  var bufSize = 0;
  getEnvStrings().forEach((string, i) => {
    var ptr = environ_buf + bufSize;
    HEAPU32[(__environ + i * 4) >> 2] = ptr;
    stringToAscii(string, ptr);
    bufSize += string.length + 1;
  });
  return 0;
};
var _environ_sizes_get = (penviron_count, penviron_buf_size) => {
  var strings = getEnvStrings();
  HEAPU32[penviron_count >> 2] = strings.length;
  var bufSize = 0;
  strings.forEach((string) => (bufSize += string.length + 1));
  HEAPU32[penviron_buf_size >> 2] = bufSize;
  return 0;
};
function _fd_close(fd) {
  try {
    var stream = SYSCALLS.getStreamFromFD(fd);
    FS.close(stream);
    return 0;
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return e.errno;
  }
}
var doReadv = (stream, iov, iovcnt, offset) => {
  var ret = 0;
  for (var i = 0; i < iovcnt; i++) {
    var ptr = HEAPU32[iov >> 2];
    var len = HEAPU32[(iov + 4) >> 2];
    iov += 8;
    var curr = FS.read(stream, HEAP8, ptr, len, offset);
    if (curr < 0) return -1;
    ret += curr;
    if (curr < len) break;
    if (typeof offset !== "undefined") {
      offset += curr;
    }
  }
  return ret;
};
function _fd_pread(fd, iov, iovcnt, offset_low, offset_high, pnum) {
  var offset = convertI32PairToI53Checked(offset_low, offset_high);
  try {
    if (isNaN(offset)) return 61;
    var stream = SYSCALLS.getStreamFromFD(fd);
    var num = doReadv(stream, iov, iovcnt, offset);
    HEAPU32[pnum >> 2] = num;
    return 0;
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return e.errno;
  }
}
function _fd_read(fd, iov, iovcnt, pnum) {
  try {
    var stream = SYSCALLS.getStreamFromFD(fd);
    var num = doReadv(stream, iov, iovcnt);
    HEAPU32[pnum >> 2] = num;
    return 0;
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return e.errno;
  }
}
function _fd_seek(fd, offset_low, offset_high, whence, newOffset) {
  var offset = convertI32PairToI53Checked(offset_low, offset_high);
  try {
    if (isNaN(offset)) return 61;
    var stream = SYSCALLS.getStreamFromFD(fd);
    FS.llseek(stream, offset, whence);
    (tempI64 = [
      stream.position >>> 0,
      ((tempDouble = stream.position),
      +Math.abs(tempDouble) >= 1
        ? tempDouble > 0
          ? +Math.floor(tempDouble / 4294967296) >>> 0
          : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>>
            0
        : 0),
    ]),
      (HEAP32[newOffset >> 2] = tempI64[0]),
      (HEAP32[(newOffset + 4) >> 2] = tempI64[1]);
    if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null;
    return 0;
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return e.errno;
  }
}
var doWritev = (stream, iov, iovcnt, offset) => {
  var ret = 0;
  for (var i = 0; i < iovcnt; i++) {
    var ptr = HEAPU32[iov >> 2];
    var len = HEAPU32[(iov + 4) >> 2];
    iov += 8;
    var curr = FS.write(stream, HEAP8, ptr, len, offset);
    if (curr < 0) return -1;
    ret += curr;
    if (typeof offset !== "undefined") {
      offset += curr;
    }
  }
  return ret;
};
function _fd_write(fd, iov, iovcnt, pnum) {
  try {
    var stream = SYSCALLS.getStreamFromFD(fd);
    var num = doWritev(stream, iov, iovcnt);
    HEAPU32[pnum >> 2] = num;
    return 0;
  } catch (e) {
    if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
    return e.errno;
  }
}
var _llvm_eh_typeid_for = (type) => type;
var arraySum = (array, index) => {
  var sum = 0;
  for (var i = 0; i <= index; sum += array[i++]) {}
  return sum;
};
var MONTH_DAYS_LEAP = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
var MONTH_DAYS_REGULAR = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
var addDays = (date, days) => {
  var newDate = new Date(date.getTime());
  while (days > 0) {
    var leap = isLeapYear(newDate.getFullYear());
    var currentMonth = newDate.getMonth();
    var daysInCurrentMonth = (leap ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR)[
      currentMonth
    ];
    if (days > daysInCurrentMonth - newDate.getDate()) {
      days -= daysInCurrentMonth - newDate.getDate() + 1;
      newDate.setDate(1);
      if (currentMonth < 11) {
        newDate.setMonth(currentMonth + 1);
      } else {
        newDate.setMonth(0);
        newDate.setFullYear(newDate.getFullYear() + 1);
      }
    } else {
      newDate.setDate(newDate.getDate() + days);
      return newDate;
    }
  }
  return newDate;
};
var writeArrayToMemory = (array, buffer) => {
  assert(
    array.length >= 0,
    "writeArrayToMemory array must have a length (should be an array or typed array)"
  );
  HEAP8.set(array, buffer);
};
var _strftime = (s, maxsize, format, tm) => {
  var tm_zone = HEAPU32[(tm + 40) >> 2];
  var date = {
    tm_sec: HEAP32[tm >> 2],
    tm_min: HEAP32[(tm + 4) >> 2],
    tm_hour: HEAP32[(tm + 8) >> 2],
    tm_mday: HEAP32[(tm + 12) >> 2],
    tm_mon: HEAP32[(tm + 16) >> 2],
    tm_year: HEAP32[(tm + 20) >> 2],
    tm_wday: HEAP32[(tm + 24) >> 2],
    tm_yday: HEAP32[(tm + 28) >> 2],
    tm_isdst: HEAP32[(tm + 32) >> 2],
    tm_gmtoff: HEAP32[(tm + 36) >> 2],
    tm_zone: tm_zone ? UTF8ToString(tm_zone) : "",
  };
  var pattern = UTF8ToString(format);
  var EXPANSION_RULES_1 = {
    "%c": "%a %b %d %H:%M:%S %Y",
    "%D": "%m/%d/%y",
    "%F": "%Y-%m-%d",
    "%h": "%b",
    "%r": "%I:%M:%S %p",
    "%R": "%H:%M",
    "%T": "%H:%M:%S",
    "%x": "%m/%d/%y",
    "%X": "%H:%M:%S",
    "%Ec": "%c",
    "%EC": "%C",
    "%Ex": "%m/%d/%y",
    "%EX": "%H:%M:%S",
    "%Ey": "%y",
    "%EY": "%Y",
    "%Od": "%d",
    "%Oe": "%e",
    "%OH": "%H",
    "%OI": "%I",
    "%Om": "%m",
    "%OM": "%M",
    "%OS": "%S",
    "%Ou": "%u",
    "%OU": "%U",
    "%OV": "%V",
    "%Ow": "%w",
    "%OW": "%W",
    "%Oy": "%y",
  };
  for (var rule in EXPANSION_RULES_1) {
    pattern = pattern.replace(new RegExp(rule, "g"), EXPANSION_RULES_1[rule]);
  }
  var WEEKDAYS = [
    "Sunday",
    "Monday",
    "Tuesday",
    "Wednesday",
    "Thursday",
    "Friday",
    "Saturday",
  ];
  var MONTHS = [
    "January",
    "February",
    "March",
    "April",
    "May",
    "June",
    "July",
    "August",
    "September",
    "October",
    "November",
    "December",
  ];
  function leadingSomething(value, digits, character) {
    var str = typeof value == "number" ? value.toString() : value || "";
    while (str.length < digits) {
      str = character[0] + str;
    }
    return str;
  }
  function leadingNulls(value, digits) {
    return leadingSomething(value, digits, "0");
  }
  function compareByDay(date1, date2) {
    function sgn(value) {
      return value < 0 ? -1 : value > 0 ? 1 : 0;
    }
    var compare;
    if ((compare = sgn(date1.getFullYear() - date2.getFullYear())) === 0) {
      if ((compare = sgn(date1.getMonth() - date2.getMonth())) === 0) {
        compare = sgn(date1.getDate() - date2.getDate());
      }
    }
    return compare;
  }
  function getFirstWeekStartDate(janFourth) {
    switch (janFourth.getDay()) {
      case 0:
        return new Date(janFourth.getFullYear() - 1, 11, 29);
      case 1:
        return janFourth;
      case 2:
        return new Date(janFourth.getFullYear(), 0, 3);
      case 3:
        return new Date(janFourth.getFullYear(), 0, 2);
      case 4:
        return new Date(janFourth.getFullYear(), 0, 1);
      case 5:
        return new Date(janFourth.getFullYear() - 1, 11, 31);
      case 6:
        return new Date(janFourth.getFullYear() - 1, 11, 30);
    }
  }
  function getWeekBasedYear(date) {
    var thisDate = addDays(new Date(date.tm_year + 1900, 0, 1), date.tm_yday);
    var janFourthThisYear = new Date(thisDate.getFullYear(), 0, 4);
    var janFourthNextYear = new Date(thisDate.getFullYear() + 1, 0, 4);
    var firstWeekStartThisYear = getFirstWeekStartDate(janFourthThisYear);
    var firstWeekStartNextYear = getFirstWeekStartDate(janFourthNextYear);
    if (compareByDay(firstWeekStartThisYear, thisDate) <= 0) {
      if (compareByDay(firstWeekStartNextYear, thisDate) <= 0) {
        return thisDate.getFullYear() + 1;
      }
      return thisDate.getFullYear();
    }
    return thisDate.getFullYear() - 1;
  }
  var EXPANSION_RULES_2 = {
    "%a": (date) => WEEKDAYS[date.tm_wday].substring(0, 3),
    "%A": (date) => WEEKDAYS[date.tm_wday],
    "%b": (date) => MONTHS[date.tm_mon].substring(0, 3),
    "%B": (date) => MONTHS[date.tm_mon],
    "%C": (date) => {
      var year = date.tm_year + 1900;
      return leadingNulls((year / 100) | 0, 2);
    },
    "%d": (date) => leadingNulls(date.tm_mday, 2),
    "%e": (date) => leadingSomething(date.tm_mday, 2, " "),
    "%g": (date) => getWeekBasedYear(date).toString().substring(2),
    "%G": (date) => getWeekBasedYear(date),
    "%H": (date) => leadingNulls(date.tm_hour, 2),
    "%I": (date) => {
      var twelveHour = date.tm_hour;
      if (twelveHour == 0) twelveHour = 12;
      else if (twelveHour > 12) twelveHour -= 12;
      return leadingNulls(twelveHour, 2);
    },
    "%j": (date) =>
      leadingNulls(
        date.tm_mday +
          arraySum(
            isLeapYear(date.tm_year + 1900)
              ? MONTH_DAYS_LEAP
              : MONTH_DAYS_REGULAR,
            date.tm_mon - 1
          ),
        3
      ),
    "%m": (date) => leadingNulls(date.tm_mon + 1, 2),
    "%M": (date) => leadingNulls(date.tm_min, 2),
    "%n": () => "\n",
    "%p": (date) => {
      if (date.tm_hour >= 0 && date.tm_hour < 12) {
        return "AM";
      }
      return "PM";
    },
    "%S": (date) => leadingNulls(date.tm_sec, 2),
    "%t": () => "\t",
    "%u": (date) => date.tm_wday || 7,
    "%U": (date) => {
      var days = date.tm_yday + 7 - date.tm_wday;
      return leadingNulls(Math.floor(days / 7), 2);
    },
    "%V": (date) => {
      var val = Math.floor((date.tm_yday + 7 - ((date.tm_wday + 6) % 7)) / 7);
      if ((date.tm_wday + 371 - date.tm_yday - 2) % 7 <= 2) {
        val++;
      }
      if (!val) {
        val = 52;
        var dec31 = (date.tm_wday + 7 - date.tm_yday - 1) % 7;
        if (
          dec31 == 4 ||
          (dec31 == 5 && isLeapYear((date.tm_year % 400) - 1))
        ) {
          val++;
        }
      } else if (val == 53) {
        var jan1 = (date.tm_wday + 371 - date.tm_yday) % 7;
        if (jan1 != 4 && (jan1 != 3 || !isLeapYear(date.tm_year))) val = 1;
      }
      return leadingNulls(val, 2);
    },
    "%w": (date) => date.tm_wday,
    "%W": (date) => {
      var days = date.tm_yday + 7 - ((date.tm_wday + 6) % 7);
      return leadingNulls(Math.floor(days / 7), 2);
    },
    "%y": (date) => (date.tm_year + 1900).toString().substring(2),
    "%Y": (date) => date.tm_year + 1900,
    "%z": (date) => {
      var off = date.tm_gmtoff;
      var ahead = off >= 0;
      off = Math.abs(off) / 60;
      off = (off / 60) * 100 + (off % 60);
      return (ahead ? "+" : "-") + String("0000" + off).slice(-4);
    },
    "%Z": (date) => date.tm_zone,
    "%%": () => "%",
  };
  pattern = pattern.replace(/%%/g, "\0\0");
  for (var rule in EXPANSION_RULES_2) {
    if (pattern.includes(rule)) {
      pattern = pattern.replace(
        new RegExp(rule, "g"),
        EXPANSION_RULES_2[rule](date)
      );
    }
  }
  pattern = pattern.replace(/\0\0/g, "%");
  var bytes = intArrayFromString(pattern, false);
  if (bytes.length > maxsize) {
    return 0;
  }
  writeArrayToMemory(bytes, s);
  return bytes.length - 1;
};
var _strftime_l = (s, maxsize, format, tm, loc) =>
  _strftime(s, maxsize, format, tm);
var _system = (command) => {
  if (ENVIRONMENT_IS_NODE) {
    if (!command) return 1;
    var cmdstr = UTF8ToString(command);
    if (!cmdstr.length) return 0;
    var cp = require("child_process");
    var ret = cp.spawnSync(cmdstr, [], { shell: true, stdio: "inherit" });
    var _W_EXITCODE = (ret, sig) => (ret << 8) | sig;
    if (ret.status === null) {
      var signalToNumber = (sig) => {
        switch (sig) {
          case "SIGHUP":
            return 1;
          case "SIGINT":
            return 2;
          case "SIGQUIT":
            return 3;
          case "SIGFPE":
            return 8;
          case "SIGKILL":
            return 9;
          case "SIGALRM":
            return 14;
          case "SIGTERM":
            return 15;
        }
        return 2;
      };
      return _W_EXITCODE(0, signalToNumber(ret.signal));
    }
    return _W_EXITCODE(ret.status, 0);
  }
  if (!command) return 0;
  setErrNo(52);
  return -1;
};
var FSNode = function (parent, name, mode, rdev) {
  if (!parent) {
    parent = this;
  }
  this.parent = parent;
  this.mount = parent.mount;
  this.mounted = null;
  this.id = FS.nextInode++;
  this.name = name;
  this.mode = mode;
  this.node_ops = {};
  this.stream_ops = {};
  this.rdev = rdev;
};
var readMode = 292 | 73;
var writeMode = 146;
Object.defineProperties(FSNode.prototype, {
  read: {
    get: function () {
      return (this.mode & readMode) === readMode;
    },
    set: function (val) {
      val ? (this.mode |= readMode) : (this.mode &= ~readMode);
    },
  },
  write: {
    get: function () {
      return (this.mode & writeMode) === writeMode;
    },
    set: function (val) {
      val ? (this.mode |= writeMode) : (this.mode &= ~writeMode);
    },
  },
  isFolder: {
    get: function () {
      return FS.isDir(this.mode);
    },
  },
  isDevice: {
    get: function () {
      return FS.isChrdev(this.mode);
    },
  },
});
FS.FSNode = FSNode;
FS.createPreloadedFile = FS_createPreloadedFile;
FS.staticInit();
ERRNO_CODES = {
  EPERM: 63,
  ENOENT: 44,
  ESRCH: 71,
  EINTR: 27,
  EIO: 29,
  ENXIO: 60,
  E2BIG: 1,
  ENOEXEC: 45,
  EBADF: 8,
  ECHILD: 12,
  EAGAIN: 6,
  EWOULDBLOCK: 6,
  ENOMEM: 48,
  EACCES: 2,
  EFAULT: 21,
  ENOTBLK: 105,
  EBUSY: 10,
  EEXIST: 20,
  EXDEV: 75,
  ENODEV: 43,
  ENOTDIR: 54,
  EISDIR: 31,
  EINVAL: 28,
  ENFILE: 41,
  EMFILE: 33,
  ENOTTY: 59,
  ETXTBSY: 74,
  EFBIG: 22,
  ENOSPC: 51,
  ESPIPE: 70,
  EROFS: 69,
  EMLINK: 34,
  EPIPE: 64,
  EDOM: 18,
  ERANGE: 68,
  ENOMSG: 49,
  EIDRM: 24,
  ECHRNG: 106,
  EL2NSYNC: 156,
  EL3HLT: 107,
  EL3RST: 108,
  ELNRNG: 109,
  EUNATCH: 110,
  ENOCSI: 111,
  EL2HLT: 112,
  EDEADLK: 16,
  ENOLCK: 46,
  EBADE: 113,
  EBADR: 114,
  EXFULL: 115,
  ENOANO: 104,
  EBADRQC: 103,
  EBADSLT: 102,
  EDEADLOCK: 16,
  EBFONT: 101,
  ENOSTR: 100,
  ENODATA: 116,
  ETIME: 117,
  ENOSR: 118,
  ENONET: 119,
  ENOPKG: 120,
  EREMOTE: 121,
  ENOLINK: 47,
  EADV: 122,
  ESRMNT: 123,
  ECOMM: 124,
  EPROTO: 65,
  EMULTIHOP: 36,
  EDOTDOT: 125,
  EBADMSG: 9,
  ENOTUNIQ: 126,
  EBADFD: 127,
  EREMCHG: 128,
  ELIBACC: 129,
  ELIBBAD: 130,
  ELIBSCN: 131,
  ELIBMAX: 132,
  ELIBEXEC: 133,
  ENOSYS: 52,
  ENOTEMPTY: 55,
  ENAMETOOLONG: 37,
  ELOOP: 32,
  EOPNOTSUPP: 138,
  EPFNOSUPPORT: 139,
  ECONNRESET: 15,
  ENOBUFS: 42,
  EAFNOSUPPORT: 5,
  EPROTOTYPE: 67,
  ENOTSOCK: 57,
  ENOPROTOOPT: 50,
  ESHUTDOWN: 140,
  ECONNREFUSED: 14,
  EADDRINUSE: 3,
  ECONNABORTED: 13,
  ENETUNREACH: 40,
  ENETDOWN: 38,
  ETIMEDOUT: 73,
  EHOSTDOWN: 142,
  EHOSTUNREACH: 23,
  EINPROGRESS: 26,
  EALREADY: 7,
  EDESTADDRREQ: 17,
  EMSGSIZE: 35,
  EPROTONOSUPPORT: 66,
  ESOCKTNOSUPPORT: 137,
  EADDRNOTAVAIL: 4,
  ENETRESET: 39,
  EISCONN: 30,
  ENOTCONN: 53,
  ETOOMANYREFS: 141,
  EUSERS: 136,
  EDQUOT: 19,
  ESTALE: 72,
  ENOTSUP: 138,
  ENOMEDIUM: 148,
  EILSEQ: 25,
  EOVERFLOW: 61,
  ECANCELED: 11,
  ENOTRECOVERABLE: 56,
  EOWNERDEAD: 62,
  ESTRPIPE: 135,
};
embind_init_charCodes();
BindingError = Module["BindingError"] = class BindingError extends Error {
  constructor(message) {
    super(message);
    this.name = "BindingError";
  }
};
InternalError = Module["InternalError"] = class InternalError extends Error {
  constructor(message) {
    super(message);
    this.name = "InternalError";
  }
};
init_ClassHandle();
init_embind();
init_RegisteredPointer();
UnboundTypeError = Module["UnboundTypeError"] = extendError(
  Error,
  "UnboundTypeError"
);
handleAllocatorInit();
init_emval();
var GLctx;
var tempFixedLengthArray = [];
for (var i = 0; i < 32; ++i) tempFixedLengthArray.push(new Array(i));
function checkIncomingModuleAPI() {
  ignoredModuleProp("fetchSettings");
}

var wasmImports = {
  NotifyEngineRunningState: _NotifyEngineRunningState,
  GetDownloadContentLength: _GetDownloadContentLength,
  GetDownloadContentType: _GetDownloadContentType,
  GetDownloadStatus: _GetDownloadStatus,
  GetPostResult: _GetPostResult,
  ProbePictureInfo: _ProbePictureInfo,
  ProbeVideoInfo: _ProbeVideoInfo,
  ProbeAudioInfo: _ProbeAudioInfo,
  RequestDownload: _RequestDownload,
  RequestPost: _RequestPost,
  __assert_fail: ___assert_fail,
  __cxa_begin_catch: ___cxa_begin_catch,
  __cxa_end_catch: ___cxa_end_catch,
  __cxa_find_matching_catch_2: ___cxa_find_matching_catch_2,
  __cxa_find_matching_catch_3: ___cxa_find_matching_catch_3,
  __cxa_rethrow: ___cxa_rethrow,
  __cxa_rethrow_primary_exception: ___cxa_rethrow_primary_exception,
  __cxa_throw: ___cxa_throw,
  __cxa_uncaught_exceptions: ___cxa_uncaught_exceptions,
  __resumeException: ___resumeException,
  __syscall_chmod: ___syscall_chmod,
  __syscall_dup3: ___syscall_dup3,
  __syscall_faccessat: ___syscall_faccessat,
  __syscall_fcntl64: ___syscall_fcntl64,
  __syscall_fstat64: ___syscall_fstat64,
  __syscall_getcwd: ___syscall_getcwd,
  __syscall_getdents64: ___syscall_getdents64,
  __syscall_ioctl: ___syscall_ioctl,
  __syscall_lstat64: ___syscall_lstat64,
  __syscall_mkdirat: ___syscall_mkdirat,
  __syscall_newfstatat: ___syscall_newfstatat,
  __syscall_openat: ___syscall_openat,
  __syscall_readlinkat: ___syscall_readlinkat,
  __syscall_renameat: ___syscall_renameat,
  __syscall_rmdir: ___syscall_rmdir,
  __syscall_stat64: ___syscall_stat64,
  __syscall_unlinkat: ___syscall_unlinkat,
  _embind_register_bigint: __embind_register_bigint,
  _embind_register_bool: __embind_register_bool,
  _embind_register_class: __embind_register_class,
  _embind_register_class_constructor: __embind_register_class_constructor,
  _embind_register_class_function: __embind_register_class_function,
  _embind_register_emval: __embind_register_emval,
  _embind_register_float: __embind_register_float,
  _embind_register_function: __embind_register_function,
  _embind_register_integer: __embind_register_integer,
  _embind_register_memory_view: __embind_register_memory_view,
  _embind_register_std_string: __embind_register_std_string,
  _embind_register_std_wstring: __embind_register_std_wstring,
  _embind_register_void: __embind_register_void,
  _emscripten_get_now_is_monotonic: __emscripten_get_now_is_monotonic,
  _emscripten_throw_longjmp: __emscripten_throw_longjmp,
  _emval_decref: __emval_decref,
  _emval_incref: __emval_incref,
  _emval_take_value: __emval_take_value,
  _gmtime_js: __gmtime_js,
  _localtime_js: __localtime_js,
  _mktime_js: __mktime_js,
  _mmap_js: __mmap_js,
  _munmap_js: __munmap_js,
  _tzset_js: __tzset_js,
  abort: _abort,
  emscripten_date_now: _emscripten_date_now,
  emscripten_get_canvas_element_size: _emscripten_get_canvas_element_size,
  emscripten_get_element_css_size: _emscripten_get_element_css_size,
  emscripten_get_now: _emscripten_get_now,
  emscripten_memcpy_js: _emscripten_memcpy_js,
  emscripten_resize_heap: _emscripten_resize_heap,
  emscripten_webgl_create_context: _emscripten_webgl_create_context,
  emscripten_webgl_destroy_context: _emscripten_webgl_destroy_context,
  emscripten_webgl_get_current_context: _emscripten_webgl_get_current_context,
  emscripten_webgl_init_context_attributes:
    _emscripten_webgl_init_context_attributes,
  emscripten_webgl_make_context_current: _emscripten_webgl_make_context_current,
  environ_get: _environ_get,
  environ_sizes_get: _environ_sizes_get,
  exit: _exit,
  fd_close: _fd_close,
  fd_pread: _fd_pread,
  fd_read: _fd_read,
  fd_seek: _fd_seek,
  fd_write: _fd_write,
  glActiveTexture: _glActiveTexture,
  glAttachShader: _glAttachShader,
  glBeginQuery: _glBeginQuery,
  glBindBuffer: _glBindBuffer,
  glBindBufferRange: _glBindBufferRange,
  glBindFramebuffer: _glBindFramebuffer,
  glBindRenderbuffer: _glBindRenderbuffer,
  glBindSampler: _glBindSampler,
  glBindTexture: _glBindTexture,
  glBindVertexArray: _glBindVertexArray,
  glBlendColor: _glBlendColor,
  glBlendEquationSeparate: _glBlendEquationSeparate,
  glBlendFuncSeparate: _glBlendFuncSeparate,
  glBlitFramebuffer: _glBlitFramebuffer,
  glBufferData: _glBufferData,
  glBufferSubData: _glBufferSubData,
  glCheckFramebufferStatus: _glCheckFramebufferStatus,
  glClear: _glClear,
  glClearBufferfv: _glClearBufferfv,
  glClearDepthf: _glClearDepthf,
  glClearStencil: _glClearStencil,
  glClientWaitSync: _glClientWaitSync,
  glColorMask: _glColorMask,
  glCompileShader: _glCompileShader,
  glCompressedTexSubImage2D: _glCompressedTexSubImage2D,
  glCompressedTexSubImage3D: _glCompressedTexSubImage3D,
  glCopyBufferSubData: _glCopyBufferSubData,
  glCreateProgram: _glCreateProgram,
  glCreateShader: _glCreateShader,
  glCullFace: _glCullFace,
  glDeleteBuffers: _glDeleteBuffers,
  glDeleteFramebuffers: _glDeleteFramebuffers,
  glDeleteProgram: _glDeleteProgram,
  glDeleteQueries: _glDeleteQueries,
  glDeleteRenderbuffers: _glDeleteRenderbuffers,
  glDeleteSamplers: _glDeleteSamplers,
  glDeleteShader: _glDeleteShader,
  glDeleteSync: _glDeleteSync,
  glDeleteTextures: _glDeleteTextures,
  glDeleteVertexArrays: _glDeleteVertexArrays,
  glDepthFunc: _glDepthFunc,
  glDepthMask: _glDepthMask,
  glDepthRangef: _glDepthRangef,
  glDetachShader: _glDetachShader,
  glDisable: _glDisable,
  glDrawArrays: _glDrawArrays,
  glDrawArraysInstanced: _glDrawArraysInstanced,
  glDrawBuffers: _glDrawBuffers,
  glDrawElements: _glDrawElements,
  glDrawElementsInstanced: _glDrawElementsInstanced,
  glEnable: _glEnable,
  glEnableVertexAttribArray: _glEnableVertexAttribArray,
  glEndQuery: _glEndQuery,
  glFenceSync: _glFenceSync,
  glFinish: _glFinish,
  glFlush: _glFlush,
  glFramebufferRenderbuffer: _glFramebufferRenderbuffer,
  glFramebufferTexture2D: _glFramebufferTexture2D,
  glFramebufferTextureLayer: _glFramebufferTextureLayer,
  glFrontFace: _glFrontFace,
  glGenBuffers: _glGenBuffers,
  glGenFramebuffers: _glGenFramebuffers,
  glGenQueries: _glGenQueries,
  glGenRenderbuffers: _glGenRenderbuffers,
  glGenSamplers: _glGenSamplers,
  glGenTextures: _glGenTextures,
  glGenVertexArrays: _glGenVertexArrays,
  glGenerateMipmap: _glGenerateMipmap,
  glGetActiveUniform: _glGetActiveUniform,
  glGetActiveUniformBlockName: _glGetActiveUniformBlockName,
  glGetBufferParameteriv: _glGetBufferParameteriv,
  glGetError: _glGetError,
  glGetIntegerv: _glGetIntegerv,
  glGetProgramInfoLog: _glGetProgramInfoLog,
  glGetProgramiv: _glGetProgramiv,
  glGetQueryObjectuiv: _glGetQueryObjectuiv,
  glGetShaderInfoLog: _glGetShaderInfoLog,
  glGetShaderiv: _glGetShaderiv,
  glGetString: _glGetString,
  glGetStringi: _glGetStringi,
  glGetTexParameteriv: _glGetTexParameteriv,
  glGetUniformBlockIndex: _glGetUniformBlockIndex,
  glGetUniformLocation: _glGetUniformLocation,
  glInvalidateFramebuffer: _glInvalidateFramebuffer,
  glLinkProgram: _glLinkProgram,
  glMapBufferRange: _glMapBufferRange,
  glPixelStorei: _glPixelStorei,
  glPolygonOffset: _glPolygonOffset,
  glProgramParameteri: _glProgramParameteri,
  glReadPixels: _glReadPixels,
  glRenderbufferStorageMultisample: _glRenderbufferStorageMultisample,
  glSamplerParameterf: _glSamplerParameterf,
  glSamplerParameterfv: _glSamplerParameterfv,
  glSamplerParameteri: _glSamplerParameteri,
  glScissor: _glScissor,
  glShaderSource: _glShaderSource,
  glStencilFuncSeparate: _glStencilFuncSeparate,
  glStencilMask: _glStencilMask,
  glStencilOpSeparate: _glStencilOpSeparate,
  glTexParameteri: _glTexParameteri,
  glTexStorage2D: _glTexStorage2D,
  glTexStorage3D: _glTexStorage3D,
  glTexSubImage2D: _glTexSubImage2D,
  glTexSubImage3D: _glTexSubImage3D,
  glUniform1i: _glUniform1i,
  glUniformBlockBinding: _glUniformBlockBinding,
  glUnmapBuffer: _glUnmapBuffer,
  glUseProgram: _glUseProgram,
  glVertexAttribDivisor: _glVertexAttribDivisor,
  glVertexAttribIPointer: _glVertexAttribIPointer,
  glVertexAttribPointer: _glVertexAttribPointer,
  glViewport: _glViewport,
  glWaitSync: _glWaitSync,
  invoke_di: invoke_di,
  invoke_did: invoke_did,
  invoke_dii: invoke_dii,
  invoke_diii: invoke_diii,
  invoke_fi: invoke_fi,
  invoke_fii: invoke_fii,
  invoke_fiifii: invoke_fiifii,
  invoke_fiii: invoke_fiii,
  invoke_fiiiif: invoke_fiiiif,
  invoke_fij: invoke_fij,
  invoke_i: invoke_i,
  invoke_idiii: invoke_idiii,
  invoke_ii: invoke_ii,
  invoke_iid: invoke_iid,
  invoke_iif: invoke_iif,
  invoke_iii: invoke_iii,
  invoke_iiii: invoke_iiii,
  invoke_iiiii: invoke_iiiii,
  invoke_iiiiii: invoke_iiiiii,
  invoke_iiiiiii: invoke_iiiiiii,
  invoke_iiiiiiii: invoke_iiiiiiii,
  invoke_iiiiiiiii: invoke_iiiiiiiii,
  invoke_iiiiiiiiiii: invoke_iiiiiiiiiii,
  invoke_iiiiiiiiiiii: invoke_iiiiiiiiiiii,
  invoke_iiiiiiiiiiiii: invoke_iiiiiiiiiiiii,
  invoke_iiiiij: invoke_iiiiij,
  invoke_iiij: invoke_iiij,
  invoke_iij: invoke_iij,
  invoke_iiji: invoke_iiji,
  invoke_iijii: invoke_iijii,
  invoke_iijiii: invoke_iijiii,
  invoke_iijjiii: invoke_iijjiii,
  invoke_ijjiii: invoke_ijjiii,
  invoke_j: invoke_j,
  invoke_ji: invoke_ji,
  invoke_jii: invoke_jii,
  invoke_jiii: invoke_jiii,
  invoke_jiiii: invoke_jiiii,
  invoke_jiij: invoke_jiij,
  invoke_jij: invoke_jij,
  invoke_v: invoke_v,
  invoke_vi: invoke_vi,
  invoke_vid: invoke_vid,
  invoke_vif: invoke_vif,
  invoke_viff: invoke_viff,
  invoke_vifff: invoke_vifff,
  invoke_viffff: invoke_viffff,
  invoke_viffffff: invoke_viffffff,
  invoke_vifi: invoke_vifi,
  invoke_vifji: invoke_vifji,
  invoke_vii: invoke_vii,
  invoke_viid: invoke_viid,
  invoke_viif: invoke_viif,
  invoke_viii: invoke_viii,
  invoke_viiif: invoke_viiif,
  invoke_viiii: invoke_viiii,
  invoke_viiiii: invoke_viiiii,
  invoke_viiiiii: invoke_viiiiii,
  invoke_viiiiiii: invoke_viiiiiii,
  invoke_viiiiiiii: invoke_viiiiiiii,
  invoke_viiiiiiiiii: invoke_viiiiiiiiii,
  invoke_viiiiiiiiiii: invoke_viiiiiiiiiii,
  invoke_viiiiiiiiiiiiiii: invoke_viiiiiiiiiiiiiii,
  invoke_viiij: invoke_viiij,
  invoke_viij: invoke_viij,
  invoke_viiji: invoke_viiji,
  invoke_viijii: invoke_viijii,
  invoke_viijjii: invoke_viijjii,
  invoke_vij: invoke_vij,
  invoke_viji: invoke_viji,
  invoke_iiiiid: invoke_iiiiid,
  __call_sighandler: ___call_sighandler,
  llvm_eh_typeid_for: _llvm_eh_typeid_for,
  strftime: _strftime,
  strftime_l: _strftime_l,
  system: _system,
};

var wasmExports;
var ___wasm_call_ctors;
var _Initialize;
var _AddFrameDatas;
var _Render;
var _Destroy;
var _Seek;
var _Pause;
var _malloc;
var ___cxa_free_exception;
var _free;
var ___errno_location;
var _fflush;
var setTempRet0;
var ___getTypeName;
var __embind_initialize_bindings;
var _emscripten_builtin_memalign;
var _setThrew;
var _emscripten_stack_init;
var _emscripten_stack_get_free;
var _emscripten_stack_get_base;
var _emscripten_stack_get_end;
var stackSave;
var stackRestore;
var stackAlloc;
var _emscripten_stack_get_current;
var ___cxa_decrement_exception_refcount;
var ___cxa_increment_exception_refcount;
var ___get_exception_message;
var ___cxa_can_catch;
var ___cxa_is_pointer_type;
var dynCall_vi;
var dynCall_iii;
var dynCall_iiii;
var dynCall_viii;
var dynCall_vii;
var dynCall_ii;
var dynCall_i;
var dynCall_vifji;
var dynCall_iiiii;
var dynCall_v;
var dynCall_ji;
var dynCall_vij;
var dynCall_viiii;
var dynCall_iij;
var dynCall_di;
var dynCall_iid;
var dynCall_viif;
var dynCall_fi;
var dynCall_vid;
var dynCall_iiiiii;
var dynCall_viij;
var dynCall_viid;
var dynCall_iiiiiii;
var dynCall_jiii;
var dynCall_iiij;
var dynCall_diii;
var dynCall_fii;
var dynCall_viji;
var dynCall_viffff;
var dynCall_viff;
var dynCall_viffffff;
var dynCall_vif;
var dynCall_viiji;
var dynCall_vifff;
var dynCall_fiii;
var dynCall_dii;
var dynCall_jii;
var dynCall_iif;
var dynCall_viiiii;
var dynCall_fiifii;
var dynCall_did;
var dynCall_jij;
var dynCall_viiiiiif;
var dynCall_viiiiffii;
var dynCall_viiiifiii;
var dynCall_iiiiiiii;
var dynCall_viiif;
var dynCall_iiji;
var dynCall_viiiiiii;
var dynCall_viiiiiiii;
var dynCall_iiiiiiiii;
var dynCall_fij;
var dynCall_vifi;
var dynCall_fiiiif;
var dynCall_viiiiii;
var dynCall_ijjiii;
var dynCall_iijiii;
var dynCall_iijjiii;
var dynCall_idiii;
var dynCall_viiij;
var dynCall_iijii;
var dynCall_jiij;
var dynCall_vijj;
var dynCall_viiifii;
var dynCall_viijjii;
var dynCall_viijiijji;
var dynCall_iiiiiiiiii;
var dynCall_viiiiiiiiiii;
var dynCall_jiiji;
var dynCall_jj;
var dynCall_jiiiji;
var dynCall_iiiji;
var dynCall_jiji;
var dynCall_iidiiii;
var dynCall_j;
var dynCall_viijii;
var dynCall_iiiiij;
var dynCall_iiiiiiiiiii;
var dynCall_jiiii;
var dynCall_iiiiiiiiiiiii;
var dynCall_iiiiiiiiiiii;
var dynCall_viiiiiiiiii;
var dynCall_viiiiiiiiiiiiiii;
var dynCall_iiiiid;
var dynCall_iiiiijj;
var dynCall_iiiiiijj;
var _asyncify_start_unwind;
var _asyncify_stop_unwind;
var _asyncify_start_rewind;
var _asyncify_stop_rewind;
function invoke_vi(index, a1) {
  var sp = stackSave();
  try {
    dynCall_vi(index, a1);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_iii(index, a1, a2) {
  var sp = stackSave();
  try {
    return dynCall_iii(index, a1, a2);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_iiii(index, a1, a2, a3) {
  var sp = stackSave();
  try {
    return dynCall_iiii(index, a1, a2, a3);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_viii(index, a1, a2, a3) {
  var sp = stackSave();
  try {
    dynCall_viii(index, a1, a2, a3);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_vii(index, a1, a2) {
  var sp = stackSave();
  try {
    dynCall_vii(index, a1, a2);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_ii(index, a1) {
  var sp = stackSave();
  try {
    return dynCall_ii(index, a1);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_i(index) {
  var sp = stackSave();
  try {
    return dynCall_i(index);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_viiii(index, a1, a2, a3, a4) {
  var sp = stackSave();
  try {
    dynCall_viiii(index, a1, a2, a3, a4);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_iiiii(index, a1, a2, a3, a4) {
  var sp = stackSave();
  try {
    return dynCall_iiiii(index, a1, a2, a3, a4);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_v(index) {
  var sp = stackSave();
  try {
    dynCall_v(index);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_di(index, a1) {
  var sp = stackSave();
  try {
    return dynCall_di(index, a1);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_iid(index, a1, a2) {
  var sp = stackSave();
  try {
    return dynCall_iid(index, a1, a2);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_viif(index, a1, a2, a3) {
  var sp = stackSave();
  try {
    dynCall_viif(index, a1, a2, a3);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_fi(index, a1) {
  var sp = stackSave();
  try {
    return dynCall_fi(index, a1);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_vid(index, a1, a2) {
  var sp = stackSave();
  try {
    dynCall_vid(index, a1, a2);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_iiiiii(index, a1, a2, a3, a4, a5) {
  var sp = stackSave();
  try {
    return dynCall_iiiiii(index, a1, a2, a3, a4, a5);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_viid(index, a1, a2, a3) {
  var sp = stackSave();
  try {
    dynCall_viid(index, a1, a2, a3);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_diii(index, a1, a2, a3) {
  var sp = stackSave();
  try {
    return dynCall_diii(index, a1, a2, a3);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_iiiiiii(index, a1, a2, a3, a4, a5, a6) {
  var sp = stackSave();
  try {
    return dynCall_iiiiiii(index, a1, a2, a3, a4, a5, a6);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_dii(index, a1, a2) {
  var sp = stackSave();
  try {
    return dynCall_dii(index, a1, a2);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_fii(index, a1, a2) {
  var sp = stackSave();
  try {
    return dynCall_fii(index, a1, a2);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_viffff(index, a1, a2, a3, a4, a5) {
  var sp = stackSave();
  try {
    dynCall_viffff(index, a1, a2, a3, a4, a5);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_viff(index, a1, a2, a3) {
  var sp = stackSave();
  try {
    dynCall_viff(index, a1, a2, a3);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_viffffff(index, a1, a2, a3, a4, a5, a6, a7) {
  var sp = stackSave();
  try {
    dynCall_viffffff(index, a1, a2, a3, a4, a5, a6, a7);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_vif(index, a1, a2) {
  var sp = stackSave();
  try {
    dynCall_vif(index, a1, a2);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_fiii(index, a1, a2, a3) {
  var sp = stackSave();
  try {
    return dynCall_fiii(index, a1, a2, a3);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_viiiiiii(index, a1, a2, a3, a4, a5, a6, a7) {
  var sp = stackSave();
  try {
    dynCall_viiiiiii(index, a1, a2, a3, a4, a5, a6, a7);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_viiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8) {
  var sp = stackSave();
  try {
    dynCall_viiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_viiiiii(index, a1, a2, a3, a4, a5, a6) {
  var sp = stackSave();
  try {
    dynCall_viiiiii(index, a1, a2, a3, a4, a5, a6);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_viiiii(index, a1, a2, a3, a4, a5) {
  var sp = stackSave();
  try {
    dynCall_viiiii(index, a1, a2, a3, a4, a5);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_fiifii(index, a1, a2, a3, a4, a5) {
  var sp = stackSave();
  try {
    return dynCall_fiifii(index, a1, a2, a3, a4, a5);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_vifff(index, a1, a2, a3, a4) {
  var sp = stackSave();
  try {
    dynCall_vifff(index, a1, a2, a3, a4);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_iif(index, a1, a2) {
  var sp = stackSave();
  try {
    return dynCall_iif(index, a1, a2);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_did(index, a1, a2) {
  var sp = stackSave();
  try {
    return dynCall_did(index, a1, a2);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_viiif(index, a1, a2, a3, a4) {
  var sp = stackSave();
  try {
    dynCall_viiif(index, a1, a2, a3, a4);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_iiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8) {
  var sp = stackSave();
  try {
    return dynCall_iiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_vifi(index, a1, a2, a3) {
  var sp = stackSave();
  try {
    dynCall_vifi(index, a1, a2, a3);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_fiiiif(index, a1, a2, a3, a4, a5) {
  var sp = stackSave();
  try {
    return dynCall_fiiiif(index, a1, a2, a3, a4, a5);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_idiii(index, a1, a2, a3, a4) {
  var sp = stackSave();
  try {
    return dynCall_idiii(index, a1, a2, a3, a4);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_viiiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {
  var sp = stackSave();
  try {
    dynCall_viiiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_viiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) {
  var sp = stackSave();
  try {
    dynCall_viiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11);
  } catch(e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_iiiiiiii(index, a1, a2, a3, a4, a5, a6, a7) {
  var sp = stackSave();
  try {
    return dynCall_iiiiiiii(index, a1, a2, a3, a4, a5, a6, a7);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_iiiiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {
  var sp = stackSave();
  try {
    return dynCall_iiiiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_iiiiiiiiiiiii(
  index,
  a1,
  a2,
  a3,
  a4,
  a5,
  a6,
  a7,
  a8,
  a9,
  a10,
  a11,
  a12
) {
  var sp = stackSave();
  try {
    return dynCall_iiiiiiiiiiiii(
      index,
      a1,
      a2,
      a3,
      a4,
      a5,
      a6,
      a7,
      a8,
      a9,
      a10,
      a11,
      a12
    );
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_iiiiiiiiiiii(
  index,
  a1,
  a2,
  a3,
  a4,
  a5,
  a6,
  a7,
  a8,
  a9,
  a10,
  a11
) {
  var sp = stackSave();
  try {
    return dynCall_iiiiiiiiiiii(
      index,
      a1,
      a2,
      a3,
      a4,
      a5,
      a6,
      a7,
      a8,
      a9,
      a10,
      a11
    );
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_viiiiiiiiiiiiiii(
  index,
  a1,
  a2,
  a3,
  a4,
  a5,
  a6,
  a7,
  a8,
  a9,
  a10,
  a11,
  a12,
  a13,
  a14,
  a15
) {
  var sp = stackSave();
  try {
    dynCall_viiiiiiiiiiiiiii(
      index,
      a1,
      a2,
      a3,
      a4,
      a5,
      a6,
      a7,
      a8,
      a9,
      a10,
      a11,
      a12,
      a13,
      a14,
      a15
    );
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_vifji(index, a1, a2, a3, a4, a5) {
  var sp = stackSave();
  try {
    dynCall_vifji(index, a1, a2, a3, a4, a5);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_ji(index, a1) {
  var sp = stackSave();
  try {
    return dynCall_ji(index, a1);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_vij(index, a1, a2, a3) {
  var sp = stackSave();
  try {
    dynCall_vij(index, a1, a2, a3);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_iij(index, a1, a2, a3) {
  var sp = stackSave();
  try {
    return dynCall_iij(index, a1, a2, a3);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_viij(index, a1, a2, a3, a4) {
  var sp = stackSave();
  try {
    dynCall_viij(index, a1, a2, a3, a4);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_jiii(index, a1, a2, a3) {
  var sp = stackSave();
  try {
    return dynCall_jiii(index, a1, a2, a3);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_iiij(index, a1, a2, a3, a4) {
  var sp = stackSave();
  try {
    return dynCall_iiij(index, a1, a2, a3, a4);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_jii(index, a1, a2) {
  var sp = stackSave();
  try {
    return dynCall_jii(index, a1, a2);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_viiji(index, a1, a2, a3, a4, a5) {
  var sp = stackSave();
  try {
    dynCall_viiji(index, a1, a2, a3, a4, a5);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_viji(index, a1, a2, a3, a4) {
  var sp = stackSave();
  try {
    dynCall_viji(index, a1, a2, a3, a4);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_fij(index, a1, a2, a3) {
  var sp = stackSave();
  try {
    return dynCall_fij(index, a1, a2, a3);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_jij(index, a1, a2, a3) {
  var sp = stackSave();
  try {
    return dynCall_jij(index, a1, a2, a3);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_viijjii(index, a1, a2, a3, a4, a5, a6, a7, a8) {
  var sp = stackSave();
  try {
    dynCall_viijjii(index, a1, a2, a3, a4, a5, a6, a7, a8);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_iiji(index, a1, a2, a3, a4) {
  var sp = stackSave();
  try {
    return dynCall_iiji(index, a1, a2, a3, a4);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_iijiii(index, a1, a2, a3, a4, a5, a6) {
  var sp = stackSave();
  try {
    return dynCall_iijiii(index, a1, a2, a3, a4, a5, a6);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_ijjiii(index, a1, a2, a3, a4, a5, a6, a7) {
  var sp = stackSave();
  try {
    return dynCall_ijjiii(index, a1, a2, a3, a4, a5, a6, a7);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_iijjiii(index, a1, a2, a3, a4, a5, a6, a7, a8) {
  var sp = stackSave();
  try {
    return dynCall_iijjiii(index, a1, a2, a3, a4, a5, a6, a7, a8);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_viiij(index, a1, a2, a3, a4, a5) {
  var sp = stackSave();
  try {
    dynCall_viiij(index, a1, a2, a3, a4, a5);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_iiiiij(index, a1, a2, a3, a4, a5, a6) {
  var sp = stackSave();
  try {
    return dynCall_iiiiij(index, a1, a2, a3, a4, a5, a6);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_iijii(index, a1, a2, a3, a4, a5) {
  var sp = stackSave();
  try {
    return dynCall_iijii(index, a1, a2, a3, a4, a5);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_jiij(index, a1, a2, a3, a4) {
  var sp = stackSave();
  try {
    return dynCall_jiij(index, a1, a2, a3, a4);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_jiiii(index, a1, a2, a3, a4) {
  var sp = stackSave();
  try {
    return dynCall_jiiii(index, a1, a2, a3, a4);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_j(index) {
  var sp = stackSave();
  try {
    return dynCall_j(index);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}
function invoke_viijii(index, a1, a2, a3, a4, a5, a6) {
  var sp = stackSave();
  try {
    dynCall_viijii(index, a1, a2, a3, a4, a5, a6);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}

function invoke_iiiiid(index, a1, a2, a3, a4, a5) {
  var sp = stackSave();
  try {
    return dynCall_iiiiid(index, a1, a2, a3, a4, a5);
  } catch (e) {
    stackRestore(sp);
    if (!(e instanceof EmscriptenEH)) throw e;
    _setThrew(1, 0);
  }
}

function ___call_sighandler(fp, sig) {
  return (function (a1) {
    return dynCall_vi(fp, a1);
  })(sig);
}

var missingLibrarySymbols = [
  "writeI53ToI64Clamped",
  "writeI53ToI64Signaling",
  "writeI53ToU64Clamped",
  "writeI53ToU64Signaling",
  "convertU32PairToI53",
  "inetPton4",
  "inetNtop4",
  "inetPton6",
  "inetNtop6",
  "readSockaddr",
  "writeSockaddr",
  "getHostByName",
  "getCallstack",
  "emscriptenLog",
  "convertPCtoSourceLocation",
  "readEmAsmArgs",
  "jstoi_s",
  "listenOnce",
  "autoResumeAudioContext",
  "safeSetTimeout",
  "asmjsMangle",
  "getNativeTypeSize",
  "STACK_SIZE",
  "STACK_ALIGN",
  "POINTER_SIZE",
  "ASSERTIONS",
  "getCFunc",
  "ccall",
  "cwrap",
  "uleb128Encode",
  "generateFuncType",
  "convertJsFunctionToWasm",
  "getEmptyTableSlot",
  "updateTableMap",
  "getFunctionAddress",
  "addFunction",
  "removeFunction",
  "reallyNegative",
  "unSign",
  "strLen",
  "reSign",
  "formatString",
  "intArrayToString",
  "AsciiToString",
  "stringToUTF8OnStack",
  "registerKeyEventCallback",
  "fillMouseEventData",
  "registerMouseEventCallback",
  "registerWheelEventCallback",
  "registerUiEventCallback",
  "registerFocusEventCallback",
  "fillDeviceOrientationEventData",
  "registerDeviceOrientationEventCallback",
  "fillDeviceMotionEventData",
  "registerDeviceMotionEventCallback",
  "screenOrientation",
  "fillOrientationChangeEventData",
  "registerOrientationChangeEventCallback",
  "fillFullscreenChangeEventData",
  "registerFullscreenChangeEventCallback",
  "JSEvents_requestFullscreen",
  "JSEvents_resizeCanvasForFullscreen",
  "registerRestoreOldStyle",
  "hideEverythingExceptGivenElement",
  "restoreHiddenElements",
  "setLetterbox",
  "softFullscreenResizeWebGLRenderTarget",
  "doRequestFullscreen",
  "fillPointerlockChangeEventData",
  "registerPointerlockChangeEventCallback",
  "registerPointerlockErrorEventCallback",
  "requestPointerLock",
  "fillVisibilityChangeEventData",
  "registerVisibilityChangeEventCallback",
  "registerTouchEventCallback",
  "fillGamepadEventData",
  "registerGamepadEventCallback",
  "registerBeforeUnloadEventCallback",
  "fillBatteryEventData",
  "battery",
  "registerBatteryEventCallback",
  "setCanvasElementSize",
  "getCanvasElementSize",
  "jsStackTrace",
  "stackTrace",
  "checkWasiClock",
  "wasiRightsToMuslOFlags",
  "wasiOFlagsToMuslOFlags",
  "createDyncallWrapper",
  "setImmediateWrapped",
  "clearImmediateWrapped",
  "polyfillSetImmediate",
  "getPromise",
  "makePromise",
  "idsToPromises",
  "makePromiseCallback",
  "setMainLoop",
  "getSocketFromFD",
  "getSocketAddress",
  "FS_unlink",
  "FS_mkdirTree",
  "_setNetworkCallback",
  "emscriptenWebGLGetUniform",
  "emscriptenWebGLGetVertexAttrib",
  "writeGLArray",
  "registerWebGlEventCallback",
  "SDL_unicode",
  "SDL_ttfContext",
  "SDL_audio",
  "emscriptenWebGLGetIndexed",
  "ALLOC_NORMAL",
  "ALLOC_STACK",
  "allocate",
  "writeStringToMemory",
  "writeAsciiToMemory",
  "registerInheritedInstance",
  "unregisterInheritedInstance",
  "enumReadValueFromPointer",
  "validateThis",
  "getStringOrSymbol",
  "craftEmvalAllocator",
  "emval_get_global",
  "emval_lookupTypes",
  "emval_allocateDestructors",
  "emval_addMethodCaller",
];
missingLibrarySymbols.forEach(missingLibrarySymbol);
var unexportedSymbols = [
  "run",
  "addOnPreRun",
  "addOnInit",
  "addOnPreMain",
  "addOnExit",
  "addOnPostRun",
  "addRunDependency",
  "removeRunDependency",
  "FS_createFolder",
  "FS_createPath",
  "FS_createLazyFile",
  "FS_createLink",
  "FS_createDevice",
  "FS_readFile",
  "out",
  "err",
  "callMain",
  "abort",
  "keepRuntimeAlive",
  "wasmMemory",
  "wasmExports",
  "stackAlloc",
  "stackSave",
  "stackRestore",
  "getTempRet0",
  "setTempRet0",
  "writeStackCookie",
  "checkStackCookie",
  "writeI53ToI64",
  "readI53FromI64",
  "readI53FromU64",
  "convertI32PairToI53",
  "convertI32PairToI53Checked",
  "ptrToString",
  "zeroMemory",
  "exitJS",
  "getHeapMax",
  "growMemory",
  "ENV",
  "MONTH_DAYS_REGULAR",
  "MONTH_DAYS_LEAP",
  "MONTH_DAYS_REGULAR_CUMULATIVE",
  "MONTH_DAYS_LEAP_CUMULATIVE",
  "isLeapYear",
  "ydayFromDate",
  "arraySum",
  "addDays",
  "ERRNO_CODES",
  "ERRNO_MESSAGES",
  "setErrNo",
  "DNS",
  "Protocols",
  "Sockets",
  "initRandomFill",
  "randomFill",
  "timers",
  "warnOnce",
  "UNWIND_CACHE",
  "readEmAsmArgsArray",
  "jstoi_q",
  "getExecutableName",
  "dynCallLegacy",
  "getDynCaller",
  "dynCall",
  "handleException",
  "runtimeKeepalivePush",
  "runtimeKeepalivePop",
  "callUserCallback",
  "maybeExit",
  "asyncLoad",
  "alignMemory",
  "mmapAlloc",
  "handleAllocatorInit",
  "HandleAllocator",
  "wasmTable",
  "sigToWasmTypes",
  "freeTableIndexes",
  "functionsInTableMap",
  "setValue",
  "getValue",
  "PATH",
  "PATH_FS",
  "UTF8Decoder",
  "UTF8ArrayToString",
  "UTF8ToString",
  "stringToUTF8Array",
  "stringToUTF8",
  "lengthBytesUTF8",
  "intArrayFromString",
  "stringToAscii",
  "UTF16Decoder",
  "UTF16ToString",
  "stringToUTF16",
  "lengthBytesUTF16",
  "UTF32ToString",
  "stringToUTF32",
  "lengthBytesUTF32",
  "stringToNewUTF8",
  "writeArrayToMemory",
  "JSEvents",
  "specialHTMLTargets",
  "maybeCStringToJsString",
  "findEventTarget",
  "findCanvasEventTarget",
  "getBoundingClientRect",
  "currentFullscreenStrategy",
  "restoreOldWindowedStyle",
  "demangle",
  "demangleAll",
  "ExitStatus",
  "getEnvStrings",
  "doReadv",
  "doWritev",
  "promiseMap",
  "uncaughtExceptionCount",
  "exceptionLast",
  "exceptionCaught",
  "ExceptionInfo",
  "findMatchingCatch",
  "getExceptionMessageCommon",
  "incrementExceptionRefcount",
  "decrementExceptionRefcount",
  "getExceptionMessage",
  "Browser",
  "wget",
  "SYSCALLS",
  "preloadPlugins",
  "FS_createPreloadedFile",
  "FS_modeStringToFlags",
  "FS_getMode",
  "FS_stdin_getChar_buffer",
  "FS_stdin_getChar",
  "FS",
  "FS_createDataFile",
  "MEMFS",
  "TTY",
  "PIPEFS",
  "SOCKFS",
  "tempFixedLengthArray",
  "miniTempWebGLFloatBuffers",
  "miniTempWebGLIntBuffers",
  "heapObjectForWebGLType",
  "heapAccessShiftForWebGLHeap",
  "webgl_enable_ANGLE_instanced_arrays",
  "webgl_enable_OES_vertex_array_object",
  "webgl_enable_WEBGL_draw_buffers",
  "webgl_enable_WEBGL_multi_draw",
  "GL",
  "emscriptenWebGLGet",
  "computeUnpackAlignedImageSize",
  "colorChannelsInGlTextureFormat",
  "__glGenObject",
  "webglGetUniformLocation",
  "webglPrepareUniformLocationsBeforeFirstUse",
  "webglGetLeftBracePos",
  "__glGetActiveAttribOrUniform",
  "emscriptenWebGLGetBufferBinding",
  "emscriptenWebGLValidateMapBufferTarget",
  "emscripten_webgl_power_preferences",
  "AL",
  "GLUT",
  "EGL",
  "GLEW",
  "IDBStore",
  "runAndAbortIfError",
  "Asyncify",
  "Fibers",
  "SDL",
  "SDL_gfx",
  "webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance",
  "webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance",
  "allocateUTF8",
  "allocateUTF8OnStack",
  "InternalError",
  "BindingError",
  "throwInternalError",
  "throwBindingError",
  "registeredTypes",
  "awaitingDependencies",
  "typeDependencies",
  "tupleRegistrations",
  "structRegistrations",
  "sharedRegisterType",
  "whenDependentTypesAreResolved",
  "embind_charCodes",
  "embind_init_charCodes",
  "readLatin1String",
  "getTypeName",
  "heap32VectorToArray",
  "requireRegisteredType",
  "UnboundTypeError",
  "PureVirtualError",
  "GenericWireTypeSize",
  "init_embind",
  "throwUnboundTypeError",
  "ensureOverloadTable",
  "exposePublicSymbol",
  "replacePublicSymbol",
  "extendError",
  "createNamedFunction",
  "embindRepr",
  "registeredInstances",
  "getBasestPointer",
  "getInheritedInstance",
  "getInheritedInstanceCount",
  "getLiveInheritedInstances",
  "registeredPointers",
  "registerType",
  "integerReadValueFromPointer",
  "floatReadValueFromPointer",
  "simpleReadValueFromPointer",
  "readPointer",
  "runDestructors",
  "newFunc",
  "craftInvokerFunction",
  "embind__requireFunction",
  "genericPointerToWireType",
  "constNoSmartPtrRawPointerToWireType",
  "nonConstNoSmartPtrRawPointerToWireType",
  "init_RegisteredPointer",
  "RegisteredPointer",
  "RegisteredPointer_fromWireType",
  "runDestructor",
  "releaseClassHandle",
  "finalizationRegistry",
  "detachFinalizer_deps",
  "detachFinalizer",
  "attachFinalizer",
  "makeClassHandle",
  "init_ClassHandle",
  "ClassHandle",
  "throwInstanceAlreadyDeleted",
  "deletionQueue",
  "flushPendingDeletes",
  "delayFunction",
  "setDelayFunction",
  "RegisteredClass",
  "shallowCopyInternalPointer",
  "downcastPointer",
  "upcastPointer",
  "char_0",
  "char_9",
  "makeLegalFunctionName",
  "emval_handles",
  "emval_symbols",
  "init_emval",
  "count_emval_handles",
  "Emval",
  "emval_newers",
  "emval_methodCallers",
  "emval_registeredMethods",
];
unexportedSymbols.forEach(unexportedRuntimeSymbol);
var calledRun;
dependenciesFulfilled = function runCaller() {
  if (!calledRun) wasmRun();
  if (!calledRun) dependenciesFulfilled = runCaller;
};
function stackCheckInit() {
  _emscripten_stack_init();
  writeStackCookie();
}
function wasmRun() {
  if (runDependencies > 0) {
    return;
  }
  stackCheckInit();
  preRun();
  if (runDependencies > 0) {
    return;
  }
  function doRun() {
    if (calledRun) return;
    calledRun = true;
    Module["calledRun"] = true;
    if (ABORT) return;
    initRuntime();
    if (Module["onRuntimeInitialized"]) Module["onRuntimeInitialized"]();
    assert(
      !Module["_main"],
      'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]'
    );
    postRun();
  }
  if (Module["setStatus"]) {
    Module["setStatus"]("Running...");
    setTimeout(function () {
      setTimeout(function () {
        Module["setStatus"]("");
      }, 1);
      doRun();
    }, 1);
  } else {
    doRun();
  }
  checkStackCookie();
}
function checkUnflushedContent() {
  var oldOut = out;
  var oldErr = err;
  var has = false;
  out = err = (x) => {
    has = true;
  };
  try {
    _fflush(0);
    ["stdout", "stderr"].forEach(function (name) {
      var info = FS.analyzePath("/dev/" + name);
      if (!info) return;
      var stream = info.object;
      var rdev = stream.rdev;
      var tty = TTY.ttys[rdev];
      if (tty && tty.output && tty.output.length) {
        has = true;
      }
    });
  } catch (e) {}
  out = oldOut;
  err = oldErr;
  if (has) {
    warnOnce(
      "stdio streams had content in them that was not flushed. you should set EXIT_RUNTIME to 1 (see the Emscripten FAQ), or make sure to emit a newline when you printf etc."
    );
  }
}

//---------------------------Export Functions Initialize-------------------------------------
function InitExportFunctions() {
  ___wasm_call_ctors = createExportWrapper("__wasm_call_ctors");
  _Initialize = (Module["_Initialize"] = createExportWrapper("Initialize"));
  _AddFrameDatas = (Module["_AddFrameDatas"] = createExportWrapper("AddFrameDatas"));
  _Render = (Module["_Render"] = createExportWrapper("Render"));
  _Destroy = (Module["_Destroy"] = createExportWrapper("Destroy"));
  _Seek = (Module["_Seek"] = createExportWrapper("Seek"));
  _Pause = (Module["_Pause"] = createExportWrapper("Pause"));
  _malloc = createExportWrapper("malloc");
  ___cxa_free_exception = createExportWrapper("__cxa_free_exception");
  _free = (Module["_free"] = createExportWrapper("free"));
  ___errno_location = createExportWrapper("__errno_location");
  _fflush = (Module["_fflush"] = createExportWrapper("fflush"));
  setTempRet0 = createExportWrapper("setTempRet0");
  ___getTypeName = createExportWrapper("__getTypeName");
  __embind_initialize_bindings = (Module["__embind_initialize_bindings"] = createExportWrapper("_embind_initialize_bindings"));
  _emscripten_builtin_memalign = createExportWrapper("emscripten_builtin_memalign");
  _setThrew = createExportWrapper("setThrew");
  _emscripten_stack_init = () => (_emscripten_stack_init = wasmExports["emscripten_stack_init"])();
  _emscripten_stack_get_free = () => (_emscripten_stack_get_free = wasmExports["emscripten_stack_get_free"])();
  _emscripten_stack_get_base = () => (_emscripten_stack_get_base = wasmExports["emscripten_stack_get_base"])();
  _emscripten_stack_get_end = () => (_emscripten_stack_get_end = wasmExports["emscripten_stack_get_end"])();
  stackSave = createExportWrapper("stackSave");
  stackRestore = createExportWrapper("stackRestore");
  stackAlloc = createExportWrapper("stackAlloc");
  _emscripten_stack_get_current = () => (_emscripten_stack_get_current = wasmExports["emscripten_stack_get_current"])();
  ___cxa_decrement_exception_refcount = createExportWrapper("__cxa_decrement_exception_refcount");
  ___cxa_increment_exception_refcount = createExportWrapper("__cxa_increment_exception_refcount");
  ___get_exception_message = (Module["___get_exception_message"] = createExportWrapper("__get_exception_message"));
  ___cxa_can_catch = createExportWrapper("__cxa_can_catch");
  ___cxa_is_pointer_type = createExportWrapper("__cxa_is_pointer_type");
  dynCall_vi = (Module["dynCall_vi"] = createExportWrapper("dynCall_vi"));
  dynCall_iii = (Module["dynCall_iii"] = createExportWrapper("dynCall_iii"));
  dynCall_iiii = (Module["dynCall_iiii"] = createExportWrapper("dynCall_iiii"));
  dynCall_viii = (Module["dynCall_viii"] = createExportWrapper("dynCall_viii"));
  dynCall_vii = (Module["dynCall_vii"] = createExportWrapper("dynCall_vii"));
  dynCall_ii = (Module["dynCall_ii"] = createExportWrapper("dynCall_ii"));
  dynCall_i = (Module["dynCall_i"] = createExportWrapper("dynCall_i"));
  dynCall_vifji = (Module["dynCall_vifji"] = createExportWrapper("dynCall_vifji"));
  dynCall_iiiii = (Module["dynCall_iiiii"] = createExportWrapper("dynCall_iiiii"));
  dynCall_v = (Module["dynCall_v"] = createExportWrapper("dynCall_v"));
  dynCall_ji = (Module["dynCall_ji"] = createExportWrapper("dynCall_ji"));
  dynCall_vij = (Module["dynCall_vij"] = createExportWrapper("dynCall_vij"));
  dynCall_viiii = (Module["dynCall_viiii"] = createExportWrapper("dynCall_viiii"));
  dynCall_iij = (Module["dynCall_iij"] = createExportWrapper("dynCall_iij"));
  dynCall_di = (Module["dynCall_di"] = createExportWrapper("dynCall_di"));
  dynCall_iid = (Module["dynCall_iid"] = createExportWrapper("dynCall_iid"));
  dynCall_viif = (Module["dynCall_viif"] = createExportWrapper("dynCall_viif"));
  dynCall_fi = (Module["dynCall_fi"] = createExportWrapper("dynCall_fi"));
  dynCall_vid = (Module["dynCall_vid"] = createExportWrapper("dynCall_vid"));
  dynCall_iiiiii = (Module["dynCall_iiiiii"] = createExportWrapper("dynCall_iiiiii"));
  dynCall_viij = (Module["dynCall_viij"] = createExportWrapper("dynCall_viij"));
  dynCall_viid = (Module["dynCall_viid"] = createExportWrapper("dynCall_viid"));
  dynCall_iiiiiii = (Module["dynCall_iiiiiii"] = createExportWrapper("dynCall_iiiiiii"));
  dynCall_jiii = (Module["dynCall_jiii"] = createExportWrapper("dynCall_jiii"));
  dynCall_iiij = (Module["dynCall_iiij"] = createExportWrapper("dynCall_iiij"));
  dynCall_diii = (Module["dynCall_diii"] = createExportWrapper("dynCall_diii"));
  dynCall_fii = (Module["dynCall_fii"] = createExportWrapper("dynCall_fii"));
  dynCall_viji = (Module["dynCall_viji"] = createExportWrapper("dynCall_viji"));
  dynCall_viffff = (Module["dynCall_viffff"] = createExportWrapper("dynCall_viffff"));
  dynCall_viff = (Module["dynCall_viff"] = createExportWrapper("dynCall_viff"));
  dynCall_viffffff = (Module["dynCall_viffffff"] = createExportWrapper("dynCall_viffffff"));
  dynCall_vif = (Module["dynCall_vif"] = createExportWrapper("dynCall_vif"));
  dynCall_viiji = (Module["dynCall_viiji"] = createExportWrapper("dynCall_viiji"));
  dynCall_vifff = (Module["dynCall_vifff"] = createExportWrapper("dynCall_vifff"));
  dynCall_fiii = (Module["dynCall_fiii"] = createExportWrapper("dynCall_fiii"));
  dynCall_dii = (Module["dynCall_dii"] = createExportWrapper("dynCall_dii"));
  dynCall_jii = (Module["dynCall_jii"] = createExportWrapper("dynCall_jii"));
  dynCall_iif = (Module["dynCall_iif"] = createExportWrapper("dynCall_iif"));
  dynCall_viiiii = (Module["dynCall_viiiii"] = createExportWrapper("dynCall_viiiii"));
  dynCall_fiifii = (Module["dynCall_fiifii"] = createExportWrapper("dynCall_fiifii"));
  dynCall_did = (Module["dynCall_did"] = createExportWrapper("dynCall_did"));
  dynCall_jij = (Module["dynCall_jij"] = createExportWrapper("dynCall_jij"));
  dynCall_viiiiiif = (Module["dynCall_viiiiiif"] = createExportWrapper("dynCall_viiiiiif"));
  dynCall_viiiiffii = (Module["dynCall_viiiiffii"] = createExportWrapper("dynCall_viiiiffii"));
  dynCall_viiiifiii = (Module["dynCall_viiiifiii"] = createExportWrapper("dynCall_viiiifiii"));
  dynCall_iiiiiiii = (Module["dynCall_iiiiiiii"] = createExportWrapper("dynCall_iiiiiiii"));
  dynCall_viiif = (Module["dynCall_viiif"] = createExportWrapper("dynCall_viiif"));
  dynCall_iiji = (Module["dynCall_iiji"] = createExportWrapper("dynCall_iiji"));
  dynCall_viiiiiii = (Module["dynCall_viiiiiii"] = createExportWrapper("dynCall_viiiiiii"));
  dynCall_viiiiiiii = (Module["dynCall_viiiiiiii"] = createExportWrapper("dynCall_viiiiiiii"));
  dynCall_iiiiiiiii = (Module["dynCall_iiiiiiiii"] = createExportWrapper("dynCall_iiiiiiiii"));
  dynCall_fij = (Module["dynCall_fij"] = createExportWrapper("dynCall_fij"));
  dynCall_vifi = (Module["dynCall_vifi"] = createExportWrapper("dynCall_vifi"));
  dynCall_fiiiif = (Module["dynCall_fiiiif"] = createExportWrapper("dynCall_fiiiif"));
  dynCall_viiiiii = (Module["dynCall_viiiiii"] = createExportWrapper("dynCall_viiiiii"));
  dynCall_ijjiii = (Module["dynCall_ijjiii"] = createExportWrapper("dynCall_ijjiii"));
  dynCall_iijiii = (Module["dynCall_iijiii"] = createExportWrapper("dynCall_iijiii"));
  dynCall_iijjiii = (Module["dynCall_iijjiii"] = createExportWrapper("dynCall_iijjiii"));
  dynCall_idiii = (Module["dynCall_idiii"] = createExportWrapper("dynCall_idiii"));
  dynCall_viiij = (Module["dynCall_viiij"] = createExportWrapper("dynCall_viiij"));
  dynCall_iijii = (Module["dynCall_iijii"] = createExportWrapper("dynCall_iijii"));
  dynCall_jiij = (Module["dynCall_jiij"] = createExportWrapper("dynCall_jiij"));
  dynCall_vijj = (Module["dynCall_vijj"] = createExportWrapper("dynCall_vijj"));
  dynCall_viiifii = (Module["dynCall_viiifii"] = createExportWrapper("dynCall_viiifii"));
  dynCall_viijjii = (Module["dynCall_viijjii"] = createExportWrapper("dynCall_viijjii"));
  dynCall_viijiijji = (Module["dynCall_viijiijji"] = createExportWrapper("dynCall_viijiijji"));
  dynCall_iiiiiiiiii = (Module["dynCall_iiiiiiiiii"] = createExportWrapper("dynCall_iiiiiiiiii"));
  dynCall_viiiiiiiiiii = Module['dynCall_viiiiiiiiiii'] = createExportWrapper('dynCall_viiiiiiiiiii');
  dynCall_jiiji = (Module["dynCall_jiiji"] = createExportWrapper("dynCall_jiiji"));
  dynCall_jj = (Module["dynCall_jj"] = createExportWrapper("dynCall_jj"));
  dynCall_jiiiji = (Module["dynCall_jiiiji"] = createExportWrapper("dynCall_jiiiji"));
  dynCall_iiiji = (Module["dynCall_iiiji"] = createExportWrapper("dynCall_iiiji"));
  dynCall_jiji = (Module["dynCall_jiji"] = createExportWrapper("dynCall_jiji"));
  dynCall_iidiiii = (Module["dynCall_iidiiii"] = createExportWrapper("dynCall_iidiiii"));
  dynCall_j = (Module["dynCall_j"] = createExportWrapper("dynCall_j"));
  dynCall_viijii = (Module["dynCall_viijii"] = createExportWrapper("dynCall_viijii"));
  dynCall_iiiiij = (Module["dynCall_iiiiij"] = createExportWrapper("dynCall_iiiiij"));
  dynCall_iiiiiiiiiii = (Module["dynCall_iiiiiiiiiii"] = createExportWrapper("dynCall_iiiiiiiiiii"));
  dynCall_jiiii = (Module["dynCall_jiiii"] = createExportWrapper("dynCall_jiiii"));
  dynCall_iiiiiiiiiiiii = (Module["dynCall_iiiiiiiiiiiii"] = createExportWrapper("dynCall_iiiiiiiiiiiii"));
  dynCall_iiiiiiiiiiii = (Module["dynCall_iiiiiiiiiiii"] = createExportWrapper("dynCall_iiiiiiiiiiii"));
  dynCall_viiiiiiiiii = (Module["dynCall_viiiiiiiiii"] = createExportWrapper("dynCall_viiiiiiiiii"));
  dynCall_viiiiiiiiiiiiiii = (Module["dynCall_viiiiiiiiiiiiiii"] = createExportWrapper("dynCall_viiiiiiiiiiiiiii"));
  dynCall_iiiiid = (Module["dynCall_iiiiid"] =
    createExportWrapper("dynCall_iiiiid"));
  dynCall_iiiiijj = (Module["dynCall_iiiiijj"] = createExportWrapper("dynCall_iiiiijj"));
  dynCall_iiiiiijj = (Module["dynCall_iiiiiijj"] = createExportWrapper("dynCall_iiiiiijj"));
  _asyncify_start_unwind = createExportWrapper("asyncify_start_unwind");
  _asyncify_stop_unwind = createExportWrapper("asyncify_stop_unwind");
  _asyncify_start_rewind = createExportWrapper("asyncify_start_rewind");
  _asyncify_stop_rewind = createExportWrapper("asyncify_stop_rewind");
}

//---------------------------WebGL Reference Begin--------------------------------------------

function _glActiveTexture(x0) {
  GLctx.activeTexture(x0);
}

function _glAttachShader(program, shader) {
  GLctx.attachShader(GL.programs[program], GL.shaders[shader]);
};

function _glBeginQuery(target, id) {
  GLctx.beginQuery(target, GL.queries[id]);
};

function _glBindBuffer(target, buffer) {
  if (target == 35052) {
    GLctx.currentPixelUnpackBufferBinding = buffer;
  } else {
    GLctx.currentPixelUnpackBufferBinding = null;
  }
  GLctx.bindBuffer(target, GL.buffers[buffer]);
};

function _glBindBufferRange(target, index, buffer, offset, ptrsize) {
  GLctx.bindBufferRange(target, index, GL.buffers[buffer], offset, ptrsize);
};

function _glBindFramebuffer(target, framebuffer) {
  let f = GL.framebuffers[framebuffer];
  if (f) {
    GLctx.bindFramebuffer(target, f);
  } else {
    GLctx.bindFramebuffer(target, null);
  }
};

function _glBindRenderbuffer(target, renderbuffer) {
  GLctx.bindRenderbuffer(target, GL.renderbuffers[renderbuffer]);
};

function _glBindSampler(unit, sampler) {
  GLctx.bindSampler(unit, GL.samplers[sampler]);
};

function _glBindTexture(target, texture) {
  GLctx.bindTexture(target, GL.textures[texture]);
};

function _glBindVertexArray(vao) {
  let v = GL.vaos[vao];
  if (v) {
    GLctx.bindVertexArray(v);
  } else {
    GLctx.bindVertexArray(null);
  }
};

function _glBlendColor(x0, x1, x2, x3) {
  GLctx.blendColor(x0, x1, x2, x3);
}

function _glBlendEquationSeparate(x0, x1) {
  GLctx.blendEquationSeparate(x0, x1);
}

function _glBlendFuncSeparate(x0, x1, x2, x3) {
  GLctx.blendFuncSeparate(x0, x1, x2, x3);
}

function _glBlitFramebuffer(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9) {
  GLctx.blitFramebuffer(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9);
}

function _glBufferData(target, size, data, usage) {
  GLctx.bufferData(target, HEAPU8, usage, data, size);
};

function _glBufferSubData(target, offset, size, data) {
  GLctx.bufferSubData(target, offset, HEAPU8, data, size);
};

function _glCheckFramebufferStatus(x0) {
  return GLctx.checkFramebufferStatus(x0);
}
function _glClear(x0) {
  GLctx.clear(x0);
}

function _glClearBufferfv(buffer, drawbuffer, value) {
  //Android真机GLctx.clearBufferfv不生效
  // GLctx.clearBufferfv(buffer, drawbuffer, HEAPF32, value >> 2);

  var red = HEAPF32[value >> 2];
  var green = HEAPF32[(value >> 2) + 1];
  var blue = HEAPF32[(value >> 2) + 2];
  var alpha = HEAPF32[(value >> 2) + 3];

  GLctx.clearColor(red, green, blue, alpha);
  GLctx.clear(GLctx.COLOR_BUFFER_BIT);
};

function _glClearDepthf(x0) {
  GLctx.clearDepth(x0);
}

function _glClearStencil(x0) {
  GLctx.clearStencil(x0);
}
var convertI32PairToI53 = (lo, hi) => (lo >>> 0) + hi * 4294967296;

function _glClientWaitSync(sync, flags, timeout_low, timeout_high) {
  var timeout = convertI32PairToI53(timeout_low, timeout_high);
  return GLctx.clientWaitSync(GL.syncs[sync], flags, timeout);
};

function _glColorMask(red, green, blue, alpha) {
  GLctx.colorMask(!!red, !!green, !!blue, !!alpha);
};

function _glCompileShader(shader) {
  GLctx.compileShader(GL.shaders[shader]);
};

function _glCompressedTexSubImage2D(
  target,
  level,
  xoffset,
  yoffset,
  width,
  height,
  format,
  imageSize,
  data
) {
  if (GLctx.currentPixelUnpackBufferBinding || !imageSize) {
    GLctx.compressedTexSubImage2D(
      target,
      level,
      xoffset,
      yoffset,
      width,
      height,
      format,
      imageSize,
      data
    );
  } else {
    GLctx.compressedTexSubImage2D(
      target,
      level,
      xoffset,
      yoffset,
      width,
      height,
      format,
      HEAPU8,
      data,
      imageSize
    );
  }
};

function _glCompressedTexSubImage3D(
  target,
  level,
  xoffset,
  yoffset,
  zoffset,
  width,
  height,
  depth,
  format,
  imageSize,
  data
) {
  if (GLctx.currentPixelUnpackBufferBinding) {
    GLctx.compressedTexSubImage3D(
      target,
      level,
      xoffset,
      yoffset,
      zoffset,
      width,
      height,
      depth,
      format,
      imageSize,
      data
    );
  } else {
    GLctx.compressedTexSubImage3D(
      target,
      level,
      xoffset,
      yoffset,
      zoffset,
      width,
      height,
      depth,
      format,
      HEAPU8,
      data,
      imageSize
    );
  }
};

function _glCopyBufferSubData(x0, x1, x2, x3, x4) {
  GLctx.copyBufferSubData(x0, x1, x2, x3, x4);
}

function _glCreateProgram() {
  var id = GL.getNewId(GL.programs);
  var program = GLctx.createProgram();
  program.name = id;
  program.maxUniformLength =
    program.maxAttributeLength =
    program.maxUniformBlockNameLength =
      0;
  program.uniformIdCounter = 1;
  GL.programs[id] = program;
  return id;
};

function _glCreateShader(shaderType) {
  var id = GL.getNewId(GL.shaders);
  GL.shaders[id] = GLctx.createShader(shaderType);
  return id;
};

function _glCullFace(x0) {
  GLctx.cullFace(x0);
}

function _glDeleteBuffers(n, buffers) {
  for (var i = 0; i < n; i++) {
    var id = HEAP32[(buffers + i * 4) >> 2];
    var buffer = GL.buffers[id];
    if (!buffer) continue;
    GLctx.deleteBuffer(buffer);
    buffer.name = 0;
    GL.buffers[id] = null;
  }
};

function _glDeleteFramebuffers(n, framebuffers) {
  for (var i = 0; i < n; ++i) {
    var id = HEAP32[(framebuffers + i * 4) >> 2];
    var framebuffer = GL.framebuffers[id];
    if (!framebuffer) continue;
    GLctx.deleteFramebuffer(framebuffer);
    framebuffer.name = 0;
    GL.framebuffers[id] = null;
  }
};

function _glDeleteProgram(id) {
  if (!id) return;
  var program = GL.programs[id];
  if (!program) {
    GL.recordError(1281);
    return;
  }
  GLctx.deleteProgram(program);
  program.name = 0;
  GL.programs[id] = null;
};

function _glDeleteQueries(n, ids) {
  for (var i = 0; i < n; i++) {
    var id = HEAP32[(ids + i * 4) >> 2];
    var query = GL.queries[id];
    if (!query) continue;
    GLctx.deleteQuery(query);
    GL.queries[id] = null;
  }
};

function _glDeleteRenderbuffers(n, renderbuffers) {
  for (var i = 0; i < n; i++) {
    var id = HEAP32[(renderbuffers + i * 4) >> 2];
    var renderbuffer = GL.renderbuffers[id];
    if (!renderbuffer) continue;
    GLctx.deleteRenderbuffer(renderbuffer);
    renderbuffer.name = 0;
    GL.renderbuffers[id] = null;
  }
};

function _glDeleteSamplers(n, samplers) {
  for (var i = 0; i < n; i++) {
    var id = HEAP32[(samplers + i * 4) >> 2];
    var sampler = GL.samplers[id];
    if (!sampler) continue;
    GLctx.deleteSampler(sampler);
    sampler.name = 0;
    GL.samplers[id] = null;
  }
};

function _glDeleteShader(id) {
  if (!id) return;
  var shader = GL.shaders[id];
  if (!shader) {
    GL.recordError(1281);
    return;
  }
  GLctx.deleteShader(shader);
  GL.shaders[id] = null;
};

function _glDeleteSync(id) {
  if (!id) return;
  var sync = GL.syncs[id];
  if (!sync) {
    GL.recordError(1281);
    return;
  }
  GLctx.deleteSync(sync);
  sync.name = 0;
  GL.syncs[id] = null;
};

function _glDeleteTextures(n, textures) {
  for (var i = 0; i < n; i++) {
    var id = HEAP32[(textures + i * 4) >> 2];
    var texture = GL.textures[id];
    if (!texture) continue;
    GLctx.deleteTexture(texture);
    texture.name = 0;
    GL.textures[id] = null;
  }
};

function _glDeleteVertexArrays(n, vaos) {
  for (var i = 0; i < n; i++) {
    var id = HEAP32[(vaos + i * 4) >> 2];
    GLctx.deleteVertexArray(GL.vaos[id]);
    GL.vaos[id] = null;
  }
};

function _glDepthFunc(x0) {
  GLctx.depthFunc(x0);
}

function _glDepthMask(flag) {
  GLctx.depthMask(!!flag);
};

function _glDepthRangef(x0, x1) {
  GLctx.depthRange(x0, x1);
}

function _glDetachShader(program, shader) {
  GLctx.detachShader(GL.programs[program], GL.shaders[shader]);
};

function _glDisable(x0) {
  GLctx.disable(x0);
}

function _glDrawArrays(mode, first, count) {
  GLctx.drawArrays(mode, first, count);
};

function _glDrawArraysInstanced(mode, first, count, primcount) {
  GLctx.drawArraysInstanced(mode, first, count, primcount);
};

function _glDrawBuffers(n, bufs) {
  var bufArray = tempFixedLengthArray[n];
  for (var i = 0; i < n; i++) {
    bufArray[i] = HEAP32[(bufs + i * 4) >> 2];
  }
  GLctx.drawBuffers(bufArray);
};

function _glDrawElements(mode, count, type, indices) {
  GLctx.drawElements(mode, count, type, indices);
};

function _glDrawElementsInstanced(mode, count, type, indices, primcount) {
  GLctx.drawElementsInstanced(mode, count, type, indices, primcount);
};

function _glEnable(x0) {
  GLctx.enable(x0);
}

function _glEnableVertexAttribArray(index) {
  GLctx.enableVertexAttribArray(index);
};

function _glEndQuery(x0) {
  GLctx.endQuery(x0);
}

function _glFenceSync(condition, flags) {
  var sync = GLctx.fenceSync(condition, flags);
  if (sync) {
    var id = GL.getNewId(GL.syncs);
    sync.name = id;
    GL.syncs[id] = sync;
    return id;
  }
  return 0;
};

function _glFinish() {
  GLctx.finish();
}

function _glFlush() {
  GLctx.flush();
}

function _glFramebufferRenderbuffer(
  target,
  attachment,
  renderbuffertarget,
  renderbuffer
) {
  GLctx.framebufferRenderbuffer(
    target,
    attachment,
    renderbuffertarget,
    GL.renderbuffers[renderbuffer]
  );
};

function _glFramebufferTexture2D(
  target,
  attachment,
  textarget,
  texture,
  level
) {
  GLctx.framebufferTexture2D(
    target,
    attachment,
    textarget,
    GL.textures[texture],
    level
  );
};

function _glFramebufferTextureLayer(
  target,
  attachment,
  texture,
  level,
  layer
){
  GLctx.framebufferTextureLayer(
    target,
    attachment,
    GL.textures[texture],
    level,
    layer
  );
};

function _glFrontFace(x0) {
  GLctx.frontFace(x0);
}

function __glGenObject(n, buffers, createFunction, objectTable) {
  for (var i = 0; i < n; i++) {
    var buffer = GLctx[createFunction]();
    var id = buffer && GL.getNewId(objectTable);
    if (buffer) {
      buffer.name = id;
      objectTable[id] = buffer;
    } else {
      GL.recordError(1282);
    }
    HEAP32[(buffers + i * 4) >> 2] = id;
  }
};

function _glGenBuffers(n, buffers) {
  __glGenObject(n, buffers, "createBuffer", GL.buffers);
};

function _glGenFramebuffers(n, ids) {
  __glGenObject(n, ids, "createFramebuffer", GL.framebuffers);
};

function _glGenQueries(n, ids) {
  __glGenObject(n, ids, "createQuery", GL.queries);
};

function _glGenRenderbuffers(n, renderbuffers) {
  __glGenObject(n, renderbuffers, "createRenderbuffer", GL.renderbuffers);
};

function _glGenSamplers(n, samplers) {
  __glGenObject(n, samplers, "createSampler", GL.samplers);
};

function _glGenTextures(n, textures) {
  __glGenObject(n, textures, "createTexture", GL.textures);
};

function _glGenVertexArrays(n, arrays) {
  __glGenObject(n, arrays, "createVertexArray", GL.vaos);
}

function _glGenerateMipmap(x0) {
  GLctx.generateMipmap(x0);
}

function __glGetActiveAttribOrUniform(
  funcName,
  program,
  index,
  bufSize,
  length,
  size,
  type,
  name
) {
  program = GL.programs[program];
  var info = GLctx[funcName](program, index);
  if (info) {
    var numBytesWrittenExclNull =
      name && stringToUTF8(info.name, name, bufSize);
    if (length) HEAP32[length >> 2] = numBytesWrittenExclNull;
    if (size) HEAP32[size >> 2] = info.size;
    if (type) HEAP32[type >> 2] = info.type;
  }
};

function _glGetActiveUniform(
  program,
  index,
  bufSize,
  length,
  size,
  type,
  name
) {
  __glGetActiveAttribOrUniform(
    "getActiveUniform",
    program,
    index,
    bufSize,
    length,
    size,
    type,
    name
  );
};

function _glGetActiveUniformBlockName(
  program,
  uniformBlockIndex,
  bufSize,
  length,
  uniformBlockName
) {
  program = GL.programs[program];
  var result = GLctx.getActiveUniformBlockName(program, uniformBlockIndex);
  if (!result) return;
  if (uniformBlockName && bufSize > 0) {
    var numBytesWrittenExclNull = stringToUTF8(
      result,
      uniformBlockName,
      bufSize
    );
    if (length) HEAP32[length >> 2] = numBytesWrittenExclNull;
  } else {
    if (length) HEAP32[length >> 2] = 0;
  }
};

function _glGetBufferParameteriv(target, value, data) {
  if (!data) {
    GL.recordError(1281);
    return;
  }
  HEAP32[data >> 2] = GLctx.getBufferParameter(target, value);
};

function _glGetError() {
  var error = GLctx.getError() || GL.lastError;
  GL.lastError = 0;
  return error;
};

var writeI53ToI64 = (ptr, num) => {
  HEAPU32[ptr >> 2] = num;
  var lower = HEAPU32[ptr >> 2];
  HEAPU32[(ptr + 4) >> 2] = (num - lower) / 4294967296;
};

var emscriptenWebGLGet = (name_, p, type) => {
  if (!p) {
    GL.recordError(1281);
    return;
  }
  var ret = undefined;
  switch (name_) {
    case 36346:
      ret = 1;
      break;
    case 36344:
      if (type != 0 && type != 1) {
        GL.recordError(1280);
      }
      return;
    case 34814:
    case 36345:
      ret = 0;
      break;
    case 34466:
      var formats = GLctx.getParameter(34467);
      ret = formats ? formats.length : 0;
      break;
    case 33309:
      if (GL.currentContext.version < 2) {
        GL.recordError(1282);
        return;
      }
      var exts = GLctx.getSupportedExtensions() || [];
      ret = 2 * exts.length;
      break;
    case 33307:
    case 33308:
      if (GL.currentContext.version < 2) {
        GL.recordError(1280);
        return;
      }
      ret = name_ == 33307 ? 3 : 0;
      break;
  }
  if (ret === undefined) {
    var result = GLctx.getParameter(name_);
    switch (typeof result) {
      case "number":
        ret = result;
        break;
      case "boolean":
        ret = result ? 1 : 0;
        break;
      case "string":
        GL.recordError(1280);
        return;
      case "object":
        if (result === null) {
          switch (name_) {
            case 34964:
            case 35725:
            case 34965:
            case 36006:
            case 36007:
            case 32873:
            case 34229:
            case 36662:
            case 36663:
            case 35053:
            case 35055:
            case 36010:
            case 35097:
            case 35869:
            case 32874:
            case 36389:
            case 35983:
            case 35368:
            case 34068: {
              ret = 0;
              break;
            }
            default: {
              GL.recordError(1280);
              return;
            }
          }
        } else if (
          result instanceof Float32Array ||
          result instanceof Uint32Array ||
          result instanceof Int32Array ||
          result instanceof Array
        ) {
          for (var i = 0; i < result.length; ++i) {
            switch (type) {
              case 0:
                HEAP32[(p + i * 4) >> 2] = result[i];
                break;
              case 2:
                HEAPF32[(p + i * 4) >> 2] = result[i];
                break;
              case 4:
                HEAP8[(p + i) >> 0] = result[i] ? 1 : 0;
                break;
            }
          }
          return;
        } else {
          try {
            ret = result.name | 0;
          } catch (e) {
            GL.recordError(1280);
            err(
              "GL_INVALID_ENUM in glGet" +
                type +
                "v: Unknown object returned from WebGL getParameter(" +
                name_ +
                ")! (error: " +
                e +
                ")"
            );
            return;
          }
        }
        break;
      default:
        GL.recordError(1280);
        err(
          "GL_INVALID_ENUM in glGet" +
            type +
            "v: Native code calling glGet" +
            type +
            "v(" +
            name_ +
            ") and it returns " +
            result +
            " of type " +
            typeof result +
            "!"
        );
        return;
    }
  }
  switch (type) {
    case 1:
      writeI53ToI64(p, ret);
      break;
    case 0:
      HEAP32[p >> 2] = ret;
      break;
    case 2:
      HEAPF32[p >> 2] = ret;
      break;
    case 4:
      HEAP8[p >> 0] = ret ? 1 : 0;
      break;
  }
};

function _glGetIntegerv(name_, p) {
  emscriptenWebGLGet(name_, p, 0);
};

function _glGetProgramInfoLog(program, maxLength, length, infoLog) {
  var log = GLctx.getProgramInfoLog(GL.programs[program]);
  if (log === null) log = "(unknown error)";
  var numBytesWrittenExclNull =
    maxLength > 0 && infoLog ? stringToUTF8(log, infoLog, maxLength) : 0;
  if (length) HEAP32[length >> 2] = numBytesWrittenExclNull;
};

function _glGetProgramiv(program, pname, p) {
  if (!p) {
    GL.recordError(1281);
    return;
  }
  if (program >= GL.counter) {
    GL.recordError(1281);
    return;
  }
  program = GL.programs[program];
  if (pname == 35716) {
    var log = GLctx.getProgramInfoLog(program);
    if (log === null) log = "(unknown error)";
    HEAP32[p >> 2] = log.length + 1;
  } else if (pname == 35719) {
    if (!program.maxUniformLength) {
      for (var i = 0; i < GLctx.getProgramParameter(program, 35718); ++i) {
        program.maxUniformLength = Math.max(
          program.maxUniformLength,
          GLctx.getActiveUniform(program, i).name.length + 1
        );
      }
    }
    HEAP32[p >> 2] = program.maxUniformLength;
  } else if (pname == 35722) {
    if (!program.maxAttributeLength) {
      for (var i = 0; i < GLctx.getProgramParameter(program, 35721); ++i) {
        program.maxAttributeLength = Math.max(
          program.maxAttributeLength,
          GLctx.getActiveAttrib(program, i).name.length + 1
        );
      }
    }
    HEAP32[p >> 2] = program.maxAttributeLength;
  } else if (pname == 35381) {
    if (!program.maxUniformBlockNameLength) {
      for (var i = 0; i < GLctx.getProgramParameter(program, 35382); ++i) {
        program.maxUniformBlockNameLength = Math.max(
          program.maxUniformBlockNameLength,
          GLctx.getActiveUniformBlockName(program, i).length + 1
        );
      }
    }
    HEAP32[p >> 2] = program.maxUniformBlockNameLength;
  } else {
    HEAP32[p >> 2] = GLctx.getProgramParameter(program, pname);
  }
};

function _glGetQueryObjectuiv(id, pname, params) {
  if (!params) {
    GL.recordError(1281);
    return;
  }
  var query = GL.queries[id];
  var param = GLctx.getQueryParameter(query, pname);
  var ret;
  if (typeof param == "boolean") {
    ret = param ? 1 : 0;
  } else {
    ret = param;
  }
  HEAP32[params >> 2] = ret;
};

function _glGetShaderInfoLog(shader, maxLength, length, infoLog) {
  var log = GLctx.getShaderInfoLog(GL.shaders[shader]);
  if (log === null) log = "(unknown error)";
  var numBytesWrittenExclNull =
    maxLength > 0 && infoLog ? stringToUTF8(log, infoLog, maxLength) : 0;
  if (length) HEAP32[length >> 2] = numBytesWrittenExclNull;
};

function _glGetShaderiv(shader, pname, p) {
  if (!p) {
    GL.recordError(1281);
    return;
  }
  if (pname == 35716) {
    var log = GLctx.getShaderInfoLog(GL.shaders[shader]);
    if (log === null) log = "(unknown error)";
    var logLength = log ? log.length + 1 : 0;
    HEAP32[p >> 2] = logLength;
  } else if (pname == 35720) {
    var source = GLctx.getShaderSource(GL.shaders[shader]);
    var sourceLength = source ? source.length + 1 : 0;
    HEAP32[p >> 2] = sourceLength;
  } else {
    HEAP32[p >> 2] = GLctx.getShaderParameter(GL.shaders[shader], pname);
  }
};

function _glGetString(name_) {
  var ret = GL.stringCache[name_];
  if (!ret) {
    switch (name_) {
      case 7939:
        var exts = GLctx.getSupportedExtensions() || [];
        exts = exts.concat(exts.map((e) => "GL_" + e));
        ret = stringToNewUTF8(exts.join(" "));
        break;
      case 7936:
      case 7937:
      case 37445:
      case 37446:
        var s = GLctx.getParameter(name_);
        if (!s) {
          GL.recordError(1280);
        }
        ret = s && stringToNewUTF8(s);
        break;
      case 7938:
        var glVersion = GLctx.getParameter(7938);
        if (GL.currentContext.version >= 2)
          glVersion = "OpenGL ES 3.0 (" + glVersion + ")";
        else {
          glVersion = "OpenGL ES 2.0 (" + glVersion + ")";
        }
        ret = stringToNewUTF8(glVersion);
        break;
      case 35724:
        var glslVersion = GLctx.getParameter(35724);
        var ver_re = /^WebGL GLSL ES ([0-9]\.[0-9][0-9]?)(?:$| .*)/;
        var ver_num = glslVersion.match(ver_re);
        if (ver_num !== null) {
          if (ver_num[1].length == 3) ver_num[1] = ver_num[1] + "0";
          glslVersion =
            "OpenGL ES GLSL ES " + ver_num[1] + " (" + glslVersion + ")";
        }
        ret = stringToNewUTF8(glslVersion);
        break;
      default:
        GL.recordError(1280);
    }
    GL.stringCache[name_] = ret;
  }
  return ret;
};

function _glGetStringi(name, index) {
  if (GL.currentContext.version < 2) {
    GL.recordError(1282);
    return 0;
  }
  var stringiCache = GL.stringiCache[name];
  if (stringiCache) {
    if (index < 0 || index >= stringiCache.length) {
      GL.recordError(1281);
      return 0;
    }
    return stringiCache[index];
  }
  switch (name) {
    case 7939:
      var exts = GLctx.getSupportedExtensions() || [];
      exts = exts.concat(
        exts.map(function (e) {
          return "GL_" + e;
        })
      );
      exts = exts.map(function (e) {
        return stringToNewUTF8(e);
      });
      stringiCache = GL.stringiCache[name] = exts;
      if (index < 0 || index >= stringiCache.length) {
        GL.recordError(1281);
        return 0;
      }
      return stringiCache[index];
    default:
      GL.recordError(1280);
      return 0;
  }
};

function _glGetTexParameteriv(target, pname, params) {
  if (!params) {
    GL.recordError(1281);
    return;
  }
  HEAP32[params >> 2] = GLctx.getTexParameter(target, pname);
};

function _glGetUniformBlockIndex(program, uniformBlockName) {
  return GLctx.getUniformBlockIndex(
    GL.programs[program],
    UTF8ToString(uniformBlockName)
  );
}

var jstoi_q = (str) => parseInt(str);

var webglGetLeftBracePos = (name) =>
  name.slice(-1) == "]" && name.lastIndexOf("[");

var webglPrepareUniformLocationsBeforeFirstUse = (program) => {
  var uniformLocsById = program.uniformLocsById,
    uniformSizeAndIdsByName = program.uniformSizeAndIdsByName,
    i,
    j;
  if (!uniformLocsById) {
    program.uniformLocsById = uniformLocsById = {};
    program.uniformArrayNamesById = {};
    for (i = 0; i < GLctx.getProgramParameter(program, 35718); ++i) {
      var u = GLctx.getActiveUniform(program, i);
      var nm = u.name;
      var sz = u.size;
      var lb = webglGetLeftBracePos(nm);
      var arrayName = lb > 0 ? nm.slice(0, lb) : nm;
      var id = program.uniformIdCounter;
      program.uniformIdCounter += sz;
      uniformSizeAndIdsByName[arrayName] = [sz, id];
      for (j = 0; j < sz; ++j) {
        uniformLocsById[id] = j;
        program.uniformArrayNamesById[id++] = arrayName;
      }
    }
  }
};

function _glGetUniformLocation(program, name) {
  name = UTF8ToString(name);
  if ((program = GL.programs[program])) {
    webglPrepareUniformLocationsBeforeFirstUse(program);
    var uniformLocsById = program.uniformLocsById;
    var arrayIndex = 0;
    var uniformBaseName = name;
    var leftBrace = webglGetLeftBracePos(name);
    if (leftBrace > 0) {
      arrayIndex = jstoi_q(name.slice(leftBrace + 1)) >>> 0;
      uniformBaseName = name.slice(0, leftBrace);
    }
    var sizeAndId = program.uniformSizeAndIdsByName[uniformBaseName];
    if (sizeAndId && arrayIndex < sizeAndId[0]) {
      arrayIndex += sizeAndId[1];
      if (
        (uniformLocsById[arrayIndex] =
          uniformLocsById[arrayIndex] ||
          GLctx.getUniformLocation(program, name))
      ) {
        return arrayIndex;
      }
    }
  } else {
    GL.recordError(1281);
  }
  return -1;
};

function _glInvalidateFramebuffer(target, numAttachments, attachments) {
  var list = tempFixedLengthArray[numAttachments];
  for (var i = 0; i < numAttachments; i++) {
    list[i] = HEAP32[(attachments + i * 4) >> 2];
  }
  GLctx.invalidateFramebuffer(target, list);
};

function _glLinkProgram(program) {
  program = GL.programs[program];
  GLctx.linkProgram(program);
  program.uniformLocsById = 0;
  program.uniformSizeAndIdsByName = {};
};

var emscriptenWebGLGetBufferBinding = (target) => {
  switch (target) {
    case 0x8892 /*GL_ARRAY_BUFFER*/:
      target = 0x8894 /*GL_ARRAY_BUFFER_BINDING*/;
      break;
    case 0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/:
      target = 0x8895 /*GL_ELEMENT_ARRAY_BUFFER_BINDING*/;
      break;
    case 0x88eb /*GL_PIXEL_PACK_BUFFER*/:
      target = 0x88ed /*GL_PIXEL_PACK_BUFFER_BINDING*/;
      break;
    case 0x88ec /*GL_PIXEL_UNPACK_BUFFER*/:
      target = 0x88ef /*GL_PIXEL_UNPACK_BUFFER_BINDING*/;
      break;
    case 0x8c8e /*GL_TRANSFORM_FEEDBACK_BUFFER*/:
      target = 0x8c8f /*GL_TRANSFORM_FEEDBACK_BUFFER_BINDING*/;
      break;
    case 0x8f36 /*GL_COPY_READ_BUFFER*/:
      target = 0x8f36 /*GL_COPY_READ_BUFFER_BINDING*/;
      break;
    case 0x8f37 /*GL_COPY_WRITE_BUFFER*/:
      target = 0x8f37 /*GL_COPY_WRITE_BUFFER_BINDING*/;
      break;
    case 0x8a11 /*GL_UNIFORM_BUFFER*/:
      target = 0x8a28 /*GL_UNIFORM_BUFFER_BINDING*/;
      break;
    // In default case, fall through and assume passed one of the _BINDING enums directly.
  }
  var buffer = GLctx.getParameter(target);
  if (buffer) return buffer.name | 0;
  else return 0;
};

var emscriptenWebGLValidateMapBufferTarget = (target) => {
  switch (target) {
    case 0x8892: // GL_ARRAY_BUFFER
    case 0x8893: // GL_ELEMENT_ARRAY_BUFFER
    case 0x8f36: // GL_COPY_READ_BUFFER
    case 0x8f37: // GL_COPY_WRITE_BUFFER
    case 0x88eb: // GL_PIXEL_PACK_BUFFER
    case 0x88ec: // GL_PIXEL_UNPACK_BUFFER
    case 0x8c2a: // GL_TEXTURE_BUFFER
    case 0x8c8e: // GL_TRANSFORM_FEEDBACK_BUFFER
    case 0x8a11: // GL_UNIFORM_BUFFER
      return true;
    default:
      return false;
  }
};

function _glMapBufferRange(target, offset, length, access) {
  if ((access & (1 | 32)) != 0) {
    err(
      "glMapBufferRange access does not support MAP_READ or MAP_UNSYNCHRONIZED"
    );
    return 0;
  }
  if ((access & 2) == 0) {
    err("glMapBufferRange access must include MAP_WRITE");
    return 0;
  }
  if ((access & (4 | 8)) == 0) {
    err(
      "glMapBufferRange access must include INVALIDATE_BUFFER or INVALIDATE_RANGE"
    );
    return 0;
  }
  if (!emscriptenWebGLValidateMapBufferTarget(target)) {
    GL.recordError(1280);
    err("GL_INVALID_ENUM in glMapBufferRange");
    return 0;
  }
  var mem = _malloc(length),
    binding = emscriptenWebGLGetBufferBinding(target);
  if (!mem) return 0;
  if (!GL.mappedBuffers[binding]) GL.mappedBuffers[binding] = {};
  binding = GL.mappedBuffers[binding];
  binding.offset = offset;
  binding.length = length;
  binding.mem = mem;
  binding.access = access;
  return mem;
};

function _glPixelStorei(pname, param) {
  if (pname == 0xcf5 /* GL_UNPACK_ALIGNMENT */) {
    GL.unpackAlignment = param;
  }

  GLctx.pixelStorei(pname, param);
};

function _glPolygonOffset(x0, x1) {
  GLctx.polygonOffset(x0, x1);
}

function _glProgramParameteri(program, pname, value) {
  GL.recordError(1280);
};

var heapObjectForWebGLType = (type) => {
  // Micro-optimization for size: Subtract lowest GL enum number (0x1400/* GL_BYTE */) from type to compare
  // smaller values for the heap, for shorter generated code size.
  // Also the type HEAPU16 is not tested for explicitly, but any unrecognized type will return out HEAPU16.
  // (since most types are HEAPU16)
  type -= 0x1400;
  if (type == 0) return HEAP8;

  if (type == 1) return HEAPU8;

  if (type == 2) return HEAP16;

  if (type == 4) return HEAP32;

  if (type == 6) return HEAPF32;

  if (
    type == 5 ||
    type == 28922 ||
    type == 28520 ||
    type == 30779 ||
    type == 30782
  )
    return HEAPU32;

  return HEAPU16;
};

var heapAccessShiftForWebGLHeap = (heap) =>
  31 - Math.clz32(heap.BYTES_PER_ELEMENT);

function _glReadPixels(x, y, width, height, format, type, pixels) {
  GLctx.readPixels(x, y, width, height, format, type, pixels);
};

function _glRenderbufferStorageMultisample(x0, x1, x2, x3, x4) {
  GLctx.renderbufferStorageMultisample(x0, x1, x2, x3, x4);
}

function _glSamplerParameterf(sampler, pname, param) {
  GLctx.samplerParameterf(GL.samplers[sampler], pname, param);
};

function _glSamplerParameterfv(sampler, pname, params) {
  var param = HEAPF32[params >> 2];
  GLctx.samplerParameterf(GL.samplers[sampler], pname, param);
};

function _glSamplerParameteri(sampler, pname, param) {
  GLctx.samplerParameteri(GL.samplers[sampler], pname, param);
};

function _glScissor(x0, x1, x2, x3) {
  GLctx.scissor(x0, x1, x2, x3);
}

function _glShaderSource(shader, count, string, length) {
  var source = GL.getSource(shader, count, string, length);
  GLctx.shaderSource(GL.shaders[shader], source);
};

function _glStencilFuncSeparate(x0, x1, x2, x3) {
  GLctx.stencilFuncSeparate(x0, x1, x2, x3);
}
function _glStencilMask(x0) {
  GLctx.stencilMask(x0);
}
function _glStencilOpSeparate(x0, x1, x2, x3) {
  GLctx.stencilOpSeparate(x0, x1, x2, x3);
}

function _glTexParameteri(x0, x1, x2) {
  GLctx.texParameteri(x0, x1, x2);
}

function _glTexStorage2D(x0, x1, x2, x3, x4) {
  GLctx.texStorage2D(x0, x1, x2, x3, x4);
}

function _glTexStorage3D(x0, x1, x2, x3, x4, x5) {
  GLctx.texStorage3D(x0, x1, x2, x3, x4, x5);
}

function _glTexSubImage2D(
  target,
  level,
  xoffset,
  yoffset,
  width,
  height,
  format,
  type,
  pixels
) {
  if (GLctx.currentPixelUnpackBufferBinding) {
    GLctx.texSubImage2D(
      target,
      level,
      xoffset,
      yoffset,
      width,
      height,
      format,
      type,
      pixels
    );
  } else if (pixels) {
    var heap = heapObjectForWebGLType(type);
    GLctx.texSubImage2D(
      target,
      level,
      xoffset,
      yoffset,
      width,
      height,
      format,
      type,
      heap,
      pixels >> heapAccessShiftForWebGLHeap(heap)
    );
  } else {
    GLctx.texSubImage2D(
      target,
      level,
      xoffset,
      yoffset,
      width,
      height,
      format,
      type,
      null
    );
  }
};

function _glTexSubImage3D(
  target,
  level,
  xoffset,
  yoffset,
  zoffset,
  width,
  height,
  depth,
  format,
  type,
  pixels
) {
  if (GLctx.currentPixelUnpackBufferBinding) {
    GLctx.texSubImage3D(
      target,
      level,
      xoffset,
      yoffset,
      zoffset,
      width,
      height,
      depth,
      format,
      type,
      pixels
    );
  } else if (pixels) {
    var heap = heapObjectForWebGLType(type);
    GLctx.texSubImage3D(
      target,
      level,
      xoffset,
      yoffset,
      zoffset,
      width,
      height,
      depth,
      format,
      type,
      heap,
      pixels >> heapAccessShiftForWebGLHeap(heap)
    );
  } else {
    GLctx.texSubImage3D(
      target,
      level,
      xoffset,
      yoffset,
      zoffset,
      width,
      height,
      depth,
      format,
      type,
      null
    );
  }
};

var webglGetUniformLocation = (location) => {
  var p = GLctx.currentProgram;
  if (p) {
    var webglLoc = p.uniformLocsById[location];
    if (typeof webglLoc == "number") {
      p.uniformLocsById[location] = webglLoc = GLctx.getUniformLocation(
        p,
        p.uniformArrayNamesById[location] +
          (webglLoc > 0 ? "[" + webglLoc + "]" : "")
      );
    }
    return webglLoc;
  } else {
    GL.recordError(1282);
  }
};

function _glUniform1i(location, v0) {
  GLctx.uniform1i(webglGetUniformLocation(location), v0);
};

function _glUniformBlockBinding(
  program,
  uniformBlockIndex,
  uniformBlockBinding
) {
  program = GL.programs[program];
  GLctx.uniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding);
};

function _glUnmapBuffer(target) {
  if (!emscriptenWebGLValidateMapBufferTarget(target)) {
    GL.recordError(1280);
    err("GL_INVALID_ENUM in glUnmapBuffer");
    return 0;
  }
  var buffer = emscriptenWebGLGetBufferBinding(target);
  var mapping = GL.mappedBuffers[buffer];
  if (!mapping || !mapping.mem) {
    GL.recordError(1282);
    err("buffer was never mapped in glUnmapBuffer");
    return 0;
  }

  if (!(mapping.access & 0x10)) {
    /* GL_MAP_FLUSH_EXPLICIT_BIT */
    GLctx.bufferSubData(
      target,
      mapping.offset,
      HEAPU8,
      mapping.mem,
      mapping.length
    );
  }

  _free(mapping.mem);
  mapping.mem = 0;
  return 1;
};

function _glUseProgram(program) {
  if (program) {
    program = GL.programs[program];
    GLctx.useProgram(program);
  } else {
    GLctx.useProgram(null);
  }

  GLctx.currentProgram = program;
};

function _glVertexAttribDivisor(index, divisor) {
  GLctx.vertexAttribDivisor(index, divisor);
};

function _glVertexAttribIPointer(index, size, type, stride, ptr) {
  GLctx.vertexAttribIPointer(index, size, type, stride, ptr);
};

function _glVertexAttribPointer(index, size, type, normalized, stride, ptr) {
  GLctx.vertexAttribPointer(index, size, type, !!normalized, stride, ptr);
};

function _glViewport(x0, x1, x2, x3) {
  GLctx.viewport(x0, x1, x2, x3);
}

function _glWaitSync(sync, flags, timeout_low, timeout_high) {
  var timeout = convertI32PairToI53(timeout_low, timeout_high);
  GLctx.waitSync(GL.syncs[sync], flags, timeout);
};

//---------------------------WebGL Reference End--------------------------------------------

//--------------------------------GL Context Functions----------------------------------------------
var GL = {
  counter: 1,
  buffers: [],
  mappedBuffers: {},
  programs: [],
  framebuffers: [],
  renderbuffers: [],
  textures: [],
  shaders: [],
  vaos: [],
  contexts: [],
  offscreenCanvases: {},
  queries: [],
  samplers: [],
  transformFeedbacks: [],
  syncs: [],
  byteSizeByTypeRoot: 5120,
  byteSizeByType: [1, 1, 2, 2, 4, 4, 4, 2, 3, 4, 8],
  stringCache: {},
  stringiCache: {},
  unpackAlignment: 4,
  recordError: function recordError(errorCode) {
    if (!GL.lastError) {
      GL.lastError = errorCode;
    }
  },
  getNewId: (table) => {
    var ret = GL.counter++;
    for (var i = table.length; i < ret; i++) {
      table[i] = null;
    }
    return ret;
  },
  MAX_TEMP_BUFFER_SIZE: 2097152,
  numTempVertexBuffersPerSize: 64,
  log2ceilLookup: (i) => 32 - Math.clz32(i === 0 ? 0 : i - 1),
  generateTempBuffers: (quads, context) => {
    var largestIndex = GL.log2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE);
    context.tempVertexBufferCounters1 = [];
    context.tempVertexBufferCounters2 = [];
    context.tempVertexBufferCounters1.length =
      context.tempVertexBufferCounters2.length = largestIndex + 1;
    context.tempVertexBuffers1 = [];
    context.tempVertexBuffers2 = [];
    context.tempVertexBuffers1.length = context.tempVertexBuffers2.length =
      largestIndex + 1;
    context.tempIndexBuffers = [];
    context.tempIndexBuffers.length = largestIndex + 1;
    for (var i = 0; i <= largestIndex; ++i) {
      context.tempIndexBuffers[i] = null;
      context.tempVertexBufferCounters1[i] = context.tempVertexBufferCounters2[
        i
      ] = 0;
      var ringbufferLength = GL.numTempVertexBuffersPerSize;
      context.tempVertexBuffers1[i] = [];
      context.tempVertexBuffers2[i] = [];
      var ringbuffer1 = context.tempVertexBuffers1[i];
      var ringbuffer2 = context.tempVertexBuffers2[i];
      ringbuffer1.length = ringbuffer2.length = ringbufferLength;
      for (var j = 0; j < ringbufferLength; ++j) {
        ringbuffer1[j] = ringbuffer2[j] = null;
      }
    }
    if (quads) {
      context.tempQuadIndexBuffer = GLctx.createBuffer();
      context.GLctx.bindBuffer(34963, context.tempQuadIndexBuffer);
      var numIndexes = GL.MAX_TEMP_BUFFER_SIZE >> 1;
      var quadIndexes = new Uint16Array(numIndexes);
      var i = 0,
        v = 0;
      while (1) {
        quadIndexes[i++] = v;
        if (i >= numIndexes) break;
        quadIndexes[i++] = v + 1;
        if (i >= numIndexes) break;
        quadIndexes[i++] = v + 2;
        if (i >= numIndexes) break;
        quadIndexes[i++] = v;
        if (i >= numIndexes) break;
        quadIndexes[i++] = v + 2;
        if (i >= numIndexes) break;
        quadIndexes[i++] = v + 3;
        if (i >= numIndexes) break;
        v += 4;
      }
      context.GLctx.bufferData(34963, quadIndexes, 35044);
      context.GLctx.bindBuffer(34963, null);
    }
  },
  getTempVertexBuffer: function getTempVertexBuffer(sizeBytes) {
    var idx = GL.log2ceilLookup(sizeBytes);
    var ringbuffer = GL.currentContext.tempVertexBuffers1[idx];
    var nextFreeBufferIndex = GL.currentContext.tempVertexBufferCounters1[idx];
    GL.currentContext.tempVertexBufferCounters1[idx] =
      (GL.currentContext.tempVertexBufferCounters1[idx] + 1) &
      (GL.numTempVertexBuffersPerSize - 1);
    var vbo = ringbuffer[nextFreeBufferIndex];
    if (vbo) {
      return vbo;
    }
    var prevVBO = GLctx.getParameter(34964);
    ringbuffer[nextFreeBufferIndex] = GLctx.createBuffer();
    GLctx.bindBuffer(34962, ringbuffer[nextFreeBufferIndex]);
    GLctx.bufferData(34962, 1 << idx, 35048);
    GLctx.bindBuffer(34962, prevVBO);
    return ringbuffer[nextFreeBufferIndex];
  },
  getTempIndexBuffer: function getTempIndexBuffer(sizeBytes) {
    var idx = GL.log2ceilLookup(sizeBytes);
    var ibo = GL.currentContext.tempIndexBuffers[idx];
    if (ibo) {
      return ibo;
    }
    var prevIBO = GLctx.getParameter(34965);
    GL.currentContext.tempIndexBuffers[idx] = GLctx.createBuffer();
    GLctx.bindBuffer(34963, GL.currentContext.tempIndexBuffers[idx]);
    GLctx.bufferData(34963, 1 << idx, 35048);
    GLctx.bindBuffer(34963, prevIBO);
    return GL.currentContext.tempIndexBuffers[idx];
  },
  newRenderingFrameStarted: function newRenderingFrameStarted() {
    if (!GL.currentContext) {
      return;
    }
    var vb = GL.currentContext.tempVertexBuffers1;
    GL.currentContext.tempVertexBuffers1 = GL.currentContext.tempVertexBuffers2;
    GL.currentContext.tempVertexBuffers2 = vb;
    vb = GL.currentContext.tempVertexBufferCounters1;
    GL.currentContext.tempVertexBufferCounters1 =
      GL.currentContext.tempVertexBufferCounters2;
    GL.currentContext.tempVertexBufferCounters2 = vb;
    var largestIndex = GL.log2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE);
    for (var i = 0; i <= largestIndex; ++i) {
      GL.currentContext.tempVertexBufferCounters1[i] = 0;
    }
  },
  getSource: (shader, count, string, length) => {
    var source = "";
    for (var i = 0; i < count; ++i) {
      var len = length ? HEAP32[(length + i * 4) >> 2] : -1;
      source += UTF8ToString(
        HEAP32[(string + i * 4) >> 2],
        len < 0 ? undefined : len
      );
    }
    return source;
  },
  calcBufLength: function calcBufLength(size, type, stride, count) {
    if (stride > 0) {
      return count * stride;
    }
    var typeSize = GL.byteSizeByType[type - GL.byteSizeByTypeRoot];
    return size * typeSize * count;
  },
  usedTempBuffers: [],
  preDrawHandleClientVertexAttribBindings:
    function preDrawHandleClientVertexAttribBindings(count) {
      GL.resetBufferBinding = false;
      for (var i = 0; i < GL.currentContext.maxVertexAttribs; ++i) {
        var cb = GL.currentContext.clientBuffers[i];
        if (!cb.clientside || !cb.enabled) continue;
        GL.resetBufferBinding = true;
        var size = GL.calcBufLength(cb.size, cb.type, cb.stride, count);
        var buf = GL.getTempVertexBuffer(size);
        GLctx.bindBuffer(34962, buf);
        GLctx.bufferSubData(34962, 0, HEAPU8.subarray(cb.ptr, cb.ptr + size));
        cb.vertexAttribPointerAdaptor.call(
          GLctx,
          i,
          cb.size,
          cb.type,
          cb.normalized,
          cb.stride,
          0
        );
      }
    },
  postDrawHandleClientVertexAttribBindings:
    function postDrawHandleClientVertexAttribBindings() {
      if (GL.resetBufferBinding) {
        GLctx.bindBuffer(34962, GL.buffers[GLctx.currentArrayBufferBinding]);
      }
    },
  createContext: (canvas, webGLContextAttributes) => {
    var ctx = canvas.getContext("webgl2");
    if (!ctx) return 0;

    var handle = GL.registerContext(ctx, webGLContextAttributes);
    return handle;
  },
  registerContext: (ctx, webGLContextAttributes) => {
    var handle = GL.getNewId(GL.contexts);
    var context = {
      handle: handle,
      attributes: webGLContextAttributes,
      version: webGLContextAttributes.majorVersion,
      GLctx: ctx,
    };
    if (ctx.canvas) ctx.canvas.GLctxObject = context;
    GL.contexts[handle] = context;

    context.maxVertexAttribs = context.GLctx.getParameter(34921);
    context.clientBuffers = [];
    for (var i = 0; i < context.maxVertexAttribs; i++) {
      context.clientBuffers[i] = {
        enabled: false,
        clientside: false,
        size: 0,
        type: 0,
        normalized: 0,
        stride: 0,
        ptr: 0,
        vertexAttribPointerAdaptor: null,
      };
    }
    GL.generateTempBuffers(false, context);
    return handle;
  },
  makeContextCurrent: (contextHandle) => {
    GL.currentContext = GL.contexts[contextHandle];
    Module.ctx = GLctx = GL.currentContext && GL.currentContext.GLctx;
    return !(contextHandle && !GLctx);
  },
  getContext: (contextHandle) => GL.contexts[contextHandle],
  deleteContext: (contextHandle) => {
    if (GL.currentContext === GL.contexts[contextHandle])
      GL.currentContext = null;
    if (typeof JSEvents == "object")
      JSEvents.removeAllHandlersOnTarget(
        GL.contexts[contextHandle].GLctx.canvas
      );
    if (GL.contexts[contextHandle] && GL.contexts[contextHandle].GLctx.canvas)
      GL.contexts[contextHandle].GLctx.canvas.GLctxObject = undefined;
    GL.contexts[contextHandle] = null;
  },
  initExtensions: (context) => {
    if (!context) context = GL.currentContext;
    if (context.initExtensionsDone) return;
    context.initExtensionsDone = true;
    var GLctx = context.GLctx;
    webgl_enable_ANGLE_instanced_arrays(GLctx);
    webgl_enable_OES_vertex_array_object(GLctx);
    webgl_enable_WEBGL_draw_buffers(GLctx);
    webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(GLctx);
    webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(GLctx);
    if (context.version >= 2) {
      GLctx.disjointTimerQueryExt = GLctx.getExtension(
        "EXT_disjoint_timer_query_webgl2"
      );
    }
    if (context.version < 2 || !GLctx.disjointTimerQueryExt) {
      GLctx.disjointTimerQueryExt = GLctx.getExtension(
        "EXT_disjoint_timer_query"
      );
    }
    webgl_enable_WEBGL_multi_draw(GLctx);
    var exts = GLctx.getSupportedExtensions() || [];
    exts.forEach((ext) => {
      if (!ext.includes("lose_context") && !ext.includes("debug")) {
        GLctx.getExtension(ext);
      }
    });
  },
};

//--------------------------------Asyncify Functions------------------------------------------------
var Asyncify = {
  instrumentWasmImports(imports) {
    var importPattern =
      /^(RequestPost|RequestDownload|invoke_.*|__asyncjs__.*)$/;
    for (var x in imports) {
      (function (x) {
        var original = imports[x];
        var sig = original.sig;
        if (typeof original == "function") {
          var isAsyncifyImport = original.isAsync || importPattern.test(x);
        }
      })(x);
    }
  },
  instrumentWasmExports(exports) {
    var ret = {};
    var exportPattern = /^(RunTask)$/;
    for (var x in exports) {
      (function (x) {
        var original = exports[x];
        if (typeof original == "function") {
          if (exportPattern.test(x)) {
            ret[x] = function () {
              Asyncify.exportCallStack.push(x);
              try {
                return original.apply(null, arguments);
              } finally {
                if (!ABORT) {
                  var y = Asyncify.exportCallStack.pop();
                  assert(y === x);
                  Asyncify.maybeStopUnwind();
                }
              }
            };
          } else {
            ret[x] = original;
          }
        } else {
          ret[x] = original;
        }
      })(x);
    }
    return ret;
  },
  State: { Normal: 0, Unwinding: 1, Rewinding: 2, Disabled: 3 },
  state: 0,
  StackSize: 65536,
  currData: null,
  handleSleepReturnValue: 0,
  exportCallStack: [],
  callStackNameToId: {},
  callStackIdToName: {},
  callStackId: 0,
  asyncPromiseHandlers: null,
  sleepCallbacks: [],
  getCallStackId(funcName) {
    var id = Asyncify.callStackNameToId[funcName];
    if (id === undefined) {
      id = Asyncify.callStackId++;
      Asyncify.callStackNameToId[funcName] = id;
      Asyncify.callStackIdToName[id] = funcName;
    }
    return id;
  },
  maybeStopUnwind() {
    if (
      Asyncify.currData &&
      Asyncify.state === Asyncify.State.Unwinding &&
      Asyncify.exportCallStack.length === 0
    ) {
      Asyncify.state = Asyncify.State.Normal;
      runAndAbortIfError(_asyncify_stop_unwind);
      if (typeof Fibers != "undefined") {
        Fibers.trampoline();
      }
    }
  },
  whenDone() {
    return new Promise((resolve, reject) => {
      Asyncify.asyncPromiseHandlers = { resolve: resolve, reject: reject };
    });
  },
  allocateData() {
    var ptr = _malloc(12 + Asyncify.StackSize);
    Asyncify.setDataHeader(ptr, ptr + 12, Asyncify.StackSize);
    Asyncify.setDataRewindFunc(ptr);
    return ptr;
  },
  setDataHeader(ptr, stack, stackSize) {
    HEAPU32[ptr >> 2] = stack;
    HEAPU32[(ptr + 4) >> 2] = stack + stackSize;
  },
  setDataRewindFunc(ptr) {
    var bottomOfCallStack = Asyncify.exportCallStack[0];
    var rewindId = Asyncify.getCallStackId(bottomOfCallStack);
    HEAP32[(ptr + 8) >> 2] = rewindId;
  },
  getDataRewindFunc(ptr) {
    var id = HEAP32[(ptr + 8) >> 2];
    var name = Asyncify.callStackIdToName[id];
    var func = wasmExports[name];
    return func;
  },
  doRewind(ptr) {
    var start = Asyncify.getDataRewindFunc(ptr);
    return start();
  },
  handleSleep(startAsync) {
    if (ABORT) return;
    if (Asyncify.state === Asyncify.State.Normal) {
      var reachedCallback = false;
      var reachedAfterCallback = false;
      startAsync((handleSleepReturnValue = 0) => {
        if (ABORT) return;
        Asyncify.handleSleepReturnValue = handleSleepReturnValue;
        reachedCallback = true;
        if (!reachedAfterCallback) {
          return;
        }
        Asyncify.state = Asyncify.State.Rewinding;
        runAndAbortIfError(() => _asyncify_start_rewind(Asyncify.currData));
        if (typeof Browser != "undefined" && Browser.mainLoop.func) {
          Browser.mainLoop.resume();
        }
        var asyncWasmReturnValue,
          isError = false;
        try {
          asyncWasmReturnValue = Asyncify.doRewind(Asyncify.currData);
        } catch (err) {
          asyncWasmReturnValue = err;
          isError = true;
        }
        var handled = false;
        if (!Asyncify.currData) {
          var asyncPromiseHandlers = Asyncify.asyncPromiseHandlers;
          if (asyncPromiseHandlers) {
            Asyncify.asyncPromiseHandlers = null;
            (isError
              ? asyncPromiseHandlers.reject
              : asyncPromiseHandlers.resolve)(asyncWasmReturnValue);
            handled = true;
          }
        }
        if (isError && !handled) {
          throw asyncWasmReturnValue;
        }
      });
      reachedAfterCallback = true;
      if (!reachedCallback) {
        Asyncify.state = Asyncify.State.Unwinding;
        Asyncify.currData = Asyncify.allocateData();
        if (typeof Browser != "undefined" && Browser.mainLoop.func) {
          Browser.mainLoop.pause();
        }
        runAndAbortIfError(() => _asyncify_start_unwind(Asyncify.currData));
      }
    } else if (Asyncify.state === Asyncify.State.Rewinding) {
      Asyncify.state = Asyncify.State.Normal;
      runAndAbortIfError(_asyncify_stop_rewind);
      _free(Asyncify.currData);
      Asyncify.currData = null;
      Asyncify.sleepCallbacks.forEach((func) => callUserCallback(func));
    } else {
      abort(`invalid state: ${Asyncify.state}`);
    }
    return Asyncify.handleSleepReturnValue;
  },
  handleAsync(startAsync) {
    return Asyncify.handleSleep((wakeUp) => {
      startAsync().then(wakeUp).catch(err => {
        if (Module['runTaskFailed']) {
          Module['runTaskFailed'](err);
        }
      });
    });
  },
};

//--------------------------------EmBinding Functions------------------------------------------------
function craftInvokerFunction(
  humanName,
  argTypes,
  classType,
  cppInvokerFunc,
  cppTargetFunc,
  isAsync
) {
  var argCount = argTypes.length;
  if (argCount < 2) {
    throwBindingError("argTypes array size mismatch! Must at least get return value and 'this' types!")
  }

  var isClassMethodFunc = argTypes[1] !== null && classType !== null;
  var needsDestructorStack = false;
  for (var i = 1; i < argTypes.length; ++i) {
    if (argTypes[i] !== null && argTypes[i].destructorFunction === undefined) {
      needsDestructorStack = true;
      break
    }
  }
  var returns = argTypes[0].name !== "void";

  var args2 = [throwBindingError, cppInvokerFunc, cppTargetFunc, runDestructors, argTypes[0], argTypes[1]];
  for (var i = 0; i < argCount - 2; ++i) {
    args2.push(argTypes[i + 2])
  }
  if (isClassMethodFunc) {
    for (var i = 1; i < argCount; ++i) {
      if (argTypes[i].destructorFunction !== null) {
        args2.push(argTypes[i].destructorFunction)
      } else {
        args2.push(null)
      }
    }
  } else {
    for (var i = 2; i < argCount; ++i) {
      if (argTypes[i].destructorFunction !== null) {
        args2.push(argTypes[i].destructorFunction)
      } else {
        args2.push(null)
      }
    }
  }


  function f1(throwBindingError, invoker, fn, runDestructors, retType, classParam) {
    // arguments = [argType0,argType1,argType2,arg0Wired_dtor]
    // argType0,argType1,argType2
    const argsTypeOrigin = Array.prototype.slice.call(arguments, 6, 6 + argCount - 2)
    // arg0Wired_dtor
    const argsWired_dtorOrigin = Array.prototype.slice.call(arguments, 6 + argCount - 2)

    return function () {
      // arguments = [arg0, arg1, arg2]
      if (arguments.length !== argCount - 2) {
        throwBindingError('function ' + humanName + ' called with ' + arguments.length + ' arguments, expected 0 args!');
      }
      var thisWired;
      var destructors;
      if (needsDestructorStack) {
        destructors = [];
      }

      if (isClassMethodFunc) {
        if (needsDestructorStack) {
          thisWired = classParam.toWireType(destructors, this);
        } else {
          thisWired = classParam.toWireType(null, this);
        }
      }

      // arg0Wired,arg1Wired,arg2Wired
      var argsWired = [];
      for (var i = 0; i < argCount - 2; ++i) {
        if (needsDestructorStack) {
          argsWired.push(argsTypeOrigin[i].toWireType(destructors, arguments[i]))
        } else {
          argsWired.push(argsTypeOrigin[i].toWireType(null, arguments[i]))
        }
      }

      var rv;
      if (isClassMethodFunc) {
        rv = invoker(fn, thisWired, ...argsWired);
      } else {
        rv = invoker(fn, ...argsWired);
      }

      if (needsDestructorStack) {
        runDestructors(destructors);
      } else {
        if (isClassMethodFunc) {
          for (var i = 1; i < argTypes.length; ++i) {
            if (argTypes[i].destructorFunction !== null) {
              if (i == 1) {
                argsWired_dtorOrigin[i - 1](thisWired);
              } else {
                argsWired_dtorOrigin[i - 1](argsWired[i - 1]);
              }
            }
          }
        } else {
          for (var i = 2; i < argTypes.length; ++i) {
            if (argTypes[i].destructorFunction !== null) {
              argsWired_dtorOrigin[i - 2](argsWired[i - 2]);
            }
          }
        }
      }
      if (returns) {
        var ret = retType.fromWireType(rv);
        return ret;
      }
    }
  }

  return f1.apply(null, args2)
}

//--------------------------------download imported function-----------------------------------------
var postResponse;
function _RequestPost(url, msg, time) {
  return Asyncify.handleAsync(async () => {
    let urlStr = UTF8ToString(url, 256);
    let dataStr = UTF8ToString(msg, 256);
    let ret = 2;

    await new Promise((resolve, reject) => {
      wx.request({
        url: urlStr,
        method: 'POST',
        data: dataStr, // 要发送的数据
        timeout:time * 1000,
        success: function (response) {
          if (workerDestroyed) {
            reject("Stop post request because ptd engine has destoryed.");
            return;
          }

          const statusCode = response.statusCode;
          if (statusCode === 200) {
            resolve(response.data);
          } else {
            reject("Network response was not OK");
          }
        },
        fail: function (error) {
          reject(error.errMsg);
        }
      });
    }).then(result => {
      postResponse = JSON.stringify(result);
      ret = 0;
    }).catch(error => {
      // 处理网络错误
      if (error.includes("timeout")) {
        ret = 1;
      } else {
        ret = 2;
      }
    });

    return ret;
  });
}

function _GetPostResult(ptr, size) {
  if (ptr === 0) {
    return lengthBytesUTF8(postResponse) + 1;
  }

  return stringToUTF8(postResponse, ptr, size);
}

var downloadResponse = {};
function _RequestDownload(url, file, time) {
  return Asyncify.handleAsync(async () => {
    let ret = 2;
    let urlStr = UTF8ToString(url, 512);

    await new Promise((resolve, reject) => {
      wx.request({
        url: urlStr,
        responseType: 'arraybuffer',
        useHighPerformanceMode: true,
        success: function (response) {
          if (workerDestroyed) {
            reject("Stop download request because ptd engine has destoryed.");
            return;
          }
          const statusCode = response.statusCode;
          if (statusCode === 200) {
            downloadResponse.contentType = response.header['Content-Type'];
            downloadResponse.contentLength = response.header["Content-Length"];
            downloadResponse.statusCode = statusCode;
            resolve(response.data);
          } else {
            reject("Network response was not OK");
          }
        },
        fail: function (error) {
          console.error("wx.request error:", error, " with url:", urlStr);
          reject(error.errMsg);
        }
      });
    }).then(result => {
      let filePath = UTF8ToString(file, 256);
      let bufferView = new Uint8Array(result);
      FS.writeFile(filePath, bufferView);
      ret = 0;
    }).catch(error => {
      // 处理网络错误
      if (error.includes("timeout") || error.includes("time out")) {
        ret = 1;
      } else {
        ret = 2;
      }
    });

    return ret;
  });
}

function _GetDownloadStatus() {
  return downloadResponse.statusCode;
}

function _GetDownloadContentLength() {
  return downloadResponse.contentLength;
}

function _GetDownloadContentType(ptr, size) {
  if (ptr === 0) {
    return lengthBytesUTF8(downloadResponse.contentType) + 1;
  }

  return stringToUTF8(downloadResponse.contentType, ptr, size);
}

function OrientationToRotation(orientation) {
  if (orientation === "up") {
    return 0;
  } else if (orientation === "right") {
    return 1;
  } else if (orientation === "down") {
    return 2;
  } else if (orientation === "left") {
    return 3;
  } 

  throw "Media orientation not support:" + orientation;
}

function _ProbePictureInfo(ptr) {
  return Asyncify.handleAsync(async () => {
    const fs = wx.getFileSystemManager();
    try {
      fs.mkdirSync(`${wx.env.USER_DATA_PATH}/wasm/tmp`, true);
    } catch(e) {
    }
    
    let file = UTF8ToString(ptr);
    let fileData = FS.readFile(file);
    let postfix = file.substring(file.lastIndexOf("/") + 1);
    const tmpFileName = `${wx.env.USER_DATA_PATH}/wasm/tmp/` + postfix;
    fs.writeFileSync(tmpFileName, fileData.buffer, 'binary');

    
    let imgInfo = null;
    await new Promise((resolve, reject) => {
      wx.getImageInfo({
        src: tmpFileName,
        success (res) {
          const metadata = {
            width: res.width,
            height: res.height,
            rotation: OrientationToRotation(res.orientation),
          };

          resolve(metadata);
        },
        fail (err) {
          reject(err);
        }
      });
    }).then(ret => {
      imgInfo = _malloc(12);
      HEAPU32[imgInfo >> 2] = ret.width;
      HEAPU32[(imgInfo + 4) >> 2] = ret.height;
      HEAPU32[(imgInfo + 8) >> 2] = ret.rotation;
      fs.unlinkSync(tmpFileName);
    }).catch(err => {
      throw err;
    });

    return imgInfo;
  });
}

function _ProbeVideoInfo(ptr) {
  return Asyncify.handleAsync(async () => {
    const fs = wx.getFileSystemManager();
    try {
      fs.mkdirSync(`${wx.env.USER_DATA_PATH}/wasm/tmp`, true);
    } catch(e) {
    }

    let file = UTF8ToString(ptr);
    let fileData = FS.readFile(file);
    let postfix = file.substring(file.lastIndexOf("/") + 1);
    const tmpFileName = `${wx.env.USER_DATA_PATH}/wasm/tmp/` + postfix;
    fs.writeFileSync(tmpFileName, fileData.buffer, 'binary');

    let videoInfo = null;
    await new Promise((resolve, reject) => {
      wx.getVideoInfo({
        src: tmpFileName,
        success (res) {
          const metadata = {
            width: res.width,
            height: res.height,
            duration: res.duration,
            rotation: OrientationToRotation(res.orientation) * 90,
          };

          resolve(metadata);
        },
        fail (err) {
          reject(err);
        }
      });
    }).then(ret => {
      videoInfo = _malloc(16);
      HEAPF32[videoInfo >> 2] = ret.width;
      HEAPF32[(videoInfo + 4) >> 2] = ret.height;
      HEAPF32[(videoInfo + 8) >> 2] = ret.rotation;
      HEAPF32[(videoInfo + 12) >> 2] = ret.duration;
      fs.unlinkSync(tmpFileName);
    }).catch(err => {
      throw err;
    });

    return videoInfo;
  });
}

function _ProbeAudioInfo(ptr) {
  return Asyncify.handleAsync(async () => {
    const fs = wx.getFileSystemManager();
    try {
      fs.mkdirSync(`${wx.env.USER_DATA_PATH}/wasm/tmp`, true);
    } catch (e) {}

    let file = UTF8ToString(ptr);
    let fileData = FS.readFile(file);
    let postfix = file.substring(file.lastIndexOf("/") + 1);
    const tmpFileName = `${wx.env.USER_DATA_PATH}/wasm/tmp/` + postfix;
    fs.writeFileSync(tmpFileName, fileData.buffer, "binary");

    let audioInfo = null;
    await new Promise((resolve, reject) => {
      audioContext.decodeAudioData(
        fileData.buffer,
        (audioBuffer) => {
          const metadata = {
            duration: audioBuffer.duration,
            sampleRate: audioBuffer.sampleRate,
            channelCount: audioBuffer.numberOfChannels,
          };
          resolve(metadata);
        },
        (err) => {
          reject(err);
        }
      );
    })
      .then((ret) => {
        audioInfo = _malloc(12);
        HEAPF32[audioInfo >> 2] = ret.duration;
        HEAPF32[(audioInfo + 4) >> 2] = ret.sampleRate;
        HEAPF32[(audioInfo + 8) >> 2] = ret.channelCount;
        fs.unlinkSync(tmpFileName);
      })
      .catch((err) => {
        throw err;
      });

    return audioInfo;
  });
}

//--------------------------------PTD Implementation-----------------------------------------
const PTD_ENGINE_STATE_UNDEFINED = 0;
const PTD_ENGINE_STATE_INITIALIZING = 1;
const PTD_ENGINE_STATE_INITIALIZED = 2;
const PTD_ENGINE_STATE_PREPARING = 3;
const PTD_ENGINE_STATE_PREPARED = 4;
const PTD_ENGINE_STATE_RENDER_READY = 5;
const PTD_ENGINE_STATE_DESTROYING = 6;
const PTD_ENGINE_STATE_DESTROYED = 7;

var WORKER_JS;
var WORKER_WASM;
var RENDER_WASM;
var total_decode_count = 0;
var total_decode_cost = 0;
var worker;
var workerDestroyed = false;
var workerStopped = false;

var SHARED_MEMORY_LENGTH;
const MIN_SHARED_MEMORY_LENGTH = 128 * 1024 * 1024;
var sharedMemory;
var sharedBuffer;
var videoResInfoVec;
var ptdStoragePath = "/tmp/ptd_engine";
var orgCwd;
var ptdEngineJSState = PTD_ENGINE_STATE_UNDEFINED;
var compressedMedias = {};
const AudioPlayerAssistant = require("audio_player_assistant.js");
var audioContext = null;
var audioPlayerAssistant = null;

function OnCatchExceptions(err) {
  audioPlayerAssistant.pause();
  workerStopped = true;
  if (Module['onPlayError']) {
    Module['onPlayError'](err);
  }
}

function PostMessageToWorker(message) {
  if (workerDestroyed || workerStopped) {
    return;
  }

  worker.postMessage(message);
}

var mainLoop = {
  loopParameters: { tickStartTime: 0, tickEndTime: 0, totalPlayTime: 0, totalRenderTime: 0, totalFrameCount: 0, fpsFrequencyTime: 0},
  performanceParameter: {enable:false, playTime:0, playFrameCount:0, renderTime:0},
  init: function() {
    mainLoop.loopParameters.tickStartTime = 0;
    mainLoop.loopParameters.tickEndTime = 0;
    mainLoop.loopParameters.totalPlayTime = 0;
    mainLoop.loopParameters.totalRenderTime = 0;
    mainLoop.loopParameters.totalFrameCount = 0;
    mainLoop.loopParameters.fpsFrequencyTime = 0;
    mainLoop.performanceParameter.playTime = 0;
    mainLoop.performanceParameter.playFrameCount = 0;
    mainLoop.performanceParameter.renderTime = 0;
  },
  runner: function (timeLine) {
    mainLoop.loopParameters.tickStartTime = _emscripten_get_now();

    let retDecoderInfos = Module.FetchDecoderInfos(true);
    if (retDecoderInfos.length > 0) {
      let cpyFrameData = new ArrayBuffer(retDecoderInfos.length);
      new Uint8Array(cpyFrameData).set(retDecoderInfos);
      PostMessageToWorker({
        msg: "createDecoders",
        decoderInfos: cpyFrameData,
      });
    }

    let genFrameContent = false;
    try {
      genFrameContent = wasmExports.Render(timeLine);
    } catch (e) {
      OnCatchExceptions(e.message);
      return -1;
    }

    let playProgress = wasmExports.GetCurrentProgress();
    if (Module['onPlayProgress']) {
      Module['onPlayProgress'](playProgress);
    }
    if (playProgress == audioPlayerAssistant.duration_us() && Module['onPlayFinish']) {
      if (mainLoop.performanceParameter.enable) {
        console.log("Play FPS average:", mainLoop.performanceParameter.playTime / mainLoop.performanceParameter.playFrameCount, ",Render FPS average:", mainLoop.performanceParameter.renderTime / mainLoop.performanceParameter.playFrameCount);
      }
      
      Module['onPlayFinish']();
    }
    
    let resumeDecoders = undefined;
    let rdRet = Module.BeginFetchResumeDecoders();
    if (rdRet.length > 0) {
      resumeDecoders = new ArrayBuffer(rdRet.byteLength);
      new Int32Array(resumeDecoders).set(rdRet);
      Module.EndFetchResumeDecoders();
    }

    let removeDecoders = undefined;
    let rmRet = Module.BeginFetchRemovedDecoders();
    if (rmRet.length > 0) {
      removeDecoders = new ArrayBuffer(rmRet.byteLength);
      new Int32Array(removeDecoders).set(rmRet);
      Module.EndFetchRemovedDecoders();
    }

    PostMessageToWorker({
      msg: "manipulateDecoder",
      resumeDecoders: resumeDecoders,
      removedDecoders: removeDecoders,
    });

    if (Module['renderFrameRate']) {
      if (genFrameContent) {
        ++mainLoop.loopParameters.totalFrameCount;
        ++mainLoop.performanceParameter.playFrameCount;
      } 

      var curTime = _emscripten_get_now();
      if (mainLoop.loopParameters.tickEndTime != 0) {    
        let deltaTime = curTime - mainLoop.loopParameters.tickEndTime;
        mainLoop.loopParameters.totalPlayTime += deltaTime;
        mainLoop.performanceParameter.playTime += deltaTime;
      }

      let deltaTime = curTime - mainLoop.loopParameters.tickStartTime;
      mainLoop.loopParameters.totalRenderTime += deltaTime;  
      mainLoop.performanceParameter.renderTime += deltaTime;

      if (curTime - mainLoop.loopParameters.fpsFrequencyTime > 100) {
        let result = Math.floor(1000 / mainLoop.loopParameters.totalPlayTime * mainLoop.loopParameters.totalFrameCount) + "-" + Math.floor(1000 / mainLoop.loopParameters.totalRenderTime * mainLoop.loopParameters.totalFrameCount);
        Module['renderFrameRate'](result);

        mainLoop.loopParameters.totalPlayTime = 0;
        mainLoop.loopParameters.totalRenderTime = 0;
        mainLoop.loopParameters.totalFrameCount = 0;

        mainLoop.loopParameters.fpsFrequencyTime = curTime;
      }      
    } 
    
    mainLoop.loopParameters.tickEndTime = _emscripten_get_now();
    return wasmExports.GetCurrentTime();
  }
};

function AddFrameData(length) {
  if (length > 0) {
    let framesData = _malloc(length);
    let framesDataView = new Uint8Array(wasmMemory.buffer, framesData, length);
    framesDataView.set(new Uint8Array(sharedBuffer, 0, length));
    wasmExports.AddFrameDatas(framesData, length);
    _free(framesData);

    let pausedDecoders = undefined;
    let pdRet = Module.BeginFetchPausedDecoders();
    if (pdRet.length > 0) {
      pausedDecoders = new ArrayBuffer(pdRet.byteLength);
      new Int32Array(pausedDecoders).set(pdRet);
      Module.EndFetchPausedDecoders();
    } 

    let removeDecoders = undefined;
    let rmRet = Module.BeginFetchRemovedDecoders();
    if (rmRet.length > 0) {
      removeDecoders = new ArrayBuffer(rmRet.byteLength);
      new Int32Array(removeDecoders).set(rmRet);
      Module.EndFetchRemovedDecoders();
    }

    PostMessageToWorker({
      msg: "manipulateDecoder",
      pausedDecoders: pausedDecoders,
      removedDecoders: removeDecoders,
    });
  }

  PostMessageToWorker({
    msg: "doDecode"
  });
}

function addResourcesCallback(event) {
  if (event.inputFileIndex != videoResInfoVec.size()) {
    addResourceInfos(event.inputFileIndex);
    return;
  }

  for (let i = 0; i < videoResInfoVec.size(); i++) {
    let fileName = videoResInfoVec.get(i);

    let node = null;
    try {
      let lookup = FS.lookupPath(fileName, { follow : false });
      node = lookup.node;
    } catch (e) {}
    if (!node) {
      continue;
    }

    if (FS.isDir(node.mode)) {
      for (let i in node.contents) {
        let subPath = fileName + "/" + node.contents[i].name;
        FS.unlink(subPath);
      }
    } else {
      FS.unlink(fileName);
    }
  }
  videoResInfoVec = null;

  let retDecoderInfos = Module.FetchDecoderInfos(false);
  let cpyFrameData = new ArrayBuffer(retDecoderInfos.length);
  new Uint8Array(cpyFrameData).set(retDecoderInfos);
  
  PostMessageToWorker({
    msg: "firstDecode",
    decoderInfos: cpyFrameData,
  });

  console.log("Begin decode first frame");
}

function EnableWorker(jsUrl) {
  if (worker) {
    return;
  }
  
  worker = wx.createWorker(jsUrl);
  worker.onMessage(function (e) {
    if (workerDestroyed || workerStopped) {
      return;
    }
    
    if (e.msg === "firstDecodeCallback") {
      console.log("Firt frame decode success, begin render");
      ptdEngineJSState = PTD_ENGINE_STATE_RENDER_READY;
      AddFrameData(e.length);
      mainLoop.init();
      total_decode_count = 0;
      total_decode_cost = 0;
      audioPlayerAssistant.prepareAudioPlayer(Module.GetAudioTimelineForWasmPlayer(), 
        wasmExports.GetCompositionFPS(),
        ()=>{
          console.log("[ptd_render]prepareAudioPlayer suc");
          if (Module['runTaskSuccessed']) {
            Module['runTaskSuccessed'](audioPlayerAssistant.duration_us());
          }
        },
        (err)=>{
          console.log("[ptd_render]prepareAudioPlayer fail");
          workerStopped = true;
          if (Module['runTaskFailed']) {
            Module['runTaskFailed'](err);
          }
        })
    } else if (e.msg === "push") {
      AddFrameData(e.length);
      if (e.length > 0 && audioPlayerAssistant) {
        audioPlayerAssistant.notifyRenderDataUpdated();
      }
    } else if (e.msg === "addResourcesCallback") {
      addResourcesCallback(e);
    } else if (e.msg === "workerInitialized") {
      console.log("Begin send video resources to worker");
      addResourceInfos(0);  
    } else if (e.msg === "cost") {
      if (e.deltaTime > 1) {
        total_decode_cost += e.deltaTime;
        ++total_decode_count;
        if (Module['decodeCost']) {
          Module['decodeCost'](Math.ceil(total_decode_cost / total_decode_count));

          if (total_decode_count > 5) {
            total_decode_count = 0;
            total_decode_cost = 0;
          }
        }
      }
    } else if (e.msg === "firstDecodeError") {
      workerStopped = true;
      if (Module['runTaskFailed']) {
        Module['runTaskFailed'](e.error);
      }
    } else if (e.msg === "reportError") {
      OnCatchExceptions(e.error);
    } 
  });
}

function addResourceInfos(fileIndex) {
  let fileDataOffset = 0;
  let fileNameArray = [];
  let fileDataLenArray = [];
  for (; fileIndex < videoResInfoVec.size(); fileIndex++) {
    let fileName = videoResInfoVec.get(fileIndex);

    let lookup = FS.lookupPath(fileName, { follow : false });
    let node = lookup.node;
    if (FS.isDir(node.mode)) {
      let subFilesSize = 0;
      for (let i in node.contents) {
        subFilesSize += node.contents[i].usedBytes;
      }

      if (fileDataOffset + subFilesSize > SHARED_MEMORY_LENGTH) {
        break;
      }   
      
      for (let i in node.contents) {
        let subPath = fileName + "/" + node.contents[i].name;
        let fileData = FS.readFile(subPath);

        let cpyFileData = new Uint8Array(sharedBuffer, fileDataOffset);
        cpyFileData.set(fileData);

        fileDataOffset += fileData.byteLength;
        fileDataLenArray.push(fileData.byteLength);
        fileNameArray.push(subPath);
      }
    } else {
      let fileData = FS.readFile(fileName);
      if (fileDataOffset + fileData.byteLength > SHARED_MEMORY_LENGTH) {
        break;
      }

      let cpyFileData = new Uint8Array(sharedBuffer, fileDataOffset);
      cpyFileData.set(fileData);

      fileDataOffset += fileData.byteLength;
      fileDataLenArray.push(fileData.byteLength);
      fileNameArray.push(fileName);
    }
  }

  PostMessageToWorker({
    msg: "addResources",
    inputFileNames: fileNameArray,
    inputFileLens: fileDataLenArray,
    intputFileIndex: fileIndex,
  });
}

function ClearEngineStroage(node) {
  for (let i in node.contents) {
      let subNode = node.contents[i];
      if (FS.isDir(subNode.mode)) {
          ClearEngineStroage(subNode);
          node.node_ops.rmdir(node, subNode.name);
      } else if (FS.isFile(subNode.mode)) {
          node.node_ops.unlink(node, subNode.name);
      } else {
          throw "Error File Type when clear engine strorage"
      }

      FS.destroyNode(subNode);
  }
}

function _NotifyEngineRunningState(state) {
  if (workerDestroyed) {
    throw new Error("Stop running task because ptd engine has destroyed.");
  }

  if (state === 3) {
    if (Module["runTaskSchedule"]) {
      Module["runTaskSchedule"](STATE_PREPARE_DECODER);
    }

    ptdEngineJSState = PTD_ENGINE_STATE_PREPARED;
    videoResInfoVec = Module.FetchVideoResourceInfos();

    let maxFileDataSize = 0;
    for (let i = 0; i < videoResInfoVec.size(); i++) {
      let fileName = videoResInfoVec.get(i);

      let lookup = FS.lookupPath(fileName, { follow : false });
      let node = lookup.node;
      let currentSize = 0 ;
      if (FS.isDir(node.mode)) {
        for (let i in node.contents) {
          currentSize += node.contents[i].usedBytes;
        }
      } else {
        currentSize = node.usedBytes;
      }

      if (currentSize > maxFileDataSize) {
        maxFileDataSize = currentSize;
      }
    }

    if (sharedMemory) {
      let preSharedMemoryLen = SHARED_MEMORY_LENGTH;
      SHARED_MEMORY_LENGTH = maxFileDataSize > MIN_SHARED_MEMORY_LENGTH? maxFileDataSize * 4 : MIN_SHARED_MEMORY_LENGTH;
      if (preSharedMemoryLen < SHARED_MEMORY_LENGTH) {
        sharedMemory = wx.createSharedArrayBuffer(SHARED_MEMORY_LENGTH);
        sharedBuffer = sharedMemory.buffer;
      } else {
        SHARED_MEMORY_LENGTH = preSharedMemoryLen;
      }
    } else {
      SHARED_MEMORY_LENGTH = maxFileDataSize > MIN_SHARED_MEMORY_LENGTH? maxFileDataSize * 4 : MIN_SHARED_MEMORY_LENGTH;
      sharedMemory = wx.createSharedArrayBuffer(SHARED_MEMORY_LENGTH);
      sharedBuffer = sharedMemory.buffer;
    }
    
    workerStopped = false;
    PostMessageToWorker({
      msg: "create",
      wasmUrl: WORKER_WASM,
      sharedMemory: sharedMemory,
    });
  } else if (state === 2) {
    if (Module["runTaskSchedule"]) {
      Module["runTaskSchedule"](STATE_BUILDING_TEMPLATE);
    }
  } else if (state === 1) {
    EnableWorker(WORKER_JS);
  }
}

async function DownloadComponentFiles() {
  // let filesInDir = [
  //   "cases/tasks/hello.json"
  // ];

  // let filesNeedDownload = {};
  // filesInDir.forEach((value, index) => {
  //   let key = "resources/" + value + ".bin";
  //   filesNeedDownload[key] = ptdStoragePath + "/" + value;
  // });

  let filesNeedDownload = {
    "/resources/cases/tasks/task.json.bin":ptdStoragePath + "/cases/tasks/task.json"
  };

  let downloadTasks = [];
  let downloadResults = [];
  var keys = Object.keys(filesNeedDownload);
  keys.forEach(function (key) {
    let task;
    if (key.includes("https")) {
      task = new Promise((resolve, reject) => {
        wx.request({
          url: key,
          responseType: 'arraybuffer',
          success:(result) => {
            resolve(result);
          },
          fail: (err) => {
            reject(err);
          }
       });
      });
    } else {
      task = new Promise((resolve, reject) => {
        const fs = wx.getFileSystemManager();
        fs.readFile({
          filePath: key,
          success:(result) => {
            resolve(result);
          },
          fail: (err) => {
            reject(err);
          }
       });
      });
    }
    
    downloadTasks.push(task);
    downloadResults.push(filesNeedDownload[key]);
  });

  await Promise.all(downloadTasks).then((values) => {
    out("Download files success");
    for (let i = 0; i < values.length; ++i) {
      let filePath = downloadResults[i];
      let pos = filePath.lastIndexOf("/");
      let dirPath = filePath.substring(0, pos);
      FS.mkdirTree(dirPath);

      let bufferView = new Uint8Array(values[i].data);
      FS.writeFile(filePath, bufferView);
    }
  });
}

function createWasm(onCreated, onError) {
  var info = { env: wasmImports, wasi_snapshot_preview1: wasmImports };
  async function receiveInstance(instance, module) {
    wasmExports = instance.exports;
    wasmExports = Asyncify.instrumentWasmExports(wasmExports);
    wasmMemory = wasmExports["memory"];
    updateMemoryViews();
    wasmTable = wasmExports["__indirect_function_table"];
    InitExportFunctions();
    addOnInit(wasmExports["__wasm_call_ctors"]);
    removeRunDependency("wasm-instantiate");

    onCreated();
  }

  addRunDependency("wasm-instantiate");

  WXWebAssembly.instantiate(RENDER_WASM, info).then(
    function (result) {
      try {
        receiveInstance(result["instance"], result["module"]);
      } catch (err) {
        onError(err);
      }
    }
  ).catch(err => {
    onError(err);
  });
}

const ImageCompressLimit = 1080;
function ProcessTask(task, compressImage, compressVideo, onSuccess, onError) {
  let runPromises = [];
  const fs = wx.getFileSystemManager();
  
  for (let key in task.video_sources_map) {
    if (task.video_sources_map.hasOwnProperty(key)) {
      runPromises.push(() => new Promise((resolve, reject) => {
        let value = task.video_sources_map[key];
        let fileUrl = value.url;
        let resolveRet = {"mapValue" : value, "fileUrl" : fileUrl};
        if (value.type === "image" && compressImage) {
          if (!compressedMedias.hasOwnProperty(fileUrl)) {
            wx.getImageInfo({
              src: fileUrl, 
              success:(imgInfo) => {
                if (Math.max(imgInfo.width, imgInfo.height) > ImageCompressLimit) {
                  let cmprWidth = undefined;
                  let cmprHeight = undefined;
                  if (imgInfo.width > imgInfo.height) {
                    cmprWidth = ImageCompressLimit;
                  } else {
                    cmprHeight = ImageCompressLimit;
                  }
  
                  wx.compressImage({
                    src: fileUrl, 
                    compressedWidth: cmprWidth,
                    compressedHeight: cmprHeight,
                    success:(result) => {
                      compressedMedias[fileUrl] = result.tempFilePath;
                      resolveRet.fileUrl = result.tempFilePath;
                      resolve(resolveRet);
                    },
                    fail: (err) => {
                      console.log(`wx.compressImage failed in ProcessTask function when access file:${fileUrl}, use original file to continue`);
                      resolve(resolveRet);
                    }
                  });
                } else {
                  resolve(resolveRet);
                }
              },
              fail: (err) => {
                console.log(`wx.getImageInfo failed in ProcessTask function when access file:${fileUrl}, use original file to continue`);
                resolve(resolveRet);
              }
            });
          } else {
            resolveRet.fileUrl = compressedMedias[fileUrl];
            resolve(resolveRet);
          }
        } else if (value.type === "video" && compressVideo) {
          wx.getVideoInfo({
            src: fileUrl, 
            success:(info) => {
              let maxSize = Math.max(info.width, info.height);
              if (maxSize > ImageCompressLimit) {
                wx.compressVideo({
                  src: fileUrl, 
                  quality: maxSize > 4 * ImageCompressLimit? "low" : "medium",
                  success:(result) => {
                    resolveRet.fileUrl = result.tempFilePath;
                    resolve(resolveRet);
                  },
                  fail: (err) => {
                    console.log(`wx.compressVideo failed in ProcessTask function when access file:${fileUrl}, use original file to continue`);
                    resolve(resolveRet);
                  }
                });
              } else {
                resolve(resolveRet);
              } 
            },
            fail: (err) => {
              console.log(`wx.getVideoInfo failed in ProcessTask function when access file:${fileUrl}, use original file to continue`);
              resolve(resolveRet);
            }
          });
        } else {
          resolve(resolveRet);
        }
      }));
    }
  }

  // 使用 Promise 链式调用处理每个任务
  let completedCount = 0; 
  runPromises.reduce((promiseChain, currentTask) => {
    return promiseChain.then(() => currentTask()).then(result => {
      if (workerDestroyed) {
        throw "Stop compressing videos because the ptd engine has destoryed."
      }

      try {
        const res = fs.readFileSync(result.fileUrl);
        let postfix = result.fileUrl.substring(result.fileUrl.lastIndexOf("."));
        result.mapValue.url = "/tmp/" + completedCount + postfix;
        writeMediaToFS(res, result.mapValue.url);
      } catch(e) {
        console.error(e)
      }
      
      if (++completedCount == runPromises.length) {
        onSuccess();
      }
    });
  }, Promise.resolve()).catch(err => {
    onError(err);
  });
};

function writeMediaToFS(fileData, filePath) {
  let pos = filePath.lastIndexOf("/");
  let dirPath = filePath.substring(0, pos);
  FS.mkdirTree(dirPath);

  let bufferView = new Uint8Array(fileData);
  FS.writeFile(filePath, bufferView);
}

//--------------------------JS Export Functions-----------------------------------------
const STATE_COMPRESS_INPUT_MEDIA = 1;
const STATE_DOWNLOAD_TEMPLATE_MATERIAL = 2;
const STATE_BUILDING_TEMPLATE = 3;
const STATE_PREPARE_DECODER = 4;

var dependenciesFulfilledBackup = null;
function initialize({enginePath, workersPath, canvas, testServer=false, success, fail}) {
  if (ptdEngineJSState === PTD_ENGINE_STATE_INITIALIZING) {
    fail("The ptd engine is in the process of initialization, please do not call this interface repeatedly.");
    return;
  }
  workerDestroyed = false;
  ptdEngineJSState = PTD_ENGINE_STATE_INITIALIZING;

  RENDER_WASM = enginePath + "/render_package/ptd_render.wasm.br";
  WORKER_JS = workersPath + "/ptd_decode.js";
  WORKER_WASM = enginePath + "/decode_package/ptd_decode.wasm.br";

  let runPromises = [];
  //加载解码WASM文件所在分包
  runPromises.push(new Promise((resolve, reject) => {
    require.async("../decode_package/index.js").then(pkg => {
      resolve(pkg);
    }).catch(({ errMsg, mod }) => {
      reject(errMsg);
    });
  }));

  if (wasmExports) {
    calledRun = false;
    dependenciesFulfilled = dependenciesFulfilledBackup;
    runtimeInitialized = false;
    Module = {};
    registeredTypes = {};
  } else {
    dependenciesFulfilledBackup = dependenciesFulfilled;
  }
  //加载RenderModuleWebassembly
  runPromises.push(new Promise((resolve, reject) => {
    createWasm(resolve, reject);
  }));
  
  Promise.all(runPromises).then((values) => {
    try {
      if (ptdEngineJSState === PTD_ENGINE_STATE_INITIALIZING && workerDestroyed) {
        ptdEngineJSState = PTD_ENGINE_STATE_UNDEFINED;
        fail("The ptd engine has destroyed.");
        return;
      }

      try {
        FS.mkdir(ptdStoragePath);
      } catch (e) {
        if (e.errno != 20) throw e;
      }
      orgCwd = FS.cwd();
      FS.chdir(ptdStoragePath);
  
      Module['canvas'] = canvas;
      wasmExports.Initialize(false, testServer);
      ptdEngineJSState = PTD_ENGINE_STATE_INITIALIZED;
    } catch (e) {
      throw e.message;
    }

    if (success) {
      success();
    }
  }).catch(err => {
    if (fail) {
      fail(err);
    }
  });
}

function prepare({task, compressImage = false, compressVideo = false, success, fail, schedule}) {
  if (ptdEngineJSState === PTD_ENGINE_STATE_PREPARING) {
    fail("The ptd engine is in the process of preparation, please do not call this interface repeatedly.");
    return;
  }

  ptdEngineJSState = PTD_ENGINE_STATE_PREPARING;

  if (!audioContext) {
    audioContext = wx.createWebAudioContext();
  }
  
  if (!audioPlayerAssistant) {
    audioPlayerAssistant = new AudioPlayerAssistant(audioContext, FS);
    audioPlayerAssistant.onStatusChanged = (preStatus, curStatus) => {
      console.log("audio player status changed, pre=", preStatus, ",cur=", curStatus);
    };
  }

  audioPlayerAssistant.initialize(mainLoop.runner);
  audioPlayerAssistant.pause(async () => {
    workerStopped = true;
    let lookup = FS.lookupPath(ptdStoragePath, { follow : false });
  let node = lookup.node;
  ClearEngineStroage(node);
  // await DownloadComponentFiles();

  if (schedule) {
    Module["runTaskSchedule"] = schedule;
    schedule(STATE_COMPRESS_INPUT_MEDIA);
  }

  ProcessTask(task, compressImage, compressVideo, 
    () => {
      try {
        if (workerDestroyed) {
          throw "Stop running task because the ptd engine has destoryed."
        }

        if (schedule) {
          schedule(STATE_DOWNLOAD_TEMPLATE_MATERIAL);
        }
        Module['runTaskSuccessed'] = success;
        Module['runTaskFailed'] = fail;
        let taskStr = stringToNewUTF8(JSON.stringify(task));
        wasmExports.RunTask(taskStr);
        _free(taskStr);
      } catch (e) {
        ptdEngineJSState = PTD_ENGINE_STATE_UNDEFINED;
        if (fail) {
          fail(e.message);
        }
      }
    }, 
    (err) => {
      ptdEngineJSState = PTD_ENGINE_STATE_UNDEFINED;
      if (fail) {
        fail(err);
      }
    });
  });
}

function initPlayer({onFinished, onProgress, onError, renderFrameRate, decodeCost}) {
  Module['onPlayFinish'] = onFinished;
  Module['onPlayProgress'] = onProgress;
  Module['onPlayError'] = onError;
  Module['renderFrameRate'] = renderFrameRate;
  Module['decodeCost'] = decodeCost;
}

function play() {
  audioPlayerAssistant.play();
}

function pause() {
  audioPlayerAssistant.pause();
}

function seekVideo(time) {
  wasmExports.Seek(audioPlayerAssistant.seekTo(time));
}

function destroy() {
  ptdEngineJSState = PTD_ENGINE_STATE_DESTROYING;

  FS.chdir(orgCwd);
  let lookup = FS.lookupPath(ptdStoragePath, { follow : false });
  let node = lookup.node;
  ClearEngineStroage(node);
  FS.rmdir(ptdStoragePath);

  audioPlayerAssistant.terminate(() => {
    if (ptdEngineJSState != PTD_ENGINE_STATE_DESTROYING) {
      return;
    }

    sharedBuffer = null;
    sharedMemory = null;
    compressedMedias = {};
    ptdEngineJSState = PTD_ENGINE_STATE_DESTROYED;

    workerDestroyed = true;
    worker.terminate();
    worker = null;
  
    try {
      wasmExports.Destroy();
    } catch(err) {
      console.error(err);
    }
  }) 
}

module.exports = {
  initialize,
  prepare,
  initPlayer,
  play,
  pause,
  seekVideo,
  destroy,
  STATE_COMPRESS_INPUT_MEDIA:STATE_COMPRESS_INPUT_MEDIA,
  STATE_DOWNLOAD_TEMPLATE_MATERIAL:STATE_DOWNLOAD_TEMPLATE_MATERIAL,
  STATE_BUILDING_TEMPLATE:STATE_BUILDING_TEMPLATE,
  STATE_PREPARE_DECODER:STATE_PREPARE_DECODER,
}
