occt-wasm bundle

var __defProp = Object.defineProperty;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __esm = (fn, res, err) => function __init() {
  if (err) throw err[0];
  try {
    return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
  } catch (e) {
    throw err = [e], e;
  }
};
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};

// dist/occt-wasm.js
var occt_wasm_exports = {};
__export(occt_wasm_exports, {
  default: () => occt_wasm_default
});
async function createOcctWasm(moduleArg = {}) {
  var moduleRtn;
  var Module = moduleArg;
  var ENVIRONMENT_IS_WEB = !!globalThis.window;
  var ENVIRONMENT_IS_WORKER = !!globalThis.WorkerGlobalScope;
  var ENVIRONMENT_IS_NODE = globalThis.process?.versions?.node && globalThis.process?.type != "renderer";
  if (ENVIRONMENT_IS_NODE) {
    const { createRequire } = await import(
      /* webpackIgnore: true */
      "node:module"
    );
    var require2 = createRequire(import.meta.url);
  }
  var arguments_ = [];
  var thisProgram = "./this.program";
  var quit_ = (status, toThrow) => {
    throw toThrow;
  };
  var _scriptName = import.meta.url;
  var scriptDirectory = "";
  function locateFile(path) {
    if (Module["locateFile"]) {
      return Module["locateFile"](path, scriptDirectory);
    }
    return scriptDirectory + path;
  }
  var readAsync, readBinary;
  if (ENVIRONMENT_IS_NODE) {
    var fs = require2("node:fs");
    if (_scriptName.startsWith("file:")) {
      scriptDirectory = require2("node:path").dirname(require2("node:url").fileURLToPath(_scriptName)) + "/";
    }
    readBinary = (filename) => {
      filename = isFileURI(filename) ? new URL(filename) : filename;
      var ret = fs.readFileSync(filename);
      return ret;
    };
    readAsync = async (filename, binary = true) => {
      filename = isFileURI(filename) ? new URL(filename) : filename;
      var ret = fs.readFileSync(filename, binary ? void 0 : "utf8");
      return ret;
    };
    if (process.argv.length > 1) {
      thisProgram = process.argv[1].replace(/\\/g, "/");
    }
    arguments_ = process.argv.slice(2);
    quit_ = (status, toThrow) => {
      process.exitCode = status;
      throw toThrow;
    };
  } else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
    try {
      scriptDirectory = new URL(".", _scriptName).href;
    } catch {
    }
    {
      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 = async (url) => {
        if (isFileURI(url)) {
          return new Promise((resolve, reject) => {
            var xhr = new XMLHttpRequest();
            xhr.open("GET", url, true);
            xhr.responseType = "arraybuffer";
            xhr.onload = () => {
              if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
                resolve(xhr.response);
                return;
              }
              reject(xhr.status);
            };
            xhr.onerror = reject;
            xhr.send(null);
          });
        }
        var response = await fetch(url, { credentials: "same-origin" });
        if (response.ok) {
          return response.arrayBuffer();
        }
        throw new Error(response.status + " : " + response.url);
      };
    }
  } else {
  }
  var out = console.log.bind(console);
  var err = console.error.bind(console);
  var wasmBinary;
  var ABORT = false;
  var EXITSTATUS;
  var isFileURI = (filename) => filename.startsWith("file://");
  var readyPromiseResolve, readyPromiseReject;
  var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;
  var HEAP64, HEAPU64;
  var runtimeInitialized = false;
  function updateMemoryViews() {
    var b = wasmMemory.buffer;
    HEAP8 = new Int8Array(b);
    HEAP16 = new Int16Array(b);
    HEAPU8 = new Uint8Array(b);
    HEAPU16 = new Uint16Array(b);
    Module["HEAP32"] = HEAP32 = new Int32Array(b);
    Module["HEAPU32"] = HEAPU32 = new Uint32Array(b);
    Module["HEAPF32"] = HEAPF32 = new Float32Array(b);
    HEAPF64 = new Float64Array(b);
    HEAP64 = new BigInt64Array(b);
    HEAPU64 = new BigUint64Array(b);
  }
  function preRun() {
    if (Module["preRun"]) {
      if (typeof Module["preRun"] == "function") Module["preRun"] = [Module["preRun"]];
      while (Module["preRun"].length) {
        addOnPreRun(Module["preRun"].shift());
      }
    }
    callRuntimeCallbacks(onPreRuns);
  }
  function initRuntime() {
    runtimeInitialized = true;
    if (!Module["noFSInit"] && !FS.initialized) FS.init();
    TTY.init();
    wasmExports["ba"]();
    FS.ignorePermissions = false;
  }
  function postRun() {
    if (Module["postRun"]) {
      if (typeof Module["postRun"] == "function") Module["postRun"] = [Module["postRun"]];
      while (Module["postRun"].length) {
        addOnPostRun(Module["postRun"].shift());
      }
    }
    callRuntimeCallbacks(onPostRuns);
  }
  function abort(what) {
    Module["onAbort"]?.(what);
    what = "Aborted(" + what + ")";
    err(what);
    ABORT = true;
    what += ". Build with -sASSERTIONS for more info.";
    if (runtimeInitialized) {
      ___trap();
    }
    var e = new WebAssembly.RuntimeError(what);
    readyPromiseReject?.(e);
    throw e;
  }
  var wasmBinaryFile;
  function findWasmBinary() {
    if (Module["locateFile"]) {
      return locateFile("occt-wasm.wasm");
    }
    return new URL("occt-wasm.wasm", import.meta.url).href;
  }
  function getBinarySync(file) {
    if (file == wasmBinaryFile && wasmBinary) {
      return new Uint8Array(wasmBinary);
    }
    if (readBinary) {
      return readBinary(file);
    }
    throw "both async and sync fetching of the wasm failed";
  }
  async function getWasmBinary(binaryFile) {
    if (!wasmBinary) {
      try {
        var response = await readAsync(binaryFile);
        return new Uint8Array(response);
      } catch {
      }
    }
    return getBinarySync(binaryFile);
  }
  async function instantiateArrayBuffer(binaryFile, imports) {
    try {
      var binary = await getWasmBinary(binaryFile);
      var instance = await WebAssembly.instantiate(binary, imports);
      return instance;
    } catch (reason) {
      err(`failed to asynchronously prepare wasm: ${reason}`);
      abort(reason);
    }
  }
  async function instantiateAsync(binary, binaryFile, imports) {
    if (!binary && !isFileURI(binaryFile) && !ENVIRONMENT_IS_NODE) {
      try {
        var response = fetch(binaryFile, { credentials: "same-origin" });
        var instantiationResult = await WebAssembly.instantiateStreaming(response, imports);
        return instantiationResult;
      } catch (reason) {
        err(`wasm streaming compile failed: ${reason}`);
        err("falling back to ArrayBuffer instantiation");
      }
    }
    return instantiateArrayBuffer(binaryFile, imports);
  }
  function getWasmImports() {
    var imports = { a: wasmImports };
    return imports;
  }
  async function createWasm() {
    function receiveInstance(instance, module) {
      wasmExports = instance.exports;
      wasmExports = applySignatureConversions(wasmExports);
      assignWasmExports(wasmExports);
      updateMemoryViews();
      return wasmExports;
    }
    function receiveInstantiationResult(result2) {
      return receiveInstance(result2["instance"]);
    }
    var info = getWasmImports();
    if (Module["instantiateWasm"]) {
      return new Promise((resolve, reject) => {
        Module["instantiateWasm"](info, (inst, mod) => {
          resolve(receiveInstance(inst, mod));
        });
      });
    }
    wasmBinaryFile ??= findWasmBinary();
    var result = await instantiateAsync(wasmBinary, wasmBinaryFile, info);
    var exports = receiveInstantiationResult(result);
    return exports;
  }
  class ExitStatus {
    name = "ExitStatus";
    constructor(status) {
      this.message = `Program terminated with exit(${status})`;
      this.status = status;
    }
  }
  var callRuntimeCallbacks = (callbacks) => {
    while (callbacks.length > 0) {
      callbacks.shift()(Module);
    }
  };
  var onPostRuns = [];
  var addOnPostRun = (cb) => onPostRuns.push(cb);
  var onPreRuns = [];
  var addOnPreRun = (cb) => onPreRuns.push(cb);
  var noExitRuntime = true;
  var INT53_MAX = 9007199254740992;
  var INT53_MIN = -9007199254740992;
  var bigintToI53Checked = (num) => num < INT53_MIN || num > INT53_MAX ? NaN : Number(num);
  var wasmTableMirror = [];
  var getWasmTableEntry = (funcPtr) => {
    var func = wasmTableMirror[funcPtr];
    if (!func) {
      wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr);
    }
    return func;
  };
  function ___call_sighandler(fp, sig) {
    fp >>>= 0;
    return getWasmTableEntry(fp)(sig);
  }
  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.slice(-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.slice(0, -1);
    }
    return root + dir;
  }, basename: (path) => path && path.match(/([^\/]+|\/)\/*$/)[1], join: (...paths) => PATH.normalize(paths.join("/")), join2: (l, r) => PATH.normalize(l + "/" + r) };
  var initRandomFill = () => {
    if (ENVIRONMENT_IS_NODE) {
      var nodeCrypto = require2("node:crypto");
      return (view) => nodeCrypto.randomFillSync(view);
    }
    return (view) => crypto.getRandomValues(view);
  };
  var randomFill = (view) => {
    (randomFill = initRandomFill())(view);
  };
  var PATH_FS = { resolve: (...args) => {
    var resolvedPath = "", resolvedAbsolute = false;
    for (var i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) {
      var path = i >= 0 ? args[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).slice(1);
    to = PATH_FS.resolve(to).slice(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 UTF8Decoder = globalThis.TextDecoder && new TextDecoder();
  var findStringEnd = (heapOrArray, idx, maxBytesToRead, ignoreNul) => {
    var maxIdx = idx + maxBytesToRead;
    if (ignoreNul) return maxIdx;
    while (heapOrArray[idx] && !(idx >= maxIdx)) ++idx;
    return idx;
  };
  var UTF8ArrayToString = (heapOrArray, idx = 0, maxBytesToRead, ignoreNul) => {
    idx >>>= 0;
    var endPtr = findStringEnd(heapOrArray, idx, maxBytesToRead, ignoreNul);
    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 {
        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 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) => {
    outIdx >>>= 0;
    if (!(maxBytesToWrite > 0)) return 0;
    var startIdx = outIdx;
    var endIdx = outIdx + maxBytesToWrite - 1;
    for (var i = 0; i < str.length; ++i) {
      var u = str.codePointAt(i);
      if (u <= 127) {
        if (outIdx >= endIdx) break;
        heap[outIdx++ >>> 0] = u;
      } else if (u <= 2047) {
        if (outIdx + 1 >= endIdx) break;
        heap[outIdx++ >>> 0] = 192 | u >> 6;
        heap[outIdx++ >>> 0] = 128 | u & 63;
      } else if (u <= 65535) {
        if (outIdx + 2 >= endIdx) break;
        heap[outIdx++ >>> 0] = 224 | u >> 12;
        heap[outIdx++ >>> 0] = 128 | u >> 6 & 63;
        heap[outIdx++ >>> 0] = 128 | u & 63;
      } else {
        if (outIdx + 3 >= endIdx) break;
        heap[outIdx++ >>> 0] = 240 | u >> 18;
        heap[outIdx++ >>> 0] = 128 | u >> 12 & 63;
        heap[outIdx++ >>> 0] = 128 | u >> 6 & 63;
        heap[outIdx++ >>> 0] = 128 | u & 63;
        i++;
      }
    }
    heap[outIdx >>> 0] = 0;
    return outIdx - startIdx;
  };
  var 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, 0, BUFSIZE);
        } catch (e) {
          if (e.toString().includes("EOF")) bytesRead = 0;
          else throw e;
        }
        if (bytesRead > 0) {
          result = buf.slice(0, bytesRead).toString("utf-8");
        }
      } else if (globalThis.window?.prompt) {
        result = window.prompt("Input: ");
        if (result !== null) {
          result += "\n";
        }
      } else {
      }
      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 };
    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 === void 0 && bytesRead === 0) {
        throw new FS.ErrnoError(6);
      }
      if (result === null || result === void 0) break;
      bytesRead++;
      buffer[offset + i] = result;
    }
    if (bytesRead) {
      stream.node.atime = 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.mtime = stream.node.ctime = 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));
      tty.output = [];
    } else {
      if (val != 0) tty.output.push(val);
    }
  }, fsync(tty) {
    if (tty.output?.length > 0) {
      out(UTF8ArrayToString(tty.output));
      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));
      tty.output = [];
    } else {
      if (val != 0) tty.output.push(val);
    }
  }, fsync(tty) {
    if (tty.output?.length > 0) {
      err(UTF8ArrayToString(tty.output));
      tty.output = [];
    }
  } } };
  var mmapAlloc = (size) => {
    abort();
  };
  var MEMFS = { ops_table: null, mount(mount) {
    return MEMFS.createNode(null, "/", 16895, 0);
  }, createNode(parent, name, mode, dev) {
    if (FS.isBlkdev(mode) || FS.isFIFO(mode)) {
      throw new FS.ErrnoError(63);
    }
    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, 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 = MEMFS.emptyFileContents ??= new Uint8Array(0);
    } 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.atime = node.mtime = node.ctime = Date.now();
    if (parent) {
      parent.contents[name] = node;
      parent.atime = parent.mtime = parent.ctime = node.atime;
    }
    return node;
  }, getFileDataAsTypedArray(node) {
    return node.contents.subarray(0, node.usedBytes);
  }, expandFileStorage(node, newCapacity) {
    var prevCapacity = node.contents.length;
    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) newCapacity = Math.max(newCapacity, 256);
    var oldContents = MEMFS.getFileDataAsTypedArray(node);
    node.contents = new Uint8Array(newCapacity);
    node.contents.set(oldContents);
  }, resizeFileStorage(node, newSize) {
    if (node.usedBytes == newSize) return;
    var oldContents = node.contents;
    node.contents = new Uint8Array(newSize);
    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.atime);
    attr.mtime = new Date(node.mtime);
    attr.ctime = new Date(node.ctime);
    attr.blksize = 4096;
    attr.blocks = Math.ceil(attr.size / attr.blksize);
    return attr;
  }, setattr(node, attr) {
    for (const key of ["mode", "atime", "mtime", "ctime"]) {
      if (attr[key] != null) {
        node[key] = attr[key];
      }
    }
    if (attr.size !== void 0) {
      MEMFS.resizeFileStorage(node, attr.size);
    }
  }, lookup(parent, name) {
    if (!MEMFS.doesNotExistError) {
      MEMFS.doesNotExistError = new FS.ErrnoError(44);
      MEMFS.doesNotExistError.stack = "<generic error, no stack>";
    }
    throw MEMFS.doesNotExistError;
  }, mknod(parent, name, mode, dev) {
    return MEMFS.createNode(parent, name, mode, dev);
  }, rename(old_node, new_dir, new_name) {
    var new_node;
    try {
      new_node = FS.lookupNode(new_dir, new_name);
    } catch (e) {
    }
    if (new_node) {
      if (FS.isDir(old_node.mode)) {
        for (var i in new_node.contents) {
          throw new FS.ErrnoError(55);
        }
      }
      FS.hashRemoveNode(new_node);
    }
    delete old_node.parent.contents[old_node.name];
    new_dir.contents[new_name] = old_node;
    old_node.name = new_name;
    new_dir.ctime = new_dir.mtime = old_node.parent.ctime = old_node.parent.mtime = Date.now();
  }, unlink(parent, name) {
    delete parent.contents[name];
    parent.ctime = parent.mtime = 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.ctime = parent.mtime = Date.now();
  }, readdir(node) {
    return [".", "..", ...Object.keys(node.contents)];
  }, 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);
    buffer.set(contents.subarray(position, position + size), offset);
    return size;
  }, write(stream, buffer, offset, length, position, canOwn) {
    if (buffer.buffer === HEAP8.buffer) {
      canOwn = false;
    }
    if (!length) return 0;
    var node = stream.node;
    node.mtime = node.ctime = Date.now();
    if (canOwn) {
      node.contents = buffer.subarray(offset, offset + length);
      node.usedBytes = length;
    } else if (node.usedBytes === 0 && position === 0) {
      node.contents = buffer.slice(offset, offset + length);
      node.usedBytes = length;
    } else {
      MEMFS.expandFileStorage(node, position + length);
      node.contents.set(buffer.subarray(offset, offset + length), position);
      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;
  }, 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 {
      allocated = true;
      ptr = mmapAlloc(length);
      if (!ptr) {
        throw new FS.ErrnoError(48);
      }
      if (contents) {
        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);
          }
        }
        HEAP8.set(contents, ptr >>> 0);
      }
    }
    return { ptr, allocated };
  }, msync(stream, buffer, offset, length, mmapFlags) {
    MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false);
    return 0;
  } } };
  var FS_modeStringToFlags = (str) => {
    if (typeof str != "string") return 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_fileDataToTypedArray = (data) => {
    if (typeof data == "string") {
      data = intArrayFromString(data, true);
    }
    if (!data.subarray) {
      data = new Uint8Array(data);
    }
    return data;
  };
  var FS_getMode = (canRead, canWrite) => {
    var mode = 0;
    if (canRead) mode |= 292 | 73;
    if (canWrite) mode |= 146;
    return mode;
  };
  var asyncLoad = async (url) => {
    var arrayBuffer = await readAsync(url);
    return new Uint8Array(arrayBuffer);
  };
  var FS_createDataFile = (...args) => FS.createDataFile(...args);
  var getUniqueRunDependency = (id) => id;
  var runDependencies = 0;
  var dependenciesFulfilled = null;
  var removeRunDependency = (id) => {
    runDependencies--;
    Module["monitorRunDependencies"]?.(runDependencies);
    if (runDependencies == 0) {
      if (dependenciesFulfilled) {
        var callback = dependenciesFulfilled;
        dependenciesFulfilled = null;
        callback();
      }
    }
  };
  var addRunDependency = (id) => {
    runDependencies++;
    Module["monitorRunDependencies"]?.(runDependencies);
  };
  var preloadPlugins = [];
  var FS_handledByPreloadPlugin = async (byteArray, fullname) => {
    if (typeof Browser != "undefined") Browser.init();
    for (var plugin of preloadPlugins) {
      if (plugin["canHandle"](fullname)) {
        return plugin["handle"](byteArray, fullname);
      }
    }
    return byteArray;
  };
  var FS_preloadFile = async (parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish) => {
    var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent;
    var dep = getUniqueRunDependency(`cp ${fullname}`);
    addRunDependency(dep);
    try {
      var byteArray = url;
      if (typeof url == "string") {
        byteArray = await asyncLoad(url);
      }
      byteArray = await FS_handledByPreloadPlugin(byteArray, fullname);
      preFinish?.();
      if (!dontCreateFile) {
        FS_createDataFile(parent, name, byteArray, canRead, canWrite, canOwn);
      }
    } finally {
      removeRunDependency(dep);
    }
  };
  var FS_createPreloadedFile = (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) => {
    FS_preloadFile(parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish).then(onload).catch(onerror);
  };
  var FS = { root: null, mounts: [], devices: {}, streams: [], nextInode: 1, nameTable: null, currentPath: "/", initialized: false, ignorePermissions: true, filesystems: null, syncFSRequests: 0, ErrnoError: class {
    name = "ErrnoError";
    constructor(errno) {
      this.errno = errno;
    }
  }, FSStream: class {
    shared = {};
    get object() {
      return this.node;
    }
    set object(val) {
      this.node = val;
    }
    get isRead() {
      return (this.flags & 2097155) !== 1;
    }
    get isWrite() {
      return (this.flags & 2097155) !== 0;
    }
    get isAppend() {
      return this.flags & 1024;
    }
    get flags() {
      return this.shared.flags;
    }
    set flags(val) {
      this.shared.flags = val;
    }
    get position() {
      return this.shared.position;
    }
    set position(val) {
      this.shared.position = val;
    }
  }, FSNode: class {
    node_ops = {};
    stream_ops = {};
    readMode = 292 | 73;
    writeMode = 146;
    mounted = null;
    constructor(parent, name, mode, rdev) {
      if (!parent) {
        parent = this;
      }
      this.parent = parent;
      this.mount = parent.mount;
      this.id = FS.nextInode++;
      this.name = name;
      this.mode = mode;
      this.rdev = rdev;
      this.atime = this.mtime = this.ctime = Date.now();
    }
    get read() {
      return (this.mode & this.readMode) === this.readMode;
    }
    set read(val) {
      val ? this.mode |= this.readMode : this.mode &= ~this.readMode;
    }
    get write() {
      return (this.mode & this.writeMode) === this.writeMode;
    }
    set write(val) {
      val ? this.mode |= this.writeMode : this.mode &= ~this.writeMode;
    }
    get isFolder() {
      return FS.isDir(this.mode);
    }
    get isDevice() {
      return FS.isChrdev(this.mode);
    }
  }, lookupPath(path, opts = {}) {
    if (!path) {
      throw new FS.ErrnoError(44);
    }
    opts.follow_mount ??= true;
    if (!PATH.isAbs(path)) {
      path = FS.cwd() + "/" + path;
    }
    linkloop: for (var nlinks = 0; nlinks < 40; nlinks++) {
      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;
        }
        if (parts[i] === ".") {
          continue;
        }
        if (parts[i] === "..") {
          current_path = PATH.dirname(current_path);
          if (FS.isRoot(current)) {
            path = current_path + "/" + parts.slice(i + 1).join("/");
            nlinks--;
            continue linkloop;
          } else {
            current = current.parent;
          }
          continue;
        }
        current_path = PATH.join2(current_path, parts[i]);
        try {
          current = FS.lookupNode(current, parts[i]);
        } catch (e) {
          if (e?.errno === 44 && islast && opts.noent_okay) {
            return { path: current_path };
          }
          throw e;
        }
        if (FS.isMountpoint(current) && (!islast || opts.follow_mount)) {
          current = current.mounted.root;
        }
        if (FS.isLink(current.mode) && (!islast || opts.follow)) {
          if (!current.node_ops.readlink) {
            throw new FS.ErrnoError(52);
          }
          var link = current.node_ops.readlink(current);
          if (!PATH.isAbs(link)) {
            link = PATH.dirname(current_path) + "/" + link;
          }
          path = link + "/" + parts.slice(i + 1).join("/");
          continue linkloop;
        }
      }
      return { path: current_path, node: current };
    }
    throw new FS.ErrnoError(32);
  }, 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);
    }
    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) {
    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;
    }
    if (perms.includes("w") && !(node.mode & 146)) {
      return 2;
    }
    if (perms.includes("x") && !(node.mode & 73)) {
      return 2;
    }
    return 0;
  }, mayLookup(dir) {
    if (!FS.isDir(dir.mode)) return 54;
    var errCode = FS.nodePermissions(dir, "x");
    if (errCode) return errCode;
    if (!dir.node_ops.lookup) return 2;
    return 0;
  }, mayCreate(dir, name) {
    if (!FS.isDir(dir.mode)) {
      return 54;
    }
    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;
    }
    var mode = FS.flagsToPermissionString(flags);
    if (FS.isDir(node.mode)) {
      if (mode !== "r" || flags & (512 | 64)) {
        return 31;
      }
    }
    return FS.nodePermissions(node, mode);
  }, checkOpExists(op, err2) {
    if (!op) {
      throw new FS.ErrnoError(err2);
    }
    return op;
  }, 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) {
    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;
  }, dupStream(origStream, fd = -1) {
    var stream = FS.createStream(origStream, fd);
    stream.stream_ops?.dup?.(stream);
    return stream;
  }, doSetAttr(stream, node, attr) {
    var setattr = stream?.stream_ops.setattr;
    var arg = setattr ? stream : node;
    setattr ??= node.node_ops.setattr;
    FS.checkOpExists(setattr, 63);
    setattr(arg, attr);
  }, chrdev_stream_ops: { open(stream) {
    var device = FS.getDevice(stream.node.rdev);
    stream.stream_ops = device.stream_ops;
    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(...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) {
      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);
      }
    }
    for (var mount of mounts) {
      if (mount.type.syncfs) {
        mount.type.syncfs(mount, populate, done);
      } else {
        done(null);
      }
    }
  }, mount(type, opts, mountpoint) {
    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, opts, 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);
    for (var [hash, current] of Object.entries(FS.nameTable)) {
      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);
    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) {
      throw new FS.ErrnoError(28);
    }
    if (name === "." || name === "..") {
      throw new FS.ErrnoError(20);
    }
    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);
  }, statfs(path) {
    return FS.statfsNode(FS.lookupPath(path, { follow: true }).node);
  }, statfsStream(stream) {
    return FS.statfsNode(stream.node);
  }, statfsNode(node) {
    var rtn = { bsize: 4096, frsize: 4096, blocks: 1e6, bfree: 5e5, bavail: 5e5, files: FS.nextInode, ffree: FS.nextInode - 1, fsid: 42, flags: 2, namelen: 255 };
    if (node.node_ops.statfs) {
      Object.assign(rtn, node.node_ops.statfs(node.mount.opts.root));
    }
    return rtn;
  }, create(path, mode = 438) {
    mode &= 4095;
    mode |= 32768;
    return FS.mknod(path, mode, 0);
  }, mkdir(path, mode = 511) {
    mode &= 511 | 512;
    mode |= 16384;
    return FS.mknod(path, mode, 0);
  }, mkdirTree(path, mode) {
    var dirs = path.split("/");
    var d = "";
    for (var dir of dirs) {
      if (!dir) continue;
      if (d || PATH.isAbs(path)) d += "/";
      d += dir;
      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);
      old_node.parent = new_dir;
    } 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;
    var readdir = FS.checkOpExists(node.node_ops.readdir, 54);
    return 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 link.node_ops.readlink(link);
  }, stat(path, dontFollow) {
    var lookup = FS.lookupPath(path, { follow: !dontFollow });
    var node = lookup.node;
    var getattr = FS.checkOpExists(node.node_ops.getattr, 63);
    return getattr(node);
  }, fstat(fd) {
    var stream = FS.getStreamChecked(fd);
    var node = stream.node;
    var getattr = stream.stream_ops.getattr;
    var arg = getattr ? stream : node;
    getattr ??= node.node_ops.getattr;
    FS.checkOpExists(getattr, 63);
    return getattr(arg);
  }, lstat(path) {
    return FS.stat(path, true);
  }, doChmod(stream, node, mode, dontFollow) {
    FS.doSetAttr(stream, node, { mode: mode & 4095 | node.mode & ~4095, ctime: Date.now(), dontFollow });
  }, chmod(path, mode, dontFollow) {
    var node;
    if (typeof path == "string") {
      var lookup = FS.lookupPath(path, { follow: !dontFollow });
      node = lookup.node;
    } else {
      node = path;
    }
    FS.doChmod(null, node, mode, dontFollow);
  }, lchmod(path, mode) {
    FS.chmod(path, mode, true);
  }, fchmod(fd, mode) {
    var stream = FS.getStreamChecked(fd);
    FS.doChmod(stream, stream.node, mode, false);
  }, doChown(stream, node, dontFollow) {
    FS.doSetAttr(stream, node, { timestamp: Date.now(), dontFollow });
  }, chown(path, uid, gid, dontFollow) {
    var node;
    if (typeof path == "string") {
      var lookup = FS.lookupPath(path, { follow: !dontFollow });
      node = lookup.node;
    } else {
      node = path;
    }
    FS.doChown(null, node, dontFollow);
  }, lchown(path, uid, gid) {
    FS.chown(path, uid, gid, true);
  }, fchown(fd, uid, gid) {
    var stream = FS.getStreamChecked(fd);
    FS.doChown(stream, stream.node, false);
  }, doTruncate(stream, node, len) {
    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);
    }
    FS.doSetAttr(stream, node, { size: len, timestamp: Date.now() });
  }, 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;
    }
    FS.doTruncate(null, node, len);
  }, ftruncate(fd, len) {
    var stream = FS.getStreamChecked(fd);
    if (len < 0 || (stream.flags & 2097155) === 0) {
      throw new FS.ErrnoError(28);
    }
    FS.doTruncate(stream, stream.node, len);
  }, utime(path, atime, mtime) {
    var lookup = FS.lookupPath(path, { follow: true });
    var node = lookup.node;
    var setattr = FS.checkOpExists(node.node_ops.setattr, 63);
    setattr(node, { atime, mtime });
  }, open(path, flags, mode = 438) {
    if (path === "") {
      throw new FS.ErrnoError(44);
    }
    flags = FS_modeStringToFlags(flags);
    if (flags & 64) {
      mode = mode & 4095 | 32768;
    } else {
      mode = 0;
    }
    var node;
    var isDirPath;
    if (typeof path == "object") {
      node = path;
    } else {
      isDirPath = path.endsWith("/");
      var lookup = FS.lookupPath(path, { follow: !(flags & 131072), noent_okay: true });
      node = lookup.node;
      path = lookup.path;
    }
    var created = false;
    if (flags & 64) {
      if (node) {
        if (flags & 128) {
          throw new FS.ErrnoError(20);
        }
      } else if (isDirPath) {
        throw new FS.ErrnoError(31);
      } else {
        node = FS.mknod(path, mode | 511, 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, path: FS.getPath(node), flags, seekable: true, position: 0, stream_ops: node.stream_ops, ungotten: [], error: false });
    if (stream.stream_ops.open) {
      stream.stream_ops.open(stream);
    }
    if (created) {
      FS.chmod(node, mode & 511);
    }
    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) {
    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) {
    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;
  }, 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);
    }
    if (!length) {
      throw new FS.ErrnoError(28);
    }
    return stream.stream_ops.mmap(stream, length, position, prot, flags);
  }, msync(stream, buffer, offset, length, mmapFlags) {
    if (!stream.stream_ops.msync) {
      return 0;
    }
    return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags);
  }, 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") {
      abort(`Invalid encoding type "${opts.encoding}"`);
    }
    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") {
      buf = UTF8ArrayToString(buf);
    }
    FS.close(stream);
    return buf;
  }, writeFile(path, data, opts = {}) {
    opts.flags = opts.flags || 577;
    var stream = FS.open(path, opts.flags, opts.mode);
    data = FS_fileDataToTypedArray(data);
    FS.write(stream, data, 0, data.byteLength, void 0, opts.canOwn);
    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, llseek: () => 0 });
    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) {
        randomFill(randomBuffer);
        randomLeft = 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", 16895, 73);
      node.stream_ops = { llseek: MEMFS.stream_ops.llseek };
      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 }, id: fd + 1 };
        ret.parent = ret;
        return ret;
      }, readdir() {
        return Array.from(FS.streams.entries()).filter(([k, v2]) => v2).map(([k, v2]) => k.toString());
      } };
      return node;
    } }, {}, "/proc/self/fd");
  }, createStandardStreams(input, output, error) {
    if (input) {
      FS.createDevice("/dev", "stdin", input);
    } else {
      FS.symlink("/dev/tty", "/dev/stdin");
    }
    if (output) {
      FS.createDevice("/dev", "stdout", null, output);
    } else {
      FS.symlink("/dev/tty", "/dev/stdout");
    }
    if (error) {
      FS.createDevice("/dev", "stderr", null, error);
    } 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);
  }, staticInit() {
    FS.nameTable = new Array(4096);
    FS.mount(MEMFS, {}, "/");
    FS.createDefaultDirectories();
    FS.createDefaultDevices();
    FS.createSpecialDirectories();
    FS.filesystems = { MEMFS };
  }, init(input, output, error) {
    FS.initialized = true;
    input ??= Module["stdin"];
    output ??= Module["stdout"];
    error ??= Module["stderr"];
    FS.createStandardStreams(input, output, error);
  }, quit() {
    FS.initialized = false;
    for (var stream of FS.streams) {
      if (stream) {
        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) {
        if (e.errno != 20) throw 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) {
      data = FS_fileDataToTypedArray(data);
      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);
    }
  }, createDevice(parent, name, input, output) {
    var path = PATH.join2(typeof parent == "string" ? parent : FS.getPath(parent), name);
    var mode = FS_getMode(!!input, !!output);
    FS.createDevice.major ??= 64;
    var dev = FS.makedev(FS.createDevice.major++, 0);
    FS.registerDevice(dev, { open(stream) {
      stream.seekable = false;
    }, close(stream) {
      if (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 === void 0 && bytesRead === 0) {
          throw new FS.ErrnoError(6);
        }
        if (result === null || result === void 0) break;
        bytesRead++;
        buffer[offset + i] = result;
      }
      if (bytesRead) {
        stream.node.atime = 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.mtime = stream.node.ctime = Date.now();
      }
      return i;
    } });
    return FS.mkdev(path, mode, dev);
  }, forceLoadFile(obj) {
    if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true;
    if (globalThis.XMLHttpRequest) {
      abort("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 {
      try {
        obj.contents = readBinary(obj.url);
      } catch (e) {
        throw new FS.ErrnoError(29);
      }
    }
  }, createLazyFile(parent, name, url, canRead, canWrite) {
    class LazyUint8Array {
      lengthKnown = false;
      chunks = [];
      get(idx) {
        if (idx > this.length - 1 || idx < 0) {
          return void 0;
        }
        var chunkOffset = idx % this.chunkSize;
        var chunkNum = idx / this.chunkSize | 0;
        return this.getter(chunkNum)[chunkOffset];
      }
      setDataGetter(getter) {
        this.getter = getter;
      }
      cacheLength() {
        var xhr = new XMLHttpRequest();
        xhr.open("HEAD", url, false);
        xhr.send(null);
        if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) abort("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) abort("invalid range (" + from + ", " + to + ") or no bytes requested!");
          if (to > datalength - 1) abort("only " + datalength + " bytes available! programmer error!");
          var xhr2 = new XMLHttpRequest();
          xhr2.open("GET", url, false);
          if (datalength !== chunkSize) xhr2.setRequestHeader("Range", "bytes=" + from + "-" + to);
          xhr2.responseType = "arraybuffer";
          if (xhr2.overrideMimeType) {
            xhr2.overrideMimeType("text/plain; charset=x-user-defined");
          }
          xhr2.send(null);
          if (!(xhr2.status >= 200 && xhr2.status < 300 || xhr2.status === 304)) abort("Couldn't load " + url + ". Status: " + xhr2.status);
          if (xhr2.response !== void 0) {
            return new Uint8Array(xhr2.response || []);
          }
          return intArrayFromString(xhr2.responseText || "", true);
        };
        var lazyArray2 = this;
        lazyArray2.setDataGetter((chunkNum) => {
          var start = chunkNum * chunkSize;
          var end = (chunkNum + 1) * chunkSize - 1;
          end = Math.min(end, datalength - 1);
          if (typeof lazyArray2.chunks[chunkNum] == "undefined") {
            lazyArray2.chunks[chunkNum] = doXHR(start, end);
          }
          if (typeof lazyArray2.chunks[chunkNum] == "undefined") abort("doXHR failed!");
          return lazyArray2.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;
      }
      get length() {
        if (!this.lengthKnown) {
          this.cacheLength();
        }
        return this._length;
      }
      get chunkSize() {
        if (!this.lengthKnown) {
          this.cacheLength();
        }
        return this._chunkSize;
      }
    }
    if (globalThis.XMLHttpRequest) {
      if (!ENVIRONMENT_IS_WORKER) abort("Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc");
      var lazyArray = new LazyUint8Array();
      var properties = { isDevice: false, contents: lazyArray };
    } else {
      var properties = { isDevice: false, 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 = {};
    for (const [key, fn] of Object.entries(node.stream_ops)) {
      stream_ops[key] = (...args) => {
        FS.forceLoadFile(node);
        return fn(...args);
      };
    }
    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);
      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, allocated: true };
    };
    node.stream_ops = stream_ops;
    return node;
  } };
  var UTF8ToString = (ptr, maxBytesToRead, ignoreNul) => {
    ptr >>>= 0;
    return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead, ignoreNul) : "";
  };
  var SYSCALLS = { 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 dir + "/" + path;
  }, writeStat(buf, stat) {
    HEAPU32[buf >>> 2 >>> 0] = stat.dev;
    HEAPU32[buf + 4 >>> 2 >>> 0] = stat.mode;
    HEAPU32[buf + 8 >>> 2 >>> 0] = stat.nlink;
    HEAPU32[buf + 12 >>> 2 >>> 0] = stat.uid;
    HEAPU32[buf + 16 >>> 2 >>> 0] = stat.gid;
    HEAPU32[buf + 20 >>> 2 >>> 0] = stat.rdev;
    HEAP64[buf + 24 >>> 3 >>> 0] = BigInt(stat.size);
    HEAP32[buf + 32 >>> 2 >>> 0] = 4096;
    HEAP32[buf + 36 >>> 2 >>> 0] = stat.blocks;
    var atime = stat.atime.getTime();
    var mtime = stat.mtime.getTime();
    var ctime = stat.ctime.getTime();
    HEAP64[buf + 40 >>> 3 >>> 0] = BigInt(Math.floor(atime / 1e3));
    HEAPU32[buf + 48 >>> 2 >>> 0] = atime % 1e3 * 1e3 * 1e3;
    HEAP64[buf + 56 >>> 3 >>> 0] = BigInt(Math.floor(mtime / 1e3));
    HEAPU32[buf + 64 >>> 2 >>> 0] = mtime % 1e3 * 1e3 * 1e3;
    HEAP64[buf + 72 >>> 3 >>> 0] = BigInt(Math.floor(ctime / 1e3));
    HEAPU32[buf + 80 >>> 2 >>> 0] = ctime % 1e3 * 1e3 * 1e3;
    HEAP64[buf + 88 >>> 3 >>> 0] = BigInt(stat.ino);
    return 0;
  }, writeStatFs(buf, stats) {
    HEAPU32[buf + 4 >>> 2 >>> 0] = stats.bsize;
    HEAPU32[buf + 60 >>> 2 >>> 0] = stats.bsize;
    HEAP64[buf + 8 >>> 3 >>> 0] = BigInt(stats.blocks);
    HEAP64[buf + 16 >>> 3 >>> 0] = BigInt(stats.bfree);
    HEAP64[buf + 24 >>> 3 >>> 0] = BigInt(stats.bavail);
    HEAP64[buf + 32 >>> 3 >>> 0] = BigInt(stats.files);
    HEAP64[buf + 40 >>> 3 >>> 0] = BigInt(stats.ffree);
    HEAPU32[buf + 48 >>> 2 >>> 0] = stats.fsid;
    HEAPU32[buf + 64 >>> 2 >>> 0] = stats.flags;
    HEAPU32[buf + 56 >>> 2 >>> 0] = stats.namelen;
  }, 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);
  }, getStreamFromFD(fd) {
    var stream = FS.getStreamChecked(fd);
    return stream;
  }, varargs: void 0, getStr(ptr) {
    var ret = UTF8ToString(ptr);
    return ret;
  } };
  function ___syscall_chmod(path, mode) {
    path >>>= 0;
    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_faccessat(dirfd, path, amode, flags) {
    path >>>= 0;
    try {
      path = SYSCALLS.getStr(path);
      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 syscallGetVarargI = () => {
    var ret = HEAP32[+SYSCALLS.varargs >>> 2 >>> 0];
    SYSCALLS.varargs += 4;
    return ret;
  };
  var syscallGetVarargP = syscallGetVarargI;
  function ___syscall_fcntl64(fd, cmd, varargs) {
    varargs >>>= 0;
    SYSCALLS.varargs = varargs;
    try {
      var stream = SYSCALLS.getStreamFromFD(fd);
      switch (cmd) {
        case 0: {
          var arg = syscallGetVarargI();
          if (arg < 0) {
            return -28;
          }
          while (FS.streams[arg]) {
            arg++;
          }
          var newStream;
          newStream = FS.dupStream(stream, arg);
          return newStream.fd;
        }
        case 1:
        case 2:
          return 0;
        case 3:
          return stream.flags;
        case 4: {
          var arg = syscallGetVarargI();
          stream.flags |= arg;
          return 0;
        }
        case 12: {
          var arg = syscallGetVarargP();
          var offset = 0;
          HEAP16[arg + offset >>> 1 >>> 0] = 2;
          return 0;
        }
        case 13:
        case 14:
          return 0;
      }
      return -28;
    } catch (e) {
      if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
      return -e.errno;
    }
  }
  function ___syscall_fstat64(fd, buf) {
    buf >>>= 0;
    try {
      return SYSCALLS.writeStat(buf, FS.fstat(fd));
    } catch (e) {
      if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
      return -e.errno;
    }
  }
  var stringToUTF8 = (str, outPtr, maxBytesToWrite) => stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
  function ___syscall_getdents64(fd, dirp, count) {
    dirp >>>= 0;
    count >>>= 0;
    try {
      var stream = SYSCALLS.getStreamFromFD(fd);
      stream.getdents ||= FS.readdir(stream.path);
      var struct_size = 280;
      var pos = 0;
      var off = FS.llseek(stream, 0, 1);
      var startIdx = Math.floor(off / struct_size);
      var endIdx = Math.min(stream.getdents.length, startIdx + Math.floor(count / struct_size));
      for (var idx = startIdx; idx < endIdx; idx++) {
        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;
          try {
            child = FS.lookupNode(stream.node, name);
          } catch (e) {
            if (e?.errno === 28) {
              continue;
            }
            throw e;
          }
          id = child.id;
          type = FS.isChrdev(child.mode) ? 2 : FS.isDir(child.mode) ? 4 : FS.isLink(child.mode) ? 10 : 8;
        }
        HEAP64[dirp + pos >>> 3 >>> 0] = BigInt(id);
        HEAP64[dirp + pos + 8 >>> 3 >>> 0] = BigInt((idx + 1) * struct_size);
        HEAP16[dirp + pos + 16 >>> 1 >>> 0] = 280;
        HEAP8[dirp + pos + 18 >>> 0] = type;
        stringToUTF8(name, dirp + pos + 19, 256);
        pos += struct_size;
      }
      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) {
    varargs >>>= 0;
    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 = syscallGetVarargP();
            HEAP32[argp >>> 2 >>> 0] = termios.c_iflag || 0;
            HEAP32[argp + 4 >>> 2 >>> 0] = termios.c_oflag || 0;
            HEAP32[argp + 8 >>> 2 >>> 0] = termios.c_cflag || 0;
            HEAP32[argp + 12 >>> 2 >>> 0] = 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 = syscallGetVarargP();
            var c_iflag = HEAP32[argp >>> 2 >>> 0];
            var c_oflag = HEAP32[argp + 4 >>> 2 >>> 0];
            var c_cflag = HEAP32[argp + 8 >>> 2 >>> 0];
            var c_lflag = HEAP32[argp + 12 >>> 2 >>> 0];
            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_oflag, c_cflag, c_lflag, c_cc });
          }
          return 0;
        }
        case 21519: {
          if (!stream.tty) return -59;
          var argp = syscallGetVarargP();
          HEAP32[argp >>> 2 >>> 0] = 0;
          return 0;
        }
        case 21520: {
          if (!stream.tty) return -59;
          return -28;
        }
        case 21537:
        case 21531: {
          var argp = syscallGetVarargP();
          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 = syscallGetVarargP();
            HEAP16[argp >>> 1 >>> 0] = winsize[0];
            HEAP16[argp + 2 >>> 1 >>> 0] = 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) {
    path >>>= 0;
    buf >>>= 0;
    try {
      path = SYSCALLS.getStr(path);
      return SYSCALLS.writeStat(buf, FS.lstat(path));
    } catch (e) {
      if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
      return -e.errno;
    }
  }
  function ___syscall_mkdirat(dirfd, path, mode) {
    path >>>= 0;
    try {
      path = SYSCALLS.getStr(path);
      path = SYSCALLS.calculateAt(dirfd, path);
      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) {
    path >>>= 0;
    buf >>>= 0;
    try {
      path = SYSCALLS.getStr(path);
      var nofollow = flags & 256;
      var allowEmpty = flags & 4096;
      flags = flags & ~6400;
      path = SYSCALLS.calculateAt(dirfd, path, allowEmpty);
      return SYSCALLS.writeStat(buf, nofollow ? FS.lstat(path) : FS.stat(path));
    } catch (e) {
      if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
      return -e.errno;
    }
  }
  function ___syscall_openat(dirfd, path, flags, varargs) {
    path >>>= 0;
    varargs >>>= 0;
    SYSCALLS.varargs = varargs;
    try {
      path = SYSCALLS.getStr(path);
      path = SYSCALLS.calculateAt(dirfd, path);
      var mode = varargs ? syscallGetVarargI() : 0;
      return FS.open(path, flags, mode).fd;
    } catch (e) {
      if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
      return -e.errno;
    }
  }
  function ___syscall_rmdir(path) {
    path >>>= 0;
    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) {
    path >>>= 0;
    buf >>>= 0;
    try {
      path = SYSCALLS.getStr(path);
      return SYSCALLS.writeStat(buf, FS.stat(path));
    } catch (e) {
      if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
      return -e.errno;
    }
  }
  function ___syscall_unlinkat(dirfd, path, flags) {
    path >>>= 0;
    try {
      path = SYSCALLS.getStr(path);
      path = SYSCALLS.calculateAt(dirfd, path);
      if (!flags) {
        FS.unlink(path);
      } else if (flags === 512) {
        FS.rmdir(path);
      } else {
        return -28;
      }
      return 0;
    } catch (e) {
      if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
      return -e.errno;
    }
  }
  var __abort_js = () => abort("");
  var structRegistrations = {};
  var runDestructors = (destructors) => {
    while (destructors.length) {
      var ptr = destructors.pop();
      var del = destructors.pop();
      del(ptr);
    }
  };
  function readPointer(pointer) {
    return this.fromWireType(HEAPU32[pointer >>> 2 >>> 0]);
  }
  var awaitingDependencies = {};
  var registeredTypes = {};
  var typeDependencies = {};
  var InternalError = class InternalError extends Error {
    constructor(message) {
      super(message);
      this.name = "InternalError";
    }
  };
  var throwInternalError = (message) => {
    throw new InternalError(message);
  };
  var whenDependentTypesAreResolved = (myTypes, dependentTypes, getTypeConverters) => {
    myTypes.forEach((type) => typeDependencies[type] = dependentTypes);
    function onComplete(typeConverters2) {
      var myTypeConverters = getTypeConverters(typeConverters2);
      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;
    for (let [i, dt] of dependentTypes.entries()) {
      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);
    }
  };
  var __embind_finalize_value_object = function(structType) {
    structType >>>= 0;
    var reg = structRegistrations[structType];
    delete structRegistrations[structType];
    var rawConstructor = reg.rawConstructor;
    var rawDestructor = reg.rawDestructor;
    var fieldRecords = reg.fields;
    var fieldTypes = fieldRecords.map((field) => field.getterReturnType).concat(fieldRecords.map((field) => field.setterArgumentType));
    whenDependentTypesAreResolved([structType], fieldTypes, (fieldTypes2) => {
      var fields = {};
      for (var [i, field] of fieldRecords.entries()) {
        const getterReturnType = fieldTypes2[i];
        const getter = field.getter;
        const getterContext = field.getterContext;
        const setterArgumentType = fieldTypes2[i + fieldRecords.length];
        const setter = field.setter;
        const setterContext = field.setterContext;
        fields[field.fieldName] = { read: (ptr) => getterReturnType.fromWireType(getter(getterContext, ptr)), write: (ptr, o) => {
          var destructors = [];
          setter(setterContext, ptr, setterArgumentType.toWireType(destructors, o));
          runDestructors(destructors);
        }, optional: getterReturnType.optional };
      }
      return [{ name: reg.name, fromWireType: (ptr) => {
        var rv = {};
        for (var i2 in fields) {
          rv[i2] = fields[i2].read(ptr);
        }
        rawDestructor(ptr);
        return rv;
      }, toWireType: (destructors, o) => {
        for (var fieldName in fields) {
          if (!(fieldName in o) && !fields[fieldName].optional) {
            throw new TypeError(`Missing field: "${fieldName}"`);
          }
        }
        var ptr = rawConstructor();
        for (fieldName in fields) {
          fields[fieldName].write(ptr, o[fieldName]);
        }
        if (destructors !== null) {
          destructors.push(rawDestructor, ptr);
        }
        return ptr;
      }, readValueFromPointer: readPointer, destructorFunction: rawDestructor }];
    });
  };
  var AsciiToString = (ptr) => {
    ptr >>>= 0;
    var str = "";
    while (1) {
      var ch = HEAPU8[ptr++ >>> 0];
      if (!ch) return str;
      str += String.fromCharCode(ch);
    }
  };
  var BindingError = class BindingError extends Error {
    constructor(message) {
      super(message);
      this.name = "BindingError";
    }
  };
  var throwBindingError = (message) => {
    throw new BindingError(message);
  };
  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 = {}) {
    return sharedRegisterType(rawType, registeredInstance, options);
  }
  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 >>> 0] : (pointer) => HEAPU16[pointer >>> 1 >>> 0];
      case 4:
        return signed ? (pointer) => HEAP32[pointer >>> 2 >>> 0] : (pointer) => HEAPU32[pointer >>> 2 >>> 0];
      case 8:
        return signed ? (pointer) => HEAP64[pointer >>> 3 >>> 0] : (pointer) => HEAPU64[pointer >>> 3 >>> 0];
      default:
        throw new TypeError(`invalid integer width (${width}): ${name}`);
    }
  };
  var __embind_register_bigint = function(primitiveType, name, size, minRange, maxRange) {
    primitiveType >>>= 0;
    name >>>= 0;
    size >>>= 0;
    name = AsciiToString(name);
    const isUnsignedType = minRange === 0n;
    let fromWireType = (value) => value;
    if (isUnsignedType) {
      const bitSize = size * 8;
      fromWireType = (value) => BigInt.asUintN(bitSize, value);
      maxRange = fromWireType(maxRange);
    }
    registerType(primitiveType, { name, fromWireType, toWireType: (destructors, value) => {
      if (typeof value == "number") {
        value = BigInt(value);
      }
      return value;
    }, readValueFromPointer: integerReadValueFromPointer(name, size, !isUnsignedType), destructorFunction: null });
  };
  function __embind_register_bool(rawType, name, trueValue, falseValue) {
    rawType >>>= 0;
    name >>>= 0;
    name = AsciiToString(name);
    registerType(rawType, { name, fromWireType: function(wt) {
      return !!wt;
    }, toWireType: function(destructors, o) {
      return o ? trueValue : falseValue;
    }, readValueFromPointer: function(pointer) {
      return this.fromWireType(HEAPU8[pointer >>> 0]);
    }, 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(handle2) {
      return handle2.$$.ptrType.registeredClass.name;
    }
    throwBindingError(getInstanceTypeName(obj) + " instance already deleted");
  };
  var finalizationRegistry = false;
  var detachFinalizer = (handle2) => {
  };
  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 attachFinalizer = (handle2) => {
    if (!globalThis.FinalizationRegistry) {
      attachFinalizer = (handle3) => handle3;
      return handle2;
    }
    finalizationRegistry = new FinalizationRegistry((info) => {
      releaseClassHandle(info.$$);
    });
    attachFinalizer = (handle3) => {
      var $$ = handle3.$$;
      var hasSmartPtr = !!$$.smartPtr;
      if (hasSmartPtr) {
        var info = { $$ };
        finalizationRegistry.register(handle3, info, handle3);
      }
      return handle3;
    };
    detachFinalizer = (handle3) => finalizationRegistry.unregister(handle3);
    return attachFinalizer(handle2);
  };
  var deletionQueue = [];
  var flushPendingDeletes = () => {
    while (deletionQueue.length) {
      var obj = deletionQueue.pop();
      obj.$$.deleteScheduled = false;
      obj["delete"]();
    }
  };
  var delayFunction;
  var init_ClassHandle = () => {
    let proto = ClassHandle.prototype;
    Object.assign(proto, { 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 = void 0;
        this.$$.ptr = void 0;
      }
    }, 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;
    } });
    const symbolDispose = Symbol.dispose;
    if (symbolDispose) {
      proto[symbolDispose] = proto["delete"];
    }
  };
  function ClassHandle() {
  }
  var createNamedFunction = (name, func) => Object.defineProperty(func, "name", { value: name });
  var registeredPointers = {};
  var ensureOverloadTable = (proto, methodName, humanName) => {
    if (void 0 === proto[methodName].overloadTable) {
      var prevFunc = proto[methodName];
      proto[methodName] = function(...args) {
        if (!proto[methodName].overloadTable.hasOwnProperty(args.length)) {
          throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${args.length}) - expects one of (${proto[methodName].overloadTable})!`);
        }
        return proto[methodName].overloadTable[args.length].apply(this, args);
      };
      proto[methodName].overloadTable = [];
      proto[methodName].overloadTable[prevFunc.argCount] = prevFunc;
    }
  };
  var exposePublicSymbol = (name, value, numArguments) => {
    if (Module.hasOwnProperty(name)) {
      if (void 0 === numArguments || void 0 !== Module[name].overloadTable && void 0 !== Module[name].overloadTable[numArguments]) {
        throwBindingError(`Cannot register public name '${name}' twice`);
      }
      ensureOverloadTable(Module, name, name);
      if (Module[name].overloadTable.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;
      Module[name].argCount = numArguments;
    }
  };
  var char_0 = 48;
  var char_9 = 57;
  var makeLegalFunctionName = (name) => {
    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 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;
  };
  var embindRepr = (v2) => {
    if (v2 === null) {
      return "null";
    }
    var t = typeof v2;
    if (t === "object" || t === "array" || t === "function") {
      return v2.toString();
    } else {
      return "" + v2;
    }
  };
  function constNoSmartPtrRawPointerToWireType(destructors, handle2) {
    if (handle2 === null) {
      if (this.isReference) {
        throwBindingError(`null is not a valid ${this.name}`);
      }
      return 0;
    }
    if (!handle2.$$) {
      throwBindingError(`Cannot pass "${embindRepr(handle2)}" as a ${this.name}`);
    }
    if (!handle2.$$.ptr) {
      throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`);
    }
    var handleClass = handle2.$$.ptrType.registeredClass;
    var ptr = upcastPointer(handle2.$$.ptr, handleClass, this.registeredClass);
    return ptr;
  }
  function genericPointerToWireType(destructors, handle2) {
    var ptr;
    if (handle2 === 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 (!handle2 || !handle2.$$) {
      throwBindingError(`Cannot pass "${embindRepr(handle2)}" as a ${this.name}`);
    }
    if (!handle2.$$.ptr) {
      throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`);
    }
    if (!this.isConst && handle2.$$.ptrType.isConst) {
      throwBindingError(`Cannot convert argument of type ${handle2.$$.smartPtrType ? handle2.$$.smartPtrType.name : handle2.$$.ptrType.name} to parameter type ${this.name}`);
    }
    var handleClass = handle2.$$.ptrType.registeredClass;
    ptr = upcastPointer(handle2.$$.ptr, handleClass, this.registeredClass);
    if (this.isSmartPointer) {
      if (void 0 === handle2.$$.smartPtr) {
        throwBindingError("Passing raw pointer to smart pointer is illegal");
      }
      switch (this.sharingPolicy) {
        case 0:
          if (handle2.$$.smartPtrType === this) {
            ptr = handle2.$$.smartPtr;
          } else {
            throwBindingError(`Cannot convert argument of type ${handle2.$$.smartPtrType ? handle2.$$.smartPtrType.name : handle2.$$.ptrType.name} to parameter type ${this.name}`);
          }
          break;
        case 1:
          ptr = handle2.$$.smartPtr;
          break;
        case 2:
          if (handle2.$$.smartPtrType === this) {
            ptr = handle2.$$.smartPtr;
          } else {
            var clonedHandle = handle2["clone"]();
            ptr = this.rawShare(ptr, Emval.toHandle(() => clonedHandle["delete"]()));
            if (destructors !== null) {
              destructors.push(this.rawDestructor, ptr);
            }
          }
          break;
        default:
          throwBindingError("Unsupported sharing policy");
      }
    }
    return ptr;
  }
  function nonConstNoSmartPtrRawPointerToWireType(destructors, handle2) {
    if (handle2 === null) {
      if (this.isReference) {
        throwBindingError(`null is not a valid ${this.name}`);
      }
      return 0;
    }
    if (!handle2.$$) {
      throwBindingError(`Cannot pass "${embindRepr(handle2)}" as a ${this.name}`);
    }
    if (!handle2.$$.ptr) {
      throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`);
    }
    if (handle2.$$.ptrType.isConst) {
      throwBindingError(`Cannot convert argument of type ${handle2.$$.ptrType.name} to parameter type ${this.name}`);
    }
    var handleClass = handle2.$$.ptrType.registeredClass;
    var ptr = upcastPointer(handle2.$$.ptr, handleClass, this.registeredClass);
    return ptr;
  }
  var downcastPointer = (ptr, ptrClass, desiredClass) => {
    if (ptrClass === desiredClass) {
      return ptr;
    }
    if (void 0 === desiredClass.baseClass) {
      return null;
    }
    var rv = downcastPointer(ptr, ptrClass, desiredClass.baseClass);
    if (rv === null) {
      return null;
    }
    return desiredClass.downcast(rv);
  };
  var registeredInstances = {};
  var getBasestPointer = (class_, ptr) => {
    if (ptr === void 0) {
      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, writable: true } }));
  };
  function RegisteredPointer_fromWireType(ptr) {
    var rawPointer = this.getPointee(ptr);
    if (!rawPointer) {
      this.destructor(ptr);
      return null;
    }
    var registeredInstance = getInheritedInstance(this.registeredClass, rawPointer);
    if (void 0 !== 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 });
      }
    }
    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 init_RegisteredPointer = () => {
    Object.assign(RegisteredPointer.prototype, { getPointee(ptr) {
      if (this.rawGetPointee) {
        ptr = this.rawGetPointee(ptr);
      }
      return ptr;
    }, destructor(ptr) {
      this.rawDestructor?.(ptr);
    }, readValueFromPointer: readPointer, 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 === void 0) {
      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 nonexistent public symbol");
    }
    if (void 0 !== Module[name].overloadTable && void 0 !== numArguments) {
      Module[name].overloadTable[numArguments] = value;
    } else {
      Module[name] = value;
      Module[name].argCount = numArguments;
    }
  };
  var dynCall = (sig, ptr, args = [], promising = false) => {
    var func = getWasmTableEntry(ptr);
    var rtn = func(...args);
    function convert(rtn2) {
      return sig[0] == "p" ? rtn2 >>> 0 : rtn2;
    }
    return convert(rtn);
  };
  var getDynCaller = (sig, ptr, promising = false) => (...args) => dynCall(sig, ptr, args, promising);
  var embind__requireFunction = (signature, rawFunction, isAsync = false) => {
    signature = AsciiToString(signature);
    function makeDynCaller() {
      if (signature.includes("p")) {
        return getDynCaller(signature, rawFunction, isAsync);
      }
      var rtn = getWasmTableEntry(rawFunction);
      return rtn;
    }
    var fp = makeDynCaller();
    if (typeof fp != "function") {
      throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`);
    }
    return fp;
  };
  class UnboundTypeError extends Error {
  }
  var getTypeName = (type) => {
    var ptr = ___getTypeName(type);
    var rv = AsciiToString(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([", "]));
  };
  function __embind_register_class(rawType, rawPointerType, rawConstPointerType, baseClassRawType, getActualTypeSignature, getActualType, upcastSignature, upcast, downcastSignature, downcast, name, destructorSignature, rawDestructor) {
    rawType >>>= 0;
    rawPointerType >>>= 0;
    rawConstPointerType >>>= 0;
    baseClassRawType >>>= 0;
    getActualTypeSignature >>>= 0;
    getActualType >>>= 0;
    upcastSignature >>>= 0;
    upcast >>>= 0;
    downcastSignature >>>= 0;
    downcast >>>= 0;
    name >>>= 0;
    destructorSignature >>>= 0;
    rawDestructor >>>= 0;
    name = AsciiToString(name);
    getActualType = embind__requireFunction(getActualTypeSignature, getActualType);
    upcast &&= embind__requireFunction(upcastSignature, upcast);
    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] : [], (base) => {
      base = base[0];
      var baseClass;
      var basePrototype;
      if (baseClassRawType) {
        baseClass = base.registeredClass;
        basePrototype = baseClass.instancePrototype;
      } else {
        basePrototype = ClassHandle.prototype;
      }
      var constructor = createNamedFunction(name, function(...args) {
        if (Object.getPrototypeOf(this) !== instancePrototype) {
          throw new BindingError(`Use 'new' to construct ${name}`);
        }
        if (void 0 === registeredClass.constructor_body) {
          throw new BindingError(`${name} has no accessible constructor`);
        }
        var body = registeredClass.constructor_body[args.length];
        if (void 0 === body) {
          throw new BindingError(`Tried to invoke ctor of ${name} with invalid number of parameters (${args.length}) - expected (${Object.keys(registeredClass.constructor_body).toString()}) parameters instead!`);
        }
        return body.apply(this, args);
      });
      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) {
        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 >>> 0]);
    }
    return array;
  };
  function usesDestructorStack(argTypes) {
    for (var i = 1; i < argTypes.length; ++i) {
      if (argTypes[i] !== null && argTypes[i].destructorFunction === void 0) {
        return true;
      }
    }
    return false;
  }
  function createJsInvoker(argTypes, isClassMethodFunc, returns, isAsync) {
    var needsDestructorStack = usesDestructorStack(argTypes);
    var argCount = argTypes.length - 2;
    var argsList = [];
    var argsListWired = ["fn"];
    if (isClassMethodFunc) {
      argsListWired.push("thisWired");
    }
    for (var i = 0; i < argCount; ++i) {
      argsList.push(`arg${i}`);
      argsListWired.push(`arg${i}Wired`);
    }
    argsList = argsList.join(",");
    argsListWired = argsListWired.join(",");
    var invokerFnBody = `return function (${argsList}) {
`;
    if (needsDestructorStack) {
      invokerFnBody += "var destructors = [];\n";
    }
    var dtorStack = needsDestructorStack ? "destructors" : "null";
    var args1 = ["humanName", "throwBindingError", "invoker", "fn", "runDestructors", "fromRetWire", "toClassParamWire"];
    if (isClassMethodFunc) {
      invokerFnBody += `var thisWired = toClassParamWire(${dtorStack}, this);
`;
    }
    for (var i = 0; i < argCount; ++i) {
      var argName = `toArg${i}Wire`;
      invokerFnBody += `var arg${i}Wired = ${argName}(${dtorStack}, arg${i});
`;
      args1.push(argName);
    }
    invokerFnBody += (returns || isAsync ? "var rv = " : "") + `invoker(${argsListWired});
`;
    if (needsDestructorStack) {
      invokerFnBody += "runDestructors(destructors);\n";
    } else {
      for (var i = isClassMethodFunc ? 1 : 2; i < argTypes.length; ++i) {
        var paramName = i === 1 ? "thisWired" : "arg" + (i - 2) + "Wired";
        if (argTypes[i].destructorFunction !== null) {
          invokerFnBody += `${paramName}_dtor(${paramName});
`;
          args1.push(`${paramName}_dtor`);
        }
      }
    }
    if (returns) {
      invokerFnBody += "var ret = fromRetWire(rv);\nreturn ret;\n";
    } else {
    }
    invokerFnBody += "}\n";
    return new Function(args1, invokerFnBody);
  }
  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 = usesDestructorStack(argTypes);
    var returns = !argTypes[0].isVoid;
    var retType = argTypes[0];
    var instType = argTypes[1];
    var closureArgs = [humanName, throwBindingError, cppInvokerFunc, cppTargetFunc, runDestructors, retType.fromWireType.bind(retType), instType?.toWireType.bind(instType)];
    for (var i = 2; i < argCount; ++i) {
      var argType = argTypes[i];
      closureArgs.push(argType.toWireType.bind(argType));
    }
    if (!needsDestructorStack) {
      for (var i = isClassMethodFunc ? 1 : 2; i < argTypes.length; ++i) {
        if (argTypes[i].destructorFunction !== null) {
          closureArgs.push(argTypes[i].destructorFunction);
        }
      }
    }
    let invokerFactory = createJsInvoker(argTypes, isClassMethodFunc, returns, isAsync);
    var invokerFn = invokerFactory(...closureArgs);
    return createNamedFunction(humanName, invokerFn);
  }
  var __embind_register_class_constructor = function(rawClassType, argCount, rawArgTypesAddr, invokerSignature, invoker, rawConstructor) {
    rawClassType >>>= 0;
    rawArgTypesAddr >>>= 0;
    invokerSignature >>>= 0;
    invoker >>>= 0;
    rawConstructor >>>= 0;
    var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr);
    invoker = embind__requireFunction(invokerSignature, invoker);
    whenDependentTypesAreResolved([], [rawClassType], (classType) => {
      classType = classType[0];
      var humanName = `constructor ${classType.name}`;
      if (void 0 === classType.registeredClass.constructor_body) {
        classType.registeredClass.constructor_body = [];
      }
      if (void 0 !== 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 getFunctionName = (signature) => {
    signature = signature.trim();
    const argsIndex = signature.indexOf("(");
    if (argsIndex === -1) return signature;
    return signature.slice(0, argsIndex);
  };
  var __embind_register_class_function = function(rawClassType, methodName, argCount, rawArgTypesAddr, invokerSignature, rawInvoker, context, isPureVirtual, isAsync, isNonnullReturn) {
    rawClassType >>>= 0;
    methodName >>>= 0;
    rawArgTypesAddr >>>= 0;
    invokerSignature >>>= 0;
    rawInvoker >>>= 0;
    context >>>= 0;
    var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr);
    methodName = AsciiToString(methodName);
    methodName = getFunctionName(methodName);
    rawInvoker = embind__requireFunction(invokerSignature, rawInvoker, isAsync);
    whenDependentTypesAreResolved([], [rawClassType], (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 (void 0 === method || void 0 === 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, (argTypes) => {
        var memberFunction = craftInvokerFunction(humanName, argTypes, classType, rawInvoker, context, isAsync);
        if (void 0 === proto[methodName].overloadTable) {
          memberFunction.argCount = argCount - 2;
          proto[methodName] = memberFunction;
        } else {
          proto[methodName].overloadTable[argCount - 2] = memberFunction;
        }
        return [];
      });
      return [];
    });
  };
  var validateThis = (this_, classType, humanName) => {
    if (!(this_ instanceof Object)) {
      throwBindingError(`${humanName} with invalid "this": ${this_}`);
    }
    if (!(this_ instanceof classType.registeredClass.constructor)) {
      throwBindingError(`${humanName} incompatible with "this" of type ${this_.constructor.name}`);
    }
    if (!this_.$$.ptr) {
      throwBindingError(`cannot call emscripten binding method ${humanName} on deleted object`);
    }
    return upcastPointer(this_.$$.ptr, this_.$$.ptrType.registeredClass, classType.registeredClass);
  };
  var __embind_register_class_property = function(classType, fieldName, getterReturnType, getterSignature, getter, getterContext, setterArgumentType, setterSignature, setter, setterContext) {
    classType >>>= 0;
    fieldName >>>= 0;
    getterReturnType >>>= 0;
    getterSignature >>>= 0;
    getter >>>= 0;
    getterContext >>>= 0;
    setterArgumentType >>>= 0;
    setterSignature >>>= 0;
    setter >>>= 0;
    setterContext >>>= 0;
    fieldName = AsciiToString(fieldName);
    getter = embind__requireFunction(getterSignature, getter);
    whenDependentTypesAreResolved([], [classType], (classType2) => {
      classType2 = classType2[0];
      var humanName = `${classType2.name}.${fieldName}`;
      var desc = { get() {
        throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`, [getterReturnType, setterArgumentType]);
      }, enumerable: true, configurable: true };
      if (setter) {
        desc.set = () => throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`, [getterReturnType, setterArgumentType]);
      } else {
        desc.set = (v2) => throwBindingError(humanName + " is a read-only property");
      }
      Object.defineProperty(classType2.registeredClass.instancePrototype, fieldName, desc);
      whenDependentTypesAreResolved([], setter ? [getterReturnType, setterArgumentType] : [getterReturnType], (types) => {
        var getterReturnType2 = types[0];
        var desc2 = { get() {
          var ptr = validateThis(this, classType2, humanName + " getter");
          return getterReturnType2.fromWireType(getter(getterContext, ptr));
        }, enumerable: true };
        if (setter) {
          setter = embind__requireFunction(setterSignature, setter);
          var setterArgumentType2 = types[1];
          desc2.set = function(v2) {
            var ptr = validateThis(this, classType2, humanName + " setter");
            var destructors = [];
            setter(setterContext, ptr, setterArgumentType2.toWireType(destructors, v2));
            runDestructors(destructors);
          };
        }
        Object.defineProperty(classType2.registeredClass.instancePrototype, fieldName, desc2);
        return [];
      });
      return [];
    });
  };
  var emval_freelist = [];
  var emval_handles = [0, 1, , 1, null, 1, true, 1, false, 1];
  function __emval_decref(handle2) {
    handle2 >>>= 0;
    if (handle2 > 9 && 0 === --emval_handles[handle2 + 1]) {
      emval_handles[handle2] = void 0;
      emval_freelist.push(handle2);
    }
  }
  var Emval = { toValue: (handle2) => {
    if (!handle2) {
      throwBindingError(`Cannot use deleted val. handle = ${handle2}`);
    }
    return emval_handles[handle2];
  }, toHandle: (value) => {
    switch (value) {
      case void 0:
        return 2;
      case null:
        return 4;
      case true:
        return 6;
      case false:
        return 8;
      default: {
        const handle2 = emval_freelist.pop() || emval_handles.length;
        emval_handles[handle2] = value;
        emval_handles[handle2 + 1] = 1;
        return handle2;
      }
    }
  } };
  var EmValType = { name: "emscripten::val", fromWireType: (handle2) => {
    var rv = Emval.toValue(handle2);
    __emval_decref(handle2);
    return rv;
  }, toWireType: (destructors, value) => Emval.toHandle(value), readValueFromPointer: readPointer, destructorFunction: null };
  function __embind_register_emval(rawType) {
    rawType >>>= 0;
    return registerType(rawType, EmValType);
  }
  var floatReadValueFromPointer = (name, width) => {
    switch (width) {
      case 4:
        return function(pointer) {
          return this.fromWireType(HEAPF32[pointer >>> 2 >>> 0]);
        };
      case 8:
        return function(pointer) {
          return this.fromWireType(HEAPF64[pointer >>> 3 >>> 0]);
        };
      default:
        throw new TypeError(`invalid float width (${width}): ${name}`);
    }
  };
  var __embind_register_float = function(rawType, name, size) {
    rawType >>>= 0;
    name >>>= 0;
    size >>>= 0;
    name = AsciiToString(name);
    registerType(rawType, { name, fromWireType: (value) => value, toWireType: (destructors, value) => value, readValueFromPointer: floatReadValueFromPointer(name, size), destructorFunction: null });
  };
  var __embind_register_integer = function(primitiveType, name, size, minRange, maxRange) {
    primitiveType >>>= 0;
    name >>>= 0;
    size >>>= 0;
    name = AsciiToString(name);
    const isUnsignedType = minRange === 0;
    let fromWireType = (value) => value;
    if (isUnsignedType) {
      var bitshift = 32 - 8 * size;
      fromWireType = (value) => value << bitshift >>> bitshift;
      maxRange = fromWireType(maxRange);
    }
    registerType(primitiveType, { name, fromWireType, toWireType: (destructors, value) => value, readValueFromPointer: integerReadValueFromPointer(name, size, minRange !== 0), destructorFunction: null });
  };
  var installIndexedIterator = (proto, sizeMethodName, getMethodName) => {
    const makeIterator = (size, getValue) => {
      let index = 0;
      return { next() {
        if (index >= size) {
          return { done: true };
        }
        const current = index;
        index++;
        const value = getValue(current);
        return { value, done: false };
      }, [Symbol.iterator]() {
        return this;
      } };
    };
    if (!proto[Symbol.iterator]) {
      proto[Symbol.iterator] = function() {
        const size = this[sizeMethodName]();
        return makeIterator(size, (i) => this[getMethodName](i));
      };
    }
  };
  var __embind_register_iterable = function(rawClassType, rawElementType, sizeMethodName, getMethodName) {
    rawClassType >>>= 0;
    rawElementType >>>= 0;
    sizeMethodName >>>= 0;
    getMethodName >>>= 0;
    sizeMethodName = AsciiToString(sizeMethodName);
    getMethodName = AsciiToString(getMethodName);
    whenDependentTypesAreResolved([], [rawClassType, rawElementType], (types) => {
      const classType = types[0];
      installIndexedIterator(classType.registeredClass.instancePrototype, sizeMethodName, getMethodName);
      return [];
    });
  };
  function __embind_register_memory_view(rawType, dataTypeIndex, name) {
    rawType >>>= 0;
    name >>>= 0;
    var typeMapping = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array, BigInt64Array, BigUint64Array];
    var TA = typeMapping[dataTypeIndex];
    function decodeMemoryView(handle2) {
      var size = HEAPU32[handle2 >>> 2 >>> 0];
      var data = HEAPU32[handle2 + 4 >>> 2 >>> 0];
      return new TA(HEAP8.buffer, data, size);
    }
    name = AsciiToString(name);
    registerType(rawType, { name, fromWireType: decodeMemoryView, readValueFromPointer: decodeMemoryView }, { ignoreDuplicateRegistrations: true });
  }
  var EmValOptionalType = Object.assign({ optional: true }, EmValType);
  function __embind_register_optional(rawOptionalType, rawType) {
    rawOptionalType >>>= 0;
    rawType >>>= 0;
    registerType(rawOptionalType, EmValOptionalType);
  }
  function __embind_register_std_string(rawType, name) {
    rawType >>>= 0;
    name >>>= 0;
    name = AsciiToString(name);
    var stdStringIsUTF8 = true;
    registerType(rawType, { name, fromWireType(value) {
      var length = HEAPU32[value >>> 2 >>> 0];
      var payload = value + 4;
      var str;
      if (stdStringIsUTF8) {
        str = UTF8ToString(payload, length, true);
      } else {
        str = "";
        for (var i = 0; i < length; ++i) {
          str += String.fromCharCode(HEAPU8[payload + i >>> 0]);
        }
      }
      _free(value);
      return str;
    }, toWireType(destructors, value) {
      if (value instanceof ArrayBuffer) {
        value = new Uint8Array(value);
      }
      var length;
      var valueIsOfTypeString = typeof value == "string";
      if (!(valueIsOfTypeString || ArrayBuffer.isView(value) && value.BYTES_PER_ELEMENT == 1)) {
        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 >>> 0] = length;
      if (valueIsOfTypeString) {
        if (stdStringIsUTF8) {
          stringToUTF8(value, ptr, length + 1);
        } else {
          for (var i = 0; i < length; ++i) {
            var charCode = value.charCodeAt(i);
            if (charCode > 255) {
              _free(base);
              throwBindingError("String has UTF-16 code units that do not fit in 8 bits");
            }
            HEAPU8[ptr + i >>> 0] = charCode;
          }
        }
      } else {
        HEAPU8.set(value, ptr >>> 0);
      }
      if (destructors !== null) {
        destructors.push(_free, base);
      }
      return base;
    }, readValueFromPointer: readPointer, destructorFunction(ptr) {
      _free(ptr);
    } });
  }
  var UTF16Decoder = globalThis.TextDecoder ? new TextDecoder("utf-16le") : void 0;
  var UTF16ToString = (ptr, maxBytesToRead, ignoreNul) => {
    var idx = ptr >>> 1;
    var endIdx = findStringEnd(HEAPU16, idx, maxBytesToRead / 2, ignoreNul);
    if (endIdx - idx > 16 && UTF16Decoder) return UTF16Decoder.decode(HEAPU16.subarray(idx >>> 0, endIdx >>> 0));
    var str = "";
    for (var i = idx; i < endIdx; ++i) {
      var codeUnit = HEAPU16[i >>> 0];
      str += String.fromCharCode(codeUnit);
    }
    return str;
  };
  var stringToUTF16 = (str, outPtr, maxBytesToWrite) => {
    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 >>> 0] = codeUnit;
      outPtr += 2;
    }
    HEAP16[outPtr >>> 1 >>> 0] = 0;
    return outPtr - startPtr;
  };
  var lengthBytesUTF16 = (str) => str.length * 2;
  var UTF32ToString = (ptr, maxBytesToRead, ignoreNul) => {
    var str = "";
    var startIdx = ptr >>> 2;
    for (var i = 0; !(i >= maxBytesToRead / 4); i++) {
      var utf32 = HEAPU32[startIdx + i >>> 0];
      if (!utf32 && !ignoreNul) break;
      str += String.fromCodePoint(utf32);
    }
    return str;
  };
  var stringToUTF32 = (str, outPtr, maxBytesToWrite) => {
    outPtr >>>= 0;
    maxBytesToWrite ??= 2147483647;
    if (maxBytesToWrite < 4) return 0;
    var startPtr = outPtr;
    var endPtr = startPtr + maxBytesToWrite - 4;
    for (var i = 0; i < str.length; ++i) {
      var codePoint = str.codePointAt(i);
      if (codePoint > 65535) {
        i++;
      }
      HEAP32[outPtr >>> 2 >>> 0] = codePoint;
      outPtr += 4;
      if (outPtr + 4 > endPtr) break;
    }
    HEAP32[outPtr >>> 2 >>> 0] = 0;
    return outPtr - startPtr;
  };
  var lengthBytesUTF32 = (str) => {
    var len = 0;
    for (var i = 0; i < str.length; ++i) {
      var codePoint = str.codePointAt(i);
      if (codePoint > 65535) {
        i++;
      }
      len += 4;
    }
    return len;
  };
  function __embind_register_std_wstring(rawType, charSize, name) {
    rawType >>>= 0;
    charSize >>>= 0;
    name >>>= 0;
    name = AsciiToString(name);
    var decodeString, encodeString, lengthBytesUTF;
    if (charSize === 2) {
      decodeString = UTF16ToString;
      encodeString = stringToUTF16;
      lengthBytesUTF = lengthBytesUTF16;
    } else {
      decodeString = UTF32ToString;
      encodeString = stringToUTF32;
      lengthBytesUTF = lengthBytesUTF32;
    }
    registerType(rawType, { name, fromWireType: (value) => {
      var length = HEAPU32[value >>> 2 >>> 0];
      var str = decodeString(value + 4, length * charSize, true);
      _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 >>> 0] = length / charSize;
      encodeString(value, ptr + 4, length + charSize);
      if (destructors !== null) {
        destructors.push(_free, ptr);
      }
      return ptr;
    }, readValueFromPointer: readPointer, destructorFunction(ptr) {
      _free(ptr);
    } });
  }
  function __embind_register_value_object(rawType, name, constructorSignature, rawConstructor, destructorSignature, rawDestructor) {
    rawType >>>= 0;
    name >>>= 0;
    constructorSignature >>>= 0;
    rawConstructor >>>= 0;
    destructorSignature >>>= 0;
    rawDestructor >>>= 0;
    structRegistrations[rawType] = { name: AsciiToString(name), rawConstructor: embind__requireFunction(constructorSignature, rawConstructor), rawDestructor: embind__requireFunction(destructorSignature, rawDestructor), fields: [] };
  }
  function __embind_register_value_object_field(structType, fieldName, getterReturnType, getterSignature, getter, getterContext, setterArgumentType, setterSignature, setter, setterContext) {
    structType >>>= 0;
    fieldName >>>= 0;
    getterReturnType >>>= 0;
    getterSignature >>>= 0;
    getter >>>= 0;
    getterContext >>>= 0;
    setterArgumentType >>>= 0;
    setterSignature >>>= 0;
    setter >>>= 0;
    setterContext >>>= 0;
    structRegistrations[structType].fields.push({ fieldName: AsciiToString(fieldName), getterReturnType, getter: embind__requireFunction(getterSignature, getter), getterContext, setterArgumentType, setter: embind__requireFunction(setterSignature, setter), setterContext });
  }
  var __embind_register_void = function(rawType, name) {
    rawType >>>= 0;
    name >>>= 0;
    name = AsciiToString(name);
    registerType(rawType, { isVoid: true, name, fromWireType: () => void 0, toWireType: (destructors, o) => void 0 });
  };
  var inetPton4 = (str) => {
    var b = str.split(".");
    for (var i = 0; i < 4; i++) {
      var tmp = Number(b[i]);
      if (isNaN(tmp)) return null;
      b[i] = tmp;
    }
    return (b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24) >>> 0;
  };
  var inetPton6 = (str) => {
    var words;
    var w, offset, z;
    var valid6regx = /^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i;
    var parts = [];
    if (!valid6regx.test(str)) {
      return null;
    }
    if (str === "::") {
      return [0, 0, 0, 0, 0, 0, 0, 0];
    }
    if (str.startsWith("::")) {
      str = str.replace("::", "Z:");
    } else {
      str = str.replace("::", ":Z:");
    }
    if (str.indexOf(".") > 0) {
      str = str.replace(new RegExp("[.]", "g"), ":");
      words = str.split(":");
      words[words.length - 4] = Number(words[words.length - 4]) + Number(words[words.length - 3]) * 256;
      words[words.length - 3] = Number(words[words.length - 2]) + Number(words[words.length - 1]) * 256;
      words = words.slice(0, words.length - 2);
    } else {
      words = str.split(":");
    }
    offset = 0;
    z = 0;
    for (w = 0; w < words.length; w++) {
      if (typeof words[w] == "string") {
        if (words[w] === "Z") {
          for (z = 0; z < 8 - words.length + 1; z++) {
            parts[w + z] = 0;
          }
          offset = z - 1;
        } else {
          parts[w + offset] = _htons(parseInt(words[w], 16));
        }
      } else {
        parts[w + offset] = words[w];
      }
    }
    return [parts[1] << 16 | parts[0], parts[3] << 16 | parts[2], parts[5] << 16 | parts[4], parts[7] << 16 | parts[6]];
  };
  var DNS = { address_map: { id: 1, addrs: {}, names: {} }, lookup_name(name) {
    var res = inetPton4(name);
    if (res !== null) {
      return name;
    }
    res = inetPton6(name);
    if (res !== null) {
      return name;
    }
    var addr;
    if (DNS.address_map.addrs[name]) {
      addr = DNS.address_map.addrs[name];
    } else {
      var id = DNS.address_map.id++;
      addr = "172.29." + (id & 255) + "." + (id & 65280);
      DNS.address_map.names[addr] = name;
      DNS.address_map.addrs[name] = addr;
    }
    return addr;
  }, lookup_addr(addr) {
    if (DNS.address_map.names[addr]) {
      return DNS.address_map.names[addr];
    }
    return null;
  } };
  function __emscripten_lookup_name(name) {
    name >>>= 0;
    var nameString = UTF8ToString(name);
    return inetPton4(DNS.lookup_name(nameString));
  }
  var runtimeKeepaliveCounter = 0;
  var __emscripten_runtime_keepalive_clear = () => {
    noExitRuntime = false;
    runtimeKeepaliveCounter = 0;
  };
  var emval_methodCallers = [];
  var emval_addMethodCaller = (caller) => {
    var id = emval_methodCallers.length;
    emval_methodCallers.push(caller);
    return id;
  };
  var requireRegisteredType = (rawType, humanName) => {
    var impl = registeredTypes[rawType];
    if (void 0 === impl) {
      throwBindingError(`${humanName} has unknown type ${getTypeName(rawType)}`);
    }
    return impl;
  };
  var emval_lookupTypes = (argCount, argTypes) => {
    var a = new Array(argCount);
    for (var i = 0; i < argCount; ++i) {
      a[i] = requireRegisteredType(HEAPU32[argTypes + i * 4 >>> 2 >>> 0], `parameter ${i}`);
    }
    return a;
  };
  var emval_returnValue = (toReturnWire, destructorsRef, handle2) => {
    var destructors = [];
    var result = toReturnWire(destructors, handle2);
    if (destructors.length) {
      HEAPU32[destructorsRef >>> 2 >>> 0] = Emval.toHandle(destructors);
    }
    return result;
  };
  var emval_symbols = {};
  var getStringOrSymbol = (address) => {
    var symbol = emval_symbols[address];
    if (symbol === void 0) {
      return AsciiToString(address);
    }
    return symbol;
  };
  var __emval_create_invoker = function(argCount, argTypesPtr, kind) {
    argTypesPtr >>>= 0;
    var GenericWireTypeSize = 8;
    var [retType, ...argTypes] = emval_lookupTypes(argCount, argTypesPtr);
    var toReturnWire = retType.toWireType.bind(retType);
    var argFromPtr = argTypes.map((type) => type.readValueFromPointer.bind(type));
    argCount--;
    var captures = { toValue: Emval.toValue };
    var args = argFromPtr.map((argFromPtr2, i) => {
      var captureName = `argFromPtr${i}`;
      captures[captureName] = argFromPtr2;
      return `${captureName}(args${i ? "+" + i * GenericWireTypeSize : ""})`;
    });
    var functionBody;
    switch (kind) {
      case 0:
        functionBody = "toValue(handle)";
        break;
      case 2:
        functionBody = "new (toValue(handle))";
        break;
      case 3:
        functionBody = "";
        break;
      case 1:
        captures["getStringOrSymbol"] = getStringOrSymbol;
        functionBody = "toValue(handle)[getStringOrSymbol(methodName)]";
        break;
    }
    functionBody += `(${args})`;
    if (!retType.isVoid) {
      captures["toReturnWire"] = toReturnWire;
      captures["emval_returnValue"] = emval_returnValue;
      functionBody = `return emval_returnValue(toReturnWire, destructorsRef, ${functionBody})`;
    }
    functionBody = `return function (handle, methodName, destructorsRef, args) {
${functionBody}
}`;
    var invokerFunction = new Function(Object.keys(captures), functionBody)(...Object.values(captures));
    var functionName = `methodCaller<(${argTypes.map((t) => t.name)}) => ${retType.name}>`;
    return emval_addMethodCaller(createNamedFunction(functionName, invokerFunction));
  };
  function __emval_invoke(caller, handle2, methodName, destructorsRef, args) {
    caller >>>= 0;
    handle2 >>>= 0;
    methodName >>>= 0;
    destructorsRef >>>= 0;
    args >>>= 0;
    return emval_methodCallers[caller](handle2, methodName, destructorsRef, args);
  }
  function __emval_run_destructors(handle2) {
    handle2 >>>= 0;
    var destructors = Emval.toValue(handle2);
    runDestructors(destructors);
    __emval_decref(handle2);
  }
  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, tmPtr) {
    time = bigintToI53Checked(time);
    tmPtr >>>= 0;
    var date = new Date(time * 1e3);
    HEAP32[tmPtr >>> 2 >>> 0] = date.getSeconds();
    HEAP32[tmPtr + 4 >>> 2 >>> 0] = date.getMinutes();
    HEAP32[tmPtr + 8 >>> 2 >>> 0] = date.getHours();
    HEAP32[tmPtr + 12 >>> 2 >>> 0] = date.getDate();
    HEAP32[tmPtr + 16 >>> 2 >>> 0] = date.getMonth();
    HEAP32[tmPtr + 20 >>> 2 >>> 0] = date.getFullYear() - 1900;
    HEAP32[tmPtr + 24 >>> 2 >>> 0] = date.getDay();
    var yday = ydayFromDate(date) | 0;
    HEAP32[tmPtr + 28 >>> 2 >>> 0] = yday;
    HEAP32[tmPtr + 36 >>> 2 >>> 0] = -(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 >>> 0] = dst;
  }
  var timers = {};
  var handleException = (e) => {
    if (e instanceof ExitStatus || e == "unwind") {
      return EXITSTATUS;
    }
    quit_(1, e);
  };
  var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0;
  var _proc_exit = (code) => {
    EXITSTATUS = code;
    if (!keepRuntimeAlive()) {
      Module["onExit"]?.(code);
      ABORT = true;
    }
    quit_(code, new ExitStatus(code));
  };
  var exitJS = (status, implicit) => {
    EXITSTATUS = status;
    _proc_exit(status);
  };
  var _exit = exitJS;
  var maybeExit = () => {
    if (!keepRuntimeAlive()) {
      try {
        _exit(EXITSTATUS);
      } catch (e) {
        handleException(e);
      }
    }
  };
  var callUserCallback = (func) => {
    if (ABORT) {
      return;
    }
    try {
      return func();
    } catch (e) {
      handleException(e);
    } finally {
      maybeExit();
    }
  };
  var _emscripten_get_now = () => performance.now();
  var __setitimer_js = (which, timeout_ms) => {
    if (timers[which]) {
      clearTimeout(timers[which].id);
      delete timers[which];
    }
    if (!timeout_ms) return 0;
    var id = setTimeout(() => {
      delete timers[which];
      callUserCallback(() => __emscripten_timeout(which, _emscripten_get_now()));
    }, timeout_ms);
    timers[which] = { id, timeout_ms };
    return 0;
  };
  var __tzset_js = function(timezone, daylight, std_name, dst_name) {
    timezone >>>= 0;
    daylight >>>= 0;
    std_name >>>= 0;
    dst_name >>>= 0;
    var currentYear = (/* @__PURE__ */ 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 >>> 0] = stdTimezoneOffset * 60;
    HEAP32[daylight >>> 2 >>> 0] = Number(winterOffset != summerOffset);
    var extractZone = (timezoneOffset) => {
      var sign = timezoneOffset >= 0 ? "-" : "+";
      var absOffset = Math.abs(timezoneOffset);
      var hours = String(Math.floor(absOffset / 60)).padStart(2, "0");
      var minutes = String(absOffset % 60).padStart(2, "0");
      return `UTC${sign}${hours}${minutes}`;
    };
    var winterName = extractZone(winterOffset);
    var summerName = extractZone(summerOffset);
    if (summerOffset < winterOffset) {
      stringToUTF8(winterName, std_name, 17);
      stringToUTF8(summerName, dst_name, 17);
    } else {
      stringToUTF8(winterName, dst_name, 17);
      stringToUTF8(summerName, std_name, 17);
    }
  };
  var _emscripten_date_now = () => Date.now();
  var nowIsMonotonic = 1;
  var checkWasiClock = (clock_id) => clock_id >= 0 && clock_id <= 3;
  function _clock_time_get(clk_id, ignored_precision, ptime) {
    ignored_precision = bigintToI53Checked(ignored_precision);
    ptime >>>= 0;
    if (!checkWasiClock(clk_id)) {
      return 28;
    }
    var now;
    if (clk_id === 0) {
      now = _emscripten_date_now();
    } else if (nowIsMonotonic) {
      now = _emscripten_get_now();
    } else {
      return 52;
    }
    var nsec = Math.round(now * 1e3 * 1e3);
    HEAP64[ptime >>> 3 >>> 0] = BigInt(nsec);
    return 0;
  }
  var jsStackTrace = () => new Error().stack.toString();
  var getCallstack = (flags) => {
    var callstack = jsStackTrace();
    var lines = callstack.split("\n");
    callstack = "";
    var firefoxRe = new RegExp("\\s*(.*?)@(.*?):([0-9]+):([0-9]+)");
    var chromeRe = new RegExp("\\s*at (.*?) \\((.*):(.*):(.*)\\)");
    for (var line of lines) {
      var symbolName = "";
      var file = "";
      var lineno = 0;
      var column = 0;
      var parts = chromeRe.exec(line);
      if (parts?.length == 5) {
        symbolName = parts[1];
        file = parts[2];
        lineno = parts[3];
        column = parts[4];
      } else {
        parts = firefoxRe.exec(line);
        if (parts?.length >= 4) {
          symbolName = parts[1];
          file = parts[2];
          lineno = parts[3];
          column = parts[4] | 0;
        } else {
          callstack += line + "\n";
          continue;
        }
      }
      if (symbolName == "_emscripten_log" || symbolName == "_emscripten_get_callstack") {
        callstack = "";
        continue;
      }
      if (flags & 24) {
        if (flags & 64) {
          file = file.substring(file.replace(/\\/g, "/").lastIndexOf("/") + 1);
        }
        callstack += `    at ${symbolName} (${file}:${lineno}:${column})
`;
      }
    }
    callstack = callstack.replace(/\s+$/, "");
    return callstack;
  };
  function _emscripten_get_callstack(flags, str, maxbytes) {
    str >>>= 0;
    var callstack = getCallstack(flags);
    if (!str || maxbytes <= 0) {
      return lengthBytesUTF8(callstack) + 1;
    }
    var bytesWrittenExcludingNull = stringToUTF8(callstack, str, maxbytes);
    return bytesWrittenExcludingNull + 1;
  }
  var getHeapMax = () => 4294901760;
  function _emscripten_get_heap_max() {
    return getHeapMax();
  }
  function getFullscreenElement() {
    return document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.webkitCurrentFullScreenElement || document.msFullscreenElement;
  }
  var safeSetTimeout = (func, timeout) => setTimeout(() => {
    callUserCallback(func);
  }, timeout);
  var warnOnce = (text) => {
    warnOnce.shown ||= {};
    if (!warnOnce.shown[text]) {
      warnOnce.shown[text] = 1;
      if (ENVIRONMENT_IS_NODE) text = "warning: " + text;
      err(text);
    }
  };
  var Browser = { useWebGL: false, isFullscreen: false, pointerLock: false, moduleContextCreatedCallbacks: [], workers: [], preloadedImages: {}, preloadedAudios: {}, getCanvas: () => Module["canvas"], init() {
    if (Browser.initted) return;
    Browser.initted = true;
    var imagePlugin = {};
    imagePlugin["canHandle"] = (name) => !Module["noImageDecoding"] && /\.(jpg|jpeg|png|bmp|webp)$/i.test(name);
    imagePlugin["handle"] = async (byteArray, name) => {
      var b = new Blob([byteArray], { type: Browser.getMimetype(name) });
      if (b.size !== byteArray.length) {
        b = new Blob([new Uint8Array(byteArray).buffer], { type: Browser.getMimetype(name) });
      }
      var url = URL.createObjectURL(b);
      return new Promise((resolve, reject) => {
        var img = new Image();
        img.onload = () => {
          var canvas2 = document.createElement("canvas");
          canvas2.width = img.width;
          canvas2.height = img.height;
          var ctx = canvas2.getContext("2d");
          ctx.drawImage(img, 0, 0);
          Browser.preloadedImages[name] = canvas2;
          URL.revokeObjectURL(url);
          resolve(byteArray);
        };
        img.onerror = (event) => {
          err(`Image ${url} could not be decoded`);
          reject();
        };
        img.src = url;
      });
    };
    preloadPlugins.push(imagePlugin);
    var audioPlugin = {};
    audioPlugin["canHandle"] = (name) => !Module["noAudioDecoding"] && name.slice(-4) in { ".ogg": 1, ".wav": 1, ".mp3": 1 };
    audioPlugin["handle"] = async (byteArray, name) => new Promise((resolve, reject) => {
      var done = false;
      function finish(audio2) {
        if (done) return;
        done = true;
        Browser.preloadedAudios[name] = audio2;
        resolve(byteArray);
      }
      var b = new Blob([byteArray], { type: Browser.getMimetype(name) });
      var url = URL.createObjectURL(b);
      var audio = new Audio();
      audio.addEventListener("canplaythrough", () => finish(audio), false);
      audio.onerror = (event) => {
        if (done) return;
        err(`warning: browser could not fully decode audio ${name}, trying slower base64 approach`);
        function encode64(data) {
          var BASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
          var PAD = "=";
          var ret = "";
          var leftchar = 0;
          var leftbits = 0;
          for (var i = 0; i < data.length; i++) {
            leftchar = leftchar << 8 | data[i];
            leftbits += 8;
            while (leftbits >= 6) {
              var curr = leftchar >> leftbits - 6 & 63;
              leftbits -= 6;
              ret += BASE[curr];
            }
          }
          if (leftbits == 2) {
            ret += BASE[(leftchar & 3) << 4];
            ret += PAD + PAD;
          } else if (leftbits == 4) {
            ret += BASE[(leftchar & 15) << 2];
            ret += PAD;
          }
          return ret;
        }
        audio.src = "data:audio/x-" + name.slice(-3) + ";base64," + encode64(byteArray);
        finish(audio);
      };
      audio.src = url;
      safeSetTimeout(() => {
        finish(audio);
      }, 1e4);
    });
    preloadPlugins.push(audioPlugin);
    function pointerLockChange() {
      var canvas2 = Browser.getCanvas();
      Browser.pointerLock = document.pointerLockElement === canvas2;
    }
    var canvas = Browser.getCanvas();
    if (canvas) {
      document.addEventListener("pointerlockchange", pointerLockChange, false);
      if (Module["elementPointerLock"]) {
        canvas.addEventListener("click", (ev) => {
          if (!Browser.pointerLock && Browser.getCanvas().requestPointerLock) {
            Browser.getCanvas().requestPointerLock();
            ev.preventDefault();
          }
        }, false);
      }
    }
  }, createContext(canvas, useWebGL, setInModule, webGLContextAttributes) {
    if (useWebGL && Module["ctx"] && canvas == Browser.getCanvas()) return Module["ctx"];
    var ctx;
    var contextHandle;
    if (useWebGL) {
      var contextAttributes = { antialias: false, alpha: false, majorVersion: 1 };
      if (webGLContextAttributes) {
        for (var attribute in webGLContextAttributes) {
          contextAttributes[attribute] = webGLContextAttributes[attribute];
        }
      }
      if (typeof GL != "undefined") {
        contextHandle = GL.createContext(canvas, contextAttributes);
        if (contextHandle) {
          ctx = GL.getContext(contextHandle).GLctx;
        }
      }
    } else {
      ctx = canvas.getContext("2d");
    }
    if (!ctx) return null;
    if (setInModule) {
      Module["ctx"] = ctx;
      if (useWebGL) GL.makeContextCurrent(contextHandle);
      Browser.useWebGL = useWebGL;
      Browser.moduleContextCreatedCallbacks.forEach((callback) => callback());
      Browser.init();
    }
    return ctx;
  }, fullscreenHandlersInstalled: false, lockPointer: void 0, resizeCanvas: void 0, requestFullscreen(lockPointer, resizeCanvas) {
    Browser.lockPointer = lockPointer;
    Browser.resizeCanvas = resizeCanvas;
    if (typeof Browser.lockPointer == "undefined") Browser.lockPointer = true;
    if (typeof Browser.resizeCanvas == "undefined") Browser.resizeCanvas = false;
    var canvas = Browser.getCanvas();
    function fullscreenChange() {
      Browser.isFullscreen = false;
      var canvasContainer2 = canvas.parentNode;
      if (getFullscreenElement() === canvasContainer2) {
        canvas.exitFullscreen = Browser.exitFullscreen;
        if (Browser.lockPointer) canvas.requestPointerLock();
        Browser.isFullscreen = true;
        if (Browser.resizeCanvas) {
          Browser.setFullscreenCanvasSize();
        } else {
          Browser.updateCanvasDimensions(canvas);
        }
      } else {
        canvasContainer2.parentNode.insertBefore(canvas, canvasContainer2);
        canvasContainer2.parentNode.removeChild(canvasContainer2);
        if (Browser.resizeCanvas) {
          Browser.setWindowedCanvasSize();
        } else {
          Browser.updateCanvasDimensions(canvas);
        }
      }
      Module["onFullScreen"]?.(Browser.isFullscreen);
      Module["onFullscreen"]?.(Browser.isFullscreen);
    }
    if (!Browser.fullscreenHandlersInstalled) {
      Browser.fullscreenHandlersInstalled = true;
      document.addEventListener("fullscreenchange", fullscreenChange, false);
      document.addEventListener("mozfullscreenchange", fullscreenChange, false);
      document.addEventListener("webkitfullscreenchange", fullscreenChange, false);
      document.addEventListener("MSFullscreenChange", fullscreenChange, false);
    }
    var canvasContainer = document.createElement("div");
    canvas.parentNode.insertBefore(canvasContainer, canvas);
    canvasContainer.appendChild(canvas);
    canvasContainer.requestFullscreen = canvasContainer["requestFullscreen"] || canvasContainer["mozRequestFullScreen"] || canvasContainer["msRequestFullscreen"] || (canvasContainer["webkitRequestFullscreen"] ? () => canvasContainer["webkitRequestFullscreen"](Element["ALLOW_KEYBOARD_INPUT"]) : null) || (canvasContainer["webkitRequestFullScreen"] ? () => canvasContainer["webkitRequestFullScreen"](Element["ALLOW_KEYBOARD_INPUT"]) : null);
    canvasContainer.requestFullscreen();
  }, exitFullscreen() {
    if (!Browser.isFullscreen) {
      return false;
    }
    var CFS = document["exitFullscreen"] || document["cancelFullScreen"] || document["mozCancelFullScreen"] || document["msExitFullscreen"] || document["webkitCancelFullScreen"] || (() => {
    });
    CFS.apply(document, []);
    return true;
  }, safeSetTimeout(func, timeout) {
    return safeSetTimeout(func, timeout);
  }, getMimetype(name) {
    return { jpg: "image/jpeg", jpeg: "image/jpeg", png: "image/png", bmp: "image/bmp", ogg: "audio/ogg", wav: "audio/wav", mp3: "audio/mpeg" }[name.slice(name.lastIndexOf(".") + 1)];
  }, getUserMedia(func) {
    window.getUserMedia ||= navigator["getUserMedia"] || navigator["mozGetUserMedia"];
    window.getUserMedia(func);
  }, getMovementX(event) {
    return event["movementX"] || event["mozMovementX"] || event["webkitMovementX"] || 0;
  }, getMovementY(event) {
    return event["movementY"] || event["mozMovementY"] || event["webkitMovementY"] || 0;
  }, getMouseWheelDelta(event) {
    var delta = 0;
    switch (event.type) {
      case "DOMMouseScroll":
        delta = event.detail / 3;
        break;
      case "mousewheel":
        delta = event.wheelDelta / 120;
        break;
      case "wheel":
        delta = event.deltaY;
        switch (event.deltaMode) {
          case 0:
            delta /= 100;
            break;
          case 1:
            delta /= 3;
            break;
          case 2:
            delta *= 80;
            break;
          default:
            abort("unrecognized mouse wheel delta mode: " + event.deltaMode);
        }
        break;
      default:
        abort("unrecognized mouse wheel event: " + event.type);
    }
    return delta;
  }, mouseX: 0, mouseY: 0, mouseMovementX: 0, mouseMovementY: 0, touches: {}, lastTouches: {}, calculateMouseCoords(pageX, pageY) {
    var canvas = Browser.getCanvas();
    var rect = canvas.getBoundingClientRect();
    var scrollX = typeof window.scrollX != "undefined" ? window.scrollX : window.pageXOffset;
    var scrollY = typeof window.scrollY != "undefined" ? window.scrollY : window.pageYOffset;
    var adjustedX = pageX - (scrollX + rect.left);
    var adjustedY = pageY - (scrollY + rect.top);
    adjustedX = adjustedX * (canvas.width / rect.width);
    adjustedY = adjustedY * (canvas.height / rect.height);
    return { x: adjustedX, y: adjustedY };
  }, setMouseCoords(pageX, pageY) {
    const { x, y } = Browser.calculateMouseCoords(pageX, pageY);
    Browser.mouseMovementX = x - Browser.mouseX;
    Browser.mouseMovementY = y - Browser.mouseY;
    Browser.mouseX = x;
    Browser.mouseY = y;
  }, calculateMouseEvent(event) {
    if (Browser.pointerLock) {
      if (event.type != "mousemove" && "mozMovementX" in event) {
        Browser.mouseMovementX = Browser.mouseMovementY = 0;
      } else {
        Browser.mouseMovementX = Browser.getMovementX(event);
        Browser.mouseMovementY = Browser.getMovementY(event);
      }
      Browser.mouseX += Browser.mouseMovementX;
      Browser.mouseY += Browser.mouseMovementY;
    } else {
      if (event.type === "touchstart" || event.type === "touchend" || event.type === "touchmove") {
        var touch = event.touch;
        if (touch === void 0) {
          return;
        }
        var coords = Browser.calculateMouseCoords(touch.pageX, touch.pageY);
        if (event.type === "touchstart") {
          Browser.lastTouches[touch.identifier] = coords;
          Browser.touches[touch.identifier] = coords;
        } else if (event.type === "touchend" || event.type === "touchmove") {
          var last = Browser.touches[touch.identifier];
          last ||= coords;
          Browser.lastTouches[touch.identifier] = last;
          Browser.touches[touch.identifier] = coords;
        }
        return;
      }
      Browser.setMouseCoords(event.pageX, event.pageY);
    }
  }, resizeListeners: [], updateResizeListeners() {
    var canvas = Browser.getCanvas();
    Browser.resizeListeners.forEach((listener) => listener(canvas.width, canvas.height));
  }, setCanvasSize(width, height, noUpdates) {
    var canvas = Browser.getCanvas();
    Browser.updateCanvasDimensions(canvas, width, height);
    if (!noUpdates) Browser.updateResizeListeners();
  }, windowedWidth: 0, windowedHeight: 0, setFullscreenCanvasSize() {
    if (typeof SDL != "undefined") {
      var flags = HEAPU32[SDL.screen >>> 2 >>> 0];
      flags = flags | 8388608;
      HEAP32[SDL.screen >>> 2 >>> 0] = flags;
    }
    Browser.updateCanvasDimensions(Browser.getCanvas());
    Browser.updateResizeListeners();
  }, setWindowedCanvasSize() {
    if (typeof SDL != "undefined") {
      var flags = HEAPU32[SDL.screen >>> 2 >>> 0];
      flags = flags & ~8388608;
      HEAP32[SDL.screen >>> 2 >>> 0] = flags;
    }
    Browser.updateCanvasDimensions(Browser.getCanvas());
    Browser.updateResizeListeners();
  }, updateCanvasDimensions(canvas, wNative, hNative) {
    if (wNative && hNative) {
      canvas.widthNative = wNative;
      canvas.heightNative = hNative;
    } else {
      wNative = canvas.widthNative;
      hNative = canvas.heightNative;
    }
    var w = wNative;
    var h = hNative;
    if (Module["forcedAspectRatio"] > 0) {
      if (w / h < Module["forcedAspectRatio"]) {
        w = Math.round(h * Module["forcedAspectRatio"]);
      } else {
        h = Math.round(w / Module["forcedAspectRatio"]);
      }
    }
    if (getFullscreenElement() === canvas.parentNode && typeof screen != "undefined") {
      var factor = Math.min(screen.width / w, screen.height / h);
      w = Math.round(w * factor);
      h = Math.round(h * factor);
    }
    if (Browser.resizeCanvas) {
      if (canvas.width != w) canvas.width = w;
      if (canvas.height != h) canvas.height = h;
      if (typeof canvas.style != "undefined") {
        canvas.style.removeProperty("width");
        canvas.style.removeProperty("height");
      }
    } else {
      if (canvas.width != wNative) canvas.width = wNative;
      if (canvas.height != hNative) canvas.height = hNative;
      if (typeof canvas.style != "undefined") {
        if (w != wNative || h != hNative) {
          canvas.style.setProperty("width", w + "px", "important");
          canvas.style.setProperty("height", h + "px", "important");
        } else {
          canvas.style.removeProperty("width");
          canvas.style.removeProperty("height");
        }
      }
    }
  } };
  var getPreloadedImageData = (path, w, h) => {
    path = PATH_FS.resolve(path);
    var canvas = Browser.preloadedImages[path];
    if (!canvas) return 0;
    var ctx = canvas.getContext("2d");
    var image = ctx.getImageData(0, 0, canvas.width, canvas.height);
    var buf = _malloc(canvas.width * canvas.height * 4);
    HEAPU8.set(image.data, buf >>> 0);
    HEAP32[w >>> 2 >>> 0] = canvas.width;
    HEAP32[h >>> 2 >>> 0] = canvas.height;
    return buf;
  };
  function _emscripten_get_preloaded_image_data(path, w, h) {
    path >>>= 0;
    w >>>= 0;
    h >>>= 0;
    return getPreloadedImageData(UTF8ToString(path), w, h);
  }
  var alignMemory = (size, alignment) => Math.ceil(size / alignment) * alignment;
  var growMemory = (size) => {
    var oldHeapSize = wasmMemory.buffer.byteLength;
    var pages = (size - oldHeapSize + 65535) / 65536 | 0;
    try {
      wasmMemory.grow(pages);
      updateMemoryViews();
      return 1;
    } catch (e) {
    }
  };
  function _emscripten_resize_heap(requestedSize) {
    requestedSize >>>= 0;
    var oldSize = HEAPU8.length;
    var maxHeapSize = getHeapMax();
    if (requestedSize > maxHeapSize) {
      return false;
    }
    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, alignMemory(Math.max(requestedSize, overGrownHeapSize), 65536));
      var replacement = growMemory(newSize);
      if (replacement) {
        return true;
      }
    }
    return false;
  }
  var ENV = {};
  var getExecutableName = () => thisProgram || "./this.program";
  var getEnvStrings = () => {
    if (!getEnvStrings.strings) {
      var lang = (globalThis.navigator?.language ?? "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] === void 0) 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;
  };
  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 >>> 0];
      var len = HEAPU32[iov + 4 >>> 2 >>> 0];
      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_read(fd, iov, iovcnt, pnum) {
    iov >>>= 0;
    iovcnt >>>= 0;
    pnum >>>= 0;
    try {
      var stream = SYSCALLS.getStreamFromFD(fd);
      var num = doReadv(stream, iov, iovcnt);
      HEAPU32[pnum >>> 2 >>> 0] = num;
      return 0;
    } catch (e) {
      if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
      return e.errno;
    }
  }
  function _fd_seek(fd, offset, whence, newOffset) {
    offset = bigintToI53Checked(offset);
    newOffset >>>= 0;
    try {
      if (isNaN(offset)) return 61;
      var stream = SYSCALLS.getStreamFromFD(fd);
      FS.llseek(stream, offset, whence);
      HEAP64[newOffset >>> 3 >>> 0] = BigInt(stream.position);
      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 >>> 0];
      var len = HEAPU32[iov + 4 >>> 2 >>> 0];
      iov += 8;
      var curr = FS.write(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_write(fd, iov, iovcnt, pnum) {
    iov >>>= 0;
    iovcnt >>>= 0;
    pnum >>>= 0;
    try {
      var stream = SYSCALLS.getStreamFromFD(fd);
      var num = doWritev(stream, iov, iovcnt);
      HEAPU32[pnum >>> 2 >>> 0] = num;
      return 0;
    } catch (e) {
      if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
      return e.errno;
    }
  }
  var getCppExceptionTag = () => ___cpp_exception;
  var getCppExceptionThrownObjectFromWebAssemblyException = (ex) => {
    var unwind_header = ex.getArg(getCppExceptionTag(), 0);
    return ___thrown_object_from_unwind_exception(unwind_header);
  };
  var incrementExceptionRefcount = (ex) => {
    var ptr = getCppExceptionThrownObjectFromWebAssemblyException(ex);
    ___cxa_increment_exception_refcount(ptr);
  };
  var decrementExceptionRefcount = (ex) => {
    var ptr = getCppExceptionThrownObjectFromWebAssemblyException(ex);
    ___cxa_decrement_exception_refcount(ptr);
  };
  var stackSave = () => _emscripten_stack_get_current();
  var stackRestore = (val) => __emscripten_stack_restore(val);
  var stackAlloc = (sz) => __emscripten_stack_alloc(sz);
  var getExceptionMessageCommon = (ptr) => {
    var sp = stackSave();
    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 >>> 0];
    var message_addr = HEAPU32[message_addr_addr >>> 2 >>> 0];
    var type = UTF8ToString(type_addr);
    _free(type_addr);
    var message;
    if (message_addr) {
      message = UTF8ToString(message_addr);
      _free(message_addr);
    }
    stackRestore(sp);
    return [type, message];
  };
  var getExceptionMessage = (ex) => {
    var ptr = getCppExceptionThrownObjectFromWebAssemblyException(ex);
    return getExceptionMessageCommon(ptr);
  };
  FS.createPreloadedFile = FS_createPreloadedFile;
  FS.preloadFile = FS_preloadFile;
  FS.staticInit();
  init_ClassHandle();
  init_RegisteredPointer();
  {
    if (Module["noExitRuntime"]) noExitRuntime = Module["noExitRuntime"];
    if (Module["preloadPlugins"]) preloadPlugins = Module["preloadPlugins"];
    if (Module["print"]) out = Module["print"];
    if (Module["printErr"]) err = Module["printErr"];
    if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"];
    if (Module["arguments"]) arguments_ = Module["arguments"];
    if (Module["thisProgram"]) thisProgram = Module["thisProgram"];
    if (Module["preInit"]) {
      if (typeof Module["preInit"] == "function") Module["preInit"] = [Module["preInit"]];
      while (Module["preInit"].length > 0) {
        Module["preInit"].shift()();
      }
    }
  }
  Module["FS"] = FS;
  Module["incrementExceptionRefcount"] = incrementExceptionRefcount;
  Module["decrementExceptionRefcount"] = decrementExceptionRefcount;
  Module["getExceptionMessage"] = getExceptionMessage;
  function OSD_MemInfo_getModuleHeapLength() {
    return Module.HEAP8.length;
  }
  var ___getTypeName, _malloc, _free, _htons, __emscripten_timeout, ___trap, __emscripten_stack_restore, __emscripten_stack_alloc, _emscripten_stack_get_current, ___cxa_decrement_exception_refcount, ___cxa_increment_exception_refcount, ___thrown_object_from_unwind_exception, ___get_exception_message, memory, __indirect_function_table, ___cpp_exception, wasmMemory, wasmTable;
  function assignWasmExports(wasmExports2) {
    ___getTypeName = wasmExports2["ca"];
    _malloc = wasmExports2["ea"];
    _free = wasmExports2["ga"];
    _htons = wasmExports2["ha"];
    __emscripten_timeout = wasmExports2["ia"];
    ___trap = wasmExports2["ja"];
    __emscripten_stack_restore = wasmExports2["ka"];
    __emscripten_stack_alloc = wasmExports2["la"];
    _emscripten_stack_get_current = wasmExports2["ma"];
    ___cxa_decrement_exception_refcount = wasmExports2["na"];
    ___cxa_increment_exception_refcount = wasmExports2["oa"];
    ___thrown_object_from_unwind_exception = wasmExports2["pa"];
    ___get_exception_message = wasmExports2["qa"];
    memory = wasmMemory = wasmExports2["aa"];
    __indirect_function_table = wasmTable = wasmExports2["da"];
    ___cpp_exception = wasmExports2["fa"];
  }
  var wasmImports = { V: OSD_MemInfo_getModuleHeapLength, D: ___call_sighandler, R: ___syscall_chmod, S: ___syscall_faccessat, o: ___syscall_fcntl64, O: ___syscall_fstat64, H: ___syscall_getdents64, U: ___syscall_ioctl, M: ___syscall_lstat64, J: ___syscall_mkdirat, L: ___syscall_newfstatat, u: ___syscall_openat, s: ___syscall_rmdir, N: ___syscall_stat64, t: ___syscall_unlinkat, G: __abort_js, h: __embind_finalize_value_object, y: __embind_register_bigint, _: __embind_register_bool, g: __embind_register_class, i: __embind_register_class_constructor, a: __embind_register_class_function, b: __embind_register_class_property, Y: __embind_register_emval, x: __embind_register_float, f: __embind_register_integer, l: __embind_register_iterable, d: __embind_register_memory_view, m: __embind_register_optional, Z: __embind_register_std_string, p: __embind_register_std_wstring, n: __embind_register_value_object, c: __embind_register_value_object_field, $: __embind_register_void, A: __emscripten_lookup_name, F: __emscripten_runtime_keepalive_clear, k: __emval_create_invoker, r: __emval_invoke, q: __emval_run_destructors, I: __localtime_js, z: __setitimer_js, T: __tzset_js, Q: _clock_time_get, P: _emscripten_date_now, W: _emscripten_get_callstack, C: _emscripten_get_heap_max, X: _emscripten_get_preloaded_image_data, B: _emscripten_resize_heap, e: _exit, j: _fd_close, w: _fd_read, K: _fd_seek, v: _fd_write, E: _proc_exit };
  function applySignatureConversions(wasmExports2) {
    wasmExports2 = Object.assign({}, wasmExports2);
    var makeWrapper_pp = (f) => (a0) => f(a0) >>> 0;
    var makeWrapper_p = (f) => () => f() >>> 0;
    wasmExports2["ca"] = makeWrapper_pp(wasmExports2["ca"]);
    wasmExports2["ea"] = makeWrapper_pp(wasmExports2["ea"]);
    wasmExports2["la"] = makeWrapper_pp(wasmExports2["la"]);
    wasmExports2["ma"] = makeWrapper_p(wasmExports2["ma"]);
    return wasmExports2;
  }
  function run() {
    if (runDependencies > 0) {
      dependenciesFulfilled = run;
      return;
    }
    preRun();
    if (runDependencies > 0) {
      dependenciesFulfilled = run;
      return;
    }
    function doRun() {
      Module["calledRun"] = true;
      if (ABORT) return;
      initRuntime();
      readyPromiseResolve?.(Module);
      Module["onRuntimeInitialized"]?.();
      postRun();
    }
    if (Module["setStatus"]) {
      Module["setStatus"]("Running...");
      setTimeout(() => {
        setTimeout(() => Module["setStatus"](""), 1);
        doRun();
      }, 1);
    } else {
      doRun();
    }
  }
  var wasmExports;
  wasmExports = await createWasm();
  run();
  if (typeof Symbol !== "undefined" && Symbol.dispose) {
    const proto = Module["__proto__"] || Object.getPrototypeOf(Module);
    for (const key of Object.getOwnPropertyNames(Module)) {
      const val = Module[key];
      if (typeof val === "function" && val.prototype && typeof val.prototype.delete === "function" && !val.prototype[Symbol.dispose]) {
        val.prototype[Symbol.dispose] = function() {
          if (!this.isDeleted()) {
            this.delete();
          }
        };
      }
    }
  }
  if (runtimeInitialized) {
    moduleRtn = Module;
  } else {
    moduleRtn = new Promise((resolve, reject) => {
      readyPromiseResolve = resolve;
      readyPromiseReject = reject;
    });
  }
  ;
  return moduleRtn;
}
var occt_wasm_default;
var init_occt_wasm = __esm({
  "dist/occt-wasm.js"() {
    occt_wasm_default = createOcctWasm;
  }
});

// dist/types.js
var SHAPE_TYPES = [
  "compound",
  "compsolid",
  "solid",
  "shell",
  "face",
  "wire",
  "edge",
  "vertex",
  "shape"
];
var SHAPE_ORIENTATIONS = ["forward", "reversed", "internal", "external"];
var POINT_CLASSIFICATIONS = ["in", "on", "out"];
var TransitionMode;
(function(TransitionMode2) {
  TransitionMode2[TransitionMode2["Transformed"] = 0] = "Transformed";
  TransitionMode2[TransitionMode2["RightCorner"] = 1] = "RightCorner";
  TransitionMode2[TransitionMode2["RoundCorner"] = 2] = "RoundCorner";
})(TransitionMode || (TransitionMode = {}));
var SweepMode;
(function(SweepMode2) {
  SweepMode2[SweepMode2["Fixed"] = 0] = "Fixed";
  SweepMode2[SweepMode2["Frenet"] = 1] = "Frenet";
  SweepMode2[SweepMode2["FixedUp"] = 2] = "FixedUp";
  SweepMode2[SweepMode2["Auxiliary"] = 3] = "Auxiliary";
})(SweepMode || (SweepMode = {}));
var SweepContact;
(function(SweepContact2) {
  SweepContact2[SweepContact2["None"] = 0] = "None";
  SweepContact2[SweepContact2["Contact"] = 1] = "Contact";
  SweepContact2[SweepContact2["ContactOnBorder"] = 2] = "ContactOnBorder";
})(SweepContact || (SweepContact = {}));
var SweepLaw;
(function(SweepLaw2) {
  SweepLaw2[SweepLaw2["None"] = 0] = "None";
  SweepLaw2[SweepLaw2["Linear"] = 1] = "Linear";
  SweepLaw2[SweepLaw2["SCurve"] = 2] = "SCurve";
})(SweepLaw || (SweepLaw = {}));
var JoinType;
(function(JoinType2) {
  JoinType2[JoinType2["Arc"] = 0] = "Arc";
  JoinType2[JoinType2["Tangent"] = 1] = "Tangent";
  JoinType2[JoinType2["Intersection"] = 2] = "Intersection";
})(JoinType || (JoinType = {}));
var BooleanOp;
(function(BooleanOp2) {
  BooleanOp2[BooleanOp2["Fuse"] = 0] = "Fuse";
  BooleanOp2[BooleanOp2["Cut"] = 1] = "Cut";
  BooleanOp2[BooleanOp2["Common"] = 2] = "Common";
})(BooleanOp || (BooleanOp = {}));
var OcctErrorCode;
(function(OcctErrorCode2) {
  OcctErrorCode2["ConstructionFailed"] = "CONSTRUCTION_FAILED";
  OcctErrorCode2["BooleanFailed"] = "BOOLEAN_FAILED";
  OcctErrorCode2["InvalidShapeId"] = "INVALID_SHAPE_ID";
  OcctErrorCode2["InvalidLabelId"] = "INVALID_LABEL_ID";
  OcctErrorCode2["TessellationFailed"] = "TESSELLATION_FAILED";
  OcctErrorCode2["ImportExportFailed"] = "IMPORT_EXPORT_FAILED";
  OcctErrorCode2["HealingFailed"] = "HEALING_FAILED";
  OcctErrorCode2["DocumentClosed"] = "DOCUMENT_CLOSED";
  OcctErrorCode2["KernelError"] = "KERNEL_ERROR";
  OcctErrorCode2["Unknown"] = "UNKNOWN";
})(OcctErrorCode || (OcctErrorCode = {}));
var OcctError = class extends Error {
  /** Name of the kernel method that failed. */
  operation;
  /** Structured error code for programmatic handling. */
  code;
  constructor(operation, message, code) {
    super(`${operation}: ${message}`);
    this.name = "OcctError";
    this.operation = operation;
    this.code = code ?? classifyError(operation, message);
  }
};
var BOOLEAN_OPS = /* @__PURE__ */ new Set(["fuse", "cut", "common", "intersect", "section", "fuseAll", "cutAll", "split", "booleanPipeline", "fuseWithHistory", "cutWithHistory", "intersectWithHistory"]);
var TESSELLATION_OPS = /* @__PURE__ */ new Set(["tessellate", "wireframe", "meshShape", "meshBatch"]);
var IO_OPS = /* @__PURE__ */ new Set(["importStep", "exportStep", "importStl", "exportStl", "toBREP", "fromBREP", "xcafExportSTEP", "xcafImportSTEP", "xcafExportGLTF"]);
var HEALING_OPS = /* @__PURE__ */ new Set(["fixShape", "unifySameDomain", "healSolid", "healFace", "healWire", "fixFaceOrientations", "removeDegenerateEdges", "fixWireOnFace", "buildCurves3d"]);
function classifyError(operation, message) {
  const msg = message.toLowerCase();
  if (msg.includes("invalid shape id"))
    return OcctErrorCode.InvalidShapeId;
  if (msg.includes("invalid label id"))
    return OcctErrorCode.InvalidLabelId;
  if (msg.includes("document is closed"))
    return OcctErrorCode.DocumentClosed;
  if (msg.includes("boolean operation failed"))
    return OcctErrorCode.BooleanFailed;
  if (msg.includes("construction failed"))
    return OcctErrorCode.ConstructionFailed;
  if (msg.includes("does not intersect the guide wire"))
    return OcctErrorCode.ConstructionFailed;
  if (msg.includes("in contact with the guide wire"))
    return OcctErrorCode.ConstructionFailed;
  if (BOOLEAN_OPS.has(operation))
    return OcctErrorCode.BooleanFailed;
  if (TESSELLATION_OPS.has(operation))
    return OcctErrorCode.TessellationFailed;
  if (IO_OPS.has(operation))
    return OcctErrorCode.ImportExportFailed;
  if (HEALING_OPS.has(operation))
    return OcctErrorCode.HealingFailed;
  if (msg.includes("operation failed"))
    return OcctErrorCode.ConstructionFailed;
  if (operation && operation !== "XCAFDocument")
    return OcctErrorCode.KernelError;
  return OcctErrorCode.Unknown;
}
var exceptionDecoders = /* @__PURE__ */ new Set();
function addExceptionDecoder(decoder) {
  exceptionDecoders.add(decoder);
  return () => {
    exceptionDecoders.delete(decoder);
  };
}
function messageOf(e) {
  if (e instanceof Error)
    return e.message;
  for (const decoder of exceptionDecoders) {
    try {
      const decoded = decoder(e);
      if (decoded?.[1])
        return decoded[1];
    } catch {
    }
  }
  return String(e);
}
function wrap(operation, fn) {
  try {
    return fn();
  } catch (e) {
    if (e instanceof OcctError) {
      throw new OcctError(operation, e.message, e.code);
    }
    const message = messageOf(e);
    const prefix = `${operation}: `;
    throw new OcctError(operation, message.startsWith(prefix) ? message.slice(prefix.length) : message);
  }
}

// dist/xcaf-document.js
function tag(n) {
  return n;
}
var XCAFDocument = class _XCAFDocument {
  #raw;
  #docId;
  #fs;
  #closed = false;
  constructor(raw, docId, fs) {
    this.#raw = raw;
    this.#docId = docId;
    this.#fs = fs;
  }
  /** Create a new empty XCAF document. */
  static create(raw, fs) {
    const docId = wrap("xcafNewDocument", () => raw.xcafNewDocument());
    return new _XCAFDocument(raw, docId, fs);
  }
  /** Import a STEP file into a new XCAF document (preserves colors/names/assemblies). */
  static fromSTEP(raw, stepData, fs) {
    const docId = wrap("xcafImportSTEP", () => raw.xcafImportSTEP(stepData));
    return new _XCAFDocument(raw, docId, fs);
  }
  /** Add a shape as a root label. */
  addShape(shape, options) {
    this.#ensureOpen();
    const t = wrap("xcafAddShape", () => this.#raw.xcafAddShape(this.#docId, shape));
    this.#applyOptions(t, options);
    return tag(t);
  }
  /** Add a shape as a child component of a parent label. */
  addChild(parent, shape, options) {
    this.#ensureOpen();
    const loc = options?.location ?? {};
    const t = wrap("xcafAddComponent", () => this.#raw.xcafAddComponent(this.#docId, parent, shape, loc.tx ?? 0, loc.ty ?? 0, loc.tz ?? 0, loc.rx ?? 0, loc.ry ?? 0, loc.rz ?? 0));
    this.#applyOptions(t, options);
    return tag(t);
  }
  /** Set color on an existing label. */
  setColor(label, color) {
    this.#ensureOpen();
    const [r, g, b] = color;
    wrap("xcafSetColor", () => this.#raw.xcafSetColor(this.#docId, label, r, g, b));
  }
  /** Set name on an existing label. */
  setName(label, name) {
    this.#ensureOpen();
    wrap("xcafSetName", () => this.#raw.xcafSetName(this.#docId, label, name));
  }
  /**
   * Get info about a label.
   * If `shapeHandle` is non-null, the caller owns it and must release it.
   */
  getLabelInfo(label) {
    this.#ensureOpen();
    const raw = wrap("xcafGetLabelInfo", () => this.#raw.xcafGetLabelInfo(this.#docId, label));
    return {
      labelId: raw.labelId,
      name: raw.name,
      hasColor: raw.hasColor,
      color: [raw.r, raw.g, raw.b],
      isAssembly: raw.isAssembly,
      isComponent: raw.isComponent,
      shapeHandle: raw.shapeId > 0 ? raw.shapeId : null
    };
  }
  /** Get child label tags of a parent. */
  getChildren(parent) {
    this.#ensureOpen();
    return this.#vecToTags(wrap("xcafGetChildLabels", () => this.#raw.xcafGetChildLabels(this.#docId, parent)));
  }
  /** Get root (free) shape label tags. */
  getRoots() {
    this.#ensureOpen();
    return this.#vecToTags(wrap("xcafGetRootLabels", () => this.#raw.xcafGetRootLabels(this.#docId)));
  }
  /** Export as STEP with colors and names preserved. */
  exportSTEP() {
    this.#ensureOpen();
    return wrap("xcafExportSTEP", () => this.#raw.xcafExportSTEP(this.#docId));
  }
  exportGLTF(fsOrOptions, maybeOptions) {
    this.#ensureOpen();
    let fs;
    let options;
    if (fsOrOptions && typeof fsOrOptions === "object" && "readFile" in fsOrOptions && "unlink" in fsOrOptions) {
      fs = fsOrOptions;
      options = maybeOptions;
    } else {
      const opts = fsOrOptions;
      fs = opts?.fs;
      options = opts;
    }
    fs ??= this.#fs;
    if (!fs) {
      throw new OcctError("xcafExportGLTF", "No Emscripten FS available. Either create the document via OcctKernel.createXCAFDocument(), or pass { fs } in options.");
    }
    const linDefl = options?.linearDeflection ?? 0.1;
    const angDefl = options?.angularDeflection ?? 0.5;
    const glbPath = wrap("xcafExportGLTF", () => this.#raw.xcafExportGLTF(this.#docId, linDefl, angDefl));
    const data = fs.readFile(glbPath);
    fs.unlink(glbPath);
    return data;
  }
  /** Close the document and free OCCT resources. */
  close() {
    if (this.#closed)
      return;
    this.#closed = true;
    wrap("xcafClose", () => this.#raw.xcafClose(this.#docId));
  }
  [Symbol.dispose]() {
    this.close();
  }
  #applyOptions(labelId, options) {
    if (options?.name) {
      wrap("xcafSetName", () => this.#raw.xcafSetName(this.#docId, labelId, options.name));
    }
    if (options?.color) {
      const [r, g, b] = options.color;
      wrap("xcafSetColor", () => this.#raw.xcafSetColor(this.#docId, labelId, r, g, b));
    }
  }
  #vecToTags(vec) {
    try {
      const result = [];
      for (let i = 0; i < vec.size(); i++) {
        result.push(tag(vec.get(i)));
      }
      return result;
    } finally {
      vec.delete();
    }
  }
  #ensureOpen() {
    if (this.#closed) {
      throw new OcctError("XCAFDocument", "Document is closed", OcctErrorCode.DocumentClosed);
    }
  }
};

// dist/svg.js
var ORIGIN = { x: 0, y: 0, z: 0 };
function basisFor(view) {
  switch (view) {
    case "front":
      return { dir: v(0, 1, 0), sx: v(1, 0, 0), sy: v(0, 0, 1) };
    case "back":
      return { dir: v(0, -1, 0), sx: v(-1, 0, 0), sy: v(0, 0, 1) };
    case "top":
      return { dir: v(0, 0, -1), sx: v(1, 0, 0), sy: v(0, 1, 0) };
    case "bottom":
      return { dir: v(0, 0, 1), sx: v(1, 0, 0), sy: v(0, -1, 0) };
    case "right":
      return { dir: v(-1, 0, 0), sx: v(0, 1, 0), sy: v(0, 0, 1) };
    case "left":
      return { dir: v(1, 0, 0), sx: v(0, -1, 0), sy: v(0, 0, 1) };
    case "iso": {
      const dir = normalize(v(-1, -1, -1));
      const sx = normalize(v(1, -1, 0));
      let sy = cross(dir, sx);
      if (sy.z < 0)
        sy = neg(sy);
      return { dir, sx, sy };
    }
  }
}
var VIEW_LABEL = {
  front: "Front",
  back: "Back",
  top: "Top",
  bottom: "Bottom",
  left: "Left",
  right: "Right",
  iso: "Iso"
};
function v(x, y, z) {
  return { x, y, z };
}
function dot(a, b) {
  return a.x * b.x + a.y * b.y + a.z * b.z;
}
function cross(a, b) {
  return {
    x: a.y * b.z - a.z * b.y,
    y: a.z * b.x - a.x * b.z,
    z: a.x * b.y - a.y * b.x
  };
}
function neg(a) {
  return { x: -a.x, y: -a.y, z: -a.z };
}
function normalize(a) {
  const len = Math.hypot(a.x, a.y, a.z) || 1;
  return { x: a.x / len, y: a.y / len, z: a.z / len };
}
var PROJECTION_FIELDS = [
  "visibleOutline",
  "visibleSmooth",
  "visibleSharp",
  "hiddenOutline",
  "hiddenSmooth",
  "hiddenSharp"
];
function collectEdges(kernel, shape, basis, deflection) {
  const proj = kernel.projectEdges(shape, ORIGIN, basis.dir, basis.sx);
  try {
    const toLines = (h) => {
      if (Number(h) === 0)
        return [];
      const { points, edgeGroups } = kernel.wireframe(h, deflection);
      const lines = [];
      for (let g = 0; g < edgeGroups.length; g += 3) {
        const start = edgeGroups[g];
        const count = edgeGroups[g + 1];
        const line = [];
        for (let i = 0; i < count; i += 3) {
          const p = v(points[start + i], points[start + i + 1], points[start + i + 2]);
          line.push(dot(p, basis.sx), dot(p, basis.sy));
        }
        if (line.length >= 4)
          lines.push(line);
      }
      return lines;
    };
    return {
      visible: [
        ...toLines(proj.visibleOutline),
        ...toLines(proj.visibleSmooth),
        ...toLines(proj.visibleSharp)
      ],
      hidden: [
        ...toLines(proj.hiddenOutline),
        ...toLines(proj.hiddenSmooth),
        ...toLines(proj.hiddenSharp)
      ]
    };
  } finally {
    for (const field of PROJECTION_FIELDS) {
      const h = proj[field];
      if (Number(h) !== 0)
        kernel.release(h);
    }
  }
}
function round(n) {
  return Math.round(n * 100) / 100;
}
function esc(s) {
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
}
function extentOf(views) {
  let minU = Infinity;
  let maxU = -Infinity;
  let minV = Infinity;
  let maxV = -Infinity;
  for (const view of views) {
    for (const line of [...view.visible, ...view.hidden]) {
      for (let i = 0; i < line.length; i += 2) {
        const u = line[i];
        const vv = line[i + 1];
        if (u < minU)
          minU = u;
        if (u > maxU)
          maxU = u;
        if (vv < minV)
          minV = vv;
        if (vv > maxV)
          maxV = vv;
      }
    }
  }
  if (!Number.isFinite(minU))
    return { minU: 0, maxU: 0, minV: 0, maxV: 0 };
  return { minU, maxU, minV, maxV };
}
function panelTransform(ext, scale, panelW, panelH, pad) {
  const midU = (ext.minU + ext.maxU) / 2;
  const midV = (ext.minV + ext.maxV) / 2;
  const offsetX = panelW / 2 - midU * scale;
  const offsetY = panelH / 2 + midV * scale;
  return { scale, offsetX, offsetY, inner: Math.min(panelW, panelH) - 2 * pad, panelW, panelH, pad };
}
function pathData(lines, t) {
  let d = "";
  for (const line of lines) {
    for (let i = 0; i < line.length; i += 2) {
      const x = round(line[i] * t.scale + t.offsetX);
      const y = round(-line[i + 1] * t.scale + t.offsetY);
      d += `${i === 0 ? "M" : "L"}${x} ${y}`;
    }
  }
  return d;
}
function gnomon(basis, t) {
  const len = 18;
  const ox = t.pad + len + 4;
  const oy = t.panelH - t.pad - len - 4;
  const axes = [
    [v(1, 0, 0), "#d33", "X"],
    [v(0, 1, 0), "#3a3", "Y"],
    [v(0, 0, 1), "#36c", "Z"]
  ];
  let s = "";
  for (const [axis, color, name] of axes) {
    const dx = dot(axis, basis.sx);
    const dy = -dot(axis, basis.sy);
    if (Math.hypot(dx, dy) < 0.05)
      continue;
    const ex = round(ox + dx * len);
    const ey = round(oy + dy * len);
    s += `<line x1="${round(ox)}" y1="${round(oy)}" x2="${ex}" y2="${ey}" stroke="${color}" stroke-width="1.5"/>`;
    s += `<text x="${ex}" y="${ey}" font-size="9" fill="${color}" text-anchor="middle" dominant-baseline="middle">${name}</text>`;
  }
  return s;
}
function resolved(options) {
  return {
    width: options.width ?? 240,
    height: options.height ?? 240,
    padding: options.padding ?? 14,
    showHidden: options.showHidden ?? true,
    showGnomon: options.showGnomon ?? true,
    strokeWidth: options.strokeWidth ?? 1,
    background: options.background ?? "#ffffff",
    visibleColor: options.visibleColor ?? "#111111",
    hiddenColor: options.hiddenColor ?? "#9aa0a6"
  };
}
function deflectionFor(kernel, shape, options) {
  if (options.deflection !== void 0)
    return options.deflection;
  const bb = kernel.getBoundingBox(shape, false);
  const diag = Math.hypot(bb.xmax - bb.xmin, bb.ymax - bb.ymin, bb.zmax - bb.zmin);
  return Math.max(diag * 2e-3, 1e-4);
}
function panelSvg(edges, basis, t, o, label) {
  let body = `<rect x="0.5" y="0.5" width="${t.panelW - 1}" height="${t.panelH - 1}" fill="${o.background}" stroke="#e0e0e0"/>`;
  if (o.showHidden && edges.hidden.length > 0) {
    const d = pathData(edges.hidden, t);
    if (d)
      body += `<path d="${d}" fill="none" stroke="${o.hiddenColor}" stroke-width="${o.strokeWidth}" stroke-dasharray="3 2"/>`;
  }
  if (edges.visible.length > 0) {
    const d = pathData(edges.visible, t);
    if (d)
      body += `<path d="${d}" fill="none" stroke="${o.visibleColor}" stroke-width="${o.strokeWidth}" stroke-linejoin="round" stroke-linecap="round"/>`;
  }
  if (o.showGnomon)
    body += gnomon(basis, t);
  if (label !== null)
    body += `<text x="${t.pad}" y="${t.pad + 4}" font-size="11" fill="#333" font-family="sans-serif">${esc(label)}</text>`;
  return body;
}
function renderShapeSVG(kernel, shape, view = "front", options = {}) {
  const o = resolved(options);
  const basis = basisFor(view);
  const deflection = deflectionFor(kernel, shape, options);
  const edges = collectEdges(kernel, shape, basis, deflection);
  const ext = extentOf([edges]);
  const inner = Math.min(o.width, o.height) - 2 * o.padding;
  const range = Math.max(ext.maxU - ext.minU, ext.maxV - ext.minV, 1e-9);
  const scale = inner / range;
  const t = panelTransform(ext, scale, o.width, o.height, o.padding);
  const body = panelSvg(edges, basis, t, o, null);
  return `<svg xmlns="http://www.w3.org/2000/svg" width="${o.width}" height="${o.height}" viewBox="0 0 ${o.width} ${o.height}">${body}</svg>`;
}
function renderMultiviewSVG(kernel, shape, options = {}) {
  const o = resolved(options);
  const views = options.views ?? ["front", "top", "right", "iso"];
  const columns = options.columns ?? 2;
  const showLabels = options.showLabels ?? true;
  const showDimensions = options.showDimensions ?? true;
  const deflection = deflectionFor(kernel, shape, options);
  const bases = views.map(basisFor);
  const edges = bases.map((b) => collectEdges(kernel, shape, b, deflection));
  const extents = edges.map((e) => extentOf([e]));
  const inner = Math.min(o.width, o.height) - 2 * o.padding;
  let maxRange = 1e-9;
  for (const ext of extents) {
    maxRange = Math.max(maxRange, ext.maxU - ext.minU, ext.maxV - ext.minV);
  }
  const scale = inner / maxRange;
  const rows = Math.ceil(views.length / columns);
  const footerH = showDimensions ? 22 : 0;
  const totalW = columns * o.width;
  const totalH = rows * o.height + footerH;
  let panels = "";
  for (let i = 0; i < views.length; i++) {
    const col = i % columns;
    const row = Math.floor(i / columns);
    const px = col * o.width;
    const py = row * o.height;
    const t = panelTransform(extents[i], scale, o.width, o.height, o.padding);
    const label = showLabels ? VIEW_LABEL[views[i]] : null;
    panels += `<g transform="translate(${px} ${py})">${panelSvg(edges[i], bases[i], t, o, label)}</g>`;
  }
  let footer = "";
  if (showDimensions) {
    const bb = kernel.getBoundingBox(shape, false);
    const dims = `${round(bb.xmax - bb.xmin)} \xD7 ${round(bb.ymax - bb.ymin)} \xD7 ${round(bb.zmax - bb.zmin)} (X\xD7Y\xD7Z)`;
    footer = `<text x="${totalW / 2}" y="${rows * o.height + 15}" font-size="11" fill="#444" font-family="sans-serif" text-anchor="middle">${esc(dims)}</text>`;
  }
  return `<svg xmlns="http://www.w3.org/2000/svg" width="${totalW}" height="${totalH}" viewBox="0 0 ${totalW} ${totalH}"><rect width="${totalW}" height="${totalH}" fill="${o.background}"/>${panels}${footer}</svg>`;
}

// dist/index.js
var _a;
function handle(id) {
  return id;
}
var SHAPE_TYPE_VALUES = new Set(SHAPE_TYPES);
var SHAPE_ORIENTATION_VALUES = new Set(SHAPE_ORIENTATIONS);
var POINT_CLASSIFICATION_VALUES = new Set(POINT_CLASSIFICATIONS);
function asEnum(value, allowed, label) {
  if (!allowed.has(value)) {
    throw new Error(`unexpected ${label} from kernel: "${value}"`);
  }
  return value;
}
var kernelRegistry = new FinalizationRegistry(({ raw, releaseDecoder }) => {
  releaseDecoder();
  try {
    raw.releaseAll();
    raw.delete();
  } catch {
  }
});
var OcctKernel = class {
  #raw;
  #module;
  #releaseDecoder;
  constructor(module) {
    this.#module = module;
    this.#raw = new module.OcctKernel();
    this.#releaseDecoder = addExceptionDecoder((e) => module.getExceptionMessage?.(e));
    kernelRegistry.register(this, { raw: this.#raw, releaseDecoder: this.#releaseDecoder }, this);
  }
  /**
   * Initialize the WASM module and create a kernel instance.
   *
   * @example
   * ```ts
   * // Auto-detect (works in browser, Node.js, and Workers):
   * const kernel = await OcctKernel.init();
   *
   * // Explicit WASM location:
   * const kernel = await OcctKernel.init({ wasm: '/path/to/occt-wasm.wasm' });
   *
   * // From pre-fetched binary:
   * const binary = await fetch('/occt-wasm.wasm').then(r => r.arrayBuffer());
   * const kernel = await OcctKernel.init({ wasm: binary });
   * ```
   */
  static async init(options) {
    const imported = await Promise.resolve().then(() => (init_occt_wasm(), occt_wasm_exports));
    const createModule = imported.default;
    const moduleOpts = {};
    const wasmSource = options?.wasm ?? options?.wasmUrl ?? options?.wasmPath;
    if (wasmSource instanceof ArrayBuffer || wasmSource instanceof Uint8Array) {
      const bytes = wasmSource instanceof Uint8Array ? wasmSource.buffer.slice(wasmSource.byteOffset, wasmSource.byteOffset + wasmSource.byteLength) : wasmSource;
      moduleOpts["wasmBinary"] = bytes;
    } else if (wasmSource) {
      const location = wasmSource instanceof URL ? wasmSource.href : wasmSource;
      moduleOpts["locateFile"] = (path) => {
        if (path.endsWith(".wasm"))
          return location;
        return path;
      };
    }
    const module = await createModule(moduleOpts);
    return new _a(module);
  }
  // =======================================================================
  // Primitives
  // =======================================================================
  /** Create an axis-aligned box solid with the given dimensions (BRepPrimAPI_MakeBox).
   * @throws OcctError if dimensions are non-positive */
  makeBox(dx, dy, dz) {
    return wrap("makeBox", () => handle(this.#raw.makeBox(dx, dy, dz)));
  }
  /** Create a box solid from two opposite corner points.
   * @throws OcctError if corners are coincident */
  makeBoxFromCorners(corner1, corner2) {
    return wrap("makeBoxFromCorners", () => handle(this.#raw.makeBoxFromCorners(corner1.x, corner1.y, corner1.z, corner2.x, corner2.y, corner2.z)));
  }
  /** Create a cylinder solid centered on the Z axis (BRepPrimAPI_MakeCylinder).
   * @throws OcctError */
  makeCylinder(radius, height) {
    return wrap("makeCylinder", () => handle(this.#raw.makeCylinder(radius, height)));
  }
  /** Create a sphere solid at the origin (BRepPrimAPI_MakeSphere).
   * @throws OcctError */
  makeSphere(radius) {
    return wrap("makeSphere", () => handle(this.#raw.makeSphere(radius)));
  }
  /** Create a cone (or truncated cone) solid along the Z axis (BRepPrimAPI_MakeCone).
   * @param r1 - bottom radius
   * @param r2 - top radius (0 for a full cone)
   * @throws OcctError */
  makeCone(r1, r2, height) {
    return wrap("makeCone", () => handle(this.#raw.makeCone(r1, r2, height)));
  }
  /** Create a torus solid at the origin (BRepPrimAPI_MakeTorus).
   * @throws OcctError */
  makeTorus(majorRadius, minorRadius) {
    return wrap("makeTorus", () => handle(this.#raw.makeTorus(majorRadius, minorRadius)));
  }
  /**
   * Infinite half-space solid bounded by the plane through `origin` with the
   * given `normal`. The solid fills the side the normal points into — useful
   * as an unbounded boolean cutting tool.
   */
  halfSpace(origin, normal) {
    return wrap("halfSpace", () => handle(this.#raw.halfSpace(origin.x, origin.y, origin.z, normal.x, normal.y, normal.z)));
  }
  /** Create an ellipsoid solid at the origin by scaling a sphere.
   * @param rx - radius along X
   * @param ry - radius along Y
   * @param rz - radius along Z
   * @throws OcctError */
  makeEllipsoid(rx, ry, rz) {
    return wrap("makeEllipsoid", () => handle(this.#raw.makeEllipsoid(rx, ry, rz)));
  }
  /** Create a rectangular planar face on the XY plane at the origin.
   * @throws OcctError */
  makeRectangle(width, height) {
    return wrap("makeRectangle", () => handle(this.#raw.makeRectangle(width, height)));
  }
  // =======================================================================
  // Booleans
  // =======================================================================
  /** Boolean union (BRepAlgoAPI_Fuse). Combines two shapes into one.
   * @throws OcctError */
  fuse(a, b) {
    return wrap("fuse", () => handle(this.#raw.fuse(a, b)));
  }
  /** Boolean subtraction (BRepAlgoAPI_Cut). Removes b from a.
   * @throws OcctError */
  cut(a, b) {
    return wrap("cut", () => handle(this.#raw.cut(a, b)));
  }
  /** Boolean intersection (BRepAlgoAPI_Common). Keeps only the overlapping volume.
   * @throws OcctError */
  common(a, b) {
    return wrap("common", () => handle(this.#raw.common(a, b)));
  }
  /** Boolean intersection — alias for common (BRepAlgoAPI_Common).
   * @throws OcctError */
  intersect(a, b) {
    return wrap("intersect", () => handle(this.#raw.intersect(a, b)));
  }
  /** Compute the intersection edges/vertices of two shapes (BRepAlgoAPI_Section).
   * @returns A compound of edges/vertices at the intersection
   * @throws OcctError */
  section(a, b) {
    return wrap("section", () => handle(this.#raw.section(a, b)));
  }
  /** Fuse all shapes in the array into a single shape.
   * @throws OcctError */
  fuseAll(shapes) {
    return wrap("fuseAll", () => {
      return this.#withU32(shapes, (vec) => handle(this.#raw.fuseAll(vec)));
    });
  }
  /** Subtract all tool shapes from the base shape.
   * @throws OcctError */
  cutAll(shape, tools) {
    return wrap("cutAll", () => {
      return this.#withU32(tools, (vec) => handle(this.#raw.cutAll(shape, vec)));
    });
  }
  /** Split a shape using tool shapes as splitting surfaces (BOPAlgo_Splitter).
   * @returns A compound of the split fragments
   * @throws OcctError */
  split(shape, tools) {
    return wrap("split", () => {
      return this.#withU32(tools, (vec) => handle(this.#raw.split(shape, vec)));
    });
  }
  /**
   * General-fuse cell selection: the union of all regions covered by two or
   * more of the inputs. Unlike {@link fuseAll} (which keeps every cell), this
   * keeps only the overlap regions via BOPAlgo_CellsBuilder.
   */
  intersectionCells(shapes) {
    return wrap("intersectionCells", () => {
      return this.#withU32(shapes, (vec) => handle(this.#raw.intersectionCells(vec)));
    });
  }
  // =======================================================================
  // Modeling
  // =======================================================================
  /** Extrude a shape along a direction vector (BRepPrimAPI_MakePrism).
   * @param dx - extrusion vector X component
   * @param dy - extrusion vector Y component
   * @param dz - extrusion vector Z component
   * @throws OcctError */
  extrude(shape, dx, dy, dz) {
    return wrap("extrude", () => handle(this.#raw.extrude(shape, dx, dy, dz)));
  }
  /** Revolve a shape around an axis (BRepPrimAPI_MakeRevol).
   * @param axis - rotation axis defined by a point and direction
   * @param angleRad - sweep angle in radians (2*PI for full revolution)
   * @throws OcctError */
  revolve(shape, axis, angleRad) {
    return wrap("revolve", () => handle(this.#raw.revolve(shape, axis.point.x, axis.point.y, axis.point.z, axis.direction.x, axis.direction.y, axis.direction.z, angleRad)));
  }
  /** Apply a constant-radius fillet to edges of a solid (BRepFilletAPI_MakeFillet).
   * @throws OcctError */
  fillet(solid, edges, radius) {
    return wrap("fillet", () => {
      return this.#withU32(edges, (vec) => handle(this.#raw.fillet(solid, vec, radius)));
    });
  }
  chamfer(solid, edges, distance) {
    return wrap("chamfer", () => {
      return this.#withU32(edges, (vec) => handle(this.#raw.chamfer(solid, vec, distance)));
    });
  }
  chamferDistAngle(solid, edges, distance, angleDeg) {
    return wrap("chamferDistAngle", () => {
      return this.#withU32(edges, (vec) => handle(this.#raw.chamferDistAngle(solid, vec, distance, angleDeg)));
    });
  }
  /**
   * Hollow a solid by removing the listed faces and offsetting remaining
   * faces inward by `thickness`.
   *
   * @param tolerance - OCCT precision for the thick-solid reconstruction.
   *     Use `1e-6` for precise shells (matches brepjs default); `1e-3` is a
   *     coarser legacy value that survives more inputs but produces
   *     different topology than brepjs.
   */
  shell(solid, facesToRemove, thickness, tolerance) {
    return wrap("shell", () => {
      return this.#withU32(facesToRemove, (vec) => handle(this.#raw.shell(solid, vec, thickness, tolerance)));
    });
  }
  /**
   * Offset all faces of a solid by `distance`.
   *
   * @param tolerance - OCCT precision for the offset reconstruction. Use
   *     `1e-6` for precise offsets (matches brepjs default); `1e-3` is a
   *     coarser legacy value.
   */
  offset(solid, distance, tolerance) {
    return wrap("offset", () => handle(this.#raw.offset(solid, distance, tolerance)));
  }
  draft(shape, face, angleRad, direction) {
    return wrap("draft", () => handle(this.#raw.draft(shape, face, angleRad, direction.x, direction.y, direction.z)));
  }
  // =======================================================================
  // Sweeps
  // =======================================================================
  pipe(profile, spine) {
    return wrap("pipe", () => handle(this.#raw.pipe(profile, spine)));
  }
  simplePipe(profile, spine) {
    return wrap("simplePipe", () => handle(this.#raw.simplePipe(profile, spine)));
  }
  /**
   * Loft a solid (or shell) through a sequence of wire profiles.
   *
   * @param ruled - When `true`, sections are joined by ruled (linear)
   *     surfaces; when `false`, by smooth B-spline surfaces. The two modes
   *     produce dramatically different topology for the same input.
   */
  loft(wires, isSolid, ruled) {
    return wrap("loft", () => {
      return this.#withU32(wires, (vec) => handle(this.#raw.loft(vec, isSolid, ruled)));
    });
  }
  loftWithVertices(wires, isSolid, ruled, startVertex, endVertex) {
    return wrap("loftWithVertices", () => {
      return this.#withU32(wires, (vec) => handle(this.#raw.loftWithVertices(vec, isSolid, ruled, startVertex, endVertex)));
    });
  }
  sweep(wire, spine, transitionMode = TransitionMode.Transformed) {
    return wrap("sweep", () => handle(this.#raw.sweep(wire, spine, transitionMode)));
  }
  sweepPipeShell(profile, spine, freenet = false, smooth = true) {
    return wrap("sweepPipeShell", () => handle(this.#raw.sweepPipeShell(profile, spine, freenet, smooth)));
  }
  /**
   * Sweep a profile wire along a spine wire with explicit profile-orientation
   * control. `up` is required for {@link SweepMode.FixedUp} (the constant
   * binormal direction); `auxSpine` is required for {@link SweepMode.Auxiliary}
   * (the guide wire). Both are ignored for the other modes.
   *
   * In `options`, `curvilinearEquivalence` and `contact` apply to
   * {@link SweepMode.Auxiliary} only; the tolerances apply to every mode and
   * are absolute, not relative to model size. See
   * {@link SweepOrientedOptions}.
   */
  sweepOriented(profile, spine, mode = SweepMode.Fixed, up = { x: 0, y: 0, z: 1 }, auxSpine, options = {}) {
    return wrap("sweepOriented", () => handle(this.#raw.sweepOriented(profile, spine, mode, up.x, up.y, up.z, auxSpine ?? 0, options.curvilinearEquivalence ?? false, options.contact ?? SweepContact.None, options.tol3d ?? 0, options.boundTol ?? 0, options.tolAngular ?? 0)));
  }
  /**
   * Sweep a profile along a spine with the full control surface: the
   * orientation modes of {@link OcctKernel.sweepOriented}, the corner
   * transitions of {@link OcctKernel.sweepPipeShell}, and the profile
   * placement neither of them exposes.
   *
   * Prefer this for new code. The other two remain for callers bound to
   * their existing raw arity.
   */
  sweepAdvanced(profile, spine, options = {}) {
    const up = options.up ?? { x: 0, y: 0, z: 1 };
    return wrap("sweepAdvanced", () => handle(this.#raw.sweepAdvanced(profile, spine, options.mode ?? SweepMode.Fixed, up.x, up.y, up.z, options.auxSpine ?? 0, options.curvilinearEquivalence ?? false, options.guideContact ?? SweepContact.None, options.transitionMode ?? TransitionMode.Transformed, options.withContact ?? false, options.withCorrection ?? false, options.tol3d ?? 0, options.boundTol ?? 0, options.tolAngular ?? 0)));
  }
  /**
   * Sweep with the complete control surface: everything
   * {@link OcctKernel.sweepAdvanced} accepts, plus a spine support surface,
   * the approximation budget, and a homothetic scaling law.
   *
   * Prefer this for new code. The narrower sweep entry points remain for
   * callers bound to their existing raw arity.
   */
  sweepFull(profile, spine, options = {}) {
    const up = options.up ?? { x: 0, y: 0, z: 1 };
    const law = options.law ?? SweepLaw.None;
    if (law !== SweepLaw.None && options.lawLength === void 0) {
      throw new Error("sweepFull: lawLength is required when a law is set");
    }
    return wrap("sweepFull", () => handle(this.#raw.sweepFull(profile, spine, options.mode ?? SweepMode.Fixed, up.x, up.y, up.z, options.auxSpine ?? 0, options.curvilinearEquivalence ?? false, options.guideContact ?? SweepContact.None, options.transitionMode ?? TransitionMode.Transformed, options.withContact ?? false, options.withCorrection ?? false, options.tol3d ?? 0, options.boundTol ?? 0, options.tolAngular ?? 0, options.support ?? 0, options.maxDegree ?? 0, options.maxSegments ?? 0, law, options.lawLength ?? 0, options.lawEndFactor ?? 1)));
  }
  draftPrism(shape, dx, dy, dz, angleDeg) {
    return wrap("draftPrism", () => handle(this.#raw.draftPrism(shape, dx, dy, dz, angleDeg)));
  }
  // =======================================================================
  // Construction
  // =======================================================================
  makeVertex(x, y, z) {
    return wrap("makeVertex", () => handle(this.#raw.makeVertex(x, y, z)));
  }
  makeEdge(v1, v2) {
    return wrap("makeEdge", () => handle(this.#raw.makeEdge(v1, v2)));
  }
  makeLineEdge(start, end) {
    return wrap("makeLineEdge", () => handle(this.#raw.makeLineEdge(start.x, start.y, start.z, end.x, end.y, end.z)));
  }
  makeCircleEdge(center, normal, radius) {
    return wrap("makeCircleEdge", () => handle(this.#raw.makeCircleEdge(center.x, center.y, center.z, normal.x, normal.y, normal.z, radius)));
  }
  makeCircleArc(center, normal, radius, startAngle, endAngle) {
    return wrap("makeCircleArc", () => handle(this.#raw.makeCircleArc(center.x, center.y, center.z, normal.x, normal.y, normal.z, radius, startAngle, endAngle)));
  }
  makeArcEdge(start, mid, end) {
    return wrap("makeArcEdge", () => handle(this.#raw.makeArcEdge(start.x, start.y, start.z, mid.x, mid.y, mid.z, end.x, end.y, end.z)));
  }
  makeEllipseEdge(center, normal, majorRadius, minorRadius) {
    return wrap("makeEllipseEdge", () => handle(this.#raw.makeEllipseEdge(center.x, center.y, center.z, normal.x, normal.y, normal.z, majorRadius, minorRadius)));
  }
  makeEllipseArc(center, normal, majorRadius, minorRadius, startAngle, endAngle) {
    return wrap("makeEllipseArc", () => handle(this.#raw.makeEllipseArc(center.x, center.y, center.z, normal.x, normal.y, normal.z, majorRadius, minorRadius, startAngle, endAngle)));
  }
  makeBezierEdge(controlPoints) {
    return wrap("makeBezierEdge", () => {
      const flat = this.#flattenPoints(controlPoints);
      try {
        return handle(this.#raw.makeBezierEdge(flat));
      } finally {
        flat.delete();
      }
    });
  }
  makeBSplineEdge(poles, weights, knots, multiplicities, degree, periodic = false) {
    return wrap("makeBSplineEdge", () => this.#withF64(poles, (polesVec) => this.#withF64(weights, (weightsVec) => this.#withF64(knots, (knotsVec) => this.#withI32(multiplicities, (multsVec) => handle(this.#raw.makeBSplineEdge(polesVec, weightsVec, knotsVec, multsVec, degree, periodic)))))));
  }
  makeTangentArc(start, tangent, end) {
    return wrap("makeTangentArc", () => handle(this.#raw.makeTangentArc(start.x, start.y, start.z, tangent.x, tangent.y, tangent.z, end.x, end.y, end.z)));
  }
  makeHelixWire(origin, axis, pitch, height, radius) {
    return wrap("makeHelixWire", () => handle(this.#raw.makeHelixWire(origin.x, origin.y, origin.z, axis.x, axis.y, axis.z, pitch, height, radius)));
  }
  /**
   * A helix with an explicit handedness: right-handed (the default) winds
   * counter-clockwise about `axis` as it climbs, left-handed clockwise. The
   * two are mirror images over the same pitch, height and radius.
   *
   * Prefer this for new code. {@link OcctKernel.makeHelixWire} remains for
   * callers bound to its existing raw arity, and is always right-handed.
   */
  makeHelixWireHanded(origin, axis, pitch, height, radius, leftHanded = false) {
    return wrap("makeHelixWireHanded", () => handle(this.#raw.makeHelixWireHanded(origin.x, origin.y, origin.z, axis.x, axis.y, axis.z, pitch, height, radius, leftHanded)));
  }
  makeWire(edges) {
    return wrap("makeWire", () => {
      return this.#withU32(edges, (vec) => handle(this.#raw.makeWire(vec)));
    });
  }
  makeFace(wire) {
    return wrap("makeFace", () => handle(this.#raw.makeFace(wire)));
  }
  makeNonPlanarFace(wire) {
    return wrap("makeNonPlanarFace", () => handle(this.#raw.makeNonPlanarFace(wire)));
  }
  addHolesInFace(face, holeWires) {
    return wrap("addHolesInFace", () => {
      return this.#withU32(holeWires, (vec) => handle(this.#raw.addHolesInFace(face, vec)));
    });
  }
  removeHolesFromFace(face, holeIndices) {
    return wrap("removeHolesFromFace", () => {
      return this.#withI32(holeIndices, (vec) => handle(this.#raw.removeHolesFromFace(face, vec)));
    });
  }
  makeSolid(shell) {
    return wrap("makeSolid", () => handle(this.#raw.makeSolid(shell)));
  }
  sew(shapes, tolerance = 1e-6) {
    return wrap("sew", () => {
      return this.#withU32(shapes, (vec) => handle(this.#raw.sew(vec, tolerance)));
    });
  }
  sewAndSolidify(faces, tolerance = 1e-6) {
    return wrap("sewAndSolidify", () => {
      return this.#withU32(faces, (vec) => handle(this.#raw.sewAndSolidify(vec, tolerance)));
    });
  }
  buildSolidFromFaces(faces, tolerance = 1e-6) {
    return wrap("buildSolidFromFaces", () => {
      return this.#withU32(faces, (vec) => handle(this.#raw.buildSolidFromFaces(vec, tolerance)));
    });
  }
  makeCompound(shapes) {
    return wrap("makeCompound", () => {
      return this.#withU32(shapes, (vec) => handle(this.#raw.makeCompound(vec)));
    });
  }
  buildTriFace(a, b, c) {
    return wrap("buildTriFace", () => handle(this.#raw.buildTriFace(a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z)));
  }
  makeFaceOnSurface(face, wire) {
    return wrap("makeFaceOnSurface", () => handle(this.#raw.makeFaceOnSurface(face, wire)));
  }
  makeNullShape() {
    return wrap("makeNullShape", () => handle(this.#raw.makeNullShape()));
  }
  // =======================================================================
  // Transforms
  // =======================================================================
  translate(shape, dx, dy, dz) {
    return wrap("translate", () => handle(this.#raw.translate(shape, dx, dy, dz)));
  }
  /**
   * Translate along X so the chosen bounding-box anchor lands at `target`.
   * Returns a new shape; the input is left untouched.
   */
  alignX(shape, target = 0, anchor = "center") {
    return wrap("alignX", () => {
      const bb = this.getBoundingBox(shape, false);
      const cur = anchor === "min" ? bb.xmin : anchor === "max" ? bb.xmax : (bb.xmin + bb.xmax) / 2;
      return handle(this.#raw.translate(shape, target - cur, 0, 0));
    });
  }
  /** Translate along Y so the chosen bounding-box anchor lands at `target`. */
  alignY(shape, target = 0, anchor = "center") {
    return wrap("alignY", () => {
      const bb = this.getBoundingBox(shape, false);
      const cur = anchor === "min" ? bb.ymin : anchor === "max" ? bb.ymax : (bb.ymin + bb.ymax) / 2;
      return handle(this.#raw.translate(shape, 0, target - cur, 0));
    });
  }
  /** Translate along Z so the chosen bounding-box anchor lands at `target`. */
  alignZ(shape, target = 0, anchor = "center") {
    return wrap("alignZ", () => {
      const bb = this.getBoundingBox(shape, false);
      const cur = anchor === "min" ? bb.zmin : anchor === "max" ? bb.zmax : (bb.zmin + bb.zmax) / 2;
      return handle(this.#raw.translate(shape, 0, 0, target - cur));
    });
  }
  rotate(shape, axis, angleRad) {
    return wrap("rotate", () => handle(this.#raw.rotate(shape, axis.point.x, axis.point.y, axis.point.z, axis.direction.x, axis.direction.y, axis.direction.z, angleRad)));
  }
  scale(shape, center, factor) {
    return wrap("scale", () => handle(this.#raw.scale(shape, center.x, center.y, center.z, factor)));
  }
  mirror(shape, point, normal) {
    return wrap("mirror", () => handle(this.#raw.mirror(shape, point.x, point.y, point.z, normal.x, normal.y, normal.z)));
  }
  copy(shape) {
    return wrap("copy", () => handle(this.#raw.copy(shape)));
  }
  /** Apply a 3x4 row-major affine transformation matrix (12 doubles: [r00,r01,r02,tx, r10,r11,r12,ty, r20,r21,r22,tz]). */
  transform(shape, matrix) {
    return wrap("transform", () => {
      return this.#withF64(matrix, (vec) => handle(this.#raw.transform(shape, vec)));
    });
  }
  /**
   * Re-tag a shape with a `TopLoc_Location` from a 3x4 row-major affine matrix
   * (same 12-double layout as {@link transform}). Shares the underlying topology
   * instead of deep-copying it, so a pure move is O(1).
   */
  located(shape, matrix) {
    return wrap("located", () => {
      return this.#withF64(matrix, (vec) => handle(this.#raw.located(shape, vec)));
    });
  }
  /** Apply a general (possibly non-affine) 3x4 row-major transformation matrix (12 doubles). */
  generalTransform(shape, matrix) {
    return wrap("generalTransform", () => {
      return this.#withF64(matrix, (vec) => handle(this.#raw.generalTransform(shape, vec)));
    });
  }
  linearPattern(shape, direction, spacing, count) {
    return wrap("linearPattern", () => handle(this.#raw.linearPattern(shape, direction.x, direction.y, direction.z, spacing, count)));
  }
  circularPattern(shape, center, axis, angle, count) {
    return wrap("circularPattern", () => handle(this.#raw.circularPattern(shape, center.x, center.y, center.z, axis.x, axis.y, axis.z, angle, count)));
  }
  /** Compose two 3x4 row-major transformation matrices. Returns a 12-element array. */
  composeTransform(m1, m2) {
    return wrap("composeTransform", () => this.#withF64(m1, (v1) => this.#withF64(m2, (v2) => this.#drainVector(this.#raw.composeTransform(v1, v2), Float64Array))));
  }
  // =======================================================================
  // Batch Operations
  // =======================================================================
  /** Translate multiple shapes by their respective offsets in a single WASM call. */
  translateBatch(shapes, offsets) {
    return wrap("translateBatch", () => this.#withU32(shapes, (ids) => this.#withF64(offsets, (off) => this.#vecToHandles(this.#raw.translateBatch(ids, off)))));
  }
  /** Chain boolean operations in a single WASM call. */
  booleanPipeline(base, opCodes, tools) {
    return wrap("booleanPipeline", () => this.#withI32(opCodes, (ops) => this.#withU32(tools, (ids) => handle(this.#raw.booleanPipeline(base, ops, ids)))));
  }
  /** Query multiple shapes in a single WASM call: bbox, volume, area, center of mass, type, validity. */
  queryBatch(shapes) {
    return wrap("queryBatch", () => this.#withU32(shapes, (ids) => {
      const arr = this.#drainVector(this.#raw.queryBatch(ids), Float64Array);
      const STRIDE = 14;
      const results = [];
      for (let i = 0; i < shapes.length; i++) {
        const o = i * STRIDE;
        results.push({
          volume: arr[o],
          area: arr[o + 1],
          bbox: { xmin: arr[o + 2], ymin: arr[o + 3], zmin: arr[o + 4], xmax: arr[o + 5], ymax: arr[o + 6], zmax: arr[o + 7] },
          centerOfMass: { x: arr[o + 8], y: arr[o + 9], z: arr[o + 10] },
          shapeType: SHAPE_TYPES[arr[o + 11]] ?? "shape",
          isValid: arr[o + 12] === 1
        });
      }
      return results;
    }));
  }
  /** Fillet multiple solids in a single WASM call. */
  filletBatch(ops) {
    return wrap("filletBatch", () => this.#withU32(ops.map((op) => op.solid), (solids) => this.#withI32(ops.map((op) => op.edges.length), (edgeCounts) => this.#withU32(ops.flatMap((op) => op.edges), (flatEdges) => this.#withF64(ops.map((op) => op.radius), (radii) => this.#vecToHandles(this.#raw.filletBatch(solids, edgeCounts, flatEdges, radii)))))));
  }
  /** Apply 3x4 affine transforms to multiple shapes in a single WASM call. */
  transformBatch(shapes, matrices) {
    return wrap("transformBatch", () => this.#withU32(shapes, (ids) => this.#withF64(matrices, (mats) => this.#vecToHandles(this.#raw.transformBatch(ids, mats)))));
  }
  /** Rotate multiple shapes in a single WASM call. */
  rotateBatch(shapes, params) {
    return wrap("rotateBatch", () => this.#withU32(shapes, (ids) => this.#withF64(params, (p) => this.#vecToHandles(this.#raw.rotateBatch(ids, p)))));
  }
  /** Scale multiple shapes in a single WASM call. */
  scaleBatch(shapes, params) {
    return wrap("scaleBatch", () => this.#withU32(shapes, (ids) => this.#withF64(params, (p) => this.#vecToHandles(this.#raw.scaleBatch(ids, p)))));
  }
  /** Mirror multiple shapes in a single WASM call. */
  mirrorBatch(shapes, params) {
    return wrap("mirrorBatch", () => this.#withU32(shapes, (ids) => this.#withF64(params, (p) => this.#vecToHandles(this.#raw.mirrorBatch(ids, p)))));
  }
  // =======================================================================
  // Topology
  // =======================================================================
  getShapeType(shape) {
    return wrap("getShapeType", () => asEnum(this.#raw.getShapeType(shape), SHAPE_TYPE_VALUES, "shape type"));
  }
  /** True if the shape is a compound. */
  isCompound(shape) {
    return this.getShapeType(shape) === "compound";
  }
  /** True if the shape is a comp-solid. */
  isCompSolid(shape) {
    return this.getShapeType(shape) === "compsolid";
  }
  /** True if the shape is a solid. */
  isSolid(shape) {
    return this.getShapeType(shape) === "solid";
  }
  /** True if the shape is a shell. */
  isShell(shape) {
    return this.getShapeType(shape) === "shell";
  }
  /** True if the shape is a face. */
  isFace(shape) {
    return this.getShapeType(shape) === "face";
  }
  /** True if the shape is a wire. */
  isWire(shape) {
    return this.getShapeType(shape) === "wire";
  }
  /** True if the shape is an edge. */
  isEdge(shape) {
    return this.getShapeType(shape) === "edge";
  }
  /** True if the shape is a vertex. */
  isVertex(shape) {
    return this.getShapeType(shape) === "vertex";
  }
  getSubShapes(shape, type) {
    return wrap("getSubShapes", () => this.#vecToHandles(this.#raw.getSubShapes(shape, type)));
  }
  /** Count sub-shapes of a type without materialising a handle per sub-shape. */
  subShapeCount(shape, type) {
    return wrap("subShapeCount", () => this.#raw.subShapeCount(shape, type));
  }
  /**
   * Deduplicated hashes of a shape's sub-shapes, with no per-sub-shape handle
   * allocation. Use for hash-only paths (face-hash collection, tagging) that
   * would otherwise iterate {@link getSubShapes} handles just to release them.
   */
  subShapeHashes(shape, type, hashUpperBound) {
    return wrap("subShapeHashes", () => this.#drainVector(this.#raw.subShapeHashes(shape, type, hashUpperBound), Int32Array));
  }
  downcast(shape, targetType) {
    return wrap("downcast", () => handle(this.#raw.downcast(shape, targetType)));
  }
  distanceBetween(a, b) {
    return wrap("distanceBetween", () => this.#raw.distanceBetween(a, b));
  }
  isSame(a, b) {
    return wrap("isSame", () => this.#raw.isSame(a, b));
  }
  isEqual(a, b) {
    return wrap("isEqual", () => this.#raw.isEqual(a, b));
  }
  isNull(shape) {
    return wrap("isNull", () => this.#raw.isNull(shape));
  }
  hashCode(shape, upperBound) {
    return wrap("hashCode", () => this.#raw.hashCode(shape, upperBound));
  }
  shapeOrientation(shape) {
    return wrap("shapeOrientation", () => asEnum(this.#raw.shapeOrientation(shape), SHAPE_ORIENTATION_VALUES, "shape orientation"));
  }
  sharedEdges(faceA, faceB) {
    return wrap("sharedEdges", () => this.#vecToHandles(this.#raw.sharedEdges(faceA, faceB)));
  }
  adjacentFaces(shape, face) {
    return wrap("adjacentFaces", () => this.#vecToHandles(this.#raw.adjacentFaces(shape, face)));
  }
  iterShapes(shape) {
    return wrap("iterShapes", () => this.#vecToHandles(this.#raw.iterShapes(shape)));
  }
  /** Returns a flat array mapping edge hashes to face hashes. */
  edgeToFaceMap(shape, hashUpperBound) {
    return wrap("edgeToFaceMap", () => {
      const vec = this.#raw.edgeToFaceMap(shape, hashUpperBound);
      return this.#drainVector(vec, Int32Array);
    });
  }
  // =======================================================================
  // Tessellation
  // =======================================================================
  /** Tessellate a shape into a triangle mesh. Returns copied data (safe to keep). */
  tessellate(shape, options) {
    return wrap("tessellate", () => {
      const linDefl = options?.linearDeflection ?? 0.1;
      const angDefl = options?.angularDeflection ?? 0.5;
      const raw = options?.relative ? this.#raw.tessellateRelative(shape, linDefl, angDefl) : this.#raw.tessellate(shape, linDefl, angDefl);
      return this.#extractMesh(raw);
    });
  }
  /** Sample edges as polylines for wireframe rendering. */
  wireframe(shape, deflection = 0.1) {
    return wrap("wireframe", () => {
      const raw = this.#raw.wireframe(shape, deflection);
      try {
        const points = new Float32Array(this.#module.HEAPF32.buffer.slice(raw.getPointsPtr(), raw.getPointsPtr() + raw.pointCount * 4));
        const edgeCount = raw.edgeGroupCount / 3;
        const edgeGroups = new Int32Array(this.#module.HEAP32.buffer.slice(raw.getEdgeGroupsPtr(), raw.getEdgeGroupsPtr() + raw.edgeGroupCount * 4));
        return { points, edgeGroups, pointCount: raw.pointCount, edgeCount };
      } finally {
        raw.delete();
      }
    });
  }
  hasTriangulation(shape) {
    return wrap("hasTriangulation", () => this.#raw.hasTriangulation(shape));
  }
  /** Tessellate with face group data (per-face triangle ranges + hashes). */
  meshShape(shape, options) {
    return wrap("meshShape", () => {
      const linDefl = options?.linearDeflection ?? 0.1;
      const angDefl = options?.angularDeflection ?? 0.5;
      return this.#extractMeshWithFaceGroups(this.#raw.meshShape(shape, linDefl, angDefl));
    });
  }
  /** Tessellate multiple shapes in a single WASM call. */
  meshBatch(shapes, options) {
    return wrap("meshBatch", () => this.#withU32(shapes, (ids) => {
      const linDefl = options?.linearDeflection ?? 0.1;
      const angDefl = options?.angularDeflection ?? 0.5;
      const raw = this.#raw.meshBatch(ids, linDefl, angDefl);
      try {
        const positions = new Float32Array(this.#module.HEAPF32.buffer.slice(raw.getPositionsPtr(), raw.getPositionsPtr() + raw.positionCount * 4));
        const normals = new Float32Array(this.#module.HEAPF32.buffer.slice(raw.getNormalsPtr(), raw.getNormalsPtr() + raw.normalCount * 4));
        const indices = new Uint32Array(this.#module.HEAPU32.buffer.slice(raw.getIndicesPtr(), raw.getIndicesPtr() + raw.indexCount * 4));
        const shapeOffsets = new Int32Array(this.#module.HEAP32.buffer.slice(raw.getShapeOffsetsPtr(), raw.getShapeOffsetsPtr() + raw.shapeCount * 4 * 4));
        return {
          positions,
          normals,
          indices,
          shapeOffsets,
          shapeCount: raw.shapeCount,
          vertexCount: raw.positionCount / 3,
          triangleCount: raw.indexCount / 3
        };
      } finally {
        raw.delete();
      }
    }));
  }
  // =======================================================================
  // I/O
  // =======================================================================
  importStep(data) {
    return wrap("importStep", () => {
      const str = typeof data === "string" ? data : new TextDecoder().decode(data);
      return handle(this.#raw.importStep(str));
    });
  }
  exportStep(shape) {
    return wrap("exportStep", () => this.#raw.exportStep(shape));
  }
  importStl(data) {
    return wrap("importStl", () => {
      const str = typeof data === "string" ? data : new TextDecoder().decode(data);
      return handle(this.#raw.importStl(str));
    });
  }
  exportStl(shape, linearDeflection = 0.1, ascii = false) {
    return wrap("exportStl", () => this.#raw.exportStl(shape, linearDeflection, ascii));
  }
  toBREP(shape) {
    return wrap("toBREP", () => this.#raw.toBREP(shape));
  }
  fromBREP(data) {
    return wrap("fromBREP", () => handle(this.#raw.fromBREP(data)));
  }
  /** Serialize a shape to binary BREP (smaller/faster than the text format). */
  toBREPBinary(shape) {
    return wrap("toBREPBinary", () => {
      const path = this.#raw.exportBrepBinary(shape);
      const bytes = this.#module.FS.readFile(path);
      this.#module.FS.unlink(path);
      return bytes;
    });
  }
  /** Load a shape from binary BREP produced by {@link toBREPBinary}. */
  fromBREPBinary(data) {
    return wrap("fromBREPBinary", () => {
      const path = "/tmp/occt-import.brep.bin";
      this.#module.FS.writeFile(path, data);
      try {
        return handle(this.#raw.importBrepBinary(path));
      } finally {
        this.#module.FS.unlink(path);
      }
    });
  }
  cacheStep(stepData) {
    return wrap("cacheStep", () => {
      const shape = this.importStep(stepData);
      try {
        return this.toBREP(shape);
      } finally {
        this.release(shape);
      }
    });
  }
  loadCached(brep) {
    return wrap("loadCached", () => this.fromBREP(brep));
  }
  // =======================================================================
  // Query / Measure
  // =======================================================================
  /**
   * Compute the axis-aligned bounding box of a shape.
   *
   * Uses `BRepBndLib::AddOptimal` for surface-precise bounds independent of
   * tessellation state. The simpler `BRepBndLib::Add` falls back to BSpline
   * pole hulls when triangulation is absent, which overshoots curved
   * geometry by ~0.27·r for arcs of radius r — that was the source of the
   * uniform 1.2 mm bounds shift versus brepjs in occt-wasm 2.0.
   *
   * @param useTriangulation - `false` (the default) does the surface analysis
   *     from scratch, giving the same bounds whether or not the shape has been
   *     tessellated. `true` bounds an existing triangulation instead, which is
   *     far faster but only as tight as that mesh — on a 2.0-deflection mesh
   *     it overshot a 26 mm extent by 1.8 mm, and on a 0.1-deflection mesh by
   *     0.16 mm. With no triangulation present the two agree exactly and cost
   *     the same, so `true` is worth it only when you have a fine mesh and
   *     want the ~30x faster query. brepjs's
   *     `BRepBndLib.Add(shape, box, true)` corresponds to `true` here.
   */
  getBoundingBox(shape, useTriangulation = false) {
    return wrap("getBoundingBox", () => this.#raw.getBoundingBox(shape, useTriangulation));
  }
  getVolume(shape) {
    return wrap("getVolume", () => this.#raw.getVolume(shape));
  }
  getSurfaceArea(shape) {
    return wrap("getSurfaceArea", () => this.#raw.getSurfaceArea(shape));
  }
  getLength(shape) {
    return wrap("getLength", () => this.#raw.getLength(shape));
  }
  getCenterOfMass(shape) {
    return wrap("getCenterOfMass", () => {
      const v2 = this.#raw.getCenterOfMass(shape);
      return this.#vec3FromEmbind(v2);
    });
  }
  /**
   * Matrix of inertia about the center of mass, as a row-major 3×3 array
   * (length 9). Symmetric: `[1]==[3]`, `[2]==[6]`, `[5]==[7]`.
   */
  getInertia(shape) {
    return wrap("getInertia", () => Array.from(this.#drainVector(this.#raw.getInertia(shape), Float64Array)));
  }
  /** True if `point` lies inside (or on the boundary of) a solid. */
  containsPoint(shape, point, tolerance = 1e-7) {
    return wrap("containsPoint", () => this.#raw.containsPoint(shape, point.x, point.y, point.z, tolerance));
  }
  /**
   * Surface (area-weighted) center of mass for a face. Equivalent to
   * `BRepGProp::SurfaceProperties(face, props).CentreOfMass()`.
   *
   * Use this for face fingerprinting and finder predicates rather than a
   * tessellation-based centroid — for non-planar faces (cylinders, holed
   * planes) the two diverge.
   */
  getSurfaceCenterOfMass(face) {
    return wrap("getSurfaceCenterOfMass", () => {
      const v2 = this.#raw.getSurfaceCenterOfMass(face);
      return this.#vec3FromEmbind(v2);
    });
  }
  getLinearCenterOfMass(shape) {
    return wrap("getLinearCenterOfMass", () => {
      const v2 = this.#raw.getLinearCenterOfMass(shape);
      return this.#vec3FromEmbind(v2);
    });
  }
  surfaceCurvature(face, u, v2) {
    return wrap("surfaceCurvature", () => this.#curvatureDataFromEmbind(this.#raw.surfaceCurvature(face, u, v2)));
  }
  // =======================================================================
  // Surfaces
  // =======================================================================
  vertexPosition(vertex) {
    return wrap("vertexPosition", () => {
      const v2 = this.#raw.vertexPosition(vertex);
      return this.#vec3FromEmbind(v2);
    });
  }
  surfaceType(face) {
    return wrap("surfaceType", () => this.#raw.surfaceType(face));
  }
  surfaceNormal(face, u, v2) {
    return wrap("surfaceNormal", () => {
      const vec = this.#raw.surfaceNormal(face, u, v2);
      return this.#vec3FromEmbind(vec);
    });
  }
  pointOnSurface(face, u, v2) {
    return wrap("pointOnSurface", () => {
      const vec = this.#raw.pointOnSurface(face, u, v2);
      return this.#vec3FromEmbind(vec);
    });
  }
  outerWire(face) {
    return wrap("outerWire", () => handle(this.#raw.outerWire(face)));
  }
  /**
   * Reverse a surface's U parametric direction (OCCT `Geom_Surface::UReverse`),
   * returning a new face proxy whose surface is the U-reversed original.
   * `pointOnSurface(result, u, v)` then evaluates the original surface at
   * `origSurface.UReversedParameter(u)` — for a full-period cylinder that is
   * `uFirst + uLast - u`.
   */
  reverseSurfaceU(face) {
    return wrap("reverseSurfaceU", () => handle(this.#raw.reverseSurfaceU(face)));
  }
  uvBounds(face) {
    return wrap("uvBounds", () => this.#uvBoundsFromEmbind(this.#raw.uvBounds(face)));
  }
  /** Project a 3D point onto a face, returning [u, v]. */
  uvFromPoint(face, point) {
    return wrap("uvFromPoint", () => this.#vec2FromEmbind(this.#raw.uvFromPoint(face, point.x, point.y, point.z)));
  }
  /**
   * Extract cylinder data from a cylindrical face.
   *
   * Returns `null` when the face's underlying surface is not a cylinder,
   * otherwise `{ radius, isDirect }` where `isDirect` mirrors
   * `gp_Cylinder::Direct()` (i.e. whether U and V form a right-handed pair).
   */
  getFaceCylinderData(face) {
    return wrap("getFaceCylinderData", () => {
      const vec = this.#raw.getFaceCylinderData(face);
      try {
        if (vec.size() === 0)
          return null;
        return { radius: vec.get(0), isDirect: vec.get(1) !== 0 };
      } finally {
        vec.delete();
      }
    });
  }
  /** Project a 3D point onto a face, returning the closest point as Vec3. */
  projectPointOnFace(face, point) {
    return wrap("projectPointOnFace", () => {
      const vec = this.#raw.projectPointOnFace(face, point.x, point.y, point.z);
      return this.#vec3FromEmbind(vec);
    });
  }
  /** Classify a UV point relative to a face boundary. */
  classifyPointOnFace(face, u, v2) {
    return wrap("classifyPointOnFace", () => asEnum(this.#raw.classifyPointOnFace(face, u, v2), POINT_CLASSIFICATION_VALUES, "point classification"));
  }
  /** Create a BSpline surface from a grid of control points. */
  bsplineSurface(controlPoints, rows, cols) {
    return wrap("bsplineSurface", () => {
      const flat = this.#flattenPoints(controlPoints);
      try {
        return handle(this.#raw.bsplineSurface(flat, rows, cols));
      } finally {
        flat.delete();
      }
    });
  }
  // =======================================================================
  // Curves
  // =======================================================================
  curveType(edge) {
    return wrap("curveType", () => this.#raw.curveType(edge));
  }
  curvePointAtParam(edge, param) {
    return wrap("curvePointAtParam", () => {
      const vec = this.#raw.curvePointAtParam(edge, param);
      return this.#vec3FromEmbind(vec);
    });
  }
  curveTangent(edge, param) {
    return wrap("curveTangent", () => {
      const vec = this.#raw.curveTangent(edge, param);
      return this.#vec3FromEmbind(vec);
    });
  }
  /** Returns [firstParam, lastParam]. */
  curveParameters(edge) {
    return wrap("curveParameters", () => {
      const { u: first, v: last } = this.#vec2FromEmbind(this.#raw.curveParameters(edge));
      return { first, last };
    });
  }
  curveIsClosed(edge) {
    return wrap("curveIsClosed", () => this.#raw.curveIsClosed(edge));
  }
  curveIsPeriodic(edge) {
    return wrap("curveIsPeriodic", () => this.#raw.curveIsPeriodic(edge));
  }
  curveLength(edge) {
    return wrap("curveLength", () => this.#raw.curveLength(edge));
  }
  interpolatePoints(points, periodic = false) {
    return wrap("interpolatePoints", () => {
      const flat = this.#flattenPoints(points);
      try {
        return handle(this.#raw.interpolatePoints(flat, periodic));
      } finally {
        flat.delete();
      }
    });
  }
  /**
   * Interpolate a cubic B-spline through the points with clamped start/end
   * tangent directions.
   */
  interpolatePointsWithTangents(points, startTangent, endTangent) {
    return wrap("interpolatePointsWithTangents", () => {
      const flat = this.#flattenPoints(points);
      try {
        return handle(this.#raw.interpolatePointsWithTangents(flat, startTangent.x, startTangent.y, startTangent.z, endTangent.x, endTangent.y, endTangent.z));
      } finally {
        flat.delete();
      }
    });
  }
  /** Closest point on an edge to `point`, with the curve tangent and parameter there. */
  projectPointOnEdge(edge, point) {
    return wrap("projectPointOnEdge", () => {
      const r = this.#drainVector(this.#raw.projectPointOnEdge(edge, point.x, point.y, point.z), Float64Array);
      return {
        point: { x: r[0], y: r[1], z: r[2] },
        tangent: { x: r[3], y: r[4], z: r[5] },
        parameter: r[6]
      };
    });
  }
  approximatePoints(points, tolerance = 1e-3) {
    return wrap("approximatePoints", () => {
      const flat = this.#flattenPoints(points);
      try {
        return handle(this.#raw.approximatePoints(flat, tolerance));
      } finally {
        flat.delete();
      }
    });
  }
  getNurbsCurveData(edge) {
    return wrap("getNurbsCurveData", () => {
      const raw = this.#raw.getNurbsCurveData(edge);
      const result = {
        degree: raw.degree,
        rational: raw.rational,
        periodic: raw.periodic,
        knots: this.#drainVector(raw.knots, Float64Array),
        multiplicities: this.#drainVector(raw.multiplicities, Int32Array),
        poles: this.#drainVector(raw.poles, Float64Array),
        weights: this.#drainVector(raw.weights, Float64Array)
      };
      return result;
    });
  }
  curveDegreeElevate(edge, elevateBy) {
    return wrap("curveDegreeElevate", () => handle(this.#raw.curveDegreeElevate(edge, elevateBy)));
  }
  curveKnotInsert(edge, knot, times) {
    return wrap("curveKnotInsert", () => handle(this.#raw.curveKnotInsert(edge, knot, times)));
  }
  curveKnotRemove(edge, knot, tolerance) {
    return wrap("curveKnotRemove", () => handle(this.#raw.curveKnotRemove(edge, knot, tolerance)));
  }
  curveSplit(edge, param) {
    return wrap("curveSplit", () => {
      const parts = this.#vecToHandles(this.#raw.curveSplit(edge, param));
      if (parts.length !== 2) {
        throw new Error(`curveSplit: expected 2 edges, got ${parts.length}`);
      }
      return [parts[0], parts[1]];
    });
  }
  liftCurve2dToPlane(points2d, planeOrigin, planeZ, planeX) {
    return wrap("liftCurve2dToPlane", () => {
      const flatArr = new Array(points2d.length * 2);
      let j = 0;
      for (const p of points2d) {
        flatArr[j++] = p.x;
        flatArr[j++] = p.y;
      }
      return this.#withF64(flatArr, (flat) => handle(this.#raw.liftCurve2dToPlane(flat, planeOrigin.x, planeOrigin.y, planeOrigin.z, planeZ.x, planeZ.y, planeZ.z, planeX.x, planeX.y, planeX.z)));
    });
  }
  // =======================================================================
  // Projection (HLR)
  // =======================================================================
  projectEdges(shape, viewOrigin, viewDirection, xAxis) {
    return wrap("projectEdges", () => {
      const hasXAxis = xAxis !== void 0;
      const xx = xAxis?.x ?? 0;
      const xy = xAxis?.y ?? 0;
      const xz = xAxis?.z ?? 0;
      const raw = this.#raw.projectEdges(shape, viewOrigin.x, viewOrigin.y, viewOrigin.z, viewDirection.x, viewDirection.y, viewDirection.z, xx, xy, xz, hasXAxis);
      return {
        visibleOutline: handle(raw.visibleOutline),
        visibleSmooth: handle(raw.visibleSmooth),
        visibleSharp: handle(raw.visibleSharp),
        hiddenOutline: handle(raw.hiddenOutline),
        hiddenSmooth: handle(raw.hiddenSmooth),
        hiddenSharp: handle(raw.hiddenSharp)
      };
    });
  }
  /**
   * Render a single named view of a shape to a standalone SVG string via
   * hidden-line removal. Visible edges are solid, hidden edges dashed.
   */
  toSVG(shape, view = "front", options = {}) {
    return wrap("toSVG", () => renderShapeSVG(this, shape, view, options));
  }
  /**
   * Render a multiview grid (default Front / Top / Right / Iso) of a shape to
   * a single SVG string, with per-view gnomons and an overall size annotation.
   * Aimed at giving an automated agent a readable picture of the geometry.
   */
  toMultiviewSVG(shape, options = {}) {
    return wrap("toMultiviewSVG", () => renderMultiviewSVG(this, shape, options));
  }
  // =======================================================================
  // Modifiers
  // =======================================================================
  /**
   * Thicken a face/shell into a solid (or grow a solid uniformly).
   *
   * @param tolerance - OCCT precision for the offset reconstruction. Use
   *     `1e-6` for precise thickening (matches brepjs default); `1e-3` is a
   *     coarser legacy value.
   */
  thicken(shape, thickness, tolerance) {
    return wrap("thicken", () => handle(this.#raw.thicken(shape, thickness, tolerance)));
  }
  /**
   * Remove complete features such as holes, bosses, chamfers, or fillets and
   * heal the surrounding faces. Arbitrary isolated faces are not guaranteed
   * to be removable.
   *
   * @param tolerance - Additional fuzzy tolerance used while reconstructing
   *     the surrounding geometry. Pass `0` to use OCCT's defaults.
   */
  defeature(shape, faces, tolerance) {
    return wrap("defeature", () => {
      return this.#withU32(faces, (vec) => handle(this.#raw.defeature(shape, vec, tolerance)));
    });
  }
  reverseShape(shape) {
    return wrap("reverseShape", () => handle(this.#raw.reverseShape(shape)));
  }
  simplify(shape) {
    return wrap("simplify", () => handle(this.#raw.simplify(shape)));
  }
  filletVariable(solid, edge, startRadius, endRadius) {
    return wrap("filletVariable", () => handle(this.#raw.filletVariable(solid, edge, startRadius, endRadius)));
  }
  /** Offset a 2D wire. */
  offsetWire2D(wire, offset, joinType = JoinType.Arc) {
    return wrap("offsetWire2D", () => handle(this.#raw.offsetWire2D(wire, offset, joinType)));
  }
  // =======================================================================
  // Evolution (operations with shape history)
  // =======================================================================
  translateWithHistory(shape, dx, dy, dz, inputFaceHashes, hashUpperBound) {
    return wrap("translateWithHistory", () => {
      return this.#withI32(inputFaceHashes, (hashes) => this.#extractEvolution(this.#raw.translateWithHistory(shape, dx, dy, dz, hashes, hashUpperBound)));
    });
  }
  fuseWithHistory(a, b, inputFaceHashes, hashUpperBound) {
    return wrap("fuseWithHistory", () => {
      return this.#withI32(inputFaceHashes, (hashes) => this.#extractEvolution(this.#raw.fuseWithHistory(a, b, hashes, hashUpperBound)));
    });
  }
  cutWithHistory(a, b, inputFaceHashes, hashUpperBound) {
    return wrap("cutWithHistory", () => {
      return this.#withI32(inputFaceHashes, (hashes) => this.#extractEvolution(this.#raw.cutWithHistory(a, b, hashes, hashUpperBound)));
    });
  }
  filletWithHistory(solid, edges, radius, inputFaceHashes, hashUpperBound) {
    return wrap("filletWithHistory", () => this.#withU32(edges, (edgeVec) => this.#withI32(inputFaceHashes, (hashes) => this.#extractEvolution(this.#raw.filletWithHistory(solid, edgeVec, radius, hashes, hashUpperBound)))));
  }
  rotateWithHistory(shape, axis, angleRad, inputFaceHashes, hashUpperBound) {
    return wrap("rotateWithHistory", () => this.#withI32(inputFaceHashes, (hashes) => this.#extractEvolution(this.#raw.rotateWithHistory(shape, axis.point.x, axis.point.y, axis.point.z, axis.direction.x, axis.direction.y, axis.direction.z, angleRad, hashes, hashUpperBound))));
  }
  mirrorWithHistory(shape, point, normal, inputFaceHashes, hashUpperBound) {
    return wrap("mirrorWithHistory", () => this.#withI32(inputFaceHashes, (hashes) => this.#extractEvolution(this.#raw.mirrorWithHistory(shape, point.x, point.y, point.z, normal.x, normal.y, normal.z, hashes, hashUpperBound))));
  }
  scaleWithHistory(shape, center, factor, inputFaceHashes, hashUpperBound) {
    return wrap("scaleWithHistory", () => this.#withI32(inputFaceHashes, (hashes) => this.#extractEvolution(this.#raw.scaleWithHistory(shape, center.x, center.y, center.z, factor, hashes, hashUpperBound))));
  }
  intersectWithHistory(a, b, inputFaceHashes, hashUpperBound) {
    return wrap("intersectWithHistory", () => {
      return this.#withI32(inputFaceHashes, (hashes) => this.#extractEvolution(this.#raw.intersectWithHistory(a, b, hashes, hashUpperBound)));
    });
  }
  chamferWithHistory(solid, edges, distance, inputFaceHashes, hashUpperBound) {
    return wrap("chamferWithHistory", () => this.#withU32(edges, (edgeVec) => this.#withI32(inputFaceHashes, (hashes) => this.#extractEvolution(this.#raw.chamferWithHistory(solid, edgeVec, distance, hashes, hashUpperBound)))));
  }
  shellWithHistory(solid, faces, thickness, tolerance, inputFaceHashes, hashUpperBound) {
    return wrap("shellWithHistory", () => this.#withU32(faces, (faceVec) => this.#withI32(inputFaceHashes, (hashes) => this.#extractEvolution(this.#raw.shellWithHistory(solid, faceVec, thickness, tolerance, hashes, hashUpperBound)))));
  }
  offsetWithHistory(solid, distance, tolerance, inputFaceHashes, hashUpperBound) {
    return wrap("offsetWithHistory", () => {
      return this.#withI32(inputFaceHashes, (hashes) => this.#extractEvolution(this.#raw.offsetWithHistory(solid, distance, tolerance, hashes, hashUpperBound)));
    });
  }
  thickenWithHistory(shape, thickness, tolerance, inputFaceHashes, hashUpperBound) {
    return wrap("thickenWithHistory", () => {
      return this.#withI32(inputFaceHashes, (hashes) => this.#extractEvolution(this.#raw.thickenWithHistory(shape, thickness, tolerance, hashes, hashUpperBound)));
    });
  }
  // =======================================================================
  // Extrusion Law
  // =======================================================================
  buildExtrusionLaw(profile, length, endFactor) {
    return wrap("buildExtrusionLaw", () => handle(this.#raw.buildExtrusionLaw(profile, length, endFactor)));
  }
  trimLaw(law, first, last) {
    return wrap("trimLaw", () => handle(this.#raw.trimLaw(law, first, last)));
  }
  sweepWithLaw(profile, spine, law) {
    return wrap("sweepWithLaw", () => handle(this.#raw.sweepWithLaw(profile, spine, law)));
  }
  // =======================================================================
  // Healing / Repair
  // =======================================================================
  fixShape(shape) {
    return wrap("fixShape", () => handle(this.#raw.fixShape(shape)));
  }
  unifySameDomain(shape) {
    return wrap("unifySameDomain", () => handle(this.#raw.unifySameDomain(shape)));
  }
  isValid(shape) {
    return wrap("isValid", () => this.#raw.isValid(shape));
  }
  healSolid(shape, tolerance = 1e-6) {
    return wrap("healSolid", () => handle(this.#raw.healSolid(shape, tolerance)));
  }
  healFace(shape, tolerance = 1e-6) {
    return wrap("healFace", () => handle(this.#raw.healFace(shape, tolerance)));
  }
  healWire(shape, tolerance = 1e-6) {
    return wrap("healWire", () => handle(this.#raw.healWire(shape, tolerance)));
  }
  fixFaceOrientations(shape) {
    return wrap("fixFaceOrientations", () => handle(this.#raw.fixFaceOrientations(shape)));
  }
  removeDegenerateEdges(shape) {
    return wrap("removeDegenerateEdges", () => handle(this.#raw.removeDegenerateEdges(shape)));
  }
  buildCurves3d(wire) {
    wrap("buildCurves3d", () => this.#raw.buildCurves3d(wire));
  }
  fixWireOnFace(wire, face, tolerance = 1e-6) {
    return wrap("fixWireOnFace", () => handle(this.#raw.fixWireOnFace(wire, face, tolerance)));
  }
  // =======================================================================
  // XCAF Document Factories
  // =======================================================================
  /**
   * Create a new XCAF document with the Emscripten FS pre-injected.
   * This allows `doc.exportGLTF()` to work without passing FS explicitly.
   */
  createXCAFDocument() {
    return XCAFDocument.create(this.#raw, this.#module.FS);
  }
  /**
   * Import a STEP file into a new XCAF document with the Emscripten FS pre-injected.
   * Preserves colors, names, and assembly structure from the STEP file.
   */
  importXCAFFromSTEP(stepData) {
    return XCAFDocument.fromSTEP(this.#raw, stepData, this.#module.FS);
  }
  // =======================================================================
  // Memory
  // =======================================================================
  release(shape) {
    this.#raw.release(shape);
  }
  releaseAll() {
    this.#raw.releaseAll();
  }
  /**
   * Mark the current arena high-water point. Every handle produced after this
   * call can be reclaimed in one step with {@link releaseSince}. Pair the two
   * around a logical operation to bulk-free intermediates instead of tracking
   * each id for individual {@link release}.
   */
  checkpoint() {
    return this.#raw.checkpoint();
  }
  /**
   * Release every handle allocated at or after `mark` (a value from a prior
   * {@link checkpoint}). Handles the caller wants to keep must be produced
   * before the checkpoint, or copied out; ids created after the mark become
   * invalid once this returns.
   */
  releaseSince(mark) {
    this.#raw.releaseSince(mark);
  }
  get shapeCount() {
    return this.#raw.getShapeCount();
  }
  // =======================================================================
  // Debugging
  // =======================================================================
  /** Return a human-readable summary of a shape for debugging. */
  describe(shape) {
    const type = this.getShapeType(shape);
    const bbox = this.getBoundingBox(shape, true);
    const dims = `[${(bbox.xmax - bbox.xmin).toFixed(2)} x ${(bbox.ymax - bbox.ymin).toFixed(2)} x ${(bbox.zmax - bbox.zmin).toFixed(2)}]`;
    const parts = [`${type} ${dims}`];
    if (type === "solid" || type === "compound" || type === "compsolid") {
      parts.push(`vol=${this.getVolume(shape).toFixed(3)}`);
      parts.push(`area=${this.getSurfaceArea(shape).toFixed(3)}`);
    }
    const faces = this.getSubShapes(shape, "face");
    const edges = this.getSubShapes(shape, "edge");
    const verts = this.getSubShapes(shape, "vertex");
    parts.push(`F:${faces.length} E:${edges.length} V:${verts.length}`);
    return parts.join(" | ");
  }
  [Symbol.dispose]() {
    kernelRegistry.unregister(this);
    this.#releaseDecoder();
    try {
      this.#raw.releaseAll();
      this.#raw.delete();
    } catch {
    }
  }
  // =======================================================================
  // Raw module / kernel access (for third-party adapters)
  // =======================================================================
  /**
   * Return the underlying Emscripten module. Intended for integrators who
   * need to hand the raw module to a third-party adapter (e.g.
   * `brepjs.OcctWasmAdapter`) without bypassing {@link OcctKernel.init}.
   *
   * The module is owned by this `OcctKernel` instance — disposing the
   * kernel does not invalidate the module reference, but the raw kernel
   * obtained via {@link getRawKernel} *will* be deleted.
   */
  getRawModule() {
    return this.#module;
  }
  /**
   * Return the underlying raw Embind kernel. Intended for integrators who
   * need to hand the raw kernel to a third-party adapter (e.g.
   * `brepjs.OcctWasmAdapter`).
   *
   * Lifecycle: the raw kernel is owned by this `OcctKernel`. Calling
   * `kernel[Symbol.dispose]()` (or letting the FinalizationRegistry collect
   * the wrapper) will `releaseAll()` and `delete()` the raw kernel — so the
   * adapter must not outlive the `OcctKernel` it was constructed from.
   * Do not call `delete()` or `releaseAll()` on the raw kernel directly.
   */
  getRawKernel() {
    return this.#raw;
  }
  // =======================================================================
  // Private helpers
  // =======================================================================
  // Per-element push_back()/get() each cross the JS->WASM boundary. Below this
  // element count the per-element loop still beats the bulk HEAP-copy path (a
  // malloc round-trip on the way in, a typed-array view + copy on the way out);
  // above it, the single bulk copy wins (measured ~50% of cost on point methods).
  static #BULK_THRESHOLD = 64;
  #makeVector(ctor, values) {
    const vec = new ctor();
    for (const v2 of values) {
      vec.push_back(v2);
    }
    return vec;
  }
  // Copy an array into WASM memory in one shot, then build the vector C++-side.
  // allocBytes() may grow the heap, so the backing buffer is read after it; a
  // fresh typed-array view is layered over it at the malloc'd (aligned) offset.
  #bulkF64(values) {
    const ptr = this.#raw.allocBytes(values.length * 8);
    new Float64Array(this.#module.HEAPU32.buffer, ptr, values.length).set(values);
    try {
      return this.#raw.vectorF64FromHeap(ptr, values.length);
    } finally {
      this.#raw.freeBytes(ptr);
    }
  }
  #bulkU32(values) {
    const ptr = this.#raw.allocBytes(values.length * 4);
    new Uint32Array(this.#module.HEAPU32.buffer, ptr, values.length).set(values);
    try {
      return this.#raw.vectorU32FromHeap(ptr, values.length);
    } finally {
      this.#raw.freeBytes(ptr);
    }
  }
  #bulkI32(values) {
    const ptr = this.#raw.allocBytes(values.length * 4);
    new Int32Array(this.#module.HEAPU32.buffer, ptr, values.length).set(values);
    try {
      return this.#raw.vectorI32FromHeap(ptr, values.length);
    } finally {
      this.#raw.freeBytes(ptr);
    }
  }
  // Reverse of the #bulk* helpers: read a returned vector into a JS array.
  // Each get() is a JS->WASM crossing, so above the threshold we fetch the
  // vector's contiguous storage pointer once and copy the whole block in one
  // shot (2 crossings total, regardless of length). heap.slice() detaches a
  // copy of those WASM bytes before the typed-array view is built, so the
  // caller can free the vector afterward with no aliasing concern.
  #readVector(vec, HeapArray, count) {
    if (count < _a.#BULK_THRESHOLD) {
      const out = new Array(count);
      for (let i = 0; i < count; i++) {
        out[i] = vec.get(i);
      }
      return out;
    }
    const ptr = vec.dataPtr();
    const heap = this.#module.HEAPU32.buffer;
    const buffer = heap.slice(ptr, ptr + count * HeapArray.BYTES_PER_ELEMENT);
    return Array.from(new HeapArray(buffer));
  }
  // Read a vector to numbers, then delete it. Every call site reads-then-frees.
  #drainVector(vec, HeapArray) {
    try {
      return this.#readVector(vec, HeapArray, vec.size());
    } finally {
      vec.delete();
    }
  }
  #vecToHandles(vec) {
    try {
      return this.#readVector(vec, Uint32Array, vec.size()).map((id) => handle(id));
    } finally {
      vec.delete();
    }
  }
  #makeVectorU32(ids) {
    if (ids.length < _a.#BULK_THRESHOLD) {
      return this.#makeVector(this.#module.VectorUint32, ids);
    }
    return this.#bulkU32(ids);
  }
  #makeVectorF64(values) {
    if (values.length < _a.#BULK_THRESHOLD) {
      return this.#makeVector(this.#module.VectorDouble, values);
    }
    return this.#bulkF64(values);
  }
  #makeVectorI32(values) {
    if (values.length < _a.#BULK_THRESHOLD) {
      return this.#makeVector(this.#module.VectorInt, values);
    }
    return this.#bulkI32(values);
  }
  // Scope guards: build a vector, run `fn` with it, and always delete it.
  // Replaces the make/try/finally/delete boilerplate at every vector-arg call
  // site so the cleanup can't be forgotten or mis-copied.
  #withU32(ids, fn) {
    const vec = this.#makeVectorU32(ids);
    try {
      return fn(vec);
    } finally {
      vec.delete();
    }
  }
  #withF64(values, fn) {
    const vec = this.#makeVectorF64(values);
    try {
      return fn(vec);
    } finally {
      vec.delete();
    }
  }
  #withI32(values, fn) {
    const vec = this.#makeVectorI32(values);
    try {
      return fn(vec);
    } finally {
      vec.delete();
    }
  }
  #flattenPoints(points) {
    if (points.length * 3 < _a.#BULK_THRESHOLD) {
      const vec = new this.#module.VectorDouble();
      for (const p of points) {
        vec.push_back(p.x);
        vec.push_back(p.y);
        vec.push_back(p.z);
      }
      return vec;
    }
    const flat = new Float64Array(points.length * 3);
    let j = 0;
    for (const p of points) {
      flat[j++] = p.x;
      flat[j++] = p.y;
      flat[j++] = p.z;
    }
    return this.#bulkF64(flat);
  }
  #vec2FromEmbind(vec) {
    const u = vec.get(0);
    const v2 = vec.get(1);
    vec.delete();
    return { u, v: v2 };
  }
  #uvBoundsFromEmbind(vec) {
    const result = {
      uMin: vec.get(0),
      uMax: vec.get(1),
      vMin: vec.get(2),
      vMax: vec.get(3)
    };
    vec.delete();
    return result;
  }
  #curvatureDataFromEmbind(vec) {
    const result = {
      min: vec.get(0),
      max: vec.get(1),
      gaussian: vec.get(2),
      mean: vec.get(3)
    };
    vec.delete();
    return result;
  }
  #vec3FromEmbind(vec) {
    const x = vec.get(0);
    const y = vec.get(1);
    const z = vec.get(2);
    vec.delete();
    return { x, y, z };
  }
  #extractMesh(raw) {
    try {
      return this.#extractMeshFromRaw(raw);
    } finally {
      raw.delete();
    }
  }
  #extractMeshFromRaw(raw) {
    const vertexCount = raw.positionCount / 3;
    const triangleCount = raw.indexCount / 3;
    const positions = new Float32Array(this.#module.HEAPF32.buffer.slice(raw.getPositionsPtr(), raw.getPositionsPtr() + raw.positionCount * 4));
    const normals = new Float32Array(this.#module.HEAPF32.buffer.slice(raw.getNormalsPtr(), raw.getNormalsPtr() + raw.normalCount * 4));
    const indices = new Uint32Array(this.#module.HEAPU32.buffer.slice(raw.getIndicesPtr(), raw.getIndicesPtr() + raw.indexCount * 4));
    return { positions, normals, indices, vertexCount, triangleCount };
  }
  #extractMeshWithFaceGroups(raw) {
    try {
      const mesh = this.#extractMeshFromRaw(raw);
      if (raw.faceGroupCount > 0) {
        mesh.faceGroups = new Int32Array(this.#module.HEAP32.buffer.slice(raw.getFaceGroupsPtr(), raw.getFaceGroupsPtr() + raw.faceGroupCount * 4));
        mesh.faceCount = raw.faceGroupCount / 3;
      }
      return mesh;
    } finally {
      raw.delete();
    }
  }
  #extractEvolution(raw) {
    const modified = this.#drainVector(raw.modified, Int32Array);
    const generated = this.#drainVector(raw.generated, Int32Array);
    const deleted = this.#drainVector(raw.deleted, Int32Array);
    return {
      result: handle(raw.resultId),
      modified,
      generated,
      deleted
    };
  }
};
_a = OcctKernel;
export {
  OcctKernel
};