@componentor/fs 3.0.9 → 3.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/src/vfs/layout.ts","../../src/src/errors.ts","../../src/src/vfs/engine.ts","../../src/src/protocol/opcodes.ts","../../src/src/workers/server.worker.ts"],"sourcesContent":["/**\n * VFS Binary Layout Constants\n *\n * Defines the on-disk structure of the virtual filesystem binary file.\n * All reads/writes go through a FileSystemSyncAccessHandle.\n */\n\n// Magic number: \"VFS!\" in ASCII\nexport const VFS_MAGIC = 0x56465321;\nexport const VFS_VERSION = 1;\n\n// Default sizes\nexport const DEFAULT_BLOCK_SIZE = 4096;\nexport const DEFAULT_INODE_COUNT = 10000;\nexport const INODE_SIZE = 64; // bytes per inode entry\n\n// Superblock layout (64 bytes)\nexport const SUPERBLOCK = {\n SIZE: 64,\n MAGIC: 0, // uint32 - 0x56465321\n VERSION: 4, // uint32\n INODE_COUNT: 8, // uint32 - total inodes allocated\n BLOCK_SIZE: 12, // uint32 - data block size (default 4096)\n TOTAL_BLOCKS: 16, // uint32 - total data blocks\n FREE_BLOCKS: 20, // uint32 - available data blocks\n INODE_OFFSET: 24, // float64 - byte offset to inode table\n PATH_OFFSET: 32, // float64 - byte offset to path table\n DATA_OFFSET: 40, // float64 - byte offset to data region\n BITMAP_OFFSET: 48, // float64 - byte offset to free block bitmap\n PATH_USED: 56, // uint32 - bytes used in path table\n RESERVED: 60, // uint32\n} as const;\n\n// Inode entry layout (64 bytes each)\nexport const INODE = {\n TYPE: 0, // uint8 - 0=free, 1=file, 2=directory, 3=symlink\n FLAGS: 1, // uint8[3] - reserved\n PATH_OFFSET: 4, // uint32 - byte offset into path table\n PATH_LENGTH: 8, // uint16 - length of path string\n RESERVED_10: 10, // uint16\n MODE: 12, // uint32 - permissions (e.g. 0o100644)\n SIZE: 16, // float64 - file content size in bytes (using f64 for >4GB)\n FIRST_BLOCK: 24, // uint32 - index of first data block\n BLOCK_COUNT: 28, // uint32 - number of contiguous data blocks\n MTIME: 32, // float64 - last modification time (ms since epoch)\n CTIME: 40, // float64 - creation/change time (ms since epoch)\n ATIME: 48, // float64 - last access time (ms since epoch)\n UID: 56, // uint32 - owner\n GID: 60, // uint32 - group\n} as const;\n\n// Inode type constants\nexport const INODE_TYPE = {\n FREE: 0,\n FILE: 1,\n DIRECTORY: 2,\n SYMLINK: 3,\n} as const;\n\n// Default file modes\nexport const DEFAULT_FILE_MODE = 0o100644;\nexport const DEFAULT_DIR_MODE = 0o040755;\nexport const DEFAULT_SYMLINK_MODE = 0o120777;\nexport const DEFAULT_UMASK = 0o022;\n\n// POSIX file type bits\nexport const S_IFMT = 0o170000;\nexport const S_IFREG = 0o100000;\nexport const S_IFDIR = 0o040000;\nexport const S_IFLNK = 0o120000;\n\n// Max symlink depth for cycle detection\nexport const MAX_SYMLINK_DEPTH = 40;\n\n// Path table compaction threshold (25% dead space)\nexport const PATH_COMPACTION_THRESHOLD = 0.25;\n\n// Initial path table size (256KB)\nexport const INITIAL_PATH_TABLE_SIZE = 256 * 1024;\n\n// Initial data blocks (1024 blocks = 4MB with 4KB blocks)\nexport const INITIAL_DATA_BLOCKS = 1024;\n\n/**\n * Calculate section offsets for a fresh VFS.\n */\nexport function calculateLayout(inodeCount: number = DEFAULT_INODE_COUNT, blockSize: number = DEFAULT_BLOCK_SIZE, totalBlocks: number = INITIAL_DATA_BLOCKS) {\n const inodeTableOffset = SUPERBLOCK.SIZE;\n const inodeTableSize = inodeCount * INODE_SIZE;\n const pathTableOffset = inodeTableOffset + inodeTableSize;\n const pathTableSize = INITIAL_PATH_TABLE_SIZE;\n const bitmapOffset = pathTableOffset + pathTableSize;\n const bitmapSize = Math.ceil(totalBlocks / 8);\n // Align data region to block boundary\n const dataOffset = Math.ceil((bitmapOffset + bitmapSize) / blockSize) * blockSize;\n const totalSize = dataOffset + totalBlocks * blockSize;\n\n return {\n inodeTableOffset,\n inodeTableSize,\n pathTableOffset,\n pathTableSize,\n bitmapOffset,\n bitmapSize,\n dataOffset,\n totalSize,\n totalBlocks,\n };\n}\n","/**\n * Node.js compatible filesystem error classes\n */\n\nexport class FSError extends Error {\n code: string;\n errno: number;\n syscall?: string;\n path?: string;\n\n constructor(code: string, errno: number, message: string, syscall?: string, path?: string) {\n super(message);\n this.name = 'FSError';\n this.code = code;\n this.errno = errno;\n this.syscall = syscall;\n this.path = path;\n }\n}\n\nexport const ErrorCodes = {\n ENOENT: -2,\n EEXIST: -17,\n EISDIR: -21,\n ENOTDIR: -20,\n ENOTEMPTY: -39,\n EACCES: -13,\n EBADF: -9,\n EINVAL: -22,\n EMFILE: -24,\n ENOSPC: -28,\n EPERM: -1,\n ENOSYS: -38,\n ELOOP: -40,\n} as const;\n\n/** Binary protocol status codes → error code mapping */\nexport const STATUS_TO_CODE: Record<number, string> = {\n 0: 'OK',\n 1: 'ENOENT',\n 2: 'EEXIST',\n 3: 'EISDIR',\n 4: 'ENOTDIR',\n 5: 'ENOTEMPTY',\n 6: 'EACCES',\n 7: 'EINVAL',\n 8: 'EBADF',\n 9: 'ELOOP',\n 10: 'ENOSPC',\n};\n\n/** Error code → binary protocol status mapping */\nexport const CODE_TO_STATUS: Record<string, number> = {\n OK: 0,\n ENOENT: 1,\n EEXIST: 2,\n EISDIR: 3,\n ENOTDIR: 4,\n ENOTEMPTY: 5,\n EACCES: 6,\n EINVAL: 7,\n EBADF: 8,\n ELOOP: 9,\n ENOSPC: 10,\n};\n\nexport function createError(code: string, syscall: string, path: string): FSError {\n const errno = ErrorCodes[code as keyof typeof ErrorCodes] ?? -1;\n const messages: Record<string, string> = {\n ENOENT: 'no such file or directory',\n EEXIST: 'file already exists',\n EISDIR: 'illegal operation on a directory',\n ENOTDIR: 'not a directory',\n ENOTEMPTY: 'directory not empty',\n EACCES: 'permission denied',\n EINVAL: 'invalid argument',\n EBADF: 'bad file descriptor',\n ELOOP: 'too many symbolic links encountered',\n ENOSPC: 'no space left on device',\n };\n const msg = messages[code] ?? 'unknown error';\n return new FSError(code, errno, `${code}: ${msg}, ${syscall} '${path}'`, syscall, path);\n}\n\nexport function statusToError(status: number, syscall: string, path: string): FSError {\n const code = STATUS_TO_CODE[status] ?? 'EINVAL';\n return createError(code, syscall, path);\n}\n","/**\n * VFS Engine — operates on a FileSystemSyncAccessHandle\n *\n * Manages the binary VFS layout: superblock, inode table, path table,\n * free block bitmap, and data region. All operations are synchronous\n * and run inside the server worker.\n */\n\nimport {\n VFS_MAGIC, VFS_VERSION, SUPERBLOCK, INODE, INODE_SIZE, INODE_TYPE,\n DEFAULT_BLOCK_SIZE, DEFAULT_INODE_COUNT, DEFAULT_FILE_MODE, DEFAULT_DIR_MODE,\n DEFAULT_SYMLINK_MODE, DEFAULT_UMASK, S_IFMT, S_IFREG, S_IFDIR, S_IFLNK,\n MAX_SYMLINK_DEPTH, INITIAL_DATA_BLOCKS, INITIAL_PATH_TABLE_SIZE,\n calculateLayout,\n} from './layout.js';\nimport { CODE_TO_STATUS } from '../errors.js';\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\n\ninterface Inode {\n type: number;\n pathOffset: number;\n pathLength: number;\n mode: number;\n size: number;\n firstBlock: number;\n blockCount: number;\n mtime: number;\n ctime: number;\n atime: number;\n uid: number;\n gid: number;\n}\n\ninterface FdEntry {\n tabId: string;\n inodeIdx: number;\n position: number;\n flags: number;\n}\n\nexport class VFSEngine {\n private handle!: FileSystemSyncAccessHandle;\n private pathIndex = new Map<string, number>(); // path → inode index\n private inodeCount = 0;\n private blockSize = DEFAULT_BLOCK_SIZE;\n private totalBlocks = 0;\n private freeBlocks = 0;\n private inodeTableOffset = 0;\n private pathTableOffset = 0;\n private pathTableUsed = 0;\n private pathTableSize = 0;\n private bitmapOffset = 0;\n private dataOffset = 0;\n private umask = DEFAULT_UMASK;\n private processUid = 0;\n private processGid = 0;\n private strictPermissions = false;\n private debug = false;\n\n // File descriptor table\n private fdTable = new Map<number, FdEntry>();\n private nextFd = 3; // 0=stdin, 1=stdout, 2=stderr reserved\n\n // Reusable buffers to avoid allocations\n private inodeBuf = new Uint8Array(INODE_SIZE);\n private inodeView = new DataView(this.inodeBuf.buffer);\n\n // In-memory inode cache — eliminates disk reads for hot inodes\n private inodeCache = new Map<number, Inode>();\n private superblockBuf = new Uint8Array(SUPERBLOCK.SIZE);\n private superblockView = new DataView(this.superblockBuf.buffer);\n\n // In-memory bitmap cache — eliminates bitmap reads from OPFS\n private bitmap: Uint8Array | null = null;\n private bitmapDirtyLo = Infinity; // lowest dirty byte index\n private bitmapDirtyHi = -1; // highest dirty byte index (inclusive)\n private superblockDirty = false;\n\n // Free inode hint — skip O(n) scan\n private freeInodeHint = 0;\n\n init(\n handle: FileSystemSyncAccessHandle,\n opts?: { uid?: number; gid?: number; umask?: number; strictPermissions?: boolean; debug?: boolean }\n ): void {\n this.handle = handle;\n this.processUid = opts?.uid ?? 0;\n this.processGid = opts?.gid ?? 0;\n this.umask = opts?.umask ?? DEFAULT_UMASK;\n this.strictPermissions = opts?.strictPermissions ?? false;\n this.debug = opts?.debug ?? false;\n\n const size = handle.getSize();\n\n if (size === 0) {\n this.format();\n } else {\n this.mount();\n }\n }\n\n /** Release the sync access handle (call on fatal error or shutdown) */\n closeHandle(): void {\n try {\n this.handle?.close();\n } catch (_) {\n // Ignore — handle may already be closed\n }\n }\n\n /** Format a fresh VFS */\n private format(): void {\n const layout = calculateLayout(DEFAULT_INODE_COUNT, DEFAULT_BLOCK_SIZE, INITIAL_DATA_BLOCKS);\n\n this.inodeCount = DEFAULT_INODE_COUNT;\n this.blockSize = DEFAULT_BLOCK_SIZE;\n this.totalBlocks = layout.totalBlocks;\n this.freeBlocks = layout.totalBlocks;\n this.inodeTableOffset = layout.inodeTableOffset;\n this.pathTableOffset = layout.pathTableOffset;\n this.pathTableSize = layout.pathTableSize;\n this.pathTableUsed = 0;\n this.bitmapOffset = layout.bitmapOffset;\n this.dataOffset = layout.dataOffset;\n\n // Grow file to total size\n this.handle.truncate(layout.totalSize);\n\n // Write superblock\n this.writeSuperblock();\n\n // Zero out inode table (type=0 means free)\n const zeroBuf = new Uint8Array(layout.inodeTableSize);\n this.handle.write(zeroBuf, { at: this.inodeTableOffset });\n\n // Zero out bitmap and cache in memory\n this.bitmap = new Uint8Array(layout.bitmapSize);\n this.handle.write(this.bitmap, { at: this.bitmapOffset });\n\n // Create root directory inode\n this.createInode('/', INODE_TYPE.DIRECTORY, DEFAULT_DIR_MODE, 0);\n\n this.handle.flush();\n }\n\n /** Mount an existing VFS from disk — validates superblock integrity */\n private mount(): void {\n const fileSize = this.handle.getSize();\n if (fileSize < SUPERBLOCK.SIZE) {\n throw new Error(`Corrupt VFS: file too small (${fileSize} bytes, need at least ${SUPERBLOCK.SIZE})`);\n }\n\n this.handle.read(this.superblockBuf, { at: 0 });\n const v = this.superblockView;\n\n // Validate magic\n const magic = v.getUint32(SUPERBLOCK.MAGIC, true);\n if (magic !== VFS_MAGIC) {\n throw new Error(`Corrupt VFS: bad magic 0x${magic.toString(16)} (expected 0x${VFS_MAGIC.toString(16)})`);\n }\n\n // Validate version\n const version = v.getUint32(SUPERBLOCK.VERSION, true);\n if (version !== VFS_VERSION) {\n throw new Error(`Corrupt VFS: unsupported version ${version} (expected ${VFS_VERSION})`);\n }\n\n // Read superblock fields\n const inodeCount = v.getUint32(SUPERBLOCK.INODE_COUNT, true);\n const blockSize = v.getUint32(SUPERBLOCK.BLOCK_SIZE, true);\n const totalBlocks = v.getUint32(SUPERBLOCK.TOTAL_BLOCKS, true);\n const freeBlocks = v.getUint32(SUPERBLOCK.FREE_BLOCKS, true);\n const inodeTableOffset = v.getFloat64(SUPERBLOCK.INODE_OFFSET, true);\n const pathTableOffset = v.getFloat64(SUPERBLOCK.PATH_OFFSET, true);\n const dataOffset = v.getFloat64(SUPERBLOCK.DATA_OFFSET, true);\n const bitmapOffset = v.getFloat64(SUPERBLOCK.BITMAP_OFFSET, true);\n const pathUsed = v.getUint32(SUPERBLOCK.PATH_USED, true);\n\n // Validate field sanity\n if (blockSize === 0 || (blockSize & (blockSize - 1)) !== 0) {\n throw new Error(`Corrupt VFS: invalid block size ${blockSize} (must be power of 2)`);\n }\n if (inodeCount === 0) {\n throw new Error('Corrupt VFS: inode count is 0');\n }\n if (freeBlocks > totalBlocks) {\n throw new Error(`Corrupt VFS: free blocks (${freeBlocks}) exceeds total blocks (${totalBlocks})`);\n }\n\n // Validate section ordering: superblock < inodes < paths < bitmap < data\n if (inodeTableOffset !== SUPERBLOCK.SIZE) {\n throw new Error(`Corrupt VFS: inode table offset ${inodeTableOffset} (expected ${SUPERBLOCK.SIZE})`);\n }\n const expectedPathOffset = inodeTableOffset + inodeCount * INODE_SIZE;\n if (pathTableOffset !== expectedPathOffset) {\n throw new Error(`Corrupt VFS: path table offset ${pathTableOffset} (expected ${expectedPathOffset})`);\n }\n if (bitmapOffset <= pathTableOffset) {\n throw new Error(`Corrupt VFS: bitmap offset ${bitmapOffset} must be after path table ${pathTableOffset}`);\n }\n if (dataOffset <= bitmapOffset) {\n throw new Error(`Corrupt VFS: data offset ${dataOffset} must be after bitmap ${bitmapOffset}`);\n }\n const pathTableSize = bitmapOffset - pathTableOffset;\n if (pathUsed > pathTableSize) {\n throw new Error(`Corrupt VFS: path used (${pathUsed}) exceeds path table size (${pathTableSize})`);\n }\n\n // Validate file is large enough for the declared layout\n const expectedMinSize = dataOffset + totalBlocks * blockSize;\n if (fileSize < expectedMinSize) {\n throw new Error(`Corrupt VFS: file size ${fileSize} too small for layout (need ${expectedMinSize})`);\n }\n\n // All checks passed — commit to engine state\n this.inodeCount = inodeCount;\n this.blockSize = blockSize;\n this.totalBlocks = totalBlocks;\n this.freeBlocks = freeBlocks;\n this.inodeTableOffset = inodeTableOffset;\n this.pathTableOffset = pathTableOffset;\n this.dataOffset = dataOffset;\n this.bitmapOffset = bitmapOffset;\n this.pathTableUsed = pathUsed;\n this.pathTableSize = pathTableSize;\n\n // Load bitmap into memory\n const bitmapSize = Math.ceil(this.totalBlocks / 8);\n this.bitmap = new Uint8Array(bitmapSize);\n this.handle.read(this.bitmap, { at: this.bitmapOffset });\n\n this.rebuildIndex();\n\n // Verify root directory exists\n if (!this.pathIndex.has('/')) {\n throw new Error('Corrupt VFS: root directory \"/\" not found in inode table');\n }\n }\n\n private writeSuperblock(): void {\n const v = this.superblockView;\n v.setUint32(SUPERBLOCK.MAGIC, VFS_MAGIC, true);\n v.setUint32(SUPERBLOCK.VERSION, VFS_VERSION, true);\n v.setUint32(SUPERBLOCK.INODE_COUNT, this.inodeCount, true);\n v.setUint32(SUPERBLOCK.BLOCK_SIZE, this.blockSize, true);\n v.setUint32(SUPERBLOCK.TOTAL_BLOCKS, this.totalBlocks, true);\n v.setUint32(SUPERBLOCK.FREE_BLOCKS, this.freeBlocks, true);\n v.setFloat64(SUPERBLOCK.INODE_OFFSET, this.inodeTableOffset, true);\n v.setFloat64(SUPERBLOCK.PATH_OFFSET, this.pathTableOffset, true);\n v.setFloat64(SUPERBLOCK.DATA_OFFSET, this.dataOffset, true);\n v.setFloat64(SUPERBLOCK.BITMAP_OFFSET, this.bitmapOffset, true);\n v.setUint32(SUPERBLOCK.PATH_USED, this.pathTableUsed, true);\n this.handle.write(this.superblockBuf, { at: 0 });\n }\n\n /** Flush pending bitmap and superblock writes to disk (one write each) */\n private markBitmapDirty(lo: number, hi: number): void {\n if (lo < this.bitmapDirtyLo) this.bitmapDirtyLo = lo;\n if (hi > this.bitmapDirtyHi) this.bitmapDirtyHi = hi;\n }\n\n private commitPending(): void {\n // Trim trailing free blocks before flushing bitmap/superblock\n if (this.blocksFreedsinceTrim) {\n this.trimTrailingBlocks();\n this.blocksFreedsinceTrim = false;\n }\n\n if (this.bitmapDirtyHi >= 0) {\n const lo = this.bitmapDirtyLo;\n const hi = this.bitmapDirtyHi;\n this.handle.write(this.bitmap!.subarray(lo, hi + 1), { at: this.bitmapOffset + lo });\n this.bitmapDirtyLo = Infinity;\n this.bitmapDirtyHi = -1;\n }\n if (this.superblockDirty) {\n this.writeSuperblock();\n this.superblockDirty = false;\n }\n }\n\n /** Shrink the OPFS file by removing trailing free blocks from the data region.\n * Scans bitmap from end to find the last used block, then truncates. */\n private trimTrailingBlocks(): void {\n const bitmap = this.bitmap!;\n\n // Find the last used block by scanning bitmap from the end\n let lastUsed = -1;\n for (let byteIdx = Math.ceil(this.totalBlocks / 8) - 1; byteIdx >= 0; byteIdx--) {\n if (bitmap[byteIdx] !== 0) {\n // Find highest set bit in this byte\n for (let bit = 7; bit >= 0; bit--) {\n const blockIdx = byteIdx * 8 + bit;\n if (blockIdx < this.totalBlocks && (bitmap[byteIdx] & (1 << bit))) {\n lastUsed = blockIdx;\n break;\n }\n }\n break;\n }\n }\n\n const newTotal = Math.max(lastUsed + 1, INITIAL_DATA_BLOCKS);\n if (newTotal >= this.totalBlocks) return; // nothing to trim\n\n // Truncate the OPFS file\n this.handle.truncate(this.dataOffset + newTotal * this.blockSize);\n\n // Shrink in-memory bitmap\n const newBitmapSize = Math.ceil(newTotal / 8);\n this.bitmap = bitmap.slice(0, newBitmapSize);\n\n // Update counters\n const trimmed = this.totalBlocks - newTotal;\n this.freeBlocks -= trimmed; // these free blocks no longer exist\n this.totalBlocks = newTotal;\n this.superblockDirty = true;\n\n // Re-mark entire bitmap dirty so the smaller bitmap is flushed\n this.bitmapDirtyLo = 0;\n this.bitmapDirtyHi = newBitmapSize - 1;\n }\n\n /** Rebuild in-memory path→inode index from disk.\n * Bulk-reads the entire inode table + path table in 2 I/O calls,\n * then parses in memory (avoids 10k+ individual reads). */\n private rebuildIndex(): void {\n this.pathIndex.clear();\n this.inodeCache.clear();\n\n // Bulk read entire inode table (e.g. 640KB for 10k inodes)\n const inodeTableSize = this.inodeCount * INODE_SIZE;\n const inodeBuf = new Uint8Array(inodeTableSize);\n this.handle.read(inodeBuf, { at: this.inodeTableOffset });\n const inodeView = new DataView(inodeBuf.buffer);\n\n // Bulk read used portion of path table\n const pathBuf = this.pathTableUsed > 0 ? new Uint8Array(this.pathTableUsed) : null;\n if (pathBuf) {\n this.handle.read(pathBuf, { at: this.pathTableOffset });\n }\n\n for (let i = 0; i < this.inodeCount; i++) {\n const off = i * INODE_SIZE;\n const type = inodeView.getUint8(off + INODE.TYPE);\n if (type === INODE_TYPE.FREE) continue;\n\n const inode: Inode = {\n type,\n pathOffset: inodeView.getUint32(off + INODE.PATH_OFFSET, true),\n pathLength: inodeView.getUint16(off + INODE.PATH_LENGTH, true),\n mode: inodeView.getUint32(off + INODE.MODE, true),\n size: inodeView.getFloat64(off + INODE.SIZE, true),\n firstBlock: inodeView.getUint32(off + INODE.FIRST_BLOCK, true),\n blockCount: inodeView.getUint32(off + INODE.BLOCK_COUNT, true),\n mtime: inodeView.getFloat64(off + INODE.MTIME, true),\n ctime: inodeView.getFloat64(off + INODE.CTIME, true),\n atime: inodeView.getFloat64(off + INODE.ATIME, true),\n uid: inodeView.getUint32(off + INODE.UID, true),\n gid: inodeView.getUint32(off + INODE.GID, true),\n };\n this.inodeCache.set(i, inode);\n\n // Decode path from in-memory path table buffer (no disk read)\n const path = pathBuf\n ? decoder.decode(pathBuf.subarray(inode.pathOffset, inode.pathOffset + inode.pathLength))\n : this.readPath(inode.pathOffset, inode.pathLength);\n this.pathIndex.set(path, i);\n }\n }\n\n // ========== Low-level inode I/O ==========\n\n private readInode(idx: number): Inode {\n const cached = this.inodeCache.get(idx);\n if (cached) return cached;\n\n const offset = this.inodeTableOffset + idx * INODE_SIZE;\n this.handle.read(this.inodeBuf, { at: offset });\n const v = this.inodeView;\n const inode: Inode = {\n type: v.getUint8(INODE.TYPE),\n pathOffset: v.getUint32(INODE.PATH_OFFSET, true),\n pathLength: v.getUint16(INODE.PATH_LENGTH, true),\n mode: v.getUint32(INODE.MODE, true),\n size: v.getFloat64(INODE.SIZE, true),\n firstBlock: v.getUint32(INODE.FIRST_BLOCK, true),\n blockCount: v.getUint32(INODE.BLOCK_COUNT, true),\n mtime: v.getFloat64(INODE.MTIME, true),\n ctime: v.getFloat64(INODE.CTIME, true),\n atime: v.getFloat64(INODE.ATIME, true),\n uid: v.getUint32(INODE.UID, true),\n gid: v.getUint32(INODE.GID, true),\n };\n this.inodeCache.set(idx, inode);\n return inode;\n }\n\n private writeInode(idx: number, inode: Inode): void {\n // Maintain inode cache\n if (inode.type === INODE_TYPE.FREE) {\n this.inodeCache.delete(idx);\n } else {\n this.inodeCache.set(idx, inode);\n }\n\n const v = this.inodeView;\n v.setUint8(INODE.TYPE, inode.type);\n v.setUint8(INODE.FLAGS, 0);\n v.setUint8(INODE.FLAGS + 1, 0);\n v.setUint8(INODE.FLAGS + 2, 0);\n v.setUint32(INODE.PATH_OFFSET, inode.pathOffset, true);\n v.setUint16(INODE.PATH_LENGTH, inode.pathLength, true);\n v.setUint16(INODE.RESERVED_10, 0, true);\n v.setUint32(INODE.MODE, inode.mode, true);\n v.setFloat64(INODE.SIZE, inode.size, true);\n v.setUint32(INODE.FIRST_BLOCK, inode.firstBlock, true);\n v.setUint32(INODE.BLOCK_COUNT, inode.blockCount, true);\n v.setFloat64(INODE.MTIME, inode.mtime, true);\n v.setFloat64(INODE.CTIME, inode.ctime, true);\n v.setFloat64(INODE.ATIME, inode.atime, true);\n v.setUint32(INODE.UID, inode.uid, true);\n v.setUint32(INODE.GID, inode.gid, true);\n\n const offset = this.inodeTableOffset + idx * INODE_SIZE;\n this.handle.write(this.inodeBuf, { at: offset });\n }\n\n // ========== Path table I/O ==========\n\n private readPath(offset: number, length: number): string {\n const buf = new Uint8Array(length);\n this.handle.read(buf, { at: this.pathTableOffset + offset });\n return decoder.decode(buf);\n }\n\n private appendPath(path: string): { offset: number; length: number } {\n const bytes = encoder.encode(path);\n const offset = this.pathTableUsed;\n\n // Check if path table needs to grow\n if (offset + bytes.byteLength > this.pathTableSize) {\n this.growPathTable(offset + bytes.byteLength);\n }\n\n this.handle.write(bytes, { at: this.pathTableOffset + offset });\n this.pathTableUsed += bytes.byteLength;\n\n // Defer superblock write — committed in commitPending()\n this.superblockDirty = true;\n\n return { offset, length: bytes.byteLength };\n }\n\n private growPathTable(needed: number): void {\n // Double the path table or grow to fit needed, whichever is larger\n const newSize = Math.max(this.pathTableSize * 2, needed + INITIAL_PATH_TABLE_SIZE);\n const growth = newSize - this.pathTableSize;\n\n // Need to shift bitmap and data region forward\n // Use in-memory bitmap (no read needed)\n\n // Read existing data region\n const dataSize = this.totalBlocks * this.blockSize;\n const dataBuf = new Uint8Array(dataSize);\n this.handle.read(dataBuf, { at: this.dataOffset });\n\n // Grow file\n const newTotalSize = this.handle.getSize() + growth;\n this.handle.truncate(newTotalSize);\n\n // Write data back at new offset\n const newBitmapOffset = this.bitmapOffset + growth;\n const newDataOffset = this.dataOffset + growth;\n this.handle.write(dataBuf, { at: newDataOffset });\n this.handle.write(this.bitmap!, { at: newBitmapOffset });\n\n // Update offsets\n this.pathTableSize = newSize;\n this.bitmapOffset = newBitmapOffset;\n this.dataOffset = newDataOffset;\n\n // Mark superblock dirty (will be written in commitPending)\n this.superblockDirty = true;\n }\n\n // ========== Bitmap I/O ==========\n\n private allocateBlocks(count: number): number {\n if (count === 0) return 0;\n\n const bitmap = this.bitmap!;\n let run = 0;\n let start = 0;\n\n for (let i = 0; i < this.totalBlocks; i++) {\n const byteIdx = i >>> 3;\n const bitIdx = i & 7;\n const used = (bitmap[byteIdx] >>> bitIdx) & 1;\n\n if (used) {\n run = 0;\n start = i + 1;\n } else {\n run++;\n if (run === count) {\n // Mark blocks as used in memory\n for (let j = start; j <= i; j++) {\n const bj = j >>> 3;\n const bi = j & 7;\n bitmap[bj] |= (1 << bi);\n }\n this.markBitmapDirty(start >>> 3, i >>> 3);\n this.freeBlocks -= count;\n this.superblockDirty = true;\n return start;\n }\n }\n }\n\n // No contiguous space — grow data region\n return this.growAndAllocate(count);\n }\n\n private growAndAllocate(count: number): number {\n const oldTotal = this.totalBlocks;\n // Grow by at least doubling or enough for the request\n const newTotal = Math.max(oldTotal * 2, oldTotal + count);\n const addedBlocks = newTotal - oldTotal;\n\n // Grow the file\n const newFileSize = this.dataOffset + newTotal * this.blockSize;\n this.handle.truncate(newFileSize);\n\n // Grow in-memory bitmap\n const newBitmapSize = Math.ceil(newTotal / 8);\n const newBitmap = new Uint8Array(newBitmapSize);\n newBitmap.set(this.bitmap!);\n this.bitmap = newBitmap;\n\n this.totalBlocks = newTotal;\n this.freeBlocks += addedBlocks;\n\n // Allocate from the newly freed area\n const start = oldTotal;\n for (let j = start; j < start + count; j++) {\n const bj = j >>> 3;\n const bi = j & 7;\n this.bitmap[bj] |= (1 << bi);\n }\n\n this.markBitmapDirty(start >>> 3, (start + count - 1) >>> 3);\n this.freeBlocks -= count;\n this.superblockDirty = true;\n\n return start;\n }\n\n private blocksFreedsinceTrim = false;\n\n private freeBlockRange(start: number, count: number): void {\n if (count === 0) return;\n const bitmap = this.bitmap!;\n\n for (let i = start; i < start + count; i++) {\n const byteIdx = i >>> 3;\n const bitIdx = i & 7;\n bitmap[byteIdx] &= ~(1 << bitIdx);\n }\n\n this.markBitmapDirty(start >>> 3, (start + count - 1) >>> 3);\n this.freeBlocks += count;\n this.superblockDirty = true;\n this.blocksFreedsinceTrim = true;\n }\n\n // updateSuperblockFreeBlocks is no longer needed — superblock writes are coalesced via commitPending()\n\n // ========== Inode allocation ==========\n\n private findFreeInode(): number {\n // Start from hint to skip already-used entries\n for (let i = this.freeInodeHint; i < this.inodeCount; i++) {\n // Check cache first — cached entries are never FREE\n if (this.inodeCache.has(i)) continue;\n\n const offset = this.inodeTableOffset + i * INODE_SIZE;\n const typeBuf = new Uint8Array(1);\n this.handle.read(typeBuf, { at: offset });\n if (typeBuf[0] === INODE_TYPE.FREE) {\n this.freeInodeHint = i + 1;\n return i;\n }\n }\n // All inodes used — grow inode table\n const idx = this.growInodeTable();\n this.freeInodeHint = idx + 1;\n return idx;\n }\n\n private growInodeTable(): number {\n const oldCount = this.inodeCount;\n const newCount = oldCount * 2;\n const growth = (newCount - oldCount) * INODE_SIZE;\n\n // Read everything after inode table\n const afterInodeOffset = this.inodeTableOffset + oldCount * INODE_SIZE;\n const afterSize = this.handle.getSize() - afterInodeOffset;\n const afterBuf = new Uint8Array(afterSize);\n this.handle.read(afterBuf, { at: afterInodeOffset });\n\n // Grow file\n this.handle.truncate(this.handle.getSize() + growth);\n\n // Write back shifted content\n this.handle.write(afterBuf, { at: afterInodeOffset + growth });\n\n // Zero out new inode entries\n const zeroes = new Uint8Array(growth);\n this.handle.write(zeroes, { at: afterInodeOffset });\n\n // Update offsets\n this.pathTableOffset += growth;\n this.bitmapOffset += growth;\n this.dataOffset += growth;\n this.inodeCount = newCount;\n\n this.superblockDirty = true;\n\n return oldCount; // First new free inode\n }\n\n // ========== Data I/O ==========\n\n private readData(firstBlock: number, blockCount: number, size: number): Uint8Array {\n const buf = new Uint8Array(size);\n const offset = this.dataOffset + firstBlock * this.blockSize;\n this.handle.read(buf, { at: offset });\n return buf;\n }\n\n private writeData(firstBlock: number, data: Uint8Array): void {\n const offset = this.dataOffset + firstBlock * this.blockSize;\n this.handle.write(data, { at: offset });\n }\n\n // ========== Path resolution ==========\n\n private resolvePath(path: string, depth: number = 0): number | undefined {\n if (depth > MAX_SYMLINK_DEPTH) return undefined; // ELOOP\n\n const idx = this.pathIndex.get(path);\n if (idx === undefined) {\n // Path not found directly — try component resolution (handles intermediate symlinks)\n return this.resolvePathComponents(path, true, depth);\n }\n\n const inode = this.readInode(idx);\n if (inode.type === INODE_TYPE.SYMLINK) {\n // Follow symlink\n const target = decoder.decode(this.readData(inode.firstBlock, inode.blockCount, inode.size));\n const resolved = target.startsWith('/') ? target : this.resolveRelative(path, target);\n return this.resolvePath(resolved, depth + 1);\n }\n\n return idx;\n }\n\n /** Resolve symlinks in intermediate path components */\n private resolvePathComponents(path: string, followLast: boolean = true, depth: number = 0): number | undefined {\n if (depth > MAX_SYMLINK_DEPTH) return undefined; // ELOOP\n\n const parts = path.split('/').filter(Boolean);\n let current = '/';\n\n for (let i = 0; i < parts.length; i++) {\n const isLast = i === parts.length - 1;\n current = current === '/' ? '/' + parts[i] : current + '/' + parts[i];\n\n const idx = this.pathIndex.get(current);\n if (idx === undefined) return undefined;\n\n const inode = this.readInode(idx);\n if (inode.type === INODE_TYPE.SYMLINK && (!isLast || followLast)) {\n const target = decoder.decode(this.readData(inode.firstBlock, inode.blockCount, inode.size));\n const resolved = target.startsWith('/') ? target : this.resolveRelative(current, target);\n\n if (isLast) {\n // Use resolvePathComponents (not resolvePath) so intermediate symlinks\n // in the resolved target path are also followed\n return this.resolvePathComponents(resolved, true, depth + 1);\n }\n\n // Reconstruct remaining path with resolved symlink\n const remaining = parts.slice(i + 1).join('/');\n const newPath = resolved + (remaining ? '/' + remaining : '');\n return this.resolvePathComponents(newPath, followLast, depth + 1);\n }\n }\n\n return this.pathIndex.get(current);\n }\n\n private resolveRelative(from: string, target: string): string {\n const dir = from.substring(0, from.lastIndexOf('/')) || '/';\n const parts = (dir + '/' + target).split('/').filter(Boolean);\n const resolved: string[] = [];\n for (const p of parts) {\n if (p === '.') continue;\n if (p === '..') { resolved.pop(); continue; }\n resolved.push(p);\n }\n return '/' + resolved.join('/');\n }\n\n // ========== Core inode creation helper ==========\n\n private createInode(path: string, type: number, mode: number, size: number, data?: Uint8Array): number {\n const idx = this.findFreeInode();\n const { offset: pathOff, length: pathLen } = this.appendPath(path);\n const now = Date.now();\n\n let firstBlock = 0;\n let blockCount = 0;\n\n if (data && data.byteLength > 0) {\n blockCount = Math.ceil(data.byteLength / this.blockSize);\n firstBlock = this.allocateBlocks(blockCount);\n this.writeData(firstBlock, data);\n }\n\n const inode: Inode = {\n type,\n pathOffset: pathOff,\n pathLength: pathLen,\n mode,\n size,\n firstBlock,\n blockCount,\n mtime: now,\n ctime: now,\n atime: now,\n uid: this.processUid,\n gid: this.processGid,\n };\n\n this.writeInode(idx, inode);\n this.pathIndex.set(path, idx);\n\n return idx;\n }\n\n // ========== Public API — called by server worker dispatch ==========\n\n /** Normalize a path: ensure leading /, resolve . and .. */\n normalizePath(p: string): string {\n if (p.charCodeAt(0) !== 47) p = '/' + p; // 47 = '/'\n // Fast path: already normalized (no '.', '..', '//', trailing '/')\n if (p.length === 1) return p; // \"/\"\n if (p.indexOf('/.') === -1 && p.indexOf('//') === -1 && p.charCodeAt(p.length - 1) !== 47) {\n return p;\n }\n // Slow path: full normalize\n const parts = p.split('/').filter(Boolean);\n const resolved: string[] = [];\n for (const part of parts) {\n if (part === '.') continue;\n if (part === '..') { resolved.pop(); continue; }\n resolved.push(part);\n }\n return '/' + resolved.join('/');\n }\n\n // ---- READ ----\n read(path: string): { status: number; data: Uint8Array | null } {\n const t0 = this.debug ? performance.now() : 0;\n path = this.normalizePath(path);\n\n // Fast path: direct index lookup (skips component-by-component walk)\n let idx = this.pathIndex.get(path);\n if (idx !== undefined) {\n const inode = this.inodeCache.get(idx);\n if (inode) {\n // Symlink? Fall through to full resolve\n if (inode.type === INODE_TYPE.SYMLINK) {\n idx = this.resolvePathComponents(path, true);\n } else if (inode.type === INODE_TYPE.DIRECTORY) {\n return { status: CODE_TO_STATUS.EISDIR, data: null };\n } else {\n // Hot path: cached inode, no symlinks\n const data = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n if (this.debug) {\n const t1 = performance.now();\n console.log(`[VFS read] path=${path} size=${inode.size} TOTAL=${(t1-t0).toFixed(3)}ms (fast)`);\n }\n return { status: 0, data };\n }\n }\n }\n\n // Slow path: full component resolution (handles symlinks, uncached inodes)\n if (idx === undefined) idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n const inode = this.readInode(idx);\n if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR, data: null };\n\n const data = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n\n if (this.debug) {\n const t1 = performance.now();\n console.log(`[VFS read] path=${path} size=${inode.size} TOTAL=${(t1-t0).toFixed(3)}ms (slow path)`);\n }\n\n return { status: 0, data };\n }\n\n // ---- WRITE ----\n write(path: string, data: Uint8Array, flags: number = 0): { status: number } {\n const t0 = this.debug ? performance.now() : 0;\n path = this.normalizePath(path);\n const t1 = this.debug ? performance.now() : 0;\n\n // Ensure parent directory exists\n const parentStatus = this.ensureParent(path);\n if (parentStatus !== 0) return { status: parentStatus };\n const t2 = this.debug ? performance.now() : 0;\n\n const existingIdx = this.resolvePathComponents(path, true);\n const t3 = this.debug ? performance.now() : 0;\n\n let tAlloc = t3, tData = t3, tInode = t3;\n\n if (existingIdx !== undefined) {\n // Update existing file\n const inode = this.readInode(existingIdx);\n if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };\n\n const neededBlocks = Math.ceil(data.byteLength / this.blockSize);\n\n if (neededBlocks <= inode.blockCount) {\n // Fits in current blocks\n tAlloc = this.debug ? performance.now() : 0;\n this.writeData(inode.firstBlock, data);\n tData = this.debug ? performance.now() : 0;\n if (neededBlocks < inode.blockCount) {\n this.freeBlockRange(inode.firstBlock + neededBlocks, inode.blockCount - neededBlocks);\n }\n } else {\n // Need more blocks — free old, allocate new\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n const newFirst = this.allocateBlocks(neededBlocks);\n tAlloc = this.debug ? performance.now() : 0;\n this.writeData(newFirst, data);\n tData = this.debug ? performance.now() : 0;\n inode.firstBlock = newFirst;\n }\n\n inode.size = data.byteLength;\n inode.blockCount = neededBlocks;\n inode.mtime = Date.now();\n this.writeInode(existingIdx, inode);\n tInode = this.debug ? performance.now() : 0;\n } else {\n // Create new file\n const mode = DEFAULT_FILE_MODE & ~(this.umask & 0o777);\n this.createInode(path, INODE_TYPE.FILE, mode, data.byteLength, data);\n tAlloc = this.debug ? performance.now() : 0;\n tData = tAlloc;\n tInode = tAlloc;\n }\n\n if (flags & 1) {\n this.commitPending();\n this.handle.flush();\n }\n const tFlush = this.debug ? performance.now() : 0;\n\n if (this.debug) {\n const existing = existingIdx !== undefined;\n console.log(`[VFS write] path=${path} size=${data.byteLength} ${existing ? 'UPDATE' : 'CREATE'} normalize=${(t1-t0).toFixed(3)}ms parent=${(t2-t1).toFixed(3)}ms resolve=${(t3-t2).toFixed(3)}ms alloc=${(tAlloc-t3).toFixed(3)}ms data=${(tData-tAlloc).toFixed(3)}ms inode=${(tInode-tData).toFixed(3)}ms flush=${(tFlush-tInode).toFixed(3)}ms TOTAL=${(tFlush-t0).toFixed(3)}ms`);\n }\n\n return { status: 0 };\n }\n\n // ---- APPEND ----\n append(path: string, data: Uint8Array): { status: number } {\n path = this.normalizePath(path);\n const existingIdx = this.resolvePathComponents(path, true);\n\n if (existingIdx === undefined) {\n // Create new file with the data\n return this.write(path, data);\n }\n\n const inode = this.readInode(existingIdx);\n if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };\n\n // Read existing data\n const existing = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n\n // Concat\n const combined = new Uint8Array(existing.byteLength + data.byteLength);\n combined.set(existing);\n combined.set(data, existing.byteLength);\n\n // Rewrite\n const neededBlocks = Math.ceil(combined.byteLength / this.blockSize);\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n const newFirst = this.allocateBlocks(neededBlocks);\n this.writeData(newFirst, combined);\n\n inode.firstBlock = newFirst;\n inode.blockCount = neededBlocks;\n inode.size = combined.byteLength;\n inode.mtime = Date.now();\n this.writeInode(existingIdx, inode);\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- UNLINK ----\n unlink(path: string): { status: number } {\n path = this.normalizePath(path);\n const idx = this.pathIndex.get(path);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };\n\n // Free data blocks\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n\n // Mark inode as free\n inode.type = INODE_TYPE.FREE;\n this.writeInode(idx, inode);\n\n // Remove from index\n this.pathIndex.delete(path);\n // Reset free inode hint\n if (idx < this.freeInodeHint) this.freeInodeHint = idx;\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- STAT ----\n stat(path: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n return this.encodeStatResponse(idx);\n }\n\n // ---- LSTAT (no symlink follow) ----\n lstat(path: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.pathIndex.get(path);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n return this.encodeStatResponse(idx);\n }\n\n private encodeStatResponse(idx: number): { status: number; data: Uint8Array } {\n const inode = this.readInode(idx);\n // Encode stat into binary: type(1) + mode(4) + size(8) + mtime(8) + ctime(8) + atime(8) + uid(4) + gid(4) + ino(4) = 49 bytes\n const buf = new Uint8Array(49);\n const view = new DataView(buf.buffer);\n view.setUint8(0, inode.type);\n view.setUint32(1, inode.mode, true);\n view.setFloat64(5, inode.size, true);\n view.setFloat64(13, inode.mtime, true);\n view.setFloat64(21, inode.ctime, true);\n view.setFloat64(29, inode.atime, true);\n view.setUint32(37, inode.uid, true);\n view.setUint32(41, inode.gid, true);\n view.setUint32(45, idx, true); // ino = inode index\n\n return { status: 0, data: buf };\n }\n\n // ---- MKDIR ----\n mkdir(path: string, flags: number = 0): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const recursive = (flags & 1) !== 0;\n\n if (recursive) {\n return this.mkdirRecursive(path);\n }\n\n // Check if already exists\n if (this.pathIndex.has(path)) return { status: CODE_TO_STATUS.EEXIST, data: null };\n\n // Ensure parent exists\n const parentStatus = this.ensureParent(path);\n if (parentStatus !== 0) return { status: parentStatus, data: null };\n\n const mode = DEFAULT_DIR_MODE & ~(this.umask & 0o777);\n this.createInode(path, INODE_TYPE.DIRECTORY, mode, 0);\n\n this.commitPending();\n // Return created path as data\n const pathBytes = encoder.encode(path);\n return { status: 0, data: pathBytes };\n }\n\n private mkdirRecursive(path: string): { status: number; data: Uint8Array | null } {\n const parts = path.split('/').filter(Boolean);\n let current = '';\n let firstCreated: string | null = null;\n\n for (const part of parts) {\n current += '/' + part;\n\n if (this.pathIndex.has(current)) {\n const idx = this.pathIndex.get(current)!;\n const inode = this.readInode(idx);\n if (inode.type !== INODE_TYPE.DIRECTORY) {\n return { status: CODE_TO_STATUS.ENOTDIR, data: null };\n }\n continue;\n }\n\n const mode = DEFAULT_DIR_MODE & ~(this.umask & 0o777);\n this.createInode(current, INODE_TYPE.DIRECTORY, mode, 0);\n if (!firstCreated) firstCreated = current;\n }\n\n this.commitPending();\n const result = firstCreated ? encoder.encode(firstCreated) : undefined;\n return { status: 0, data: result ?? null };\n }\n\n // ---- RMDIR ----\n rmdir(path: string, flags: number = 0): { status: number } {\n path = this.normalizePath(path);\n const recursive = (flags & 1) !== 0;\n const idx = this.pathIndex.get(path);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n if (inode.type !== INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.ENOTDIR };\n\n // Check for children\n const children = this.getDirectChildren(path);\n\n if (children.length > 0) {\n if (!recursive) return { status: CODE_TO_STATUS.ENOTEMPTY };\n\n // Recursive delete\n for (const child of this.getAllDescendants(path)) {\n const childIdx = this.pathIndex.get(child)!;\n const childInode = this.readInode(childIdx);\n this.freeBlockRange(childInode.firstBlock, childInode.blockCount);\n childInode.type = INODE_TYPE.FREE;\n this.writeInode(childIdx, childInode);\n this.pathIndex.delete(child);\n }\n }\n\n // Remove the directory itself\n inode.type = INODE_TYPE.FREE;\n this.writeInode(idx, inode);\n this.pathIndex.delete(path);\n if (idx < this.freeInodeHint) this.freeInodeHint = idx;\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- READDIR ----\n readdir(path: string, flags: number = 0): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n const inode = this.readInode(idx);\n if (inode.type !== INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.ENOTDIR, data: null };\n\n const withFileTypes = (flags & 1) !== 0;\n const children = this.getDirectChildren(path);\n\n if (withFileTypes) {\n // Encode as: count(u32) + entries[name_len(u16) + name(bytes) + type(u8)]\n let totalSize = 4;\n const entries: { name: Uint8Array; type: number }[] = [];\n\n for (const childPath of children) {\n const name = childPath.substring(childPath.lastIndexOf('/') + 1);\n const nameBytes = encoder.encode(name);\n const childIdx = this.pathIndex.get(childPath)!;\n const childInode = this.readInode(childIdx);\n entries.push({ name: nameBytes, type: childInode.type });\n totalSize += 2 + nameBytes.byteLength + 1; // nameLen + name + type\n }\n\n const buf = new Uint8Array(totalSize);\n const view = new DataView(buf.buffer);\n view.setUint32(0, entries.length, true);\n let offset = 4;\n\n for (const entry of entries) {\n view.setUint16(offset, entry.name.byteLength, true);\n offset += 2;\n buf.set(entry.name, offset);\n offset += entry.name.byteLength;\n buf[offset++] = entry.type;\n }\n\n return { status: 0, data: buf };\n }\n\n // Simple name list: count(u32) + entries[name_len(u16) + name(bytes)]\n let totalSize = 4;\n const nameEntries: Uint8Array[] = [];\n\n for (const childPath of children) {\n const name = childPath.substring(childPath.lastIndexOf('/') + 1);\n const nameBytes = encoder.encode(name);\n nameEntries.push(nameBytes);\n totalSize += 2 + nameBytes.byteLength;\n }\n\n const buf = new Uint8Array(totalSize);\n const view = new DataView(buf.buffer);\n view.setUint32(0, nameEntries.length, true);\n let offset = 4;\n\n for (const nameBytes of nameEntries) {\n view.setUint16(offset, nameBytes.byteLength, true);\n offset += 2;\n buf.set(nameBytes, offset);\n offset += nameBytes.byteLength;\n }\n\n return { status: 0, data: buf };\n }\n\n // ---- RENAME ----\n rename(oldPath: string, newPath: string): { status: number } {\n oldPath = this.normalizePath(oldPath);\n newPath = this.normalizePath(newPath);\n\n const idx = this.pathIndex.get(oldPath);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n // Ensure parent of new path exists\n const parentStatus = this.ensureParent(newPath);\n if (parentStatus !== 0) return { status: parentStatus };\n\n // If target exists, remove it\n const existingIdx = this.pathIndex.get(newPath);\n if (existingIdx !== undefined) {\n const existingInode = this.readInode(existingIdx);\n this.freeBlockRange(existingInode.firstBlock, existingInode.blockCount);\n existingInode.type = INODE_TYPE.FREE;\n this.writeInode(existingIdx, existingInode);\n this.pathIndex.delete(newPath);\n }\n\n // Update inode with new path\n const inode = this.readInode(idx);\n const { offset: pathOff, length: pathLen } = this.appendPath(newPath);\n inode.pathOffset = pathOff;\n inode.pathLength = pathLen;\n inode.mtime = Date.now();\n this.writeInode(idx, inode);\n\n // Update index\n this.pathIndex.delete(oldPath);\n this.pathIndex.set(newPath, idx);\n\n // If it's a directory, rename all descendants\n if (inode.type === INODE_TYPE.DIRECTORY) {\n const prefix = oldPath === '/' ? '/' : oldPath + '/';\n const toRename: [string, number][] = [];\n\n for (const [p, i] of this.pathIndex) {\n if (p.startsWith(prefix)) {\n toRename.push([p, i]);\n }\n }\n\n for (const [p, i] of toRename) {\n const suffix = p.substring(oldPath.length);\n const childNewPath = newPath + suffix;\n const childInode = this.readInode(i);\n const { offset: cpo, length: cpl } = this.appendPath(childNewPath);\n childInode.pathOffset = cpo;\n childInode.pathLength = cpl;\n this.writeInode(i, childInode);\n this.pathIndex.delete(p);\n this.pathIndex.set(childNewPath, i);\n }\n }\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- EXISTS ----\n exists(path: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n const buf = new Uint8Array(1);\n buf[0] = idx !== undefined ? 1 : 0;\n return { status: 0, data: buf };\n }\n\n // ---- TRUNCATE ----\n truncate(path: string, len: number = 0): { status: number } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };\n\n if (len === 0) {\n // Free all blocks\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n inode.firstBlock = 0;\n inode.blockCount = 0;\n inode.size = 0;\n } else if (len < inode.size) {\n // Shrink\n const neededBlocks = Math.ceil(len / this.blockSize);\n if (neededBlocks < inode.blockCount) {\n this.freeBlockRange(inode.firstBlock + neededBlocks, inode.blockCount - neededBlocks);\n }\n inode.blockCount = neededBlocks;\n inode.size = len;\n } else if (len > inode.size) {\n // Grow (zero-fill)\n const neededBlocks = Math.ceil(len / this.blockSize);\n if (neededBlocks > inode.blockCount) {\n // Need more blocks\n const oldData = this.readData(inode.firstBlock, inode.blockCount, inode.size);\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n const newFirst = this.allocateBlocks(neededBlocks);\n const newData = new Uint8Array(len);\n newData.set(oldData);\n // Rest is already zero-filled\n this.writeData(newFirst, newData);\n inode.firstBlock = newFirst;\n }\n inode.blockCount = neededBlocks;\n inode.size = len;\n }\n\n inode.mtime = Date.now();\n this.writeInode(idx, inode);\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- COPY ----\n copy(srcPath: string, destPath: string, flags: number = 0): { status: number } {\n srcPath = this.normalizePath(srcPath);\n destPath = this.normalizePath(destPath);\n\n const srcIdx = this.resolvePathComponents(srcPath, true);\n if (srcIdx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const srcInode = this.readInode(srcIdx);\n if (srcInode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };\n\n // COPYFILE_EXCL check\n if ((flags & 1) && this.pathIndex.has(destPath)) {\n return { status: CODE_TO_STATUS.EEXIST };\n }\n\n // Read source data\n const data = srcInode.size > 0\n ? this.readData(srcInode.firstBlock, srcInode.blockCount, srcInode.size)\n : new Uint8Array(0);\n\n return this.write(destPath, data);\n }\n\n // ---- ACCESS ----\n access(path: string, mode: number = 0): { status: number } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n if (mode === 0) return { status: 0 }; // F_OK — just check existence\n\n if (!this.strictPermissions) return { status: 0 }; // Relaxed mode\n\n const inode = this.readInode(idx);\n // Check permission bits against process identity\n const filePerm = this.getEffectivePermission(inode);\n\n if ((mode & 4) && !(filePerm & 4)) return { status: CODE_TO_STATUS.EACCES }; // R_OK\n if ((mode & 2) && !(filePerm & 2)) return { status: CODE_TO_STATUS.EACCES }; // W_OK\n if ((mode & 1) && !(filePerm & 1)) return { status: CODE_TO_STATUS.EACCES }; // X_OK\n\n return { status: 0 };\n }\n\n private getEffectivePermission(inode: Inode): number {\n const modeBits = inode.mode & 0o777;\n if (this.processUid === inode.uid) return (modeBits >>> 6) & 7;\n if (this.processGid === inode.gid) return (modeBits >>> 3) & 7;\n return modeBits & 7;\n }\n\n // ---- REALPATH ----\n realpath(path: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n // Find the resolved path for this inode\n const inode = this.readInode(idx);\n const resolvedPath = this.readPath(inode.pathOffset, inode.pathLength);\n return { status: 0, data: encoder.encode(resolvedPath) };\n }\n\n // ---- CHMOD ----\n chmod(path: string, mode: number): { status: number } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n // Preserve file type bits, update permission bits\n inode.mode = (inode.mode & S_IFMT) | (mode & 0o7777);\n inode.ctime = Date.now();\n this.writeInode(idx, inode);\n\n return { status: 0 };\n }\n\n // ---- CHOWN ----\n chown(path: string, uid: number, gid: number): { status: number } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n inode.uid = uid;\n inode.gid = gid;\n inode.ctime = Date.now();\n this.writeInode(idx, inode);\n\n return { status: 0 };\n }\n\n // ---- UTIMES ----\n utimes(path: string, atime: number, mtime: number): { status: number } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n inode.atime = atime;\n inode.mtime = mtime;\n inode.ctime = Date.now();\n this.writeInode(idx, inode);\n\n return { status: 0 };\n }\n\n // ---- SYMLINK ----\n symlink(target: string, linkPath: string): { status: number } {\n linkPath = this.normalizePath(linkPath);\n if (this.pathIndex.has(linkPath)) return { status: CODE_TO_STATUS.EEXIST };\n\n const parentStatus = this.ensureParent(linkPath);\n if (parentStatus !== 0) return { status: parentStatus };\n\n const targetBytes = encoder.encode(target);\n this.createInode(linkPath, INODE_TYPE.SYMLINK, DEFAULT_SYMLINK_MODE, targetBytes.byteLength, targetBytes);\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- READLINK ----\n readlink(path: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.pathIndex.get(path);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n const inode = this.readInode(idx);\n if (inode.type !== INODE_TYPE.SYMLINK) return { status: CODE_TO_STATUS.EINVAL, data: null };\n\n const target = this.readData(inode.firstBlock, inode.blockCount, inode.size);\n return { status: 0, data: target };\n }\n\n // ---- LINK (hard link — copies the file) ----\n link(existingPath: string, newPath: string): { status: number } {\n return this.copy(existingPath, newPath);\n }\n\n // ---- OPEN (file descriptor) ----\n open(path: string, flags: number, tabId: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n\n const hasCreate = (flags & 64) !== 0; // O_CREAT\n const hasTrunc = (flags & 512) !== 0; // O_TRUNC\n const hasExcl = (flags & 128) !== 0; // O_EXCL\n\n let idx = this.resolvePathComponents(path, true);\n\n if (idx === undefined) {\n if (!hasCreate) return { status: CODE_TO_STATUS.ENOENT, data: null };\n // Create file\n const mode = DEFAULT_FILE_MODE & ~(this.umask & 0o777);\n idx = this.createInode(path, INODE_TYPE.FILE, mode, 0);\n } else if (hasExcl && hasCreate) {\n return { status: CODE_TO_STATUS.EEXIST, data: null };\n }\n\n if (hasTrunc) {\n this.truncate(path, 0);\n }\n\n const fd = this.nextFd++;\n this.fdTable.set(fd, { tabId, inodeIdx: idx, position: 0, flags });\n\n const buf = new Uint8Array(4);\n new DataView(buf.buffer).setUint32(0, fd, true);\n return { status: 0, data: buf };\n }\n\n // ---- CLOSE ----\n close(fd: number): { status: number } {\n if (!this.fdTable.has(fd)) return { status: CODE_TO_STATUS.EBADF };\n this.fdTable.delete(fd);\n return { status: 0 };\n }\n\n // ---- FREAD ----\n fread(fd: number, length: number, position: number | null): { status: number; data: Uint8Array | null } {\n const entry = this.fdTable.get(fd);\n if (!entry) return { status: CODE_TO_STATUS.EBADF, data: null };\n\n const inode = this.readInode(entry.inodeIdx);\n const pos = position ?? entry.position;\n const readLen = Math.min(length, inode.size - pos);\n\n if (readLen <= 0) return { status: 0, data: new Uint8Array(0) };\n\n // Read from specific offset within the file's data blocks\n const dataOffset = this.dataOffset + inode.firstBlock * this.blockSize + pos;\n const buf = new Uint8Array(readLen);\n this.handle.read(buf, { at: dataOffset });\n\n // Update position\n if (position === null) {\n entry.position += readLen;\n }\n\n return { status: 0, data: buf };\n }\n\n // ---- FWRITE ----\n fwrite(fd: number, data: Uint8Array, position: number | null): { status: number; data: Uint8Array | null } {\n const entry = this.fdTable.get(fd);\n if (!entry) return { status: CODE_TO_STATUS.EBADF, data: null };\n\n const inode = this.readInode(entry.inodeIdx);\n const isAppend = (entry.flags & 1024) !== 0; // O_APPEND\n const pos = isAppend ? inode.size : (position ?? entry.position);\n const endPos = pos + data.byteLength;\n\n // Check if we need to grow\n if (endPos > inode.size) {\n const neededBlocks = Math.ceil(endPos / this.blockSize);\n if (neededBlocks > inode.blockCount) {\n // Grow — read old data, reallocate, write back\n const oldData = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n const newFirst = this.allocateBlocks(neededBlocks);\n const newBuf = new Uint8Array(endPos);\n newBuf.set(oldData);\n newBuf.set(data, pos);\n this.writeData(newFirst, newBuf);\n inode.firstBlock = newFirst;\n inode.blockCount = neededBlocks;\n } else {\n // Fits, write at position\n const dataOffset = this.dataOffset + inode.firstBlock * this.blockSize + pos;\n this.handle.write(data, { at: dataOffset });\n }\n inode.size = endPos;\n } else {\n // Write within existing bounds\n const dataOffset = this.dataOffset + inode.firstBlock * this.blockSize + pos;\n this.handle.write(data, { at: dataOffset });\n }\n\n inode.mtime = Date.now();\n this.writeInode(entry.inodeIdx, inode);\n\n // Update position\n if (position === null) {\n entry.position = endPos;\n }\n\n this.commitPending();\n const buf = new Uint8Array(4);\n new DataView(buf.buffer).setUint32(0, data.byteLength, true);\n return { status: 0, data: buf };\n }\n\n // ---- FSTAT ----\n fstat(fd: number): { status: number; data: Uint8Array | null } {\n const entry = this.fdTable.get(fd);\n if (!entry) return { status: CODE_TO_STATUS.EBADF, data: null };\n return this.encodeStatResponse(entry.inodeIdx);\n }\n\n // ---- FTRUNCATE ----\n ftruncate(fd: number, len: number = 0): { status: number } {\n const entry = this.fdTable.get(fd);\n if (!entry) return { status: CODE_TO_STATUS.EBADF };\n\n const inode = this.readInode(entry.inodeIdx);\n const path = this.readPath(inode.pathOffset, inode.pathLength);\n return this.truncate(path, len);\n }\n\n // ---- FSYNC ----\n fsync(): { status: number } {\n this.commitPending();\n this.handle.flush();\n return { status: 0 };\n }\n\n // ---- OPENDIR ----\n opendir(path: string, tabId: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n const inode = this.readInode(idx);\n if (inode.type !== INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.ENOTDIR, data: null };\n\n // Use fd table for dir handles too\n const fd = this.nextFd++;\n this.fdTable.set(fd, { tabId, inodeIdx: idx, position: 0, flags: 0 });\n\n const buf = new Uint8Array(4);\n new DataView(buf.buffer).setUint32(0, fd, true);\n return { status: 0, data: buf };\n }\n\n // ---- MKDTEMP ----\n mkdtemp(prefix: string): { status: number; data: Uint8Array | null } {\n const suffix = Math.random().toString(36).substring(2, 8);\n const path = this.normalizePath(prefix + suffix);\n\n // Ensure parent directories exist\n const parentStatus = this.ensureParent(path);\n if (parentStatus !== 0) {\n // Auto-create parent directories for mkdtemp\n const parentPath = path.substring(0, path.lastIndexOf('/'));\n if (parentPath) {\n this.mkdirRecursive(parentPath);\n }\n }\n\n const mode = DEFAULT_DIR_MODE & ~(this.umask & 0o777);\n this.createInode(path, INODE_TYPE.DIRECTORY, mode, 0);\n\n this.commitPending();\n return { status: 0, data: encoder.encode(path) };\n }\n\n // ========== Helpers ==========\n\n private getDirectChildren(dirPath: string): string[] {\n const prefix = dirPath === '/' ? '/' : dirPath + '/';\n const children: string[] = [];\n\n for (const path of this.pathIndex.keys()) {\n if (path === dirPath) continue;\n if (!path.startsWith(prefix)) continue;\n // Direct child: no more slashes after prefix\n const rest = path.substring(prefix.length);\n if (!rest.includes('/')) {\n children.push(path);\n }\n }\n\n return children.sort();\n }\n\n private getAllDescendants(dirPath: string): string[] {\n const prefix = dirPath === '/' ? '/' : dirPath + '/';\n const descendants: string[] = [];\n\n for (const path of this.pathIndex.keys()) {\n if (path.startsWith(prefix)) descendants.push(path);\n }\n\n // Sort by depth (deepest first) for safe deletion\n return descendants.sort((a, b) => {\n const da = a.split('/').length;\n const db = b.split('/').length;\n return db - da;\n });\n }\n\n private ensureParent(path: string): number {\n const lastSlash = path.lastIndexOf('/');\n if (lastSlash <= 0) return 0; // Parent is root, always exists\n\n const parentPath = path.substring(0, lastSlash);\n const parentIdx = this.pathIndex.get(parentPath);\n if (parentIdx === undefined) return CODE_TO_STATUS.ENOENT;\n\n const parentInode = this.readInode(parentIdx);\n if (parentInode.type !== INODE_TYPE.DIRECTORY) return CODE_TO_STATUS.ENOTDIR;\n\n return 0;\n }\n\n /** Clean up all fds owned by a tab */\n cleanupTab(tabId: string): void {\n for (const [fd, entry] of this.fdTable) {\n if (entry.tabId === tabId) {\n this.fdTable.delete(fd);\n }\n }\n }\n\n /** Get all file paths and their data for OPFS sync */\n getAllFiles(): { path: string; idx: number }[] {\n const files: { path: string; idx: number }[] = [];\n for (const [path, idx] of this.pathIndex) {\n files.push({ path, idx });\n }\n return files;\n }\n\n /** Get file path for a file descriptor (used by OPFS sync for FD-based ops) */\n getPathForFd(fd: number): string | null {\n const entry = this.fdTable.get(fd);\n if (!entry) return null;\n const inode = this.readInode(entry.inodeIdx);\n return this.readPath(inode.pathOffset, inode.pathLength);\n }\n\n /** Get file data by inode index */\n getInodeData(idx: number): { type: number; data: Uint8Array; mtime: number } {\n const inode = this.readInode(idx);\n const data = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n return { type: inode.type, data, mtime: inode.mtime };\n }\n\n /** Export all files/dirs/symlinks from the VFS */\n exportAll(): Array<{ path: string; type: number; data: Uint8Array | null; mode: number; mtime: number }> {\n const result: Array<{ path: string; type: number; data: Uint8Array | null; mode: number; mtime: number }> = [];\n for (const [path, idx] of this.pathIndex) {\n const inode = this.readInode(idx);\n let data: Uint8Array | null = null;\n if (inode.type === INODE_TYPE.FILE || inode.type === INODE_TYPE.SYMLINK) {\n data = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n }\n result.push({ path, type: inode.type, data, mode: inode.mode, mtime: inode.mtime });\n }\n // Sort directories first so parents are created before children\n result.sort((a, b) => {\n if (a.type === INODE_TYPE.DIRECTORY && b.type !== INODE_TYPE.DIRECTORY) return -1;\n if (a.type !== INODE_TYPE.DIRECTORY && b.type === INODE_TYPE.DIRECTORY) return 1;\n return a.path.localeCompare(b.path);\n });\n return result;\n }\n\n flush(): void {\n this.handle.flush();\n }\n}\n","/**\n * Binary protocol operation codes and header encoding/decoding.\n * All inter-worker messages use this minimal binary protocol — no JSON, no strings.\n */\n\n// Operation codes\nexport const OP = {\n READ: 1,\n WRITE: 2,\n UNLINK: 3,\n STAT: 4,\n LSTAT: 5,\n MKDIR: 6,\n RMDIR: 7,\n READDIR: 8,\n RENAME: 9,\n EXISTS: 10,\n TRUNCATE: 11,\n APPEND: 12,\n COPY: 13,\n ACCESS: 14,\n REALPATH: 15,\n CHMOD: 16,\n CHOWN: 17,\n UTIMES: 18,\n SYMLINK: 19,\n READLINK: 20,\n LINK: 21,\n OPEN: 22,\n CLOSE: 23,\n FREAD: 24,\n FWRITE: 25,\n FSTAT: 26,\n FTRUNCATE: 27,\n FSYNC: 28,\n OPENDIR: 29,\n MKDTEMP: 30,\n} as const;\n\nexport type OpCode = (typeof OP)[keyof typeof OP];\n\n// Response status codes\nexport const STATUS = {\n OK: 0,\n ENOENT: 1,\n EEXIST: 2,\n EISDIR: 3,\n ENOTDIR: 4,\n ENOTEMPTY: 5,\n EACCES: 6,\n EINVAL: 7,\n EBADF: 8,\n ELOOP: 9,\n ENOSPC: 10,\n} as const;\n\n// SAB layout offsets\nexport const SAB_OFFSETS = {\n CONTROL: 0, // Int32 - signal (0=idle, 1=request, 2=response, 3=chunk, 4=ack)\n OPCODE: 4, // Int32 - operation code\n STATUS: 8, // Int32 - response status / error\n CHUNK_LEN: 12, // Int32 - bytes in this chunk\n TOTAL_LEN: 16, // BigUint64 - full data size across all chunks\n CHUNK_IDX: 24, // Int32 - 0-based chunk index\n RESERVED: 28, // Int32 - reserved\n HEADER_SIZE: 32, // Data payload starts here\n} as const;\n\n// SAB control signals\nexport const SIGNAL = {\n IDLE: 0,\n REQUEST: 1,\n RESPONSE: 2,\n CHUNK: 3,\n CHUNK_ACK: 4,\n} as const;\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\n\n/**\n * Encode a request into an ArrayBuffer for MessageChannel transfer.\n *\n * Request format (16-byte header + path + data):\n * bytes 0-3: operation (uint32)\n * bytes 4-7: flags (uint32)\n * bytes 8-11: pathLen (uint32)\n * bytes 12-15: dataLen (uint32)\n * bytes 16+: path (UTF-8)\n * bytes 16+pathLen: data payload\n */\nexport function encodeRequest(\n op: number,\n path: string,\n flags: number = 0,\n data?: Uint8Array\n): ArrayBuffer {\n const pathBytes = encoder.encode(path);\n const dataLen = data ? data.byteLength : 0;\n const totalLen = 16 + pathBytes.byteLength + dataLen;\n const buf = new ArrayBuffer(totalLen);\n const view = new DataView(buf);\n\n view.setUint32(0, op, true);\n view.setUint32(4, flags, true);\n view.setUint32(8, pathBytes.byteLength, true);\n view.setUint32(12, dataLen, true);\n\n const bytes = new Uint8Array(buf);\n bytes.set(pathBytes, 16);\n if (data) {\n bytes.set(data, 16 + pathBytes.byteLength);\n }\n\n return buf;\n}\n\n/**\n * Decode a request ArrayBuffer.\n */\nexport function decodeRequest(buf: ArrayBuffer): {\n op: number;\n flags: number;\n path: string;\n data: Uint8Array | null;\n} {\n const view = new DataView(buf);\n const op = view.getUint32(0, true);\n const flags = view.getUint32(4, true);\n const pathLen = view.getUint32(8, true);\n const dataLen = view.getUint32(12, true);\n\n const bytes = new Uint8Array(buf);\n const path = decoder.decode(bytes.subarray(16, 16 + pathLen));\n const data = dataLen > 0\n ? bytes.subarray(16 + pathLen, 16 + pathLen + dataLen)\n : null;\n\n return { op, flags, path, data };\n}\n\n/**\n * Encode a response into an ArrayBuffer.\n *\n * Response format (8-byte header + data):\n * bytes 0-3: status (uint32)\n * bytes 4-7: dataLen (uint32)\n * bytes 8+: data payload\n */\nexport function encodeResponse(status: number, data?: Uint8Array): ArrayBuffer {\n const dataLen = data ? data.byteLength : 0;\n const buf = new ArrayBuffer(8 + dataLen);\n const view = new DataView(buf);\n\n view.setUint32(0, status, true);\n view.setUint32(4, dataLen, true);\n\n if (data) {\n new Uint8Array(buf).set(data, 8);\n }\n\n return buf;\n}\n\n/**\n * Decode a response ArrayBuffer.\n */\nexport function decodeResponse(buf: ArrayBuffer): {\n status: number;\n data: Uint8Array | null;\n} {\n const view = new DataView(buf);\n const status = view.getUint32(0, true);\n const dataLen = view.getUint32(4, true);\n\n const data = dataLen > 0\n ? new Uint8Array(buf, 8, dataLen)\n : null;\n\n return { status, data };\n}\n\n/**\n * Encode a two-path request (rename, copy, symlink, link).\n * Data payload contains: [pathLen2:u32] [path2 bytes]\n */\nexport function encodeTwoPathRequest(\n op: number,\n path1: string,\n path2: string,\n flags: number = 0\n): ArrayBuffer {\n const path2Bytes = encoder.encode(path2);\n const payload = new Uint8Array(4 + path2Bytes.byteLength);\n const pv = new DataView(payload.buffer);\n pv.setUint32(0, path2Bytes.byteLength, true);\n payload.set(path2Bytes, 4);\n\n return encodeRequest(op, path1, flags, payload);\n}\n\n/**\n * Decode the second path from a two-path request's data payload.\n */\nexport function decodeSecondPath(data: Uint8Array): string {\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const pathLen = view.getUint32(0, true);\n return decoder.decode(data.subarray(4, 4 + pathLen));\n}\n","/**\n * Server Worker — the VFS file handle owner.\n *\n * This worker is the ONLY entity that opens sync file handles.\n * It receives binary requests from client workers via MessageChannel\n * ports and dispatches to the VFS engine.\n *\n * Critical performance rules:\n * 1. Only receives and sends ArrayBuffers — no JSON, no strings\n * 2. Only does sync file operations\n * 3. Minimal work — decode header, execute op, encode response\n * 4. Zero-copy transfers on all MessageChannel communication\n * 5. No encoding/decoding — that is the client's responsibility\n * 6. Handles stay open — never close/reopen during normal operation\n */\n\nimport { VFSEngine } from '../vfs/engine.js';\nimport { decodeRequest, decodeSecondPath, encodeResponse, OP } from '../protocol/opcodes.js';\n\nconst engine = new VFSEngine();\n\n// Map of tabId → received port (from client workers via Service Worker)\nconst ports = new Map<string, MessagePort>();\n\n// OPFS Sync Worker port (optional)\nlet opfsSyncPort: MessagePort | null = null;\n\n// Config received from spawning tab\nlet config: {\n root: string;\n opfsSync: boolean;\n uid: number;\n gid: number;\n umask: number;\n strictPermissions: boolean;\n} = {\n root: '/',\n opfsSync: true,\n uid: 0,\n gid: 0,\n umask: 0o022,\n strictPermissions: false,\n};\n\n/**\n * Handle a binary request from a client worker.\n */\nfunction handleRequest(tabId: string, buffer: ArrayBuffer): ArrayBuffer {\n const { op, flags, path, data } = decodeRequest(buffer);\n\n let result: { status: number; data?: Uint8Array | null };\n\n switch (op) {\n case OP.READ:\n result = engine.read(path);\n break;\n\n case OP.WRITE:\n result = engine.write(path, data ?? new Uint8Array(0), flags);\n notifyOPFSSync('write', path, data);\n break;\n\n case OP.APPEND:\n result = engine.append(path, data ?? new Uint8Array(0));\n notifyOPFSSync('write', path, data);\n break;\n\n case OP.UNLINK:\n result = engine.unlink(path);\n notifyOPFSSync('delete', path);\n break;\n\n case OP.STAT:\n result = engine.stat(path);\n break;\n\n case OP.LSTAT:\n result = engine.lstat(path);\n break;\n\n case OP.MKDIR:\n result = engine.mkdir(path, flags);\n notifyOPFSSync('mkdir', path);\n break;\n\n case OP.RMDIR:\n result = engine.rmdir(path, flags);\n notifyOPFSSync('delete', path);\n break;\n\n case OP.READDIR:\n result = engine.readdir(path, flags);\n break;\n\n case OP.RENAME: {\n const newPath = data ? decodeSecondPath(data) : '';\n result = engine.rename(path, newPath);\n notifyOPFSSync('rename', path, undefined, newPath);\n break;\n }\n\n case OP.EXISTS:\n result = engine.exists(path);\n break;\n\n case OP.TRUNCATE: {\n const len = data ? new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true) : 0;\n result = engine.truncate(path, len);\n break;\n }\n\n case OP.COPY: {\n const destPath = data ? decodeSecondPath(data) : '';\n result = engine.copy(path, destPath, flags);\n break;\n }\n\n case OP.ACCESS:\n result = engine.access(path, flags);\n break;\n\n case OP.REALPATH:\n result = engine.realpath(path);\n break;\n\n case OP.CHMOD: {\n const mode = data ? new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true) : 0;\n result = engine.chmod(path, mode);\n break;\n }\n\n case OP.CHOWN: {\n if (!data || data.byteLength < 8) {\n result = { status: 7 }; // EINVAL\n break;\n }\n const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const uid = dv.getUint32(0, true);\n const gid = dv.getUint32(4, true);\n result = engine.chown(path, uid, gid);\n break;\n }\n\n case OP.UTIMES: {\n if (!data || data.byteLength < 16) {\n result = { status: 7 }; // EINVAL\n break;\n }\n const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const atime = dv.getFloat64(0, true);\n const mtime = dv.getFloat64(8, true);\n result = engine.utimes(path, atime, mtime);\n break;\n }\n\n case OP.SYMLINK: {\n const target = data ? new TextDecoder().decode(data) : '';\n result = engine.symlink(target, path);\n break;\n }\n\n case OP.READLINK:\n result = engine.readlink(path);\n break;\n\n case OP.LINK: {\n const newPath = data ? decodeSecondPath(data) : '';\n result = engine.link(path, newPath);\n break;\n }\n\n case OP.OPEN: {\n result = engine.open(path, flags, tabId);\n break;\n }\n\n case OP.CLOSE: {\n const fd = data ? new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true) : 0;\n result = engine.close(fd);\n break;\n }\n\n case OP.FREAD: {\n if (!data || data.byteLength < 12) {\n result = { status: 7 }; // EINVAL\n break;\n }\n const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const fd = dv.getUint32(0, true);\n const length = dv.getUint32(4, true);\n const pos = dv.getInt32(8, true);\n result = engine.fread(fd, length, pos === -1 ? null : pos);\n break;\n }\n\n case OP.FWRITE: {\n if (!data || data.byteLength < 8) {\n result = { status: 7 }; // EINVAL\n break;\n }\n const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const fd = dv.getUint32(0, true);\n const pos = dv.getInt32(4, true);\n const writeData = data.subarray(8);\n result = engine.fwrite(fd, writeData, pos === -1 ? null : pos);\n break;\n }\n\n case OP.FSTAT: {\n const fd = data ? new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true) : 0;\n result = engine.fstat(fd);\n break;\n }\n\n case OP.FTRUNCATE: {\n if (!data || data.byteLength < 8) {\n result = { status: 7 };\n break;\n }\n const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const fd = dv.getUint32(0, true);\n const len = dv.getUint32(4, true);\n result = engine.ftruncate(fd, len);\n break;\n }\n\n case OP.FSYNC:\n result = engine.fsync();\n break;\n\n case OP.OPENDIR:\n result = engine.opendir(path, tabId);\n break;\n\n case OP.MKDTEMP:\n result = engine.mkdtemp(path);\n break;\n\n default:\n result = { status: 7 }; // EINVAL — unknown op\n }\n\n const responseData = result.data instanceof Uint8Array ? result.data : undefined;\n return encodeResponse(result.status, responseData);\n}\n\n/** Notify OPFS sync worker of a VFS mutation */\nfunction notifyOPFSSync(\n op: 'write' | 'delete' | 'mkdir' | 'rename',\n path: string,\n data?: Uint8Array | null,\n newPath?: string\n): void {\n if (!opfsSyncPort) return;\n\n const msg: Record<string, unknown> = { op, path, ts: Date.now() };\n const transfers: ArrayBuffer[] = [];\n\n if (op === 'write' && data) {\n // Copy data for transfer (original may be reused)\n const copy = data.slice().buffer;\n msg.data = copy;\n transfers.push(copy);\n }\n\n if (op === 'rename' && newPath) {\n msg.newPath = newPath;\n }\n\n opfsSyncPort.postMessage(msg, transfers);\n}\n\n/** Set up a client port for a specific tab */\nfunction setupClientPort(tabId: string, port: MessagePort): void {\n ports.set(tabId, port);\n\n port.onmessage = (e: MessageEvent) => {\n const { buffer, id } = e.data;\n\n if (buffer instanceof ArrayBuffer) {\n const response = handleRequest(tabId, buffer);\n port.postMessage({ id, buffer: response }, [response]);\n }\n };\n\n port.start();\n}\n\n/** Handle tab death — clean up resources */\nfunction onTabLost(tabId: string): void {\n engine.cleanupTab(tabId);\n const port = ports.get(tabId);\n if (port) {\n port.close();\n ports.delete(tabId);\n }\n}\n\n// ========== Initialization ==========\n\nasync function init(initData: {\n root: string;\n opfsSync: boolean;\n uid: number;\n gid: number;\n umask: number;\n strictPermissions: boolean;\n}): Promise<void> {\n config = initData;\n\n // Get OPFS root\n let rootDir = await navigator.storage.getDirectory();\n\n // Navigate to configured root\n if (config.root && config.root !== '/') {\n const segments = config.root.split('/').filter(Boolean);\n for (const segment of segments) {\n rootDir = await rootDir.getDirectoryHandle(segment, { create: true });\n }\n }\n\n // Open VFS binary file\n const vfsFileHandle = await rootDir.getFileHandle('.vfs.bin', { create: true });\n const vfsHandle = await vfsFileHandle.createSyncAccessHandle();\n\n // Initialize VFS engine\n engine.init(vfsHandle, {\n uid: config.uid,\n gid: config.gid,\n umask: config.umask,\n strictPermissions: config.strictPermissions,\n });\n}\n\n// ========== Message handling (from sync relay worker in same tab) ==========\n\nself.onmessage = async (e: MessageEvent) => {\n const msg = e.data;\n\n if (msg.type === 'init') {\n await init(msg.config);\n (self as unknown as Worker).postMessage({ type: 'ready' });\n return;\n }\n\n if (msg.type === 'port') {\n // Receive a client port (transferred from service worker or direct)\n setupClientPort(msg.tabId, msg.port);\n return;\n }\n\n if (msg.type === 'tab-lost') {\n onTabLost(msg.tabId);\n return;\n }\n\n if (msg.type === 'opfs-sync-port') {\n opfsSyncPort = msg.port;\n opfsSyncPort!.start();\n return;\n }\n\n // Direct request (from same-tab sync worker, uses buffer + id)\n if (msg.buffer instanceof ArrayBuffer) {\n const tabId = msg.tabId || 'local';\n const response = handleRequest(tabId, msg.buffer);\n (self as unknown as Worker).postMessage(\n { id: msg.id, buffer: response },\n [response]\n );\n }\n};\n"],"mappings":";AAQO,IAAM,YAAY;AAClB,IAAM,cAAc;AAGpB,IAAM,qBAAqB;AAC3B,IAAM,sBAAsB;AAC5B,IAAM,aAAa;AAGnB,IAAM,aAAa;AAAA,EACxB,MAAM;AAAA,EACN,OAAO;AAAA;AAAA,EACP,SAAS;AAAA;AAAA,EACT,aAAa;AAAA;AAAA,EACb,YAAY;AAAA;AAAA,EACZ,cAAc;AAAA;AAAA,EACd,aAAa;AAAA;AAAA,EACb,cAAc;AAAA;AAAA,EACd,aAAa;AAAA;AAAA,EACb,aAAa;AAAA;AAAA,EACb,eAAe;AAAA;AAAA,EACf,WAAW;AAAA;AAAA,EACX,UAAU;AAAA;AACZ;AAGO,IAAM,QAAQ;AAAA,EACnB,MAAM;AAAA;AAAA,EACN,OAAO;AAAA;AAAA,EACP,aAAa;AAAA;AAAA,EACb,aAAa;AAAA;AAAA,EACb,aAAa;AAAA;AAAA,EACb,MAAM;AAAA;AAAA,EACN,MAAM;AAAA;AAAA,EACN,aAAa;AAAA;AAAA,EACb,aAAa;AAAA;AAAA,EACb,OAAO;AAAA;AAAA,EACP,OAAO;AAAA;AAAA,EACP,OAAO;AAAA;AAAA,EACP,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AACP;AAGO,IAAM,aAAa;AAAA,EACxB,MAAM;AAAA,EACN,MAAM;AAAA,EACN,WAAW;AAAA,EACX,SAAS;AACX;AAGO,IAAM,oBAAoB;AAC1B,IAAM,mBAAmB;AACzB,IAAM,uBAAuB;AAC7B,IAAM,gBAAgB;AAGtB,IAAM,SAAS;AAMf,IAAM,oBAAoB;AAM1B,IAAM,0BAA0B,MAAM;AAGtC,IAAM,sBAAsB;AAK5B,SAAS,gBAAgB,aAAqB,qBAAqB,YAAoB,oBAAoB,cAAsB,qBAAqB;AAC3J,QAAM,mBAAmB,WAAW;AACpC,QAAM,iBAAiB,aAAa;AACpC,QAAM,kBAAkB,mBAAmB;AAC3C,QAAM,gBAAgB;AACtB,QAAM,eAAe,kBAAkB;AACvC,QAAM,aAAa,KAAK,KAAK,cAAc,CAAC;AAE5C,QAAM,aAAa,KAAK,MAAM,eAAe,cAAc,SAAS,IAAI;AACxE,QAAM,YAAY,aAAa,cAAc;AAE7C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACxDO,IAAM,iBAAyC;AAAA,EACpD,IAAI;AAAA,EACJ,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ;AACV;;;AC/CA,IAAM,UAAU,IAAI,YAAY;AAChC,IAAM,UAAU,IAAI,YAAY;AAwBzB,IAAM,YAAN,MAAgB;AAAA,EACb;AAAA,EACA,YAAY,oBAAI,IAAoB;AAAA;AAAA,EACpC,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,aAAa;AAAA,EACb,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,aAAa;AAAA,EACb,oBAAoB;AAAA,EACpB,QAAQ;AAAA;AAAA,EAGR,UAAU,oBAAI,IAAqB;AAAA,EACnC,SAAS;AAAA;AAAA;AAAA,EAGT,WAAW,IAAI,WAAW,UAAU;AAAA,EACpC,YAAY,IAAI,SAAS,KAAK,SAAS,MAAM;AAAA;AAAA,EAG7C,aAAa,oBAAI,IAAmB;AAAA,EACpC,gBAAgB,IAAI,WAAW,WAAW,IAAI;AAAA,EAC9C,iBAAiB,IAAI,SAAS,KAAK,cAAc,MAAM;AAAA;AAAA,EAGvD,SAA4B;AAAA,EAC5B,gBAAgB;AAAA;AAAA,EAChB,gBAAgB;AAAA;AAAA,EAChB,kBAAkB;AAAA;AAAA,EAGlB,gBAAgB;AAAA,EAExB,KACE,QACA,MACM;AACN,SAAK,SAAS;AACd,SAAK,aAAa,MAAM,OAAO;AAC/B,SAAK,aAAa,MAAM,OAAO;AAC/B,SAAK,QAAQ,MAAM,SAAS;AAC5B,SAAK,oBAAoB,MAAM,qBAAqB;AACpD,SAAK,QAAQ,MAAM,SAAS;AAE5B,UAAM,OAAO,OAAO,QAAQ;AAE5B,QAAI,SAAS,GAAG;AACd,WAAK,OAAO;AAAA,IACd,OAAO;AACL,WAAK,MAAM;AAAA,IACb;AAAA,EACF;AAAA;AAAA,EAGA,cAAoB;AAClB,QAAI;AACF,WAAK,QAAQ,MAAM;AAAA,IACrB,SAAS,GAAG;AAAA,IAEZ;AAAA,EACF;AAAA;AAAA,EAGQ,SAAe;AACrB,UAAM,SAAS,gBAAgB,qBAAqB,oBAAoB,mBAAmB;AAE3F,SAAK,aAAa;AAClB,SAAK,YAAY;AACjB,SAAK,cAAc,OAAO;AAC1B,SAAK,aAAa,OAAO;AACzB,SAAK,mBAAmB,OAAO;AAC/B,SAAK,kBAAkB,OAAO;AAC9B,SAAK,gBAAgB,OAAO;AAC5B,SAAK,gBAAgB;AACrB,SAAK,eAAe,OAAO;AAC3B,SAAK,aAAa,OAAO;AAGzB,SAAK,OAAO,SAAS,OAAO,SAAS;AAGrC,SAAK,gBAAgB;AAGrB,UAAM,UAAU,IAAI,WAAW,OAAO,cAAc;AACpD,SAAK,OAAO,MAAM,SAAS,EAAE,IAAI,KAAK,iBAAiB,CAAC;AAGxD,SAAK,SAAS,IAAI,WAAW,OAAO,UAAU;AAC9C,SAAK,OAAO,MAAM,KAAK,QAAQ,EAAE,IAAI,KAAK,aAAa,CAAC;AAGxD,SAAK,YAAY,KAAK,WAAW,WAAW,kBAAkB,CAAC;AAE/D,SAAK,OAAO,MAAM;AAAA,EACpB;AAAA;AAAA,EAGQ,QAAc;AACpB,UAAM,WAAW,KAAK,OAAO,QAAQ;AACrC,QAAI,WAAW,WAAW,MAAM;AAC9B,YAAM,IAAI,MAAM,gCAAgC,QAAQ,yBAAyB,WAAW,IAAI,GAAG;AAAA,IACrG;AAEA,SAAK,OAAO,KAAK,KAAK,eAAe,EAAE,IAAI,EAAE,CAAC;AAC9C,UAAM,IAAI,KAAK;AAGf,UAAM,QAAQ,EAAE,UAAU,WAAW,OAAO,IAAI;AAChD,QAAI,UAAU,WAAW;AACvB,YAAM,IAAI,MAAM,4BAA4B,MAAM,SAAS,EAAE,CAAC,gBAAgB,UAAU,SAAS,EAAE,CAAC,GAAG;AAAA,IACzG;AAGA,UAAM,UAAU,EAAE,UAAU,WAAW,SAAS,IAAI;AACpD,QAAI,YAAY,aAAa;AAC3B,YAAM,IAAI,MAAM,oCAAoC,OAAO,cAAc,WAAW,GAAG;AAAA,IACzF;AAGA,UAAM,aAAa,EAAE,UAAU,WAAW,aAAa,IAAI;AAC3D,UAAM,YAAY,EAAE,UAAU,WAAW,YAAY,IAAI;AACzD,UAAM,cAAc,EAAE,UAAU,WAAW,cAAc,IAAI;AAC7D,UAAM,aAAa,EAAE,UAAU,WAAW,aAAa,IAAI;AAC3D,UAAM,mBAAmB,EAAE,WAAW,WAAW,cAAc,IAAI;AACnE,UAAM,kBAAkB,EAAE,WAAW,WAAW,aAAa,IAAI;AACjE,UAAM,aAAa,EAAE,WAAW,WAAW,aAAa,IAAI;AAC5D,UAAM,eAAe,EAAE,WAAW,WAAW,eAAe,IAAI;AAChE,UAAM,WAAW,EAAE,UAAU,WAAW,WAAW,IAAI;AAGvD,QAAI,cAAc,MAAM,YAAa,YAAY,OAAQ,GAAG;AAC1D,YAAM,IAAI,MAAM,mCAAmC,SAAS,uBAAuB;AAAA,IACrF;AACA,QAAI,eAAe,GAAG;AACpB,YAAM,IAAI,MAAM,+BAA+B;AAAA,IACjD;AACA,QAAI,aAAa,aAAa;AAC5B,YAAM,IAAI,MAAM,6BAA6B,UAAU,2BAA2B,WAAW,GAAG;AAAA,IAClG;AAGA,QAAI,qBAAqB,WAAW,MAAM;AACxC,YAAM,IAAI,MAAM,mCAAmC,gBAAgB,cAAc,WAAW,IAAI,GAAG;AAAA,IACrG;AACA,UAAM,qBAAqB,mBAAmB,aAAa;AAC3D,QAAI,oBAAoB,oBAAoB;AAC1C,YAAM,IAAI,MAAM,kCAAkC,eAAe,cAAc,kBAAkB,GAAG;AAAA,IACtG;AACA,QAAI,gBAAgB,iBAAiB;AACnC,YAAM,IAAI,MAAM,8BAA8B,YAAY,6BAA6B,eAAe,EAAE;AAAA,IAC1G;AACA,QAAI,cAAc,cAAc;AAC9B,YAAM,IAAI,MAAM,4BAA4B,UAAU,yBAAyB,YAAY,EAAE;AAAA,IAC/F;AACA,UAAM,gBAAgB,eAAe;AACrC,QAAI,WAAW,eAAe;AAC5B,YAAM,IAAI,MAAM,2BAA2B,QAAQ,8BAA8B,aAAa,GAAG;AAAA,IACnG;AAGA,UAAM,kBAAkB,aAAa,cAAc;AACnD,QAAI,WAAW,iBAAiB;AAC9B,YAAM,IAAI,MAAM,0BAA0B,QAAQ,+BAA+B,eAAe,GAAG;AAAA,IACrG;AAGA,SAAK,aAAa;AAClB,SAAK,YAAY;AACjB,SAAK,cAAc;AACnB,SAAK,aAAa;AAClB,SAAK,mBAAmB;AACxB,SAAK,kBAAkB;AACvB,SAAK,aAAa;AAClB,SAAK,eAAe;AACpB,SAAK,gBAAgB;AACrB,SAAK,gBAAgB;AAGrB,UAAM,aAAa,KAAK,KAAK,KAAK,cAAc,CAAC;AACjD,SAAK,SAAS,IAAI,WAAW,UAAU;AACvC,SAAK,OAAO,KAAK,KAAK,QAAQ,EAAE,IAAI,KAAK,aAAa,CAAC;AAEvD,SAAK,aAAa;AAGlB,QAAI,CAAC,KAAK,UAAU,IAAI,GAAG,GAAG;AAC5B,YAAM,IAAI,MAAM,0DAA0D;AAAA,IAC5E;AAAA,EACF;AAAA,EAEQ,kBAAwB;AAC9B,UAAM,IAAI,KAAK;AACf,MAAE,UAAU,WAAW,OAAO,WAAW,IAAI;AAC7C,MAAE,UAAU,WAAW,SAAS,aAAa,IAAI;AACjD,MAAE,UAAU,WAAW,aAAa,KAAK,YAAY,IAAI;AACzD,MAAE,UAAU,WAAW,YAAY,KAAK,WAAW,IAAI;AACvD,MAAE,UAAU,WAAW,cAAc,KAAK,aAAa,IAAI;AAC3D,MAAE,UAAU,WAAW,aAAa,KAAK,YAAY,IAAI;AACzD,MAAE,WAAW,WAAW,cAAc,KAAK,kBAAkB,IAAI;AACjE,MAAE,WAAW,WAAW,aAAa,KAAK,iBAAiB,IAAI;AAC/D,MAAE,WAAW,WAAW,aAAa,KAAK,YAAY,IAAI;AAC1D,MAAE,WAAW,WAAW,eAAe,KAAK,cAAc,IAAI;AAC9D,MAAE,UAAU,WAAW,WAAW,KAAK,eAAe,IAAI;AAC1D,SAAK,OAAO,MAAM,KAAK,eAAe,EAAE,IAAI,EAAE,CAAC;AAAA,EACjD;AAAA;AAAA,EAGQ,gBAAgB,IAAY,IAAkB;AACpD,QAAI,KAAK,KAAK,cAAe,MAAK,gBAAgB;AAClD,QAAI,KAAK,KAAK,cAAe,MAAK,gBAAgB;AAAA,EACpD;AAAA,EAEQ,gBAAsB;AAE5B,QAAI,KAAK,sBAAsB;AAC7B,WAAK,mBAAmB;AACxB,WAAK,uBAAuB;AAAA,IAC9B;AAEA,QAAI,KAAK,iBAAiB,GAAG;AAC3B,YAAM,KAAK,KAAK;AAChB,YAAM,KAAK,KAAK;AAChB,WAAK,OAAO,MAAM,KAAK,OAAQ,SAAS,IAAI,KAAK,CAAC,GAAG,EAAE,IAAI,KAAK,eAAe,GAAG,CAAC;AACnF,WAAK,gBAAgB;AACrB,WAAK,gBAAgB;AAAA,IACvB;AACA,QAAI,KAAK,iBAAiB;AACxB,WAAK,gBAAgB;AACrB,WAAK,kBAAkB;AAAA,IACzB;AAAA,EACF;AAAA;AAAA;AAAA,EAIQ,qBAA2B;AACjC,UAAM,SAAS,KAAK;AAGpB,QAAI,WAAW;AACf,aAAS,UAAU,KAAK,KAAK,KAAK,cAAc,CAAC,IAAI,GAAG,WAAW,GAAG,WAAW;AAC/E,UAAI,OAAO,OAAO,MAAM,GAAG;AAEzB,iBAAS,MAAM,GAAG,OAAO,GAAG,OAAO;AACjC,gBAAM,WAAW,UAAU,IAAI;AAC/B,cAAI,WAAW,KAAK,eAAgB,OAAO,OAAO,IAAK,KAAK,KAAO;AACjE,uBAAW;AACX;AAAA,UACF;AAAA,QACF;AACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,WAAW,KAAK,IAAI,WAAW,GAAG,mBAAmB;AAC3D,QAAI,YAAY,KAAK,YAAa;AAGlC,SAAK,OAAO,SAAS,KAAK,aAAa,WAAW,KAAK,SAAS;AAGhE,UAAM,gBAAgB,KAAK,KAAK,WAAW,CAAC;AAC5C,SAAK,SAAS,OAAO,MAAM,GAAG,aAAa;AAG3C,UAAM,UAAU,KAAK,cAAc;AACnC,SAAK,cAAc;AACnB,SAAK,cAAc;AACnB,SAAK,kBAAkB;AAGvB,SAAK,gBAAgB;AACrB,SAAK,gBAAgB,gBAAgB;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAqB;AAC3B,SAAK,UAAU,MAAM;AACrB,SAAK,WAAW,MAAM;AAGtB,UAAM,iBAAiB,KAAK,aAAa;AACzC,UAAM,WAAW,IAAI,WAAW,cAAc;AAC9C,SAAK,OAAO,KAAK,UAAU,EAAE,IAAI,KAAK,iBAAiB,CAAC;AACxD,UAAM,YAAY,IAAI,SAAS,SAAS,MAAM;AAG9C,UAAM,UAAU,KAAK,gBAAgB,IAAI,IAAI,WAAW,KAAK,aAAa,IAAI;AAC9E,QAAI,SAAS;AACX,WAAK,OAAO,KAAK,SAAS,EAAE,IAAI,KAAK,gBAAgB,CAAC;AAAA,IACxD;AAEA,aAAS,IAAI,GAAG,IAAI,KAAK,YAAY,KAAK;AACxC,YAAM,MAAM,IAAI;AAChB,YAAM,OAAO,UAAU,SAAS,MAAM,MAAM,IAAI;AAChD,UAAI,SAAS,WAAW,KAAM;AAE9B,YAAM,QAAe;AAAA,QACnB;AAAA,QACA,YAAY,UAAU,UAAU,MAAM,MAAM,aAAa,IAAI;AAAA,QAC7D,YAAY,UAAU,UAAU,MAAM,MAAM,aAAa,IAAI;AAAA,QAC7D,MAAM,UAAU,UAAU,MAAM,MAAM,MAAM,IAAI;AAAA,QAChD,MAAM,UAAU,WAAW,MAAM,MAAM,MAAM,IAAI;AAAA,QACjD,YAAY,UAAU,UAAU,MAAM,MAAM,aAAa,IAAI;AAAA,QAC7D,YAAY,UAAU,UAAU,MAAM,MAAM,aAAa,IAAI;AAAA,QAC7D,OAAO,UAAU,WAAW,MAAM,MAAM,OAAO,IAAI;AAAA,QACnD,OAAO,UAAU,WAAW,MAAM,MAAM,OAAO,IAAI;AAAA,QACnD,OAAO,UAAU,WAAW,MAAM,MAAM,OAAO,IAAI;AAAA,QACnD,KAAK,UAAU,UAAU,MAAM,MAAM,KAAK,IAAI;AAAA,QAC9C,KAAK,UAAU,UAAU,MAAM,MAAM,KAAK,IAAI;AAAA,MAChD;AACA,WAAK,WAAW,IAAI,GAAG,KAAK;AAG5B,YAAM,OAAO,UACT,QAAQ,OAAO,QAAQ,SAAS,MAAM,YAAY,MAAM,aAAa,MAAM,UAAU,CAAC,IACtF,KAAK,SAAS,MAAM,YAAY,MAAM,UAAU;AACpD,WAAK,UAAU,IAAI,MAAM,CAAC;AAAA,IAC5B;AAAA,EACF;AAAA;AAAA,EAIQ,UAAU,KAAoB;AACpC,UAAM,SAAS,KAAK,WAAW,IAAI,GAAG;AACtC,QAAI,OAAQ,QAAO;AAEnB,UAAM,SAAS,KAAK,mBAAmB,MAAM;AAC7C,SAAK,OAAO,KAAK,KAAK,UAAU,EAAE,IAAI,OAAO,CAAC;AAC9C,UAAM,IAAI,KAAK;AACf,UAAM,QAAe;AAAA,MACnB,MAAM,EAAE,SAAS,MAAM,IAAI;AAAA,MAC3B,YAAY,EAAE,UAAU,MAAM,aAAa,IAAI;AAAA,MAC/C,YAAY,EAAE,UAAU,MAAM,aAAa,IAAI;AAAA,MAC/C,MAAM,EAAE,UAAU,MAAM,MAAM,IAAI;AAAA,MAClC,MAAM,EAAE,WAAW,MAAM,MAAM,IAAI;AAAA,MACnC,YAAY,EAAE,UAAU,MAAM,aAAa,IAAI;AAAA,MAC/C,YAAY,EAAE,UAAU,MAAM,aAAa,IAAI;AAAA,MAC/C,OAAO,EAAE,WAAW,MAAM,OAAO,IAAI;AAAA,MACrC,OAAO,EAAE,WAAW,MAAM,OAAO,IAAI;AAAA,MACrC,OAAO,EAAE,WAAW,MAAM,OAAO,IAAI;AAAA,MACrC,KAAK,EAAE,UAAU,MAAM,KAAK,IAAI;AAAA,MAChC,KAAK,EAAE,UAAU,MAAM,KAAK,IAAI;AAAA,IAClC;AACA,SAAK,WAAW,IAAI,KAAK,KAAK;AAC9B,WAAO;AAAA,EACT;AAAA,EAEQ,WAAW,KAAa,OAAoB;AAElD,QAAI,MAAM,SAAS,WAAW,MAAM;AAClC,WAAK,WAAW,OAAO,GAAG;AAAA,IAC5B,OAAO;AACL,WAAK,WAAW,IAAI,KAAK,KAAK;AAAA,IAChC;AAEA,UAAM,IAAI,KAAK;AACf,MAAE,SAAS,MAAM,MAAM,MAAM,IAAI;AACjC,MAAE,SAAS,MAAM,OAAO,CAAC;AACzB,MAAE,SAAS,MAAM,QAAQ,GAAG,CAAC;AAC7B,MAAE,SAAS,MAAM,QAAQ,GAAG,CAAC;AAC7B,MAAE,UAAU,MAAM,aAAa,MAAM,YAAY,IAAI;AACrD,MAAE,UAAU,MAAM,aAAa,MAAM,YAAY,IAAI;AACrD,MAAE,UAAU,MAAM,aAAa,GAAG,IAAI;AACtC,MAAE,UAAU,MAAM,MAAM,MAAM,MAAM,IAAI;AACxC,MAAE,WAAW,MAAM,MAAM,MAAM,MAAM,IAAI;AACzC,MAAE,UAAU,MAAM,aAAa,MAAM,YAAY,IAAI;AACrD,MAAE,UAAU,MAAM,aAAa,MAAM,YAAY,IAAI;AACrD,MAAE,WAAW,MAAM,OAAO,MAAM,OAAO,IAAI;AAC3C,MAAE,WAAW,MAAM,OAAO,MAAM,OAAO,IAAI;AAC3C,MAAE,WAAW,MAAM,OAAO,MAAM,OAAO,IAAI;AAC3C,MAAE,UAAU,MAAM,KAAK,MAAM,KAAK,IAAI;AACtC,MAAE,UAAU,MAAM,KAAK,MAAM,KAAK,IAAI;AAEtC,UAAM,SAAS,KAAK,mBAAmB,MAAM;AAC7C,SAAK,OAAO,MAAM,KAAK,UAAU,EAAE,IAAI,OAAO,CAAC;AAAA,EACjD;AAAA;AAAA,EAIQ,SAAS,QAAgB,QAAwB;AACvD,UAAM,MAAM,IAAI,WAAW,MAAM;AACjC,SAAK,OAAO,KAAK,KAAK,EAAE,IAAI,KAAK,kBAAkB,OAAO,CAAC;AAC3D,WAAO,QAAQ,OAAO,GAAG;AAAA,EAC3B;AAAA,EAEQ,WAAW,MAAkD;AACnE,UAAM,QAAQ,QAAQ,OAAO,IAAI;AACjC,UAAM,SAAS,KAAK;AAGpB,QAAI,SAAS,MAAM,aAAa,KAAK,eAAe;AAClD,WAAK,cAAc,SAAS,MAAM,UAAU;AAAA,IAC9C;AAEA,SAAK,OAAO,MAAM,OAAO,EAAE,IAAI,KAAK,kBAAkB,OAAO,CAAC;AAC9D,SAAK,iBAAiB,MAAM;AAG5B,SAAK,kBAAkB;AAEvB,WAAO,EAAE,QAAQ,QAAQ,MAAM,WAAW;AAAA,EAC5C;AAAA,EAEQ,cAAc,QAAsB;AAE1C,UAAM,UAAU,KAAK,IAAI,KAAK,gBAAgB,GAAG,SAAS,uBAAuB;AACjF,UAAM,SAAS,UAAU,KAAK;AAM9B,UAAM,WAAW,KAAK,cAAc,KAAK;AACzC,UAAM,UAAU,IAAI,WAAW,QAAQ;AACvC,SAAK,OAAO,KAAK,SAAS,EAAE,IAAI,KAAK,WAAW,CAAC;AAGjD,UAAM,eAAe,KAAK,OAAO,QAAQ,IAAI;AAC7C,SAAK,OAAO,SAAS,YAAY;AAGjC,UAAM,kBAAkB,KAAK,eAAe;AAC5C,UAAM,gBAAgB,KAAK,aAAa;AACxC,SAAK,OAAO,MAAM,SAAS,EAAE,IAAI,cAAc,CAAC;AAChD,SAAK,OAAO,MAAM,KAAK,QAAS,EAAE,IAAI,gBAAgB,CAAC;AAGvD,SAAK,gBAAgB;AACrB,SAAK,eAAe;AACpB,SAAK,aAAa;AAGlB,SAAK,kBAAkB;AAAA,EACzB;AAAA;AAAA,EAIQ,eAAe,OAAuB;AAC5C,QAAI,UAAU,EAAG,QAAO;AAExB,UAAM,SAAS,KAAK;AACpB,QAAI,MAAM;AACV,QAAI,QAAQ;AAEZ,aAAS,IAAI,GAAG,IAAI,KAAK,aAAa,KAAK;AACzC,YAAM,UAAU,MAAM;AACtB,YAAM,SAAS,IAAI;AACnB,YAAM,OAAQ,OAAO,OAAO,MAAM,SAAU;AAE5C,UAAI,MAAM;AACR,cAAM;AACN,gBAAQ,IAAI;AAAA,MACd,OAAO;AACL;AACA,YAAI,QAAQ,OAAO;AAEjB,mBAAS,IAAI,OAAO,KAAK,GAAG,KAAK;AAC/B,kBAAM,KAAK,MAAM;AACjB,kBAAM,KAAK,IAAI;AACf,mBAAO,EAAE,KAAM,KAAK;AAAA,UACtB;AACA,eAAK,gBAAgB,UAAU,GAAG,MAAM,CAAC;AACzC,eAAK,cAAc;AACnB,eAAK,kBAAkB;AACvB,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAGA,WAAO,KAAK,gBAAgB,KAAK;AAAA,EACnC;AAAA,EAEQ,gBAAgB,OAAuB;AAC7C,UAAM,WAAW,KAAK;AAEtB,UAAM,WAAW,KAAK,IAAI,WAAW,GAAG,WAAW,KAAK;AACxD,UAAM,cAAc,WAAW;AAG/B,UAAM,cAAc,KAAK,aAAa,WAAW,KAAK;AACtD,SAAK,OAAO,SAAS,WAAW;AAGhC,UAAM,gBAAgB,KAAK,KAAK,WAAW,CAAC;AAC5C,UAAM,YAAY,IAAI,WAAW,aAAa;AAC9C,cAAU,IAAI,KAAK,MAAO;AAC1B,SAAK,SAAS;AAEd,SAAK,cAAc;AACnB,SAAK,cAAc;AAGnB,UAAM,QAAQ;AACd,aAAS,IAAI,OAAO,IAAI,QAAQ,OAAO,KAAK;AAC1C,YAAM,KAAK,MAAM;AACjB,YAAM,KAAK,IAAI;AACf,WAAK,OAAO,EAAE,KAAM,KAAK;AAAA,IAC3B;AAEA,SAAK,gBAAgB,UAAU,GAAI,QAAQ,QAAQ,MAAO,CAAC;AAC3D,SAAK,cAAc;AACnB,SAAK,kBAAkB;AAEvB,WAAO;AAAA,EACT;AAAA,EAEQ,uBAAuB;AAAA,EAEvB,eAAe,OAAe,OAAqB;AACzD,QAAI,UAAU,EAAG;AACjB,UAAM,SAAS,KAAK;AAEpB,aAAS,IAAI,OAAO,IAAI,QAAQ,OAAO,KAAK;AAC1C,YAAM,UAAU,MAAM;AACtB,YAAM,SAAS,IAAI;AACnB,aAAO,OAAO,KAAK,EAAE,KAAK;AAAA,IAC5B;AAEA,SAAK,gBAAgB,UAAU,GAAI,QAAQ,QAAQ,MAAO,CAAC;AAC3D,SAAK,cAAc;AACnB,SAAK,kBAAkB;AACvB,SAAK,uBAAuB;AAAA,EAC9B;AAAA;AAAA;AAAA,EAMQ,gBAAwB;AAE9B,aAAS,IAAI,KAAK,eAAe,IAAI,KAAK,YAAY,KAAK;AAEzD,UAAI,KAAK,WAAW,IAAI,CAAC,EAAG;AAE5B,YAAM,SAAS,KAAK,mBAAmB,IAAI;AAC3C,YAAM,UAAU,IAAI,WAAW,CAAC;AAChC,WAAK,OAAO,KAAK,SAAS,EAAE,IAAI,OAAO,CAAC;AACxC,UAAI,QAAQ,CAAC,MAAM,WAAW,MAAM;AAClC,aAAK,gBAAgB,IAAI;AACzB,eAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,MAAM,KAAK,eAAe;AAChC,SAAK,gBAAgB,MAAM;AAC3B,WAAO;AAAA,EACT;AAAA,EAEQ,iBAAyB;AAC/B,UAAM,WAAW,KAAK;AACtB,UAAM,WAAW,WAAW;AAC5B,UAAM,UAAU,WAAW,YAAY;AAGvC,UAAM,mBAAmB,KAAK,mBAAmB,WAAW;AAC5D,UAAM,YAAY,KAAK,OAAO,QAAQ,IAAI;AAC1C,UAAM,WAAW,IAAI,WAAW,SAAS;AACzC,SAAK,OAAO,KAAK,UAAU,EAAE,IAAI,iBAAiB,CAAC;AAGnD,SAAK,OAAO,SAAS,KAAK,OAAO,QAAQ,IAAI,MAAM;AAGnD,SAAK,OAAO,MAAM,UAAU,EAAE,IAAI,mBAAmB,OAAO,CAAC;AAG7D,UAAM,SAAS,IAAI,WAAW,MAAM;AACpC,SAAK,OAAO,MAAM,QAAQ,EAAE,IAAI,iBAAiB,CAAC;AAGlD,SAAK,mBAAmB;AACxB,SAAK,gBAAgB;AACrB,SAAK,cAAc;AACnB,SAAK,aAAa;AAElB,SAAK,kBAAkB;AAEvB,WAAO;AAAA,EACT;AAAA;AAAA,EAIQ,SAAS,YAAoB,YAAoB,MAA0B;AACjF,UAAM,MAAM,IAAI,WAAW,IAAI;AAC/B,UAAM,SAAS,KAAK,aAAa,aAAa,KAAK;AACnD,SAAK,OAAO,KAAK,KAAK,EAAE,IAAI,OAAO,CAAC;AACpC,WAAO;AAAA,EACT;AAAA,EAEQ,UAAU,YAAoB,MAAwB;AAC5D,UAAM,SAAS,KAAK,aAAa,aAAa,KAAK;AACnD,SAAK,OAAO,MAAM,MAAM,EAAE,IAAI,OAAO,CAAC;AAAA,EACxC;AAAA;AAAA,EAIQ,YAAY,MAAc,QAAgB,GAAuB;AACvE,QAAI,QAAQ,kBAAmB,QAAO;AAEtC,UAAM,MAAM,KAAK,UAAU,IAAI,IAAI;AACnC,QAAI,QAAQ,QAAW;AAErB,aAAO,KAAK,sBAAsB,MAAM,MAAM,KAAK;AAAA,IACrD;AAEA,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,QAAI,MAAM,SAAS,WAAW,SAAS;AAErC,YAAM,SAAS,QAAQ,OAAO,KAAK,SAAS,MAAM,YAAY,MAAM,YAAY,MAAM,IAAI,CAAC;AAC3F,YAAM,WAAW,OAAO,WAAW,GAAG,IAAI,SAAS,KAAK,gBAAgB,MAAM,MAAM;AACpF,aAAO,KAAK,YAAY,UAAU,QAAQ,CAAC;AAAA,IAC7C;AAEA,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,sBAAsB,MAAc,aAAsB,MAAM,QAAgB,GAAuB;AAC7G,QAAI,QAAQ,kBAAmB,QAAO;AAEtC,UAAM,QAAQ,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAC5C,QAAI,UAAU;AAEd,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,SAAS,MAAM,MAAM,SAAS;AACpC,gBAAU,YAAY,MAAM,MAAM,MAAM,CAAC,IAAI,UAAU,MAAM,MAAM,CAAC;AAEpE,YAAM,MAAM,KAAK,UAAU,IAAI,OAAO;AACtC,UAAI,QAAQ,OAAW,QAAO;AAE9B,YAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,UAAI,MAAM,SAAS,WAAW,YAAY,CAAC,UAAU,aAAa;AAChE,cAAM,SAAS,QAAQ,OAAO,KAAK,SAAS,MAAM,YAAY,MAAM,YAAY,MAAM,IAAI,CAAC;AAC3F,cAAM,WAAW,OAAO,WAAW,GAAG,IAAI,SAAS,KAAK,gBAAgB,SAAS,MAAM;AAEvF,YAAI,QAAQ;AAGV,iBAAO,KAAK,sBAAsB,UAAU,MAAM,QAAQ,CAAC;AAAA,QAC7D;AAGA,cAAM,YAAY,MAAM,MAAM,IAAI,CAAC,EAAE,KAAK,GAAG;AAC7C,cAAM,UAAU,YAAY,YAAY,MAAM,YAAY;AAC1D,eAAO,KAAK,sBAAsB,SAAS,YAAY,QAAQ,CAAC;AAAA,MAClE;AAAA,IACF;AAEA,WAAO,KAAK,UAAU,IAAI,OAAO;AAAA,EACnC;AAAA,EAEQ,gBAAgB,MAAc,QAAwB;AAC5D,UAAM,MAAM,KAAK,UAAU,GAAG,KAAK,YAAY,GAAG,CAAC,KAAK;AACxD,UAAM,SAAS,MAAM,MAAM,QAAQ,MAAM,GAAG,EAAE,OAAO,OAAO;AAC5D,UAAM,WAAqB,CAAC;AAC5B,eAAW,KAAK,OAAO;AACrB,UAAI,MAAM,IAAK;AACf,UAAI,MAAM,MAAM;AAAE,iBAAS,IAAI;AAAG;AAAA,MAAU;AAC5C,eAAS,KAAK,CAAC;AAAA,IACjB;AACA,WAAO,MAAM,SAAS,KAAK,GAAG;AAAA,EAChC;AAAA;AAAA,EAIQ,YAAY,MAAc,MAAc,MAAc,MAAc,MAA2B;AACrG,UAAM,MAAM,KAAK,cAAc;AAC/B,UAAM,EAAE,QAAQ,SAAS,QAAQ,QAAQ,IAAI,KAAK,WAAW,IAAI;AACjE,UAAM,MAAM,KAAK,IAAI;AAErB,QAAI,aAAa;AACjB,QAAI,aAAa;AAEjB,QAAI,QAAQ,KAAK,aAAa,GAAG;AAC/B,mBAAa,KAAK,KAAK,KAAK,aAAa,KAAK,SAAS;AACvD,mBAAa,KAAK,eAAe,UAAU;AAC3C,WAAK,UAAU,YAAY,IAAI;AAAA,IACjC;AAEA,UAAM,QAAe;AAAA,MACnB;AAAA,MACA,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,KAAK,KAAK;AAAA,MACV,KAAK,KAAK;AAAA,IACZ;AAEA,SAAK,WAAW,KAAK,KAAK;AAC1B,SAAK,UAAU,IAAI,MAAM,GAAG;AAE5B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA,EAKA,cAAc,GAAmB;AAC/B,QAAI,EAAE,WAAW,CAAC,MAAM,GAAI,KAAI,MAAM;AAEtC,QAAI,EAAE,WAAW,EAAG,QAAO;AAC3B,QAAI,EAAE,QAAQ,IAAI,MAAM,MAAM,EAAE,QAAQ,IAAI,MAAM,MAAM,EAAE,WAAW,EAAE,SAAS,CAAC,MAAM,IAAI;AACzF,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,EAAE,MAAM,GAAG,EAAE,OAAO,OAAO;AACzC,UAAM,WAAqB,CAAC;AAC5B,eAAW,QAAQ,OAAO;AACxB,UAAI,SAAS,IAAK;AAClB,UAAI,SAAS,MAAM;AAAE,iBAAS,IAAI;AAAG;AAAA,MAAU;AAC/C,eAAS,KAAK,IAAI;AAAA,IACpB;AACA,WAAO,MAAM,SAAS,KAAK,GAAG;AAAA,EAChC;AAAA;AAAA,EAGA,KAAK,MAA2D;AAC9D,UAAM,KAAK,KAAK,QAAQ,YAAY,IAAI,IAAI;AAC5C,WAAO,KAAK,cAAc,IAAI;AAG9B,QAAI,MAAM,KAAK,UAAU,IAAI,IAAI;AACjC,QAAI,QAAQ,QAAW;AACrB,YAAMA,SAAQ,KAAK,WAAW,IAAI,GAAG;AACrC,UAAIA,QAAO;AAET,YAAIA,OAAM,SAAS,WAAW,SAAS;AACrC,gBAAM,KAAK,sBAAsB,MAAM,IAAI;AAAA,QAC7C,WAAWA,OAAM,SAAS,WAAW,WAAW;AAC9C,iBAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAAA,QACrD,OAAO;AAEL,gBAAMC,QAAOD,OAAM,OAAO,IACtB,KAAK,SAASA,OAAM,YAAYA,OAAM,YAAYA,OAAM,IAAI,IAC5D,IAAI,WAAW,CAAC;AACpB,cAAI,KAAK,OAAO;AACd,kBAAM,KAAK,YAAY,IAAI;AAC3B,oBAAQ,IAAI,mBAAmB,IAAI,SAASA,OAAM,IAAI,WAAW,KAAG,IAAI,QAAQ,CAAC,CAAC,WAAW;AAAA,UAC/F;AACA,iBAAO,EAAE,QAAQ,GAAG,MAAAC,MAAK;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAGA,QAAI,QAAQ,OAAW,OAAM,KAAK,sBAAsB,MAAM,IAAI;AAClE,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAE1E,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,QAAI,MAAM,SAAS,WAAW,UAAW,QAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAE5F,UAAM,OAAO,MAAM,OAAO,IACtB,KAAK,SAAS,MAAM,YAAY,MAAM,YAAY,MAAM,IAAI,IAC5D,IAAI,WAAW,CAAC;AAEpB,QAAI,KAAK,OAAO;AACd,YAAM,KAAK,YAAY,IAAI;AAC3B,cAAQ,IAAI,mBAAmB,IAAI,SAAS,MAAM,IAAI,WAAW,KAAG,IAAI,QAAQ,CAAC,CAAC,gBAAgB;AAAA,IACpG;AAEA,WAAO,EAAE,QAAQ,GAAG,KAAK;AAAA,EAC3B;AAAA;AAAA,EAGA,MAAM,MAAc,MAAkB,QAAgB,GAAuB;AAC3E,UAAM,KAAK,KAAK,QAAQ,YAAY,IAAI,IAAI;AAC5C,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,KAAK,KAAK,QAAQ,YAAY,IAAI,IAAI;AAG5C,UAAM,eAAe,KAAK,aAAa,IAAI;AAC3C,QAAI,iBAAiB,EAAG,QAAO,EAAE,QAAQ,aAAa;AACtD,UAAM,KAAK,KAAK,QAAQ,YAAY,IAAI,IAAI;AAE5C,UAAM,cAAc,KAAK,sBAAsB,MAAM,IAAI;AACzD,UAAM,KAAK,KAAK,QAAQ,YAAY,IAAI,IAAI;AAE5C,QAAI,SAAS,IAAI,QAAQ,IAAI,SAAS;AAEtC,QAAI,gBAAgB,QAAW;AAE7B,YAAM,QAAQ,KAAK,UAAU,WAAW;AACxC,UAAI,MAAM,SAAS,WAAW,UAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAEhF,YAAM,eAAe,KAAK,KAAK,KAAK,aAAa,KAAK,SAAS;AAE/D,UAAI,gBAAgB,MAAM,YAAY;AAEpC,iBAAS,KAAK,QAAQ,YAAY,IAAI,IAAI;AAC1C,aAAK,UAAU,MAAM,YAAY,IAAI;AACrC,gBAAQ,KAAK,QAAQ,YAAY,IAAI,IAAI;AACzC,YAAI,eAAe,MAAM,YAAY;AACnC,eAAK,eAAe,MAAM,aAAa,cAAc,MAAM,aAAa,YAAY;AAAA,QACtF;AAAA,MACF,OAAO;AAEL,aAAK,eAAe,MAAM,YAAY,MAAM,UAAU;AACtD,cAAM,WAAW,KAAK,eAAe,YAAY;AACjD,iBAAS,KAAK,QAAQ,YAAY,IAAI,IAAI;AAC1C,aAAK,UAAU,UAAU,IAAI;AAC7B,gBAAQ,KAAK,QAAQ,YAAY,IAAI,IAAI;AACzC,cAAM,aAAa;AAAA,MACrB;AAEA,YAAM,OAAO,KAAK;AAClB,YAAM,aAAa;AACnB,YAAM,QAAQ,KAAK,IAAI;AACvB,WAAK,WAAW,aAAa,KAAK;AAClC,eAAS,KAAK,QAAQ,YAAY,IAAI,IAAI;AAAA,IAC5C,OAAO;AAEL,YAAM,OAAO,oBAAoB,EAAE,KAAK,QAAQ;AAChD,WAAK,YAAY,MAAM,WAAW,MAAM,MAAM,KAAK,YAAY,IAAI;AACnE,eAAS,KAAK,QAAQ,YAAY,IAAI,IAAI;AAC1C,cAAQ;AACR,eAAS;AAAA,IACX;AAEA,QAAI,QAAQ,GAAG;AACb,WAAK,cAAc;AACnB,WAAK,OAAO,MAAM;AAAA,IACpB;AACA,UAAM,SAAS,KAAK,QAAQ,YAAY,IAAI,IAAI;AAEhD,QAAI,KAAK,OAAO;AACd,YAAM,WAAW,gBAAgB;AACjC,cAAQ,IAAI,oBAAoB,IAAI,SAAS,KAAK,UAAU,IAAI,WAAW,WAAW,QAAQ,eAAe,KAAG,IAAI,QAAQ,CAAC,CAAC,cAAc,KAAG,IAAI,QAAQ,CAAC,CAAC,eAAe,KAAG,IAAI,QAAQ,CAAC,CAAC,aAAa,SAAO,IAAI,QAAQ,CAAC,CAAC,YAAY,QAAM,QAAQ,QAAQ,CAAC,CAAC,aAAa,SAAO,OAAO,QAAQ,CAAC,CAAC,aAAa,SAAO,QAAQ,QAAQ,CAAC,CAAC,aAAa,SAAO,IAAI,QAAQ,CAAC,CAAC,IAAI;AAAA,IACtX;AAEA,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,OAAO,MAAc,MAAsC;AACzD,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,cAAc,KAAK,sBAAsB,MAAM,IAAI;AAEzD,QAAI,gBAAgB,QAAW;AAE7B,aAAO,KAAK,MAAM,MAAM,IAAI;AAAA,IAC9B;AAEA,UAAM,QAAQ,KAAK,UAAU,WAAW;AACxC,QAAI,MAAM,SAAS,WAAW,UAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAGhF,UAAM,WAAW,MAAM,OAAO,IAC1B,KAAK,SAAS,MAAM,YAAY,MAAM,YAAY,MAAM,IAAI,IAC5D,IAAI,WAAW,CAAC;AAGpB,UAAM,WAAW,IAAI,WAAW,SAAS,aAAa,KAAK,UAAU;AACrE,aAAS,IAAI,QAAQ;AACrB,aAAS,IAAI,MAAM,SAAS,UAAU;AAGtC,UAAM,eAAe,KAAK,KAAK,SAAS,aAAa,KAAK,SAAS;AACnE,SAAK,eAAe,MAAM,YAAY,MAAM,UAAU;AACtD,UAAM,WAAW,KAAK,eAAe,YAAY;AACjD,SAAK,UAAU,UAAU,QAAQ;AAEjC,UAAM,aAAa;AACnB,UAAM,aAAa;AACnB,UAAM,OAAO,SAAS;AACtB,UAAM,QAAQ,KAAK,IAAI;AACvB,SAAK,WAAW,aAAa,KAAK;AAElC,SAAK,cAAc;AACnB,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,OAAO,MAAkC;AACvC,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,UAAU,IAAI,IAAI;AACnC,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAE9D,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,QAAI,MAAM,SAAS,WAAW,UAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAGhF,SAAK,eAAe,MAAM,YAAY,MAAM,UAAU;AAGtD,UAAM,OAAO,WAAW;AACxB,SAAK,WAAW,KAAK,KAAK;AAG1B,SAAK,UAAU,OAAO,IAAI;AAE1B,QAAI,MAAM,KAAK,cAAe,MAAK,gBAAgB;AAEnD,SAAK,cAAc;AACnB,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,KAAK,MAA2D;AAC9D,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,sBAAsB,MAAM,IAAI;AACjD,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAE1E,WAAO,KAAK,mBAAmB,GAAG;AAAA,EACpC;AAAA;AAAA,EAGA,MAAM,MAA2D;AAC/D,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,UAAU,IAAI,IAAI;AACnC,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAE1E,WAAO,KAAK,mBAAmB,GAAG;AAAA,EACpC;AAAA,EAEQ,mBAAmB,KAAmD;AAC5E,UAAM,QAAQ,KAAK,UAAU,GAAG;AAEhC,UAAM,MAAM,IAAI,WAAW,EAAE;AAC7B,UAAM,OAAO,IAAI,SAAS,IAAI,MAAM;AACpC,SAAK,SAAS,GAAG,MAAM,IAAI;AAC3B,SAAK,UAAU,GAAG,MAAM,MAAM,IAAI;AAClC,SAAK,WAAW,GAAG,MAAM,MAAM,IAAI;AACnC,SAAK,WAAW,IAAI,MAAM,OAAO,IAAI;AACrC,SAAK,WAAW,IAAI,MAAM,OAAO,IAAI;AACrC,SAAK,WAAW,IAAI,MAAM,OAAO,IAAI;AACrC,SAAK,UAAU,IAAI,MAAM,KAAK,IAAI;AAClC,SAAK,UAAU,IAAI,MAAM,KAAK,IAAI;AAClC,SAAK,UAAU,IAAI,KAAK,IAAI;AAE5B,WAAO,EAAE,QAAQ,GAAG,MAAM,IAAI;AAAA,EAChC;AAAA;AAAA,EAGA,MAAM,MAAc,QAAgB,GAAgD;AAClF,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,aAAa,QAAQ,OAAO;AAElC,QAAI,WAAW;AACb,aAAO,KAAK,eAAe,IAAI;AAAA,IACjC;AAGA,QAAI,KAAK,UAAU,IAAI,IAAI,EAAG,QAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAGjF,UAAM,eAAe,KAAK,aAAa,IAAI;AAC3C,QAAI,iBAAiB,EAAG,QAAO,EAAE,QAAQ,cAAc,MAAM,KAAK;AAElE,UAAM,OAAO,mBAAmB,EAAE,KAAK,QAAQ;AAC/C,SAAK,YAAY,MAAM,WAAW,WAAW,MAAM,CAAC;AAEpD,SAAK,cAAc;AAEnB,UAAM,YAAY,QAAQ,OAAO,IAAI;AACrC,WAAO,EAAE,QAAQ,GAAG,MAAM,UAAU;AAAA,EACtC;AAAA,EAEQ,eAAe,MAA2D;AAChF,UAAM,QAAQ,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAC5C,QAAI,UAAU;AACd,QAAI,eAA8B;AAElC,eAAW,QAAQ,OAAO;AACxB,iBAAW,MAAM;AAEjB,UAAI,KAAK,UAAU,IAAI,OAAO,GAAG;AAC/B,cAAM,MAAM,KAAK,UAAU,IAAI,OAAO;AACtC,cAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,YAAI,MAAM,SAAS,WAAW,WAAW;AACvC,iBAAO,EAAE,QAAQ,eAAe,SAAS,MAAM,KAAK;AAAA,QACtD;AACA;AAAA,MACF;AAEA,YAAM,OAAO,mBAAmB,EAAE,KAAK,QAAQ;AAC/C,WAAK,YAAY,SAAS,WAAW,WAAW,MAAM,CAAC;AACvD,UAAI,CAAC,aAAc,gBAAe;AAAA,IACpC;AAEA,SAAK,cAAc;AACnB,UAAM,SAAS,eAAe,QAAQ,OAAO,YAAY,IAAI;AAC7D,WAAO,EAAE,QAAQ,GAAG,MAAM,UAAU,KAAK;AAAA,EAC3C;AAAA;AAAA,EAGA,MAAM,MAAc,QAAgB,GAAuB;AACzD,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,aAAa,QAAQ,OAAO;AAClC,UAAM,MAAM,KAAK,UAAU,IAAI,IAAI;AACnC,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAE9D,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,QAAI,MAAM,SAAS,WAAW,UAAW,QAAO,EAAE,QAAQ,eAAe,QAAQ;AAGjF,UAAM,WAAW,KAAK,kBAAkB,IAAI;AAE5C,QAAI,SAAS,SAAS,GAAG;AACvB,UAAI,CAAC,UAAW,QAAO,EAAE,QAAQ,eAAe,UAAU;AAG1D,iBAAW,SAAS,KAAK,kBAAkB,IAAI,GAAG;AAChD,cAAM,WAAW,KAAK,UAAU,IAAI,KAAK;AACzC,cAAM,aAAa,KAAK,UAAU,QAAQ;AAC1C,aAAK,eAAe,WAAW,YAAY,WAAW,UAAU;AAChE,mBAAW,OAAO,WAAW;AAC7B,aAAK,WAAW,UAAU,UAAU;AACpC,aAAK,UAAU,OAAO,KAAK;AAAA,MAC7B;AAAA,IACF;AAGA,UAAM,OAAO,WAAW;AACxB,SAAK,WAAW,KAAK,KAAK;AAC1B,SAAK,UAAU,OAAO,IAAI;AAC1B,QAAI,MAAM,KAAK,cAAe,MAAK,gBAAgB;AAEnD,SAAK,cAAc;AACnB,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,QAAQ,MAAc,QAAgB,GAAgD;AACpF,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,sBAAsB,MAAM,IAAI;AACjD,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAE1E,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,QAAI,MAAM,SAAS,WAAW,UAAW,QAAO,EAAE,QAAQ,eAAe,SAAS,MAAM,KAAK;AAE7F,UAAM,iBAAiB,QAAQ,OAAO;AACtC,UAAM,WAAW,KAAK,kBAAkB,IAAI;AAE5C,QAAI,eAAe;AAEjB,UAAIC,aAAY;AAChB,YAAM,UAAgD,CAAC;AAEvD,iBAAW,aAAa,UAAU;AAChC,cAAM,OAAO,UAAU,UAAU,UAAU,YAAY,GAAG,IAAI,CAAC;AAC/D,cAAM,YAAY,QAAQ,OAAO,IAAI;AACrC,cAAM,WAAW,KAAK,UAAU,IAAI,SAAS;AAC7C,cAAM,aAAa,KAAK,UAAU,QAAQ;AAC1C,gBAAQ,KAAK,EAAE,MAAM,WAAW,MAAM,WAAW,KAAK,CAAC;AACvD,QAAAA,cAAa,IAAI,UAAU,aAAa;AAAA,MAC1C;AAEA,YAAMC,OAAM,IAAI,WAAWD,UAAS;AACpC,YAAME,QAAO,IAAI,SAASD,KAAI,MAAM;AACpC,MAAAC,MAAK,UAAU,GAAG,QAAQ,QAAQ,IAAI;AACtC,UAAIC,UAAS;AAEb,iBAAW,SAAS,SAAS;AAC3B,QAAAD,MAAK,UAAUC,SAAQ,MAAM,KAAK,YAAY,IAAI;AAClD,QAAAA,WAAU;AACV,QAAAF,KAAI,IAAI,MAAM,MAAME,OAAM;AAC1B,QAAAA,WAAU,MAAM,KAAK;AACrB,QAAAF,KAAIE,SAAQ,IAAI,MAAM;AAAA,MACxB;AAEA,aAAO,EAAE,QAAQ,GAAG,MAAMF,KAAI;AAAA,IAChC;AAGA,QAAI,YAAY;AAChB,UAAM,cAA4B,CAAC;AAEnC,eAAW,aAAa,UAAU;AAChC,YAAM,OAAO,UAAU,UAAU,UAAU,YAAY,GAAG,IAAI,CAAC;AAC/D,YAAM,YAAY,QAAQ,OAAO,IAAI;AACrC,kBAAY,KAAK,SAAS;AAC1B,mBAAa,IAAI,UAAU;AAAA,IAC7B;AAEA,UAAM,MAAM,IAAI,WAAW,SAAS;AACpC,UAAM,OAAO,IAAI,SAAS,IAAI,MAAM;AACpC,SAAK,UAAU,GAAG,YAAY,QAAQ,IAAI;AAC1C,QAAI,SAAS;AAEb,eAAW,aAAa,aAAa;AACnC,WAAK,UAAU,QAAQ,UAAU,YAAY,IAAI;AACjD,gBAAU;AACV,UAAI,IAAI,WAAW,MAAM;AACzB,gBAAU,UAAU;AAAA,IACtB;AAEA,WAAO,EAAE,QAAQ,GAAG,MAAM,IAAI;AAAA,EAChC;AAAA;AAAA,EAGA,OAAO,SAAiB,SAAqC;AAC3D,cAAU,KAAK,cAAc,OAAO;AACpC,cAAU,KAAK,cAAc,OAAO;AAEpC,UAAM,MAAM,KAAK,UAAU,IAAI,OAAO;AACtC,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAG9D,UAAM,eAAe,KAAK,aAAa,OAAO;AAC9C,QAAI,iBAAiB,EAAG,QAAO,EAAE,QAAQ,aAAa;AAGtD,UAAM,cAAc,KAAK,UAAU,IAAI,OAAO;AAC9C,QAAI,gBAAgB,QAAW;AAC7B,YAAM,gBAAgB,KAAK,UAAU,WAAW;AAChD,WAAK,eAAe,cAAc,YAAY,cAAc,UAAU;AACtE,oBAAc,OAAO,WAAW;AAChC,WAAK,WAAW,aAAa,aAAa;AAC1C,WAAK,UAAU,OAAO,OAAO;AAAA,IAC/B;AAGA,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,UAAM,EAAE,QAAQ,SAAS,QAAQ,QAAQ,IAAI,KAAK,WAAW,OAAO;AACpE,UAAM,aAAa;AACnB,UAAM,aAAa;AACnB,UAAM,QAAQ,KAAK,IAAI;AACvB,SAAK,WAAW,KAAK,KAAK;AAG1B,SAAK,UAAU,OAAO,OAAO;AAC7B,SAAK,UAAU,IAAI,SAAS,GAAG;AAG/B,QAAI,MAAM,SAAS,WAAW,WAAW;AACvC,YAAM,SAAS,YAAY,MAAM,MAAM,UAAU;AACjD,YAAM,WAA+B,CAAC;AAEtC,iBAAW,CAAC,GAAG,CAAC,KAAK,KAAK,WAAW;AACnC,YAAI,EAAE,WAAW,MAAM,GAAG;AACxB,mBAAS,KAAK,CAAC,GAAG,CAAC,CAAC;AAAA,QACtB;AAAA,MACF;AAEA,iBAAW,CAAC,GAAG,CAAC,KAAK,UAAU;AAC7B,cAAM,SAAS,EAAE,UAAU,QAAQ,MAAM;AACzC,cAAM,eAAe,UAAU;AAC/B,cAAM,aAAa,KAAK,UAAU,CAAC;AACnC,cAAM,EAAE,QAAQ,KAAK,QAAQ,IAAI,IAAI,KAAK,WAAW,YAAY;AACjE,mBAAW,aAAa;AACxB,mBAAW,aAAa;AACxB,aAAK,WAAW,GAAG,UAAU;AAC7B,aAAK,UAAU,OAAO,CAAC;AACvB,aAAK,UAAU,IAAI,cAAc,CAAC;AAAA,MACpC;AAAA,IACF;AAEA,SAAK,cAAc;AACnB,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,OAAO,MAA2D;AAChE,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,sBAAsB,MAAM,IAAI;AACjD,UAAM,MAAM,IAAI,WAAW,CAAC;AAC5B,QAAI,CAAC,IAAI,QAAQ,SAAY,IAAI;AACjC,WAAO,EAAE,QAAQ,GAAG,MAAM,IAAI;AAAA,EAChC;AAAA;AAAA,EAGA,SAAS,MAAc,MAAc,GAAuB;AAC1D,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,sBAAsB,MAAM,IAAI;AACjD,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAE9D,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,QAAI,MAAM,SAAS,WAAW,UAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAEhF,QAAI,QAAQ,GAAG;AAEb,WAAK,eAAe,MAAM,YAAY,MAAM,UAAU;AACtD,YAAM,aAAa;AACnB,YAAM,aAAa;AACnB,YAAM,OAAO;AAAA,IACf,WAAW,MAAM,MAAM,MAAM;AAE3B,YAAM,eAAe,KAAK,KAAK,MAAM,KAAK,SAAS;AACnD,UAAI,eAAe,MAAM,YAAY;AACnC,aAAK,eAAe,MAAM,aAAa,cAAc,MAAM,aAAa,YAAY;AAAA,MACtF;AACA,YAAM,aAAa;AACnB,YAAM,OAAO;AAAA,IACf,WAAW,MAAM,MAAM,MAAM;AAE3B,YAAM,eAAe,KAAK,KAAK,MAAM,KAAK,SAAS;AACnD,UAAI,eAAe,MAAM,YAAY;AAEnC,cAAM,UAAU,KAAK,SAAS,MAAM,YAAY,MAAM,YAAY,MAAM,IAAI;AAC5E,aAAK,eAAe,MAAM,YAAY,MAAM,UAAU;AACtD,cAAM,WAAW,KAAK,eAAe,YAAY;AACjD,cAAM,UAAU,IAAI,WAAW,GAAG;AAClC,gBAAQ,IAAI,OAAO;AAEnB,aAAK,UAAU,UAAU,OAAO;AAChC,cAAM,aAAa;AAAA,MACrB;AACA,YAAM,aAAa;AACnB,YAAM,OAAO;AAAA,IACf;AAEA,UAAM,QAAQ,KAAK,IAAI;AACvB,SAAK,WAAW,KAAK,KAAK;AAE1B,SAAK,cAAc;AACnB,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,KAAK,SAAiB,UAAkB,QAAgB,GAAuB;AAC7E,cAAU,KAAK,cAAc,OAAO;AACpC,eAAW,KAAK,cAAc,QAAQ;AAEtC,UAAM,SAAS,KAAK,sBAAsB,SAAS,IAAI;AACvD,QAAI,WAAW,OAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAEjE,UAAM,WAAW,KAAK,UAAU,MAAM;AACtC,QAAI,SAAS,SAAS,WAAW,UAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAGnF,QAAK,QAAQ,KAAM,KAAK,UAAU,IAAI,QAAQ,GAAG;AAC/C,aAAO,EAAE,QAAQ,eAAe,OAAO;AAAA,IACzC;AAGA,UAAM,OAAO,SAAS,OAAO,IACzB,KAAK,SAAS,SAAS,YAAY,SAAS,YAAY,SAAS,IAAI,IACrE,IAAI,WAAW,CAAC;AAEpB,WAAO,KAAK,MAAM,UAAU,IAAI;AAAA,EAClC;AAAA;AAAA,EAGA,OAAO,MAAc,OAAe,GAAuB;AACzD,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,sBAAsB,MAAM,IAAI;AACjD,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAE9D,QAAI,SAAS,EAAG,QAAO,EAAE,QAAQ,EAAE;AAEnC,QAAI,CAAC,KAAK,kBAAmB,QAAO,EAAE,QAAQ,EAAE;AAEhD,UAAM,QAAQ,KAAK,UAAU,GAAG;AAEhC,UAAM,WAAW,KAAK,uBAAuB,KAAK;AAElD,QAAK,OAAO,KAAM,EAAE,WAAW,GAAI,QAAO,EAAE,QAAQ,eAAe,OAAO;AAC1E,QAAK,OAAO,KAAM,EAAE,WAAW,GAAI,QAAO,EAAE,QAAQ,eAAe,OAAO;AAC1E,QAAK,OAAO,KAAM,EAAE,WAAW,GAAI,QAAO,EAAE,QAAQ,eAAe,OAAO;AAE1E,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA,EAEQ,uBAAuB,OAAsB;AACnD,UAAM,WAAW,MAAM,OAAO;AAC9B,QAAI,KAAK,eAAe,MAAM,IAAK,QAAQ,aAAa,IAAK;AAC7D,QAAI,KAAK,eAAe,MAAM,IAAK,QAAQ,aAAa,IAAK;AAC7D,WAAO,WAAW;AAAA,EACpB;AAAA;AAAA,EAGA,SAAS,MAA2D;AAClE,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,sBAAsB,MAAM,IAAI;AACjD,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAG1E,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,UAAM,eAAe,KAAK,SAAS,MAAM,YAAY,MAAM,UAAU;AACrE,WAAO,EAAE,QAAQ,GAAG,MAAM,QAAQ,OAAO,YAAY,EAAE;AAAA,EACzD;AAAA;AAAA,EAGA,MAAM,MAAc,MAAkC;AACpD,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,sBAAsB,MAAM,IAAI;AACjD,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAE9D,UAAM,QAAQ,KAAK,UAAU,GAAG;AAEhC,UAAM,OAAQ,MAAM,OAAO,SAAW,OAAO;AAC7C,UAAM,QAAQ,KAAK,IAAI;AACvB,SAAK,WAAW,KAAK,KAAK;AAE1B,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,MAAM,MAAc,KAAa,KAAiC;AAChE,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,sBAAsB,MAAM,IAAI;AACjD,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAE9D,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,UAAM,MAAM;AACZ,UAAM,MAAM;AACZ,UAAM,QAAQ,KAAK,IAAI;AACvB,SAAK,WAAW,KAAK,KAAK;AAE1B,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,OAAO,MAAc,OAAe,OAAmC;AACrE,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,sBAAsB,MAAM,IAAI;AACjD,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAE9D,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,UAAM,QAAQ;AACd,UAAM,QAAQ;AACd,UAAM,QAAQ,KAAK,IAAI;AACvB,SAAK,WAAW,KAAK,KAAK;AAE1B,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,QAAQ,QAAgB,UAAsC;AAC5D,eAAW,KAAK,cAAc,QAAQ;AACtC,QAAI,KAAK,UAAU,IAAI,QAAQ,EAAG,QAAO,EAAE,QAAQ,eAAe,OAAO;AAEzE,UAAM,eAAe,KAAK,aAAa,QAAQ;AAC/C,QAAI,iBAAiB,EAAG,QAAO,EAAE,QAAQ,aAAa;AAEtD,UAAM,cAAc,QAAQ,OAAO,MAAM;AACzC,SAAK,YAAY,UAAU,WAAW,SAAS,sBAAsB,YAAY,YAAY,WAAW;AAExG,SAAK,cAAc;AACnB,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,SAAS,MAA2D;AAClE,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,UAAU,IAAI,IAAI;AACnC,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAE1E,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,QAAI,MAAM,SAAS,WAAW,QAAS,QAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAE1F,UAAM,SAAS,KAAK,SAAS,MAAM,YAAY,MAAM,YAAY,MAAM,IAAI;AAC3E,WAAO,EAAE,QAAQ,GAAG,MAAM,OAAO;AAAA,EACnC;AAAA;AAAA,EAGA,KAAK,cAAsB,SAAqC;AAC9D,WAAO,KAAK,KAAK,cAAc,OAAO;AAAA,EACxC;AAAA;AAAA,EAGA,KAAK,MAAc,OAAe,OAA4D;AAC5F,WAAO,KAAK,cAAc,IAAI;AAE9B,UAAM,aAAa,QAAQ,QAAQ;AACnC,UAAM,YAAY,QAAQ,SAAS;AACnC,UAAM,WAAW,QAAQ,SAAS;AAElC,QAAI,MAAM,KAAK,sBAAsB,MAAM,IAAI;AAE/C,QAAI,QAAQ,QAAW;AACrB,UAAI,CAAC,UAAW,QAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAEnE,YAAM,OAAO,oBAAoB,EAAE,KAAK,QAAQ;AAChD,YAAM,KAAK,YAAY,MAAM,WAAW,MAAM,MAAM,CAAC;AAAA,IACvD,WAAW,WAAW,WAAW;AAC/B,aAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAAA,IACrD;AAEA,QAAI,UAAU;AACZ,WAAK,SAAS,MAAM,CAAC;AAAA,IACvB;AAEA,UAAM,KAAK,KAAK;AAChB,SAAK,QAAQ,IAAI,IAAI,EAAE,OAAO,UAAU,KAAK,UAAU,GAAG,MAAM,CAAC;AAEjE,UAAM,MAAM,IAAI,WAAW,CAAC;AAC5B,QAAI,SAAS,IAAI,MAAM,EAAE,UAAU,GAAG,IAAI,IAAI;AAC9C,WAAO,EAAE,QAAQ,GAAG,MAAM,IAAI;AAAA,EAChC;AAAA;AAAA,EAGA,MAAM,IAAgC;AACpC,QAAI,CAAC,KAAK,QAAQ,IAAI,EAAE,EAAG,QAAO,EAAE,QAAQ,eAAe,MAAM;AACjE,SAAK,QAAQ,OAAO,EAAE;AACtB,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,MAAM,IAAY,QAAgB,UAAsE;AACtG,UAAM,QAAQ,KAAK,QAAQ,IAAI,EAAE;AACjC,QAAI,CAAC,MAAO,QAAO,EAAE,QAAQ,eAAe,OAAO,MAAM,KAAK;AAE9D,UAAM,QAAQ,KAAK,UAAU,MAAM,QAAQ;AAC3C,UAAM,MAAM,YAAY,MAAM;AAC9B,UAAM,UAAU,KAAK,IAAI,QAAQ,MAAM,OAAO,GAAG;AAEjD,QAAI,WAAW,EAAG,QAAO,EAAE,QAAQ,GAAG,MAAM,IAAI,WAAW,CAAC,EAAE;AAG9D,UAAM,aAAa,KAAK,aAAa,MAAM,aAAa,KAAK,YAAY;AACzE,UAAM,MAAM,IAAI,WAAW,OAAO;AAClC,SAAK,OAAO,KAAK,KAAK,EAAE,IAAI,WAAW,CAAC;AAGxC,QAAI,aAAa,MAAM;AACrB,YAAM,YAAY;AAAA,IACpB;AAEA,WAAO,EAAE,QAAQ,GAAG,MAAM,IAAI;AAAA,EAChC;AAAA;AAAA,EAGA,OAAO,IAAY,MAAkB,UAAsE;AACzG,UAAM,QAAQ,KAAK,QAAQ,IAAI,EAAE;AACjC,QAAI,CAAC,MAAO,QAAO,EAAE,QAAQ,eAAe,OAAO,MAAM,KAAK;AAE9D,UAAM,QAAQ,KAAK,UAAU,MAAM,QAAQ;AAC3C,UAAM,YAAY,MAAM,QAAQ,UAAU;AAC1C,UAAM,MAAM,WAAW,MAAM,OAAQ,YAAY,MAAM;AACvD,UAAM,SAAS,MAAM,KAAK;AAG1B,QAAI,SAAS,MAAM,MAAM;AACvB,YAAM,eAAe,KAAK,KAAK,SAAS,KAAK,SAAS;AACtD,UAAI,eAAe,MAAM,YAAY;AAEnC,cAAM,UAAU,MAAM,OAAO,IACzB,KAAK,SAAS,MAAM,YAAY,MAAM,YAAY,MAAM,IAAI,IAC5D,IAAI,WAAW,CAAC;AACpB,aAAK,eAAe,MAAM,YAAY,MAAM,UAAU;AACtD,cAAM,WAAW,KAAK,eAAe,YAAY;AACjD,cAAM,SAAS,IAAI,WAAW,MAAM;AACpC,eAAO,IAAI,OAAO;AAClB,eAAO,IAAI,MAAM,GAAG;AACpB,aAAK,UAAU,UAAU,MAAM;AAC/B,cAAM,aAAa;AACnB,cAAM,aAAa;AAAA,MACrB,OAAO;AAEL,cAAM,aAAa,KAAK,aAAa,MAAM,aAAa,KAAK,YAAY;AACzE,aAAK,OAAO,MAAM,MAAM,EAAE,IAAI,WAAW,CAAC;AAAA,MAC5C;AACA,YAAM,OAAO;AAAA,IACf,OAAO;AAEL,YAAM,aAAa,KAAK,aAAa,MAAM,aAAa,KAAK,YAAY;AACzE,WAAK,OAAO,MAAM,MAAM,EAAE,IAAI,WAAW,CAAC;AAAA,IAC5C;AAEA,UAAM,QAAQ,KAAK,IAAI;AACvB,SAAK,WAAW,MAAM,UAAU,KAAK;AAGrC,QAAI,aAAa,MAAM;AACrB,YAAM,WAAW;AAAA,IACnB;AAEA,SAAK,cAAc;AACnB,UAAM,MAAM,IAAI,WAAW,CAAC;AAC5B,QAAI,SAAS,IAAI,MAAM,EAAE,UAAU,GAAG,KAAK,YAAY,IAAI;AAC3D,WAAO,EAAE,QAAQ,GAAG,MAAM,IAAI;AAAA,EAChC;AAAA;AAAA,EAGA,MAAM,IAAyD;AAC7D,UAAM,QAAQ,KAAK,QAAQ,IAAI,EAAE;AACjC,QAAI,CAAC,MAAO,QAAO,EAAE,QAAQ,eAAe,OAAO,MAAM,KAAK;AAC9D,WAAO,KAAK,mBAAmB,MAAM,QAAQ;AAAA,EAC/C;AAAA;AAAA,EAGA,UAAU,IAAY,MAAc,GAAuB;AACzD,UAAM,QAAQ,KAAK,QAAQ,IAAI,EAAE;AACjC,QAAI,CAAC,MAAO,QAAO,EAAE,QAAQ,eAAe,MAAM;AAElD,UAAM,QAAQ,KAAK,UAAU,MAAM,QAAQ;AAC3C,UAAM,OAAO,KAAK,SAAS,MAAM,YAAY,MAAM,UAAU;AAC7D,WAAO,KAAK,SAAS,MAAM,GAAG;AAAA,EAChC;AAAA;AAAA,EAGA,QAA4B;AAC1B,SAAK,cAAc;AACnB,SAAK,OAAO,MAAM;AAClB,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,QAAQ,MAAc,OAA4D;AAChF,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,sBAAsB,MAAM,IAAI;AACjD,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAE1E,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,QAAI,MAAM,SAAS,WAAW,UAAW,QAAO,EAAE,QAAQ,eAAe,SAAS,MAAM,KAAK;AAG7F,UAAM,KAAK,KAAK;AAChB,SAAK,QAAQ,IAAI,IAAI,EAAE,OAAO,UAAU,KAAK,UAAU,GAAG,OAAO,EAAE,CAAC;AAEpE,UAAM,MAAM,IAAI,WAAW,CAAC;AAC5B,QAAI,SAAS,IAAI,MAAM,EAAE,UAAU,GAAG,IAAI,IAAI;AAC9C,WAAO,EAAE,QAAQ,GAAG,MAAM,IAAI;AAAA,EAChC;AAAA;AAAA,EAGA,QAAQ,QAA6D;AACnE,UAAM,SAAS,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,CAAC;AACxD,UAAM,OAAO,KAAK,cAAc,SAAS,MAAM;AAG/C,UAAM,eAAe,KAAK,aAAa,IAAI;AAC3C,QAAI,iBAAiB,GAAG;AAEtB,YAAM,aAAa,KAAK,UAAU,GAAG,KAAK,YAAY,GAAG,CAAC;AAC1D,UAAI,YAAY;AACd,aAAK,eAAe,UAAU;AAAA,MAChC;AAAA,IACF;AAEA,UAAM,OAAO,mBAAmB,EAAE,KAAK,QAAQ;AAC/C,SAAK,YAAY,MAAM,WAAW,WAAW,MAAM,CAAC;AAEpD,SAAK,cAAc;AACnB,WAAO,EAAE,QAAQ,GAAG,MAAM,QAAQ,OAAO,IAAI,EAAE;AAAA,EACjD;AAAA;AAAA,EAIQ,kBAAkB,SAA2B;AACnD,UAAM,SAAS,YAAY,MAAM,MAAM,UAAU;AACjD,UAAM,WAAqB,CAAC;AAE5B,eAAW,QAAQ,KAAK,UAAU,KAAK,GAAG;AACxC,UAAI,SAAS,QAAS;AACtB,UAAI,CAAC,KAAK,WAAW,MAAM,EAAG;AAE9B,YAAM,OAAO,KAAK,UAAU,OAAO,MAAM;AACzC,UAAI,CAAC,KAAK,SAAS,GAAG,GAAG;AACvB,iBAAS,KAAK,IAAI;AAAA,MACpB;AAAA,IACF;AAEA,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA,EAEQ,kBAAkB,SAA2B;AACnD,UAAM,SAAS,YAAY,MAAM,MAAM,UAAU;AACjD,UAAM,cAAwB,CAAC;AAE/B,eAAW,QAAQ,KAAK,UAAU,KAAK,GAAG;AACxC,UAAI,KAAK,WAAW,MAAM,EAAG,aAAY,KAAK,IAAI;AAAA,IACpD;AAGA,WAAO,YAAY,KAAK,CAAC,GAAG,MAAM;AAChC,YAAM,KAAK,EAAE,MAAM,GAAG,EAAE;AACxB,YAAM,KAAK,EAAE,MAAM,GAAG,EAAE;AACxB,aAAO,KAAK;AAAA,IACd,CAAC;AAAA,EACH;AAAA,EAEQ,aAAa,MAAsB;AACzC,UAAM,YAAY,KAAK,YAAY,GAAG;AACtC,QAAI,aAAa,EAAG,QAAO;AAE3B,UAAM,aAAa,KAAK,UAAU,GAAG,SAAS;AAC9C,UAAM,YAAY,KAAK,UAAU,IAAI,UAAU;AAC/C,QAAI,cAAc,OAAW,QAAO,eAAe;AAEnD,UAAM,cAAc,KAAK,UAAU,SAAS;AAC5C,QAAI,YAAY,SAAS,WAAW,UAAW,QAAO,eAAe;AAErE,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,WAAW,OAAqB;AAC9B,eAAW,CAAC,IAAI,KAAK,KAAK,KAAK,SAAS;AACtC,UAAI,MAAM,UAAU,OAAO;AACzB,aAAK,QAAQ,OAAO,EAAE;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,cAA+C;AAC7C,UAAM,QAAyC,CAAC;AAChD,eAAW,CAAC,MAAM,GAAG,KAAK,KAAK,WAAW;AACxC,YAAM,KAAK,EAAE,MAAM,IAAI,CAAC;AAAA,IAC1B;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,aAAa,IAA2B;AACtC,UAAM,QAAQ,KAAK,QAAQ,IAAI,EAAE;AACjC,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,QAAQ,KAAK,UAAU,MAAM,QAAQ;AAC3C,WAAO,KAAK,SAAS,MAAM,YAAY,MAAM,UAAU;AAAA,EACzD;AAAA;AAAA,EAGA,aAAa,KAAgE;AAC3E,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,UAAM,OAAO,MAAM,OAAO,IACtB,KAAK,SAAS,MAAM,YAAY,MAAM,YAAY,MAAM,IAAI,IAC5D,IAAI,WAAW,CAAC;AACpB,WAAO,EAAE,MAAM,MAAM,MAAM,MAAM,OAAO,MAAM,MAAM;AAAA,EACtD;AAAA;AAAA,EAGA,YAAyG;AACvG,UAAM,SAAsG,CAAC;AAC7G,eAAW,CAAC,MAAM,GAAG,KAAK,KAAK,WAAW;AACxC,YAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,UAAI,OAA0B;AAC9B,UAAI,MAAM,SAAS,WAAW,QAAQ,MAAM,SAAS,WAAW,SAAS;AACvE,eAAO,MAAM,OAAO,IAChB,KAAK,SAAS,MAAM,YAAY,MAAM,YAAY,MAAM,IAAI,IAC5D,IAAI,WAAW,CAAC;AAAA,MACtB;AACA,aAAO,KAAK,EAAE,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,OAAO,MAAM,MAAM,CAAC;AAAA,IACpF;AAEA,WAAO,KAAK,CAAC,GAAG,MAAM;AACpB,UAAI,EAAE,SAAS,WAAW,aAAa,EAAE,SAAS,WAAW,UAAW,QAAO;AAC/E,UAAI,EAAE,SAAS,WAAW,aAAa,EAAE,SAAS,WAAW,UAAW,QAAO;AAC/E,aAAO,EAAE,KAAK,cAAc,EAAE,IAAI;AAAA,IACpC,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAEA,QAAc;AACZ,SAAK,OAAO,MAAM;AAAA,EACpB;AACF;;;AC3pDO,IAAM,KAAK;AAAA,EAChB,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,UAAU;AAAA,EACV,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,WAAW;AAAA,EACX,OAAO;AAAA,EACP,SAAS;AAAA,EACT,SAAS;AACX;AAwCA,IAAMG,WAAU,IAAI,YAAY;AAChC,IAAMC,WAAU,IAAI,YAAY;AA0CzB,SAAS,cAAc,KAK5B;AACA,QAAM,OAAO,IAAI,SAAS,GAAG;AAC7B,QAAM,KAAK,KAAK,UAAU,GAAG,IAAI;AACjC,QAAM,QAAQ,KAAK,UAAU,GAAG,IAAI;AACpC,QAAM,UAAU,KAAK,UAAU,GAAG,IAAI;AACtC,QAAM,UAAU,KAAK,UAAU,IAAI,IAAI;AAEvC,QAAM,QAAQ,IAAI,WAAW,GAAG;AAChC,QAAM,OAAOC,SAAQ,OAAO,MAAM,SAAS,IAAI,KAAK,OAAO,CAAC;AAC5D,QAAM,OAAO,UAAU,IACnB,MAAM,SAAS,KAAK,SAAS,KAAK,UAAU,OAAO,IACnD;AAEJ,SAAO,EAAE,IAAI,OAAO,MAAM,KAAK;AACjC;AAUO,SAAS,eAAe,QAAgB,MAAgC;AAC7E,QAAM,UAAU,OAAO,KAAK,aAAa;AACzC,QAAM,MAAM,IAAI,YAAY,IAAI,OAAO;AACvC,QAAM,OAAO,IAAI,SAAS,GAAG;AAE7B,OAAK,UAAU,GAAG,QAAQ,IAAI;AAC9B,OAAK,UAAU,GAAG,SAAS,IAAI;AAE/B,MAAI,MAAM;AACR,QAAI,WAAW,GAAG,EAAE,IAAI,MAAM,CAAC;AAAA,EACjC;AAEA,SAAO;AACT;AA0CO,SAAS,iBAAiB,MAA0B;AACzD,QAAM,OAAO,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU;AACvE,QAAM,UAAU,KAAK,UAAU,GAAG,IAAI;AACtC,SAAOC,SAAQ,OAAO,KAAK,SAAS,GAAG,IAAI,OAAO,CAAC;AACrD;;;AC7LA,IAAM,SAAS,IAAI,UAAU;AAG7B,IAAM,QAAQ,oBAAI,IAAyB;AAG3C,IAAI,eAAmC;AAGvC,IAAI,SAOA;AAAA,EACF,MAAM;AAAA,EACN,UAAU;AAAA,EACV,KAAK;AAAA,EACL,KAAK;AAAA,EACL,OAAO;AAAA,EACP,mBAAmB;AACrB;AAKA,SAAS,cAAc,OAAe,QAAkC;AACtE,QAAM,EAAE,IAAI,OAAO,MAAM,KAAK,IAAI,cAAc,MAAM;AAEtD,MAAI;AAEJ,UAAQ,IAAI;AAAA,IACV,KAAK,GAAG;AACN,eAAS,OAAO,KAAK,IAAI;AACzB;AAAA,IAEF,KAAK,GAAG;AACN,eAAS,OAAO,MAAM,MAAM,QAAQ,IAAI,WAAW,CAAC,GAAG,KAAK;AAC5D,qBAAe,SAAS,MAAM,IAAI;AAClC;AAAA,IAEF,KAAK,GAAG;AACN,eAAS,OAAO,OAAO,MAAM,QAAQ,IAAI,WAAW,CAAC,CAAC;AACtD,qBAAe,SAAS,MAAM,IAAI;AAClC;AAAA,IAEF,KAAK,GAAG;AACN,eAAS,OAAO,OAAO,IAAI;AAC3B,qBAAe,UAAU,IAAI;AAC7B;AAAA,IAEF,KAAK,GAAG;AACN,eAAS,OAAO,KAAK,IAAI;AACzB;AAAA,IAEF,KAAK,GAAG;AACN,eAAS,OAAO,MAAM,IAAI;AAC1B;AAAA,IAEF,KAAK,GAAG;AACN,eAAS,OAAO,MAAM,MAAM,KAAK;AACjC,qBAAe,SAAS,IAAI;AAC5B;AAAA,IAEF,KAAK,GAAG;AACN,eAAS,OAAO,MAAM,MAAM,KAAK;AACjC,qBAAe,UAAU,IAAI;AAC7B;AAAA,IAEF,KAAK,GAAG;AACN,eAAS,OAAO,QAAQ,MAAM,KAAK;AACnC;AAAA,IAEF,KAAK,GAAG,QAAQ;AACd,YAAM,UAAU,OAAO,iBAAiB,IAAI,IAAI;AAChD,eAAS,OAAO,OAAO,MAAM,OAAO;AACpC,qBAAe,UAAU,MAAM,QAAW,OAAO;AACjD;AAAA,IACF;AAAA,IAEA,KAAK,GAAG;AACN,eAAS,OAAO,OAAO,IAAI;AAC3B;AAAA,IAEF,KAAK,GAAG,UAAU;AAChB,YAAM,MAAM,OAAO,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU,EAAE,UAAU,GAAG,IAAI,IAAI;AACpG,eAAS,OAAO,SAAS,MAAM,GAAG;AAClC;AAAA,IACF;AAAA,IAEA,KAAK,GAAG,MAAM;AACZ,YAAM,WAAW,OAAO,iBAAiB,IAAI,IAAI;AACjD,eAAS,OAAO,KAAK,MAAM,UAAU,KAAK;AAC1C;AAAA,IACF;AAAA,IAEA,KAAK,GAAG;AACN,eAAS,OAAO,OAAO,MAAM,KAAK;AAClC;AAAA,IAEF,KAAK,GAAG;AACN,eAAS,OAAO,SAAS,IAAI;AAC7B;AAAA,IAEF,KAAK,GAAG,OAAO;AACb,YAAM,OAAO,OAAO,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU,EAAE,UAAU,GAAG,IAAI,IAAI;AACrG,eAAS,OAAO,MAAM,MAAM,IAAI;AAChC;AAAA,IACF;AAAA,IAEA,KAAK,GAAG,OAAO;AACb,UAAI,CAAC,QAAQ,KAAK,aAAa,GAAG;AAChC,iBAAS,EAAE,QAAQ,EAAE;AACrB;AAAA,MACF;AACA,YAAM,KAAK,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU;AACrE,YAAM,MAAM,GAAG,UAAU,GAAG,IAAI;AAChC,YAAM,MAAM,GAAG,UAAU,GAAG,IAAI;AAChC,eAAS,OAAO,MAAM,MAAM,KAAK,GAAG;AACpC;AAAA,IACF;AAAA,IAEA,KAAK,GAAG,QAAQ;AACd,UAAI,CAAC,QAAQ,KAAK,aAAa,IAAI;AACjC,iBAAS,EAAE,QAAQ,EAAE;AACrB;AAAA,MACF;AACA,YAAM,KAAK,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU;AACrE,YAAM,QAAQ,GAAG,WAAW,GAAG,IAAI;AACnC,YAAM,QAAQ,GAAG,WAAW,GAAG,IAAI;AACnC,eAAS,OAAO,OAAO,MAAM,OAAO,KAAK;AACzC;AAAA,IACF;AAAA,IAEA,KAAK,GAAG,SAAS;AACf,YAAM,SAAS,OAAO,IAAI,YAAY,EAAE,OAAO,IAAI,IAAI;AACvD,eAAS,OAAO,QAAQ,QAAQ,IAAI;AACpC;AAAA,IACF;AAAA,IAEA,KAAK,GAAG;AACN,eAAS,OAAO,SAAS,IAAI;AAC7B;AAAA,IAEF,KAAK,GAAG,MAAM;AACZ,YAAM,UAAU,OAAO,iBAAiB,IAAI,IAAI;AAChD,eAAS,OAAO,KAAK,MAAM,OAAO;AAClC;AAAA,IACF;AAAA,IAEA,KAAK,GAAG,MAAM;AACZ,eAAS,OAAO,KAAK,MAAM,OAAO,KAAK;AACvC;AAAA,IACF;AAAA,IAEA,KAAK,GAAG,OAAO;AACb,YAAM,KAAK,OAAO,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU,EAAE,UAAU,GAAG,IAAI,IAAI;AACnG,eAAS,OAAO,MAAM,EAAE;AACxB;AAAA,IACF;AAAA,IAEA,KAAK,GAAG,OAAO;AACb,UAAI,CAAC,QAAQ,KAAK,aAAa,IAAI;AACjC,iBAAS,EAAE,QAAQ,EAAE;AACrB;AAAA,MACF;AACA,YAAM,KAAK,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU;AACrE,YAAM,KAAK,GAAG,UAAU,GAAG,IAAI;AAC/B,YAAM,SAAS,GAAG,UAAU,GAAG,IAAI;AACnC,YAAM,MAAM,GAAG,SAAS,GAAG,IAAI;AAC/B,eAAS,OAAO,MAAM,IAAI,QAAQ,QAAQ,KAAK,OAAO,GAAG;AACzD;AAAA,IACF;AAAA,IAEA,KAAK,GAAG,QAAQ;AACd,UAAI,CAAC,QAAQ,KAAK,aAAa,GAAG;AAChC,iBAAS,EAAE,QAAQ,EAAE;AACrB;AAAA,MACF;AACA,YAAM,KAAK,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU;AACrE,YAAM,KAAK,GAAG,UAAU,GAAG,IAAI;AAC/B,YAAM,MAAM,GAAG,SAAS,GAAG,IAAI;AAC/B,YAAM,YAAY,KAAK,SAAS,CAAC;AACjC,eAAS,OAAO,OAAO,IAAI,WAAW,QAAQ,KAAK,OAAO,GAAG;AAC7D;AAAA,IACF;AAAA,IAEA,KAAK,GAAG,OAAO;AACb,YAAM,KAAK,OAAO,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU,EAAE,UAAU,GAAG,IAAI,IAAI;AACnG,eAAS,OAAO,MAAM,EAAE;AACxB;AAAA,IACF;AAAA,IAEA,KAAK,GAAG,WAAW;AACjB,UAAI,CAAC,QAAQ,KAAK,aAAa,GAAG;AAChC,iBAAS,EAAE,QAAQ,EAAE;AACrB;AAAA,MACF;AACA,YAAM,KAAK,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU;AACrE,YAAM,KAAK,GAAG,UAAU,GAAG,IAAI;AAC/B,YAAM,MAAM,GAAG,UAAU,GAAG,IAAI;AAChC,eAAS,OAAO,UAAU,IAAI,GAAG;AACjC;AAAA,IACF;AAAA,IAEA,KAAK,GAAG;AACN,eAAS,OAAO,MAAM;AACtB;AAAA,IAEF,KAAK,GAAG;AACN,eAAS,OAAO,QAAQ,MAAM,KAAK;AACnC;AAAA,IAEF,KAAK,GAAG;AACN,eAAS,OAAO,QAAQ,IAAI;AAC5B;AAAA,IAEF;AACE,eAAS,EAAE,QAAQ,EAAE;AAAA,EACzB;AAEA,QAAM,eAAe,OAAO,gBAAgB,aAAa,OAAO,OAAO;AACvE,SAAO,eAAe,OAAO,QAAQ,YAAY;AACnD;AAGA,SAAS,eACP,IACA,MACA,MACA,SACM;AACN,MAAI,CAAC,aAAc;AAEnB,QAAM,MAA+B,EAAE,IAAI,MAAM,IAAI,KAAK,IAAI,EAAE;AAChE,QAAM,YAA2B,CAAC;AAElC,MAAI,OAAO,WAAW,MAAM;AAE1B,UAAM,OAAO,KAAK,MAAM,EAAE;AAC1B,QAAI,OAAO;AACX,cAAU,KAAK,IAAI;AAAA,EACrB;AAEA,MAAI,OAAO,YAAY,SAAS;AAC9B,QAAI,UAAU;AAAA,EAChB;AAEA,eAAa,YAAY,KAAK,SAAS;AACzC;AAGA,SAAS,gBAAgB,OAAe,MAAyB;AAC/D,QAAM,IAAI,OAAO,IAAI;AAErB,OAAK,YAAY,CAAC,MAAoB;AACpC,UAAM,EAAE,QAAQ,GAAG,IAAI,EAAE;AAEzB,QAAI,kBAAkB,aAAa;AACjC,YAAM,WAAW,cAAc,OAAO,MAAM;AAC5C,WAAK,YAAY,EAAE,IAAI,QAAQ,SAAS,GAAG,CAAC,QAAQ,CAAC;AAAA,IACvD;AAAA,EACF;AAEA,OAAK,MAAM;AACb;AAGA,SAAS,UAAU,OAAqB;AACtC,SAAO,WAAW,KAAK;AACvB,QAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,MAAI,MAAM;AACR,SAAK,MAAM;AACX,UAAM,OAAO,KAAK;AAAA,EACpB;AACF;AAIA,eAAe,KAAK,UAOF;AAChB,WAAS;AAGT,MAAI,UAAU,MAAM,UAAU,QAAQ,aAAa;AAGnD,MAAI,OAAO,QAAQ,OAAO,SAAS,KAAK;AACtC,UAAM,WAAW,OAAO,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AACtD,eAAW,WAAW,UAAU;AAC9B,gBAAU,MAAM,QAAQ,mBAAmB,SAAS,EAAE,QAAQ,KAAK,CAAC;AAAA,IACtE;AAAA,EACF;AAGA,QAAM,gBAAgB,MAAM,QAAQ,cAAc,YAAY,EAAE,QAAQ,KAAK,CAAC;AAC9E,QAAM,YAAY,MAAM,cAAc,uBAAuB;AAG7D,SAAO,KAAK,WAAW;AAAA,IACrB,KAAK,OAAO;AAAA,IACZ,KAAK,OAAO;AAAA,IACZ,OAAO,OAAO;AAAA,IACd,mBAAmB,OAAO;AAAA,EAC5B,CAAC;AACH;AAIA,KAAK,YAAY,OAAO,MAAoB;AAC1C,QAAM,MAAM,EAAE;AAEd,MAAI,IAAI,SAAS,QAAQ;AACvB,UAAM,KAAK,IAAI,MAAM;AACrB,IAAC,KAA2B,YAAY,EAAE,MAAM,QAAQ,CAAC;AACzD;AAAA,EACF;AAEA,MAAI,IAAI,SAAS,QAAQ;AAEvB,oBAAgB,IAAI,OAAO,IAAI,IAAI;AACnC;AAAA,EACF;AAEA,MAAI,IAAI,SAAS,YAAY;AAC3B,cAAU,IAAI,KAAK;AACnB;AAAA,EACF;AAEA,MAAI,IAAI,SAAS,kBAAkB;AACjC,mBAAe,IAAI;AACnB,iBAAc,MAAM;AACpB;AAAA,EACF;AAGA,MAAI,IAAI,kBAAkB,aAAa;AACrC,UAAM,QAAQ,IAAI,SAAS;AAC3B,UAAM,WAAW,cAAc,OAAO,IAAI,MAAM;AAChD,IAAC,KAA2B;AAAA,MAC1B,EAAE,IAAI,IAAI,IAAI,QAAQ,SAAS;AAAA,MAC/B,CAAC,QAAQ;AAAA,IACX;AAAA,EACF;AACF;","names":["inode","data","totalSize","buf","view","offset","encoder","decoder","decoder","decoder"]}
1
+ {"version":3,"sources":["../../src/src/vfs/layout.ts","../../src/src/errors.ts","../../src/src/vfs/engine.ts","../../src/src/protocol/opcodes.ts","../../src/src/workers/server.worker.ts"],"sourcesContent":["/**\n * VFS Binary Layout Constants\n *\n * Defines the on-disk structure of the virtual filesystem binary file.\n * All reads/writes go through a FileSystemSyncAccessHandle.\n */\n\n// Magic number: \"VFS!\" in ASCII\nexport const VFS_MAGIC = 0x56465321;\nexport const VFS_VERSION = 1;\n\n// Default sizes\nexport const DEFAULT_BLOCK_SIZE = 4096;\nexport const DEFAULT_INODE_COUNT = 10000;\nexport const INODE_SIZE = 64; // bytes per inode entry\n\n// Superblock layout (64 bytes)\nexport const SUPERBLOCK = {\n SIZE: 64,\n MAGIC: 0, // uint32 - 0x56465321\n VERSION: 4, // uint32\n INODE_COUNT: 8, // uint32 - total inodes allocated\n BLOCK_SIZE: 12, // uint32 - data block size (default 4096)\n TOTAL_BLOCKS: 16, // uint32 - total data blocks\n FREE_BLOCKS: 20, // uint32 - available data blocks\n INODE_OFFSET: 24, // float64 - byte offset to inode table\n PATH_OFFSET: 32, // float64 - byte offset to path table\n DATA_OFFSET: 40, // float64 - byte offset to data region\n BITMAP_OFFSET: 48, // float64 - byte offset to free block bitmap\n PATH_USED: 56, // uint32 - bytes used in path table\n RESERVED: 60, // uint32\n} as const;\n\n// Inode entry layout (64 bytes each)\nexport const INODE = {\n TYPE: 0, // uint8 - 0=free, 1=file, 2=directory, 3=symlink\n FLAGS: 1, // uint8[3] - reserved\n PATH_OFFSET: 4, // uint32 - byte offset into path table\n PATH_LENGTH: 8, // uint16 - length of path string\n RESERVED_10: 10, // uint16\n MODE: 12, // uint32 - permissions (e.g. 0o100644)\n SIZE: 16, // float64 - file content size in bytes (using f64 for >4GB)\n FIRST_BLOCK: 24, // uint32 - index of first data block\n BLOCK_COUNT: 28, // uint32 - number of contiguous data blocks\n MTIME: 32, // float64 - last modification time (ms since epoch)\n CTIME: 40, // float64 - creation/change time (ms since epoch)\n ATIME: 48, // float64 - last access time (ms since epoch)\n UID: 56, // uint32 - owner\n GID: 60, // uint32 - group\n} as const;\n\n// Inode type constants\nexport const INODE_TYPE = {\n FREE: 0,\n FILE: 1,\n DIRECTORY: 2,\n SYMLINK: 3,\n} as const;\n\n// Default file modes\nexport const DEFAULT_FILE_MODE = 0o100644;\nexport const DEFAULT_DIR_MODE = 0o040755;\nexport const DEFAULT_SYMLINK_MODE = 0o120777;\nexport const DEFAULT_UMASK = 0o022;\n\n// POSIX file type bits\nexport const S_IFMT = 0o170000;\nexport const S_IFREG = 0o100000;\nexport const S_IFDIR = 0o040000;\nexport const S_IFLNK = 0o120000;\n\n// Max symlink depth for cycle detection\nexport const MAX_SYMLINK_DEPTH = 40;\n\n// Path table compaction threshold (25% dead space)\nexport const PATH_COMPACTION_THRESHOLD = 0.25;\n\n// Initial path table size (256KB)\nexport const INITIAL_PATH_TABLE_SIZE = 256 * 1024;\n\n// Initial data blocks (1024 blocks = 4MB with 4KB blocks)\nexport const INITIAL_DATA_BLOCKS = 1024;\n\n/**\n * Calculate section offsets for a fresh VFS.\n */\nexport function calculateLayout(inodeCount: number = DEFAULT_INODE_COUNT, blockSize: number = DEFAULT_BLOCK_SIZE, totalBlocks: number = INITIAL_DATA_BLOCKS) {\n const inodeTableOffset = SUPERBLOCK.SIZE;\n const inodeTableSize = inodeCount * INODE_SIZE;\n const pathTableOffset = inodeTableOffset + inodeTableSize;\n const pathTableSize = INITIAL_PATH_TABLE_SIZE;\n const bitmapOffset = pathTableOffset + pathTableSize;\n const bitmapSize = Math.ceil(totalBlocks / 8);\n // Align data region to block boundary\n const dataOffset = Math.ceil((bitmapOffset + bitmapSize) / blockSize) * blockSize;\n const totalSize = dataOffset + totalBlocks * blockSize;\n\n return {\n inodeTableOffset,\n inodeTableSize,\n pathTableOffset,\n pathTableSize,\n bitmapOffset,\n bitmapSize,\n dataOffset,\n totalSize,\n totalBlocks,\n };\n}\n","/**\n * Node.js compatible filesystem error classes\n */\n\nexport class FSError extends Error {\n code: string;\n errno: number;\n syscall?: string;\n path?: string;\n\n constructor(code: string, errno: number, message: string, syscall?: string, path?: string) {\n super(message);\n this.name = 'FSError';\n this.code = code;\n this.errno = errno;\n this.syscall = syscall;\n this.path = path;\n }\n}\n\nexport const ErrorCodes = {\n ENOENT: -2,\n EEXIST: -17,\n EISDIR: -21,\n ENOTDIR: -20,\n ENOTEMPTY: -39,\n EACCES: -13,\n EBADF: -9,\n EINVAL: -22,\n EMFILE: -24,\n ENOSPC: -28,\n EPERM: -1,\n ENOSYS: -38,\n ELOOP: -40,\n} as const;\n\n/** Binary protocol status codes → error code mapping */\nexport const STATUS_TO_CODE: Record<number, string> = {\n 0: 'OK',\n 1: 'ENOENT',\n 2: 'EEXIST',\n 3: 'EISDIR',\n 4: 'ENOTDIR',\n 5: 'ENOTEMPTY',\n 6: 'EACCES',\n 7: 'EINVAL',\n 8: 'EBADF',\n 9: 'ELOOP',\n 10: 'ENOSPC',\n};\n\n/** Error code → binary protocol status mapping */\nexport const CODE_TO_STATUS: Record<string, number> = {\n OK: 0,\n ENOENT: 1,\n EEXIST: 2,\n EISDIR: 3,\n ENOTDIR: 4,\n ENOTEMPTY: 5,\n EACCES: 6,\n EINVAL: 7,\n EBADF: 8,\n ELOOP: 9,\n ENOSPC: 10,\n};\n\nexport function createError(code: string, syscall: string, path: string): FSError {\n const errno = ErrorCodes[code as keyof typeof ErrorCodes] ?? -1;\n const messages: Record<string, string> = {\n ENOENT: 'no such file or directory',\n EEXIST: 'file already exists',\n EISDIR: 'illegal operation on a directory',\n ENOTDIR: 'not a directory',\n ENOTEMPTY: 'directory not empty',\n EACCES: 'permission denied',\n EINVAL: 'invalid argument',\n EBADF: 'bad file descriptor',\n ELOOP: 'too many symbolic links encountered',\n ENOSPC: 'no space left on device',\n };\n const msg = messages[code] ?? 'unknown error';\n return new FSError(code, errno, `${code}: ${msg}, ${syscall} '${path}'`, syscall, path);\n}\n\nexport function statusToError(status: number, syscall: string, path: string): FSError {\n const code = STATUS_TO_CODE[status] ?? 'EINVAL';\n return createError(code, syscall, path);\n}\n","/**\n * VFS Engine — operates on a FileSystemSyncAccessHandle\n *\n * Manages the binary VFS layout: superblock, inode table, path table,\n * free block bitmap, and data region. All operations are synchronous\n * and run inside the server worker.\n */\n\nimport {\n VFS_MAGIC, VFS_VERSION, SUPERBLOCK, INODE, INODE_SIZE, INODE_TYPE,\n DEFAULT_BLOCK_SIZE, DEFAULT_INODE_COUNT, DEFAULT_FILE_MODE, DEFAULT_DIR_MODE,\n DEFAULT_SYMLINK_MODE, DEFAULT_UMASK, S_IFMT, S_IFREG, S_IFDIR, S_IFLNK,\n MAX_SYMLINK_DEPTH, INITIAL_DATA_BLOCKS, INITIAL_PATH_TABLE_SIZE,\n calculateLayout,\n} from './layout.js';\nimport { CODE_TO_STATUS } from '../errors.js';\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\n\ninterface Inode {\n type: number;\n pathOffset: number;\n pathLength: number;\n mode: number;\n size: number;\n firstBlock: number;\n blockCount: number;\n mtime: number;\n ctime: number;\n atime: number;\n uid: number;\n gid: number;\n}\n\ninterface FdEntry {\n tabId: string;\n inodeIdx: number;\n position: number;\n flags: number;\n}\n\nexport class VFSEngine {\n private handle!: FileSystemSyncAccessHandle;\n private pathIndex = new Map<string, number>(); // path → inode index\n private inodeCount = 0;\n private blockSize = DEFAULT_BLOCK_SIZE;\n private totalBlocks = 0;\n private freeBlocks = 0;\n private inodeTableOffset = 0;\n private pathTableOffset = 0;\n private pathTableUsed = 0;\n private pathTableSize = 0;\n private bitmapOffset = 0;\n private dataOffset = 0;\n private umask = DEFAULT_UMASK;\n private processUid = 0;\n private processGid = 0;\n private strictPermissions = false;\n private debug = false;\n\n // File descriptor table\n private fdTable = new Map<number, FdEntry>();\n private nextFd = 3; // 0=stdin, 1=stdout, 2=stderr reserved\n\n // Reusable buffers to avoid allocations\n private inodeBuf = new Uint8Array(INODE_SIZE);\n private inodeView = new DataView(this.inodeBuf.buffer);\n\n // In-memory inode cache — eliminates disk reads for hot inodes\n private inodeCache = new Map<number, Inode>();\n private superblockBuf = new Uint8Array(SUPERBLOCK.SIZE);\n private superblockView = new DataView(this.superblockBuf.buffer);\n\n // In-memory bitmap cache — eliminates bitmap reads from OPFS\n private bitmap: Uint8Array | null = null;\n private bitmapDirtyLo = Infinity; // lowest dirty byte index\n private bitmapDirtyHi = -1; // highest dirty byte index (inclusive)\n private superblockDirty = false;\n\n // Free inode hint — skip O(n) scan\n private freeInodeHint = 0;\n\n init(\n handle: FileSystemSyncAccessHandle,\n opts?: { uid?: number; gid?: number; umask?: number; strictPermissions?: boolean; debug?: boolean }\n ): void {\n this.handle = handle;\n this.processUid = opts?.uid ?? 0;\n this.processGid = opts?.gid ?? 0;\n this.umask = opts?.umask ?? DEFAULT_UMASK;\n this.strictPermissions = opts?.strictPermissions ?? false;\n this.debug = opts?.debug ?? false;\n\n const size = handle.getSize();\n\n if (size === 0) {\n this.format();\n } else {\n this.mount();\n }\n }\n\n /** Release the sync access handle (call on fatal error or shutdown) */\n closeHandle(): void {\n try {\n this.handle?.close();\n } catch (_) {\n // Ignore — handle may already be closed\n }\n }\n\n /** Format a fresh VFS */\n private format(): void {\n const layout = calculateLayout(DEFAULT_INODE_COUNT, DEFAULT_BLOCK_SIZE, INITIAL_DATA_BLOCKS);\n\n this.inodeCount = DEFAULT_INODE_COUNT;\n this.blockSize = DEFAULT_BLOCK_SIZE;\n this.totalBlocks = layout.totalBlocks;\n this.freeBlocks = layout.totalBlocks;\n this.inodeTableOffset = layout.inodeTableOffset;\n this.pathTableOffset = layout.pathTableOffset;\n this.pathTableSize = layout.pathTableSize;\n this.pathTableUsed = 0;\n this.bitmapOffset = layout.bitmapOffset;\n this.dataOffset = layout.dataOffset;\n\n // Grow file to total size\n this.handle.truncate(layout.totalSize);\n\n // Write superblock\n this.writeSuperblock();\n\n // Zero out inode table (type=0 means free)\n const zeroBuf = new Uint8Array(layout.inodeTableSize);\n this.handle.write(zeroBuf, { at: this.inodeTableOffset });\n\n // Zero out bitmap and cache in memory\n this.bitmap = new Uint8Array(layout.bitmapSize);\n this.handle.write(this.bitmap, { at: this.bitmapOffset });\n\n // Create root directory inode\n this.createInode('/', INODE_TYPE.DIRECTORY, DEFAULT_DIR_MODE, 0);\n\n // Re-write superblock with updated pathTableUsed (createInode appended \"/\" to path table)\n this.writeSuperblock();\n this.handle.flush();\n }\n\n /** Mount an existing VFS from disk — validates superblock integrity */\n private mount(): void {\n const fileSize = this.handle.getSize();\n if (fileSize < SUPERBLOCK.SIZE) {\n throw new Error(`Corrupt VFS: file too small (${fileSize} bytes, need at least ${SUPERBLOCK.SIZE})`);\n }\n\n this.handle.read(this.superblockBuf, { at: 0 });\n const v = this.superblockView;\n\n // Validate magic\n const magic = v.getUint32(SUPERBLOCK.MAGIC, true);\n if (magic !== VFS_MAGIC) {\n throw new Error(`Corrupt VFS: bad magic 0x${magic.toString(16)} (expected 0x${VFS_MAGIC.toString(16)})`);\n }\n\n // Validate version\n const version = v.getUint32(SUPERBLOCK.VERSION, true);\n if (version !== VFS_VERSION) {\n throw new Error(`Corrupt VFS: unsupported version ${version} (expected ${VFS_VERSION})`);\n }\n\n // Read superblock fields\n const inodeCount = v.getUint32(SUPERBLOCK.INODE_COUNT, true);\n const blockSize = v.getUint32(SUPERBLOCK.BLOCK_SIZE, true);\n const totalBlocks = v.getUint32(SUPERBLOCK.TOTAL_BLOCKS, true);\n const freeBlocks = v.getUint32(SUPERBLOCK.FREE_BLOCKS, true);\n const inodeTableOffset = v.getFloat64(SUPERBLOCK.INODE_OFFSET, true);\n const pathTableOffset = v.getFloat64(SUPERBLOCK.PATH_OFFSET, true);\n const dataOffset = v.getFloat64(SUPERBLOCK.DATA_OFFSET, true);\n const bitmapOffset = v.getFloat64(SUPERBLOCK.BITMAP_OFFSET, true);\n const pathUsed = v.getUint32(SUPERBLOCK.PATH_USED, true);\n\n // Validate field sanity\n if (blockSize === 0 || (blockSize & (blockSize - 1)) !== 0) {\n throw new Error(`Corrupt VFS: invalid block size ${blockSize} (must be power of 2)`);\n }\n if (inodeCount === 0) {\n throw new Error('Corrupt VFS: inode count is 0');\n }\n if (freeBlocks > totalBlocks) {\n throw new Error(`Corrupt VFS: free blocks (${freeBlocks}) exceeds total blocks (${totalBlocks})`);\n }\n\n // Validate section ordering: superblock < inodes < paths < bitmap < data\n if (inodeTableOffset !== SUPERBLOCK.SIZE) {\n throw new Error(`Corrupt VFS: inode table offset ${inodeTableOffset} (expected ${SUPERBLOCK.SIZE})`);\n }\n const expectedPathOffset = inodeTableOffset + inodeCount * INODE_SIZE;\n if (pathTableOffset !== expectedPathOffset) {\n throw new Error(`Corrupt VFS: path table offset ${pathTableOffset} (expected ${expectedPathOffset})`);\n }\n if (bitmapOffset <= pathTableOffset) {\n throw new Error(`Corrupt VFS: bitmap offset ${bitmapOffset} must be after path table ${pathTableOffset}`);\n }\n if (dataOffset <= bitmapOffset) {\n throw new Error(`Corrupt VFS: data offset ${dataOffset} must be after bitmap ${bitmapOffset}`);\n }\n const pathTableSize = bitmapOffset - pathTableOffset;\n if (pathUsed > pathTableSize) {\n throw new Error(`Corrupt VFS: path used (${pathUsed}) exceeds path table size (${pathTableSize})`);\n }\n\n // Validate file is large enough for the declared layout\n const expectedMinSize = dataOffset + totalBlocks * blockSize;\n if (fileSize < expectedMinSize) {\n throw new Error(`Corrupt VFS: file size ${fileSize} too small for layout (need ${expectedMinSize})`);\n }\n\n // All checks passed — commit to engine state\n this.inodeCount = inodeCount;\n this.blockSize = blockSize;\n this.totalBlocks = totalBlocks;\n this.freeBlocks = freeBlocks;\n this.inodeTableOffset = inodeTableOffset;\n this.pathTableOffset = pathTableOffset;\n this.dataOffset = dataOffset;\n this.bitmapOffset = bitmapOffset;\n this.pathTableUsed = pathUsed;\n this.pathTableSize = pathTableSize;\n\n // Load bitmap into memory\n const bitmapSize = Math.ceil(this.totalBlocks / 8);\n this.bitmap = new Uint8Array(bitmapSize);\n this.handle.read(this.bitmap, { at: this.bitmapOffset });\n\n this.rebuildIndex();\n\n // Verify root directory exists\n if (!this.pathIndex.has('/')) {\n throw new Error('Corrupt VFS: root directory \"/\" not found in inode table');\n }\n }\n\n private writeSuperblock(): void {\n const v = this.superblockView;\n v.setUint32(SUPERBLOCK.MAGIC, VFS_MAGIC, true);\n v.setUint32(SUPERBLOCK.VERSION, VFS_VERSION, true);\n v.setUint32(SUPERBLOCK.INODE_COUNT, this.inodeCount, true);\n v.setUint32(SUPERBLOCK.BLOCK_SIZE, this.blockSize, true);\n v.setUint32(SUPERBLOCK.TOTAL_BLOCKS, this.totalBlocks, true);\n v.setUint32(SUPERBLOCK.FREE_BLOCKS, this.freeBlocks, true);\n v.setFloat64(SUPERBLOCK.INODE_OFFSET, this.inodeTableOffset, true);\n v.setFloat64(SUPERBLOCK.PATH_OFFSET, this.pathTableOffset, true);\n v.setFloat64(SUPERBLOCK.DATA_OFFSET, this.dataOffset, true);\n v.setFloat64(SUPERBLOCK.BITMAP_OFFSET, this.bitmapOffset, true);\n v.setUint32(SUPERBLOCK.PATH_USED, this.pathTableUsed, true);\n this.handle.write(this.superblockBuf, { at: 0 });\n }\n\n /** Flush pending bitmap and superblock writes to disk (one write each) */\n private markBitmapDirty(lo: number, hi: number): void {\n if (lo < this.bitmapDirtyLo) this.bitmapDirtyLo = lo;\n if (hi > this.bitmapDirtyHi) this.bitmapDirtyHi = hi;\n }\n\n private commitPending(): void {\n // Trim trailing free blocks before flushing bitmap/superblock\n if (this.blocksFreedsinceTrim) {\n this.trimTrailingBlocks();\n this.blocksFreedsinceTrim = false;\n }\n\n if (this.bitmapDirtyHi >= 0) {\n const lo = this.bitmapDirtyLo;\n const hi = this.bitmapDirtyHi;\n this.handle.write(this.bitmap!.subarray(lo, hi + 1), { at: this.bitmapOffset + lo });\n this.bitmapDirtyLo = Infinity;\n this.bitmapDirtyHi = -1;\n }\n if (this.superblockDirty) {\n this.writeSuperblock();\n this.superblockDirty = false;\n }\n }\n\n /** Shrink the OPFS file by removing trailing free blocks from the data region.\n * Scans bitmap from end to find the last used block, then truncates. */\n private trimTrailingBlocks(): void {\n const bitmap = this.bitmap!;\n\n // Find the last used block by scanning bitmap from the end\n let lastUsed = -1;\n for (let byteIdx = Math.ceil(this.totalBlocks / 8) - 1; byteIdx >= 0; byteIdx--) {\n if (bitmap[byteIdx] !== 0) {\n // Find highest set bit in this byte\n for (let bit = 7; bit >= 0; bit--) {\n const blockIdx = byteIdx * 8 + bit;\n if (blockIdx < this.totalBlocks && (bitmap[byteIdx] & (1 << bit))) {\n lastUsed = blockIdx;\n break;\n }\n }\n break;\n }\n }\n\n const newTotal = Math.max(lastUsed + 1, INITIAL_DATA_BLOCKS);\n if (newTotal >= this.totalBlocks) return; // nothing to trim\n\n // Truncate the OPFS file\n this.handle.truncate(this.dataOffset + newTotal * this.blockSize);\n\n // Shrink in-memory bitmap\n const newBitmapSize = Math.ceil(newTotal / 8);\n this.bitmap = bitmap.slice(0, newBitmapSize);\n\n // Update counters\n const trimmed = this.totalBlocks - newTotal;\n this.freeBlocks -= trimmed; // these free blocks no longer exist\n this.totalBlocks = newTotal;\n this.superblockDirty = true;\n\n // Re-mark entire bitmap dirty so the smaller bitmap is flushed\n this.bitmapDirtyLo = 0;\n this.bitmapDirtyHi = newBitmapSize - 1;\n }\n\n /** Rebuild in-memory path→inode index from disk.\n * Bulk-reads the entire inode table + path table in 2 I/O calls,\n * then parses in memory (avoids 10k+ individual reads). */\n private rebuildIndex(): void {\n this.pathIndex.clear();\n this.inodeCache.clear();\n\n // Bulk read entire inode table (e.g. 640KB for 10k inodes)\n const inodeTableSize = this.inodeCount * INODE_SIZE;\n const inodeBuf = new Uint8Array(inodeTableSize);\n this.handle.read(inodeBuf, { at: this.inodeTableOffset });\n const inodeView = new DataView(inodeBuf.buffer);\n\n // Bulk read used portion of path table\n const pathBuf = this.pathTableUsed > 0 ? new Uint8Array(this.pathTableUsed) : null;\n if (pathBuf) {\n this.handle.read(pathBuf, { at: this.pathTableOffset });\n }\n\n for (let i = 0; i < this.inodeCount; i++) {\n const off = i * INODE_SIZE;\n const type = inodeView.getUint8(off + INODE.TYPE);\n if (type === INODE_TYPE.FREE) continue;\n\n // Validate inode type\n if (type < INODE_TYPE.FILE || type > INODE_TYPE.SYMLINK) {\n throw new Error(`Corrupt VFS: inode ${i} has invalid type ${type}`);\n }\n\n const pathOffset = inodeView.getUint32(off + INODE.PATH_OFFSET, true);\n const pathLength = inodeView.getUint16(off + INODE.PATH_LENGTH, true);\n const size = inodeView.getFloat64(off + INODE.SIZE, true);\n const firstBlock = inodeView.getUint32(off + INODE.FIRST_BLOCK, true);\n const blockCount = inodeView.getUint32(off + INODE.BLOCK_COUNT, true);\n\n // Validate path bounds\n if (pathLength === 0 || pathOffset + pathLength > this.pathTableUsed) {\n throw new Error(`Corrupt VFS: inode ${i} path out of bounds (offset=${pathOffset}, len=${pathLength}, tableUsed=${this.pathTableUsed})`);\n }\n\n // Validate data bounds for files/symlinks\n if (type !== INODE_TYPE.DIRECTORY) {\n if (size < 0 || !isFinite(size)) {\n throw new Error(`Corrupt VFS: inode ${i} has invalid size ${size}`);\n }\n if (blockCount > 0 && firstBlock + blockCount > this.totalBlocks) {\n throw new Error(`Corrupt VFS: inode ${i} data blocks out of range (first=${firstBlock}, count=${blockCount}, total=${this.totalBlocks})`);\n }\n }\n\n const inode: Inode = {\n type,\n pathOffset,\n pathLength,\n mode: inodeView.getUint32(off + INODE.MODE, true),\n size,\n firstBlock,\n blockCount,\n mtime: inodeView.getFloat64(off + INODE.MTIME, true),\n ctime: inodeView.getFloat64(off + INODE.CTIME, true),\n atime: inodeView.getFloat64(off + INODE.ATIME, true),\n uid: inodeView.getUint32(off + INODE.UID, true),\n gid: inodeView.getUint32(off + INODE.GID, true),\n };\n this.inodeCache.set(i, inode);\n\n // Decode path from in-memory path table buffer (no disk read)\n let path: string;\n if (pathBuf) {\n path = decoder.decode(pathBuf.subarray(inode.pathOffset, inode.pathOffset + inode.pathLength));\n } else {\n path = this.readPath(inode.pathOffset, inode.pathLength);\n }\n\n // Validate path format\n if (!path.startsWith('/') || path.includes('\\0')) {\n throw new Error(`Corrupt VFS: inode ${i} has invalid path \"${path.substring(0, 50)}\"`);\n }\n\n this.pathIndex.set(path, i);\n }\n }\n\n // ========== Low-level inode I/O ==========\n\n private readInode(idx: number): Inode {\n const cached = this.inodeCache.get(idx);\n if (cached) return cached;\n\n const offset = this.inodeTableOffset + idx * INODE_SIZE;\n this.handle.read(this.inodeBuf, { at: offset });\n const v = this.inodeView;\n const inode: Inode = {\n type: v.getUint8(INODE.TYPE),\n pathOffset: v.getUint32(INODE.PATH_OFFSET, true),\n pathLength: v.getUint16(INODE.PATH_LENGTH, true),\n mode: v.getUint32(INODE.MODE, true),\n size: v.getFloat64(INODE.SIZE, true),\n firstBlock: v.getUint32(INODE.FIRST_BLOCK, true),\n blockCount: v.getUint32(INODE.BLOCK_COUNT, true),\n mtime: v.getFloat64(INODE.MTIME, true),\n ctime: v.getFloat64(INODE.CTIME, true),\n atime: v.getFloat64(INODE.ATIME, true),\n uid: v.getUint32(INODE.UID, true),\n gid: v.getUint32(INODE.GID, true),\n };\n this.inodeCache.set(idx, inode);\n return inode;\n }\n\n private writeInode(idx: number, inode: Inode): void {\n // Maintain inode cache\n if (inode.type === INODE_TYPE.FREE) {\n this.inodeCache.delete(idx);\n } else {\n this.inodeCache.set(idx, inode);\n }\n\n const v = this.inodeView;\n v.setUint8(INODE.TYPE, inode.type);\n v.setUint8(INODE.FLAGS, 0);\n v.setUint8(INODE.FLAGS + 1, 0);\n v.setUint8(INODE.FLAGS + 2, 0);\n v.setUint32(INODE.PATH_OFFSET, inode.pathOffset, true);\n v.setUint16(INODE.PATH_LENGTH, inode.pathLength, true);\n v.setUint16(INODE.RESERVED_10, 0, true);\n v.setUint32(INODE.MODE, inode.mode, true);\n v.setFloat64(INODE.SIZE, inode.size, true);\n v.setUint32(INODE.FIRST_BLOCK, inode.firstBlock, true);\n v.setUint32(INODE.BLOCK_COUNT, inode.blockCount, true);\n v.setFloat64(INODE.MTIME, inode.mtime, true);\n v.setFloat64(INODE.CTIME, inode.ctime, true);\n v.setFloat64(INODE.ATIME, inode.atime, true);\n v.setUint32(INODE.UID, inode.uid, true);\n v.setUint32(INODE.GID, inode.gid, true);\n\n const offset = this.inodeTableOffset + idx * INODE_SIZE;\n this.handle.write(this.inodeBuf, { at: offset });\n }\n\n // ========== Path table I/O ==========\n\n private readPath(offset: number, length: number): string {\n const buf = new Uint8Array(length);\n this.handle.read(buf, { at: this.pathTableOffset + offset });\n return decoder.decode(buf);\n }\n\n private appendPath(path: string): { offset: number; length: number } {\n const bytes = encoder.encode(path);\n const offset = this.pathTableUsed;\n\n // Check if path table needs to grow\n if (offset + bytes.byteLength > this.pathTableSize) {\n this.growPathTable(offset + bytes.byteLength);\n }\n\n this.handle.write(bytes, { at: this.pathTableOffset + offset });\n this.pathTableUsed += bytes.byteLength;\n\n // Defer superblock write — committed in commitPending()\n this.superblockDirty = true;\n\n return { offset, length: bytes.byteLength };\n }\n\n private growPathTable(needed: number): void {\n // Double the path table or grow to fit needed, whichever is larger\n const newSize = Math.max(this.pathTableSize * 2, needed + INITIAL_PATH_TABLE_SIZE);\n const growth = newSize - this.pathTableSize;\n\n // Need to shift bitmap and data region forward\n // Use in-memory bitmap (no read needed)\n\n // Read existing data region\n const dataSize = this.totalBlocks * this.blockSize;\n const dataBuf = new Uint8Array(dataSize);\n this.handle.read(dataBuf, { at: this.dataOffset });\n\n // Grow file\n const newTotalSize = this.handle.getSize() + growth;\n this.handle.truncate(newTotalSize);\n\n // Write data back at new offset\n const newBitmapOffset = this.bitmapOffset + growth;\n const newDataOffset = this.dataOffset + growth;\n this.handle.write(dataBuf, { at: newDataOffset });\n this.handle.write(this.bitmap!, { at: newBitmapOffset });\n\n // Update offsets\n this.pathTableSize = newSize;\n this.bitmapOffset = newBitmapOffset;\n this.dataOffset = newDataOffset;\n\n // Mark superblock dirty (will be written in commitPending)\n this.superblockDirty = true;\n }\n\n // ========== Bitmap I/O ==========\n\n private allocateBlocks(count: number): number {\n if (count === 0) return 0;\n\n const bitmap = this.bitmap!;\n let run = 0;\n let start = 0;\n\n for (let i = 0; i < this.totalBlocks; i++) {\n const byteIdx = i >>> 3;\n const bitIdx = i & 7;\n const used = (bitmap[byteIdx] >>> bitIdx) & 1;\n\n if (used) {\n run = 0;\n start = i + 1;\n } else {\n run++;\n if (run === count) {\n // Mark blocks as used in memory\n for (let j = start; j <= i; j++) {\n const bj = j >>> 3;\n const bi = j & 7;\n bitmap[bj] |= (1 << bi);\n }\n this.markBitmapDirty(start >>> 3, i >>> 3);\n this.freeBlocks -= count;\n this.superblockDirty = true;\n return start;\n }\n }\n }\n\n // No contiguous space — grow data region\n return this.growAndAllocate(count);\n }\n\n private growAndAllocate(count: number): number {\n const oldTotal = this.totalBlocks;\n // Grow by at least doubling or enough for the request\n const newTotal = Math.max(oldTotal * 2, oldTotal + count);\n const addedBlocks = newTotal - oldTotal;\n\n // Grow the file\n const newFileSize = this.dataOffset + newTotal * this.blockSize;\n this.handle.truncate(newFileSize);\n\n // Grow in-memory bitmap\n const newBitmapSize = Math.ceil(newTotal / 8);\n const newBitmap = new Uint8Array(newBitmapSize);\n newBitmap.set(this.bitmap!);\n this.bitmap = newBitmap;\n\n this.totalBlocks = newTotal;\n this.freeBlocks += addedBlocks;\n\n // Allocate from the newly freed area\n const start = oldTotal;\n for (let j = start; j < start + count; j++) {\n const bj = j >>> 3;\n const bi = j & 7;\n this.bitmap[bj] |= (1 << bi);\n }\n\n this.markBitmapDirty(start >>> 3, (start + count - 1) >>> 3);\n this.freeBlocks -= count;\n this.superblockDirty = true;\n\n return start;\n }\n\n private blocksFreedsinceTrim = false;\n\n private freeBlockRange(start: number, count: number): void {\n if (count === 0) return;\n const bitmap = this.bitmap!;\n\n for (let i = start; i < start + count; i++) {\n const byteIdx = i >>> 3;\n const bitIdx = i & 7;\n bitmap[byteIdx] &= ~(1 << bitIdx);\n }\n\n this.markBitmapDirty(start >>> 3, (start + count - 1) >>> 3);\n this.freeBlocks += count;\n this.superblockDirty = true;\n this.blocksFreedsinceTrim = true;\n }\n\n // updateSuperblockFreeBlocks is no longer needed — superblock writes are coalesced via commitPending()\n\n // ========== Inode allocation ==========\n\n private findFreeInode(): number {\n // Start from hint to skip already-used entries\n for (let i = this.freeInodeHint; i < this.inodeCount; i++) {\n // Check cache first — cached entries are never FREE\n if (this.inodeCache.has(i)) continue;\n\n const offset = this.inodeTableOffset + i * INODE_SIZE;\n const typeBuf = new Uint8Array(1);\n this.handle.read(typeBuf, { at: offset });\n if (typeBuf[0] === INODE_TYPE.FREE) {\n this.freeInodeHint = i + 1;\n return i;\n }\n }\n // All inodes used — grow inode table\n const idx = this.growInodeTable();\n this.freeInodeHint = idx + 1;\n return idx;\n }\n\n private growInodeTable(): number {\n const oldCount = this.inodeCount;\n const newCount = oldCount * 2;\n const growth = (newCount - oldCount) * INODE_SIZE;\n\n // Read everything after inode table\n const afterInodeOffset = this.inodeTableOffset + oldCount * INODE_SIZE;\n const afterSize = this.handle.getSize() - afterInodeOffset;\n const afterBuf = new Uint8Array(afterSize);\n this.handle.read(afterBuf, { at: afterInodeOffset });\n\n // Grow file\n this.handle.truncate(this.handle.getSize() + growth);\n\n // Write back shifted content\n this.handle.write(afterBuf, { at: afterInodeOffset + growth });\n\n // Zero out new inode entries\n const zeroes = new Uint8Array(growth);\n this.handle.write(zeroes, { at: afterInodeOffset });\n\n // Update offsets\n this.pathTableOffset += growth;\n this.bitmapOffset += growth;\n this.dataOffset += growth;\n this.inodeCount = newCount;\n\n this.superblockDirty = true;\n\n return oldCount; // First new free inode\n }\n\n // ========== Data I/O ==========\n\n private readData(firstBlock: number, blockCount: number, size: number): Uint8Array {\n const buf = new Uint8Array(size);\n const offset = this.dataOffset + firstBlock * this.blockSize;\n this.handle.read(buf, { at: offset });\n return buf;\n }\n\n private writeData(firstBlock: number, data: Uint8Array): void {\n const offset = this.dataOffset + firstBlock * this.blockSize;\n this.handle.write(data, { at: offset });\n }\n\n // ========== Path resolution ==========\n\n private resolvePath(path: string, depth: number = 0): number | undefined {\n if (depth > MAX_SYMLINK_DEPTH) return undefined; // ELOOP\n\n const idx = this.pathIndex.get(path);\n if (idx === undefined) {\n // Path not found directly — try component resolution (handles intermediate symlinks)\n return this.resolvePathComponents(path, true, depth);\n }\n\n const inode = this.readInode(idx);\n if (inode.type === INODE_TYPE.SYMLINK) {\n // Follow symlink\n const target = decoder.decode(this.readData(inode.firstBlock, inode.blockCount, inode.size));\n const resolved = target.startsWith('/') ? target : this.resolveRelative(path, target);\n return this.resolvePath(resolved, depth + 1);\n }\n\n return idx;\n }\n\n /** Resolve symlinks in intermediate path components */\n private resolvePathComponents(path: string, followLast: boolean = true, depth: number = 0): number | undefined {\n if (depth > MAX_SYMLINK_DEPTH) return undefined; // ELOOP\n\n const parts = path.split('/').filter(Boolean);\n let current = '/';\n\n for (let i = 0; i < parts.length; i++) {\n const isLast = i === parts.length - 1;\n current = current === '/' ? '/' + parts[i] : current + '/' + parts[i];\n\n const idx = this.pathIndex.get(current);\n if (idx === undefined) return undefined;\n\n const inode = this.readInode(idx);\n if (inode.type === INODE_TYPE.SYMLINK && (!isLast || followLast)) {\n const target = decoder.decode(this.readData(inode.firstBlock, inode.blockCount, inode.size));\n const resolved = target.startsWith('/') ? target : this.resolveRelative(current, target);\n\n if (isLast) {\n // Use resolvePathComponents (not resolvePath) so intermediate symlinks\n // in the resolved target path are also followed\n return this.resolvePathComponents(resolved, true, depth + 1);\n }\n\n // Reconstruct remaining path with resolved symlink\n const remaining = parts.slice(i + 1).join('/');\n const newPath = resolved + (remaining ? '/' + remaining : '');\n return this.resolvePathComponents(newPath, followLast, depth + 1);\n }\n }\n\n return this.pathIndex.get(current);\n }\n\n private resolveRelative(from: string, target: string): string {\n const dir = from.substring(0, from.lastIndexOf('/')) || '/';\n const parts = (dir + '/' + target).split('/').filter(Boolean);\n const resolved: string[] = [];\n for (const p of parts) {\n if (p === '.') continue;\n if (p === '..') { resolved.pop(); continue; }\n resolved.push(p);\n }\n return '/' + resolved.join('/');\n }\n\n // ========== Core inode creation helper ==========\n\n private createInode(path: string, type: number, mode: number, size: number, data?: Uint8Array): number {\n const idx = this.findFreeInode();\n const { offset: pathOff, length: pathLen } = this.appendPath(path);\n const now = Date.now();\n\n let firstBlock = 0;\n let blockCount = 0;\n\n if (data && data.byteLength > 0) {\n blockCount = Math.ceil(data.byteLength / this.blockSize);\n firstBlock = this.allocateBlocks(blockCount);\n this.writeData(firstBlock, data);\n }\n\n const inode: Inode = {\n type,\n pathOffset: pathOff,\n pathLength: pathLen,\n mode,\n size,\n firstBlock,\n blockCount,\n mtime: now,\n ctime: now,\n atime: now,\n uid: this.processUid,\n gid: this.processGid,\n };\n\n this.writeInode(idx, inode);\n this.pathIndex.set(path, idx);\n\n return idx;\n }\n\n // ========== Public API — called by server worker dispatch ==========\n\n /** Normalize a path: ensure leading /, resolve . and .. */\n normalizePath(p: string): string {\n if (p.charCodeAt(0) !== 47) p = '/' + p; // 47 = '/'\n // Fast path: already normalized (no '.', '..', '//', trailing '/')\n if (p.length === 1) return p; // \"/\"\n if (p.indexOf('/.') === -1 && p.indexOf('//') === -1 && p.charCodeAt(p.length - 1) !== 47) {\n return p;\n }\n // Slow path: full normalize\n const parts = p.split('/').filter(Boolean);\n const resolved: string[] = [];\n for (const part of parts) {\n if (part === '.') continue;\n if (part === '..') { resolved.pop(); continue; }\n resolved.push(part);\n }\n return '/' + resolved.join('/');\n }\n\n // ---- READ ----\n read(path: string): { status: number; data: Uint8Array | null } {\n const t0 = this.debug ? performance.now() : 0;\n path = this.normalizePath(path);\n\n // Fast path: direct index lookup (skips component-by-component walk)\n let idx = this.pathIndex.get(path);\n if (idx !== undefined) {\n const inode = this.inodeCache.get(idx);\n if (inode) {\n // Symlink? Fall through to full resolve\n if (inode.type === INODE_TYPE.SYMLINK) {\n idx = this.resolvePathComponents(path, true);\n } else if (inode.type === INODE_TYPE.DIRECTORY) {\n return { status: CODE_TO_STATUS.EISDIR, data: null };\n } else {\n // Hot path: cached inode, no symlinks\n const data = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n if (this.debug) {\n const t1 = performance.now();\n console.log(`[VFS read] path=${path} size=${inode.size} TOTAL=${(t1-t0).toFixed(3)}ms (fast)`);\n }\n return { status: 0, data };\n }\n }\n }\n\n // Slow path: full component resolution (handles symlinks, uncached inodes)\n if (idx === undefined) idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n const inode = this.readInode(idx);\n if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR, data: null };\n\n const data = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n\n if (this.debug) {\n const t1 = performance.now();\n console.log(`[VFS read] path=${path} size=${inode.size} TOTAL=${(t1-t0).toFixed(3)}ms (slow path)`);\n }\n\n return { status: 0, data };\n }\n\n // ---- WRITE ----\n write(path: string, data: Uint8Array, flags: number = 0): { status: number } {\n const t0 = this.debug ? performance.now() : 0;\n path = this.normalizePath(path);\n const t1 = this.debug ? performance.now() : 0;\n\n // Ensure parent directory exists\n const parentStatus = this.ensureParent(path);\n if (parentStatus !== 0) return { status: parentStatus };\n const t2 = this.debug ? performance.now() : 0;\n\n const existingIdx = this.resolvePathComponents(path, true);\n const t3 = this.debug ? performance.now() : 0;\n\n let tAlloc = t3, tData = t3, tInode = t3;\n\n if (existingIdx !== undefined) {\n // Update existing file\n const inode = this.readInode(existingIdx);\n if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };\n\n const neededBlocks = Math.ceil(data.byteLength / this.blockSize);\n\n if (neededBlocks <= inode.blockCount) {\n // Fits in current blocks\n tAlloc = this.debug ? performance.now() : 0;\n this.writeData(inode.firstBlock, data);\n tData = this.debug ? performance.now() : 0;\n if (neededBlocks < inode.blockCount) {\n this.freeBlockRange(inode.firstBlock + neededBlocks, inode.blockCount - neededBlocks);\n }\n } else {\n // Need more blocks — free old, allocate new\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n const newFirst = this.allocateBlocks(neededBlocks);\n tAlloc = this.debug ? performance.now() : 0;\n this.writeData(newFirst, data);\n tData = this.debug ? performance.now() : 0;\n inode.firstBlock = newFirst;\n }\n\n inode.size = data.byteLength;\n inode.blockCount = neededBlocks;\n inode.mtime = Date.now();\n this.writeInode(existingIdx, inode);\n tInode = this.debug ? performance.now() : 0;\n } else {\n // Create new file\n const mode = DEFAULT_FILE_MODE & ~(this.umask & 0o777);\n this.createInode(path, INODE_TYPE.FILE, mode, data.byteLength, data);\n tAlloc = this.debug ? performance.now() : 0;\n tData = tAlloc;\n tInode = tAlloc;\n }\n\n if (flags & 1) {\n this.commitPending();\n this.handle.flush();\n }\n const tFlush = this.debug ? performance.now() : 0;\n\n if (this.debug) {\n const existing = existingIdx !== undefined;\n console.log(`[VFS write] path=${path} size=${data.byteLength} ${existing ? 'UPDATE' : 'CREATE'} normalize=${(t1-t0).toFixed(3)}ms parent=${(t2-t1).toFixed(3)}ms resolve=${(t3-t2).toFixed(3)}ms alloc=${(tAlloc-t3).toFixed(3)}ms data=${(tData-tAlloc).toFixed(3)}ms inode=${(tInode-tData).toFixed(3)}ms flush=${(tFlush-tInode).toFixed(3)}ms TOTAL=${(tFlush-t0).toFixed(3)}ms`);\n }\n\n return { status: 0 };\n }\n\n // ---- APPEND ----\n append(path: string, data: Uint8Array): { status: number } {\n path = this.normalizePath(path);\n const existingIdx = this.resolvePathComponents(path, true);\n\n if (existingIdx === undefined) {\n // Create new file with the data\n return this.write(path, data);\n }\n\n const inode = this.readInode(existingIdx);\n if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };\n\n // Read existing data\n const existing = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n\n // Concat\n const combined = new Uint8Array(existing.byteLength + data.byteLength);\n combined.set(existing);\n combined.set(data, existing.byteLength);\n\n // Rewrite\n const neededBlocks = Math.ceil(combined.byteLength / this.blockSize);\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n const newFirst = this.allocateBlocks(neededBlocks);\n this.writeData(newFirst, combined);\n\n inode.firstBlock = newFirst;\n inode.blockCount = neededBlocks;\n inode.size = combined.byteLength;\n inode.mtime = Date.now();\n this.writeInode(existingIdx, inode);\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- UNLINK ----\n unlink(path: string): { status: number } {\n path = this.normalizePath(path);\n const idx = this.pathIndex.get(path);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };\n\n // Free data blocks\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n\n // Mark inode as free\n inode.type = INODE_TYPE.FREE;\n this.writeInode(idx, inode);\n\n // Remove from index\n this.pathIndex.delete(path);\n // Reset free inode hint\n if (idx < this.freeInodeHint) this.freeInodeHint = idx;\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- STAT ----\n stat(path: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n return this.encodeStatResponse(idx);\n }\n\n // ---- LSTAT (no symlink follow) ----\n lstat(path: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.pathIndex.get(path);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n return this.encodeStatResponse(idx);\n }\n\n private encodeStatResponse(idx: number): { status: number; data: Uint8Array } {\n const inode = this.readInode(idx);\n // Encode stat into binary: type(1) + mode(4) + size(8) + mtime(8) + ctime(8) + atime(8) + uid(4) + gid(4) + ino(4) = 49 bytes\n const buf = new Uint8Array(49);\n const view = new DataView(buf.buffer);\n view.setUint8(0, inode.type);\n view.setUint32(1, inode.mode, true);\n view.setFloat64(5, inode.size, true);\n view.setFloat64(13, inode.mtime, true);\n view.setFloat64(21, inode.ctime, true);\n view.setFloat64(29, inode.atime, true);\n view.setUint32(37, inode.uid, true);\n view.setUint32(41, inode.gid, true);\n view.setUint32(45, idx, true); // ino = inode index\n\n return { status: 0, data: buf };\n }\n\n // ---- MKDIR ----\n mkdir(path: string, flags: number = 0): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const recursive = (flags & 1) !== 0;\n\n if (recursive) {\n return this.mkdirRecursive(path);\n }\n\n // Check if already exists\n if (this.pathIndex.has(path)) return { status: CODE_TO_STATUS.EEXIST, data: null };\n\n // Ensure parent exists\n const parentStatus = this.ensureParent(path);\n if (parentStatus !== 0) return { status: parentStatus, data: null };\n\n const mode = DEFAULT_DIR_MODE & ~(this.umask & 0o777);\n this.createInode(path, INODE_TYPE.DIRECTORY, mode, 0);\n\n this.commitPending();\n // Return created path as data\n const pathBytes = encoder.encode(path);\n return { status: 0, data: pathBytes };\n }\n\n private mkdirRecursive(path: string): { status: number; data: Uint8Array | null } {\n const parts = path.split('/').filter(Boolean);\n let current = '';\n let firstCreated: string | null = null;\n\n for (const part of parts) {\n current += '/' + part;\n\n if (this.pathIndex.has(current)) {\n const idx = this.pathIndex.get(current)!;\n const inode = this.readInode(idx);\n if (inode.type !== INODE_TYPE.DIRECTORY) {\n return { status: CODE_TO_STATUS.ENOTDIR, data: null };\n }\n continue;\n }\n\n const mode = DEFAULT_DIR_MODE & ~(this.umask & 0o777);\n this.createInode(current, INODE_TYPE.DIRECTORY, mode, 0);\n if (!firstCreated) firstCreated = current;\n }\n\n this.commitPending();\n const result = firstCreated ? encoder.encode(firstCreated) : undefined;\n return { status: 0, data: result ?? null };\n }\n\n // ---- RMDIR ----\n rmdir(path: string, flags: number = 0): { status: number } {\n path = this.normalizePath(path);\n const recursive = (flags & 1) !== 0;\n const idx = this.pathIndex.get(path);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n if (inode.type !== INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.ENOTDIR };\n\n // Check for children\n const children = this.getDirectChildren(path);\n\n if (children.length > 0) {\n if (!recursive) return { status: CODE_TO_STATUS.ENOTEMPTY };\n\n // Recursive delete\n for (const child of this.getAllDescendants(path)) {\n const childIdx = this.pathIndex.get(child)!;\n const childInode = this.readInode(childIdx);\n this.freeBlockRange(childInode.firstBlock, childInode.blockCount);\n childInode.type = INODE_TYPE.FREE;\n this.writeInode(childIdx, childInode);\n this.pathIndex.delete(child);\n }\n }\n\n // Remove the directory itself\n inode.type = INODE_TYPE.FREE;\n this.writeInode(idx, inode);\n this.pathIndex.delete(path);\n if (idx < this.freeInodeHint) this.freeInodeHint = idx;\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- READDIR ----\n readdir(path: string, flags: number = 0): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n const inode = this.readInode(idx);\n if (inode.type !== INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.ENOTDIR, data: null };\n\n const withFileTypes = (flags & 1) !== 0;\n const children = this.getDirectChildren(path);\n\n if (withFileTypes) {\n // Encode as: count(u32) + entries[name_len(u16) + name(bytes) + type(u8)]\n let totalSize = 4;\n const entries: { name: Uint8Array; type: number }[] = [];\n\n for (const childPath of children) {\n const name = childPath.substring(childPath.lastIndexOf('/') + 1);\n const nameBytes = encoder.encode(name);\n const childIdx = this.pathIndex.get(childPath)!;\n const childInode = this.readInode(childIdx);\n entries.push({ name: nameBytes, type: childInode.type });\n totalSize += 2 + nameBytes.byteLength + 1; // nameLen + name + type\n }\n\n const buf = new Uint8Array(totalSize);\n const view = new DataView(buf.buffer);\n view.setUint32(0, entries.length, true);\n let offset = 4;\n\n for (const entry of entries) {\n view.setUint16(offset, entry.name.byteLength, true);\n offset += 2;\n buf.set(entry.name, offset);\n offset += entry.name.byteLength;\n buf[offset++] = entry.type;\n }\n\n return { status: 0, data: buf };\n }\n\n // Simple name list: count(u32) + entries[name_len(u16) + name(bytes)]\n let totalSize = 4;\n const nameEntries: Uint8Array[] = [];\n\n for (const childPath of children) {\n const name = childPath.substring(childPath.lastIndexOf('/') + 1);\n const nameBytes = encoder.encode(name);\n nameEntries.push(nameBytes);\n totalSize += 2 + nameBytes.byteLength;\n }\n\n const buf = new Uint8Array(totalSize);\n const view = new DataView(buf.buffer);\n view.setUint32(0, nameEntries.length, true);\n let offset = 4;\n\n for (const nameBytes of nameEntries) {\n view.setUint16(offset, nameBytes.byteLength, true);\n offset += 2;\n buf.set(nameBytes, offset);\n offset += nameBytes.byteLength;\n }\n\n return { status: 0, data: buf };\n }\n\n // ---- RENAME ----\n rename(oldPath: string, newPath: string): { status: number } {\n oldPath = this.normalizePath(oldPath);\n newPath = this.normalizePath(newPath);\n\n const idx = this.pathIndex.get(oldPath);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n // Ensure parent of new path exists\n const parentStatus = this.ensureParent(newPath);\n if (parentStatus !== 0) return { status: parentStatus };\n\n // If target exists, remove it\n const existingIdx = this.pathIndex.get(newPath);\n if (existingIdx !== undefined) {\n const existingInode = this.readInode(existingIdx);\n this.freeBlockRange(existingInode.firstBlock, existingInode.blockCount);\n existingInode.type = INODE_TYPE.FREE;\n this.writeInode(existingIdx, existingInode);\n this.pathIndex.delete(newPath);\n }\n\n // Update inode with new path\n const inode = this.readInode(idx);\n const { offset: pathOff, length: pathLen } = this.appendPath(newPath);\n inode.pathOffset = pathOff;\n inode.pathLength = pathLen;\n inode.mtime = Date.now();\n this.writeInode(idx, inode);\n\n // Update index\n this.pathIndex.delete(oldPath);\n this.pathIndex.set(newPath, idx);\n\n // If it's a directory, rename all descendants\n if (inode.type === INODE_TYPE.DIRECTORY) {\n const prefix = oldPath === '/' ? '/' : oldPath + '/';\n const toRename: [string, number][] = [];\n\n for (const [p, i] of this.pathIndex) {\n if (p.startsWith(prefix)) {\n toRename.push([p, i]);\n }\n }\n\n for (const [p, i] of toRename) {\n const suffix = p.substring(oldPath.length);\n const childNewPath = newPath + suffix;\n const childInode = this.readInode(i);\n const { offset: cpo, length: cpl } = this.appendPath(childNewPath);\n childInode.pathOffset = cpo;\n childInode.pathLength = cpl;\n this.writeInode(i, childInode);\n this.pathIndex.delete(p);\n this.pathIndex.set(childNewPath, i);\n }\n }\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- EXISTS ----\n exists(path: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n const buf = new Uint8Array(1);\n buf[0] = idx !== undefined ? 1 : 0;\n return { status: 0, data: buf };\n }\n\n // ---- TRUNCATE ----\n truncate(path: string, len: number = 0): { status: number } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };\n\n if (len === 0) {\n // Free all blocks\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n inode.firstBlock = 0;\n inode.blockCount = 0;\n inode.size = 0;\n } else if (len < inode.size) {\n // Shrink\n const neededBlocks = Math.ceil(len / this.blockSize);\n if (neededBlocks < inode.blockCount) {\n this.freeBlockRange(inode.firstBlock + neededBlocks, inode.blockCount - neededBlocks);\n }\n inode.blockCount = neededBlocks;\n inode.size = len;\n } else if (len > inode.size) {\n // Grow (zero-fill)\n const neededBlocks = Math.ceil(len / this.blockSize);\n if (neededBlocks > inode.blockCount) {\n // Need more blocks\n const oldData = this.readData(inode.firstBlock, inode.blockCount, inode.size);\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n const newFirst = this.allocateBlocks(neededBlocks);\n const newData = new Uint8Array(len);\n newData.set(oldData);\n // Rest is already zero-filled\n this.writeData(newFirst, newData);\n inode.firstBlock = newFirst;\n }\n inode.blockCount = neededBlocks;\n inode.size = len;\n }\n\n inode.mtime = Date.now();\n this.writeInode(idx, inode);\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- COPY ----\n copy(srcPath: string, destPath: string, flags: number = 0): { status: number } {\n srcPath = this.normalizePath(srcPath);\n destPath = this.normalizePath(destPath);\n\n const srcIdx = this.resolvePathComponents(srcPath, true);\n if (srcIdx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const srcInode = this.readInode(srcIdx);\n if (srcInode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };\n\n // COPYFILE_EXCL check\n if ((flags & 1) && this.pathIndex.has(destPath)) {\n return { status: CODE_TO_STATUS.EEXIST };\n }\n\n // Read source data\n const data = srcInode.size > 0\n ? this.readData(srcInode.firstBlock, srcInode.blockCount, srcInode.size)\n : new Uint8Array(0);\n\n return this.write(destPath, data);\n }\n\n // ---- ACCESS ----\n access(path: string, mode: number = 0): { status: number } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n if (mode === 0) return { status: 0 }; // F_OK — just check existence\n\n if (!this.strictPermissions) return { status: 0 }; // Relaxed mode\n\n const inode = this.readInode(idx);\n // Check permission bits against process identity\n const filePerm = this.getEffectivePermission(inode);\n\n if ((mode & 4) && !(filePerm & 4)) return { status: CODE_TO_STATUS.EACCES }; // R_OK\n if ((mode & 2) && !(filePerm & 2)) return { status: CODE_TO_STATUS.EACCES }; // W_OK\n if ((mode & 1) && !(filePerm & 1)) return { status: CODE_TO_STATUS.EACCES }; // X_OK\n\n return { status: 0 };\n }\n\n private getEffectivePermission(inode: Inode): number {\n const modeBits = inode.mode & 0o777;\n if (this.processUid === inode.uid) return (modeBits >>> 6) & 7;\n if (this.processGid === inode.gid) return (modeBits >>> 3) & 7;\n return modeBits & 7;\n }\n\n // ---- REALPATH ----\n realpath(path: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n // Find the resolved path for this inode\n const inode = this.readInode(idx);\n const resolvedPath = this.readPath(inode.pathOffset, inode.pathLength);\n return { status: 0, data: encoder.encode(resolvedPath) };\n }\n\n // ---- CHMOD ----\n chmod(path: string, mode: number): { status: number } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n // Preserve file type bits, update permission bits\n inode.mode = (inode.mode & S_IFMT) | (mode & 0o7777);\n inode.ctime = Date.now();\n this.writeInode(idx, inode);\n\n return { status: 0 };\n }\n\n // ---- CHOWN ----\n chown(path: string, uid: number, gid: number): { status: number } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n inode.uid = uid;\n inode.gid = gid;\n inode.ctime = Date.now();\n this.writeInode(idx, inode);\n\n return { status: 0 };\n }\n\n // ---- UTIMES ----\n utimes(path: string, atime: number, mtime: number): { status: number } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n inode.atime = atime;\n inode.mtime = mtime;\n inode.ctime = Date.now();\n this.writeInode(idx, inode);\n\n return { status: 0 };\n }\n\n // ---- SYMLINK ----\n symlink(target: string, linkPath: string): { status: number } {\n linkPath = this.normalizePath(linkPath);\n if (this.pathIndex.has(linkPath)) return { status: CODE_TO_STATUS.EEXIST };\n\n const parentStatus = this.ensureParent(linkPath);\n if (parentStatus !== 0) return { status: parentStatus };\n\n const targetBytes = encoder.encode(target);\n this.createInode(linkPath, INODE_TYPE.SYMLINK, DEFAULT_SYMLINK_MODE, targetBytes.byteLength, targetBytes);\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- READLINK ----\n readlink(path: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.pathIndex.get(path);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n const inode = this.readInode(idx);\n if (inode.type !== INODE_TYPE.SYMLINK) return { status: CODE_TO_STATUS.EINVAL, data: null };\n\n const target = this.readData(inode.firstBlock, inode.blockCount, inode.size);\n return { status: 0, data: target };\n }\n\n // ---- LINK (hard link — copies the file) ----\n link(existingPath: string, newPath: string): { status: number } {\n return this.copy(existingPath, newPath);\n }\n\n // ---- OPEN (file descriptor) ----\n open(path: string, flags: number, tabId: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n\n const hasCreate = (flags & 64) !== 0; // O_CREAT\n const hasTrunc = (flags & 512) !== 0; // O_TRUNC\n const hasExcl = (flags & 128) !== 0; // O_EXCL\n\n let idx = this.resolvePathComponents(path, true);\n\n if (idx === undefined) {\n if (!hasCreate) return { status: CODE_TO_STATUS.ENOENT, data: null };\n // Create file\n const mode = DEFAULT_FILE_MODE & ~(this.umask & 0o777);\n idx = this.createInode(path, INODE_TYPE.FILE, mode, 0);\n } else if (hasExcl && hasCreate) {\n return { status: CODE_TO_STATUS.EEXIST, data: null };\n }\n\n if (hasTrunc) {\n this.truncate(path, 0);\n }\n\n const fd = this.nextFd++;\n this.fdTable.set(fd, { tabId, inodeIdx: idx, position: 0, flags });\n\n const buf = new Uint8Array(4);\n new DataView(buf.buffer).setUint32(0, fd, true);\n return { status: 0, data: buf };\n }\n\n // ---- CLOSE ----\n close(fd: number): { status: number } {\n if (!this.fdTable.has(fd)) return { status: CODE_TO_STATUS.EBADF };\n this.fdTable.delete(fd);\n return { status: 0 };\n }\n\n // ---- FREAD ----\n fread(fd: number, length: number, position: number | null): { status: number; data: Uint8Array | null } {\n const entry = this.fdTable.get(fd);\n if (!entry) return { status: CODE_TO_STATUS.EBADF, data: null };\n\n const inode = this.readInode(entry.inodeIdx);\n const pos = position ?? entry.position;\n const readLen = Math.min(length, inode.size - pos);\n\n if (readLen <= 0) return { status: 0, data: new Uint8Array(0) };\n\n // Read from specific offset within the file's data blocks\n const dataOffset = this.dataOffset + inode.firstBlock * this.blockSize + pos;\n const buf = new Uint8Array(readLen);\n this.handle.read(buf, { at: dataOffset });\n\n // Update position\n if (position === null) {\n entry.position += readLen;\n }\n\n return { status: 0, data: buf };\n }\n\n // ---- FWRITE ----\n fwrite(fd: number, data: Uint8Array, position: number | null): { status: number; data: Uint8Array | null } {\n const entry = this.fdTable.get(fd);\n if (!entry) return { status: CODE_TO_STATUS.EBADF, data: null };\n\n const inode = this.readInode(entry.inodeIdx);\n const isAppend = (entry.flags & 1024) !== 0; // O_APPEND\n const pos = isAppend ? inode.size : (position ?? entry.position);\n const endPos = pos + data.byteLength;\n\n // Check if we need to grow\n if (endPos > inode.size) {\n const neededBlocks = Math.ceil(endPos / this.blockSize);\n if (neededBlocks > inode.blockCount) {\n // Grow — read old data, reallocate, write back\n const oldData = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n const newFirst = this.allocateBlocks(neededBlocks);\n const newBuf = new Uint8Array(endPos);\n newBuf.set(oldData);\n newBuf.set(data, pos);\n this.writeData(newFirst, newBuf);\n inode.firstBlock = newFirst;\n inode.blockCount = neededBlocks;\n } else {\n // Fits, write at position\n const dataOffset = this.dataOffset + inode.firstBlock * this.blockSize + pos;\n this.handle.write(data, { at: dataOffset });\n }\n inode.size = endPos;\n } else {\n // Write within existing bounds\n const dataOffset = this.dataOffset + inode.firstBlock * this.blockSize + pos;\n this.handle.write(data, { at: dataOffset });\n }\n\n inode.mtime = Date.now();\n this.writeInode(entry.inodeIdx, inode);\n\n // Update position\n if (position === null) {\n entry.position = endPos;\n }\n\n this.commitPending();\n const buf = new Uint8Array(4);\n new DataView(buf.buffer).setUint32(0, data.byteLength, true);\n return { status: 0, data: buf };\n }\n\n // ---- FSTAT ----\n fstat(fd: number): { status: number; data: Uint8Array | null } {\n const entry = this.fdTable.get(fd);\n if (!entry) return { status: CODE_TO_STATUS.EBADF, data: null };\n return this.encodeStatResponse(entry.inodeIdx);\n }\n\n // ---- FTRUNCATE ----\n ftruncate(fd: number, len: number = 0): { status: number } {\n const entry = this.fdTable.get(fd);\n if (!entry) return { status: CODE_TO_STATUS.EBADF };\n\n const inode = this.readInode(entry.inodeIdx);\n const path = this.readPath(inode.pathOffset, inode.pathLength);\n return this.truncate(path, len);\n }\n\n // ---- FSYNC ----\n fsync(): { status: number } {\n this.commitPending();\n this.handle.flush();\n return { status: 0 };\n }\n\n // ---- OPENDIR ----\n opendir(path: string, tabId: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n const inode = this.readInode(idx);\n if (inode.type !== INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.ENOTDIR, data: null };\n\n // Use fd table for dir handles too\n const fd = this.nextFd++;\n this.fdTable.set(fd, { tabId, inodeIdx: idx, position: 0, flags: 0 });\n\n const buf = new Uint8Array(4);\n new DataView(buf.buffer).setUint32(0, fd, true);\n return { status: 0, data: buf };\n }\n\n // ---- MKDTEMP ----\n mkdtemp(prefix: string): { status: number; data: Uint8Array | null } {\n const suffix = Math.random().toString(36).substring(2, 8);\n const path = this.normalizePath(prefix + suffix);\n\n // Ensure parent directories exist\n const parentStatus = this.ensureParent(path);\n if (parentStatus !== 0) {\n // Auto-create parent directories for mkdtemp\n const parentPath = path.substring(0, path.lastIndexOf('/'));\n if (parentPath) {\n this.mkdirRecursive(parentPath);\n }\n }\n\n const mode = DEFAULT_DIR_MODE & ~(this.umask & 0o777);\n this.createInode(path, INODE_TYPE.DIRECTORY, mode, 0);\n\n this.commitPending();\n return { status: 0, data: encoder.encode(path) };\n }\n\n // ========== Helpers ==========\n\n private getDirectChildren(dirPath: string): string[] {\n const prefix = dirPath === '/' ? '/' : dirPath + '/';\n const children: string[] = [];\n\n for (const path of this.pathIndex.keys()) {\n if (path === dirPath) continue;\n if (!path.startsWith(prefix)) continue;\n // Direct child: no more slashes after prefix\n const rest = path.substring(prefix.length);\n if (!rest.includes('/')) {\n children.push(path);\n }\n }\n\n return children.sort();\n }\n\n private getAllDescendants(dirPath: string): string[] {\n const prefix = dirPath === '/' ? '/' : dirPath + '/';\n const descendants: string[] = [];\n\n for (const path of this.pathIndex.keys()) {\n if (path.startsWith(prefix)) descendants.push(path);\n }\n\n // Sort by depth (deepest first) for safe deletion\n return descendants.sort((a, b) => {\n const da = a.split('/').length;\n const db = b.split('/').length;\n return db - da;\n });\n }\n\n private ensureParent(path: string): number {\n const lastSlash = path.lastIndexOf('/');\n if (lastSlash <= 0) return 0; // Parent is root, always exists\n\n const parentPath = path.substring(0, lastSlash);\n const parentIdx = this.pathIndex.get(parentPath);\n if (parentIdx === undefined) return CODE_TO_STATUS.ENOENT;\n\n const parentInode = this.readInode(parentIdx);\n if (parentInode.type !== INODE_TYPE.DIRECTORY) return CODE_TO_STATUS.ENOTDIR;\n\n return 0;\n }\n\n /** Clean up all fds owned by a tab */\n cleanupTab(tabId: string): void {\n for (const [fd, entry] of this.fdTable) {\n if (entry.tabId === tabId) {\n this.fdTable.delete(fd);\n }\n }\n }\n\n /** Get all file paths and their data for OPFS sync */\n getAllFiles(): { path: string; idx: number }[] {\n const files: { path: string; idx: number }[] = [];\n for (const [path, idx] of this.pathIndex) {\n files.push({ path, idx });\n }\n return files;\n }\n\n /** Get file path for a file descriptor (used by OPFS sync for FD-based ops) */\n getPathForFd(fd: number): string | null {\n const entry = this.fdTable.get(fd);\n if (!entry) return null;\n const inode = this.readInode(entry.inodeIdx);\n return this.readPath(inode.pathOffset, inode.pathLength);\n }\n\n /** Get file data by inode index */\n getInodeData(idx: number): { type: number; data: Uint8Array; mtime: number } {\n const inode = this.readInode(idx);\n const data = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n return { type: inode.type, data, mtime: inode.mtime };\n }\n\n /** Export all files/dirs/symlinks from the VFS */\n exportAll(): Array<{ path: string; type: number; data: Uint8Array | null; mode: number; mtime: number }> {\n const result: Array<{ path: string; type: number; data: Uint8Array | null; mode: number; mtime: number }> = [];\n for (const [path, idx] of this.pathIndex) {\n const inode = this.readInode(idx);\n let data: Uint8Array | null = null;\n if (inode.type === INODE_TYPE.FILE || inode.type === INODE_TYPE.SYMLINK) {\n data = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n }\n result.push({ path, type: inode.type, data, mode: inode.mode, mtime: inode.mtime });\n }\n // Sort directories first so parents are created before children\n result.sort((a, b) => {\n if (a.type === INODE_TYPE.DIRECTORY && b.type !== INODE_TYPE.DIRECTORY) return -1;\n if (a.type !== INODE_TYPE.DIRECTORY && b.type === INODE_TYPE.DIRECTORY) return 1;\n return a.path.localeCompare(b.path);\n });\n return result;\n }\n\n flush(): void {\n this.handle.flush();\n }\n}\n","/**\n * Binary protocol operation codes and header encoding/decoding.\n * All inter-worker messages use this minimal binary protocol — no JSON, no strings.\n */\n\n// Operation codes\nexport const OP = {\n READ: 1,\n WRITE: 2,\n UNLINK: 3,\n STAT: 4,\n LSTAT: 5,\n MKDIR: 6,\n RMDIR: 7,\n READDIR: 8,\n RENAME: 9,\n EXISTS: 10,\n TRUNCATE: 11,\n APPEND: 12,\n COPY: 13,\n ACCESS: 14,\n REALPATH: 15,\n CHMOD: 16,\n CHOWN: 17,\n UTIMES: 18,\n SYMLINK: 19,\n READLINK: 20,\n LINK: 21,\n OPEN: 22,\n CLOSE: 23,\n FREAD: 24,\n FWRITE: 25,\n FSTAT: 26,\n FTRUNCATE: 27,\n FSYNC: 28,\n OPENDIR: 29,\n MKDTEMP: 30,\n} as const;\n\nexport type OpCode = (typeof OP)[keyof typeof OP];\n\n// Response status codes\nexport const STATUS = {\n OK: 0,\n ENOENT: 1,\n EEXIST: 2,\n EISDIR: 3,\n ENOTDIR: 4,\n ENOTEMPTY: 5,\n EACCES: 6,\n EINVAL: 7,\n EBADF: 8,\n ELOOP: 9,\n ENOSPC: 10,\n} as const;\n\n// SAB layout offsets\nexport const SAB_OFFSETS = {\n CONTROL: 0, // Int32 - signal (0=idle, 1=request, 2=response, 3=chunk, 4=ack)\n OPCODE: 4, // Int32 - operation code\n STATUS: 8, // Int32 - response status / error\n CHUNK_LEN: 12, // Int32 - bytes in this chunk\n TOTAL_LEN: 16, // BigUint64 - full data size across all chunks\n CHUNK_IDX: 24, // Int32 - 0-based chunk index\n RESERVED: 28, // Int32 - reserved\n HEADER_SIZE: 32, // Data payload starts here\n} as const;\n\n// SAB control signals\nexport const SIGNAL = {\n IDLE: 0,\n REQUEST: 1,\n RESPONSE: 2,\n CHUNK: 3,\n CHUNK_ACK: 4,\n} as const;\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\n\n/**\n * Encode a request into an ArrayBuffer for MessageChannel transfer.\n *\n * Request format (16-byte header + path + data):\n * bytes 0-3: operation (uint32)\n * bytes 4-7: flags (uint32)\n * bytes 8-11: pathLen (uint32)\n * bytes 12-15: dataLen (uint32)\n * bytes 16+: path (UTF-8)\n * bytes 16+pathLen: data payload\n */\nexport function encodeRequest(\n op: number,\n path: string,\n flags: number = 0,\n data?: Uint8Array\n): ArrayBuffer {\n const pathBytes = encoder.encode(path);\n const dataLen = data ? data.byteLength : 0;\n const totalLen = 16 + pathBytes.byteLength + dataLen;\n const buf = new ArrayBuffer(totalLen);\n const view = new DataView(buf);\n\n view.setUint32(0, op, true);\n view.setUint32(4, flags, true);\n view.setUint32(8, pathBytes.byteLength, true);\n view.setUint32(12, dataLen, true);\n\n const bytes = new Uint8Array(buf);\n bytes.set(pathBytes, 16);\n if (data) {\n bytes.set(data, 16 + pathBytes.byteLength);\n }\n\n return buf;\n}\n\n/**\n * Decode a request ArrayBuffer.\n */\nexport function decodeRequest(buf: ArrayBuffer): {\n op: number;\n flags: number;\n path: string;\n data: Uint8Array | null;\n} {\n const view = new DataView(buf);\n const op = view.getUint32(0, true);\n const flags = view.getUint32(4, true);\n const pathLen = view.getUint32(8, true);\n const dataLen = view.getUint32(12, true);\n\n const bytes = new Uint8Array(buf);\n const path = decoder.decode(bytes.subarray(16, 16 + pathLen));\n const data = dataLen > 0\n ? bytes.subarray(16 + pathLen, 16 + pathLen + dataLen)\n : null;\n\n return { op, flags, path, data };\n}\n\n/**\n * Encode a response into an ArrayBuffer.\n *\n * Response format (8-byte header + data):\n * bytes 0-3: status (uint32)\n * bytes 4-7: dataLen (uint32)\n * bytes 8+: data payload\n */\nexport function encodeResponse(status: number, data?: Uint8Array): ArrayBuffer {\n const dataLen = data ? data.byteLength : 0;\n const buf = new ArrayBuffer(8 + dataLen);\n const view = new DataView(buf);\n\n view.setUint32(0, status, true);\n view.setUint32(4, dataLen, true);\n\n if (data) {\n new Uint8Array(buf).set(data, 8);\n }\n\n return buf;\n}\n\n/**\n * Decode a response ArrayBuffer.\n */\nexport function decodeResponse(buf: ArrayBuffer): {\n status: number;\n data: Uint8Array | null;\n} {\n const view = new DataView(buf);\n const status = view.getUint32(0, true);\n const dataLen = view.getUint32(4, true);\n\n const data = dataLen > 0\n ? new Uint8Array(buf, 8, dataLen)\n : null;\n\n return { status, data };\n}\n\n/**\n * Encode a two-path request (rename, copy, symlink, link).\n * Data payload contains: [pathLen2:u32] [path2 bytes]\n */\nexport function encodeTwoPathRequest(\n op: number,\n path1: string,\n path2: string,\n flags: number = 0\n): ArrayBuffer {\n const path2Bytes = encoder.encode(path2);\n const payload = new Uint8Array(4 + path2Bytes.byteLength);\n const pv = new DataView(payload.buffer);\n pv.setUint32(0, path2Bytes.byteLength, true);\n payload.set(path2Bytes, 4);\n\n return encodeRequest(op, path1, flags, payload);\n}\n\n/**\n * Decode the second path from a two-path request's data payload.\n */\nexport function decodeSecondPath(data: Uint8Array): string {\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const pathLen = view.getUint32(0, true);\n return decoder.decode(data.subarray(4, 4 + pathLen));\n}\n","/**\n * Server Worker — the VFS file handle owner.\n *\n * This worker is the ONLY entity that opens sync file handles.\n * It receives binary requests from client workers via MessageChannel\n * ports and dispatches to the VFS engine.\n *\n * Critical performance rules:\n * 1. Only receives and sends ArrayBuffers — no JSON, no strings\n * 2. Only does sync file operations\n * 3. Minimal work — decode header, execute op, encode response\n * 4. Zero-copy transfers on all MessageChannel communication\n * 5. No encoding/decoding — that is the client's responsibility\n * 6. Handles stay open — never close/reopen during normal operation\n */\n\nimport { VFSEngine } from '../vfs/engine.js';\nimport { decodeRequest, decodeSecondPath, encodeResponse, OP } from '../protocol/opcodes.js';\n\nconst engine = new VFSEngine();\n\n// Map of tabId → received port (from client workers via Service Worker)\nconst ports = new Map<string, MessagePort>();\n\n// OPFS Sync Worker port (optional)\nlet opfsSyncPort: MessagePort | null = null;\n\n// Config received from spawning tab\nlet config: {\n root: string;\n opfsSync: boolean;\n uid: number;\n gid: number;\n umask: number;\n strictPermissions: boolean;\n} = {\n root: '/',\n opfsSync: true,\n uid: 0,\n gid: 0,\n umask: 0o022,\n strictPermissions: false,\n};\n\n/**\n * Handle a binary request from a client worker.\n */\nfunction handleRequest(tabId: string, buffer: ArrayBuffer): ArrayBuffer {\n const { op, flags, path, data } = decodeRequest(buffer);\n\n let result: { status: number; data?: Uint8Array | null };\n\n switch (op) {\n case OP.READ:\n result = engine.read(path);\n break;\n\n case OP.WRITE:\n result = engine.write(path, data ?? new Uint8Array(0), flags);\n notifyOPFSSync('write', path, data);\n break;\n\n case OP.APPEND:\n result = engine.append(path, data ?? new Uint8Array(0));\n notifyOPFSSync('write', path, data);\n break;\n\n case OP.UNLINK:\n result = engine.unlink(path);\n notifyOPFSSync('delete', path);\n break;\n\n case OP.STAT:\n result = engine.stat(path);\n break;\n\n case OP.LSTAT:\n result = engine.lstat(path);\n break;\n\n case OP.MKDIR:\n result = engine.mkdir(path, flags);\n notifyOPFSSync('mkdir', path);\n break;\n\n case OP.RMDIR:\n result = engine.rmdir(path, flags);\n notifyOPFSSync('delete', path);\n break;\n\n case OP.READDIR:\n result = engine.readdir(path, flags);\n break;\n\n case OP.RENAME: {\n const newPath = data ? decodeSecondPath(data) : '';\n result = engine.rename(path, newPath);\n notifyOPFSSync('rename', path, undefined, newPath);\n break;\n }\n\n case OP.EXISTS:\n result = engine.exists(path);\n break;\n\n case OP.TRUNCATE: {\n const len = data ? new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true) : 0;\n result = engine.truncate(path, len);\n break;\n }\n\n case OP.COPY: {\n const destPath = data ? decodeSecondPath(data) : '';\n result = engine.copy(path, destPath, flags);\n break;\n }\n\n case OP.ACCESS:\n result = engine.access(path, flags);\n break;\n\n case OP.REALPATH:\n result = engine.realpath(path);\n break;\n\n case OP.CHMOD: {\n const mode = data ? new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true) : 0;\n result = engine.chmod(path, mode);\n break;\n }\n\n case OP.CHOWN: {\n if (!data || data.byteLength < 8) {\n result = { status: 7 }; // EINVAL\n break;\n }\n const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const uid = dv.getUint32(0, true);\n const gid = dv.getUint32(4, true);\n result = engine.chown(path, uid, gid);\n break;\n }\n\n case OP.UTIMES: {\n if (!data || data.byteLength < 16) {\n result = { status: 7 }; // EINVAL\n break;\n }\n const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const atime = dv.getFloat64(0, true);\n const mtime = dv.getFloat64(8, true);\n result = engine.utimes(path, atime, mtime);\n break;\n }\n\n case OP.SYMLINK: {\n const target = data ? new TextDecoder().decode(data) : '';\n result = engine.symlink(target, path);\n break;\n }\n\n case OP.READLINK:\n result = engine.readlink(path);\n break;\n\n case OP.LINK: {\n const newPath = data ? decodeSecondPath(data) : '';\n result = engine.link(path, newPath);\n break;\n }\n\n case OP.OPEN: {\n result = engine.open(path, flags, tabId);\n break;\n }\n\n case OP.CLOSE: {\n const fd = data ? new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true) : 0;\n result = engine.close(fd);\n break;\n }\n\n case OP.FREAD: {\n if (!data || data.byteLength < 12) {\n result = { status: 7 }; // EINVAL\n break;\n }\n const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const fd = dv.getUint32(0, true);\n const length = dv.getUint32(4, true);\n const pos = dv.getInt32(8, true);\n result = engine.fread(fd, length, pos === -1 ? null : pos);\n break;\n }\n\n case OP.FWRITE: {\n if (!data || data.byteLength < 8) {\n result = { status: 7 }; // EINVAL\n break;\n }\n const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const fd = dv.getUint32(0, true);\n const pos = dv.getInt32(4, true);\n const writeData = data.subarray(8);\n result = engine.fwrite(fd, writeData, pos === -1 ? null : pos);\n break;\n }\n\n case OP.FSTAT: {\n const fd = data ? new DataView(data.buffer, data.byteOffset, data.byteLength).getUint32(0, true) : 0;\n result = engine.fstat(fd);\n break;\n }\n\n case OP.FTRUNCATE: {\n if (!data || data.byteLength < 8) {\n result = { status: 7 };\n break;\n }\n const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const fd = dv.getUint32(0, true);\n const len = dv.getUint32(4, true);\n result = engine.ftruncate(fd, len);\n break;\n }\n\n case OP.FSYNC:\n result = engine.fsync();\n break;\n\n case OP.OPENDIR:\n result = engine.opendir(path, tabId);\n break;\n\n case OP.MKDTEMP:\n result = engine.mkdtemp(path);\n break;\n\n default:\n result = { status: 7 }; // EINVAL — unknown op\n }\n\n const responseData = result.data instanceof Uint8Array ? result.data : undefined;\n return encodeResponse(result.status, responseData);\n}\n\n/** Notify OPFS sync worker of a VFS mutation */\nfunction notifyOPFSSync(\n op: 'write' | 'delete' | 'mkdir' | 'rename',\n path: string,\n data?: Uint8Array | null,\n newPath?: string\n): void {\n if (!opfsSyncPort) return;\n\n const msg: Record<string, unknown> = { op, path, ts: Date.now() };\n const transfers: ArrayBuffer[] = [];\n\n if (op === 'write' && data) {\n // Copy data for transfer (original may be reused)\n const copy = data.slice().buffer;\n msg.data = copy;\n transfers.push(copy);\n }\n\n if (op === 'rename' && newPath) {\n msg.newPath = newPath;\n }\n\n opfsSyncPort.postMessage(msg, transfers);\n}\n\n/** Set up a client port for a specific tab */\nfunction setupClientPort(tabId: string, port: MessagePort): void {\n ports.set(tabId, port);\n\n port.onmessage = (e: MessageEvent) => {\n const { buffer, id } = e.data;\n\n if (buffer instanceof ArrayBuffer) {\n const response = handleRequest(tabId, buffer);\n port.postMessage({ id, buffer: response }, [response]);\n }\n };\n\n port.start();\n}\n\n/** Handle tab death — clean up resources */\nfunction onTabLost(tabId: string): void {\n engine.cleanupTab(tabId);\n const port = ports.get(tabId);\n if (port) {\n port.close();\n ports.delete(tabId);\n }\n}\n\n// ========== Initialization ==========\n\nasync function init(initData: {\n root: string;\n opfsSync: boolean;\n uid: number;\n gid: number;\n umask: number;\n strictPermissions: boolean;\n}): Promise<void> {\n config = initData;\n\n // Get OPFS root\n let rootDir = await navigator.storage.getDirectory();\n\n // Navigate to configured root\n if (config.root && config.root !== '/') {\n const segments = config.root.split('/').filter(Boolean);\n for (const segment of segments) {\n rootDir = await rootDir.getDirectoryHandle(segment, { create: true });\n }\n }\n\n // Open VFS binary file\n const vfsFileHandle = await rootDir.getFileHandle('.vfs.bin', { create: true });\n const vfsHandle = await vfsFileHandle.createSyncAccessHandle();\n\n // Initialize VFS engine\n engine.init(vfsHandle, {\n uid: config.uid,\n gid: config.gid,\n umask: config.umask,\n strictPermissions: config.strictPermissions,\n });\n}\n\n// ========== Message handling (from sync relay worker in same tab) ==========\n\nself.onmessage = async (e: MessageEvent) => {\n const msg = e.data;\n\n if (msg.type === 'init') {\n await init(msg.config);\n (self as unknown as Worker).postMessage({ type: 'ready' });\n return;\n }\n\n if (msg.type === 'port') {\n // Receive a client port (transferred from service worker or direct)\n setupClientPort(msg.tabId, msg.port);\n return;\n }\n\n if (msg.type === 'tab-lost') {\n onTabLost(msg.tabId);\n return;\n }\n\n if (msg.type === 'opfs-sync-port') {\n opfsSyncPort = msg.port;\n opfsSyncPort!.start();\n return;\n }\n\n // Direct request (from same-tab sync worker, uses buffer + id)\n if (msg.buffer instanceof ArrayBuffer) {\n const tabId = msg.tabId || 'local';\n const response = handleRequest(tabId, msg.buffer);\n (self as unknown as Worker).postMessage(\n { id: msg.id, buffer: response },\n [response]\n );\n }\n};\n"],"mappings":";AAQO,IAAM,YAAY;AAClB,IAAM,cAAc;AAGpB,IAAM,qBAAqB;AAC3B,IAAM,sBAAsB;AAC5B,IAAM,aAAa;AAGnB,IAAM,aAAa;AAAA,EACxB,MAAM;AAAA,EACN,OAAO;AAAA;AAAA,EACP,SAAS;AAAA;AAAA,EACT,aAAa;AAAA;AAAA,EACb,YAAY;AAAA;AAAA,EACZ,cAAc;AAAA;AAAA,EACd,aAAa;AAAA;AAAA,EACb,cAAc;AAAA;AAAA,EACd,aAAa;AAAA;AAAA,EACb,aAAa;AAAA;AAAA,EACb,eAAe;AAAA;AAAA,EACf,WAAW;AAAA;AAAA,EACX,UAAU;AAAA;AACZ;AAGO,IAAM,QAAQ;AAAA,EACnB,MAAM;AAAA;AAAA,EACN,OAAO;AAAA;AAAA,EACP,aAAa;AAAA;AAAA,EACb,aAAa;AAAA;AAAA,EACb,aAAa;AAAA;AAAA,EACb,MAAM;AAAA;AAAA,EACN,MAAM;AAAA;AAAA,EACN,aAAa;AAAA;AAAA,EACb,aAAa;AAAA;AAAA,EACb,OAAO;AAAA;AAAA,EACP,OAAO;AAAA;AAAA,EACP,OAAO;AAAA;AAAA,EACP,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AACP;AAGO,IAAM,aAAa;AAAA,EACxB,MAAM;AAAA,EACN,MAAM;AAAA,EACN,WAAW;AAAA,EACX,SAAS;AACX;AAGO,IAAM,oBAAoB;AAC1B,IAAM,mBAAmB;AACzB,IAAM,uBAAuB;AAC7B,IAAM,gBAAgB;AAGtB,IAAM,SAAS;AAMf,IAAM,oBAAoB;AAM1B,IAAM,0BAA0B,MAAM;AAGtC,IAAM,sBAAsB;AAK5B,SAAS,gBAAgB,aAAqB,qBAAqB,YAAoB,oBAAoB,cAAsB,qBAAqB;AAC3J,QAAM,mBAAmB,WAAW;AACpC,QAAM,iBAAiB,aAAa;AACpC,QAAM,kBAAkB,mBAAmB;AAC3C,QAAM,gBAAgB;AACtB,QAAM,eAAe,kBAAkB;AACvC,QAAM,aAAa,KAAK,KAAK,cAAc,CAAC;AAE5C,QAAM,aAAa,KAAK,MAAM,eAAe,cAAc,SAAS,IAAI;AACxE,QAAM,YAAY,aAAa,cAAc;AAE7C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACxDO,IAAM,iBAAyC;AAAA,EACpD,IAAI;AAAA,EACJ,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ;AACV;;;AC/CA,IAAM,UAAU,IAAI,YAAY;AAChC,IAAM,UAAU,IAAI,YAAY;AAwBzB,IAAM,YAAN,MAAgB;AAAA,EACb;AAAA,EACA,YAAY,oBAAI,IAAoB;AAAA;AAAA,EACpC,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,aAAa;AAAA,EACb,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,aAAa;AAAA,EACb,oBAAoB;AAAA,EACpB,QAAQ;AAAA;AAAA,EAGR,UAAU,oBAAI,IAAqB;AAAA,EACnC,SAAS;AAAA;AAAA;AAAA,EAGT,WAAW,IAAI,WAAW,UAAU;AAAA,EACpC,YAAY,IAAI,SAAS,KAAK,SAAS,MAAM;AAAA;AAAA,EAG7C,aAAa,oBAAI,IAAmB;AAAA,EACpC,gBAAgB,IAAI,WAAW,WAAW,IAAI;AAAA,EAC9C,iBAAiB,IAAI,SAAS,KAAK,cAAc,MAAM;AAAA;AAAA,EAGvD,SAA4B;AAAA,EAC5B,gBAAgB;AAAA;AAAA,EAChB,gBAAgB;AAAA;AAAA,EAChB,kBAAkB;AAAA;AAAA,EAGlB,gBAAgB;AAAA,EAExB,KACE,QACA,MACM;AACN,SAAK,SAAS;AACd,SAAK,aAAa,MAAM,OAAO;AAC/B,SAAK,aAAa,MAAM,OAAO;AAC/B,SAAK,QAAQ,MAAM,SAAS;AAC5B,SAAK,oBAAoB,MAAM,qBAAqB;AACpD,SAAK,QAAQ,MAAM,SAAS;AAE5B,UAAM,OAAO,OAAO,QAAQ;AAE5B,QAAI,SAAS,GAAG;AACd,WAAK,OAAO;AAAA,IACd,OAAO;AACL,WAAK,MAAM;AAAA,IACb;AAAA,EACF;AAAA;AAAA,EAGA,cAAoB;AAClB,QAAI;AACF,WAAK,QAAQ,MAAM;AAAA,IACrB,SAAS,GAAG;AAAA,IAEZ;AAAA,EACF;AAAA;AAAA,EAGQ,SAAe;AACrB,UAAM,SAAS,gBAAgB,qBAAqB,oBAAoB,mBAAmB;AAE3F,SAAK,aAAa;AAClB,SAAK,YAAY;AACjB,SAAK,cAAc,OAAO;AAC1B,SAAK,aAAa,OAAO;AACzB,SAAK,mBAAmB,OAAO;AAC/B,SAAK,kBAAkB,OAAO;AAC9B,SAAK,gBAAgB,OAAO;AAC5B,SAAK,gBAAgB;AACrB,SAAK,eAAe,OAAO;AAC3B,SAAK,aAAa,OAAO;AAGzB,SAAK,OAAO,SAAS,OAAO,SAAS;AAGrC,SAAK,gBAAgB;AAGrB,UAAM,UAAU,IAAI,WAAW,OAAO,cAAc;AACpD,SAAK,OAAO,MAAM,SAAS,EAAE,IAAI,KAAK,iBAAiB,CAAC;AAGxD,SAAK,SAAS,IAAI,WAAW,OAAO,UAAU;AAC9C,SAAK,OAAO,MAAM,KAAK,QAAQ,EAAE,IAAI,KAAK,aAAa,CAAC;AAGxD,SAAK,YAAY,KAAK,WAAW,WAAW,kBAAkB,CAAC;AAG/D,SAAK,gBAAgB;AACrB,SAAK,OAAO,MAAM;AAAA,EACpB;AAAA;AAAA,EAGQ,QAAc;AACpB,UAAM,WAAW,KAAK,OAAO,QAAQ;AACrC,QAAI,WAAW,WAAW,MAAM;AAC9B,YAAM,IAAI,MAAM,gCAAgC,QAAQ,yBAAyB,WAAW,IAAI,GAAG;AAAA,IACrG;AAEA,SAAK,OAAO,KAAK,KAAK,eAAe,EAAE,IAAI,EAAE,CAAC;AAC9C,UAAM,IAAI,KAAK;AAGf,UAAM,QAAQ,EAAE,UAAU,WAAW,OAAO,IAAI;AAChD,QAAI,UAAU,WAAW;AACvB,YAAM,IAAI,MAAM,4BAA4B,MAAM,SAAS,EAAE,CAAC,gBAAgB,UAAU,SAAS,EAAE,CAAC,GAAG;AAAA,IACzG;AAGA,UAAM,UAAU,EAAE,UAAU,WAAW,SAAS,IAAI;AACpD,QAAI,YAAY,aAAa;AAC3B,YAAM,IAAI,MAAM,oCAAoC,OAAO,cAAc,WAAW,GAAG;AAAA,IACzF;AAGA,UAAM,aAAa,EAAE,UAAU,WAAW,aAAa,IAAI;AAC3D,UAAM,YAAY,EAAE,UAAU,WAAW,YAAY,IAAI;AACzD,UAAM,cAAc,EAAE,UAAU,WAAW,cAAc,IAAI;AAC7D,UAAM,aAAa,EAAE,UAAU,WAAW,aAAa,IAAI;AAC3D,UAAM,mBAAmB,EAAE,WAAW,WAAW,cAAc,IAAI;AACnE,UAAM,kBAAkB,EAAE,WAAW,WAAW,aAAa,IAAI;AACjE,UAAM,aAAa,EAAE,WAAW,WAAW,aAAa,IAAI;AAC5D,UAAM,eAAe,EAAE,WAAW,WAAW,eAAe,IAAI;AAChE,UAAM,WAAW,EAAE,UAAU,WAAW,WAAW,IAAI;AAGvD,QAAI,cAAc,MAAM,YAAa,YAAY,OAAQ,GAAG;AAC1D,YAAM,IAAI,MAAM,mCAAmC,SAAS,uBAAuB;AAAA,IACrF;AACA,QAAI,eAAe,GAAG;AACpB,YAAM,IAAI,MAAM,+BAA+B;AAAA,IACjD;AACA,QAAI,aAAa,aAAa;AAC5B,YAAM,IAAI,MAAM,6BAA6B,UAAU,2BAA2B,WAAW,GAAG;AAAA,IAClG;AAGA,QAAI,qBAAqB,WAAW,MAAM;AACxC,YAAM,IAAI,MAAM,mCAAmC,gBAAgB,cAAc,WAAW,IAAI,GAAG;AAAA,IACrG;AACA,UAAM,qBAAqB,mBAAmB,aAAa;AAC3D,QAAI,oBAAoB,oBAAoB;AAC1C,YAAM,IAAI,MAAM,kCAAkC,eAAe,cAAc,kBAAkB,GAAG;AAAA,IACtG;AACA,QAAI,gBAAgB,iBAAiB;AACnC,YAAM,IAAI,MAAM,8BAA8B,YAAY,6BAA6B,eAAe,EAAE;AAAA,IAC1G;AACA,QAAI,cAAc,cAAc;AAC9B,YAAM,IAAI,MAAM,4BAA4B,UAAU,yBAAyB,YAAY,EAAE;AAAA,IAC/F;AACA,UAAM,gBAAgB,eAAe;AACrC,QAAI,WAAW,eAAe;AAC5B,YAAM,IAAI,MAAM,2BAA2B,QAAQ,8BAA8B,aAAa,GAAG;AAAA,IACnG;AAGA,UAAM,kBAAkB,aAAa,cAAc;AACnD,QAAI,WAAW,iBAAiB;AAC9B,YAAM,IAAI,MAAM,0BAA0B,QAAQ,+BAA+B,eAAe,GAAG;AAAA,IACrG;AAGA,SAAK,aAAa;AAClB,SAAK,YAAY;AACjB,SAAK,cAAc;AACnB,SAAK,aAAa;AAClB,SAAK,mBAAmB;AACxB,SAAK,kBAAkB;AACvB,SAAK,aAAa;AAClB,SAAK,eAAe;AACpB,SAAK,gBAAgB;AACrB,SAAK,gBAAgB;AAGrB,UAAM,aAAa,KAAK,KAAK,KAAK,cAAc,CAAC;AACjD,SAAK,SAAS,IAAI,WAAW,UAAU;AACvC,SAAK,OAAO,KAAK,KAAK,QAAQ,EAAE,IAAI,KAAK,aAAa,CAAC;AAEvD,SAAK,aAAa;AAGlB,QAAI,CAAC,KAAK,UAAU,IAAI,GAAG,GAAG;AAC5B,YAAM,IAAI,MAAM,0DAA0D;AAAA,IAC5E;AAAA,EACF;AAAA,EAEQ,kBAAwB;AAC9B,UAAM,IAAI,KAAK;AACf,MAAE,UAAU,WAAW,OAAO,WAAW,IAAI;AAC7C,MAAE,UAAU,WAAW,SAAS,aAAa,IAAI;AACjD,MAAE,UAAU,WAAW,aAAa,KAAK,YAAY,IAAI;AACzD,MAAE,UAAU,WAAW,YAAY,KAAK,WAAW,IAAI;AACvD,MAAE,UAAU,WAAW,cAAc,KAAK,aAAa,IAAI;AAC3D,MAAE,UAAU,WAAW,aAAa,KAAK,YAAY,IAAI;AACzD,MAAE,WAAW,WAAW,cAAc,KAAK,kBAAkB,IAAI;AACjE,MAAE,WAAW,WAAW,aAAa,KAAK,iBAAiB,IAAI;AAC/D,MAAE,WAAW,WAAW,aAAa,KAAK,YAAY,IAAI;AAC1D,MAAE,WAAW,WAAW,eAAe,KAAK,cAAc,IAAI;AAC9D,MAAE,UAAU,WAAW,WAAW,KAAK,eAAe,IAAI;AAC1D,SAAK,OAAO,MAAM,KAAK,eAAe,EAAE,IAAI,EAAE,CAAC;AAAA,EACjD;AAAA;AAAA,EAGQ,gBAAgB,IAAY,IAAkB;AACpD,QAAI,KAAK,KAAK,cAAe,MAAK,gBAAgB;AAClD,QAAI,KAAK,KAAK,cAAe,MAAK,gBAAgB;AAAA,EACpD;AAAA,EAEQ,gBAAsB;AAE5B,QAAI,KAAK,sBAAsB;AAC7B,WAAK,mBAAmB;AACxB,WAAK,uBAAuB;AAAA,IAC9B;AAEA,QAAI,KAAK,iBAAiB,GAAG;AAC3B,YAAM,KAAK,KAAK;AAChB,YAAM,KAAK,KAAK;AAChB,WAAK,OAAO,MAAM,KAAK,OAAQ,SAAS,IAAI,KAAK,CAAC,GAAG,EAAE,IAAI,KAAK,eAAe,GAAG,CAAC;AACnF,WAAK,gBAAgB;AACrB,WAAK,gBAAgB;AAAA,IACvB;AACA,QAAI,KAAK,iBAAiB;AACxB,WAAK,gBAAgB;AACrB,WAAK,kBAAkB;AAAA,IACzB;AAAA,EACF;AAAA;AAAA;AAAA,EAIQ,qBAA2B;AACjC,UAAM,SAAS,KAAK;AAGpB,QAAI,WAAW;AACf,aAAS,UAAU,KAAK,KAAK,KAAK,cAAc,CAAC,IAAI,GAAG,WAAW,GAAG,WAAW;AAC/E,UAAI,OAAO,OAAO,MAAM,GAAG;AAEzB,iBAAS,MAAM,GAAG,OAAO,GAAG,OAAO;AACjC,gBAAM,WAAW,UAAU,IAAI;AAC/B,cAAI,WAAW,KAAK,eAAgB,OAAO,OAAO,IAAK,KAAK,KAAO;AACjE,uBAAW;AACX;AAAA,UACF;AAAA,QACF;AACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,WAAW,KAAK,IAAI,WAAW,GAAG,mBAAmB;AAC3D,QAAI,YAAY,KAAK,YAAa;AAGlC,SAAK,OAAO,SAAS,KAAK,aAAa,WAAW,KAAK,SAAS;AAGhE,UAAM,gBAAgB,KAAK,KAAK,WAAW,CAAC;AAC5C,SAAK,SAAS,OAAO,MAAM,GAAG,aAAa;AAG3C,UAAM,UAAU,KAAK,cAAc;AACnC,SAAK,cAAc;AACnB,SAAK,cAAc;AACnB,SAAK,kBAAkB;AAGvB,SAAK,gBAAgB;AACrB,SAAK,gBAAgB,gBAAgB;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAqB;AAC3B,SAAK,UAAU,MAAM;AACrB,SAAK,WAAW,MAAM;AAGtB,UAAM,iBAAiB,KAAK,aAAa;AACzC,UAAM,WAAW,IAAI,WAAW,cAAc;AAC9C,SAAK,OAAO,KAAK,UAAU,EAAE,IAAI,KAAK,iBAAiB,CAAC;AACxD,UAAM,YAAY,IAAI,SAAS,SAAS,MAAM;AAG9C,UAAM,UAAU,KAAK,gBAAgB,IAAI,IAAI,WAAW,KAAK,aAAa,IAAI;AAC9E,QAAI,SAAS;AACX,WAAK,OAAO,KAAK,SAAS,EAAE,IAAI,KAAK,gBAAgB,CAAC;AAAA,IACxD;AAEA,aAAS,IAAI,GAAG,IAAI,KAAK,YAAY,KAAK;AACxC,YAAM,MAAM,IAAI;AAChB,YAAM,OAAO,UAAU,SAAS,MAAM,MAAM,IAAI;AAChD,UAAI,SAAS,WAAW,KAAM;AAG9B,UAAI,OAAO,WAAW,QAAQ,OAAO,WAAW,SAAS;AACvD,cAAM,IAAI,MAAM,sBAAsB,CAAC,qBAAqB,IAAI,EAAE;AAAA,MACpE;AAEA,YAAM,aAAa,UAAU,UAAU,MAAM,MAAM,aAAa,IAAI;AACpE,YAAM,aAAa,UAAU,UAAU,MAAM,MAAM,aAAa,IAAI;AACpE,YAAM,OAAO,UAAU,WAAW,MAAM,MAAM,MAAM,IAAI;AACxD,YAAM,aAAa,UAAU,UAAU,MAAM,MAAM,aAAa,IAAI;AACpE,YAAM,aAAa,UAAU,UAAU,MAAM,MAAM,aAAa,IAAI;AAGpE,UAAI,eAAe,KAAK,aAAa,aAAa,KAAK,eAAe;AACpE,cAAM,IAAI,MAAM,sBAAsB,CAAC,+BAA+B,UAAU,SAAS,UAAU,eAAe,KAAK,aAAa,GAAG;AAAA,MACzI;AAGA,UAAI,SAAS,WAAW,WAAW;AACjC,YAAI,OAAO,KAAK,CAAC,SAAS,IAAI,GAAG;AAC/B,gBAAM,IAAI,MAAM,sBAAsB,CAAC,qBAAqB,IAAI,EAAE;AAAA,QACpE;AACA,YAAI,aAAa,KAAK,aAAa,aAAa,KAAK,aAAa;AAChE,gBAAM,IAAI,MAAM,sBAAsB,CAAC,oCAAoC,UAAU,WAAW,UAAU,WAAW,KAAK,WAAW,GAAG;AAAA,QAC1I;AAAA,MACF;AAEA,YAAM,QAAe;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,QACA,MAAM,UAAU,UAAU,MAAM,MAAM,MAAM,IAAI;AAAA,QAChD;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO,UAAU,WAAW,MAAM,MAAM,OAAO,IAAI;AAAA,QACnD,OAAO,UAAU,WAAW,MAAM,MAAM,OAAO,IAAI;AAAA,QACnD,OAAO,UAAU,WAAW,MAAM,MAAM,OAAO,IAAI;AAAA,QACnD,KAAK,UAAU,UAAU,MAAM,MAAM,KAAK,IAAI;AAAA,QAC9C,KAAK,UAAU,UAAU,MAAM,MAAM,KAAK,IAAI;AAAA,MAChD;AACA,WAAK,WAAW,IAAI,GAAG,KAAK;AAG5B,UAAI;AACJ,UAAI,SAAS;AACX,eAAO,QAAQ,OAAO,QAAQ,SAAS,MAAM,YAAY,MAAM,aAAa,MAAM,UAAU,CAAC;AAAA,MAC/F,OAAO;AACL,eAAO,KAAK,SAAS,MAAM,YAAY,MAAM,UAAU;AAAA,MACzD;AAGA,UAAI,CAAC,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,IAAI,GAAG;AAChD,cAAM,IAAI,MAAM,sBAAsB,CAAC,sBAAsB,KAAK,UAAU,GAAG,EAAE,CAAC,GAAG;AAAA,MACvF;AAEA,WAAK,UAAU,IAAI,MAAM,CAAC;AAAA,IAC5B;AAAA,EACF;AAAA;AAAA,EAIQ,UAAU,KAAoB;AACpC,UAAM,SAAS,KAAK,WAAW,IAAI,GAAG;AACtC,QAAI,OAAQ,QAAO;AAEnB,UAAM,SAAS,KAAK,mBAAmB,MAAM;AAC7C,SAAK,OAAO,KAAK,KAAK,UAAU,EAAE,IAAI,OAAO,CAAC;AAC9C,UAAM,IAAI,KAAK;AACf,UAAM,QAAe;AAAA,MACnB,MAAM,EAAE,SAAS,MAAM,IAAI;AAAA,MAC3B,YAAY,EAAE,UAAU,MAAM,aAAa,IAAI;AAAA,MAC/C,YAAY,EAAE,UAAU,MAAM,aAAa,IAAI;AAAA,MAC/C,MAAM,EAAE,UAAU,MAAM,MAAM,IAAI;AAAA,MAClC,MAAM,EAAE,WAAW,MAAM,MAAM,IAAI;AAAA,MACnC,YAAY,EAAE,UAAU,MAAM,aAAa,IAAI;AAAA,MAC/C,YAAY,EAAE,UAAU,MAAM,aAAa,IAAI;AAAA,MAC/C,OAAO,EAAE,WAAW,MAAM,OAAO,IAAI;AAAA,MACrC,OAAO,EAAE,WAAW,MAAM,OAAO,IAAI;AAAA,MACrC,OAAO,EAAE,WAAW,MAAM,OAAO,IAAI;AAAA,MACrC,KAAK,EAAE,UAAU,MAAM,KAAK,IAAI;AAAA,MAChC,KAAK,EAAE,UAAU,MAAM,KAAK,IAAI;AAAA,IAClC;AACA,SAAK,WAAW,IAAI,KAAK,KAAK;AAC9B,WAAO;AAAA,EACT;AAAA,EAEQ,WAAW,KAAa,OAAoB;AAElD,QAAI,MAAM,SAAS,WAAW,MAAM;AAClC,WAAK,WAAW,OAAO,GAAG;AAAA,IAC5B,OAAO;AACL,WAAK,WAAW,IAAI,KAAK,KAAK;AAAA,IAChC;AAEA,UAAM,IAAI,KAAK;AACf,MAAE,SAAS,MAAM,MAAM,MAAM,IAAI;AACjC,MAAE,SAAS,MAAM,OAAO,CAAC;AACzB,MAAE,SAAS,MAAM,QAAQ,GAAG,CAAC;AAC7B,MAAE,SAAS,MAAM,QAAQ,GAAG,CAAC;AAC7B,MAAE,UAAU,MAAM,aAAa,MAAM,YAAY,IAAI;AACrD,MAAE,UAAU,MAAM,aAAa,MAAM,YAAY,IAAI;AACrD,MAAE,UAAU,MAAM,aAAa,GAAG,IAAI;AACtC,MAAE,UAAU,MAAM,MAAM,MAAM,MAAM,IAAI;AACxC,MAAE,WAAW,MAAM,MAAM,MAAM,MAAM,IAAI;AACzC,MAAE,UAAU,MAAM,aAAa,MAAM,YAAY,IAAI;AACrD,MAAE,UAAU,MAAM,aAAa,MAAM,YAAY,IAAI;AACrD,MAAE,WAAW,MAAM,OAAO,MAAM,OAAO,IAAI;AAC3C,MAAE,WAAW,MAAM,OAAO,MAAM,OAAO,IAAI;AAC3C,MAAE,WAAW,MAAM,OAAO,MAAM,OAAO,IAAI;AAC3C,MAAE,UAAU,MAAM,KAAK,MAAM,KAAK,IAAI;AACtC,MAAE,UAAU,MAAM,KAAK,MAAM,KAAK,IAAI;AAEtC,UAAM,SAAS,KAAK,mBAAmB,MAAM;AAC7C,SAAK,OAAO,MAAM,KAAK,UAAU,EAAE,IAAI,OAAO,CAAC;AAAA,EACjD;AAAA;AAAA,EAIQ,SAAS,QAAgB,QAAwB;AACvD,UAAM,MAAM,IAAI,WAAW,MAAM;AACjC,SAAK,OAAO,KAAK,KAAK,EAAE,IAAI,KAAK,kBAAkB,OAAO,CAAC;AAC3D,WAAO,QAAQ,OAAO,GAAG;AAAA,EAC3B;AAAA,EAEQ,WAAW,MAAkD;AACnE,UAAM,QAAQ,QAAQ,OAAO,IAAI;AACjC,UAAM,SAAS,KAAK;AAGpB,QAAI,SAAS,MAAM,aAAa,KAAK,eAAe;AAClD,WAAK,cAAc,SAAS,MAAM,UAAU;AAAA,IAC9C;AAEA,SAAK,OAAO,MAAM,OAAO,EAAE,IAAI,KAAK,kBAAkB,OAAO,CAAC;AAC9D,SAAK,iBAAiB,MAAM;AAG5B,SAAK,kBAAkB;AAEvB,WAAO,EAAE,QAAQ,QAAQ,MAAM,WAAW;AAAA,EAC5C;AAAA,EAEQ,cAAc,QAAsB;AAE1C,UAAM,UAAU,KAAK,IAAI,KAAK,gBAAgB,GAAG,SAAS,uBAAuB;AACjF,UAAM,SAAS,UAAU,KAAK;AAM9B,UAAM,WAAW,KAAK,cAAc,KAAK;AACzC,UAAM,UAAU,IAAI,WAAW,QAAQ;AACvC,SAAK,OAAO,KAAK,SAAS,EAAE,IAAI,KAAK,WAAW,CAAC;AAGjD,UAAM,eAAe,KAAK,OAAO,QAAQ,IAAI;AAC7C,SAAK,OAAO,SAAS,YAAY;AAGjC,UAAM,kBAAkB,KAAK,eAAe;AAC5C,UAAM,gBAAgB,KAAK,aAAa;AACxC,SAAK,OAAO,MAAM,SAAS,EAAE,IAAI,cAAc,CAAC;AAChD,SAAK,OAAO,MAAM,KAAK,QAAS,EAAE,IAAI,gBAAgB,CAAC;AAGvD,SAAK,gBAAgB;AACrB,SAAK,eAAe;AACpB,SAAK,aAAa;AAGlB,SAAK,kBAAkB;AAAA,EACzB;AAAA;AAAA,EAIQ,eAAe,OAAuB;AAC5C,QAAI,UAAU,EAAG,QAAO;AAExB,UAAM,SAAS,KAAK;AACpB,QAAI,MAAM;AACV,QAAI,QAAQ;AAEZ,aAAS,IAAI,GAAG,IAAI,KAAK,aAAa,KAAK;AACzC,YAAM,UAAU,MAAM;AACtB,YAAM,SAAS,IAAI;AACnB,YAAM,OAAQ,OAAO,OAAO,MAAM,SAAU;AAE5C,UAAI,MAAM;AACR,cAAM;AACN,gBAAQ,IAAI;AAAA,MACd,OAAO;AACL;AACA,YAAI,QAAQ,OAAO;AAEjB,mBAAS,IAAI,OAAO,KAAK,GAAG,KAAK;AAC/B,kBAAM,KAAK,MAAM;AACjB,kBAAM,KAAK,IAAI;AACf,mBAAO,EAAE,KAAM,KAAK;AAAA,UACtB;AACA,eAAK,gBAAgB,UAAU,GAAG,MAAM,CAAC;AACzC,eAAK,cAAc;AACnB,eAAK,kBAAkB;AACvB,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAGA,WAAO,KAAK,gBAAgB,KAAK;AAAA,EACnC;AAAA,EAEQ,gBAAgB,OAAuB;AAC7C,UAAM,WAAW,KAAK;AAEtB,UAAM,WAAW,KAAK,IAAI,WAAW,GAAG,WAAW,KAAK;AACxD,UAAM,cAAc,WAAW;AAG/B,UAAM,cAAc,KAAK,aAAa,WAAW,KAAK;AACtD,SAAK,OAAO,SAAS,WAAW;AAGhC,UAAM,gBAAgB,KAAK,KAAK,WAAW,CAAC;AAC5C,UAAM,YAAY,IAAI,WAAW,aAAa;AAC9C,cAAU,IAAI,KAAK,MAAO;AAC1B,SAAK,SAAS;AAEd,SAAK,cAAc;AACnB,SAAK,cAAc;AAGnB,UAAM,QAAQ;AACd,aAAS,IAAI,OAAO,IAAI,QAAQ,OAAO,KAAK;AAC1C,YAAM,KAAK,MAAM;AACjB,YAAM,KAAK,IAAI;AACf,WAAK,OAAO,EAAE,KAAM,KAAK;AAAA,IAC3B;AAEA,SAAK,gBAAgB,UAAU,GAAI,QAAQ,QAAQ,MAAO,CAAC;AAC3D,SAAK,cAAc;AACnB,SAAK,kBAAkB;AAEvB,WAAO;AAAA,EACT;AAAA,EAEQ,uBAAuB;AAAA,EAEvB,eAAe,OAAe,OAAqB;AACzD,QAAI,UAAU,EAAG;AACjB,UAAM,SAAS,KAAK;AAEpB,aAAS,IAAI,OAAO,IAAI,QAAQ,OAAO,KAAK;AAC1C,YAAM,UAAU,MAAM;AACtB,YAAM,SAAS,IAAI;AACnB,aAAO,OAAO,KAAK,EAAE,KAAK;AAAA,IAC5B;AAEA,SAAK,gBAAgB,UAAU,GAAI,QAAQ,QAAQ,MAAO,CAAC;AAC3D,SAAK,cAAc;AACnB,SAAK,kBAAkB;AACvB,SAAK,uBAAuB;AAAA,EAC9B;AAAA;AAAA;AAAA,EAMQ,gBAAwB;AAE9B,aAAS,IAAI,KAAK,eAAe,IAAI,KAAK,YAAY,KAAK;AAEzD,UAAI,KAAK,WAAW,IAAI,CAAC,EAAG;AAE5B,YAAM,SAAS,KAAK,mBAAmB,IAAI;AAC3C,YAAM,UAAU,IAAI,WAAW,CAAC;AAChC,WAAK,OAAO,KAAK,SAAS,EAAE,IAAI,OAAO,CAAC;AACxC,UAAI,QAAQ,CAAC,MAAM,WAAW,MAAM;AAClC,aAAK,gBAAgB,IAAI;AACzB,eAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,MAAM,KAAK,eAAe;AAChC,SAAK,gBAAgB,MAAM;AAC3B,WAAO;AAAA,EACT;AAAA,EAEQ,iBAAyB;AAC/B,UAAM,WAAW,KAAK;AACtB,UAAM,WAAW,WAAW;AAC5B,UAAM,UAAU,WAAW,YAAY;AAGvC,UAAM,mBAAmB,KAAK,mBAAmB,WAAW;AAC5D,UAAM,YAAY,KAAK,OAAO,QAAQ,IAAI;AAC1C,UAAM,WAAW,IAAI,WAAW,SAAS;AACzC,SAAK,OAAO,KAAK,UAAU,EAAE,IAAI,iBAAiB,CAAC;AAGnD,SAAK,OAAO,SAAS,KAAK,OAAO,QAAQ,IAAI,MAAM;AAGnD,SAAK,OAAO,MAAM,UAAU,EAAE,IAAI,mBAAmB,OAAO,CAAC;AAG7D,UAAM,SAAS,IAAI,WAAW,MAAM;AACpC,SAAK,OAAO,MAAM,QAAQ,EAAE,IAAI,iBAAiB,CAAC;AAGlD,SAAK,mBAAmB;AACxB,SAAK,gBAAgB;AACrB,SAAK,cAAc;AACnB,SAAK,aAAa;AAElB,SAAK,kBAAkB;AAEvB,WAAO;AAAA,EACT;AAAA;AAAA,EAIQ,SAAS,YAAoB,YAAoB,MAA0B;AACjF,UAAM,MAAM,IAAI,WAAW,IAAI;AAC/B,UAAM,SAAS,KAAK,aAAa,aAAa,KAAK;AACnD,SAAK,OAAO,KAAK,KAAK,EAAE,IAAI,OAAO,CAAC;AACpC,WAAO;AAAA,EACT;AAAA,EAEQ,UAAU,YAAoB,MAAwB;AAC5D,UAAM,SAAS,KAAK,aAAa,aAAa,KAAK;AACnD,SAAK,OAAO,MAAM,MAAM,EAAE,IAAI,OAAO,CAAC;AAAA,EACxC;AAAA;AAAA,EAIQ,YAAY,MAAc,QAAgB,GAAuB;AACvE,QAAI,QAAQ,kBAAmB,QAAO;AAEtC,UAAM,MAAM,KAAK,UAAU,IAAI,IAAI;AACnC,QAAI,QAAQ,QAAW;AAErB,aAAO,KAAK,sBAAsB,MAAM,MAAM,KAAK;AAAA,IACrD;AAEA,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,QAAI,MAAM,SAAS,WAAW,SAAS;AAErC,YAAM,SAAS,QAAQ,OAAO,KAAK,SAAS,MAAM,YAAY,MAAM,YAAY,MAAM,IAAI,CAAC;AAC3F,YAAM,WAAW,OAAO,WAAW,GAAG,IAAI,SAAS,KAAK,gBAAgB,MAAM,MAAM;AACpF,aAAO,KAAK,YAAY,UAAU,QAAQ,CAAC;AAAA,IAC7C;AAEA,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,sBAAsB,MAAc,aAAsB,MAAM,QAAgB,GAAuB;AAC7G,QAAI,QAAQ,kBAAmB,QAAO;AAEtC,UAAM,QAAQ,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAC5C,QAAI,UAAU;AAEd,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,SAAS,MAAM,MAAM,SAAS;AACpC,gBAAU,YAAY,MAAM,MAAM,MAAM,CAAC,IAAI,UAAU,MAAM,MAAM,CAAC;AAEpE,YAAM,MAAM,KAAK,UAAU,IAAI,OAAO;AACtC,UAAI,QAAQ,OAAW,QAAO;AAE9B,YAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,UAAI,MAAM,SAAS,WAAW,YAAY,CAAC,UAAU,aAAa;AAChE,cAAM,SAAS,QAAQ,OAAO,KAAK,SAAS,MAAM,YAAY,MAAM,YAAY,MAAM,IAAI,CAAC;AAC3F,cAAM,WAAW,OAAO,WAAW,GAAG,IAAI,SAAS,KAAK,gBAAgB,SAAS,MAAM;AAEvF,YAAI,QAAQ;AAGV,iBAAO,KAAK,sBAAsB,UAAU,MAAM,QAAQ,CAAC;AAAA,QAC7D;AAGA,cAAM,YAAY,MAAM,MAAM,IAAI,CAAC,EAAE,KAAK,GAAG;AAC7C,cAAM,UAAU,YAAY,YAAY,MAAM,YAAY;AAC1D,eAAO,KAAK,sBAAsB,SAAS,YAAY,QAAQ,CAAC;AAAA,MAClE;AAAA,IACF;AAEA,WAAO,KAAK,UAAU,IAAI,OAAO;AAAA,EACnC;AAAA,EAEQ,gBAAgB,MAAc,QAAwB;AAC5D,UAAM,MAAM,KAAK,UAAU,GAAG,KAAK,YAAY,GAAG,CAAC,KAAK;AACxD,UAAM,SAAS,MAAM,MAAM,QAAQ,MAAM,GAAG,EAAE,OAAO,OAAO;AAC5D,UAAM,WAAqB,CAAC;AAC5B,eAAW,KAAK,OAAO;AACrB,UAAI,MAAM,IAAK;AACf,UAAI,MAAM,MAAM;AAAE,iBAAS,IAAI;AAAG;AAAA,MAAU;AAC5C,eAAS,KAAK,CAAC;AAAA,IACjB;AACA,WAAO,MAAM,SAAS,KAAK,GAAG;AAAA,EAChC;AAAA;AAAA,EAIQ,YAAY,MAAc,MAAc,MAAc,MAAc,MAA2B;AACrG,UAAM,MAAM,KAAK,cAAc;AAC/B,UAAM,EAAE,QAAQ,SAAS,QAAQ,QAAQ,IAAI,KAAK,WAAW,IAAI;AACjE,UAAM,MAAM,KAAK,IAAI;AAErB,QAAI,aAAa;AACjB,QAAI,aAAa;AAEjB,QAAI,QAAQ,KAAK,aAAa,GAAG;AAC/B,mBAAa,KAAK,KAAK,KAAK,aAAa,KAAK,SAAS;AACvD,mBAAa,KAAK,eAAe,UAAU;AAC3C,WAAK,UAAU,YAAY,IAAI;AAAA,IACjC;AAEA,UAAM,QAAe;AAAA,MACnB;AAAA,MACA,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,KAAK,KAAK;AAAA,MACV,KAAK,KAAK;AAAA,IACZ;AAEA,SAAK,WAAW,KAAK,KAAK;AAC1B,SAAK,UAAU,IAAI,MAAM,GAAG;AAE5B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA,EAKA,cAAc,GAAmB;AAC/B,QAAI,EAAE,WAAW,CAAC,MAAM,GAAI,KAAI,MAAM;AAEtC,QAAI,EAAE,WAAW,EAAG,QAAO;AAC3B,QAAI,EAAE,QAAQ,IAAI,MAAM,MAAM,EAAE,QAAQ,IAAI,MAAM,MAAM,EAAE,WAAW,EAAE,SAAS,CAAC,MAAM,IAAI;AACzF,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,EAAE,MAAM,GAAG,EAAE,OAAO,OAAO;AACzC,UAAM,WAAqB,CAAC;AAC5B,eAAW,QAAQ,OAAO;AACxB,UAAI,SAAS,IAAK;AAClB,UAAI,SAAS,MAAM;AAAE,iBAAS,IAAI;AAAG;AAAA,MAAU;AAC/C,eAAS,KAAK,IAAI;AAAA,IACpB;AACA,WAAO,MAAM,SAAS,KAAK,GAAG;AAAA,EAChC;AAAA;AAAA,EAGA,KAAK,MAA2D;AAC9D,UAAM,KAAK,KAAK,QAAQ,YAAY,IAAI,IAAI;AAC5C,WAAO,KAAK,cAAc,IAAI;AAG9B,QAAI,MAAM,KAAK,UAAU,IAAI,IAAI;AACjC,QAAI,QAAQ,QAAW;AACrB,YAAMA,SAAQ,KAAK,WAAW,IAAI,GAAG;AACrC,UAAIA,QAAO;AAET,YAAIA,OAAM,SAAS,WAAW,SAAS;AACrC,gBAAM,KAAK,sBAAsB,MAAM,IAAI;AAAA,QAC7C,WAAWA,OAAM,SAAS,WAAW,WAAW;AAC9C,iBAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAAA,QACrD,OAAO;AAEL,gBAAMC,QAAOD,OAAM,OAAO,IACtB,KAAK,SAASA,OAAM,YAAYA,OAAM,YAAYA,OAAM,IAAI,IAC5D,IAAI,WAAW,CAAC;AACpB,cAAI,KAAK,OAAO;AACd,kBAAM,KAAK,YAAY,IAAI;AAC3B,oBAAQ,IAAI,mBAAmB,IAAI,SAASA,OAAM,IAAI,WAAW,KAAG,IAAI,QAAQ,CAAC,CAAC,WAAW;AAAA,UAC/F;AACA,iBAAO,EAAE,QAAQ,GAAG,MAAAC,MAAK;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAGA,QAAI,QAAQ,OAAW,OAAM,KAAK,sBAAsB,MAAM,IAAI;AAClE,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAE1E,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,QAAI,MAAM,SAAS,WAAW,UAAW,QAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAE5F,UAAM,OAAO,MAAM,OAAO,IACtB,KAAK,SAAS,MAAM,YAAY,MAAM,YAAY,MAAM,IAAI,IAC5D,IAAI,WAAW,CAAC;AAEpB,QAAI,KAAK,OAAO;AACd,YAAM,KAAK,YAAY,IAAI;AAC3B,cAAQ,IAAI,mBAAmB,IAAI,SAAS,MAAM,IAAI,WAAW,KAAG,IAAI,QAAQ,CAAC,CAAC,gBAAgB;AAAA,IACpG;AAEA,WAAO,EAAE,QAAQ,GAAG,KAAK;AAAA,EAC3B;AAAA;AAAA,EAGA,MAAM,MAAc,MAAkB,QAAgB,GAAuB;AAC3E,UAAM,KAAK,KAAK,QAAQ,YAAY,IAAI,IAAI;AAC5C,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,KAAK,KAAK,QAAQ,YAAY,IAAI,IAAI;AAG5C,UAAM,eAAe,KAAK,aAAa,IAAI;AAC3C,QAAI,iBAAiB,EAAG,QAAO,EAAE,QAAQ,aAAa;AACtD,UAAM,KAAK,KAAK,QAAQ,YAAY,IAAI,IAAI;AAE5C,UAAM,cAAc,KAAK,sBAAsB,MAAM,IAAI;AACzD,UAAM,KAAK,KAAK,QAAQ,YAAY,IAAI,IAAI;AAE5C,QAAI,SAAS,IAAI,QAAQ,IAAI,SAAS;AAEtC,QAAI,gBAAgB,QAAW;AAE7B,YAAM,QAAQ,KAAK,UAAU,WAAW;AACxC,UAAI,MAAM,SAAS,WAAW,UAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAEhF,YAAM,eAAe,KAAK,KAAK,KAAK,aAAa,KAAK,SAAS;AAE/D,UAAI,gBAAgB,MAAM,YAAY;AAEpC,iBAAS,KAAK,QAAQ,YAAY,IAAI,IAAI;AAC1C,aAAK,UAAU,MAAM,YAAY,IAAI;AACrC,gBAAQ,KAAK,QAAQ,YAAY,IAAI,IAAI;AACzC,YAAI,eAAe,MAAM,YAAY;AACnC,eAAK,eAAe,MAAM,aAAa,cAAc,MAAM,aAAa,YAAY;AAAA,QACtF;AAAA,MACF,OAAO;AAEL,aAAK,eAAe,MAAM,YAAY,MAAM,UAAU;AACtD,cAAM,WAAW,KAAK,eAAe,YAAY;AACjD,iBAAS,KAAK,QAAQ,YAAY,IAAI,IAAI;AAC1C,aAAK,UAAU,UAAU,IAAI;AAC7B,gBAAQ,KAAK,QAAQ,YAAY,IAAI,IAAI;AACzC,cAAM,aAAa;AAAA,MACrB;AAEA,YAAM,OAAO,KAAK;AAClB,YAAM,aAAa;AACnB,YAAM,QAAQ,KAAK,IAAI;AACvB,WAAK,WAAW,aAAa,KAAK;AAClC,eAAS,KAAK,QAAQ,YAAY,IAAI,IAAI;AAAA,IAC5C,OAAO;AAEL,YAAM,OAAO,oBAAoB,EAAE,KAAK,QAAQ;AAChD,WAAK,YAAY,MAAM,WAAW,MAAM,MAAM,KAAK,YAAY,IAAI;AACnE,eAAS,KAAK,QAAQ,YAAY,IAAI,IAAI;AAC1C,cAAQ;AACR,eAAS;AAAA,IACX;AAEA,QAAI,QAAQ,GAAG;AACb,WAAK,cAAc;AACnB,WAAK,OAAO,MAAM;AAAA,IACpB;AACA,UAAM,SAAS,KAAK,QAAQ,YAAY,IAAI,IAAI;AAEhD,QAAI,KAAK,OAAO;AACd,YAAM,WAAW,gBAAgB;AACjC,cAAQ,IAAI,oBAAoB,IAAI,SAAS,KAAK,UAAU,IAAI,WAAW,WAAW,QAAQ,eAAe,KAAG,IAAI,QAAQ,CAAC,CAAC,cAAc,KAAG,IAAI,QAAQ,CAAC,CAAC,eAAe,KAAG,IAAI,QAAQ,CAAC,CAAC,aAAa,SAAO,IAAI,QAAQ,CAAC,CAAC,YAAY,QAAM,QAAQ,QAAQ,CAAC,CAAC,aAAa,SAAO,OAAO,QAAQ,CAAC,CAAC,aAAa,SAAO,QAAQ,QAAQ,CAAC,CAAC,aAAa,SAAO,IAAI,QAAQ,CAAC,CAAC,IAAI;AAAA,IACtX;AAEA,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,OAAO,MAAc,MAAsC;AACzD,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,cAAc,KAAK,sBAAsB,MAAM,IAAI;AAEzD,QAAI,gBAAgB,QAAW;AAE7B,aAAO,KAAK,MAAM,MAAM,IAAI;AAAA,IAC9B;AAEA,UAAM,QAAQ,KAAK,UAAU,WAAW;AACxC,QAAI,MAAM,SAAS,WAAW,UAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAGhF,UAAM,WAAW,MAAM,OAAO,IAC1B,KAAK,SAAS,MAAM,YAAY,MAAM,YAAY,MAAM,IAAI,IAC5D,IAAI,WAAW,CAAC;AAGpB,UAAM,WAAW,IAAI,WAAW,SAAS,aAAa,KAAK,UAAU;AACrE,aAAS,IAAI,QAAQ;AACrB,aAAS,IAAI,MAAM,SAAS,UAAU;AAGtC,UAAM,eAAe,KAAK,KAAK,SAAS,aAAa,KAAK,SAAS;AACnE,SAAK,eAAe,MAAM,YAAY,MAAM,UAAU;AACtD,UAAM,WAAW,KAAK,eAAe,YAAY;AACjD,SAAK,UAAU,UAAU,QAAQ;AAEjC,UAAM,aAAa;AACnB,UAAM,aAAa;AACnB,UAAM,OAAO,SAAS;AACtB,UAAM,QAAQ,KAAK,IAAI;AACvB,SAAK,WAAW,aAAa,KAAK;AAElC,SAAK,cAAc;AACnB,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,OAAO,MAAkC;AACvC,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,UAAU,IAAI,IAAI;AACnC,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAE9D,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,QAAI,MAAM,SAAS,WAAW,UAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAGhF,SAAK,eAAe,MAAM,YAAY,MAAM,UAAU;AAGtD,UAAM,OAAO,WAAW;AACxB,SAAK,WAAW,KAAK,KAAK;AAG1B,SAAK,UAAU,OAAO,IAAI;AAE1B,QAAI,MAAM,KAAK,cAAe,MAAK,gBAAgB;AAEnD,SAAK,cAAc;AACnB,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,KAAK,MAA2D;AAC9D,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,sBAAsB,MAAM,IAAI;AACjD,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAE1E,WAAO,KAAK,mBAAmB,GAAG;AAAA,EACpC;AAAA;AAAA,EAGA,MAAM,MAA2D;AAC/D,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,UAAU,IAAI,IAAI;AACnC,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAE1E,WAAO,KAAK,mBAAmB,GAAG;AAAA,EACpC;AAAA,EAEQ,mBAAmB,KAAmD;AAC5E,UAAM,QAAQ,KAAK,UAAU,GAAG;AAEhC,UAAM,MAAM,IAAI,WAAW,EAAE;AAC7B,UAAM,OAAO,IAAI,SAAS,IAAI,MAAM;AACpC,SAAK,SAAS,GAAG,MAAM,IAAI;AAC3B,SAAK,UAAU,GAAG,MAAM,MAAM,IAAI;AAClC,SAAK,WAAW,GAAG,MAAM,MAAM,IAAI;AACnC,SAAK,WAAW,IAAI,MAAM,OAAO,IAAI;AACrC,SAAK,WAAW,IAAI,MAAM,OAAO,IAAI;AACrC,SAAK,WAAW,IAAI,MAAM,OAAO,IAAI;AACrC,SAAK,UAAU,IAAI,MAAM,KAAK,IAAI;AAClC,SAAK,UAAU,IAAI,MAAM,KAAK,IAAI;AAClC,SAAK,UAAU,IAAI,KAAK,IAAI;AAE5B,WAAO,EAAE,QAAQ,GAAG,MAAM,IAAI;AAAA,EAChC;AAAA;AAAA,EAGA,MAAM,MAAc,QAAgB,GAAgD;AAClF,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,aAAa,QAAQ,OAAO;AAElC,QAAI,WAAW;AACb,aAAO,KAAK,eAAe,IAAI;AAAA,IACjC;AAGA,QAAI,KAAK,UAAU,IAAI,IAAI,EAAG,QAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAGjF,UAAM,eAAe,KAAK,aAAa,IAAI;AAC3C,QAAI,iBAAiB,EAAG,QAAO,EAAE,QAAQ,cAAc,MAAM,KAAK;AAElE,UAAM,OAAO,mBAAmB,EAAE,KAAK,QAAQ;AAC/C,SAAK,YAAY,MAAM,WAAW,WAAW,MAAM,CAAC;AAEpD,SAAK,cAAc;AAEnB,UAAM,YAAY,QAAQ,OAAO,IAAI;AACrC,WAAO,EAAE,QAAQ,GAAG,MAAM,UAAU;AAAA,EACtC;AAAA,EAEQ,eAAe,MAA2D;AAChF,UAAM,QAAQ,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAC5C,QAAI,UAAU;AACd,QAAI,eAA8B;AAElC,eAAW,QAAQ,OAAO;AACxB,iBAAW,MAAM;AAEjB,UAAI,KAAK,UAAU,IAAI,OAAO,GAAG;AAC/B,cAAM,MAAM,KAAK,UAAU,IAAI,OAAO;AACtC,cAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,YAAI,MAAM,SAAS,WAAW,WAAW;AACvC,iBAAO,EAAE,QAAQ,eAAe,SAAS,MAAM,KAAK;AAAA,QACtD;AACA;AAAA,MACF;AAEA,YAAM,OAAO,mBAAmB,EAAE,KAAK,QAAQ;AAC/C,WAAK,YAAY,SAAS,WAAW,WAAW,MAAM,CAAC;AACvD,UAAI,CAAC,aAAc,gBAAe;AAAA,IACpC;AAEA,SAAK,cAAc;AACnB,UAAM,SAAS,eAAe,QAAQ,OAAO,YAAY,IAAI;AAC7D,WAAO,EAAE,QAAQ,GAAG,MAAM,UAAU,KAAK;AAAA,EAC3C;AAAA;AAAA,EAGA,MAAM,MAAc,QAAgB,GAAuB;AACzD,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,aAAa,QAAQ,OAAO;AAClC,UAAM,MAAM,KAAK,UAAU,IAAI,IAAI;AACnC,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAE9D,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,QAAI,MAAM,SAAS,WAAW,UAAW,QAAO,EAAE,QAAQ,eAAe,QAAQ;AAGjF,UAAM,WAAW,KAAK,kBAAkB,IAAI;AAE5C,QAAI,SAAS,SAAS,GAAG;AACvB,UAAI,CAAC,UAAW,QAAO,EAAE,QAAQ,eAAe,UAAU;AAG1D,iBAAW,SAAS,KAAK,kBAAkB,IAAI,GAAG;AAChD,cAAM,WAAW,KAAK,UAAU,IAAI,KAAK;AACzC,cAAM,aAAa,KAAK,UAAU,QAAQ;AAC1C,aAAK,eAAe,WAAW,YAAY,WAAW,UAAU;AAChE,mBAAW,OAAO,WAAW;AAC7B,aAAK,WAAW,UAAU,UAAU;AACpC,aAAK,UAAU,OAAO,KAAK;AAAA,MAC7B;AAAA,IACF;AAGA,UAAM,OAAO,WAAW;AACxB,SAAK,WAAW,KAAK,KAAK;AAC1B,SAAK,UAAU,OAAO,IAAI;AAC1B,QAAI,MAAM,KAAK,cAAe,MAAK,gBAAgB;AAEnD,SAAK,cAAc;AACnB,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,QAAQ,MAAc,QAAgB,GAAgD;AACpF,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,sBAAsB,MAAM,IAAI;AACjD,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAE1E,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,QAAI,MAAM,SAAS,WAAW,UAAW,QAAO,EAAE,QAAQ,eAAe,SAAS,MAAM,KAAK;AAE7F,UAAM,iBAAiB,QAAQ,OAAO;AACtC,UAAM,WAAW,KAAK,kBAAkB,IAAI;AAE5C,QAAI,eAAe;AAEjB,UAAIC,aAAY;AAChB,YAAM,UAAgD,CAAC;AAEvD,iBAAW,aAAa,UAAU;AAChC,cAAM,OAAO,UAAU,UAAU,UAAU,YAAY,GAAG,IAAI,CAAC;AAC/D,cAAM,YAAY,QAAQ,OAAO,IAAI;AACrC,cAAM,WAAW,KAAK,UAAU,IAAI,SAAS;AAC7C,cAAM,aAAa,KAAK,UAAU,QAAQ;AAC1C,gBAAQ,KAAK,EAAE,MAAM,WAAW,MAAM,WAAW,KAAK,CAAC;AACvD,QAAAA,cAAa,IAAI,UAAU,aAAa;AAAA,MAC1C;AAEA,YAAMC,OAAM,IAAI,WAAWD,UAAS;AACpC,YAAME,QAAO,IAAI,SAASD,KAAI,MAAM;AACpC,MAAAC,MAAK,UAAU,GAAG,QAAQ,QAAQ,IAAI;AACtC,UAAIC,UAAS;AAEb,iBAAW,SAAS,SAAS;AAC3B,QAAAD,MAAK,UAAUC,SAAQ,MAAM,KAAK,YAAY,IAAI;AAClD,QAAAA,WAAU;AACV,QAAAF,KAAI,IAAI,MAAM,MAAME,OAAM;AAC1B,QAAAA,WAAU,MAAM,KAAK;AACrB,QAAAF,KAAIE,SAAQ,IAAI,MAAM;AAAA,MACxB;AAEA,aAAO,EAAE,QAAQ,GAAG,MAAMF,KAAI;AAAA,IAChC;AAGA,QAAI,YAAY;AAChB,UAAM,cAA4B,CAAC;AAEnC,eAAW,aAAa,UAAU;AAChC,YAAM,OAAO,UAAU,UAAU,UAAU,YAAY,GAAG,IAAI,CAAC;AAC/D,YAAM,YAAY,QAAQ,OAAO,IAAI;AACrC,kBAAY,KAAK,SAAS;AAC1B,mBAAa,IAAI,UAAU;AAAA,IAC7B;AAEA,UAAM,MAAM,IAAI,WAAW,SAAS;AACpC,UAAM,OAAO,IAAI,SAAS,IAAI,MAAM;AACpC,SAAK,UAAU,GAAG,YAAY,QAAQ,IAAI;AAC1C,QAAI,SAAS;AAEb,eAAW,aAAa,aAAa;AACnC,WAAK,UAAU,QAAQ,UAAU,YAAY,IAAI;AACjD,gBAAU;AACV,UAAI,IAAI,WAAW,MAAM;AACzB,gBAAU,UAAU;AAAA,IACtB;AAEA,WAAO,EAAE,QAAQ,GAAG,MAAM,IAAI;AAAA,EAChC;AAAA;AAAA,EAGA,OAAO,SAAiB,SAAqC;AAC3D,cAAU,KAAK,cAAc,OAAO;AACpC,cAAU,KAAK,cAAc,OAAO;AAEpC,UAAM,MAAM,KAAK,UAAU,IAAI,OAAO;AACtC,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAG9D,UAAM,eAAe,KAAK,aAAa,OAAO;AAC9C,QAAI,iBAAiB,EAAG,QAAO,EAAE,QAAQ,aAAa;AAGtD,UAAM,cAAc,KAAK,UAAU,IAAI,OAAO;AAC9C,QAAI,gBAAgB,QAAW;AAC7B,YAAM,gBAAgB,KAAK,UAAU,WAAW;AAChD,WAAK,eAAe,cAAc,YAAY,cAAc,UAAU;AACtE,oBAAc,OAAO,WAAW;AAChC,WAAK,WAAW,aAAa,aAAa;AAC1C,WAAK,UAAU,OAAO,OAAO;AAAA,IAC/B;AAGA,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,UAAM,EAAE,QAAQ,SAAS,QAAQ,QAAQ,IAAI,KAAK,WAAW,OAAO;AACpE,UAAM,aAAa;AACnB,UAAM,aAAa;AACnB,UAAM,QAAQ,KAAK,IAAI;AACvB,SAAK,WAAW,KAAK,KAAK;AAG1B,SAAK,UAAU,OAAO,OAAO;AAC7B,SAAK,UAAU,IAAI,SAAS,GAAG;AAG/B,QAAI,MAAM,SAAS,WAAW,WAAW;AACvC,YAAM,SAAS,YAAY,MAAM,MAAM,UAAU;AACjD,YAAM,WAA+B,CAAC;AAEtC,iBAAW,CAAC,GAAG,CAAC,KAAK,KAAK,WAAW;AACnC,YAAI,EAAE,WAAW,MAAM,GAAG;AACxB,mBAAS,KAAK,CAAC,GAAG,CAAC,CAAC;AAAA,QACtB;AAAA,MACF;AAEA,iBAAW,CAAC,GAAG,CAAC,KAAK,UAAU;AAC7B,cAAM,SAAS,EAAE,UAAU,QAAQ,MAAM;AACzC,cAAM,eAAe,UAAU;AAC/B,cAAM,aAAa,KAAK,UAAU,CAAC;AACnC,cAAM,EAAE,QAAQ,KAAK,QAAQ,IAAI,IAAI,KAAK,WAAW,YAAY;AACjE,mBAAW,aAAa;AACxB,mBAAW,aAAa;AACxB,aAAK,WAAW,GAAG,UAAU;AAC7B,aAAK,UAAU,OAAO,CAAC;AACvB,aAAK,UAAU,IAAI,cAAc,CAAC;AAAA,MACpC;AAAA,IACF;AAEA,SAAK,cAAc;AACnB,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,OAAO,MAA2D;AAChE,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,sBAAsB,MAAM,IAAI;AACjD,UAAM,MAAM,IAAI,WAAW,CAAC;AAC5B,QAAI,CAAC,IAAI,QAAQ,SAAY,IAAI;AACjC,WAAO,EAAE,QAAQ,GAAG,MAAM,IAAI;AAAA,EAChC;AAAA;AAAA,EAGA,SAAS,MAAc,MAAc,GAAuB;AAC1D,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,sBAAsB,MAAM,IAAI;AACjD,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAE9D,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,QAAI,MAAM,SAAS,WAAW,UAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAEhF,QAAI,QAAQ,GAAG;AAEb,WAAK,eAAe,MAAM,YAAY,MAAM,UAAU;AACtD,YAAM,aAAa;AACnB,YAAM,aAAa;AACnB,YAAM,OAAO;AAAA,IACf,WAAW,MAAM,MAAM,MAAM;AAE3B,YAAM,eAAe,KAAK,KAAK,MAAM,KAAK,SAAS;AACnD,UAAI,eAAe,MAAM,YAAY;AACnC,aAAK,eAAe,MAAM,aAAa,cAAc,MAAM,aAAa,YAAY;AAAA,MACtF;AACA,YAAM,aAAa;AACnB,YAAM,OAAO;AAAA,IACf,WAAW,MAAM,MAAM,MAAM;AAE3B,YAAM,eAAe,KAAK,KAAK,MAAM,KAAK,SAAS;AACnD,UAAI,eAAe,MAAM,YAAY;AAEnC,cAAM,UAAU,KAAK,SAAS,MAAM,YAAY,MAAM,YAAY,MAAM,IAAI;AAC5E,aAAK,eAAe,MAAM,YAAY,MAAM,UAAU;AACtD,cAAM,WAAW,KAAK,eAAe,YAAY;AACjD,cAAM,UAAU,IAAI,WAAW,GAAG;AAClC,gBAAQ,IAAI,OAAO;AAEnB,aAAK,UAAU,UAAU,OAAO;AAChC,cAAM,aAAa;AAAA,MACrB;AACA,YAAM,aAAa;AACnB,YAAM,OAAO;AAAA,IACf;AAEA,UAAM,QAAQ,KAAK,IAAI;AACvB,SAAK,WAAW,KAAK,KAAK;AAE1B,SAAK,cAAc;AACnB,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,KAAK,SAAiB,UAAkB,QAAgB,GAAuB;AAC7E,cAAU,KAAK,cAAc,OAAO;AACpC,eAAW,KAAK,cAAc,QAAQ;AAEtC,UAAM,SAAS,KAAK,sBAAsB,SAAS,IAAI;AACvD,QAAI,WAAW,OAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAEjE,UAAM,WAAW,KAAK,UAAU,MAAM;AACtC,QAAI,SAAS,SAAS,WAAW,UAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAGnF,QAAK,QAAQ,KAAM,KAAK,UAAU,IAAI,QAAQ,GAAG;AAC/C,aAAO,EAAE,QAAQ,eAAe,OAAO;AAAA,IACzC;AAGA,UAAM,OAAO,SAAS,OAAO,IACzB,KAAK,SAAS,SAAS,YAAY,SAAS,YAAY,SAAS,IAAI,IACrE,IAAI,WAAW,CAAC;AAEpB,WAAO,KAAK,MAAM,UAAU,IAAI;AAAA,EAClC;AAAA;AAAA,EAGA,OAAO,MAAc,OAAe,GAAuB;AACzD,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,sBAAsB,MAAM,IAAI;AACjD,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAE9D,QAAI,SAAS,EAAG,QAAO,EAAE,QAAQ,EAAE;AAEnC,QAAI,CAAC,KAAK,kBAAmB,QAAO,EAAE,QAAQ,EAAE;AAEhD,UAAM,QAAQ,KAAK,UAAU,GAAG;AAEhC,UAAM,WAAW,KAAK,uBAAuB,KAAK;AAElD,QAAK,OAAO,KAAM,EAAE,WAAW,GAAI,QAAO,EAAE,QAAQ,eAAe,OAAO;AAC1E,QAAK,OAAO,KAAM,EAAE,WAAW,GAAI,QAAO,EAAE,QAAQ,eAAe,OAAO;AAC1E,QAAK,OAAO,KAAM,EAAE,WAAW,GAAI,QAAO,EAAE,QAAQ,eAAe,OAAO;AAE1E,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA,EAEQ,uBAAuB,OAAsB;AACnD,UAAM,WAAW,MAAM,OAAO;AAC9B,QAAI,KAAK,eAAe,MAAM,IAAK,QAAQ,aAAa,IAAK;AAC7D,QAAI,KAAK,eAAe,MAAM,IAAK,QAAQ,aAAa,IAAK;AAC7D,WAAO,WAAW;AAAA,EACpB;AAAA;AAAA,EAGA,SAAS,MAA2D;AAClE,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,sBAAsB,MAAM,IAAI;AACjD,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAG1E,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,UAAM,eAAe,KAAK,SAAS,MAAM,YAAY,MAAM,UAAU;AACrE,WAAO,EAAE,QAAQ,GAAG,MAAM,QAAQ,OAAO,YAAY,EAAE;AAAA,EACzD;AAAA;AAAA,EAGA,MAAM,MAAc,MAAkC;AACpD,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,sBAAsB,MAAM,IAAI;AACjD,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAE9D,UAAM,QAAQ,KAAK,UAAU,GAAG;AAEhC,UAAM,OAAQ,MAAM,OAAO,SAAW,OAAO;AAC7C,UAAM,QAAQ,KAAK,IAAI;AACvB,SAAK,WAAW,KAAK,KAAK;AAE1B,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,MAAM,MAAc,KAAa,KAAiC;AAChE,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,sBAAsB,MAAM,IAAI;AACjD,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAE9D,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,UAAM,MAAM;AACZ,UAAM,MAAM;AACZ,UAAM,QAAQ,KAAK,IAAI;AACvB,SAAK,WAAW,KAAK,KAAK;AAE1B,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,OAAO,MAAc,OAAe,OAAmC;AACrE,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,sBAAsB,MAAM,IAAI;AACjD,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,OAAO;AAE9D,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,UAAM,QAAQ;AACd,UAAM,QAAQ;AACd,UAAM,QAAQ,KAAK,IAAI;AACvB,SAAK,WAAW,KAAK,KAAK;AAE1B,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,QAAQ,QAAgB,UAAsC;AAC5D,eAAW,KAAK,cAAc,QAAQ;AACtC,QAAI,KAAK,UAAU,IAAI,QAAQ,EAAG,QAAO,EAAE,QAAQ,eAAe,OAAO;AAEzE,UAAM,eAAe,KAAK,aAAa,QAAQ;AAC/C,QAAI,iBAAiB,EAAG,QAAO,EAAE,QAAQ,aAAa;AAEtD,UAAM,cAAc,QAAQ,OAAO,MAAM;AACzC,SAAK,YAAY,UAAU,WAAW,SAAS,sBAAsB,YAAY,YAAY,WAAW;AAExG,SAAK,cAAc;AACnB,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,SAAS,MAA2D;AAClE,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,UAAU,IAAI,IAAI;AACnC,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAE1E,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,QAAI,MAAM,SAAS,WAAW,QAAS,QAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAE1F,UAAM,SAAS,KAAK,SAAS,MAAM,YAAY,MAAM,YAAY,MAAM,IAAI;AAC3E,WAAO,EAAE,QAAQ,GAAG,MAAM,OAAO;AAAA,EACnC;AAAA;AAAA,EAGA,KAAK,cAAsB,SAAqC;AAC9D,WAAO,KAAK,KAAK,cAAc,OAAO;AAAA,EACxC;AAAA;AAAA,EAGA,KAAK,MAAc,OAAe,OAA4D;AAC5F,WAAO,KAAK,cAAc,IAAI;AAE9B,UAAM,aAAa,QAAQ,QAAQ;AACnC,UAAM,YAAY,QAAQ,SAAS;AACnC,UAAM,WAAW,QAAQ,SAAS;AAElC,QAAI,MAAM,KAAK,sBAAsB,MAAM,IAAI;AAE/C,QAAI,QAAQ,QAAW;AACrB,UAAI,CAAC,UAAW,QAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAEnE,YAAM,OAAO,oBAAoB,EAAE,KAAK,QAAQ;AAChD,YAAM,KAAK,YAAY,MAAM,WAAW,MAAM,MAAM,CAAC;AAAA,IACvD,WAAW,WAAW,WAAW;AAC/B,aAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAAA,IACrD;AAEA,QAAI,UAAU;AACZ,WAAK,SAAS,MAAM,CAAC;AAAA,IACvB;AAEA,UAAM,KAAK,KAAK;AAChB,SAAK,QAAQ,IAAI,IAAI,EAAE,OAAO,UAAU,KAAK,UAAU,GAAG,MAAM,CAAC;AAEjE,UAAM,MAAM,IAAI,WAAW,CAAC;AAC5B,QAAI,SAAS,IAAI,MAAM,EAAE,UAAU,GAAG,IAAI,IAAI;AAC9C,WAAO,EAAE,QAAQ,GAAG,MAAM,IAAI;AAAA,EAChC;AAAA;AAAA,EAGA,MAAM,IAAgC;AACpC,QAAI,CAAC,KAAK,QAAQ,IAAI,EAAE,EAAG,QAAO,EAAE,QAAQ,eAAe,MAAM;AACjE,SAAK,QAAQ,OAAO,EAAE;AACtB,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,MAAM,IAAY,QAAgB,UAAsE;AACtG,UAAM,QAAQ,KAAK,QAAQ,IAAI,EAAE;AACjC,QAAI,CAAC,MAAO,QAAO,EAAE,QAAQ,eAAe,OAAO,MAAM,KAAK;AAE9D,UAAM,QAAQ,KAAK,UAAU,MAAM,QAAQ;AAC3C,UAAM,MAAM,YAAY,MAAM;AAC9B,UAAM,UAAU,KAAK,IAAI,QAAQ,MAAM,OAAO,GAAG;AAEjD,QAAI,WAAW,EAAG,QAAO,EAAE,QAAQ,GAAG,MAAM,IAAI,WAAW,CAAC,EAAE;AAG9D,UAAM,aAAa,KAAK,aAAa,MAAM,aAAa,KAAK,YAAY;AACzE,UAAM,MAAM,IAAI,WAAW,OAAO;AAClC,SAAK,OAAO,KAAK,KAAK,EAAE,IAAI,WAAW,CAAC;AAGxC,QAAI,aAAa,MAAM;AACrB,YAAM,YAAY;AAAA,IACpB;AAEA,WAAO,EAAE,QAAQ,GAAG,MAAM,IAAI;AAAA,EAChC;AAAA;AAAA,EAGA,OAAO,IAAY,MAAkB,UAAsE;AACzG,UAAM,QAAQ,KAAK,QAAQ,IAAI,EAAE;AACjC,QAAI,CAAC,MAAO,QAAO,EAAE,QAAQ,eAAe,OAAO,MAAM,KAAK;AAE9D,UAAM,QAAQ,KAAK,UAAU,MAAM,QAAQ;AAC3C,UAAM,YAAY,MAAM,QAAQ,UAAU;AAC1C,UAAM,MAAM,WAAW,MAAM,OAAQ,YAAY,MAAM;AACvD,UAAM,SAAS,MAAM,KAAK;AAG1B,QAAI,SAAS,MAAM,MAAM;AACvB,YAAM,eAAe,KAAK,KAAK,SAAS,KAAK,SAAS;AACtD,UAAI,eAAe,MAAM,YAAY;AAEnC,cAAM,UAAU,MAAM,OAAO,IACzB,KAAK,SAAS,MAAM,YAAY,MAAM,YAAY,MAAM,IAAI,IAC5D,IAAI,WAAW,CAAC;AACpB,aAAK,eAAe,MAAM,YAAY,MAAM,UAAU;AACtD,cAAM,WAAW,KAAK,eAAe,YAAY;AACjD,cAAM,SAAS,IAAI,WAAW,MAAM;AACpC,eAAO,IAAI,OAAO;AAClB,eAAO,IAAI,MAAM,GAAG;AACpB,aAAK,UAAU,UAAU,MAAM;AAC/B,cAAM,aAAa;AACnB,cAAM,aAAa;AAAA,MACrB,OAAO;AAEL,cAAM,aAAa,KAAK,aAAa,MAAM,aAAa,KAAK,YAAY;AACzE,aAAK,OAAO,MAAM,MAAM,EAAE,IAAI,WAAW,CAAC;AAAA,MAC5C;AACA,YAAM,OAAO;AAAA,IACf,OAAO;AAEL,YAAM,aAAa,KAAK,aAAa,MAAM,aAAa,KAAK,YAAY;AACzE,WAAK,OAAO,MAAM,MAAM,EAAE,IAAI,WAAW,CAAC;AAAA,IAC5C;AAEA,UAAM,QAAQ,KAAK,IAAI;AACvB,SAAK,WAAW,MAAM,UAAU,KAAK;AAGrC,QAAI,aAAa,MAAM;AACrB,YAAM,WAAW;AAAA,IACnB;AAEA,SAAK,cAAc;AACnB,UAAM,MAAM,IAAI,WAAW,CAAC;AAC5B,QAAI,SAAS,IAAI,MAAM,EAAE,UAAU,GAAG,KAAK,YAAY,IAAI;AAC3D,WAAO,EAAE,QAAQ,GAAG,MAAM,IAAI;AAAA,EAChC;AAAA;AAAA,EAGA,MAAM,IAAyD;AAC7D,UAAM,QAAQ,KAAK,QAAQ,IAAI,EAAE;AACjC,QAAI,CAAC,MAAO,QAAO,EAAE,QAAQ,eAAe,OAAO,MAAM,KAAK;AAC9D,WAAO,KAAK,mBAAmB,MAAM,QAAQ;AAAA,EAC/C;AAAA;AAAA,EAGA,UAAU,IAAY,MAAc,GAAuB;AACzD,UAAM,QAAQ,KAAK,QAAQ,IAAI,EAAE;AACjC,QAAI,CAAC,MAAO,QAAO,EAAE,QAAQ,eAAe,MAAM;AAElD,UAAM,QAAQ,KAAK,UAAU,MAAM,QAAQ;AAC3C,UAAM,OAAO,KAAK,SAAS,MAAM,YAAY,MAAM,UAAU;AAC7D,WAAO,KAAK,SAAS,MAAM,GAAG;AAAA,EAChC;AAAA;AAAA,EAGA,QAA4B;AAC1B,SAAK,cAAc;AACnB,SAAK,OAAO,MAAM;AAClB,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,QAAQ,MAAc,OAA4D;AAChF,WAAO,KAAK,cAAc,IAAI;AAC9B,UAAM,MAAM,KAAK,sBAAsB,MAAM,IAAI;AACjD,QAAI,QAAQ,OAAW,QAAO,EAAE,QAAQ,eAAe,QAAQ,MAAM,KAAK;AAE1E,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,QAAI,MAAM,SAAS,WAAW,UAAW,QAAO,EAAE,QAAQ,eAAe,SAAS,MAAM,KAAK;AAG7F,UAAM,KAAK,KAAK;AAChB,SAAK,QAAQ,IAAI,IAAI,EAAE,OAAO,UAAU,KAAK,UAAU,GAAG,OAAO,EAAE,CAAC;AAEpE,UAAM,MAAM,IAAI,WAAW,CAAC;AAC5B,QAAI,SAAS,IAAI,MAAM,EAAE,UAAU,GAAG,IAAI,IAAI;AAC9C,WAAO,EAAE,QAAQ,GAAG,MAAM,IAAI;AAAA,EAChC;AAAA;AAAA,EAGA,QAAQ,QAA6D;AACnE,UAAM,SAAS,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,CAAC;AACxD,UAAM,OAAO,KAAK,cAAc,SAAS,MAAM;AAG/C,UAAM,eAAe,KAAK,aAAa,IAAI;AAC3C,QAAI,iBAAiB,GAAG;AAEtB,YAAM,aAAa,KAAK,UAAU,GAAG,KAAK,YAAY,GAAG,CAAC;AAC1D,UAAI,YAAY;AACd,aAAK,eAAe,UAAU;AAAA,MAChC;AAAA,IACF;AAEA,UAAM,OAAO,mBAAmB,EAAE,KAAK,QAAQ;AAC/C,SAAK,YAAY,MAAM,WAAW,WAAW,MAAM,CAAC;AAEpD,SAAK,cAAc;AACnB,WAAO,EAAE,QAAQ,GAAG,MAAM,QAAQ,OAAO,IAAI,EAAE;AAAA,EACjD;AAAA;AAAA,EAIQ,kBAAkB,SAA2B;AACnD,UAAM,SAAS,YAAY,MAAM,MAAM,UAAU;AACjD,UAAM,WAAqB,CAAC;AAE5B,eAAW,QAAQ,KAAK,UAAU,KAAK,GAAG;AACxC,UAAI,SAAS,QAAS;AACtB,UAAI,CAAC,KAAK,WAAW,MAAM,EAAG;AAE9B,YAAM,OAAO,KAAK,UAAU,OAAO,MAAM;AACzC,UAAI,CAAC,KAAK,SAAS,GAAG,GAAG;AACvB,iBAAS,KAAK,IAAI;AAAA,MACpB;AAAA,IACF;AAEA,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA,EAEQ,kBAAkB,SAA2B;AACnD,UAAM,SAAS,YAAY,MAAM,MAAM,UAAU;AACjD,UAAM,cAAwB,CAAC;AAE/B,eAAW,QAAQ,KAAK,UAAU,KAAK,GAAG;AACxC,UAAI,KAAK,WAAW,MAAM,EAAG,aAAY,KAAK,IAAI;AAAA,IACpD;AAGA,WAAO,YAAY,KAAK,CAAC,GAAG,MAAM;AAChC,YAAM,KAAK,EAAE,MAAM,GAAG,EAAE;AACxB,YAAM,KAAK,EAAE,MAAM,GAAG,EAAE;AACxB,aAAO,KAAK;AAAA,IACd,CAAC;AAAA,EACH;AAAA,EAEQ,aAAa,MAAsB;AACzC,UAAM,YAAY,KAAK,YAAY,GAAG;AACtC,QAAI,aAAa,EAAG,QAAO;AAE3B,UAAM,aAAa,KAAK,UAAU,GAAG,SAAS;AAC9C,UAAM,YAAY,KAAK,UAAU,IAAI,UAAU;AAC/C,QAAI,cAAc,OAAW,QAAO,eAAe;AAEnD,UAAM,cAAc,KAAK,UAAU,SAAS;AAC5C,QAAI,YAAY,SAAS,WAAW,UAAW,QAAO,eAAe;AAErE,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,WAAW,OAAqB;AAC9B,eAAW,CAAC,IAAI,KAAK,KAAK,KAAK,SAAS;AACtC,UAAI,MAAM,UAAU,OAAO;AACzB,aAAK,QAAQ,OAAO,EAAE;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,cAA+C;AAC7C,UAAM,QAAyC,CAAC;AAChD,eAAW,CAAC,MAAM,GAAG,KAAK,KAAK,WAAW;AACxC,YAAM,KAAK,EAAE,MAAM,IAAI,CAAC;AAAA,IAC1B;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,aAAa,IAA2B;AACtC,UAAM,QAAQ,KAAK,QAAQ,IAAI,EAAE;AACjC,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,QAAQ,KAAK,UAAU,MAAM,QAAQ;AAC3C,WAAO,KAAK,SAAS,MAAM,YAAY,MAAM,UAAU;AAAA,EACzD;AAAA;AAAA,EAGA,aAAa,KAAgE;AAC3E,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,UAAM,OAAO,MAAM,OAAO,IACtB,KAAK,SAAS,MAAM,YAAY,MAAM,YAAY,MAAM,IAAI,IAC5D,IAAI,WAAW,CAAC;AACpB,WAAO,EAAE,MAAM,MAAM,MAAM,MAAM,OAAO,MAAM,MAAM;AAAA,EACtD;AAAA;AAAA,EAGA,YAAyG;AACvG,UAAM,SAAsG,CAAC;AAC7G,eAAW,CAAC,MAAM,GAAG,KAAK,KAAK,WAAW;AACxC,YAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,UAAI,OAA0B;AAC9B,UAAI,MAAM,SAAS,WAAW,QAAQ,MAAM,SAAS,WAAW,SAAS;AACvE,eAAO,MAAM,OAAO,IAChB,KAAK,SAAS,MAAM,YAAY,MAAM,YAAY,MAAM,IAAI,IAC5D,IAAI,WAAW,CAAC;AAAA,MACtB;AACA,aAAO,KAAK,EAAE,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,OAAO,MAAM,MAAM,CAAC;AAAA,IACpF;AAEA,WAAO,KAAK,CAAC,GAAG,MAAM;AACpB,UAAI,EAAE,SAAS,WAAW,aAAa,EAAE,SAAS,WAAW,UAAW,QAAO;AAC/E,UAAI,EAAE,SAAS,WAAW,aAAa,EAAE,SAAS,WAAW,UAAW,QAAO;AAC/E,aAAO,EAAE,KAAK,cAAc,EAAE,IAAI;AAAA,IACpC,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAEA,QAAc;AACZ,SAAK,OAAO,MAAM;AAAA,EACpB;AACF;;;AChsDO,IAAM,KAAK;AAAA,EAChB,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,UAAU;AAAA,EACV,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,WAAW;AAAA,EACX,OAAO;AAAA,EACP,SAAS;AAAA,EACT,SAAS;AACX;AAwCA,IAAMG,WAAU,IAAI,YAAY;AAChC,IAAMC,WAAU,IAAI,YAAY;AA0CzB,SAAS,cAAc,KAK5B;AACA,QAAM,OAAO,IAAI,SAAS,GAAG;AAC7B,QAAM,KAAK,KAAK,UAAU,GAAG,IAAI;AACjC,QAAM,QAAQ,KAAK,UAAU,GAAG,IAAI;AACpC,QAAM,UAAU,KAAK,UAAU,GAAG,IAAI;AACtC,QAAM,UAAU,KAAK,UAAU,IAAI,IAAI;AAEvC,QAAM,QAAQ,IAAI,WAAW,GAAG;AAChC,QAAM,OAAOC,SAAQ,OAAO,MAAM,SAAS,IAAI,KAAK,OAAO,CAAC;AAC5D,QAAM,OAAO,UAAU,IACnB,MAAM,SAAS,KAAK,SAAS,KAAK,UAAU,OAAO,IACnD;AAEJ,SAAO,EAAE,IAAI,OAAO,MAAM,KAAK;AACjC;AAUO,SAAS,eAAe,QAAgB,MAAgC;AAC7E,QAAM,UAAU,OAAO,KAAK,aAAa;AACzC,QAAM,MAAM,IAAI,YAAY,IAAI,OAAO;AACvC,QAAM,OAAO,IAAI,SAAS,GAAG;AAE7B,OAAK,UAAU,GAAG,QAAQ,IAAI;AAC9B,OAAK,UAAU,GAAG,SAAS,IAAI;AAE/B,MAAI,MAAM;AACR,QAAI,WAAW,GAAG,EAAE,IAAI,MAAM,CAAC;AAAA,EACjC;AAEA,SAAO;AACT;AA0CO,SAAS,iBAAiB,MAA0B;AACzD,QAAM,OAAO,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU;AACvE,QAAM,UAAU,KAAK,UAAU,GAAG,IAAI;AACtC,SAAOC,SAAQ,OAAO,KAAK,SAAS,GAAG,IAAI,OAAO,CAAC;AACrD;;;AC7LA,IAAM,SAAS,IAAI,UAAU;AAG7B,IAAM,QAAQ,oBAAI,IAAyB;AAG3C,IAAI,eAAmC;AAGvC,IAAI,SAOA;AAAA,EACF,MAAM;AAAA,EACN,UAAU;AAAA,EACV,KAAK;AAAA,EACL,KAAK;AAAA,EACL,OAAO;AAAA,EACP,mBAAmB;AACrB;AAKA,SAAS,cAAc,OAAe,QAAkC;AACtE,QAAM,EAAE,IAAI,OAAO,MAAM,KAAK,IAAI,cAAc,MAAM;AAEtD,MAAI;AAEJ,UAAQ,IAAI;AAAA,IACV,KAAK,GAAG;AACN,eAAS,OAAO,KAAK,IAAI;AACzB;AAAA,IAEF,KAAK,GAAG;AACN,eAAS,OAAO,MAAM,MAAM,QAAQ,IAAI,WAAW,CAAC,GAAG,KAAK;AAC5D,qBAAe,SAAS,MAAM,IAAI;AAClC;AAAA,IAEF,KAAK,GAAG;AACN,eAAS,OAAO,OAAO,MAAM,QAAQ,IAAI,WAAW,CAAC,CAAC;AACtD,qBAAe,SAAS,MAAM,IAAI;AAClC;AAAA,IAEF,KAAK,GAAG;AACN,eAAS,OAAO,OAAO,IAAI;AAC3B,qBAAe,UAAU,IAAI;AAC7B;AAAA,IAEF,KAAK,GAAG;AACN,eAAS,OAAO,KAAK,IAAI;AACzB;AAAA,IAEF,KAAK,GAAG;AACN,eAAS,OAAO,MAAM,IAAI;AAC1B;AAAA,IAEF,KAAK,GAAG;AACN,eAAS,OAAO,MAAM,MAAM,KAAK;AACjC,qBAAe,SAAS,IAAI;AAC5B;AAAA,IAEF,KAAK,GAAG;AACN,eAAS,OAAO,MAAM,MAAM,KAAK;AACjC,qBAAe,UAAU,IAAI;AAC7B;AAAA,IAEF,KAAK,GAAG;AACN,eAAS,OAAO,QAAQ,MAAM,KAAK;AACnC;AAAA,IAEF,KAAK,GAAG,QAAQ;AACd,YAAM,UAAU,OAAO,iBAAiB,IAAI,IAAI;AAChD,eAAS,OAAO,OAAO,MAAM,OAAO;AACpC,qBAAe,UAAU,MAAM,QAAW,OAAO;AACjD;AAAA,IACF;AAAA,IAEA,KAAK,GAAG;AACN,eAAS,OAAO,OAAO,IAAI;AAC3B;AAAA,IAEF,KAAK,GAAG,UAAU;AAChB,YAAM,MAAM,OAAO,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU,EAAE,UAAU,GAAG,IAAI,IAAI;AACpG,eAAS,OAAO,SAAS,MAAM,GAAG;AAClC;AAAA,IACF;AAAA,IAEA,KAAK,GAAG,MAAM;AACZ,YAAM,WAAW,OAAO,iBAAiB,IAAI,IAAI;AACjD,eAAS,OAAO,KAAK,MAAM,UAAU,KAAK;AAC1C;AAAA,IACF;AAAA,IAEA,KAAK,GAAG;AACN,eAAS,OAAO,OAAO,MAAM,KAAK;AAClC;AAAA,IAEF,KAAK,GAAG;AACN,eAAS,OAAO,SAAS,IAAI;AAC7B;AAAA,IAEF,KAAK,GAAG,OAAO;AACb,YAAM,OAAO,OAAO,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU,EAAE,UAAU,GAAG,IAAI,IAAI;AACrG,eAAS,OAAO,MAAM,MAAM,IAAI;AAChC;AAAA,IACF;AAAA,IAEA,KAAK,GAAG,OAAO;AACb,UAAI,CAAC,QAAQ,KAAK,aAAa,GAAG;AAChC,iBAAS,EAAE,QAAQ,EAAE;AACrB;AAAA,MACF;AACA,YAAM,KAAK,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU;AACrE,YAAM,MAAM,GAAG,UAAU,GAAG,IAAI;AAChC,YAAM,MAAM,GAAG,UAAU,GAAG,IAAI;AAChC,eAAS,OAAO,MAAM,MAAM,KAAK,GAAG;AACpC;AAAA,IACF;AAAA,IAEA,KAAK,GAAG,QAAQ;AACd,UAAI,CAAC,QAAQ,KAAK,aAAa,IAAI;AACjC,iBAAS,EAAE,QAAQ,EAAE;AACrB;AAAA,MACF;AACA,YAAM,KAAK,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU;AACrE,YAAM,QAAQ,GAAG,WAAW,GAAG,IAAI;AACnC,YAAM,QAAQ,GAAG,WAAW,GAAG,IAAI;AACnC,eAAS,OAAO,OAAO,MAAM,OAAO,KAAK;AACzC;AAAA,IACF;AAAA,IAEA,KAAK,GAAG,SAAS;AACf,YAAM,SAAS,OAAO,IAAI,YAAY,EAAE,OAAO,IAAI,IAAI;AACvD,eAAS,OAAO,QAAQ,QAAQ,IAAI;AACpC;AAAA,IACF;AAAA,IAEA,KAAK,GAAG;AACN,eAAS,OAAO,SAAS,IAAI;AAC7B;AAAA,IAEF,KAAK,GAAG,MAAM;AACZ,YAAM,UAAU,OAAO,iBAAiB,IAAI,IAAI;AAChD,eAAS,OAAO,KAAK,MAAM,OAAO;AAClC;AAAA,IACF;AAAA,IAEA,KAAK,GAAG,MAAM;AACZ,eAAS,OAAO,KAAK,MAAM,OAAO,KAAK;AACvC;AAAA,IACF;AAAA,IAEA,KAAK,GAAG,OAAO;AACb,YAAM,KAAK,OAAO,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU,EAAE,UAAU,GAAG,IAAI,IAAI;AACnG,eAAS,OAAO,MAAM,EAAE;AACxB;AAAA,IACF;AAAA,IAEA,KAAK,GAAG,OAAO;AACb,UAAI,CAAC,QAAQ,KAAK,aAAa,IAAI;AACjC,iBAAS,EAAE,QAAQ,EAAE;AACrB;AAAA,MACF;AACA,YAAM,KAAK,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU;AACrE,YAAM,KAAK,GAAG,UAAU,GAAG,IAAI;AAC/B,YAAM,SAAS,GAAG,UAAU,GAAG,IAAI;AACnC,YAAM,MAAM,GAAG,SAAS,GAAG,IAAI;AAC/B,eAAS,OAAO,MAAM,IAAI,QAAQ,QAAQ,KAAK,OAAO,GAAG;AACzD;AAAA,IACF;AAAA,IAEA,KAAK,GAAG,QAAQ;AACd,UAAI,CAAC,QAAQ,KAAK,aAAa,GAAG;AAChC,iBAAS,EAAE,QAAQ,EAAE;AACrB;AAAA,MACF;AACA,YAAM,KAAK,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU;AACrE,YAAM,KAAK,GAAG,UAAU,GAAG,IAAI;AAC/B,YAAM,MAAM,GAAG,SAAS,GAAG,IAAI;AAC/B,YAAM,YAAY,KAAK,SAAS,CAAC;AACjC,eAAS,OAAO,OAAO,IAAI,WAAW,QAAQ,KAAK,OAAO,GAAG;AAC7D;AAAA,IACF;AAAA,IAEA,KAAK,GAAG,OAAO;AACb,YAAM,KAAK,OAAO,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU,EAAE,UAAU,GAAG,IAAI,IAAI;AACnG,eAAS,OAAO,MAAM,EAAE;AACxB;AAAA,IACF;AAAA,IAEA,KAAK,GAAG,WAAW;AACjB,UAAI,CAAC,QAAQ,KAAK,aAAa,GAAG;AAChC,iBAAS,EAAE,QAAQ,EAAE;AACrB;AAAA,MACF;AACA,YAAM,KAAK,IAAI,SAAS,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU;AACrE,YAAM,KAAK,GAAG,UAAU,GAAG,IAAI;AAC/B,YAAM,MAAM,GAAG,UAAU,GAAG,IAAI;AAChC,eAAS,OAAO,UAAU,IAAI,GAAG;AACjC;AAAA,IACF;AAAA,IAEA,KAAK,GAAG;AACN,eAAS,OAAO,MAAM;AACtB;AAAA,IAEF,KAAK,GAAG;AACN,eAAS,OAAO,QAAQ,MAAM,KAAK;AACnC;AAAA,IAEF,KAAK,GAAG;AACN,eAAS,OAAO,QAAQ,IAAI;AAC5B;AAAA,IAEF;AACE,eAAS,EAAE,QAAQ,EAAE;AAAA,EACzB;AAEA,QAAM,eAAe,OAAO,gBAAgB,aAAa,OAAO,OAAO;AACvE,SAAO,eAAe,OAAO,QAAQ,YAAY;AACnD;AAGA,SAAS,eACP,IACA,MACA,MACA,SACM;AACN,MAAI,CAAC,aAAc;AAEnB,QAAM,MAA+B,EAAE,IAAI,MAAM,IAAI,KAAK,IAAI,EAAE;AAChE,QAAM,YAA2B,CAAC;AAElC,MAAI,OAAO,WAAW,MAAM;AAE1B,UAAM,OAAO,KAAK,MAAM,EAAE;AAC1B,QAAI,OAAO;AACX,cAAU,KAAK,IAAI;AAAA,EACrB;AAEA,MAAI,OAAO,YAAY,SAAS;AAC9B,QAAI,UAAU;AAAA,EAChB;AAEA,eAAa,YAAY,KAAK,SAAS;AACzC;AAGA,SAAS,gBAAgB,OAAe,MAAyB;AAC/D,QAAM,IAAI,OAAO,IAAI;AAErB,OAAK,YAAY,CAAC,MAAoB;AACpC,UAAM,EAAE,QAAQ,GAAG,IAAI,EAAE;AAEzB,QAAI,kBAAkB,aAAa;AACjC,YAAM,WAAW,cAAc,OAAO,MAAM;AAC5C,WAAK,YAAY,EAAE,IAAI,QAAQ,SAAS,GAAG,CAAC,QAAQ,CAAC;AAAA,IACvD;AAAA,EACF;AAEA,OAAK,MAAM;AACb;AAGA,SAAS,UAAU,OAAqB;AACtC,SAAO,WAAW,KAAK;AACvB,QAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,MAAI,MAAM;AACR,SAAK,MAAM;AACX,UAAM,OAAO,KAAK;AAAA,EACpB;AACF;AAIA,eAAe,KAAK,UAOF;AAChB,WAAS;AAGT,MAAI,UAAU,MAAM,UAAU,QAAQ,aAAa;AAGnD,MAAI,OAAO,QAAQ,OAAO,SAAS,KAAK;AACtC,UAAM,WAAW,OAAO,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AACtD,eAAW,WAAW,UAAU;AAC9B,gBAAU,MAAM,QAAQ,mBAAmB,SAAS,EAAE,QAAQ,KAAK,CAAC;AAAA,IACtE;AAAA,EACF;AAGA,QAAM,gBAAgB,MAAM,QAAQ,cAAc,YAAY,EAAE,QAAQ,KAAK,CAAC;AAC9E,QAAM,YAAY,MAAM,cAAc,uBAAuB;AAG7D,SAAO,KAAK,WAAW;AAAA,IACrB,KAAK,OAAO;AAAA,IACZ,KAAK,OAAO;AAAA,IACZ,OAAO,OAAO;AAAA,IACd,mBAAmB,OAAO;AAAA,EAC5B,CAAC;AACH;AAIA,KAAK,YAAY,OAAO,MAAoB;AAC1C,QAAM,MAAM,EAAE;AAEd,MAAI,IAAI,SAAS,QAAQ;AACvB,UAAM,KAAK,IAAI,MAAM;AACrB,IAAC,KAA2B,YAAY,EAAE,MAAM,QAAQ,CAAC;AACzD;AAAA,EACF;AAEA,MAAI,IAAI,SAAS,QAAQ;AAEvB,oBAAgB,IAAI,OAAO,IAAI,IAAI;AACnC;AAAA,EACF;AAEA,MAAI,IAAI,SAAS,YAAY;AAC3B,cAAU,IAAI,KAAK;AACnB;AAAA,EACF;AAEA,MAAI,IAAI,SAAS,kBAAkB;AACjC,mBAAe,IAAI;AACnB,iBAAc,MAAM;AACpB;AAAA,EACF;AAGA,MAAI,IAAI,kBAAkB,aAAa;AACrC,UAAM,QAAQ,IAAI,SAAS;AAC3B,UAAM,WAAW,cAAc,OAAO,IAAI,MAAM;AAChD,IAAC,KAA2B;AAAA,MAC1B,EAAE,IAAI,IAAI,IAAI,QAAQ,SAAS;AAAA,MAC/B,CAAC,QAAQ;AAAA,IACX;AAAA,EACF;AACF;","names":["inode","data","totalSize","buf","view","offset","encoder","decoder","decoder","decoder"]}