From 6da9a6a6f5d7cff151f6972236a2a9b957753eb3 Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Tue, 3 Nov 2026 04:57:20 +0100 Subject: [PATCH] feat: add an encrypted local mail store that syncs in a worker --- .dockerignore | 5 + .gitignore | 3 + Dockerfile | 1 + lib/store/__tests__/helpers/fake-jmap.ts | 285 + lib/store/__tests__/helpers/node-adapter.ts | 36 + lib/store/__tests__/mail-sync.test.ts | 390 + lib/store/adapters/wasm.ts | 197 + lib/store/area.ts | 101 + lib/store/areas.ts | 6 + lib/store/client/keys.ts | 173 + lib/store/client/store-client.ts | 261 + lib/store/engine/account-engine.ts | 223 + lib/store/engine/changes.ts | 101 + lib/store/engine/core-schema.ts | 57 + lib/store/engine/responder.ts | 89 + lib/store/engine/transport.ts | 142 + lib/store/mail/index.ts | 11 + lib/store/mail/methods.ts | 273 + lib/store/mail/records.ts | 147 + lib/store/mail/schema.ts | 65 + lib/store/mail/search.ts | 59 + lib/store/mail/sync.ts | 323 + lib/store/sqlite-version.ts | 3 + lib/store/storage.ts | 73 + lib/store/worker/host.ts | 168 + lib/store/worker/protocol.ts | 76 + lib/store/worker/worker.ts | 147 + next.config.ts | 5 + package.json | 4 +- proxy.ts | 2 +- scripts/build-store-worker.mjs | 46 + scripts/fetch-sqlite3mc.mjs | 79 + scripts/lite/lib.mjs | 3 + vendor/sqlite3mc/2.6.1-3.54.0/LICENSE | 21 + vendor/sqlite3mc/2.6.1-3.54.0/sqlite3.mjs | 14727 ++++++++++++++++++ vendor/sqlite3mc/2.6.1-3.54.0/sqlite3.wasm | Bin 0 -> 1072003 bytes 36 files changed, 18299 insertions(+), 3 deletions(-) create mode 100644 lib/store/__tests__/helpers/fake-jmap.ts create mode 100644 lib/store/__tests__/helpers/node-adapter.ts create mode 100644 lib/store/__tests__/mail-sync.test.ts create mode 100644 lib/store/adapters/wasm.ts create mode 100644 lib/store/area.ts create mode 100644 lib/store/areas.ts create mode 100644 lib/store/client/keys.ts create mode 100644 lib/store/client/store-client.ts create mode 100644 lib/store/engine/account-engine.ts create mode 100644 lib/store/engine/changes.ts create mode 100644 lib/store/engine/core-schema.ts create mode 100644 lib/store/engine/responder.ts create mode 100644 lib/store/engine/transport.ts create mode 100644 lib/store/mail/index.ts create mode 100644 lib/store/mail/methods.ts create mode 100644 lib/store/mail/records.ts create mode 100644 lib/store/mail/schema.ts create mode 100644 lib/store/mail/search.ts create mode 100644 lib/store/mail/sync.ts create mode 100644 lib/store/sqlite-version.ts create mode 100644 lib/store/storage.ts create mode 100644 lib/store/worker/host.ts create mode 100644 lib/store/worker/protocol.ts create mode 100644 lib/store/worker/worker.ts create mode 100644 scripts/build-store-worker.mjs create mode 100644 scripts/fetch-sqlite3mc.mjs create mode 100644 vendor/sqlite3mc/2.6.1-3.54.0/LICENSE create mode 100644 vendor/sqlite3mc/2.6.1-3.54.0/sqlite3.mjs create mode 100644 vendor/sqlite3mc/2.6.1-3.54.0/sqlite3.wasm diff --git a/.dockerignore b/.dockerignore index e61ff58d2..060be0c1f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -12,11 +12,16 @@ scripts/ !scripts/lite/ !scripts/build-plugin-sandbox.mjs !scripts/build-pst-worker.mjs +!scripts/build-store-worker.mjs +!scripts/fetch-sqlite3mc.mjs !scripts/healthcheck.mjs !scripts/sourcemaps.mjs !scripts/standalone-guard.mjs # Built in the image by scripts/build-plugin-sandbox.mjs public/plugin-sandbox-assets/ +# Built in the image by scripts/build-store-worker.mjs +public/store-worker.js +public/sqlite3mc/ TODO.md *.md !README.md diff --git a/.gitignore b/.gitignore index 0914d4091..67e25a46d 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,9 @@ /public/plugin-sandbox-assets/ # scripts/build-pst-worker.mjs /public/pst-worker.js +# scripts/build-store-worker.mjs +/public/store-worker.js +/public/sqlite3mc/ # production /build diff --git a/Dockerfile b/Dockerfile index ed2713b1f..d8d5081c8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,6 +35,7 @@ RUN rm -rf "app/api/dev-jmap" && \ \( -name __tests__ -o -name "*.test.ts" -o -name "*.test.tsx" \) \ -prune -exec rm -rf {} \; && \ node scripts/build-pst-worker.mjs && \ + node scripts/build-store-worker.mjs && \ node scripts/build-plugin-sandbox.mjs && \ npx next build --webpack && \ node scripts/standalone-guard.mjs diff --git a/lib/store/__tests__/helpers/fake-jmap.ts b/lib/store/__tests__/helpers/fake-jmap.ts new file mode 100644 index 000000000..9aa917be5 --- /dev/null +++ b/lib/store/__tests__/helpers/fake-jmap.ts @@ -0,0 +1,285 @@ +/** + * A small JMAP server for engine tests, modelled on how Stalwart really + * behaves (local-data/desktop-offline-facts-parts/stalwart-changes-prf.md): + * a 5000 cap on /changes pages, fixed log ranges, the three kinds of state + * refusal, 500 ids per Email/get, 16 calls per request, `ids: null` giving the + * first 500. + */ + +import { TransportError, type JmapResponse, type JmapTransport, type MethodCall, type MethodResponse, type StoreSession } from '../../engine/transport'; + +export type FakeEmail = Record & { id: string }; + +export const JMAP_ACCOUNT = 'acc1'; + +export const FAKE_SESSION: StoreSession = { + apiUrl: 'https://fake.test/jmap/', + downloadUrl: 'https://fake.test/d/{accountId}/{blobId}/{name}?type={type}', + uploadUrl: 'https://fake.test/u/{accountId}', + primaryAccounts: { 'urn:ietf:params:jmap:mail': JMAP_ACCOUNT }, + accounts: { [JMAP_ACCOUNT]: { name: 'a@example.org', isPersonal: true, accountCapabilities: { 'urn:ietf:params:jmap:mail': {} } } }, + capabilities: { 'urn:ietf:params:jmap:mail': {} }, +}; + +type ChangeKind = 'created' | 'updated' | 'destroyed'; + +interface Log { kind: ChangeKind; id: string } + +class Collection { + log: Log[] = []; + /** Below this log position, states are refused as truncated. */ + truncatedBelow = 0; + + state(): string { + return `s${this.log.length}`; + } + + push(kind: ChangeKind, id: string): void { + this.log.push({ kind, id }); + } + + changes(since: string, maxChanges: number): { created: string[]; updated: string[]; destroyed: string[]; newState: string; hasMoreChanges: boolean } { + const from = Number(since.slice(1)); + const slice = this.log.slice(from, from + maxChanges); + const created = new Set(); + const updated = new Set(); + const destroyed = new Set(); + for (const { kind, id } of slice) { + if (kind === 'created') created.add(id); + else if (kind === 'updated') { + if (!created.has(id)) updated.add(id); + } else if (created.delete(id)) { + // Created and destroyed in the window: nowhere. + } else { + updated.delete(id); + destroyed.add(id); + } + } + const end = from + slice.length; + return { + created: [...created], + updated: [...updated], + destroyed: [...destroyed], + newState: `s${end}`, + hasMoreChanges: end < this.log.length, + }; + } +} + +export interface FakeOptions { + /** Ten mailboxes by default, a single Inbox here unless given. */ + mailboxes?: Array & { id: string }>; +} + +export class FakeJmap implements JmapTransport { + readonly emails = new Map(); + readonly mailboxes = new Map & { id: string }>(); + readonly threads = new Map(); + readonly coll = { Email: new Collection(), Mailbox: new Collection(), Thread: new Collection() }; + readonly calls: MethodCall[] = []; + requests = 0; + /** Set to make every request fail like a network drop. */ + offline = false; + /** Fails the next N requests as busy. */ + busyNext = 0; + /** Called before each request; can change data while a sync is running. */ + beforeRequest: ((n: number) => void) | null = null; + nextId = 1; + + constructor(options: FakeOptions = {}) { + for (const box of options.mailboxes ?? [{ id: 'inbox', name: 'Inbox', role: 'inbox', totalEmails: 0, unreadEmails: 0 }]) { + this.mailboxes.set(box.id, box); + this.coll.Mailbox.push('created', box.id); + } + } + + addEmail(partial: Partial = {}): FakeEmail { + const n = this.nextId++; + const id = partial.id ?? `e${n}`; + const threadId = (partial.threadId as string) ?? `t${n}`; + const email: FakeEmail = { + id, + threadId, + mailboxIds: { inbox: true }, + keywords: {}, + size: 100, + receivedAt: new Date(Date.UTC(2026, 9, 1) + n * 1000).toISOString(), + sentAt: new Date(Date.UTC(2026, 9, 1) + n * 1000).toISOString(), + from: [{ name: `Sender ${n}`, email: `s${n}@example.org` }], + to: [{ name: 'A', email: 'a@example.org' }], + cc: [], + subject: `Subject ${n}`, + preview: `Preview ${n}`, + hasAttachment: false, + blobId: `b${n}`, + textBody: [{ partId: '1', type: 'text/plain' }], + htmlBody: [{ partId: '1', type: 'text/plain' }], + bodyValues: { 1: { value: `Body of message ${n}`, isTruncated: false, isEncodingProblem: false } }, + attachments: [], + messageId: [`m${n}@example.org`], + headers: [], + bodyStructure: { partId: '1', type: 'text/plain' }, + ...partial, + }; + this.emails.set(id, email); + this.coll.Email.push('created', id); + const members = this.threads.get(threadId); + if (members) { + members.push(id); + this.coll.Thread.push('updated', threadId); + } else { + this.threads.set(threadId, [id]); + this.coll.Thread.push('created', threadId); + } + return email; + } + + updateEmail(id: string, patch: Partial): void { + Object.assign(this.emails.get(id) as FakeEmail, patch); + this.coll.Email.push('updated', id); + } + + destroyEmail(id: string): void { + const email = this.emails.get(id); + if (!email) return; + this.emails.delete(id); + this.coll.Email.push('destroyed', id); + const threadId = email.threadId as string; + const members = (this.threads.get(threadId) ?? []).filter((m) => m !== id); + if (members.length > 0) { + this.threads.set(threadId, members); + this.coll.Thread.push('updated', threadId); + } else { + this.threads.delete(threadId); + this.coll.Thread.push('destroyed', threadId); + } + } + + /** The next /changes from before this point gets cannotCalculateChanges. */ + truncateLog(type: 'Email' | 'Mailbox' | 'Thread'): void { + this.coll[type].truncatedBelow = this.coll[type].log.length; + } + + private queryIds(args: Record): string[] { + const filter = args.filter as { after?: string; inMailbox?: string } | undefined; + let list = [...this.emails.values()]; + if (filter?.after) list = list.filter((e) => Date.parse(String(e.receivedAt)) >= Date.parse(filter.after as string)); + if (filter?.inMailbox) list = list.filter((e) => (e.mailboxIds as Record)[filter.inMailbox as string]); + list.sort((a, b) => Date.parse(String(b.receivedAt)) - Date.parse(String(a.receivedAt))); + return list.map((e) => e.id); + } + + private handle(name: string, args: Record): Record { + switch (name) { + case 'Mailbox/get': { + const ids = args.ids as string[] | null; + const all = [...this.mailboxes.values()]; + const list = ids ? all.filter((b) => ids.includes(b.id)) : all; + return { accountId: args.accountId, state: this.coll.Mailbox.state(), list, notFound: [] }; + } + case 'Email/query': { + const ids = this.queryIds(args); + const position = Number(args.position ?? 0); + const limit = Number(args.limit ?? 5000) || 5000; + return { + accountId: args.accountId, + queryState: this.coll.Email.state(), + canCalculateChanges: true, + position, + ids: ids.slice(position, position + Math.min(limit, 5000)), + ...(args.calculateTotal ? { total: ids.length } : {}), + }; + } + case 'Email/get': { + const ids = args.ids as string[] | null; + if (ids && ids.length > 500) throw Object.assign(new Error('requestTooLarge'), { jmapError: 'requestTooLarge' }); + const chosen = ids ?? [...this.emails.keys()].slice(0, 500); + const properties = args.properties as string[] | undefined; + const list: Record[] = []; + const notFound: string[] = []; + for (const id of chosen) { + const email = this.emails.get(id); + if (!email) { + notFound.push(id); + continue; + } + if (!properties) { + list.push({ ...email }); + continue; + } + const out: Record = { id }; + for (const p of properties) if (p in email) out[p] = email[p]; + list.push(out); + } + return { accountId: args.accountId, state: this.coll.Email.state(), list, notFound }; + } + case 'Thread/get': { + const ids = (args.ids ?? []) as string[]; + return { + accountId: args.accountId, + state: this.coll.Thread.state(), + list: ids.filter((id) => this.threads.has(id)).map((id) => ({ id, emailIds: this.threads.get(id) })), + notFound: ids.filter((id) => !this.threads.has(id)), + }; + } + case 'Email/changes': + case 'Mailbox/changes': + case 'Thread/changes': { + const type = name.split('/')[0] as 'Email' | 'Mailbox' | 'Thread'; + const coll = this.coll[type]; + const since = String(args.sinceState); + if (!/^s\d+$/.test(since)) throw Object.assign(new Error('bad state'), { jmapError: 'invalidArguments' }); + const from = Number(since.slice(1)); + if (from < coll.truncatedBelow || from > coll.log.length) { + throw Object.assign(new Error('log truncated'), { jmapError: 'cannotCalculateChanges' }); + } + const maxChanges = Math.min(Number(args.maxChanges ?? 5000) || 5000, 5000); + return { accountId: args.accountId, oldState: since, ...coll.changes(since, maxChanges) }; + } + default: + throw Object.assign(new Error(name), { jmapError: 'unknownMethod' }); + } + } + + async request(calls: MethodCall[]): Promise { + this.requests += 1; + this.beforeRequest?.(this.requests); + if (this.offline) throw new TransportError('network', 'Failed to fetch'); + if (this.busyNext > 0) { + this.busyNext -= 1; + throw new TransportError('rate', 'Server busy', 429, undefined, 1); + } + if (calls.length > 16) throw new TransportError('http', 'too many calls', 400, 'urn:ietf:params:jmap:error:limit'); + const done: MethodResponse[] = []; + for (const call of calls) { + this.calls.push(call); + const [name, raw, id] = call; + const args: Record = {}; + for (const [key, value] of Object.entries(raw)) { + if (key.startsWith('#')) { + const ref = value as { resultOf: string; path: string }; + const source = done.find(([, , callId]) => callId === ref.resultOf); + args[key.slice(1)] = source?.[1][ref.path.slice(1)]; + } else { + args[key] = value; + } + } + try { + done.push([name, this.handle(name, args), id]); + } catch (error) { + const type = (error as { jmapError?: string }).jmapError; + if (!type) throw error; + done.push(['error', { type }, id]); + } + } + return { methodResponses: done }; + } + + async download(): Promise { + return new Uint8Array(); + } + + async upload(): Promise<{ blobId: string; type: string; size: number }> { + return { blobId: 'uploaded', type: 'application/octet-stream', size: 0 }; + } +} diff --git a/lib/store/__tests__/helpers/node-adapter.ts b/lib/store/__tests__/helpers/node-adapter.ts new file mode 100644 index 000000000..421324cfa --- /dev/null +++ b/lib/store/__tests__/helpers/node-adapter.ts @@ -0,0 +1,36 @@ +/** The storage adapter for tests: real SQLite with FTS5 through node:sqlite. */ + +import { DatabaseSync, type SQLInputValue } from 'node:sqlite'; +import { runTransaction, type SqlRow, type SqlValue, type StorageAdapter } from '../../storage'; + +export function openMemoryStore(): StorageAdapter { + return adapterFor(new DatabaseSync(':memory:')); +} + +export function openFileStore(file: string): StorageAdapter { + return adapterFor(new DatabaseSync(file)); +} + +function adapterFor(db: DatabaseSync): StorageAdapter { + const tx = { depth: 0 }; + const prepared = new Map>(); + const statement = (sql: string) => { + let stmt = prepared.get(sql); + if (!stmt) { + stmt = db.prepare(sql); + prepared.set(sql, stmt); + } + return stmt; + }; + return { + exec: (sql) => db.exec(sql), + run: (sql, params = []) => { + const result = statement(sql).run(...(params as SQLInputValue[])); + return { changes: Number(result.changes), lastInsertRowid: Number(result.lastInsertRowid) }; + }, + all: (sql: string, params: readonly SqlValue[] = []) => statement(sql).all(...(params as SQLInputValue[])) as T[], + get: (sql: string, params: readonly SqlValue[] = []) => statement(sql).get(...(params as SQLInputValue[])) as T | undefined, + transaction: (fn) => runTransaction(tx, (sql) => db.exec(sql), fn), + close: () => db.close(), + }; +} diff --git a/lib/store/__tests__/mail-sync.test.ts b/lib/store/__tests__/mail-sync.test.ts new file mode 100644 index 000000000..dd8b70728 --- /dev/null +++ b/lib/store/__tests__/mail-sync.test.ts @@ -0,0 +1,390 @@ +// @vitest-environment node +import { describe, expect, it } from 'vitest'; +import { mkdtempSync, rmSync } from 'node:fs'; +import os from 'node:os'; +import path from 'node:path'; +import { DEFAULT_SCOPE, type StoreEvent } from '../area'; +import { AccountEngine } from '../engine/account-engine'; +import { runChangesLoop } from '../engine/changes'; +import { TransportError, type MethodCall } from '../engine/transport'; +import { mailArea } from '../mail'; +import { FAKE_SESSION, FakeJmap, JMAP_ACCOUNT } from './helpers/fake-jmap'; +import { openFileStore, openMemoryStore } from './helpers/node-adapter'; + +const EVERYTHING = { ...DEFAULT_SCOPE, days: null }; +const INBOX = { inMailbox: 'inbox' }; + +function engineFor(server: FakeJmap, db = openMemoryStore(), emit?: (e: StoreEvent) => void) { + return new AccountEngine({ + account: 'a@fake.test', + db, + session: FAKE_SESSION, + transport: server, + areas: [mailArea], + scope: EVERYTHING, + emit, + now: () => Date.UTC(2026, 10, 3), + sleep: async () => {}, + }); +} + +function count(db: ReturnType, table: string): number { + return Number(db.get<{ n: number }>(`SELECT COUNT(*) AS n FROM ${table}`)?.n); +} + +function callsNamed(server: FakeJmap, name: string): MethodCall[] { + return server.calls.filter(([n]) => n === name); +} + +describe('full sync', () => { + it('stores every message, thread and body across pages', async () => { + const server = new FakeJmap(); + for (let i = 0; i < 1234; i += 1) server.addEmail(); + const db = openMemoryStore(); + await engineFor(server, db).requestSync(); + expect(count(db, 'email')).toBe(1234); + expect(count(db, 'email_body')).toBe(1234); + expect(count(db, 'thread')).toBe(1234); + expect(count(db, 'email_mailbox')).toBe(1234); + }); + + it('captures the state before paging, so a message landing mid-sync is not lost', async () => { + const server = new FakeJmap(); + for (let i = 0; i < 600; i += 1) server.addEmail(); + let landed = false; + server.beforeRequest = (n) => { + if (n === 4 && !landed) { + landed = true; + server.addEmail({ id: 'late' }); + } + }; + const db = openMemoryStore(); + await engineFor(server, db).requestSync(); + expect(landed).toBe(true); + expect(db.get('SELECT id FROM email WHERE id = ?', ['late'])).toBeTruthy(); + }); + + it('keeps only the chosen window', async () => { + const server = new FakeJmap(); + server.addEmail({ id: 'old', receivedAt: '2020-01-01T00:00:00Z' }); + server.addEmail({ id: 'new', receivedAt: '2026-10-30T00:00:00Z' }); + const db = openMemoryStore(); + const engine = new AccountEngine({ + account: 'a@fake.test', db, session: FAKE_SESSION, transport: server, areas: [mailArea], + scope: { ...DEFAULT_SCOPE, days: 30 }, now: () => Date.UTC(2026, 10, 3), sleep: async () => {}, + }); + await engine.requestSync(); + expect(db.all('SELECT id FROM email').map((r) => r.id)).toEqual(['new']); + }); +}); + +describe('persisted state', () => { + it('survives a reload and continues from the saved state with a delta', async () => { + const dir = mkdtempSync(path.join(os.tmpdir(), 'store-')); + const file = path.join(dir, 's.db'); + try { + const server = new FakeJmap(); + for (let i = 0; i < 50; i += 1) server.addEmail(); + const first = openFileStore(file); + await engineFor(server, first).requestSync(); + first.close(); + + server.addEmail({ id: 'after-reload' }); + server.calls.length = 0; + const second = openFileStore(file); + await engineFor(server, second).requestSync(); + expect(second.get('SELECT id FROM email WHERE id = ?', ['after-reload'])).toBeTruthy(); + expect(count(second, 'email')).toBe(51); + // A delta, not another full listing. + expect(callsNamed(server, 'Email/query')).toHaveLength(0); + expect(callsNamed(server, 'Email/changes').length).toBeGreaterThan(0); + second.close(); + } finally { + rmSync(dir, { recursive: true, force: true }); + } + }); + + it('resumes an interrupted full sync from its cursor', async () => { + const dir = mkdtempSync(path.join(os.tmpdir(), 'store-')); + const file = path.join(dir, 's.db'); + try { + const server = new FakeJmap(); + for (let i = 0; i < 4500; i += 1) server.addEmail(); + const first = openFileStore(file); + // Goes down after the first page of the list. + server.beforeRequest = (n) => { + if (n === 4) server.offline = true; + }; + await engineFor(server, first).requestSync(); + const listed = count(first, 'email'); + expect(listed).toBeGreaterThan(0); + expect(listed).toBeLessThan(4500); + first.close(); + + server.offline = false; + server.beforeRequest = null; + server.calls.length = 0; + const second = openFileStore(file); + await engineFor(server, second).requestSync(); + expect(count(second, 'email')).toBe(4500); + const firstQuery = callsNamed(server, 'Email/query')[0]; + expect(firstQuery[1].position).toBe(listed); + second.close(); + } finally { + rmSync(dir, { recursive: true, force: true }); + } + }); +}); + +describe('deltas', () => { + it('applies created, updated and destroyed, and leaves bodies alone on an update', async () => { + const server = new FakeJmap(); + const a = server.addEmail(); + const b = server.addEmail(); + const db = openMemoryStore(); + const engine = engineFor(server, db); + await engine.requestSync(); + + server.updateEmail(a.id, { keywords: { $seen: true } }); + server.destroyEmail(b.id); + server.addEmail({ id: 'c' }); + await engine.requestSync(); + + expect(db.all('SELECT id FROM email ORDER BY id').map((r) => r.id)).toEqual(['c', a.id]); + expect(db.get('SELECT 1 AS x FROM email_keyword WHERE keyword = ?', ['$seen'])).toBeTruthy(); + const kept = db.get<{ body_state: number }>('SELECT body_state FROM email WHERE id = ?', [a.id]); + expect(kept?.body_state).toBe(1); + // The destroyed message left nothing behind in the search index. + expect(db.all("SELECT rowid FROM email_fts_word WHERE email_fts_word MATCH ?", [`"Subject" `]).length).toBe(2); + }); + + it('pages through more changes than one call gives', async () => { + const server = new FakeJmap(); + server.addEmail(); + const db = openMemoryStore(); + const engine = engineFor(server, db); + await engine.requestSync(); + server.calls.length = 0; + for (let i = 0; i < 1500; i += 1) server.addEmail(); + await engine.requestSync(); + expect(count(db, 'email')).toBe(1501); + expect(callsNamed(server, 'Email/changes').length).toBeGreaterThanOrEqual(3); + const page = callsNamed(server, 'Email/changes')[0][1]; + expect(page.maxChanges).toBe(500); + }); + + it('sends sinceState last, because a malformed one otherwise fails the whole request on Stalwart', async () => { + const server = new FakeJmap(); + server.addEmail(); + const engine = engineFor(server); + await engine.requestSync(); + server.addEmail(); + server.calls.length = 0; + await engine.requestSync(); + const keys = Object.keys(callsNamed(server, 'Email/changes')[0][1]); + expect(keys[keys.length - 1]).toBe('sinceState'); + }); + + it('keeps going while behind the pushed state, since hasMoreChanges false does not mean caught up', async () => { + const server = new FakeJmap(); + server.addEmail(); + const applied: string[] = []; + let wrote = false; + const outcome = await runChangesLoop({ + transport: server, + type: 'Email', + jmap: JMAP_ACCOUNT, + using: [], + since: 's0', + target: 's2', + apply: async (page) => { + applied.push(page.newState); + if (!wrote) { + wrote = true; + server.addEmail(); + } + }, + }); + expect(outcome).toMatchObject({ outcome: 'caughtUp', state: 's2' }); + expect(applied).toEqual(['s1', 's2']); + }); + + it('stops when the state stands still even though the push named a newer one', async () => { + const server = new FakeJmap(); + server.addEmail(); + const outcome = await runChangesLoop({ + transport: server, type: 'Email', jmap: JMAP_ACCOUNT, using: [], since: 's1', target: 's9', + apply: async () => {}, + }); + expect(outcome.outcome).toBe('caughtUp'); + expect(server.requests).toBe(1); + }); +}); + +describe('resync', () => { + it('starts Email over on cannotCalculateChanges, keeps bodies, and drops what is gone', async () => { + const server = new FakeJmap(); + const keep = server.addEmail({ id: 'keep' }); + server.addEmail({ id: 'gone' }); + const db = openMemoryStore(); + const engine = engineFor(server, db); + await engine.requestSync(); + + server.destroyEmail('gone'); + server.updateEmail(keep.id, { keywords: { $flagged: true } }); + server.truncateLog('Email'); + server.calls.length = 0; + await engine.requestSync(); + + expect(callsNamed(server, 'Email/query').length).toBeGreaterThan(0); + expect(db.all('SELECT id FROM email').map((r) => r.id)).toEqual(['keep']); + expect(db.get('SELECT 1 AS x FROM email_keyword WHERE keyword = ?', ['$flagged'])).toBeTruthy(); + // The body wasn't fetched a second time. + const bodyFetches = callsNamed(server, 'Email/get').filter(([, a]) => a.fetchTextBodyValues); + expect(bodyFetches).toHaveLength(0); + expect(count(db, 'email_body')).toBe(1); + }); + + it.each([ + ['invalidArguments', { jmapError: 'invalidArguments' }], + ['cannotCalculateChanges', { jmapError: 'cannotCalculateChanges' }], + ])('treats %s as a reason to start over', async (_name, thrown) => { + const server = new FakeJmap(); + const original = server.request.bind(server); + let refused = false; + server.request = async (calls) => { + if (!refused && calls[0][0] === 'Email/changes') { + refused = true; + return { methodResponses: [['error', { type: thrown.jmapError }, 'c']] }; + } + return original(calls); + }; + const outcome = await runChangesLoop({ transport: server, type: 'Email', jmap: JMAP_ACCOUNT, using: [], since: 's0', apply: async () => {} }); + expect(outcome.outcome).toBe('resync'); + }); + + it('treats an HTTP 400 notRequest as a reason to start over, not as an outage', async () => { + const server = new FakeJmap(); + server.request = async () => { + throw new TransportError('http', 'bad', 400, 'urn:ietf:params:jmap:error:notRequest'); + }; + const outcome = await runChangesLoop({ transport: server, type: 'Email', jmap: JMAP_ACCOUNT, using: [], since: 's0', apply: async () => {} }); + expect(outcome.outcome).toBe('resync'); + }); + + it('never sends a stored state a server cannot have sent', async () => { + const server = new FakeJmap(); + const outcome = await runChangesLoop({ transport: server, type: 'Email', jmap: JMAP_ACCOUNT, using: [], since: 'bad state\n', apply: async () => {} }); + expect(outcome.outcome).toBe('resync'); + expect(server.requests).toBe(0); + }); +}); + +describe('when the server is busy or gone', () => { + it('backs off and carries on after a 429', async () => { + const server = new FakeJmap(); + server.addEmail(); + server.busyNext = 2; + const db = openMemoryStore(); + await engineFor(server, db).requestSync(); + expect(count(db, 'email')).toBe(1); + }); + + it('ends the run quietly when the network is gone, and picks up when back', async () => { + const server = new FakeJmap(); + server.addEmail(); + server.offline = true; + const events: StoreEvent[] = []; + const db = openMemoryStore(); + const engine = engineFor(server, db, (e) => events.push(e)); + await engine.requestSync(); + expect(count(db, 'email')).toBe(0); + expect(events.some((e) => e.type === 'error')).toBe(false); + server.offline = false; + await engine.requestSync(); + expect(count(db, 'email')).toBe(1); + }); + + it('tells the page about new mail only for messages it had not seen', async () => { + const server = new FakeJmap(); + server.addEmail(); + const events: StoreEvent[] = []; + const engine = engineFor(server, openMemoryStore(), (e) => events.push(e)); + await engine.requestSync(); + expect(events.filter((e) => e.type === 'created')).toHaveLength(0); + server.addEmail({ id: 'fresh' }); + await engine.requestSync(); + expect(events.filter((e) => e.type === 'created')).toEqual([ + { type: 'created', account: 'a@fake.test', jmap: JMAP_ACCOUNT, collection: 'Email', ids: ['fresh'] }, + ]); + }); +}); + +describe('answers from the store', () => { + async function seeded() { + const server = new FakeJmap(); + server.addEmail({ id: 'one', subject: 'Zahlungserinnerung Rechnungsbetrag', keywords: { $seen: true } }); + server.addEmail({ id: 'two', subject: 'Hello', mailboxIds: { inbox: true }, bodyValues: { 1: { value: 'See you Tuesday' } } }); + const db = openMemoryStore(); + const engine = engineFor(server, db); + await engine.requestSync(); + return { engine, db, server }; + } + + it('gives every call its own answer, in order, with a per-call error for what it cannot answer', async () => { + const { engine } = await seeded(); + const answer = await engine.answer([ + ['Email/query', { filter: INBOX, sort: [{ property: 'receivedAt', isAscending: false }], calculateTotal: true }, 'a'], + ['SieveScript/get', {}, 'b'], + ['Email/get', { '#ids': { resultOf: 'a', name: 'Email/query', path: '/ids' }, properties: ['id', 'subject'] }, 'c'], + ]); + expect(answer?.methodResponses.map(([name, , id]) => [name, id])).toEqual([ + ['Email/query', 'a'], ['error', 'b'], ['Email/get', 'c'], + ]); + expect(answer?.methodResponses[0][1]).toMatchObject({ ids: ['two', 'one'], total: 2, position: 0 }); + expect(answer?.methodResponses[1][1].type).toBe('serverUnavailable'); + expect(answer?.methodResponses[2][1].list).toEqual([ + { id: 'two', subject: 'Hello' }, + { id: 'one', subject: 'Zahlungserinnerung Rechnungsbetrag' }, + ]); + }); + + it('answers null when nothing in the request could be answered', async () => { + const { engine } = await seeded(); + expect(await engine.answer([['SieveScript/get', {}, 'a']])).toBeNull(); + }); + + it('finds a German compound from inside the word, and a word start', async () => { + const { engine } = await seeded(); + const search = async (text: string) => (await engine.answer([['Email/query', { filter: { text } }, 'q']]))?.methodResponses[0][1].ids; + expect(await search('rechnung')).toEqual(['one']); + expect(await search('erinnerung')).toEqual(['one']); + expect(await search('zahl*')).toEqual(['one']); + expect(await search('tuesday')).toEqual(['two']); + expect(await search('nichtda')).toEqual([]); + }); + + it('reads keyword sort the way the client sends it for that server', async () => { + const { engine } = await seeded(); + const sorted = async () => (await engine.answer([['Email/query', { + filter: INBOX, + sort: [{ property: 'hasKeyword', keyword: '$seen', isAscending: false }], + }, 'q']]))?.methodResponses[0][1].ids; + expect(await sorted()).toEqual(['one', 'two']); + engine.setInvertedKeywordSort(true); + expect(await sorted()).toEqual(['two', 'one']); + }); + + it('does not make up a message with empty text when the body is not kept', async () => { + const { engine, db } = await seeded(); + db.run('DELETE FROM email_body'); + const answer = await engine.answer([['Email/get', { ids: ['one'], fetchTextBodyValues: true }, 'g']]); + expect(answer?.methodResponses[0][1]).toMatchObject({ list: [], notFound: ['one'] }); + }); + + it('answers with the real server state, never a made-up one', async () => { + const { engine, server } = await seeded(); + const answer = await engine.answer([['Email/get', { ids: ['one'], properties: ['id'] }, 'g']]); + expect(answer?.methodResponses[0][1].state).toBe(server.coll.Email.state()); + }); +}); diff --git a/lib/store/adapters/wasm.ts b/lib/store/adapters/wasm.ts new file mode 100644 index 000000000..e85bf14f4 --- /dev/null +++ b/lib/store/adapters/wasm.ts @@ -0,0 +1,197 @@ +/** + * SQLite3MultipleCiphers on OPFS, for the owner tab's worker. + * + * Rules that come from bugs reproduced in 2.6.1, see + * local-data/desktop-offline-facts-parts/sqlite-wasm.md section 5: + * - PRAGMA key is the very first thing on a connection. Reading first deletes + * a hot journal (#292). + * - The page size must be 8192. On 4096, rollback doesn't work (#293). + * - No PRAGMA rekey (#291, #294). The key is random and only ever re-wrapped. + * - Always the multipleciphers VFS. On plain opfs-sahpool, PRAGMA key throws + * and the connection still writes in the clear if that's ignored. + */ + +import { runTransaction, type SqlRow, type SqlValue, type StorageAdapter } from '../storage'; + +const VFS = 'multipleciphers-opfs-sahpool'; +const INIT_TIMEOUT_MS = 30_000; +const REQUIRED_PAGE_SIZE = 8192; +const POOL_DIRECTORY = '.bulwark-store'; +const INITIAL_CAPACITY = 16; +/** A database and its journal, plus room for one more. */ +const SLOTS_PER_DATABASE = 3; + +/* eslint-disable @typescript-eslint/no-explicit-any */ + +interface Pool { + getFileNames(): string[]; + getCapacity(): number; + getFileCount(): number; + addCapacity(n: number): Promise; + unlink(name: string): boolean; + wipeFiles(): Promise; + pauseVfs(): void; + unpauseVfs(): Promise; + isPaused(): boolean; +} + +export class StoreKeyError extends Error { + constructor() { + super('The local store could not be opened with this key'); + this.name = 'StoreKeyError'; + } +} + +function withTimeout(promise: Promise, ms: number, what: string): Promise { + return new Promise((resolve, reject) => { + const timer = setTimeout(() => reject(new Error(`${what} timed out`)), ms); + promise.then((value) => { + clearTimeout(timer); + resolve(value); + }, (error) => { + clearTimeout(timer); + reject(error); + }); + }); +} + +class WasmAdapter implements StorageAdapter { + private readonly tx = { depth: 0 }; + private readonly statements = new Map(); + + constructor(private readonly sqlite3: any, private readonly db: any) {} + + exec(sql: string): void { + this.db.exec(sql); + } + + private statement(sql: string): any { + let stmt = this.statements.get(sql); + if (!stmt) { + stmt = this.db.prepare(sql); + this.statements.set(sql, stmt); + } + return stmt; + } + + private bindAndRun(sql: string, params: readonly SqlValue[] | undefined, read: (stmt: any) => T): T { + const stmt = this.statement(sql); + try { + if (params && params.length > 0) stmt.bind(params as SqlValue[]); + return read(stmt); + } finally { + stmt.reset(true); + } + } + + run(sql: string, params?: readonly SqlValue[]): { changes: number; lastInsertRowid: number } { + this.bindAndRun(sql, params, (stmt) => { + while (stmt.step()) { /* no rows wanted */ } + }); + return { + changes: Number(this.db.changes()), + lastInsertRowid: Number(this.sqlite3.capi.sqlite3_last_insert_rowid(this.db.pointer)), + }; + } + + all(sql: string, params?: readonly SqlValue[]): T[] { + return this.bindAndRun(sql, params, (stmt) => { + const rows: T[] = []; + while (stmt.step()) rows.push(stmt.get({}) as T); + return rows; + }); + } + + get(sql: string, params?: readonly SqlValue[]): T | undefined { + return this.bindAndRun(sql, params, (stmt) => (stmt.step() ? stmt.get({}) as T : undefined)); + } + + transaction(fn: () => T): T { + return runTransaction(this.tx, (sql) => this.db.exec(sql), fn); + } + + close(): void { + for (const stmt of this.statements.values()) stmt.finalize(); + this.statements.clear(); + this.db.close(); + } +} + +/** The module and the pool, once. Only the owner gets here. */ +export class WasmStorage { + private constructor(private readonly sqlite3: any, private readonly pool: Pool) {} + + /** + * Call only while holding the owner lock. The holder before may still be + * letting go, so a refusal is retried for a while. + */ + static async install(moduleUrl: string): Promise { + const { default: init } = await import(/* webpackIgnore: true */ moduleUrl) as { default: (o: unknown) => Promise }; + // A failed wasm load never settles the promise from the module's init. + const sqlite3 = await withTimeout(init({ print() {}, printErr() {} }), INIT_TIMEOUT_MS, 'Loading the store engine'); + let lastError: unknown; + for (let attempt = 0; attempt < 20; attempt += 1) { + try { + const pool = await sqlite3.installOpfsSAHPoolVfs({ + name: 'opfs-sahpool', + directory: POOL_DIRECTORY, + initialCapacity: INITIAL_CAPACITY, + preserveOnInitFailure: true, + forceReinitIfPreviouslyFailed: true, + }) as Pool; + return new WasmStorage(sqlite3, pool); + } catch (error) { + lastError = error; + await new Promise((resolve) => setTimeout(resolve, 100 + attempt * 50)); + } + } + throw lastError; + } + + /** Opens one account's database. `keyHex` is 32 random bytes in hex. */ + async open(file: string, keyHex: string): Promise { + if (!/^\/a[0-9a-f]+\.db$/.test(file)) throw new Error('Store file names carry no account data'); + if (!/^[0-9a-f]{64}$/.test(keyHex)) throw new Error('A store key is 32 bytes of hex'); + const needed = this.pool.getFileCount() + SLOTS_PER_DATABASE; + if (this.pool.getCapacity() < needed) await this.pool.addCapacity(needed - this.pool.getCapacity()); + const db = new this.sqlite3.oo1.DB({ filename: file, vfs: VFS, flags: 'c' }); + try { + db.exec(`PRAGMA key = "raw:${keyHex}"`); + try { + db.selectValue('SELECT count(*) FROM sqlite_master'); + } catch { + throw new StoreKeyError(); + } + const pageSize = Number(db.selectValue('PRAGMA page_size')); + if (pageSize !== REQUIRED_PAGE_SIZE) throw new Error(`Refusing an unsafe page size: ${pageSize}`); + db.exec('PRAGMA temp_store = MEMORY'); + db.exec('PRAGMA foreign_keys = OFF'); + db.exec('PRAGMA synchronous = NORMAL'); + } catch (error) { + db.close(); + throw error; + } + return new WasmAdapter(this.sqlite3, db); + } + + remove(file: string): boolean { + let removed = false; + for (const name of this.pool.getFileNames()) { + if (name === file || name === `${file}-journal`) removed = this.pool.unlink(name) || removed; + } + return removed; + } + + /** Lets go of the OPFS handles. Every database must be closed first. */ + pause(): void { + this.pool.pauseVfs(); + } + + async unpause(): Promise { + await this.pool.unpauseVfs(); + } + + files(): string[] { + return this.pool.getFileNames(); + } +} diff --git a/lib/store/area.ts b/lib/store/area.ts new file mode 100644 index 000000000..fa757e37d --- /dev/null +++ b/lib/store/area.ts @@ -0,0 +1,101 @@ +/** + * What one part of the local store (mail, calendar, contacts, files, ...) + * plugs into the engine: its tables, the JMAP methods it answers while the + * server can't be reached, and how it syncs. + * + * Migration id ranges: core 1-99, mail 100-199, outbox 200-299, search + * 300-399, drafts 400-499, calendar 500-599, contacts 600-699, files 700-799, + * settings and reminders 800-899, wipe and lock 900-999. + */ + +import type { JmapTransport, MethodCall, StoreSession } from './engine/transport'; +import type { Migration, StorageAdapter } from './storage'; + +export interface StoreScope { + /** How far back mail is kept, in days. Null keeps everything. */ + days: number | null; + /** Whether attachments are kept. */ + attachments: boolean; + /** The largest attachment kept, and the total for all of them. */ + maxAttachmentBytes: number; + maxTotalBytes: number; +} + +export const DEFAULT_SCOPE: StoreScope = { + days: 90, + attachments: true, + maxAttachmentBytes: 25 * 1024 * 1024, + maxTotalBytes: 2 * 1024 * 1024 * 1024, +}; + +export interface SyncStateRow { + state: string | null; + /** The newest state the server told us about, to know when a run is caught up. */ + target: string | null; + /** The area's own phase name; null when in normal delta mode. */ + phase: string | null; + /** The area's own resume point. */ + cursor: Record | null; +} + +export type StoreEvent = + | { type: 'progress'; account: string; area: string; phase: string; done: number; total: number | null } + | { type: 'synced'; account: string; at: number } + | { type: 'changed'; account: string; collections: string[] } + | { type: 'created'; account: string; jmap: string; collection: string; ids: string[] } + | { type: 'error'; account: string; area: string; message: string }; + +export interface StoreContext { + account: string; + db: StorageAdapter; + session: StoreSession; + scope: StoreScope; + now(): number; + emit(event: StoreEvent): void; +} + +export interface SyncContext extends StoreContext { + transport: JmapTransport; + /** True once the engine is closing or lost the network: stop at the next batch. */ + stopped(): boolean; + syncState(jmap: string, type: string): SyncStateRow; + /** Call inside the transaction that writes the data, so the two can't disagree. */ + setSyncState(jmap: string, type: string, row: Partial): void; +} + +export interface Syncer { + /** A short name for progress and errors. */ + name: string; + /** The JMAP capability an account must advertise for this to run for it. */ + capability: string; + /** Runs one pass for one JMAP account. Must be safe to stop between batches and start again. */ + run(ctx: SyncContext, jmap: string): Promise; +} + +export type MethodResult = Record; + +/** Thrown by a method handler: the client gets a per-call JMAP error. */ +export class MethodError extends Error { + constructor(readonly type: string, readonly description?: string) { + super(description ?? type); + this.name = 'MethodError'; + } +} + +export interface MethodContext extends StoreContext { + /** The account's own default JMAP account for calls that don't say. */ + defaultJmap: string; + /** Whether keyword sort comparators arrive inverted from this client. */ + invertedKeywordSort: boolean; + /** Earlier responses in this request, for creation-id references. */ + createdIds: Map; +} + +export type MethodHandler = (ctx: MethodContext, args: Record, call: MethodCall) => MethodResult | Promise; + +export interface StoreArea { + name: string; + migrations: readonly Migration[]; + methods: Readonly>; + syncers: readonly Syncer[]; +} diff --git a/lib/store/areas.ts b/lib/store/areas.ts new file mode 100644 index 000000000..6bff665ca --- /dev/null +++ b/lib/store/areas.ts @@ -0,0 +1,6 @@ +/** Every part of the local store. New areas go here. */ + +import type { StoreArea } from './area'; +import { mailArea } from './mail'; + +export const STORE_AREAS: readonly StoreArea[] = [mailArea]; diff --git a/lib/store/client/keys.ts b/lib/store/client/keys.ts new file mode 100644 index 000000000..ecd4fe4c2 --- /dev/null +++ b/lib/store/client/keys.ts @@ -0,0 +1,173 @@ +/** + * The per-account database keys, as the page sees them. + * + * Each account's database has a random 32-byte key. It is only ever stored + * wrapped: AES-GCM with a non-extractable key that lives in IndexedDB, then + * any extra layers on top (the desktop app's OS keychain, app lock). Forgetting + * the record makes the file unreadable even if deleting it failed. + */ + +const DB_NAME = 'bulwark-store'; +const DB_VERSION = 1; +const KEYS = 'keys'; +const ACCOUNTS = 'accounts'; +const WRAP_ID = 'wrap'; + +export interface WrapLayer { + /** A name for the layer: 'safeStorage', 'pin', 'prf'. */ + name: string; + wrap(data: Uint8Array): Promise; + unwrap(data: Uint8Array): Promise; +} + +export interface AccountRecord { + account: string; + /** `/a.db`. */ + file: string; + iv: Uint8Array; + wrapped: Uint8Array; + /** Layers applied after the WebCrypto wrap, innermost first. */ + layers: string[]; + createdAt: number; +} + +function promisify(request: IDBRequest): Promise { + return new Promise((resolve, reject) => { + request.onsuccess = () => resolve(request.result); + request.onerror = () => reject(request.error); + }); +} + +function openDb(): Promise { + const request = indexedDB.open(DB_NAME, DB_VERSION); + request.onupgradeneeded = () => { + const db = request.result; + if (!db.objectStoreNames.contains(KEYS)) db.createObjectStore(KEYS, { keyPath: 'id' }); + if (!db.objectStoreNames.contains(ACCOUNTS)) db.createObjectStore(ACCOUNTS, { keyPath: 'account' }); + }; + return promisify(request); +} + +async function withDb(fn: (db: IDBDatabase) => Promise): Promise { + const db = await openDb(); + try { + return await fn(db); + } finally { + db.close(); + } +} + +async function wrapKey(db: IDBDatabase): Promise { + const read = db.transaction(KEYS, 'readonly').objectStore(KEYS).get(WRAP_ID); + const existing = await promisify(read) as { key: CryptoKey } | undefined; + if (existing) return existing.key; + const key = await crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt']); + const tx = db.transaction(KEYS, 'readwrite'); + const store = tx.objectStore(KEYS); + // Another tab may have got there first: keep theirs. + const raced = await promisify(store.get(WRAP_ID)) as { key: CryptoKey } | undefined; + if (raced) return raced.key; + await promisify(store.put({ id: WRAP_ID, key })); + return key; +} + +function toHex(bytes: Uint8Array): string { + return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join(''); +} + +function asBuffer(bytes: Uint8Array): ArrayBuffer { + return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength) as ArrayBuffer; +} + +export function newStoreFileName(): string { + return `/a${toHex(crypto.getRandomValues(new Uint8Array(8)))}.db`; +} + +export async function getAccountRecord(account: string): Promise { + return withDb(async (db) => { + const found = await promisify(db.transaction(ACCOUNTS, 'readonly').objectStore(ACCOUNTS).get(account)) as AccountRecord | undefined; + return found ?? null; + }); +} + +export async function listAccountRecords(): Promise { + return withDb((db) => promisify(db.transaction(ACCOUNTS, 'readonly').objectStore(ACCOUNTS).getAll()) as Promise); +} + +/** The account's key in hex, created on first use. Returns the record too, for the file name. */ +export async function openAccountKey(account: string, layers: readonly WrapLayer[] = []): Promise<{ keyHex: string; record: AccountRecord }> { + return withDb(async (db) => { + const wrapping = await wrapKey(db); + const found = await promisify(db.transaction(ACCOUNTS, 'readonly').objectStore(ACCOUNTS).get(account)) as AccountRecord | undefined; + if (found) { + let data = found.wrapped; + for (const name of [...found.layers].reverse()) { + const layer = layers.find((candidate) => candidate.name === name); + if (!layer) throw new StoreKeyLayerMissingError(name); + data = await layer.unwrap(data); + } + const raw = new Uint8Array(await crypto.subtle.decrypt({ name: 'AES-GCM', iv: asBuffer(found.iv) }, wrapping, asBuffer(data))); + const keyHex = toHex(raw); + raw.fill(0); + return { keyHex, record: found }; + } + const raw = crypto.getRandomValues(new Uint8Array(32)); + const iv = crypto.getRandomValues(new Uint8Array(12)); + let wrapped = new Uint8Array(await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, wrapping, raw)); + for (const layer of layers) wrapped = new Uint8Array(await layer.wrap(wrapped)); + const record: AccountRecord = { + account, + file: newStoreFileName(), + iv, + wrapped, + layers: layers.map((layer) => layer.name), + createdAt: Date.now(), + }; + await promisify(db.transaction(ACCOUNTS, 'readwrite').objectStore(ACCOUNTS).put(record)); + const keyHex = toHex(raw); + raw.fill(0); + return { keyHex, record }; + }); +} + +/** Adds or removes wrap layers without touching the database key. */ +export async function rewrapAccountKey( + account: string, + from: readonly WrapLayer[], + to: readonly WrapLayer[], +): Promise { + await withDb(async (db) => { + const found = await promisify(db.transaction(ACCOUNTS, 'readonly').objectStore(ACCOUNTS).get(account)) as AccountRecord | undefined; + if (!found) return; + let data = found.wrapped; + for (const name of [...found.layers].reverse()) { + const layer = from.find((candidate) => candidate.name === name); + if (!layer) throw new StoreKeyLayerMissingError(name); + data = await layer.unwrap(data); + } + for (const layer of to) data = new Uint8Array(await layer.wrap(data)); + const record: AccountRecord = { ...found, wrapped: data, layers: to.map((layer) => layer.name) }; + await promisify(db.transaction(ACCOUNTS, 'readwrite').objectStore(ACCOUNTS).put(record)); + }); +} + +/** Forgets the account's key. The database file can't be read after this. */ +export async function forgetAccountKey(account: string): Promise { + await withDb((db) => promisify(db.transaction(ACCOUNTS, 'readwrite').objectStore(ACCOUNTS).delete(account)).then(() => undefined)); +} + +export class StoreKeyLayerMissingError extends Error { + constructor(readonly layer: string) { + super(`The key needs the ${layer} layer`); + this.name = 'StoreKeyLayerMissingError'; + } +} + +/** Deletes every key at sign-out. Works with no worker running, on any page. */ +export function deleteKeyDatabase(): void { + try { + indexedDB.deleteDatabase(DB_NAME); + } catch { + // Private mode or similar: nothing was stored either. + } +} diff --git a/lib/store/client/store-client.ts b/lib/store/client/store-client.ts new file mode 100644 index 000000000..2b47961a6 --- /dev/null +++ b/lib/store/client/store-client.ts @@ -0,0 +1,261 @@ +/** + * The page's side of the local store. Each tab starts its own worker, which + * waits for the owner lock. Calls go over a BroadcastChannel to whichever + * worker owns the store, including this tab's own, so a tab doesn't need to + * know whether it's the owner. A key never goes over the channel. + */ + +import type { StoreEvent, StoreScope } from '../area'; +import type { JmapResponse, MethodCall, StoreSession } from '../engine/transport'; +import { SQLITE3MC_PUBLIC_DIR } from '../sqlite-version'; +import { + RPC_CHANNEL, + type ChannelMessage, + type OpenAccountParams, + type PageToWorker, + type RpcReply, + type StoreRpc, + type StoreStatus, + type WorkerToPage, +} from '../worker/protocol'; + +const CALL_TIMEOUT_MS = 60_000; +const OWNER_WAIT_MS = 15_000; + +export class StoreOwnerGoneError extends Error { + constructor() { + super('The local store is not available in this browser window'); + this.name = 'StoreOwnerGoneError'; + } +} + +interface Pending { + resolve(value: unknown): void; + reject(error: Error): void; + timer: ReturnType; +} + +export interface StoreClientOptions { + /** NEXT_PUBLIC_BASE_PATH plus the build id, passed in so this works in tests. */ + basePath?: string; + buildId?: string; + onEvent?(event: StoreEvent): void; + /** The tab became the owner: open its accounts. */ + onOwner?(): void; + /** The worker asks for a fresh Authorization header. */ + onNeedAuth?(account: string): void; +} + +export class StoreClient { + readonly clientId = crypto.randomUUID(); + private worker: Worker | null = null; + private channel: BroadcastChannel | null = null; + private owner: string | null = null; + private isOwner = false; + private readonly pending = new Map(); + private readonly ownerWaiters: Array<() => void> = []; + + constructor(private readonly options: StoreClientOptions = {}) {} + + static supported(): boolean { + return typeof Worker === 'function' + && typeof BroadcastChannel === 'function' + && typeof navigator !== 'undefined' + && Boolean(navigator.locks) + && typeof navigator.storage?.getDirectory === 'function' + && typeof FileSystemFileHandle !== 'undefined' + && 'createSyncAccessHandle' in FileSystemFileHandle.prototype; + } + + start(): void { + if (this.worker) return; + const base = this.options.basePath ?? ''; + const query = this.options.buildId ? `?v=${encodeURIComponent(this.options.buildId)}` : ''; + this.channel = new BroadcastChannel(RPC_CHANNEL); + this.channel.onmessage = (event: MessageEvent) => this.onChannel(event.data); + this.worker = new Worker(`${base}/store-worker.js${query}`, { type: 'module' }); + this.worker.onmessage = (event: MessageEvent) => this.onWorker(event.data); + this.post({ + kind: 'init', + clientId: this.clientId, + moduleUrl: new URL(`${base}/${SQLITE3MC_PUBLIC_DIR}/sqlite3.mjs`, location.origin).href, + }); + this.bindLifecycle(); + } + + private bindLifecycle(): void { + // A clean handover when the tab goes. If this doesn't get to run, the lock + // and the handles die with the worker and the next owner retries. + addEventListener('pagehide', (event) => { + if (!event.persisted) void this.release().catch(() => {}); + }); + } + + private post(message: PageToWorker): void { + this.worker?.postMessage(message); + } + + private onWorker(message: WorkerToPage): void { + switch (message.kind) { + case 'owner': + this.isOwner = true; + this.owner = this.clientId; + this.flushOwnerWaiters(); + this.options.onOwner?.(); + break; + case 'result': { + const pending = this.pending.get(message.id); + if (!pending) return; + this.pending.delete(message.id); + clearTimeout(pending.timer); + if (message.error) { + const error = new Error(message.error); + if (message.errorName) error.name = message.errorName; + pending.reject(error); + } else { + pending.resolve(message.result); + } + break; + } + case 'need-auth': + this.options.onNeedAuth?.(message.account); + break; + case 'event': + // The owner's events also reach every other tab over the channel. + this.options.onEvent?.(message.event); + break; + } + } + + private onChannel(message: ChannelMessage): void { + switch (message.kind) { + case 'reply': + if ((message as RpcReply).to === this.clientId) this.settle(message); + break; + case 'event': + if (!this.isOwner) this.options.onEvent?.(message.event); + break; + case 'owner-changed': + this.owner = message.owner; + if (message.owner) this.flushOwnerWaiters(); + break; + default: + break; + } + } + + private settle(message: RpcReply): void { + const pending = this.pending.get(message.id); + if (!pending) return; + this.pending.delete(message.id); + clearTimeout(pending.timer); + if (message.error) pending.reject(new Error(message.error)); + else pending.resolve(message.result); + } + + private flushOwnerWaiters(): void { + for (const waiter of this.ownerWaiters.splice(0)) waiter(); + } + + private track(id: string, timeoutMs: number): Promise { + return new Promise((resolve, reject) => { + const timer = setTimeout(() => { + this.pending.delete(id); + reject(new StoreOwnerGoneError()); + }, timeoutMs); + this.pending.set(id, { resolve: resolve as (value: unknown) => void, reject, timer }); + }); + } + + private async waitForOwner(): Promise { + if (this.owner) return; + await new Promise((resolve, reject) => { + const timer = setTimeout(() => reject(new StoreOwnerGoneError()), OWNER_WAIT_MS); + this.ownerWaiters.push(() => { + clearTimeout(timer); + resolve(); + }); + }); + } + + private async rpc(method: K, params: Parameters[0]): Promise> { + await this.waitForOwner(); + const id = crypto.randomUUID(); + const result = this.track>(id, CALL_TIMEOUT_MS); + this.channel?.postMessage({ kind: 'rpc', id, from: this.clientId, method, params } as ChannelMessage); + return result; + } + + private direct(message: PageToWorker & { id: string }): Promise { + const result = this.track(message.id, CALL_TIMEOUT_MS); + this.post(message); + return result; + } + + // ---- Owner only: these carry keys or manage files ---- + + get ownsStore(): boolean { + return this.isOwner; + } + + openAccount(params: OpenAccountParams): Promise { + return this.direct({ kind: 'open', id: crypto.randomUUID(), params }); + } + + closeAccount(account: string): Promise { + return this.direct({ kind: 'close-account', id: crypto.randomUUID(), account }); + } + + removeAccount(account: string, file: string): Promise { + return this.direct({ kind: 'remove-account', id: crypto.randomUUID(), account, file }); + } + + setAuth(account: string, auth: string | null): void { + this.post({ kind: 'set-auth', account, auth }); + } + + setSession(account: string, session: StoreSession): void { + this.post({ kind: 'set-session', account, session }); + } + + setScope(account: string, scope: StoreScope): void { + this.post({ kind: 'set-scope', account, scope }); + } + + /** Hands the store over: the worker closes everything, then lets go of the lock. */ + async release(): Promise { + if (!this.worker) return; + const worker = this.worker; + if (this.isOwner) { + await this.direct({ kind: 'release', id: crypto.randomUUID() }); + this.isOwner = false; + this.owner = null; + } + worker.terminate(); + this.worker = null; + this.channel?.close(); + this.channel = null; + } + + // ---- Any tab ---- + + answer(account: string, calls: MethodCall[]): Promise { + return this.rpc('answer', { account, calls }); + } + + sync(account: string): Promise { + return this.rpc('sync', { account }); + } + + noteStateChange(account: string, changed: Record>): Promise { + return this.rpc('noteStateChange', { account, changed }); + } + + setOnline(online: boolean): Promise { + return this.rpc('setOnline', { online }); + } + + status(account: string): Promise { + return this.rpc('status', { account }); + } +} diff --git a/lib/store/engine/account-engine.ts b/lib/store/engine/account-engine.ts new file mode 100644 index 000000000..3b460e3a0 --- /dev/null +++ b/lib/store/engine/account-engine.ts @@ -0,0 +1,223 @@ +/** + * One local account in the store: its database, its sync runs, its answers. + * It acts as a JMAP client toward the real server and as a JMAP server toward + * the UI. Nothing here touches the DOM, so tests run it on node:sqlite. + */ + +import { MethodError, type MethodHandler, type StoreArea, type StoreEvent, type StoreScope, type SyncContext, type SyncStateRow, type Syncer } from '../area'; +import { migrate, type StorageAdapter } from '../storage'; +import { answerRequest, buildMethodTable } from './responder'; +import { TransportError, type JmapResponse, type JmapTransport, type MethodCall, type StoreSession } from './transport'; +import { CORE_MIGRATIONS, metaGet, metaSet } from './core-schema'; + +export interface AccountEngineOptions { + account: string; + db: StorageAdapter; + session: StoreSession; + transport: JmapTransport; + areas: readonly StoreArea[]; + scope: StoreScope; + invertedKeywordSort?: boolean; + emit?: (event: StoreEvent) => void; + now?: () => number; + /** Waits before a retry after the server said it's busy. Tests pass a stub. */ + sleep?: (ms: number) => Promise; +} + +const RATE_RETRIES = 5; +const RATE_BACKOFF_MS = 2_000; + +export class AccountEngine { + readonly account: string; + private readonly db: StorageAdapter; + private session: StoreSession; + private scope: StoreScope; + private readonly transport: JmapTransport; + private readonly syncers: readonly Syncer[]; + private readonly methods: ReadonlyMap; + private readonly emitter: (event: StoreEvent) => void; + private readonly now: () => number; + private readonly sleep: (ms: number) => Promise; + private invertedKeywordSort: boolean; + private closed = false; + private online = true; + private running: Promise | null = null; + private again = false; + + constructor(options: AccountEngineOptions) { + this.account = options.account; + this.db = options.db; + this.session = options.session; + this.scope = options.scope; + this.transport = options.transport; + this.syncers = options.areas.flatMap((area) => area.syncers); + this.methods = buildMethodTable(options.areas); + this.emitter = options.emit ?? (() => {}); + this.now = options.now ?? Date.now; + this.sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms))); + this.invertedKeywordSort = options.invertedKeywordSort ?? false; + migrate(this.db, [...CORE_MIGRATIONS, ...options.areas.flatMap((area) => area.migrations)]); + metaSet(this.db, 'session', JSON.stringify(options.session)); + } + + /** The session kept from the last time, for a start without a network. */ + static storedSession(db: StorageAdapter): StoreSession | null { + migrate(db, CORE_MIGRATIONS); + const raw = metaGet(db, 'session'); + return raw ? JSON.parse(raw) as StoreSession : null; + } + + setSession(session: StoreSession): void { + this.session = session; + metaSet(this.db, 'session', JSON.stringify(session)); + } + + setScope(scope: StoreScope): void { + this.scope = scope; + metaSet(this.db, 'scope', JSON.stringify(scope)); + } + + setInvertedKeywordSort(inverted: boolean): void { + this.invertedKeywordSort = inverted; + } + + setOnline(online: boolean): void { + this.online = online; + if (online) this.requestSync(); + } + + private syncState(jmap: string, type: string): SyncStateRow { + const row = this.db.get<{ state: string | null; target: string | null; phase: string | null; cursor: string | null }>( + 'SELECT state, target, phase, cursor FROM sync_state WHERE jmap = ? AND type = ?', + [jmap, type], + ); + return { + state: row?.state ?? null, + target: row?.target ?? null, + phase: row?.phase ?? null, + cursor: row?.cursor ? JSON.parse(row.cursor) as Record : null, + }; + } + + private setSyncState(jmap: string, type: string, patch: Partial): void { + const row = { ...this.syncState(jmap, type), ...patch }; + this.db.run( + `INSERT INTO sync_state (jmap, type, state, target, phase, cursor, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?) + ON CONFLICT (jmap, type) DO UPDATE SET state = excluded.state, target = excluded.target, phase = excluded.phase, + cursor = excluded.cursor, updated_at = excluded.updated_at`, + [jmap, type, row.state, row.target, row.phase, row.cursor ? JSON.stringify(row.cursor) : null, this.now()], + ); + } + + /** What the server pushed: jmap account id to { type: state }. */ + noteStateChange(changed: Record>): void { + this.db.transaction(() => { + for (const [jmap, types] of Object.entries(changed)) { + for (const [type, state] of Object.entries(types)) this.setSyncState(jmap, type, { target: state }); + } + }); + this.requestSync(); + } + + /** Starts a run, or asks the running one to go again when it's done. */ + requestSync(): Promise { + if (this.closed) return Promise.resolve(); + if (this.running) { + this.again = true; + return this.running; + } + this.running = this.runLoop().finally(() => { + this.running = null; + }); + return this.running; + } + + private async runLoop(): Promise { + do { + this.again = false; + await this.runOnce(); + } while (this.again && !this.closed && this.online); + } + + private async runOnce(): Promise { + if (!this.online) return; + const ctx = this.syncContext(); + const jmapAccounts = Object.keys(this.session.accounts); + for (const syncer of this.syncers) { + for (const jmap of jmapAccounts) { + const capabilities = this.session.accounts[jmap].accountCapabilities ?? this.session.capabilities; + if (!(syncer.capability in capabilities)) continue; + if (this.closed || !this.online) return; + if (!(await this.runSyncer(ctx, syncer, jmap))) return; + } + } + if (!this.closed && this.online) this.emitter({ type: 'synced', account: this.account, at: this.now() }); + } + + /** False when the run should end: no network, no credentials. */ + private async runSyncer(ctx: SyncContext, syncer: Syncer, jmap: string): Promise { + for (let attempt = 0; ; attempt += 1) { + try { + await syncer.run(ctx, jmap); + return true; + } catch (error) { + if (error instanceof TransportError) { + if (error.kind === 'network' || error.kind === 'auth') return false; + if (error.kind === 'rate' && attempt < RATE_RETRIES) { + await this.sleep(error.retryAfterMs ?? RATE_BACKOFF_MS * 2 ** attempt); + continue; + } + } + // One part failing doesn't hold up the others. It runs again next time. + this.emitter({ + type: 'error', + account: this.account, + area: syncer.name, + message: error instanceof Error ? error.message : String(error), + }); + return true; + } + } + } + + private syncContext(): SyncContext { + return { + account: this.account, + db: this.db, + session: this.session, + scope: this.scope, + transport: this.transport, + now: this.now, + emit: this.emitter, + stopped: () => this.closed || !this.online, + syncState: (jmap, type) => this.syncState(jmap, type), + setSyncState: (jmap, type, row) => this.setSyncState(jmap, type, row), + }; + } + + /** An answer from the device. Null when nothing in the request could be answered. */ + async answer(calls: MethodCall[]): Promise { + if (this.closed) throw new MethodError('serverUnavailable', 'The local store is closed'); + const primary = this.session.primaryAccounts['urn:ietf:params:jmap:mail'] ?? Object.keys(this.session.accounts)[0]; + return answerRequest( + { + account: this.account, + db: this.db, + session: this.session, + scope: this.scope, + now: this.now, + emit: this.emitter, + defaultJmap: primary, + invertedKeywordSort: this.invertedKeywordSort, + }, + this.methods, + calls, + ); + } + + /** Stops syncing and waits for the current batch. The database stays open for the caller to close. */ + async close(): Promise { + this.closed = true; + await this.running?.catch(() => {}); + } +} diff --git a/lib/store/engine/changes.ts b/lib/store/engine/changes.ts new file mode 100644 index 000000000..a14b7ca17 --- /dev/null +++ b/lib/store/engine/changes.ts @@ -0,0 +1,101 @@ +/** + * The /changes loop, written for how servers really answer (see + * local-data/desktop-offline-facts-parts/stalwart-changes-prf.md): + * + * - sinceState goes last: on Stalwart a malformed state followed by more + * arguments is an HTTP 400 that fails the whole request. + * - hasMoreChanges false doesn't mean caught up. A page walks a fixed range of + * the log, so the loop also runs while newState differs from the state the + * server last pushed. + * - An unusable state comes as cannotCalculateChanges, invalidArguments or that + * HTTP 400. All three mean: start this type over. + */ + +import { JmapMethodError, responseFor, TransportError, type JmapTransport } from './transport'; + +export interface ChangesPage { + created: string[]; + updated: string[]; + destroyed: string[]; + newState: string; + /** Set when only these properties changed (Mailbox counts). */ + updatedProperties: string[] | null; +} + +export interface ChangesLoopOptions { + transport: JmapTransport; + type: string; + jmap: string; + using: string[]; + since: string; + /** The newest state the server pushed, if any. */ + target?: string | null; + maxChanges?: number; + stopped?: () => boolean; + /** Stores one page and its newState. Runs to completion before the next call. */ + apply(page: ChangesPage): Promise; +} + +export type ChangesOutcome = + | { outcome: 'caughtUp'; state: string; pages: number } + | { outcome: 'stopped'; state: string; pages: number } + | { outcome: 'resync'; state: string; pages: number }; + +const MAX_PAGES_PAST_TARGET = 3; + +/** A stored state a server can't have sent: don't send it, it can fail the whole request. */ +export function isUsableState(state: unknown): state is string { + return typeof state === 'string' && state.length > 0 && state.length < 1024 && /^[\w.~+=:/-]+$/.test(state); +} + +function isStateRefusal(error: unknown): boolean { + if (error instanceof JmapMethodError) { + return error.type === 'cannotCalculateChanges' || error.type === 'invalidArguments'; + } + if (error instanceof TransportError) { + return error.kind === 'http' && error.status === 400 && /notRequest/.test(error.problem ?? ''); + } + return false; +} + +export async function runChangesLoop(options: ChangesLoopOptions): Promise { + const { transport, type, jmap, using, target } = options; + const maxChanges = options.maxChanges ?? 500; + let state = options.since; + let pages = 0; + let pastTarget = 0; + if (!isUsableState(state)) return { outcome: 'resync', state, pages }; + for (;;) { + if (options.stopped?.()) return { outcome: 'stopped', state, pages }; + let page: ChangesPage & { hasMoreChanges: boolean }; + try { + const response = await transport.request( + [[`${type}/changes`, { accountId: jmap, maxChanges, sinceState: state }, 'c']], + using, + ); + const [, result] = responseFor(response, 'c'); + page = { + created: result.created ?? [], + updated: result.updated ?? [], + destroyed: result.destroyed ?? [], + newState: String(result.newState), + updatedProperties: Array.isArray(result.updatedProperties) ? result.updatedProperties : null, + hasMoreChanges: Boolean(result.hasMoreChanges), + }; + } catch (error) { + if (isStateRefusal(error)) return { outcome: 'resync', state, pages }; + throw error; + } + const before = state; + await options.apply(page); + state = page.newState; + pages += 1; + if (page.hasMoreChanges) continue; + if (!target || state === target) return { outcome: 'caughtUp', state, pages }; + // Behind the pushed state: the log moved on while we paged. A state that + // stands still means the server has nothing more for this type. + if (state === before) return { outcome: 'caughtUp', state, pages }; + pastTarget += 1; + if (pastTarget >= MAX_PAGES_PAST_TARGET) return { outcome: 'caughtUp', state, pages }; + } +} diff --git a/lib/store/engine/core-schema.ts b/lib/store/engine/core-schema.ts new file mode 100644 index 000000000..938f4baa2 --- /dev/null +++ b/lib/store/engine/core-schema.ts @@ -0,0 +1,57 @@ +import type { Migration, StorageAdapter } from '../storage'; + +export const CORE_MIGRATIONS: readonly Migration[] = [ + { + id: 1, + name: 'core', + sql: ` + CREATE TABLE meta (k TEXT PRIMARY KEY, v TEXT) WITHOUT ROWID; + CREATE TABLE sync_state ( + jmap TEXT NOT NULL, + type TEXT NOT NULL, + state TEXT, + target TEXT, + phase TEXT, + cursor TEXT, + updated_at INTEGER NOT NULL, + PRIMARY KEY (jmap, type) + ) WITHOUT ROWID; + CREATE TABLE object ( + jmap TEXT NOT NULL, + type TEXT NOT NULL, + id TEXT NOT NULL, + json TEXT NOT NULL, + PRIMARY KEY (jmap, type, id) + ) WITHOUT ROWID; + `, + }, +]; + +export function metaGet(db: StorageAdapter, key: string): string | null { + return db.get<{ v: string | null }>('SELECT v FROM meta WHERE k = ?', [key])?.v ?? null; +} + +export function metaSet(db: StorageAdapter, key: string, value: string | null): void { + db.run('INSERT INTO meta (k, v) VALUES (?, ?) ON CONFLICT (k) DO UPDATE SET v = excluded.v', [key, value]); +} + +export function putObject(db: StorageAdapter, jmap: string, type: string, id: string, value: unknown): void { + db.run( + 'INSERT INTO object (jmap, type, id, json) VALUES (?, ?, ?, ?) ON CONFLICT (jmap, type, id) DO UPDATE SET json = excluded.json', + [jmap, type, id, JSON.stringify(value)], + ); +} + +export function deleteObject(db: StorageAdapter, jmap: string, type: string, id: string): void { + db.run('DELETE FROM object WHERE jmap = ? AND type = ? AND id = ?', [jmap, type, id]); +} + +export function getObject>(db: StorageAdapter, jmap: string, type: string, id: string): T | null { + const row = db.get<{ json: string }>('SELECT json FROM object WHERE jmap = ? AND type = ? AND id = ?', [jmap, type, id]); + return row ? JSON.parse(row.json) as T : null; +} + +export function listObjects>(db: StorageAdapter, jmap: string, type: string): T[] { + return db.all<{ json: string }>('SELECT json FROM object WHERE jmap = ? AND type = ?', [jmap, type]) + .map((row) => JSON.parse(row.json) as T); +} diff --git a/lib/store/engine/responder.ts b/lib/store/engine/responder.ts new file mode 100644 index 000000000..be03dc5db --- /dev/null +++ b/lib/store/engine/responder.ts @@ -0,0 +1,89 @@ +/** + * Answers a JMAP request from the local store: the store acting as a server + * toward the UI. Every call gets its own answer, in order, as a server would: + * one the store can't answer gets a per-call error and the rest still work. + */ + +import { MethodError, type MethodContext, type MethodHandler, type MethodResult, type StoreArea } from '../area'; +import type { JmapResponse, MethodCall, MethodResponse } from './transport'; + +class BadReference extends Error {} + +/** RFC 8620 §3.7 result references, with the `*` array step. */ +export function resolvePointer(value: unknown, path: string): unknown { + const steps = path.split('/').slice(1).map((s) => s.replace(/~1/g, '/').replace(/~0/g, '~')); + const walk = (node: unknown, i: number): unknown => { + if (i === steps.length) return node; + const step = steps[i]; + if (step === '*') { + if (!Array.isArray(node)) throw new BadReference(); + return node.flatMap((item) => { + const out = walk(item, i + 1); + return Array.isArray(out) ? out : [out]; + }); + } + if (node === null || typeof node !== 'object') throw new BadReference(); + return walk((node as Record)[step], i + 1); + }; + return walk(value, 0); +} + +function resolveArgs(args: Record, done: readonly MethodResponse[]): Record { + const out: Record = {}; + for (const [key, value] of Object.entries(args)) { + if (!key.startsWith('#')) { + out[key] = value; + continue; + } + const ref = value as { resultOf?: string; name?: string; path?: string }; + const source = done.find(([name, , id]) => id === ref.resultOf && name === ref.name); + if (!source || typeof ref.path !== 'string') throw new BadReference(); + out[key.slice(1)] = resolvePointer(source[1], ref.path); + } + return out; +} + +export function buildMethodTable(areas: readonly StoreArea[]): Map { + const table = new Map(); + for (const area of areas) { + for (const [name, handler] of Object.entries(area.methods)) { + if (table.has(name)) throw new Error(`Two store areas answer ${name}`); + table.set(name, handler); + } + } + return table; +} + +/** Answers are copied by structured clone on the way to the page, so callers can't mutate stored objects. */ +export async function answerRequest( + ctx: Omit, + methods: ReadonlyMap, + calls: readonly MethodCall[], +): Promise { + const done: MethodResponse[] = []; + const full: MethodContext = { ...ctx, createdIds: new Map() }; + let answered = 0; + for (const call of calls) { + const [name, rawArgs, callId] = call; + const handler = methods.get(name); + if (!handler) { + done.push(['error', { type: 'serverUnavailable', description: `${name} needs the server` }, callId]); + continue; + } + try { + const args = resolveArgs(rawArgs, done); + const result: MethodResult = await handler(full, args, call); + done.push([name, result, callId]); + answered += 1; + } catch (error) { + if (error instanceof BadReference) { + done.push(['error', { type: 'invalidResultReference' }, callId]); + } else if (error instanceof MethodError) { + done.push(['error', { type: error.type, description: error.description }, callId]); + } else { + throw error; + } + } + } + return answered === 0 ? null : { methodResponses: done }; +} diff --git a/lib/store/engine/transport.ts b/lib/store/engine/transport.ts new file mode 100644 index 000000000..cc55ff300 --- /dev/null +++ b/lib/store/engine/transport.ts @@ -0,0 +1,142 @@ +/** + * The engine's way to the real JMAP server. Bulk sync runs in the worker with + * its own fetch, so large JSON isn't parsed on the main thread. Auth stays + * with the page: it hands over the header and refreshes it on request. + */ + +export type MethodCall = [string, Record, string]; +// Shaped like the server's answer (any per method, as the callers read it). +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type MethodResponse = [string, any, string]; + +export interface JmapResponse { + methodResponses: MethodResponse[]; + sessionState?: string; +} + +/** The parts of a JMAP session the engine uses. */ +export interface StoreSession { + apiUrl: string; + downloadUrl: string; + uploadUrl: string; + primaryAccounts: Record; + accounts: Record }>; + capabilities: Record; +} + +export type TransportFailure = 'network' | 'auth' | 'rate' | 'http'; + +export class TransportError extends Error { + constructor( + readonly kind: TransportFailure, + message: string, + readonly status?: number, + /** The `type` of an RFC 7807 problem body, when there was one. */ + readonly problem?: string, + readonly retryAfterMs?: number, + ) { + super(message); + this.name = 'TransportError'; + } +} + +export interface JmapTransport { + request(calls: MethodCall[], using: string[]): Promise; + download(jmap: string, blobId: string, type: string, name: string): Promise; + upload(jmap: string, data: Uint8Array, type: string): Promise<{ blobId: string; type: string; size: number }>; +} + +export interface FetchTransportOptions { + session(): StoreSession; + /** The current Authorization header value, or null when the page has none yet. */ + auth(): string | null; + /** Asks the page for a fresh header; resolves null when it can't get one. */ + refreshAuth(): Promise; + fetch?: typeof fetch; +} + +const REQUEST_TIMEOUT_MS = 120_000; + +function fillTemplate(template: string, values: Record): string { + return template.replace(/\{(\w+)\}/g, (whole, key: string) => (key in values ? encodeURIComponent(values[key]) : whole)); +} + +export class FetchTransport implements JmapTransport { + constructor(private readonly options: FetchTransportOptions) {} + + private async fetchWithAuth(url: string, init: RequestInit): Promise { + const doFetch = this.options.fetch ?? fetch; + const send = async (header: string | null): Promise => { + if (!header) throw new TransportError('auth', 'No credentials yet'); + const signal = AbortSignal.timeout(REQUEST_TIMEOUT_MS); + try { + return await doFetch(url, { ...init, signal, headers: { ...init.headers, Authorization: header } }); + } catch (error) { + throw new TransportError('network', error instanceof Error ? error.message : 'Network failure'); + } + }; + let response = await send(this.options.auth()); + if (response.status === 401) { + response = await send(await this.options.refreshAuth()); + if (response.status === 401) throw new TransportError('auth', 'The server refused the credentials', 401); + } + if (response.status === 429 || response.status === 503) { + const seconds = Number(response.headers.get('Retry-After')); + throw new TransportError('rate', `Server busy (${response.status})`, response.status, undefined, Number.isFinite(seconds) && seconds > 0 ? seconds * 1000 : undefined); + } + return response; + } + + async request(calls: MethodCall[], using: string[]): Promise { + const response = await this.fetchWithAuth(this.options.session().apiUrl, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ using, methodCalls: calls }), + }); + if (!response.ok) { + let problem: string | undefined; + try { + problem = (await response.json() as { type?: string }).type; + } catch { + // Not a problem document. + } + throw new TransportError('http', `JMAP request failed: ${response.status}`, response.status, problem); + } + return await response.json() as JmapResponse; + } + + async download(jmap: string, blobId: string, type: string, name: string): Promise { + const url = fillTemplate(this.options.session().downloadUrl, { accountId: jmap, blobId, type, name }); + const response = await this.fetchWithAuth(url, { method: 'GET' }); + if (!response.ok) throw new TransportError('http', `Download failed: ${response.status}`, response.status); + return new Uint8Array(await response.arrayBuffer()); + } + + async upload(jmap: string, data: Uint8Array, type: string): Promise<{ blobId: string; type: string; size: number }> { + const url = fillTemplate(this.options.session().uploadUrl, { accountId: jmap }); + const response = await this.fetchWithAuth(url, { + method: 'POST', + headers: { 'Content-Type': type || 'application/octet-stream' }, + body: data as BodyInit, + }); + if (!response.ok) throw new TransportError('http', `Upload failed: ${response.status}`, response.status); + return await response.json() as { blobId: string; type: string; size: number }; + } +} + +/** Finds the response to one call. Throws if the server answered it with an error. */ +export function responseFor(response: JmapResponse, callId: string): MethodResponse { + const found = response.methodResponses.find(([name, , id]) => id === callId && name !== 'error'); + if (found) return found; + const failed = response.methodResponses.find(([, , id]) => id === callId); + if (failed) throw new JmapMethodError(String(failed[1]?.type ?? 'serverFail'), failed[1]?.description); + throw new JmapMethodError('serverFail', `No response for call ${callId}`); +} + +/** The server answered a call with a method-level error. */ +export class JmapMethodError extends Error { + constructor(readonly type: string, description?: string) { + super(description ? `${type}: ${description}` : type); + this.name = 'JmapMethodError'; + } +} diff --git a/lib/store/mail/index.ts b/lib/store/mail/index.ts new file mode 100644 index 000000000..e76d61d28 --- /dev/null +++ b/lib/store/mail/index.ts @@ -0,0 +1,11 @@ +import type { StoreArea } from '../area'; +import { MAIL_METHODS } from './methods'; +import { MAIL_MIGRATIONS } from './schema'; +import { mailSyncer } from './sync'; + +export const mailArea: StoreArea = { + name: 'mail', + migrations: MAIL_MIGRATIONS, + methods: MAIL_METHODS, + syncers: [mailSyncer], +}; diff --git a/lib/store/mail/methods.ts b/lib/store/mail/methods.ts new file mode 100644 index 000000000..e91bdd45c --- /dev/null +++ b/lib/store/mail/methods.ts @@ -0,0 +1,273 @@ +/** Mail reads answered from the store. */ + +import { MethodError, type MethodContext, type MethodHandler, type MethodResult } from '../area'; +import { listObjects } from '../engine/core-schema'; +import type { SqlValue } from '../storage'; +import { textCondition, type TextField } from './search'; + +type Filter = Record; + +interface Sql { sql: string; params: SqlValue[] } + +const TEXT_FIELDS: readonly TextField[] = ['text', 'subject', 'from', 'to', 'body']; + +function jmapOf(ctx: MethodContext, args: Record): string { + return (args.accountId as string | undefined) ?? ctx.defaultJmap; +} + +function filterSql(filter: Filter, jmap: string): Sql { + if (typeof filter.operator === 'string') { + const conditions = Array.isArray(filter.conditions) ? filter.conditions as Filter[] : []; + const parts = conditions.map((c) => filterSql(c, jmap)); + const params = parts.flatMap((p) => p.params); + const joined = (joiner: string) => parts.map((p) => `(${p.sql})`).join(joiner); + if (filter.operator === 'AND') return { sql: parts.length ? joined(' AND ') : '1', params }; + if (filter.operator === 'OR') return { sql: parts.length ? joined(' OR ') : '0', params }; + if (filter.operator === 'NOT') return { sql: parts.length ? `NOT (${joined(' OR ')})` : '1', params }; + throw new MethodError('unsupportedFilter', `Unknown operator ${String(filter.operator)}`); + } + const conditions: string[] = []; + const params: SqlValue[] = []; + for (const [key, value] of Object.entries(filter)) { + switch (key) { + case 'inMailbox': + conditions.push('EXISTS (SELECT 1 FROM email_mailbox m WHERE m.email_rowid = e.rowid AND m.mailbox_id = ?)'); + params.push(String(value)); + break; + case 'inMailboxOtherThan': { + const ids = (value as string[]).map(String); + conditions.push(`EXISTS (SELECT 1 FROM email_mailbox m WHERE m.email_rowid = e.rowid AND m.mailbox_id NOT IN (${ids.map(() => '?').join(',') || "''"}))`); + params.push(...ids); + break; + } + case 'hasKeyword': + conditions.push('EXISTS (SELECT 1 FROM email_keyword k WHERE k.email_rowid = e.rowid AND k.keyword = ?)'); + params.push(String(value).toLowerCase()); + break; + case 'notKeyword': + conditions.push('NOT EXISTS (SELECT 1 FROM email_keyword k WHERE k.email_rowid = e.rowid AND k.keyword = ?)'); + params.push(String(value).toLowerCase()); + break; + case 'after': + conditions.push('e.received_at >= ?'); + params.push(Date.parse(String(value)) || 0); + break; + case 'before': + conditions.push('e.received_at < ?'); + params.push(Date.parse(String(value)) || 0); + break; + case 'minSize': + conditions.push('e.size >= ?'); + params.push(Number(value)); + break; + case 'maxSize': + conditions.push('e.size < ?'); + params.push(Number(value)); + break; + case 'hasAttachment': + conditions.push(value ? 'e.has_attachment = 1' : 'e.has_attachment = 0'); + break; + case 'id': + conditions.push(`e.id IN (${(value as string[]).map(() => '?').join(',') || "''"})`); + params.push(...(value as string[]).map(String)); + break; + default: + if ((TEXT_FIELDS as readonly string[]).includes(key)) { + const text = textCondition(key as TextField, String(value)); + conditions.push(text.sql); + params.push(...text.params); + break; + } + // cc, bcc, header and the thread keyword filters: the server's job. + throw new MethodError('unsupportedFilter', `${key} isn't available offline`); + } + } + return { sql: conditions.length ? conditions.join(' AND ') : '1', params }; +} + +interface Comparator { property?: string; isAscending?: boolean; keyword?: string } + +function orderSql(ctx: MethodContext, sort: Comparator[]): Sql { + const levels = sort.length > 0 ? sort : [{ property: 'receivedAt', isAscending: false }]; + const parts: string[] = []; + const params: SqlValue[] = []; + for (const level of levels) { + // RFC 8621 says isAscending defaults to true. + let ascending = level.isAscending !== false; + switch (level.property) { + case 'receivedAt': parts.push(`e.received_at ${ascending ? 'ASC' : 'DESC'}`); break; + case 'sentAt': parts.push(`COALESCE(e.sent_at, e.received_at) ${ascending ? 'ASC' : 'DESC'}`); break; + case 'size': parts.push(`e.size ${ascending ? 'ASC' : 'DESC'}`); break; + case 'subject': parts.push(`e.subject_sort COLLATE NOCASE ${ascending ? 'ASC' : 'DESC'}`); break; + case 'from': parts.push(`e.from_sort COLLATE NOCASE ${ascending ? 'ASC' : 'DESC'}`); break; + case 'to': parts.push(`e.to_sort COLLATE NOCASE ${ascending ? 'ASC' : 'DESC'}`); break; + case 'hasKeyword': { + // The client flips this on servers that read it the other way, so a + // stored answer has to read it the way that server would. + if (ctx.invertedKeywordSort) ascending = !ascending; + parts.push(`EXISTS (SELECT 1 FROM email_keyword s WHERE s.email_rowid = e.rowid AND s.keyword = ?) ${ascending ? 'ASC' : 'DESC'}`); + params.push(String(level.keyword ?? '').toLowerCase()); + break; + } + default: + throw new MethodError('unsupportedSort', `${String(level.property)} isn't available offline`); + } + } + parts.push('e.rowid DESC'); + return { sql: parts.join(', '), params }; +} + +/** The one folder a filter limits itself to, so the query can start from that folder's index. */ +function drivingMailbox(filter: Filter | undefined): string | null { + if (!filter) return null; + if (typeof filter.inMailbox === 'string') return filter.inMailbox; + if (filter.operator === 'AND' && Array.isArray(filter.conditions)) { + for (const condition of filter.conditions as Filter[]) { + const found = drivingMailbox(condition); + if (found) return found; + } + } + return null; +} + +const emailQuery: MethodHandler = (ctx, args) => { + const jmap = jmapOf(ctx, args); + const filter = (args.filter ?? undefined) as Filter | undefined; + if (args.anchor !== undefined) throw new MethodError('unsupportedFilter', 'anchor needs the server'); + const where = filter ? filterSql(filter, jmap) : { sql: '1', params: [] }; + const order = orderSql(ctx, (args.sort as Comparator[]) ?? []); + const box = drivingMailbox(filter); + // Starting from the folder's own index keeps small folders fast in a large account. + const from = box + ? 'email_mailbox d INDEXED BY email_mailbox_list CROSS JOIN email e ON e.rowid = d.email_rowid' + : 'email e'; + const base = box + ? { sql: 'd.jmap = ? AND d.mailbox_id = ?', params: [jmap, box] as SqlValue[] } + : { sql: 'e.jmap = ?', params: [jmap] as SqlValue[] }; + const position = Math.max(0, Number(args.position ?? 0)); + const limit = typeof args.limit === 'number' && args.limit > 0 ? args.limit : -1; + const collapse = Boolean(args.collapseThreads); + const group = collapse ? 'GROUP BY COALESCE(e.thread_id, e.id)' : ''; + const ids = ctx.db.all<{ id: string }>( + `SELECT e.id FROM ${from} WHERE ${base.sql} AND (${where.sql}) ${group} ORDER BY ${order.sql} LIMIT ? OFFSET ?`, + [...base.params, ...where.params, ...order.params, limit, position], + ).map((row) => String(row.id)); + const result: MethodResult = { + accountId: jmap, + canCalculateChanges: false, + // Local answers aren't a position in the server's log, so this is a token only. + queryState: 'local', + position, + ids, + }; + if (args.calculateTotal) { + const count = collapse ? 'COUNT(DISTINCT COALESCE(e.thread_id, e.id))' : 'COUNT(*)'; + result.total = Number(ctx.db.get<{ n: number }>( + `SELECT ${count} AS n FROM ${from} WHERE ${base.sql} AND (${where.sql})`, + [...base.params, ...where.params], + )?.n ?? 0); + } + return result; +}; + +const BODY_PROPERTIES = new Set(['bodyValues', 'textBody', 'htmlBody', 'bodyStructure', 'headers', 'attachments', 'bcc', 'replyTo', 'messageId', 'inReplyTo', 'references']); + +function pick(email: Record, properties: string[] | undefined): Record { + if (!properties) return email; + const out: Record = { id: email.id }; + for (const property of properties) if (property in email) out[property] = email[property]; + return out; +} + +const emailGet: MethodHandler = (ctx, args) => { + const jmap = jmapOf(ctx, args); + if (!Array.isArray(args.ids)) throw new MethodError('requestTooLarge', 'ids: null needs the server'); + const properties = args.properties as string[] | undefined; + const wantsValues = Boolean(args.fetchTextBodyValues || args.fetchHTMLBodyValues || args.fetchAllBodyValues) || Boolean(properties?.includes('bodyValues')); + const wantsBody = wantsValues || !properties || properties.some((p) => BODY_PROPERTIES.has(p)); + const list: Record[] = []; + const notFound: string[] = []; + for (const id of args.ids as string[]) { + const row = ctx.db.get<{ rowid: number; json: string; body_state: number }>( + 'SELECT rowid, json, body_state FROM email WHERE jmap = ? AND id = ?', + [jmap, id], + ); + if (!row) { + notFound.push(id); + continue; + } + const email = JSON.parse(row.json) as Record; + if (!wantsBody) { + list.push(pick(email, properties)); + continue; + } + const body = ctx.db.get<{ json: string }>('SELECT json FROM email_body WHERE email_rowid = ?', [row.rowid]); + // Asked for the text and it isn't here: as if the message weren't there, not an empty message. + if (!body && wantsValues) { + notFound.push(id); + continue; + } + list.push(pick({ ...(body ? JSON.parse(body.json) as object : {}), ...email }, properties)); + } + const state = ctx.db.get<{ state: string | null }>("SELECT state FROM sync_state WHERE jmap = ? AND type = 'Email'", [jmap])?.state; + return { accountId: jmap, ...(state ? { state } : {}), list, notFound }; +}; + +const threadGet: MethodHandler = (ctx, args) => { + const jmap = jmapOf(ctx, args); + const ids = Array.isArray(args.ids) ? [...new Set(args.ids as string[])] : []; + const list: Array<{ id: string; emailIds: string[] }> = []; + const notFound: string[] = []; + for (const id of ids) { + const stored = ctx.db.get<{ email_ids: string }>('SELECT email_ids FROM thread WHERE jmap = ? AND id = ?', [jmap, id]); + if (stored) { + list.push({ id, emailIds: JSON.parse(stored.email_ids) as string[] }); + continue; + } + const rows = ctx.db.all<{ id: string }>('SELECT id FROM email WHERE jmap = ? AND thread_id = ? ORDER BY received_at ASC', [jmap, id]); + if (rows.length > 0) list.push({ id, emailIds: rows.map((row) => String(row.id)) }); + else notFound.push(id); + } + return { accountId: jmap, list, notFound }; +}; + +const mailboxGet: MethodHandler = (ctx, args) => { + const jmap = jmapOf(ctx, args); + const boxes = listObjects>(ctx.db, jmap, 'Mailbox'); + if (boxes.length === 0) throw new MethodError('serverUnavailable', 'Folders not kept yet'); + const ids = Array.isArray(args.ids) ? new Set(args.ids as string[]) : null; + const chosen = ids ? boxes.filter((box) => ids.has(box.id as string)) : boxes; + const state = ctx.db.get<{ state: string | null }>("SELECT state FROM sync_state WHERE jmap = ? AND type = 'Mailbox'", [jmap])?.state; + return { + accountId: jmap, + ...(state ? { state } : {}), + list: chosen.map((box) => pick(box, args.properties as string[] | undefined)), + notFound: ids ? [...ids].filter((id) => !boxes.some((box) => box.id === id)) : [], + }; +}; + +const mailboxQuery: MethodHandler = (ctx, args) => { + const jmap = jmapOf(ctx, args); + const boxes = listObjects>(ctx.db, jmap, 'Mailbox'); + if (boxes.length === 0) throw new MethodError('serverUnavailable', 'Folders not kept yet'); + const filter = (args.filter ?? {}) as { role?: string }; + const chosen = filter.role ? boxes.filter((box) => box.role === filter.role) : boxes; + const position = typeof args.position === 'number' ? args.position : 0; + const limit = typeof args.limit === 'number' ? args.limit : chosen.length; + return { + accountId: jmap, + queryState: 'local', + canCalculateChanges: false, + position, + ids: chosen.slice(position, position + limit).map((box) => box.id), + ...(args.calculateTotal ? { total: chosen.length } : {}), + }; +}; + +export const MAIL_METHODS: Readonly> = { + 'Email/query': emailQuery, + 'Email/get': emailGet, + 'Thread/get': threadGet, + 'Mailbox/get': mailboxGet, + 'Mailbox/query': mailboxQuery, +}; diff --git a/lib/store/mail/records.ts b/lib/store/mail/records.ts new file mode 100644 index 000000000..b0e292718 --- /dev/null +++ b/lib/store/mail/records.ts @@ -0,0 +1,147 @@ +/** How an Email object becomes rows, and back. */ + +import type { StorageAdapter } from '../storage'; + +export const MAIL_USING = ['urn:ietf:params:jmap:core', 'urn:ietf:params:jmap:mail']; + +export const EMAIL_LIST_PROPERTIES = [ + 'id', 'threadId', 'mailboxIds', 'keywords', 'size', 'receivedAt', 'sentAt', 'from', 'to', 'cc', + 'subject', 'preview', 'hasAttachment', 'blobId', 'header:Authentication-Results:all', +]; + +/** What opening a message asks for, past the list properties. */ +export const EMAIL_BODY_PROPERTIES = [ + 'bcc', 'replyTo', 'textBody', 'htmlBody', 'bodyValues', 'attachments', 'messageId', 'inReplyTo', + 'references', 'headers', 'bodyStructure', +]; + +export type EmailObject = Record & { id: string }; + +interface Address { name?: string | null; email?: string | null } + +function firstAddress(value: unknown): string | null { + const first = Array.isArray(value) ? value[0] as Address | undefined : undefined; + const text = first?.name || first?.email; + return text ? text.toLowerCase() : null; +} + +function addressText(value: unknown): string { + if (!Array.isArray(value)) return ''; + return (value as Address[]).map((a) => [a.name, a.email].filter(Boolean).join(' ')).join(' '); +} + +function time(value: unknown): number | null { + if (typeof value !== 'string') return null; + const ms = Date.parse(value); + return Number.isFinite(ms) ? ms : null; +} + +/** The subject without Re:, Fwd: and the like, as the client sorts it. */ +export function baseSubject(subject: string): string { + return subject.replace(/^(\s*(re|aw|fw|fwd|wg)\s*(\[\d+\])?\s*:\s*)+/i, '').trim().toLowerCase(); +} + +/** Inserts or updates one message from its list properties. Keeps a body already stored. */ +export function upsertEmail(db: StorageAdapter, jmap: string, email: EmailObject, gen: number): number { + const receivedAt = time(email.receivedAt) ?? 0; + const subject = typeof email.subject === 'string' ? email.subject : ''; + const existing = db.get<{ rowid: number }>('SELECT rowid FROM email WHERE jmap = ? AND id = ?', [jmap, email.id]); + const values = [ + typeof email.threadId === 'string' ? email.threadId : null, + receivedAt, + time(email.sentAt), + typeof email.size === 'number' ? email.size : 0, + email.hasAttachment ? 1 : 0, + baseSubject(subject), + firstAddress(email.from), + firstAddress(email.to), + JSON.stringify(email), + gen, + ]; + let rowid: number; + if (existing) { + rowid = Number(existing.rowid); + db.run( + `UPDATE email SET thread_id = ?, received_at = ?, sent_at = ?, size = ?, has_attachment = ?, subject_sort = ?, + from_sort = ?, to_sort = ?, json = ?, gen = ? WHERE rowid = ?`, + [...values, rowid], + ); + db.run('DELETE FROM email_mailbox WHERE email_rowid = ?', [rowid]); + db.run('DELETE FROM email_keyword WHERE email_rowid = ?', [rowid]); + } else { + rowid = db.run( + `INSERT INTO email (thread_id, received_at, sent_at, size, has_attachment, subject_sort, from_sort, to_sort, json, gen, jmap, id) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + [...values, jmap, email.id], + ).lastInsertRowid; + indexEmail(db, rowid, email, ''); + } + for (const [box, on] of Object.entries((email.mailboxIds ?? {}) as Record)) { + if (on) db.run('INSERT INTO email_mailbox (email_rowid, jmap, mailbox_id, received_at) VALUES (?, ?, ?, ?)', [rowid, jmap, box, receivedAt]); + } + for (const [keyword, on] of Object.entries((email.keywords ?? {}) as Record)) { + if (on) db.run('INSERT INTO email_keyword (email_rowid, keyword) VALUES (?, ?)', [rowid, keyword.toLowerCase()]); + } + return rowid; +} + +export function deleteEmail(db: StorageAdapter, jmap: string, id: string): void { + const row = db.get<{ rowid: number }>('SELECT rowid FROM email WHERE jmap = ? AND id = ?', [jmap, id]); + if (!row) return; + deleteEmailRow(db, Number(row.rowid)); +} + +export function deleteEmailRow(db: StorageAdapter, rowid: number): void { + db.run('DELETE FROM email_fts_word WHERE rowid = ?', [rowid]); + db.run('DELETE FROM email_fts_tri WHERE rowid = ?', [rowid]); + // Explicit rather than ON DELETE CASCADE: foreign keys stay off for bulk speed. + db.run('DELETE FROM email_mailbox WHERE email_rowid = ?', [rowid]); + db.run('DELETE FROM email_keyword WHERE email_rowid = ?', [rowid]); + db.run('DELETE FROM email_body WHERE email_rowid = ?', [rowid]); + db.run('DELETE FROM email WHERE rowid = ?', [rowid]); +} + +/** Plain text of a message for the search index: the text part, or the HTML part without its tags. */ +export function bodyText(email: Record): string { + const values = (email.bodyValues ?? {}) as Record; + const parts = (key: string) => ((email[key] ?? []) as Array<{ partId?: string; type?: string }>); + const text = parts('textBody') + .filter((part) => part.type !== 'text/html') + .map((part) => values[part.partId ?? '']?.value ?? '') + .join('\n'); + if (text.trim()) return text; + return parts('htmlBody') + .map((part) => values[part.partId ?? '']?.value ?? '') + .join('\n') + .replace(/<(style|script)[\s\S]*?<\/\1>/gi, ' ') + .replace(/<[^>]+>/g, ' ') + .replace(/ /g, ' ') + .replace(/&/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/\s+/g, ' '); +} + +/** A long message past this is rare and only bloats the index. */ +const INDEX_BODY_CHARS = 200_000; + +export function indexEmail(db: StorageAdapter, rowid: number, email: Record, body: string): void { + const subject = typeof email.subject === 'string' ? email.subject : ''; + const from = addressText(email.from); + const to = [addressText(email.to), addressText(email.cc), addressText(email.bcc)].filter(Boolean).join(' '); + const text = body.slice(0, INDEX_BODY_CHARS); + for (const table of ['email_fts_word', 'email_fts_tri']) { + db.run(`INSERT INTO ${table} (rowid, subject, from_addr, to_addr, body) VALUES (?, ?, ?, ?, ?)`, [rowid, subject, from, to, text]); + } +} + +export function storeBody(db: StorageAdapter, rowid: number, listJson: string, full: Record): void { + const list = JSON.parse(listJson) as Record; + const body: Record = {}; + for (const [key, value] of Object.entries(full)) if (!(key in list)) body[key] = value; + db.run('INSERT INTO email_body (email_rowid, json) VALUES (?, ?) ON CONFLICT (email_rowid) DO UPDATE SET json = excluded.json', [rowid, JSON.stringify(body)]); + db.run('UPDATE email SET body_state = 1 WHERE rowid = ?', [rowid]); + db.run('DELETE FROM email_fts_word WHERE rowid = ?', [rowid]); + db.run('DELETE FROM email_fts_tri WHERE rowid = ?', [rowid]); + indexEmail(db, rowid, { ...list, ...body }, bodyText(full)); +} diff --git a/lib/store/mail/schema.ts b/lib/store/mail/schema.ts new file mode 100644 index 000000000..52ef16dde --- /dev/null +++ b/lib/store/mail/schema.ts @@ -0,0 +1,65 @@ +import type { Migration } from '../storage'; + +export const MAIL_MIGRATIONS: readonly Migration[] = [ + { + id: 100, + name: 'mail', + sql: ` + CREATE TABLE email ( + rowid INTEGER PRIMARY KEY, + jmap TEXT NOT NULL, + id TEXT NOT NULL, + thread_id TEXT, + received_at INTEGER NOT NULL, + sent_at INTEGER, + size INTEGER NOT NULL DEFAULT 0, + has_attachment INTEGER NOT NULL DEFAULT 0, + subject_sort TEXT, + from_sort TEXT, + to_sort TEXT, + json TEXT NOT NULL, + -- 0 no body yet, 1 kept, 2 the server had none to give + body_state INTEGER NOT NULL DEFAULT 0, + gen INTEGER NOT NULL DEFAULT 0, + UNIQUE (jmap, id) + ); + CREATE INDEX email_received ON email (jmap, received_at DESC); + CREATE INDEX email_thread ON email (jmap, thread_id); + CREATE INDEX email_backfill ON email (jmap, body_state, received_at DESC); + CREATE TABLE email_mailbox ( + email_rowid INTEGER NOT NULL REFERENCES email (rowid) ON DELETE CASCADE, + jmap TEXT NOT NULL, + mailbox_id TEXT NOT NULL, + received_at INTEGER NOT NULL, + PRIMARY KEY (email_rowid, mailbox_id) + ) WITHOUT ROWID; + CREATE INDEX email_mailbox_list ON email_mailbox (jmap, mailbox_id, received_at DESC); + CREATE TABLE email_keyword ( + email_rowid INTEGER NOT NULL REFERENCES email (rowid) ON DELETE CASCADE, + keyword TEXT NOT NULL, + PRIMARY KEY (email_rowid, keyword) + ) WITHOUT ROWID; + CREATE INDEX email_keyword_lookup ON email_keyword (keyword, email_rowid); + CREATE TABLE email_body ( + email_rowid INTEGER PRIMARY KEY REFERENCES email (rowid) ON DELETE CASCADE, + json TEXT NOT NULL + ); + CREATE TABLE thread ( + jmap TEXT NOT NULL, + id TEXT NOT NULL, + email_ids TEXT NOT NULL, + PRIMARY KEY (jmap, id) + ) WITHOUT ROWID; + CREATE VIRTUAL TABLE email_fts_word USING fts5( + subject, from_addr, to_addr, body, + content = '', contentless_delete = 1, + tokenize = 'unicode61 remove_diacritics 2' + ); + CREATE VIRTUAL TABLE email_fts_tri USING fts5( + subject, from_addr, to_addr, body, + content = '', contentless_delete = 1, + tokenize = 'trigram remove_diacritics 1' + ); + `, + }, +]; diff --git a/lib/store/mail/search.ts b/lib/store/mail/search.ts new file mode 100644 index 000000000..57b94f849 --- /dev/null +++ b/lib/store/mail/search.ts @@ -0,0 +1,59 @@ +/** Full-text matching over the two FTS indexes. */ + +import type { SqlValue } from '../storage'; + +export type TextField = 'text' | 'subject' | 'from' | 'to' | 'body'; + +const COLUMNS: Record = { + text: null, + subject: 'subject', + from: 'from_addr', + to: 'to_addr', + body: 'body', +}; + +function quote(term: string): string { + return `"${term.replace(/"/g, '""')}"`; +} + +/** The terms of a search box value: quoted phrases stay whole, `word*` keeps its star. */ +export function splitTerms(input: string): string[] { + const out: string[] = []; + for (const match of input.matchAll(/"([^"]+)"|(\S+)/g)) out.push(match[1] ?? match[2]); + return out; +} + +/** + * One term as SQL over rowids. The word index finds words and word starts, + * the trigram index finds a term inside a longer word, which is how German + * compounds are found ("Rechnung" in "Zahlungserinnerungsrechnung"). + */ +function termRowids(field: TextField, term: string): { sql: string; params: SqlValue[] } { + const column = COLUMNS[field]; + const star = term.endsWith('*'); + const clean = star ? term.slice(0, -1) : term; + const scope = column ? `${column} : ` : ''; + const word = `${scope}${quote(clean)}${' *'.slice(1)}`; + const parts = ['SELECT rowid FROM email_fts_word WHERE email_fts_word MATCH ?']; + const params: SqlValue[] = [word]; + // Trigrams need three characters. Shorter terms use the word index alone. + if ([...clean].length >= 3) { + parts.push('SELECT rowid FROM email_fts_tri WHERE email_fts_tri MATCH ?'); + params.push(`${scope}${quote(clean)}`); + } + return { sql: parts.join(' UNION '), params }; +} + +/** SQL for a text condition, as a condition on `e.rowid`. Every term has to match. */ +export function textCondition(field: TextField, input: string): { sql: string; params: SqlValue[] } { + const terms = splitTerms(input); + if (terms.length === 0) return { sql: '1', params: [] }; + const conditions: string[] = []; + const params: SqlValue[] = []; + for (const term of terms) { + const part = termRowids(field, term); + conditions.push(`e.rowid IN (${part.sql})`); + params.push(...part.params); + } + return { sql: conditions.join(' AND '), params }; +} diff --git a/lib/store/mail/sync.ts b/lib/store/mail/sync.ts new file mode 100644 index 000000000..21ad9bb0d --- /dev/null +++ b/lib/store/mail/sync.ts @@ -0,0 +1,323 @@ +/** + * Mail sync for one JMAP account. + * + * A full sync captures the state first, then pages through the window, so a + * change that lands during it is picked up by the delta afterwards. Its cursor + * lives in sync_state, written in the same transaction as the page, so a + * reload continues where it stopped. Bodies come after the list, newest first. + */ + +import type { SyncContext, Syncer } from '../area'; +import { deleteObject, putObject } from '../engine/core-schema'; +import { runChangesLoop } from '../engine/changes'; +import { responseFor, type MethodCall } from '../engine/transport'; +import { + deleteEmail, + deleteEmailRow, + EMAIL_BODY_PROPERTIES, + EMAIL_LIST_PROPERTIES, + MAIL_USING, + storeBody, + upsertEmail, + type EmailObject, +} from './records'; + +const PAGE = 500; +const PAIRS_PER_REQUEST = 4; +const BODY_BATCH_IDS = 100; +const BODY_BATCH_BYTES = 8 * 1024 * 1024; +const MAX_BODY_VALUE_BYTES = 1_000_000; +const DELTA_BATCH = 500; + +function windowFilter(ctx: SyncContext): Record | undefined { + if (ctx.scope.days === null) return undefined; + return { after: new Date(ctx.now() - ctx.scope.days * 86_400_000).toISOString() }; +} + +function inWindow(ctx: SyncContext, email: EmailObject): boolean { + if (ctx.scope.days === null) return true; + return (Date.parse(String(email.receivedAt)) || 0) >= ctx.now() - ctx.scope.days * 86_400_000; +} + +// ---- Mailboxes ---- + +async function fullMailboxes(ctx: SyncContext, jmap: string): Promise { + const response = await ctx.transport.request([['Mailbox/get', { accountId: jmap, ids: null }, 'm']], MAIL_USING); + const [, result] = responseFor(response, 'm'); + ctx.db.transaction(() => { + ctx.db.run("DELETE FROM object WHERE jmap = ? AND type = 'Mailbox'", [jmap]); + for (const box of result.list as Array<{ id: string }>) putObject(ctx.db, jmap, 'Mailbox', box.id, box); + ctx.setSyncState(jmap, 'Mailbox', { state: String(result.state), phase: null, cursor: null }); + }); +} + +async function syncMailboxes(ctx: SyncContext, jmap: string): Promise { + const { state, target } = ctx.syncState(jmap, 'Mailbox'); + if (!state) return fullMailboxes(ctx, jmap); + const outcome = await runChangesLoop({ + transport: ctx.transport, + type: 'Mailbox', + jmap, + using: MAIL_USING, + since: state, + target, + stopped: ctx.stopped, + apply: async (page) => { + const ids = [...page.created, ...page.updated]; + const list: Array<{ id: string }> = []; + for (let i = 0; i < ids.length; i += PAGE) { + const response = await ctx.transport.request([['Mailbox/get', { accountId: jmap, ids: ids.slice(i, i + PAGE) }, 'm']], MAIL_USING); + list.push(...responseFor(response, 'm')[1].list); + } + ctx.db.transaction(() => { + for (const box of list) putObject(ctx.db, jmap, 'Mailbox', box.id, box); + for (const id of page.destroyed) deleteObject(ctx.db, jmap, 'Mailbox', id); + ctx.setSyncState(jmap, 'Mailbox', { state: page.newState }); + }); + }, + }); + if (outcome.outcome === 'resync') await fullMailboxes(ctx, jmap); +} + +// ---- Email list ---- + +interface ListCursor { position: number; gen: number; captured: string } + +async function startFullList(ctx: SyncContext, jmap: string): Promise { + const response = await ctx.transport.request([['Email/get', { accountId: jmap, ids: [], properties: ['id'] }, 's']], MAIL_USING); + const captured = String(responseFor(response, 's')[1].state); + const gen = (ctx.db.get<{ gen: number | null }>('SELECT MAX(gen) AS gen FROM email WHERE jmap = ?', [jmap])?.gen ?? 0) + 1; + const cursor: ListCursor = { position: 0, gen: Number(gen), captured }; + ctx.db.transaction(() => ctx.setSyncState(jmap, 'Email', { state: null, phase: 'list', cursor: { ...cursor } })); + return cursor; +} + +async function runFullList(ctx: SyncContext, jmap: string, start: ListCursor): Promise { + const cursor = { ...start }; + const filter = windowFilter(ctx); + let total: number | null = null; + for (;;) { + if (ctx.stopped()) return false; + const calls: MethodCall[] = []; + for (let i = 0; i < PAIRS_PER_REQUEST; i += 1) { + calls.push(['Email/query', { + accountId: jmap, + ...(filter ? { filter } : {}), + sort: [{ property: 'receivedAt', isAscending: false }], + position: cursor.position + i * PAGE, + limit: PAGE, + calculateTotal: i === 0, + }, `q${i}`]); + calls.push(['Email/get', { + accountId: jmap, + '#ids': { resultOf: `q${i}`, name: 'Email/query', path: '/ids' }, + properties: EMAIL_LIST_PROPERTIES, + }, `g${i}`]); + } + const response = await ctx.transport.request(calls, MAIL_USING); + let done = false; + let got = 0; + const lists: EmailObject[][] = []; + for (let i = 0; i < PAIRS_PER_REQUEST; i += 1) { + const [, query] = responseFor(response, `q${i}`); + if (i === 0 && typeof query.total === 'number') total = query.total; + lists.push(responseFor(response, `g${i}`)[1].list as EmailObject[]); + got += (query.ids as string[]).length; + if ((query.ids as string[]).length < PAGE) { + done = true; + break; + } + } + cursor.position += got; + ctx.db.transaction(() => { + for (const list of lists) for (const email of list) upsertEmail(ctx.db, jmap, email, cursor.gen); + if (done) { + // Whatever this pass didn't see is gone from the server or the window. + const stale = ctx.db.all<{ rowid: number }>('SELECT rowid FROM email WHERE jmap = ? AND gen < ?', [jmap, cursor.gen]); + for (const row of stale) deleteEmailRow(ctx.db, Number(row.rowid)); + ctx.setSyncState(jmap, 'Email', { state: cursor.captured, phase: null, cursor: null }); + } else { + ctx.setSyncState(jmap, 'Email', { cursor: { ...cursor } }); + } + }); + ctx.emit({ type: 'progress', account: ctx.account, area: 'mail', phase: 'list', done: cursor.position, total }); + if (done) { + ctx.emit({ type: 'changed', account: ctx.account, collections: ['Email'] }); + return true; + } + } +} + +async function syncEmailDelta(ctx: SyncContext, jmap: string, since: string, target: string | null): Promise<'done' | 'resync' | 'stopped'> { + const outcome = await runChangesLoop({ + transport: ctx.transport, + type: 'Email', + jmap, + using: MAIL_USING, + since, + target, + stopped: ctx.stopped, + apply: async (page) => { + const ids = [...page.created, ...page.updated]; + const fetched: EmailObject[] = []; + for (let i = 0; i < ids.length; i += DELTA_BATCH) { + const response = await ctx.transport.request([['Email/get', { + accountId: jmap, + ids: ids.slice(i, i + DELTA_BATCH), + properties: EMAIL_LIST_PROPERTIES, + }, 'g']], MAIL_USING); + fetched.push(...responseFor(response, 'g')[1].list as EmailObject[]); + } + const created = new Set(page.created); + const newIds: string[] = []; + ctx.db.transaction(() => { + for (const email of fetched) { + const known = ctx.db.get('SELECT 1 AS x FROM email WHERE jmap = ? AND id = ?', [jmap, email.id]); + // An old message changing doesn't pull it into the window. + if (!known && !inWindow(ctx, email)) continue; + const gen = Number(ctx.db.get<{ gen: number | null }>('SELECT MAX(gen) AS gen FROM email WHERE jmap = ?', [jmap])?.gen ?? 0); + upsertEmail(ctx.db, jmap, email, gen); + if (!known && created.has(email.id)) newIds.push(email.id); + } + for (const id of page.destroyed) deleteEmail(ctx.db, jmap, id); + ctx.setSyncState(jmap, 'Email', { state: page.newState }); + }); + if (newIds.length > 0) ctx.emit({ type: 'created', account: ctx.account, jmap, collection: 'Email', ids: newIds }); + if (ids.length + page.destroyed.length > 0) ctx.emit({ type: 'changed', account: ctx.account, collections: ['Email'] }); + }, + }); + if (outcome.outcome === 'resync') return 'resync'; + return outcome.outcome === 'stopped' ? 'stopped' : 'done'; +} + +// ---- Threads ---- + +async function fetchThreads(ctx: SyncContext, jmap: string, ids: string[]): Promise> { + const out: Array<{ id: string; emailIds: string[] }> = []; + for (let i = 0; i < ids.length; i += PAGE) { + const response = await ctx.transport.request([['Thread/get', { accountId: jmap, ids: ids.slice(i, i + PAGE) }, 't']], MAIL_USING); + out.push(...responseFor(response, 't')[1].list); + } + return out; +} + +async function syncThreads(ctx: SyncContext, jmap: string): Promise { + const { state, target } = ctx.syncState(jmap, 'Thread'); + const fullThreads = async () => { + const response = await ctx.transport.request([['Thread/get', { accountId: jmap, ids: [] }, 's']], MAIL_USING); + const captured = String(responseFor(response, 's')[1].state); + const known = ctx.db.all<{ id: string }>( + `SELECT DISTINCT e.thread_id AS id FROM email e WHERE e.jmap = ? AND e.thread_id IS NOT NULL + AND NOT EXISTS (SELECT 1 FROM thread t WHERE t.jmap = e.jmap AND t.id = e.thread_id)`, + [jmap], + ).map((row) => String(row.id)); + for (let i = 0; i < known.length; i += PAGE) { + if (ctx.stopped()) return; + const list = await fetchThreads(ctx, jmap, known.slice(i, i + PAGE)); + ctx.db.transaction(() => { + for (const thread of list) ctx.db.run('INSERT OR REPLACE INTO thread (jmap, id, email_ids) VALUES (?, ?, ?)', [jmap, thread.id, JSON.stringify(thread.emailIds)]); + }); + ctx.emit({ type: 'progress', account: ctx.account, area: 'mail', phase: 'threads', done: i + list.length, total: known.length }); + } + ctx.db.transaction(() => ctx.setSyncState(jmap, 'Thread', { state: captured })); + }; + if (!state) return fullThreads(); + const outcome = await runChangesLoop({ + transport: ctx.transport, + type: 'Thread', + jmap, + using: MAIL_USING, + since: state, + target, + stopped: ctx.stopped, + apply: async (page) => { + const list = await fetchThreads(ctx, jmap, [...page.created, ...page.updated]); + ctx.db.transaction(() => { + for (const thread of list) ctx.db.run('INSERT OR REPLACE INTO thread (jmap, id, email_ids) VALUES (?, ?, ?)', [jmap, thread.id, JSON.stringify(thread.emailIds)]); + for (const id of page.destroyed) ctx.db.run('DELETE FROM thread WHERE jmap = ? AND id = ?', [jmap, id]); + ctx.setSyncState(jmap, 'Thread', { state: page.newState }); + }); + }, + }); + if (outcome.outcome === 'resync') { + ctx.db.transaction(() => { + ctx.db.run('DELETE FROM thread WHERE jmap = ?', [jmap]); + ctx.setSyncState(jmap, 'Thread', { state: null }); + }); + await fullThreads(); + } +} + +// ---- Bodies ---- + +async function backfillBodies(ctx: SyncContext, jmap: string): Promise { + let done = 0; + const totalRow = ctx.db.get<{ n: number }>('SELECT COUNT(*) AS n FROM email WHERE jmap = ? AND body_state = 0', [jmap]); + const total = Number(totalRow?.n ?? 0); + for (;;) { + if (ctx.stopped()) return; + const candidates = ctx.db.all<{ rowid: number; id: string; size: number; json: string }>( + 'SELECT rowid, id, size, json FROM email WHERE jmap = ? AND body_state = 0 ORDER BY received_at DESC LIMIT ?', + [jmap, BODY_BATCH_IDS], + ); + if (candidates.length === 0) return; + let bytes = 0; + const batch: typeof candidates = []; + for (const row of candidates) { + if (batch.length > 0 && bytes + Number(row.size) > BODY_BATCH_BYTES) break; + bytes += Number(row.size); + batch.push(row); + } + const response = await ctx.transport.request([['Email/get', { + accountId: jmap, + ids: batch.map((row) => String(row.id)), + properties: ['id', ...EMAIL_BODY_PROPERTIES], + fetchTextBodyValues: true, + fetchHTMLBodyValues: true, + fetchAllBodyValues: true, + maxBodyValueBytes: MAX_BODY_VALUE_BYTES, + }, 'b']], MAIL_USING); + const list = responseFor(response, 'b')[1].list as EmailObject[]; + const byId = new Map(list.map((email) => [email.id, email])); + ctx.db.transaction(() => { + for (const row of batch) { + const full = byId.get(String(row.id)); + if (full) storeBody(ctx.db, Number(row.rowid), String(row.json), full); + else ctx.db.run('UPDATE email SET body_state = 2 WHERE rowid = ?', [row.rowid]); + } + }); + done += batch.length; + ctx.emit({ type: 'progress', account: ctx.account, area: 'mail', phase: 'bodies', done, total }); + } +} + +// ---- The whole pass ---- + +export const mailSyncer: Syncer = { + name: 'mail', + capability: 'urn:ietf:params:jmap:mail', + async run(ctx, jmap) { + await syncMailboxes(ctx, jmap); + if (ctx.stopped()) return; + + const email = ctx.syncState(jmap, 'Email'); + let cursor = email.phase === 'list' ? email.cursor as unknown as ListCursor : null; + if (!cursor && !email.state) cursor = await startFullList(ctx, jmap); + if (!cursor && email.state) { + const outcome = await syncEmailDelta(ctx, jmap, email.state, email.target); + if (outcome === 'stopped') return; + if (outcome === 'resync') cursor = await startFullList(ctx, jmap); + } + if (cursor) { + const finished = await runFullList(ctx, jmap, cursor); + if (!finished) return; + // Catch what changed while paging. + const after = ctx.syncState(jmap, 'Email'); + if (after.state && (await syncEmailDelta(ctx, jmap, after.state, after.target)) === 'stopped') return; + } + if (ctx.stopped()) return; + await syncThreads(ctx, jmap); + if (ctx.stopped()) return; + await backfillBodies(ctx, jmap); + }, +}; diff --git a/lib/store/sqlite-version.ts b/lib/store/sqlite-version.ts new file mode 100644 index 000000000..1b6ee653c --- /dev/null +++ b/lib/store/sqlite-version.ts @@ -0,0 +1,3 @@ +/** The vendored SQLite3MultipleCiphers build. Change it with scripts/fetch-sqlite3mc.mjs. */ +export const SQLITE3MC_VERSION = '2.6.1-3.54.0'; +export const SQLITE3MC_PUBLIC_DIR = `sqlite3mc/${SQLITE3MC_VERSION}`; diff --git a/lib/store/storage.ts b/lib/store/storage.ts new file mode 100644 index 000000000..e8cde1216 --- /dev/null +++ b/lib/store/storage.ts @@ -0,0 +1,73 @@ +/** + * The small storage interface the local store is written against. + * + * Synchronous on purpose: SQLite3MC in a worker and node:sqlite in the tests + * both are, and a transaction then can't hold an await by accident. A native + * or mobile adapter runs the engine next to its database, not across a + * message boundary. + */ + +export type SqlValue = string | number | bigint | null | Uint8Array; +export type SqlRow = Record; + +export interface StorageAdapter { + /** Runs one or more statements without parameters. */ + exec(sql: string): void; + /** Runs one statement. */ + run(sql: string, params?: readonly SqlValue[]): { changes: number; lastInsertRowid: number }; + all(sql: string, params?: readonly SqlValue[]): T[]; + get(sql: string, params?: readonly SqlValue[]): T | undefined; + /** Commits when fn returns, rolls back when it throws. Nested calls join the outer one. */ + transaction(fn: () => T): T; + close(): void; +} + +/** Shared by the adapters: BEGIN/COMMIT around fn, and a guard against async bodies. */ +export function runTransaction( + state: { depth: number }, + exec: (sql: string) => void, + fn: () => T, +): T { + if (state.depth > 0) return fn(); + exec('BEGIN IMMEDIATE'); + state.depth += 1; + try { + const result = fn(); + if (result && typeof (result as { then?: unknown }).then === 'function') { + throw new Error('A store transaction must be synchronous'); + } + exec('COMMIT'); + return result; + } catch (error) { + exec('ROLLBACK'); + throw error; + } finally { + state.depth -= 1; + } +} + +export interface Migration { + /** Unique, ascending. Ranges per area are listed in lib/store/area.ts. */ + id: number; + name: string; + sql: string; +} + +/** Applies what's missing, in id order, each in its own transaction. */ +export function migrate(db: StorageAdapter, migrations: readonly Migration[]): number[] { + db.exec('CREATE TABLE IF NOT EXISTS schema_migration (id INTEGER PRIMARY KEY, name TEXT NOT NULL, at INTEGER NOT NULL)'); + const done = new Set(db.all<{ id: number }>('SELECT id FROM schema_migration').map((row) => Number(row.id))); + const ids = new Set(); + const applied: number[] = []; + for (const migration of [...migrations].sort((a, b) => a.id - b.id)) { + if (ids.has(migration.id)) throw new Error(`Duplicate store migration id ${migration.id}`); + ids.add(migration.id); + if (done.has(migration.id)) continue; + db.transaction(() => { + db.exec(migration.sql); + db.run('INSERT INTO schema_migration (id, name, at) VALUES (?, ?, ?)', [migration.id, migration.name, Date.now()]); + }); + applied.push(migration.id); + } + return applied; +} diff --git a/lib/store/worker/host.ts b/lib/store/worker/host.ts new file mode 100644 index 000000000..25e63e270 --- /dev/null +++ b/lib/store/worker/host.ts @@ -0,0 +1,168 @@ +/** + * What runs in the owner tab's worker: one database and engine per account. + * The list of areas is the only thing that decides what the store answers. + */ + +import type { StoreArea, StoreEvent } from '../area'; +import { AccountEngine } from '../engine/account-engine'; +import { FetchTransport, type StoreSession } from '../engine/transport'; +import type { StorageAdapter } from '../storage'; +import type { OpenAccountParams, StoreRpc, StoreStatus } from './protocol'; + +export interface HostStorage { + open(file: string, keyHex: string): Promise; + remove(file: string): boolean; +} + +interface OpenAccount { + engine: AccountEngine; + db: StorageAdapter; + file: string; + auth: string | null; + pendingAuth: Array<(header: string | null) => void>; + session: StoreSession; +} + +export interface StoreHostOptions { + areas: readonly StoreArea[]; + storage: HostStorage; + emit(event: StoreEvent): void; + needAuth(account: string): void; +} + +export class StoreHost { + private readonly accounts = new Map(); + private online = true; + private readonly synced = new Map(); + + constructor(private readonly options: StoreHostOptions) {} + + async openAccount(params: OpenAccountParams): Promise { + const existing = this.accounts.get(params.account); + if (existing) { + if (params.session) this.setSession(params.account, params.session); + this.setAuth(params.account, params.auth); + existing.engine.setScope(params.scope); + existing.engine.setInvertedKeywordSort(params.invertedKeywordSort); + void existing.engine.requestSync(); + return; + } + const db = await this.options.storage.open(params.file, params.keyHex); + const session = params.session ?? AccountEngine.storedSession(db); + if (!session) { + db.close(); + throw new Error('No session for this account yet'); + } + const account: OpenAccount = { db, file: params.file, auth: params.auth, pendingAuth: [], session, engine: undefined as unknown as AccountEngine }; + const transport = new FetchTransport({ + session: () => account.session, + auth: () => account.auth, + refreshAuth: () => new Promise((resolve) => { + account.pendingAuth.push(resolve); + this.options.needAuth(params.account); + }), + }); + account.engine = new AccountEngine({ + account: params.account, + db, + session, + transport, + areas: this.options.areas, + scope: params.scope, + invertedKeywordSort: params.invertedKeywordSort, + emit: (event) => { + if (event.type === 'synced') this.synced.set(event.account, event.at); + this.options.emit(event); + }, + }); + account.engine.setOnline(this.online); + this.accounts.set(params.account, account); + void account.engine.requestSync(); + } + + setAuth(account: string, auth: string | null): void { + const open = this.accounts.get(account); + if (!open) return; + open.auth = auth; + for (const resolve of open.pendingAuth.splice(0)) resolve(auth); + } + + setSession(account: string, session: StoreSession): void { + const open = this.accounts.get(account); + if (!open) return; + open.session = session; + open.engine.setSession(session); + } + + setScope(account: string, scope: Parameters[0]): void { + const open = this.accounts.get(account); + if (!open) return; + open.engine.setScope(scope); + void open.engine.requestSync(); + } + + async closeAccount(account: string): Promise { + const open = this.accounts.get(account); + if (!open) return; + this.accounts.delete(account); + await open.engine.close(); + for (const resolve of open.pendingAuth.splice(0)) resolve(null); + open.db.close(); + } + + async removeAccount(account: string, file: string): Promise { + await this.closeAccount(account); + this.synced.delete(account); + return this.options.storage.remove(file); + } + + async closeAll(): Promise { + await Promise.all([...this.accounts.keys()].map((account) => this.closeAccount(account))); + } + + /** The calls other tabs can make. */ + async call(method: keyof StoreRpc, params: unknown): Promise { + switch (method) { + case 'answer': { + const { account, calls } = params as Parameters[0]; + const open = this.accounts.get(account); + if (!open) throw new Error('The local store is not open for this account'); + return open.engine.answer(calls); + } + case 'sync': { + const { account } = params as Parameters[0]; + await this.accounts.get(account)?.engine.requestSync(); + return undefined; + } + case 'noteStateChange': { + const { account, changed } = params as Parameters[0]; + this.accounts.get(account)?.engine.noteStateChange(changed); + return undefined; + } + case 'setOnline': { + const { online } = params as Parameters[0]; + this.online = online; + for (const open of this.accounts.values()) open.engine.setOnline(online); + return undefined; + } + case 'status': { + const { account } = params as Parameters[0]; + return this.status(account); + } + default: + throw new Error(`Unknown store call ${String(method)}`); + } + } + + private status(account: string): StoreStatus | null { + const open = this.accounts.get(account); + if (!open) return null; + return { + account, + open: true, + emails: Number(open.db.get<{ n: number }>('SELECT COUNT(*) AS n FROM email')?.n ?? 0), + bodies: Number(open.db.get<{ n: number }>('SELECT COUNT(*) AS n FROM email_body')?.n ?? 0), + lastSyncedAt: this.synced.get(account) ?? null, + }; + } +} diff --git a/lib/store/worker/protocol.ts b/lib/store/worker/protocol.ts new file mode 100644 index 000000000..8b3257648 --- /dev/null +++ b/lib/store/worker/protocol.ts @@ -0,0 +1,76 @@ +/** Messages between the page and the store worker. */ + +import type { StoreEvent, StoreScope } from '../area'; +import type { JmapResponse, MethodCall, StoreSession } from '../engine/transport'; + +export const RPC_CHANNEL = 'bulwark-store-rpc'; +export const OWNER_LOCK = 'bulwark-store-owner'; + +export interface OpenAccountParams { + account: string; + /** `/a.db`, no account data: the name is plaintext in the OPFS slot. */ + file: string; + /** 32 bytes in hex. Only ever sent to this tab's own worker, never over the channel. */ + keyHex: string; + session: StoreSession | null; + scope: StoreScope; + invertedKeywordSort: boolean; + /** The page's current Authorization header. */ + auth: string | null; +} + +/** What other tabs can ask for, over the channel. */ +export interface StoreRpc { + answer(params: { account: string; calls: MethodCall[] }): JmapResponse | null; + sync(params: { account: string }): void; + noteStateChange(params: { account: string; changed: Record> }): void; + setOnline(params: { online: boolean }): void; + status(params: { account: string }): StoreStatus | null; +} + +export interface StoreStatus { + account: string; + open: boolean; + emails: number; + bodies: number; + lastSyncedAt: number | null; +} + +export type RpcRequest = { + kind: 'rpc'; + id: string; + from: string; + method: K; + params: Parameters[0]; +}; + +export type RpcReply = { + kind: 'reply'; + id: string; + to: string; + result?: unknown; + error?: string; +}; + +export type ChannelMessage = + | RpcRequest + | RpcReply + | { kind: 'event'; event: StoreEvent } + | { kind: 'owner-changed'; owner: string | null }; + +/** From this tab's page to its own worker, never on the channel. */ +export type PageToWorker = + | { kind: 'init'; clientId: string; moduleUrl: string } + | { kind: 'open'; id: string; params: OpenAccountParams } + | { kind: 'close-account'; id: string; account: string } + | { kind: 'remove-account'; id: string; account: string; file: string } + | { kind: 'set-auth'; account: string; auth: string | null } + | { kind: 'set-session'; account: string; session: StoreSession } + | { kind: 'set-scope'; account: string; scope: StoreScope } + | { kind: 'release'; id: string }; + +export type WorkerToPage = + | { kind: 'owner' } + | { kind: 'result'; id: string; result?: unknown; error?: string; errorName?: string } + | { kind: 'need-auth'; account: string } + | { kind: 'event'; event: StoreEvent }; diff --git a/lib/store/worker/worker.ts b/lib/store/worker/worker.ts new file mode 100644 index 000000000..003340c82 --- /dev/null +++ b/lib/store/worker/worker.ts @@ -0,0 +1,147 @@ +/** + * The store worker. Every tab has one, parked on the owner lock, and only the + * holder loads the wasm and touches OPFS. The lock is held for the worker's + * whole life, so handing over means: close, pause the VFS, then let go. + * + * Built to public/store-worker.js by scripts/build-store-worker.mjs. + */ + +import { WasmStorage } from '../adapters/wasm'; +import { STORE_AREAS } from '../areas'; +import { RPC_CHANNEL, OWNER_LOCK, type ChannelMessage, type PageToWorker, type WorkerToPage } from './protocol'; +import { StoreHost } from './host'; + +const scope = self as unknown as { + postMessage(message: WorkerToPage): void; + addEventListener(type: 'message', listener: (event: MessageEvent) => void): void; + close(): void; +}; + +let clientId = ''; +let moduleUrl = ''; +let storage: WasmStorage | null = null; +let host: StoreHost | null = null; +let channel: BroadcastChannel | null = null; +let releaseLock: (() => void) | null = null; + +function reply(id: string, result?: unknown): void { + scope.postMessage({ kind: 'result', id, result }); +} + +function replyError(id: string, error: unknown): void { + scope.postMessage({ + kind: 'result', + id, + error: error instanceof Error ? error.message : String(error), + errorName: error instanceof Error ? error.name : undefined, + }); +} + +function requireHost(): StoreHost { + if (!host) throw new Error('This tab does not own the local store'); + return host; +} + +async function becomeOwner(): Promise { + storage = await WasmStorage.install(moduleUrl); + host = new StoreHost({ + areas: STORE_AREAS, + storage, + emit: (event) => { + scope.postMessage({ kind: 'event', event }); + channel?.postMessage({ kind: 'event', event } satisfies ChannelMessage); + }, + needAuth: (account) => scope.postMessage({ kind: 'need-auth', account }), + }); + channel = new BroadcastChannel(RPC_CHANNEL); + channel.onmessage = async (event: MessageEvent) => { + const message = event.data; + if (message.kind !== 'rpc') return; + try { + const result = await requireHost().call(message.method, message.params); + channel?.postMessage({ kind: 'reply', id: message.id, to: message.from, result } satisfies ChannelMessage); + } catch (error) { + channel?.postMessage({ + kind: 'reply', + id: message.id, + to: message.from, + error: error instanceof Error ? error.message : String(error), + } satisfies ChannelMessage); + } + }; + channel.postMessage({ kind: 'owner-changed', owner: clientId } satisfies ChannelMessage); + scope.postMessage({ kind: 'owner' }); +} + +async function release(): Promise { + // The order matters: the OPFS handles have to be free before the lock is. + channel?.postMessage({ kind: 'owner-changed', owner: null } satisfies ChannelMessage); + await host?.closeAll(); + host = null; + storage?.pause(); + storage = null; + channel?.close(); + channel = null; + releaseLock?.(); + releaseLock = null; +} + +scope.addEventListener('message', async (event) => { + const message = event.data; + switch (message.kind) { + case 'init': + clientId = message.clientId; + moduleUrl = message.moduleUrl; + void navigator.locks.request(OWNER_LOCK, () => new Promise((resolve) => { + releaseLock = resolve; + becomeOwner().catch((error) => { + scope.postMessage({ + kind: 'event', + event: { type: 'error', account: '', area: 'store', message: error instanceof Error ? error.message : String(error) }, + }); + resolve(); + }); + })); + break; + case 'open': + try { + await requireHost().openAccount(message.params); + reply(message.id); + } catch (error) { + replyError(message.id, error); + } + break; + case 'close-account': + try { + await requireHost().closeAccount(message.account); + reply(message.id); + } catch (error) { + replyError(message.id, error); + } + break; + case 'remove-account': + try { + reply(message.id, await requireHost().removeAccount(message.account, message.file)); + } catch (error) { + replyError(message.id, error); + } + break; + case 'set-auth': + host?.setAuth(message.account, message.auth); + break; + case 'set-session': + host?.setSession(message.account, message.session); + break; + case 'set-scope': + host?.setScope(message.account, message.scope); + break; + case 'release': + try { + await release(); + reply(message.id); + } catch (error) { + replyError(message.id, error); + } + break; + } +}); diff --git a/next.config.ts b/next.config.ts index e57a5f3af..1ce8a7714 100644 --- a/next.config.ts +++ b/next.config.ts @@ -140,6 +140,11 @@ const nextConfig: NextConfig = { { key: "Cache-Control", value: "public, max-age=31536000, immutable" }, ], }, + { + // The local store's database engine, in a folder named after its version. + source: "/sqlite3mc/:path*", + headers: [{ key: "Cache-Control", value: "public, max-age=31536000, immutable" }], + }, // The upload routes proxy.ts's matcher leaves out, with the // headers it sets on every other API response. ...["/api/webdav", "/api/plugin-proxy", "/api/wopi/files/:fileId/contents"].map((source) => ({ diff --git a/package.json b/package.json index 9c1abb8ac..52adefb78 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,8 @@ "typescript" ], "scripts": { - "dev": "node scripts/build-pst-worker.mjs && node scripts/build-plugin-sandbox.mjs --watch -- next dev --turbopack", - "build": "node scripts/build-pst-worker.mjs && node scripts/build-plugin-sandbox.mjs && next build --turbopack && node scripts/standalone-guard.mjs", + "dev": "node scripts/build-pst-worker.mjs && node scripts/build-store-worker.mjs && node scripts/build-plugin-sandbox.mjs --watch -- next dev --turbopack", + "build": "node scripts/build-pst-worker.mjs && node scripts/build-store-worker.mjs && node scripts/build-plugin-sandbox.mjs && next build --turbopack && node scripts/standalone-guard.mjs", "build:lite": "node scripts/lite/build.mjs", "lite:serve": "node scripts/lite/serve.mjs out 4173", "test:lite-smoke": "playwright test -c scripts/lite/smoke/playwright.config.ts", diff --git a/proxy.ts b/proxy.ts index eb767eb03..4e47be5e8 100644 --- a/proxy.ts +++ b/proxy.ts @@ -86,7 +86,7 @@ export const config = { // /en/mail/folder/inbox/statement.pdf a real signed-in page, and it rendered // without a CSP or any other security header (GHSA-xvjh-v9c6-qcvc). Only what // is genuinely static may skip locale routing and the headers. -const STATIC_ASSET_PATTERN = /^\/[^/]+\.[^/]+$|^\/(?:branding|notification|demo|plugin-sandbox-assets)\//; +const STATIC_ASSET_PATTERN = /^\/[^/]+\.[^/]+$|^\/(?:branding|notification|demo|plugin-sandbox-assets|sqlite3mc)\//; export function isStaticAssetPath(pathname: string): boolean { return STATIC_ASSET_PATTERN.test(pathname); diff --git a/scripts/build-store-worker.mjs b/scripts/build-store-worker.mjs new file mode 100644 index 000000000..835bc10e6 --- /dev/null +++ b/scripts/build-store-worker.mjs @@ -0,0 +1,46 @@ +// Builds the local store's worker (lib/store/worker/worker.ts) into +// public/store-worker.js and copies the vendored SQLite3MultipleCiphers build +// next to it, in a folder named after its version: emscripten looks for the +// literal name sqlite3.wasm, so the files can't have hashed names. +// Both go through proxy.ts's static asset rule, which keeps the page CSP off +// them: wasm compiles under the worker's own response headers. +// +// node scripts/build-store-worker.mjs (npm run build, npm run dev) + +import { build } from 'esbuild'; +import { copyFileSync, mkdirSync } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { SQLITE3MC, SQLITE3MC_VENDOR_DIR, verifyVendored } from './fetch-sqlite3mc.mjs'; + +const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); +export const STORE_WORKER_OUTFILE = path.join(root, 'public', 'store-worker.js'); +export const SQLITE3MC_PUBLIC_DIR = path.join(root, 'public', 'sqlite3mc', SQLITE3MC.version); + +export async function buildStoreWorker({ outfile = STORE_WORKER_OUTFILE, publicDir = SQLITE3MC_PUBLIC_DIR } = {}) { + verifyVendored(); + mkdirSync(publicDir, { recursive: true }); + for (const name of [...Object.keys(SQLITE3MC.files), 'LICENSE']) { + copyFileSync(path.join(SQLITE3MC_VENDOR_DIR, name), path.join(publicDir, name)); + } + const result = await build({ + entryPoints: [path.join(root, 'lib/store/worker/worker.ts')], + bundle: true, + format: 'esm', + platform: 'browser', + target: 'es2022', + outfile, + minify: true, + legalComments: 'none', + alias: { '@': root }, + define: { 'process.env.NODE_ENV': '"production"' }, + metafile: true, + logLevel: 'warning', + }); + return { bytes: Object.values(result.metafile.outputs).reduce((n, o) => n + o.bytes, 0) }; +} + +if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { + const { bytes } = await buildStoreWorker(); + console.log(`[build-store-worker] ${path.relative(root, STORE_WORKER_OUTFILE)} ${bytes}`); +} diff --git a/scripts/fetch-sqlite3mc.mjs b/scripts/fetch-sqlite3mc.mjs new file mode 100644 index 000000000..f119f3df7 --- /dev/null +++ b/scripts/fetch-sqlite3mc.mjs @@ -0,0 +1,79 @@ +// Fetches the pinned SQLite3MultipleCiphers WASM build into vendor/sqlite3mc/. +// Run it by hand when moving to a new version, and commit the result, so a +// Docker build needs no access to GitHub. Every download is checked against the +// pinned sha256: a changed artifact fails here. +// +// node scripts/fetch-sqlite3mc.mjs downloads and verifies +// node scripts/fetch-sqlite3mc.mjs --check verifies what is committed +// +// Fixes for bugs #291-#294 are on trunk, not in a release yet. Check the rules +// in lib/store/adapters/wasm.ts when moving to a newer build, and never go below 2.6.0. + +import { createHash } from 'node:crypto'; +import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'; +import path from 'node:path'; +import { unzipSync } from 'fflate'; +import { fileURLToPath } from 'node:url'; + +const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); + +export const SQLITE3MC = { + version: '2.6.1-3.54.0', + tag: 'v2.6.1', + zip: 'sqlite3mc-2.6.1-sqlite-3.54.0-wasm.zip', + zipSha256: 'aba121490fd6123bcbef8404ee26df9b26c0301063781e2aa31f05aed6f48384', + innerDir: 'sqlite3mc-wasm-3540000/jswasm', + files: { + 'sqlite3.mjs': '5308c7cc857408697c657a8d314e647a6f31c4aee67974ab8efd80c1a07161e0', + 'sqlite3.wasm': '0b5a4bfff35f1ec87bf6f68ea293f425b86cbd661b77628a955cb827c9fbf524', + }, +}; + +export const SQLITE3MC_VENDOR_DIR = path.join(root, 'vendor', 'sqlite3mc', SQLITE3MC.version); + +function sha256(data) { + return createHash('sha256').update(data).digest('hex'); +} + +/** Throws unless the committed files match their pins. */ +export function verifyVendored(dir = SQLITE3MC_VENDOR_DIR) { + for (const [name, expected] of Object.entries(SQLITE3MC.files)) { + const actual = sha256(readFileSync(path.join(dir, name))); + if (actual !== expected) throw new Error(`[sqlite3mc] ${name}: expected ${expected}, got ${actual}`); + } + readFileSync(path.join(dir, 'LICENSE')); +} + +async function download(url) { + const response = await fetch(url); + if (!response.ok) throw new Error(`[sqlite3mc] ${url}: ${response.status}`); + return Buffer.from(await response.arrayBuffer()); +} + +async function fetchAndVendor() { + const base = `https://github.com/utelle/SQLite3MultipleCiphers/releases/download/${SQLITE3MC.tag}`; + const zip = await download(`${base}/${SQLITE3MC.zip}`); + const actual = sha256(zip); + if (actual !== SQLITE3MC.zipSha256) throw new Error(`[sqlite3mc] zip: expected ${SQLITE3MC.zipSha256}, got ${actual}`); + const entries = unzipSync(zip); + mkdirSync(SQLITE3MC_VENDOR_DIR, { recursive: true }); + for (const name of Object.keys(SQLITE3MC.files)) { + const entry = entries[`${SQLITE3MC.innerDir}/${name}`]; + if (!entry) throw new Error(`[sqlite3mc] ${name} is not in the zip`); + writeFileSync(path.join(SQLITE3MC_VENDOR_DIR, name), entry); + } + // The zip has no licence file. + const license = await download(`https://raw.githubusercontent.com/utelle/SQLite3MultipleCiphers/${SQLITE3MC.tag}/LICENSE`); + writeFileSync(path.join(SQLITE3MC_VENDOR_DIR, 'LICENSE'), license); + verifyVendored(); + console.log(`[fetch-sqlite3mc] vendored ${SQLITE3MC.version}`); +} + +if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { + if (process.argv.includes('--check')) { + verifyVendored(); + console.log('[fetch-sqlite3mc] ok'); + } else { + await fetchAndVendor(); + } +} diff --git a/scripts/lite/lib.mjs b/scripts/lite/lib.mjs index 559c09eca..18bdc6cdf 100644 --- a/scripts/lite/lib.mjs +++ b/scripts/lite/lib.mjs @@ -43,6 +43,9 @@ export const LITE_REMOVED_PATHS = [ "app/(main)/protocol", "e2e", "integration", + // The local store: Lite has no offline mode. A dev checkout may hold these. + "public/store-worker.js", + "public/sqlite3mc", ]; /** Test trees are pruned too: they import the routes removed above. */ diff --git a/vendor/sqlite3mc/2.6.1-3.54.0/LICENSE b/vendor/sqlite3mc/2.6.1-3.54.0/LICENSE new file mode 100644 index 000000000..2fff29de4 --- /dev/null +++ b/vendor/sqlite3mc/2.6.1-3.54.0/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019-2026 Ulrich Telle + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/sqlite3mc/2.6.1-3.54.0/sqlite3.mjs b/vendor/sqlite3mc/2.6.1-3.54.0/sqlite3.mjs new file mode 100644 index 000000000..4ea31fb03 --- /dev/null +++ b/vendor/sqlite3mc/2.6.1-3.54.0/sqlite3.mjs @@ -0,0 +1,14727 @@ +/* @preserve +** +** LICENSE for the sqlite3 WebAssembly/JavaScript APIs. +** +** This bundle (typically released as sqlite3.js or sqlite3.mjs) +** is an amalgamation of JavaScript source code from two projects: +** +** 1) https://emscripten.org: the Emscripten "glue code" is covered by +** the terms of the MIT license and University of Illinois/NCSA +** Open Source License, as described at: +** +** https://emscripten.org/docs/introducing_emscripten/emscripten_license.html +** +** 2) https://sqlite.org: all code and documentation labeled as being +** from this source are released under the same terms as the sqlite3 +** C library: +** +** 2022-10-16 +** +** The author disclaims copyright to this source code. In place of a +** legal notice, here is a blessing: +** +** * May you do good and not evil. +** * May you find forgiveness for yourself and forgive others. +** * May you share freely, never taking more than you give. +*/ +/* @preserve +** This code was built from sqlite3 version... +** +** SQLITE_VERSION "3.54.0" +** SQLITE_VERSION_NUMBER 3054000 +** SQLITE_SOURCE_ID "2026-10-09 15:46:58 be8d059e9a49089ab2dce5ed26dd87aaf598fdc5fbe0b107c0dd758464bcd5e3" +** +** Emscripten SDK: 6.0.3 +*/ + + + + + +async function sqlite3InitModule(moduleArg = {}) { + var Module = moduleArg; + + + + + + + + + + + + + + + + + + + + + +var ENVIRONMENT_IS_WEB = !!globalThis.window; +var ENVIRONMENT_IS_WORKER = !!globalThis.WorkerGlobalScope; + + +var ENVIRONMENT_IS_NODE = globalThis.process?.versions?.node && globalThis.process?.type != 'renderer'; +var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; + + + + + + +(function(Module){ + const sIMS = + globalThis.sqlite3InitModuleState + || Object.assign(Object.create(null),{ + + debugModule: function(){ + console.warn("globalThis.sqlite3InitModuleState is missing",arguments); + } + }); + delete globalThis.sqlite3InitModuleState; + sIMS.debugModule('pre-js.js sqlite3InitModuleState =',sIMS); + + + Module['locateFile'] = function(path, prefix) { + if( this.emscriptenLocateFile instanceof Function ){ + + return this.emscriptenLocateFile(path, prefix); + } + return new URL(path, import.meta.url).href; + }.bind(sIMS); + + + Module['instantiateWasm'] = function callee(imports, onSuccess){ + if( this.emscriptenInstantiateWasm instanceof Function ){ + + return this.emscriptenInstantiateWasm(imports, onSuccess); + } + const sims = this; + const finalThen = (arg)=>{ + arg.imports = imports; + sims.instantiateWasm = arg; + onSuccess(arg.instance, arg.module); + }; + const uri = Module.locateFile( + sims.wasmFilename, ( + ('undefined'===typeof scriptDirectory) + ? "" : scriptDirectory) + ); + sims.debugModule("instantiateWasm() uri =", uri, "sIMS =",this); + const wfetch = ()=>fetch(uri, {credentials: 'same-origin'}); + const loadWasm = WebAssembly.instantiateStreaming + ? async ()=> + WebAssembly + .instantiateStreaming(wfetch(), imports) + .then(finalThen) + : async ()=> + wfetch() + .then(response => response.arrayBuffer()) + .then(bytes => WebAssembly.instantiate(bytes, imports)) + .then(finalThen) + return loadWasm(); + }.bind(sIMS); +})(Module); + + + + +var programArgs = []; +var thisProgram = './this.program'; +var quit_ = (status, toThrow) => { + throw toThrow; +}; + +var _scriptName = import.meta.url; + + +var scriptDirectory = ''; +function locateFile(path) { + if (Module['locateFile']) { + return Module['locateFile'](path, scriptDirectory); + } + return scriptDirectory + path; +} + + +var readAsync, readBinary; + + + + +if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { + try { + scriptDirectory = new URL('.', _scriptName).href; + } catch { + + + } + + { + +if (ENVIRONMENT_IS_WORKER) { + readBinary = (url) => { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + xhr.responseType = 'arraybuffer'; + xhr.send(null); + return new Uint8Array((xhr.response)); + }; + } + + readAsync = async (url) => { + var response = await fetch(url, { credentials: 'same-origin' }); + if (response.ok) { + return response.arrayBuffer(); + } + throw new Error(response.status + ' : ' + response.url); + }; + + } +} else +{ +} + +var out = console.log.bind(console); +var err = console.error.bind(console); + + + + + + + + + + + + + + +var wasmBinary; + + + + + + + + + +var ABORT = false; + + + + +var EXITSTATUS; + + + + + + +function assert(condition, text) { + if (!condition) { + + + + abort(text); + } +} + + +var isFileURI = (filename) => filename.startsWith('file://'); + + + + +class EmscriptenEH {} + +class EmscriptenSjLj extends EmscriptenEH {} + + + + + + +var runtimeInitialized = false; + + + + + +function getMemoryBuffer() { + return wasmMemory.buffer; +} + +function updateMemoryViews() { + + + if (HEAP8?.buffer?.resizable) return; + var b = getMemoryBuffer(); + HEAP8 = new Int8Array(b); + HEAP16 = new Int16Array(b); + HEAPU8 = new Uint8Array(b); + HEAPU16 = new Uint16Array(b); + HEAP32 = new Int32Array(b); + HEAPU32 = new Uint32Array(b); + HEAPF32 = new Float32Array(b); + HEAPF64 = new Float64Array(b); + HEAP64 = new BigInt64Array(b); + HEAPU64 = new BigUint64Array(b); +} + + + + + + + +function initMemory() { + + + + if (Module['wasmMemory']) { + wasmMemory = Module['wasmMemory']; + } else + { + var INITIAL_MEMORY = Module['INITIAL_MEMORY'] || 8388608; + + + wasmMemory = new WebAssembly.Memory({ + 'initial': INITIAL_MEMORY / 65536, + + + + + + 'maximum': 32768, + }); + } + + updateMemoryViews(); +} + + + + + + +function preRun() { + var preRun = Module['preRun']; + if (preRun) { + if (typeof preRun == 'function') preRun = [preRun]; + onPreRuns.push(...preRun); + } + + callRuntimeCallbacks(onPreRuns); + +} + +function initRuntime() { + runtimeInitialized = true; + + + if (!Module['noFSInit'] && !FS.initialized) FS.init(); +TTY.init(); + + + wasmExports['__wasm_call_ctors'](); + + + FS.ignorePermissions = false; + + +} + +function postRun() { + + var postRun = Module['postRun']; + if (postRun) { + if (typeof postRun == 'function') postRun = [postRun]; + onPostRuns.push(...postRun); + } + + + callRuntimeCallbacks(onPostRuns); + +} + + +function abort(what) { + Module['onAbort']?.(what); + + what = `Aborted(${what})`; + + + err(what); + + ABORT = true; + + what += '. Build with -sASSERTIONS for more info.'; + + + + + + + + + + + + + + + + var e = new WebAssembly.RuntimeError(what); + + + + + throw e; +} + +var wasmBinaryFile; + +function findWasmBinary() { + + if (Module['locateFile']) { + return locateFile('sqlite3.wasm'); + } + + + return new URL('sqlite3.wasm', import.meta.url).href; + +} + +function getBinarySync(file) { + if (readBinary) { + return readBinary(file); + } + + + throw 'both async and sync fetching of the wasm failed'; +} + +async function getWasmBinary(binaryFile) { + + if (!wasmBinary) { + + try { + var response = await readAsync(binaryFile); + return new Uint8Array(response); + } catch { + + } + } + + + return getBinarySync(binaryFile); +} + +async function instantiateArrayBuffer(binaryFile, imports) { + try { + var binary = await getWasmBinary(binaryFile); + var instance = await WebAssembly.instantiate(binary, imports); + return instance; + } catch (reason) { + err(`failed to asynchronously prepare wasm: ${reason}`); + + abort(reason); + } +} + +async function instantiateAsync(binary, binaryFile, imports) { + if (!binary + ) { + try { + var response = fetch(binaryFile, { credentials: 'same-origin' }); + var instantiationResult = await WebAssembly.instantiateStreaming(response, imports); + return instantiationResult; + } catch (reason) { + + + err(`wasm streaming compile failed: ${reason}`); + err('falling back to ArrayBuffer instantiation'); + + }; + } + return instantiateArrayBuffer(binaryFile, imports); +} + +function getWasmImports() { + + var imports = { + 'env': wasmImports, + 'wasi_snapshot_preview1': wasmImports, + }; + return imports; +} + + + +async function createWasm() { + + + + function receiveInstance(instance) { + wasmExports = instance.exports; + + assignWasmExports(wasmExports); + + return wasmExports; + } + + + function receiveInstantiationResult(result) { + + + + + return receiveInstance(result['instance']); + } + + var info = getWasmImports(); + + + + + + + + var instantiateWasm = Module['instantiateWasm']; + if (instantiateWasm) { + return new Promise((resolve) => { + instantiateWasm(info, (inst) => resolve(receiveInstance(inst))); + }); + } + + wasmBinaryFile ??= findWasmBinary(); + var result = await instantiateAsync(wasmBinary, wasmBinaryFile, info); + var exports = receiveInstantiationResult(result); + return exports; +} + + + + + + + class ExitStatus { + name = 'ExitStatus'; + constructor(status) { + this.message = `Program terminated with exit(${status})`; + this.status = status; + } + } + + + var HEAP16; + + + var HEAP32; + + + var HEAP64; + + + var HEAP8; + + + var HEAPF32; + + + var HEAPF64; + + + var HEAPU16; + + + var HEAPU32; + + + var HEAPU64; + + + var HEAPU8; + + var callRuntimeCallbacks = (callbacks) => { + while (callbacks.length > 0) { + + callbacks.shift()(Module); + } + }; + var onPostRuns = []; + var addOnPostRun = (cb) => onPostRuns.push(cb); + + var onPreRuns = []; + var addOnPreRun = (cb) => onPreRuns.push(cb); + + + + + function getValue(ptr, type = 'i8') { + if (type.endsWith('*')) type = '*'; + switch (type) { + case 'i1': return HEAP8[ptr]; + case 'i8': return HEAP8[ptr]; + case 'i16': return HEAP16[((ptr)>>1)]; + case 'i32': return HEAP32[((ptr)>>2)]; + case 'i64': return HEAP64[((ptr)>>3)]; + case 'float': return HEAPF32[((ptr)>>2)]; + case 'double': return HEAPF64[((ptr)>>3)]; + case '*': return HEAPU32[((ptr)>>2)]; + default: abort(`invalid type for getValue: ${type}`); + } + } + + var noExitRuntime = true; + + + + function setValue(ptr, value, type = 'i8') { + if (type.endsWith('*')) type = '*'; + switch (type) { + case 'i1': HEAP8[ptr] = value; break; + case 'i8': HEAP8[ptr] = value; break; + case 'i16': HEAP16[((ptr)>>1)] = value; break; + case 'i32': HEAP32[((ptr)>>2)] = value; break; + case 'i64': HEAP64[((ptr)>>3)] = BigInt(value); break; + case 'float': HEAPF32[((ptr)>>2)] = value; break; + case 'double': HEAPF64[((ptr)>>3)] = value; break; + case '*': HEAPU32[((ptr)>>2)] = value; break; + default: abort(`invalid type for setValue: ${type}`); + } + } + + var stackRestore = (val) => __emscripten_stack_restore(val); + + var stackSave = () => _emscripten_stack_get_current(); + + var wasmMemory; + + var PATH = { + isAbs:(path) => path.charAt(0) === '/', + splitPath:(filename) => { + var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; + return splitPathRe.exec(filename).slice(1); + }, + normalizeArray:(parts, allowAboveRoot) => { + + var up = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var last = parts[i]; + if (last === '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + + if (allowAboveRoot) { + for (; up; up--) { + parts.unshift('..'); + } + } + return parts; + }, + normalize:(path) => { + var isAbsolute = PATH.isAbs(path), + trailingSlash = path.slice(-1) === '/'; + + path = PATH.normalizeArray(path.split('/').filter((p) => !!p), !isAbsolute).join('/'); + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + return (isAbsolute ? '/' : '') + path; + }, + dirname:(path) => { + var result = PATH.splitPath(path), + root = result[0], + dir = result[1]; + if (!root && !dir) { + + return '.'; + } + if (dir) { + + dir = dir.slice(0, -1); + } + return root + dir; + }, + basename:(path) => path && path.match(/([^\/]+|\/)\/*$/)[1], +join:(...paths) => PATH.normalize(paths.join('/')), +join2:(l, r) => PATH.normalize(l + '/' + r), +}; + +var initRandomFill = () => { + + return (view) => (crypto.getRandomValues(view), 0); + }; +var randomFill = (view) => (randomFill = initRandomFill())(view); + + + +var PATH_FS = { +resolve:(...args) => { + var resolvedPath = '', + resolvedAbsolute = false; + for (var i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? args[i] : FS.cwd(); + + if (typeof path != 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + return ''; + } + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = PATH.isAbs(path); + } + + + resolvedPath = PATH.normalizeArray(resolvedPath.split('/').filter((p) => !!p), !resolvedAbsolute).join('/'); + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; + }, +relative:(from, to) => { + from = PATH_FS.resolve(from).slice(1); + to = PATH_FS.resolve(to).slice(1); + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + if (start > end) return []; + return arr.slice(start, end - start + 1); + } + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + return outputParts.join('/'); + }, +}; + + +var UTF8Decoder = new TextDecoder(); + + + + var findStringEnd = (heapOrArray, idx, maxBytesToRead, ignoreNul) => { + var maxIdx = idx + maxBytesToRead; + if (ignoreNul) return maxIdx; + + + + + while (heapOrArray[idx] && !(idx >= maxIdx)) ++idx; + return idx; + }; + + + var UTF8ArrayToString = (heapOrArray, idx = 0, maxBytesToRead, ignoreNul) => { + + var endPtr = findStringEnd(heapOrArray, idx, maxBytesToRead, ignoreNul); + + return UTF8Decoder.decode(heapOrArray.buffer ? heapOrArray.subarray(idx, endPtr) : new Uint8Array(heapOrArray.slice(idx, endPtr))); + }; + + var FS_stdin_getChar_buffer = []; + + var lengthBytesUTF8 = (str) => { + var len = 0; + for (var i = 0; i < str.length; ++i) { + + + + + var c = str.charCodeAt(i); + if (c <= 0x7F) { + len++; + } else if (c <= 0x7FF) { + len += 2; + } else if (c >= 0xD800 && c <= 0xDFFF) { + len += 4; ++i; + } else { + len += 3; + } + } + return len; + }; + + var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => { + + + if (!(maxBytesToWrite > 0)) + return 0; + + var startIdx = outIdx; + var endIdx = outIdx + maxBytesToWrite - 1; + for (var i = 0; i < str.length; ++i) { + + + + var u = str.codePointAt(i); + if (u <= 0x7F) { + if (outIdx >= endIdx) break; + heap[outIdx++] = u; + } else if (u <= 0x7FF) { + if (outIdx + 1 >= endIdx) break; + heap[outIdx++] = 0xC0 | (u >> 6); + heap[outIdx++] = 0x80 | (u & 63); + } else if (u <= 0xFFFF) { + if (outIdx + 2 >= endIdx) break; + heap[outIdx++] = 0xE0 | (u >> 12); + heap[outIdx++] = 0x80 | ((u >> 6) & 63); + heap[outIdx++] = 0x80 | (u & 63); + } else { + if (outIdx + 3 >= endIdx) break; + heap[outIdx++] = 0xF0 | (u >> 18); + heap[outIdx++] = 0x80 | ((u >> 12) & 63); + heap[outIdx++] = 0x80 | ((u >> 6) & 63); + heap[outIdx++] = 0x80 | (u & 63); + + + i++; + } + } + + heap[outIdx] = 0; + return outIdx - startIdx; + }; + + var intArrayFromString = (stringy, dontAddNull, length) => { + var len = length > 0 ? length : lengthBytesUTF8(stringy)+1; + var u8array = new Array(len); + var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length); + if (dontAddNull) u8array.length = numBytesWritten; + return u8array; + }; + var FS_stdin_getChar = () => { + if (!FS_stdin_getChar_buffer.length) { + var result = null; + if (globalThis.window?.prompt) { + + result = window.prompt('Input: '); + if (result !== null) { + result += '\n'; + } + } else + {} + if (!result) { + return null; + } + FS_stdin_getChar_buffer = intArrayFromString(result, true); + } + return FS_stdin_getChar_buffer.shift(); + }; + var TTY = { + ttys:[], + init() { + + + + + + + + + }, + shutdown() { + + + + + + + + + + }, + register(dev, ops) { + TTY.ttys[dev] = { input: [], output: [], ops: ops }; + FS.registerDevice(dev, TTY.stream_ops); + }, + stream_ops:{ + open(stream) { + var tty = TTY.ttys[stream.node.rdev]; + if (!tty) { + throw new FS.ErrnoError(43); + } + stream.tty = tty; + stream.seekable = false; + }, + close(stream) { + + stream.tty.ops.fsync(stream.tty); + }, + fsync(stream) { + stream.tty.ops.fsync(stream.tty); + }, + read(stream, buffer, offset, length, pos ) { + if (!stream.tty || !stream.tty.ops.get_char) { + throw new FS.ErrnoError(60); + } + var bytesRead = 0; + for (var i = 0; i < length; i++) { + var result; + try { + result = stream.tty.ops.get_char(stream.tty); + } catch (e) { + throw new FS.ErrnoError(29); + } + if (result === undefined && bytesRead === 0) { + throw new FS.ErrnoError(6); + } + if (result === null || result === undefined) break; + bytesRead++; + buffer[offset+i] = result; + } + if (bytesRead) { + stream.node.atime = Date.now(); + } + return bytesRead; + }, + write(stream, buffer, offset, length, pos) { + if (!stream.tty || !stream.tty.ops.put_char) { + throw new FS.ErrnoError(60); + } + try { + for (var i = 0; i < length; i++) { + stream.tty.ops.put_char(stream.tty, buffer[offset+i]); + } + } catch (e) { + throw new FS.ErrnoError(29); + } + if (length) { + stream.node.mtime = stream.node.ctime = Date.now(); + } + return i; + }, + }, + default_tty_ops:{ + get_char(tty) { + return FS_stdin_getChar(); + }, + put_char(tty, val) { + if (val === null || val === 10) { + out(UTF8ArrayToString(tty.output)); + tty.output = []; + } else { + if (val != 0) tty.output.push(val); + } + }, + fsync(tty) { + if (tty.output?.length > 0) { + out(UTF8ArrayToString(tty.output)); + tty.output = []; + } + }, + ioctl_tcgets(tty) { + + return { + c_iflag: 25856, + c_oflag: 5, + c_cflag: 191, + c_lflag: 35387, + c_cc: [ + 0x03, 0x1c, 0x7f, 0x15, 0x04, 0x00, 0x01, 0x00, 0x11, 0x13, 0x1a, 0x00, + 0x12, 0x0f, 0x17, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ] + }; + }, + ioctl_tcsets(tty, optional_actions, data) { + + return 0; + }, + ioctl_tiocgwinsz(tty) { + return [24, 80]; + }, + }, + default_tty1_ops:{ + put_char(tty, val) { + if (val === null || val === 10) { + err(UTF8ArrayToString(tty.output)); + tty.output = []; + } else { + if (val != 0) tty.output.push(val); + } + }, + fsync(tty) { + if (tty.output?.length > 0) { + err(UTF8ArrayToString(tty.output)); + tty.output = []; + } + }, + }, + }; + + + var zeroMemory = (ptr, size) => HEAPU8.fill(0, ptr, ptr + size); + + var alignMemory = (size, alignment) => { + return Math.ceil(size / alignment) * alignment; + }; + var mmapAlloc = (size) => { + size = alignMemory(size, 65536); + var ptr = _emscripten_builtin_memalign(65536, size); + if (ptr) zeroMemory(ptr, size); + return ptr; + }; + var MEMFS = { + ops_table:null, + mount(mount) { + return MEMFS.createNode(null, '/', 16895, 0); + }, + createNode(parent, name, mode, dev) { + if (FS.isBlkdev(mode) || FS.isFIFO(mode)) { + + throw new FS.ErrnoError(63); + } + MEMFS.ops_table ||= { + dir: { + node: { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr, + lookup: MEMFS.node_ops.lookup, + mknod: MEMFS.node_ops.mknod, + rename: MEMFS.node_ops.rename, + unlink: MEMFS.node_ops.unlink, + rmdir: MEMFS.node_ops.rmdir, + readdir: MEMFS.node_ops.readdir, + symlink: MEMFS.node_ops.symlink + }, + stream: { + llseek: MEMFS.stream_ops.llseek + } + }, + file: { + node: { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr + }, + stream: { + llseek: MEMFS.stream_ops.llseek, + read: MEMFS.stream_ops.read, + write: MEMFS.stream_ops.write, + mmap: MEMFS.stream_ops.mmap, + msync: MEMFS.stream_ops.msync + } + }, + link: { + node: { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr, + readlink: MEMFS.node_ops.readlink + }, + stream: {} + }, + chrdev: { + node: { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr + }, + stream: FS.chrdev_stream_ops + } + }; + var node = FS.createNode(parent, name, mode, dev); + if (FS.isDir(node.mode)) { + node.node_ops = MEMFS.ops_table.dir.node; + node.stream_ops = MEMFS.ops_table.dir.stream; + node.contents = {}; + } else if (FS.isFile(node.mode)) { + node.node_ops = MEMFS.ops_table.file.node; + node.stream_ops = MEMFS.ops_table.file.stream; + + + node.usedBytes = 0; + + + + + node.contents = MEMFS.emptyFileContents ??= new Uint8Array(0); + } else if (FS.isLink(node.mode)) { + node.node_ops = MEMFS.ops_table.link.node; + node.stream_ops = MEMFS.ops_table.link.stream; + } else if (FS.isChrdev(node.mode)) { + node.node_ops = MEMFS.ops_table.chrdev.node; + node.stream_ops = MEMFS.ops_table.chrdev.stream; + } + node.atime = node.mtime = node.ctime = Date.now(); + + if (parent) { + parent.contents[name] = node; + parent.atime = parent.mtime = parent.ctime = node.atime; + } + return node; + }, + getFileDataAsTypedArray(node) { + return node.contents.subarray(0, node.usedBytes); + }, + expandFileStorage(node, newCapacity) { + var prevCapacity = node.contents.length; + if (prevCapacity >= newCapacity) return; + + + + + + var CAPACITY_DOUBLING_MAX = 1024 * 1024; + newCapacity = Math.max(newCapacity, (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2.0 : 1.125)) >>> 0); + if (prevCapacity) newCapacity = Math.max(newCapacity, 256); + var oldContents = MEMFS.getFileDataAsTypedArray(node); + node.contents = new Uint8Array(newCapacity); + node.contents.set(oldContents); + }, + resizeFileStorage(node, newSize) { + if (node.usedBytes == newSize) return; + var oldContents = node.contents; + node.contents = new Uint8Array(newSize); + node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); + node.usedBytes = newSize; + }, + node_ops:{ + getattr(node) { + var attr = {}; + + attr.dev = FS.isChrdev(node.mode) ? node.id : 1; + attr.ino = node.id; + attr.mode = node.mode; + attr.nlink = 1; + attr.uid = 0; + attr.gid = 0; + attr.rdev = node.rdev; + if (FS.isDir(node.mode)) { + attr.size = 4096; + } else if (FS.isFile(node.mode)) { + attr.size = node.usedBytes; + } else if (FS.isLink(node.mode)) { + attr.size = node.link.length; + } else { + attr.size = 0; + } + attr.atime = new Date(node.atime); + attr.mtime = new Date(node.mtime); + attr.ctime = new Date(node.ctime); + + + attr.blksize = 4096; + attr.blocks = Math.ceil(attr.size / attr.blksize); + return attr; + }, + setattr(node, attr) { + for (const key of ["mode", "atime", "mtime", "ctime"]) { + if (attr[key] != null) { + node[key] = attr[key]; + } + } + if (attr.size !== undefined) { + MEMFS.resizeFileStorage(node, attr.size); + } + }, + lookup(parent, name) { + + + if (!MEMFS.doesNotExistError) { + MEMFS.doesNotExistError = new FS.ErrnoError(44); + + MEMFS.doesNotExistError.stack = ''; + } + throw MEMFS.doesNotExistError; + }, + mknod(parent, name, mode, dev) { + return MEMFS.createNode(parent, name, mode, dev); + }, + rename(old_node, new_dir, new_name) { + var new_node; + try { + new_node = FS.lookupNode(new_dir, new_name); + } catch (e) {} + if (new_node) { + if (FS.isDir(old_node.mode)) { + + for (var i in new_node.contents) { + throw new FS.ErrnoError(55); + } + } + FS.hashRemoveNode(new_node); + } + + delete old_node.parent.contents[old_node.name]; + new_dir.contents[new_name] = old_node; + old_node.name = new_name; + new_dir.ctime = new_dir.mtime = old_node.parent.ctime = old_node.parent.mtime = Date.now(); + }, + unlink(parent, name) { + delete parent.contents[name]; + parent.ctime = parent.mtime = Date.now(); + }, + rmdir(parent, name) { + var node = FS.lookupNode(parent, name); + for (var i in node.contents) { + throw new FS.ErrnoError(55); + } + delete parent.contents[name]; + parent.ctime = parent.mtime = Date.now(); + }, + readdir(node) { + return ['.', '..', ...Object.keys(node.contents)]; + }, + symlink(parent, newname, oldpath) { + var node = MEMFS.createNode(parent, newname, 0o777 | 40960, 0); + node.link = oldpath; + return node; + }, + readlink(node) { + if (!FS.isLink(node.mode)) { + throw new FS.ErrnoError(28); + } + return node.link; + }, + }, + stream_ops:{ + read(stream, buffer, offset, length, position) { + var contents = stream.node.contents; + if (position >= stream.node.usedBytes) return 0; + var size = Math.min(stream.node.usedBytes - position, length); + buffer.set(contents.subarray(position, position + size), offset); + return size; + }, + write(stream, buffer, offset, length, position, canOwn) { + + + + + if (buffer.buffer === HEAP8.buffer) { + canOwn = false; + } + + if (!length) return 0; + var node = stream.node; + node.mtime = node.ctime = Date.now(); + + if (canOwn) { + node.contents = buffer.subarray(offset, offset + length); + node.usedBytes = length; + } else if (node.usedBytes === 0 && position === 0) { + node.contents = buffer.slice(offset, offset + length); + node.usedBytes = length; + } else { + MEMFS.expandFileStorage(node, position+length); + + node.contents.set(buffer.subarray(offset, offset + length), position); + node.usedBytes = Math.max(node.usedBytes, position + length); + } + return length; + }, + llseek(stream, offset, whence) { + var position = offset; + if (whence === 1) { + position += stream.position; + } else if (whence === 2) { + if (FS.isFile(stream.node.mode)) { + position += stream.node.usedBytes; + } + } + if (position < 0) { + throw new FS.ErrnoError(28); + } + return position; + }, + mmap(stream, length, position, prot, flags) { + if (!FS.isFile(stream.node.mode)) { + throw new FS.ErrnoError(43); + } + var ptr; + var allocated; + var contents = stream.node.contents; + + if (!(flags & 2) && contents.buffer === HEAP8.buffer) { + + + allocated = false; + ptr = contents.byteOffset; + } else { + allocated = true; + ptr = mmapAlloc(length); + if (!ptr) { + throw new FS.ErrnoError(48); + } + if (contents) { + + if (position > 0 || position + length < contents.length) { + if (contents.subarray) { + contents = contents.subarray(position, position + length); + } else { + contents = Array.prototype.slice.call(contents, position, position + length); + } + } + HEAP8.set(contents, ptr); + } + } + return { ptr, allocated }; + }, + msync(stream, buffer, offset, length, mmapFlags) { + MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false); + + return 0; + }, + }, + }; + + var FS_modeStringToFlags = (str) => { + if (typeof str != 'string') return str; + var flagModes = { + 'r': 0, + 'r+': 2, + 'w': 512 | 64 | 1, + 'w+': 512 | 64 | 2, + 'a': 1024 | 64 | 1, + 'a+': 1024 | 64 | 2, + }; + var flags = flagModes[str]; + if (typeof flags == 'undefined') { + throw new Error(`Unknown file open mode: ${str}`); + } + return flags; + }; + + var FS_fileDataToTypedArray = (data) => { + if (typeof data == 'string') { + data = intArrayFromString(data, true); + } + if (!data.subarray) { + data = new Uint8Array(data); + } + return data; + }; + + var FS_getMode = (canRead, canWrite) => { + var mode = 0; + if (canRead) mode |= 292 | 73; + if (canWrite) mode |= 146; + return mode; + }; + + + var asyncLoad = async (url) => { + var arrayBuffer = await readAsync(url); + return new Uint8Array(arrayBuffer); + }; + + + var FS_createDataFile = (...args) => FS.createDataFile(...args); + + var getUniqueRunDependency = (id) => { + return id; + }; + + var dependenciesPromise = null; + var resolveRunDependencies = async () => dependenciesPromise; + var runDependencies = 0; + + + var dependenciesPromiseResolve = null; + var removeRunDependency = (id) => { + runDependencies--; + + Module['monitorRunDependencies']?.(runDependencies); + + if (!runDependencies) { + dependenciesPromiseResolve(); + } + }; + + + var addRunDependency = (id) => { + if (!runDependencies) { + dependenciesPromise = new Promise((resolve) => dependenciesPromiseResolve = resolve); + } + runDependencies++; + + Module['monitorRunDependencies']?.(runDependencies); + + }; + + + var preloadPlugins = []; + var FS_handledByPreloadPlugin = async (byteArray, fullname) => { + + if (typeof Browser != 'undefined') Browser.init(); + + for (var plugin of preloadPlugins) { + if (plugin['canHandle'](fullname)) { + return plugin['handle'](byteArray, fullname); + } + } + + + return byteArray; + }; + var FS_preloadFile = async (parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish) => { + + + var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent; + var dep = getUniqueRunDependency(`cp ${fullname}`); + addRunDependency(dep); + + try { + var byteArray = url; + if (typeof url == 'string') { + byteArray = await asyncLoad(url); + } + + byteArray = await FS_handledByPreloadPlugin(byteArray, fullname); + preFinish?.(); + if (!dontCreateFile) { + FS_createDataFile(parent, name, byteArray, canRead, canWrite, canOwn); + } + } finally { + removeRunDependency(dep); + } + }; + var FS_createPreloadedFile = (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) => { + FS_preloadFile(parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish).then(onload).catch(onerror); + }; + var FS = { + root:null, + mounts:[], + devices:{ + }, + streams:[], + nextInode:1, + nameTable:null, + currentPath:"/", + initialized:false, + ignorePermissions:true, + filesystems:null, + syncFSRequests:0, + ErrnoError:class { + name = 'ErrnoError'; + + + + + + + constructor(errno) { + this.errno = errno; + } + }, + FSStream:class { + shared = {}; + get object() { + return this.node; + } + set object(val) { + this.node = val; + } + get isRead() { + return (this.flags & 2097155) !== 1; + } + get isWrite() { + return (this.flags & 2097155) !== 0; + } + get isAppend() { + return (this.flags & 1024); + } + get flags() { + return this.shared.flags; + } + set flags(val) { + this.shared.flags = val; + } + get position() { + return this.shared.position; + } + set position(val) { + this.shared.position = val; + } + }, + FSNode:class { + node_ops = {}; + stream_ops = {}; + readMode = 292 | 73; + writeMode = 146; + mounted = null; + constructor(parent, name, mode, rdev) { + if (!parent) { + parent = this; + } + this.parent = parent; + this.mount = parent.mount; + this.id = FS.nextInode++; + this.name = name; + this.mode = mode; + this.rdev = rdev; + this.atime = this.mtime = this.ctime = Date.now(); + } + get read() { + return (this.mode & this.readMode) === this.readMode; + } + set read(val) { + val ? this.mode |= this.readMode : this.mode &= ~this.readMode; + } + get write() { + return (this.mode & this.writeMode) === this.writeMode; + } + set write(val) { + val ? this.mode |= this.writeMode : this.mode &= ~this.writeMode; + } + get isFolder() { + return FS.isDir(this.mode); + } + get isDevice() { + return FS.isChrdev(this.mode); + } + + + + + + + addListener(cb, exclusive = false) { + var entry = {cb, exclusive}; + var listeners = (this.listeners ??= new Set()); + listeners.add(entry); + return {listeners, entry}; + } + notifyListeners(flags) { + + + + + + + + + + + + + + if (!this.listeners) return; + + + + + var excl; + for (var entry of this.listeners) { + if (entry.exclusive) (excl ||= []).push(entry); + else entry.cb(flags); + } + if (excl) { + var i = (this.exclTurn || 0) % excl.length; + this.exclTurn = i + 1; + excl[i].cb(flags); + } + } + }, + lookupPath(path, opts = {}) { + if (!path) { + throw new FS.ErrnoError(44); + } + opts.follow_mount ??= true + + if (!PATH.isAbs(path)) { + path = FS.cwd() + '/' + path; + } + + + linkloop: for (var nlinks = 0; nlinks < 40; nlinks++) { + + var parts = path.split('/').filter((p) => !!p); + + + var current = FS.root; + var current_path = '/'; + + for (var i = 0; i < parts.length; i++) { + var islast = (i === parts.length-1); + if (islast && opts.parent) { + + break; + } + + if (parts[i] === '.') { + continue; + } + + if (parts[i] === '..') { + current_path = PATH.dirname(current_path); + if (FS.isRoot(current)) { + path = current_path + '/' + parts.slice(i + 1).join('/'); + + + nlinks--; + continue linkloop; + } else { + current = current.parent; + } + continue; + } + + current_path = PATH.join2(current_path, parts[i]); + try { + current = FS.lookupNode(current, parts[i]); + } catch (e) { + + + + if ((e?.errno === 44) && islast && opts.noent_okay) { + return { path: current_path }; + } + throw e; + } + + + if (FS.isMountpoint(current) && (!islast || opts.follow_mount)) { + current = current.mounted.root; + } + + + + if (FS.isLink(current.mode) && (!islast || opts.follow)) { + if (!current.node_ops.readlink) { + throw new FS.ErrnoError(52); + } + var link = current.node_ops.readlink(current); + if (!PATH.isAbs(link)) { + link = PATH.dirname(current_path) + '/' + link; + } + path = link + '/' + parts.slice(i + 1).join('/'); + continue linkloop; + } + } + return { path: current_path, node: current }; + } + throw new FS.ErrnoError(32); + }, + getPath(node) { + var path; + while (true) { + if (FS.isRoot(node)) { + var mount = node.mount.mountpoint; + if (!path) return mount; + return mount[mount.length-1] !== '/' ? `${mount}/${path}` : mount + path; + } + path = path ? `${node.name}/${path}` : node.name; + node = node.parent; + } + }, + hashName(parentid, name) { + var hash = 0; + + for (var i = 0; i < name.length; i++) { + hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0; + } + return ((parentid + hash) >>> 0) % FS.nameTable.length; + }, + hashAddNode(node) { + var hash = FS.hashName(node.parent.id, node.name); + node.name_next = FS.nameTable[hash]; + FS.nameTable[hash] = node; + }, + hashRemoveNode(node) { + var hash = FS.hashName(node.parent.id, node.name); + if (FS.nameTable[hash] === node) { + FS.nameTable[hash] = node.name_next; + } else { + var current = FS.nameTable[hash]; + while (current) { + if (current.name_next === node) { + current.name_next = node.name_next; + break; + } + current = current.name_next; + } + } + }, + lookupNode(parent, name) { + var errCode = FS.mayLookup(parent); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + var hash = FS.hashName(parent.id, name); + for (var node = FS.nameTable[hash]; node; node = node.name_next) { + var nodeName = node.name; + if (node.parent.id === parent.id && nodeName === name) { + return node; + } + } + + return FS.lookup(parent, name); + }, + createNode(parent, name, mode, rdev) { + var node = new FS.FSNode(parent, name, mode, rdev); + + FS.hashAddNode(node); + + return node; + }, + destroyNode(node) { + FS.hashRemoveNode(node); + }, + isRoot(node) { + return node === node.parent; + }, + isMountpoint(node) { + return !!node.mounted; + }, + isFile(mode) { + return (mode & 61440) === 32768; + }, + isDir(mode) { + return (mode & 61440) === 16384; + }, + isLink(mode) { + return (mode & 61440) === 40960; + }, + isChrdev(mode) { + return (mode & 61440) === 8192; + }, + isBlkdev(mode) { + return (mode & 61440) === 24576; + }, + isFIFO(mode) { + return (mode & 61440) === 4096; + }, + isSocket(mode) { + return (mode & 49152) === 49152; + }, + flagsToPermissionString(flag) { + var perms = ['r', 'w', 'rw'][flag & 3]; + if ((flag & 512)) { + perms += 'w'; + } + return perms; + }, + nodePermissions(node, perms) { + if (FS.ignorePermissions) { + return 0; + } + + if (perms.includes('r') && !(node.mode & 292)) { + return 2; + } + if (perms.includes('w') && !(node.mode & 146)) { + return 2; + } + if (perms.includes('x') && !(node.mode & 73)) { + return 2; + } + return 0; + }, + mayLookup(dir) { + if (!FS.isDir(dir.mode)) return 54; + var errCode = FS.nodePermissions(dir, 'x'); + if (errCode) return errCode; + if (!dir.node_ops.lookup) return 2; + return 0; + }, + mayCreate(dir, name) { + if (!FS.isDir(dir.mode)) { + return 54; + } + try { + var node = FS.lookupNode(dir, name); + return 20; + } catch (e) { + } + return FS.nodePermissions(dir, 'wx'); + }, + mayDelete(dir, name, isdir) { + var node; + try { + node = FS.lookupNode(dir, name); + } catch (e) { + return e.errno; + } + var errCode = FS.nodePermissions(dir, 'wx'); + if (errCode) { + return errCode; + } + if (isdir) { + if (!FS.isDir(node.mode)) { + return 54; + } + if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) { + return 10; + } + } else if (FS.isDir(node.mode)) { + return 31; + } + return 0; + }, + mayOpen(node, flags) { + if (!node) { + return 44; + } + if (FS.isLink(node.mode)) { + return 32; + } + var mode = FS.flagsToPermissionString(flags); + if (FS.isDir(node.mode)) { + + + if (mode !== 'r' || (flags & (512 | 64))) { + return 31; + } + } + return FS.nodePermissions(node, mode); + }, + checkOpExists(op, err) { + if (!op) { + throw new FS.ErrnoError(err); + } + return op; + }, + MAX_OPEN_FDS:4096, + nextfd() { + for (var fd = 0; fd <= FS.MAX_OPEN_FDS; fd++) { + if (!FS.streams[fd]) { + return fd; + } + } + throw new FS.ErrnoError(33); + }, + getStreamChecked(fd) { + var stream = FS.getStream(fd); + if (!stream) { + throw new FS.ErrnoError(8); + } + return stream; + }, + getStream:(fd) => FS.streams[fd], + createStream(stream, fd = -1) { + + + stream = Object.assign(new FS.FSStream(), stream); + if (fd == -1) { + fd = FS.nextfd(); + } + stream.fd = fd; + FS.streams[fd] = stream; + return stream; + }, + closeStream(fd) { + FS.streams[fd] = null; + }, + dupStream(origStream, fd = -1) { + var stream = FS.createStream(origStream, fd); + stream.stream_ops?.dup?.(stream); + return stream; + }, + doSetAttr(stream, node, attr) { + var setattr = stream?.stream_ops.setattr; + var arg = setattr ? stream : node; + setattr ??= node.node_ops.setattr; + FS.checkOpExists(setattr, 63) + try { + setattr(arg, attr); + } catch (e) { + if (e instanceof RangeError) { + throw new FS.ErrnoError(22); + } + throw e; + } + }, + chrdev_stream_ops:{ + open(stream) { + var device = FS.getDevice(stream.node.rdev); + + stream.stream_ops = device.stream_ops; + + stream.stream_ops.open?.(stream); + }, + llseek() { + throw new FS.ErrnoError(70); + }, + }, + major:(dev) => ((dev) >> 8), + minor:(dev) => ((dev) & 0xff), + makedev:(ma, mi) => ((ma) << 8 | (mi)), + registerDevice(dev, ops) { + FS.devices[dev] = { stream_ops: ops }; + }, + getDevice:(dev) => FS.devices[dev], + getMounts(mount) { + var mounts = []; + var check = [mount]; + + while (check.length) { + var m = check.pop(); + + mounts.push(m); + + check.push(...m.mounts); + } + + return mounts; + }, + syncfs(populate, callback) { + if (typeof populate == 'function') { + callback = populate; + populate = false; + } + + FS.syncFSRequests++; + + if (FS.syncFSRequests > 1) { + err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`); + } + + var mounts = FS.getMounts(FS.root.mount); + var completed = 0; + + function doCallback(errCode) { + FS.syncFSRequests--; + return callback(errCode); + } + + function done(errCode) { + if (errCode) { + if (!done.errored) { + done.errored = true; + return doCallback(errCode); + } + return; + } + if (++completed >= mounts.length) { + doCallback(null); + } + }; + + + for (var mount of mounts) { + if (mount.type.syncfs) { + mount.type.syncfs(mount, populate, done); + } else { + done(null); + } + } + }, + mount(type, opts, mountpoint) { + var root = mountpoint === '/'; + var pseudo = !mountpoint; + var node; + + if (root && FS.root) { + throw new FS.ErrnoError(10); + } else if (!root && !pseudo) { + var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); + + mountpoint = lookup.path; + node = lookup.node; + + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(10); + } + + if (!FS.isDir(node.mode)) { + throw new FS.ErrnoError(54); + } + } + + var mount = { + type, + opts, + mountpoint, + mounts: [] + }; + + + var mountRoot = type.mount(mount); + mountRoot.mount = mount; + mount.root = mountRoot; + + if (root) { + FS.root = mountRoot; + } else if (node) { + + node.mounted = mount; + + + if (node.mount) { + node.mount.mounts.push(mount); + } + } + + return mountRoot; + }, + unmount(mountpoint) { + var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); + + if (!FS.isMountpoint(lookup.node)) { + throw new FS.ErrnoError(28); + } + + + var node = lookup.node; + var mount = node.mounted; + var mounts = FS.getMounts(mount); + + for (var [hash, current] of Object.entries(FS.nameTable)) { + while (current) { + var next = current.name_next; + + if (mounts.includes(current.mount)) { + FS.destroyNode(current); + } + + current = next; + } + } + + + node.mounted = null; + + + var idx = node.mount.mounts.indexOf(mount); + node.mount.mounts.splice(idx, 1); + }, + lookup(parent, name) { + return parent.node_ops.lookup(parent, name); + }, + mknod(path, mode, dev) { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + if (!name) { + throw new FS.ErrnoError(28); + } + if (name === '.' || name === '..') { + throw new FS.ErrnoError(20); + } + var errCode = FS.mayCreate(parent, name); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + if (!parent.node_ops.mknod) { + throw new FS.ErrnoError(63); + } + return parent.node_ops.mknod(parent, name, mode, dev); + }, + statfs(path) { + return FS.statfsNode(FS.lookupPath(path, {follow: true}).node); + }, + statfsStream(stream) { + + + + return FS.statfsNode(stream.node); + }, + statfsNode(node) { + + + + var rtn = { + bsize: 4096, + frsize: 4096, + blocks: 1e6, + bfree: 5e5, + bavail: 5e5, + files: FS.nextInode, + ffree: FS.nextInode - 1, + fsid: 42, + flags: 2, + namelen: 255, + }; + + if (node.node_ops.statfs) { + Object.assign(rtn, node.node_ops.statfs(node.mount.opts.root)); + } + return rtn; + }, + create(path, mode = 0o666) { + mode &= 4095; + mode |= 32768; + return FS.mknod(path, mode, 0); + }, + mkdir(path, mode = 0o777) { + mode &= 511 | 512; + mode |= 16384; + return FS.mknod(path, mode, 0); + }, + mkdirTree(path, mode) { + var dirs = path.split('/'); + var d = ''; + for (var dir of dirs) { + if (!dir) continue; + if (d || PATH.isAbs(path)) d += '/'; + d += dir; + try { + FS.mkdir(d, mode); + } catch(e) { + if (e.errno != 20) throw e; + } + } + }, + mkdev(path, mode, dev) { + if (typeof dev == 'undefined') { + dev = mode; + mode = 0o666; + } + mode |= 8192; + return FS.mknod(path, mode, dev); + }, + symlink(oldpath, newpath) { + if (!PATH_FS.resolve(oldpath)) { + throw new FS.ErrnoError(44); + } + var lookup = FS.lookupPath(newpath, { parent: true }); + var parent = lookup.node; + if (!parent) { + throw new FS.ErrnoError(44); + } + var newname = PATH.basename(newpath); + var errCode = FS.mayCreate(parent, newname); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + if (!parent.node_ops.symlink) { + throw new FS.ErrnoError(63); + } + return parent.node_ops.symlink(parent, newname, oldpath); + }, + link(oldpath, newpath, flags) { + var lookup = FS.lookupPath(newpath, { parent: true }); + var parent = lookup.node; + if (!parent) { + throw new FS.ErrnoError(44); + } + var newname = PATH.basename(newpath); + var errCode = FS.mayCreate(parent, newname); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + + + + if (!parent.node_ops.link) { + throw new FS.ErrnoError(34); + } + return parent.node_ops.link(parent, newname, oldpath, flags); + }, + rename(old_path, new_path) { + var old_dirname = PATH.dirname(old_path); + var new_dirname = PATH.dirname(new_path); + var old_name = PATH.basename(old_path); + var new_name = PATH.basename(new_path); + + var lookup, old_dir, new_dir; + + + lookup = FS.lookupPath(old_path, { parent: true }); + old_dir = lookup.node; + lookup = FS.lookupPath(new_path, { parent: true }); + new_dir = lookup.node; + + if (!old_dir || !new_dir) throw new FS.ErrnoError(44); + + if (old_dir.mount !== new_dir.mount) { + throw new FS.ErrnoError(75); + } + + var old_node = FS.lookupNode(old_dir, old_name); + + var relative = PATH_FS.relative(old_path, new_dirname); + if (relative.charAt(0) !== '.') { + throw new FS.ErrnoError(28); + } + + relative = PATH_FS.relative(new_path, old_dirname); + if (relative.charAt(0) !== '.') { + throw new FS.ErrnoError(55); + } + + var new_node; + try { + new_node = FS.lookupNode(new_dir, new_name); + } catch (e) { + + } + + if (old_node === new_node) { + return; + } + + var isdir = FS.isDir(old_node.mode); + var errCode = FS.mayDelete(old_dir, old_name, isdir); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + + + errCode = new_node ? + FS.mayDelete(new_dir, new_name, isdir) : + FS.mayCreate(new_dir, new_name); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + if (!old_dir.node_ops.rename) { + throw new FS.ErrnoError(63); + } + if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) { + throw new FS.ErrnoError(10); + } + + if (new_dir !== old_dir) { + errCode = FS.nodePermissions(old_dir, 'w'); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + } + + FS.hashRemoveNode(old_node); + + try { + old_dir.node_ops.rename(old_node, new_dir, new_name); + + + old_node.parent = new_dir; + } catch (e) { + throw e; + } finally { + + + FS.hashAddNode(old_node); + } + }, + rmdir(path) { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + var node = FS.lookupNode(parent, name); + var errCode = FS.mayDelete(parent, name, true); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + if (!parent.node_ops.rmdir) { + throw new FS.ErrnoError(63); + } + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(10); + } + parent.node_ops.rmdir(parent, name); + FS.destroyNode(node); + }, + readdir(path) { + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + var readdir = FS.checkOpExists(node.node_ops.readdir, 54); + return readdir(node); + }, + unlink(path) { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + if (!parent) { + throw new FS.ErrnoError(44); + } + var name = PATH.basename(path); + var node = FS.lookupNode(parent, name); + var errCode = FS.mayDelete(parent, name, false); + if (errCode) { + + + + throw new FS.ErrnoError(errCode); + } + if (!parent.node_ops.unlink) { + throw new FS.ErrnoError(63); + } + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(10); + } + parent.node_ops.unlink(parent, name); + FS.destroyNode(node); + }, + readlink(path) { + var lookup = FS.lookupPath(path); + var link = lookup.node; + if (!link) { + throw new FS.ErrnoError(44); + } + if (!link.node_ops.readlink) { + throw new FS.ErrnoError(28); + } + return link.node_ops.readlink(link); + }, + stat(path, dontFollow) { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + var node = lookup.node; + var getattr = FS.checkOpExists(node.node_ops.getattr, 63); + return getattr(node); + }, + fstat(fd) { + var stream = FS.getStreamChecked(fd); + var node = stream.node; + var getattr = stream.stream_ops.getattr; + var arg = getattr ? stream : node; + getattr ??= node.node_ops.getattr; + FS.checkOpExists(getattr, 63) + return getattr(arg); + }, + lstat(path) { + return FS.stat(path, true); + }, + doChmod(stream, node, mode, dontFollow) { + FS.doSetAttr(stream, node, { + mode: (mode & 4095) | (node.mode & ~4095), + ctime: Date.now(), + dontFollow + }); + }, + chmod(path, mode, dontFollow) { + var node; + if (typeof path == 'string') { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + node = lookup.node; + } else { + node = path; + } + FS.doChmod(null, node, mode, dontFollow); + }, + lchmod(path, mode) { + FS.chmod(path, mode, true); + }, + fchmod(fd, mode) { + var stream = FS.getStreamChecked(fd); + FS.doChmod(stream, stream.node, mode, false); + }, + doChown(stream, node, dontFollow) { + FS.doSetAttr(stream, node, { + timestamp: Date.now(), + dontFollow + + }); + }, + chown(path, uid, gid, dontFollow) { + var node; + if (typeof path == 'string') { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + node = lookup.node; + } else { + node = path; + } + FS.doChown(null, node, dontFollow); + }, + lchown(path, uid, gid) { + FS.chown(path, uid, gid, true); + }, + fchown(fd, uid, gid) { + var stream = FS.getStreamChecked(fd); + FS.doChown(stream, stream.node, false); + }, + doTruncate(stream, node, len) { + if (FS.isDir(node.mode)) { + throw new FS.ErrnoError(31); + } + if (!FS.isFile(node.mode)) { + throw new FS.ErrnoError(28); + } + var errCode = FS.nodePermissions(node, 'w'); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + FS.doSetAttr(stream, node, { + size: len, + timestamp: Date.now() + }); + }, + truncate(path, len) { + if (len < 0) { + throw new FS.ErrnoError(28); + } + var node; + if (typeof path == 'string') { + var lookup = FS.lookupPath(path, { follow: true }); + node = lookup.node; + } else { + node = path; + } + FS.doTruncate(null, node, len); + }, + ftruncate(fd, len) { + var stream = FS.getStreamChecked(fd); + if (len < 0 || (stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(28); + } + FS.doTruncate(stream, stream.node, len); + }, + utime(path, atime, mtime, dontFollow) { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + FS.doSetAttr(null, lookup.node, { + atime: atime, + mtime: mtime, + dontFollow + }); + }, + open(path, flags, mode = 0o666) { + if (path === "") { + throw new FS.ErrnoError(44); + } + flags = FS_modeStringToFlags(flags); + if ((flags & 64)) { + mode = (mode & 4095) | 32768; + } else { + mode = 0; + } + var node; + var isDirPath; + if (typeof path == 'object') { + node = path; + } else { + isDirPath = path.endsWith("/"); + + + + var lookup = FS.lookupPath(path, { + follow: !(flags & 131072), + noent_okay: true + }); + node = lookup.node; + path = lookup.path; + } + + var created = false; + if ((flags & 64)) { + if (node) { + + if ((flags & 128)) { + throw new FS.ErrnoError(20); + } + } else if (isDirPath) { + throw new FS.ErrnoError(31); + } else { + + + + + node = FS.mknod(path, mode | 0o777, 0); + created = true; + } + } + if (!node) { + throw new FS.ErrnoError(44); + } + + if (FS.isChrdev(node.mode)) { + flags &= ~512; + } + + if ((flags & 65536) && !FS.isDir(node.mode)) { + throw new FS.ErrnoError(54); + } + + + + if (!created) { + var errCode = FS.mayOpen(node, flags); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + } + + if ((flags & 512) && !created) { + FS.truncate(node, 0); + } + + flags &= ~(128 | 512 | 131072); + + + var stream = FS.createStream({ + node, + path: FS.getPath(node), + flags, + seekable: true, + position: 0, + stream_ops: node.stream_ops, + + ungotten: [], + error: false + }); + + if (stream.stream_ops.open) { + stream.stream_ops.open(stream); + } + if (created) { + FS.chmod(node, mode & 0o777); + } + return stream; + }, + close(stream) { + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if (stream.getdents) stream.getdents = null; + + + + + stream.node?.notifyListeners(32); + try { + if (stream.stream_ops.close) { + stream.stream_ops.close(stream); + } + } catch (e) { + throw e; + } finally { + FS.closeStream(stream.fd); + } + stream.fd = null; + }, + isClosed(stream) { + return stream.fd === null; + }, + llseek(stream, offset, whence) { + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if (!stream.seekable || !stream.stream_ops.llseek) { + throw new FS.ErrnoError(70); + } + if (whence != 0 && whence != 1 && whence != 2) { + throw new FS.ErrnoError(28); + } + stream.position = stream.stream_ops.llseek(stream, offset, whence); + stream.ungotten = []; + return stream.position; + }, + read(stream, buffer, offset, length, position) { + if (length < 0 || position < 0) { + throw new FS.ErrnoError(28); + } + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if ((stream.flags & 2097155) === 1) { + throw new FS.ErrnoError(8); + } + if (FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(31); + } + if (!stream.stream_ops.read) { + throw new FS.ErrnoError(28); + } + var seeking = typeof position != 'undefined'; + if (!seeking) { + position = stream.position; + } else if (!stream.seekable) { + throw new FS.ErrnoError(70); + } + var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position); + if (!seeking) stream.position += bytesRead; + return bytesRead; + }, + write(stream, buffer, offset, length, position, canOwn) { + if (length < 0 || position < 0) { + throw new FS.ErrnoError(28); + } + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(8); + } + if (FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(31); + } + if (!stream.stream_ops.write) { + throw new FS.ErrnoError(28); + } + if (stream.seekable && stream.flags & 1024) { + + FS.llseek(stream, 0, 2); + } + var seeking = typeof position != 'undefined'; + if (!seeking) { + position = stream.position; + } else if (!stream.seekable) { + throw new FS.ErrnoError(70); + } + var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn); + if (!seeking) stream.position += bytesWritten; + return bytesWritten; + }, + mmap(stream, length, position, prot, flags) { + + + + + + + if ((prot & 2) !== 0 + && (flags & 2) === 0 + && (stream.flags & 2097155) !== 2) { + throw new FS.ErrnoError(2); + } + if ((stream.flags & 2097155) === 1) { + throw new FS.ErrnoError(2); + } + if (!stream.stream_ops.mmap) { + throw new FS.ErrnoError(43); + } + if (!length) { + throw new FS.ErrnoError(28); + } + return stream.stream_ops.mmap(stream, length, position, prot, flags); + }, + msync(stream, buffer, offset, length, mmapFlags) { + if (!stream.stream_ops.msync) { + return 0; + } + return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags); + }, + ioctl(stream, cmd, arg) { + if (!stream.stream_ops.ioctl) { + throw new FS.ErrnoError(59); + } + return stream.stream_ops.ioctl(stream, cmd, arg); + }, + readFile(path, opts = {}) { + opts.flags = opts.flags ?? 0; + opts.encoding = opts.encoding ?? 'binary'; + if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') { + abort(`Invalid encoding type "${opts.encoding}"`); + } + var stream = FS.open(path, opts.flags); + var stat = FS.stat(path); + var length = stat.size; + var buf = new Uint8Array(length); + FS.read(stream, buf, 0, length, 0); + if (opts.encoding === 'utf8') { + buf = UTF8ArrayToString(buf); + } + FS.close(stream); + return buf; + }, + writeFile(path, data, opts = {}) { + opts.flags = opts.flags ?? 577; + var stream = FS.open(path, opts.flags, opts.mode); + data = FS_fileDataToTypedArray(data); + FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn); + FS.close(stream); + }, + cwd:() => FS.currentPath, + chdir(path) { + var lookup = FS.lookupPath(path, { follow: true }); + if (lookup.node === null) { + throw new FS.ErrnoError(44); + } + if (!FS.isDir(lookup.node.mode)) { + throw new FS.ErrnoError(54); + } + var errCode = FS.nodePermissions(lookup.node, 'x'); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + FS.currentPath = lookup.path; + }, + createDefaultDirectories() { + FS.mkdir('/tmp'); + FS.mkdir('/home'); + FS.mkdir('/home/web_user'); + }, + createDefaultDevices() { + + FS.mkdir('/dev'); + + FS.registerDevice(FS.makedev(1, 3), { + read: () => 0, + write: (stream, buffer, offset, length, pos) => length, + llseek: () => 0, + }); + FS.mkdev('/dev/null', FS.makedev(1, 3)); + + + + TTY.register(FS.makedev(5, 0), TTY.default_tty_ops); + TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops); + FS.mkdev('/dev/tty', FS.makedev(5, 0)); + FS.mkdev('/dev/tty1', FS.makedev(6, 0)); + + + var randomBuffer = new Uint8Array(1024), randomLeft = 0; + var randomByte = () => { + if (randomLeft === 0) { + randomFill(randomBuffer); + randomLeft = randomBuffer.byteLength; + } + return randomBuffer[--randomLeft]; + }; + FS.createDevice('/dev', 'random', randomByte); + FS.createDevice('/dev', 'urandom', randomByte); + + + FS.mkdir('/dev/shm'); + FS.mkdir('/dev/shm/tmp'); + }, + createSpecialDirectories() { + + + FS.mkdir('/proc'); + var proc_self = FS.mkdir('/proc/self'); + FS.mkdir('/proc/self/fd'); + FS.mount({ + mount() { + var node = FS.createNode(proc_self, 'fd', 16895, 73); + node.stream_ops = { + llseek: MEMFS.stream_ops.llseek, + }; + node.node_ops = { + lookup(parent, name) { + var fd = +name; + var stream = FS.getStreamChecked(fd); + var ret = { + parent: null, + mount: { mountpoint: 'fake' }, + node_ops: { readlink: () => stream.path }, + id: fd + 1, + }; + ret.parent = ret; + return ret; + }, + readdir() { + return Array.from(FS.streams.entries()) + .filter(([k, v]) => v) + .map(([k, v]) => k.toString()); + } + }; + return node; + } + }, {}, '/proc/self/fd'); + }, + createStandardStreams(input, output, error) { + + + + + + + + + if (input) { + FS.createDevice('/dev', 'stdin', input); + } else { + FS.symlink('/dev/tty', '/dev/stdin'); + } + if (output) { + FS.createDevice('/dev', 'stdout', null, output); + } else { + FS.symlink('/dev/tty', '/dev/stdout'); + } + if (error) { + FS.createDevice('/dev', 'stderr', null, error); + } else { + FS.symlink('/dev/tty1', '/dev/stderr'); + } + + + var stdin = FS.open('/dev/stdin', 0); + var stdout = FS.open('/dev/stdout', 1); + var stderr = FS.open('/dev/stderr', 1); + }, + staticInit() { + FS.nameTable = new Array(4096); + + FS.mount(MEMFS, {}, '/'); + + FS.createDefaultDirectories(); + FS.createDefaultDevices(); + FS.createSpecialDirectories(); + + FS.filesystems = { + 'MEMFS': MEMFS, + }; + }, + init(input, output, error) { + FS.initialized = true; + + + input ??= Module['stdin']; + output ??= Module['stdout']; + error ??= Module['stderr']; + + FS.createStandardStreams(input, output, error); + }, + quit() { + FS.initialized = false; + + + for (var stream of FS.streams) { + if (stream) { + FS.close(stream); + } + } + }, + findObject(path, dontResolveLastLink) { + var ret = FS.analyzePath(path, dontResolveLastLink); + if (!ret.exists) { + return null; + } + return ret.object; + }, + analyzePath(path, dontResolveLastLink) { + + try { + var lookup = FS.lookupPath(path, { follow: !dontResolveLastLink }); + path = lookup.path; + } catch (e) { + } + var ret = { + isRoot: false, exists: false, error: 0, name: null, path: null, object: null, + parentExists: false, parentPath: null, parentObject: null + }; + try { + var lookup = FS.lookupPath(path, { parent: true }); + ret.parentExists = true; + ret.parentPath = lookup.path; + ret.parentObject = lookup.node; + ret.name = PATH.basename(path); + lookup = FS.lookupPath(path, { follow: !dontResolveLastLink }); + ret.exists = true; + ret.path = lookup.path; + ret.object = lookup.node; + ret.name = lookup.node.name; + ret.isRoot = lookup.path === '/'; + } catch (e) { + ret.error = e.errno; + }; + return ret; + }, + createPath(parent, path, canRead, canWrite) { + parent = typeof parent == 'string' ? parent : FS.getPath(parent); + var parts = path.split('/').reverse(); + while (parts.length) { + var part = parts.pop(); + if (!part) continue; + var current = PATH.join2(parent, part); + try { + FS.mkdir(current); + } catch (e) { + if (e.errno != 20) throw e; + } + parent = current; + } + return current; + }, + createFile(parent, name, properties, canRead, canWrite) { + var path = PATH.join2(typeof parent == 'string' ? parent : FS.getPath(parent), name); + var mode = FS_getMode(canRead, canWrite); + return FS.create(path, mode); + }, + createDataFile(parent, name, data, canRead, canWrite, canOwn) { + var path = name; + if (parent) { + parent = typeof parent == 'string' ? parent : FS.getPath(parent); + path = name ? PATH.join2(parent, name) : parent; + } + var mode = FS_getMode(canRead, canWrite); + var node = FS.create(path, mode); + if (data) { + data = FS_fileDataToTypedArray(data); + + FS.chmod(node, mode | 146); + var stream = FS.open(node, 577); + FS.write(stream, data, 0, data.length, 0, canOwn); + FS.close(stream); + FS.chmod(node, mode); + } + }, + createDevice(parent, name, input, output) { + var path = PATH.join2(typeof parent == 'string' ? parent : FS.getPath(parent), name); + var mode = FS_getMode(!!input, !!output); + FS.createDevice.major ??= 64; + var dev = FS.makedev(FS.createDevice.major++, 0); + + + FS.registerDevice(dev, { + open(stream) { + stream.seekable = false; + }, + close(stream) { + + if (output?.buffer?.length) { + output(10); + } + }, + read(stream, buffer, offset, length, pos ) { + var bytesRead = 0; + for (var i = 0; i < length; i++) { + var result; + try { + result = input(); + } catch (e) { + throw new FS.ErrnoError(29); + } + if (result === undefined && bytesRead === 0) { + throw new FS.ErrnoError(6); + } + if (result === null || result === undefined) break; + bytesRead++; + buffer[offset+i] = result; + } + if (bytesRead) { + stream.node.atime = Date.now(); + } + return bytesRead; + }, + write(stream, buffer, offset, length, pos) { + for (var i = 0; i < length; i++) { + try { + output(buffer[offset+i]); + } catch (e) { + throw new FS.ErrnoError(29); + } + } + if (length) { + stream.node.mtime = stream.node.ctime = Date.now(); + } + return i; + } + }); + return FS.mkdev(path, mode, dev); + }, + forceLoadFile(obj) { + if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true; + if (globalThis.XMLHttpRequest) { + abort("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread."); + } else { + try { + obj.contents = readBinary(obj.url); + } catch (e) { + throw new FS.ErrnoError(29); + } + } + }, + createLazyFile(parent, name, url, canRead, canWrite) { + + + class LazyUint8Array { + lengthKnown = false; + chunks = []; + get(idx) { + if (idx > this.length-1 || idx < 0) { + return undefined; + } + var chunkOffset = idx % this.chunkSize; + var chunkNum = (idx / this.chunkSize)|0; + return this.getter(chunkNum)[chunkOffset]; + } + setDataGetter(getter) { + this.getter = getter; + } + cacheLength() { + + var xhr = new XMLHttpRequest(); + xhr.open('HEAD', url, false); + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) abort("Couldn't load " + url + ". Status: " + xhr.status); + var datalength = Number(xhr.getResponseHeader("Content-length")); + var header; + var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes"; + var usesGzip = (header = xhr.getResponseHeader("Content-Encoding")) && header === "gzip"; + + var chunkSize = 1024*1024; + + if (!hasByteServing) chunkSize = datalength; + + + var doXHR = (from, to) => { + if (from > to) abort(`invalid range (${from}, ${to}) or no bytes requested!`); + if (to > datalength-1) abort(`only ${datalength} bytes available! programmer error!`); + + + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); + + + xhr.responseType = 'arraybuffer'; + if (xhr.overrideMimeType) { + xhr.overrideMimeType('text/plain; charset=x-user-defined'); + } + + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) abort("Couldn't load " + url + ". Status: " + xhr.status); + if (xhr.response !== undefined) { + return new Uint8Array((xhr.response || [])); + } + return intArrayFromString(xhr.responseText ?? '', true); + }; + var lazyArray = this; + lazyArray.setDataGetter((chunkNum) => { + var start = chunkNum * chunkSize; + var end = (chunkNum+1) * chunkSize - 1; + end = Math.min(end, datalength-1); + if (typeof lazyArray.chunks[chunkNum] == 'undefined') { + lazyArray.chunks[chunkNum] = doXHR(start, end); + } + if (typeof lazyArray.chunks[chunkNum] == 'undefined') abort('doXHR failed!'); + return lazyArray.chunks[chunkNum]; + }); + + if (usesGzip || !datalength) { + + chunkSize = datalength = 1; + datalength = this.getter(0).length; + chunkSize = datalength; + out("LazyFiles on gzip forces download of the whole file when length is accessed"); + } + + this._length = datalength; + this._chunkSize = chunkSize; + this.lengthKnown = true; + } + get length() { + if (!this.lengthKnown) { + this.cacheLength(); + } + return this._length; + } + get chunkSize() { + if (!this.lengthKnown) { + this.cacheLength(); + } + return this._chunkSize; + } + } + + if (globalThis.XMLHttpRequest) { + if (!ENVIRONMENT_IS_WORKER) abort('Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc'); + var lazyArray = new LazyUint8Array(); + var properties = { isDevice: false, contents: lazyArray }; + } else { + var properties = { isDevice: false, url: url }; + } + + var node = FS.createFile(parent, name, properties, canRead, canWrite); + + + + if (properties.contents) { + node.contents = properties.contents; + } else if (properties.url) { + node.contents = null; + node.url = properties.url; + } + + Object.defineProperties(node, { + usedBytes: { + get: function() { return this.contents.length; } + } + }); + + var stream_ops = {}; + for (const [key, fn] of Object.entries(node.stream_ops)) { + stream_ops[key] = (...args) => { + FS.forceLoadFile(node); + return fn(...args); + }; + } + function writeChunks(stream, buffer, offset, length, position) { + var contents = stream.node.contents; + if (position >= contents.length) + return 0; + var size = Math.min(contents.length - position, length); + if (contents.slice) { + for (var i = 0; i < size; i++) { + buffer[offset + i] = contents[position + i]; + } + } else { + for (var i = 0; i < size; i++) { + buffer[offset + i] = contents.get(position + i); + } + } + return size; + } + + stream_ops.read = (stream, buffer, offset, length, position) => { + FS.forceLoadFile(node); + return writeChunks(stream, buffer, offset, length, position) + }; + + stream_ops.mmap = (stream, length, position, prot, flags) => { + FS.forceLoadFile(node); + var ptr = mmapAlloc(length); + if (!ptr) { + throw new FS.ErrnoError(48); + } + writeChunks(stream, HEAP8, ptr, length, position); + return { ptr, allocated: true }; + }; + node.stream_ops = stream_ops; + return node; + }, + }; + + + + + var UTF8ToString = (ptr, maxBytesToRead, ignoreNul) => { + if (!ptr) return ''; + var end = findStringEnd(HEAPU8, ptr, maxBytesToRead, ignoreNul); + return UTF8Decoder.decode(HEAPU8.subarray(ptr, end)); + }; + var SYSCALLS = { + currentUmask:18, + calculateAt(dirfd, path, allowEmpty) { + if (PATH.isAbs(path)) { + return path; + } + + var dir; + if (dirfd === -100) { + dir = FS.cwd(); + } else { + var dirstream = SYSCALLS.getStreamFromFD(dirfd); + dir = dirstream.path; + } + if (path.length == 0) { + if (!allowEmpty) { + throw new FS.ErrnoError(44);; + } + return dir; + } + return dir + '/' + path; + }, + writeStat(buf, stat) { + HEAPU32[((buf)>>2)] = stat.dev; + HEAPU32[(((buf)+(4))>>2)] = stat.mode; + HEAPU32[(((buf)+(8))>>2)] = stat.nlink; + HEAPU32[(((buf)+(12))>>2)] = stat.uid; + HEAPU32[(((buf)+(16))>>2)] = stat.gid; + HEAPU32[(((buf)+(20))>>2)] = stat.rdev; + HEAP64[(((buf)+(24))>>3)] = BigInt(stat.size); + HEAP32[(((buf)+(32))>>2)] = 4096; + HEAP32[(((buf)+(36))>>2)] = stat.blocks; + var atime = stat.atime.getTime(); + var mtime = stat.mtime.getTime(); + var ctime = stat.ctime.getTime(); + HEAP64[(((buf)+(40))>>3)] = BigInt(Math.floor(atime / 1000)); + HEAPU32[(((buf)+(48))>>2)] = (atime % 1000) * 1000 * 1000; + HEAP64[(((buf)+(56))>>3)] = BigInt(Math.floor(mtime / 1000)); + HEAPU32[(((buf)+(64))>>2)] = (mtime % 1000) * 1000 * 1000; + HEAP64[(((buf)+(72))>>3)] = BigInt(Math.floor(ctime / 1000)); + HEAPU32[(((buf)+(80))>>2)] = (ctime % 1000) * 1000 * 1000; + HEAP64[(((buf)+(88))>>3)] = BigInt(stat.ino); + return 0; + }, + writeStatFs(buf, stats) { + HEAPU32[(((buf)+(4))>>2)] = stats.bsize; + HEAPU32[(((buf)+(60))>>2)] = stats.bsize; + HEAP64[(((buf)+(8))>>3)] = BigInt(stats.blocks); + HEAP64[(((buf)+(16))>>3)] = BigInt(stats.bfree); + HEAP64[(((buf)+(24))>>3)] = BigInt(stats.bavail); + HEAP64[(((buf)+(32))>>3)] = BigInt(stats.files); + HEAP64[(((buf)+(40))>>3)] = BigInt(stats.ffree); + HEAPU32[(((buf)+(48))>>2)] = stats.fsid; + HEAPU32[(((buf)+(64))>>2)] = stats.flags; + HEAPU32[(((buf)+(56))>>2)] = stats.namelen; + }, + doMsync(addr, stream, len, flags, offset) { + if (!FS.isFile(stream.node.mode)) { + throw new FS.ErrnoError(43); + } + if (flags & 2) { + + return 0; + } + var buffer = HEAPU8.subarray(addr, addr + len); + FS.msync(stream, buffer, offset, len, flags); + }, + getStreamFromFD(fd) { + var stream = FS.getStreamChecked(fd); + return stream; + }, + varargs:undefined, + getStr(ptr) { + var ret = UTF8ToString(ptr); + return ret; + }, + }; + function ___syscall_chmod(path, mode) { + try { + + path = SYSCALLS.getStr(path); + FS.chmod(path, mode); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + function ___syscall_faccessat(dirfd, path, amode, flags) { + try { + + path = SYSCALLS.getStr(path); + path = SYSCALLS.calculateAt(dirfd, path); + if (amode & ~7) { + + return -28; + } + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + if (!node) { + return -44; + } + var perms = ''; + if (amode & 4) perms += 'r'; + if (amode & 2) perms += 'w'; + if (amode & 1) perms += 'x'; + if (perms && FS.nodePermissions(node, perms)) { + return -2; + } + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + function ___syscall_fchmod(fd, mode) { + try { + + FS.fchmod(fd, mode); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + function ___syscall_fchown32(fd, owner, group) { + try { + + FS.fchown(fd, owner, group); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + var syscallGetVarargI = () => { + + var ret = HEAP32[((+SYSCALLS.varargs)>>2)]; + SYSCALLS.varargs += 4; + return ret; + }; + var syscallGetVarargP = syscallGetVarargI; + + + function ___syscall_fcntl64(fd, cmd, varargs) { + SYSCALLS.varargs = varargs; + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + switch (cmd) { + case 0: { + var arg = syscallGetVarargI(); + if (arg < 0) { + return -28; + } + while (FS.streams[arg]) { + arg++; + } + var newStream; + newStream = FS.dupStream(stream, arg); + return newStream.fd; + } + case 1: + case 2: + return 0; + case 3: + return stream.flags; + case 4: { + var arg = syscallGetVarargI(); + var mask = 289792; + stream.flags = (stream.flags & ~mask) | (arg & mask); + return 0; + } + case 12: { + var arg = syscallGetVarargP(); + var offset = 0; + + HEAP16[(((arg)+(offset))>>1)] = 2; + return 0; + } + case 13: + case 14: + + + + + return 0; + } + return -28; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + function ___syscall_fstat64(fd, buf) { + try { + + return SYSCALLS.writeStat(buf, FS.fstat(fd)); + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + var INT53_MAX = 9007199254740992; + + var INT53_MIN = -9007199254740992; + var bigintToI53Checked = (num) => (num < INT53_MIN || num > INT53_MAX) ? NaN : Number(num); + function ___syscall_ftruncate64(fd, length) { + length = bigintToI53Checked(length); + + + try { + + if (isNaN(length)) return -22; + FS.ftruncate(fd, length); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + ; + } + + + var stringToUTF8 = (str, outPtr, maxBytesToWrite) => { + return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite); + }; + function ___syscall_getcwd(buf, size) { + try { + + if (size === 0) return -28; + var cwd = FS.cwd(); + var cwdLengthInBytes = lengthBytesUTF8(cwd) + 1; + if (size < cwdLengthInBytes) return -68; + stringToUTF8(cwd, buf, size); + return cwdLengthInBytes; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + + function ___syscall_ioctl(fd, op, varargs) { + SYSCALLS.varargs = varargs; + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + switch (op) { + case 21509: { + if (!stream.tty) return -59; + return 0; + } + case 21505: { + if (!stream.tty) return -59; + if (stream.tty.ops.ioctl_tcgets) { + var termios = stream.tty.ops.ioctl_tcgets(stream); + var argp = syscallGetVarargP(); + HEAP32[((argp)>>2)] = termios.c_iflag || 0; + HEAP32[(((argp)+(4))>>2)] = termios.c_oflag || 0; + HEAP32[(((argp)+(8))>>2)] = termios.c_cflag || 0; + HEAP32[(((argp)+(12))>>2)] = termios.c_lflag || 0; + for (var i = 0; i < 32; i++) { + HEAP8[(argp + i)+(17)] = termios.c_cc[i] || 0; + } + return 0; + } + return 0; + } + case 21510: + case 21511: + case 21512: { + if (!stream.tty) return -59; + return 0; + } + case 21506: + case 21507: + case 21508: { + if (!stream.tty) return -59; + if (stream.tty.ops.ioctl_tcsets) { + var argp = syscallGetVarargP(); + var c_iflag = HEAP32[((argp)>>2)]; + var c_oflag = HEAP32[(((argp)+(4))>>2)]; + var c_cflag = HEAP32[(((argp)+(8))>>2)]; + var c_lflag = HEAP32[(((argp)+(12))>>2)]; + var c_cc = [] + for (var i = 0; i < 32; i++) { + c_cc.push(HEAP8[(argp + i)+(17)]); + } + return stream.tty.ops.ioctl_tcsets(stream.tty, op, { c_iflag, c_oflag, c_cflag, c_lflag, c_cc }); + } + return 0; + } + case 21519: { + if (!stream.tty) return -59; + var argp = syscallGetVarargP(); + HEAP32[((argp)>>2)] = 0; + return 0; + } + case 21520: { + if (!stream.tty) return -59; + return -28; + } + case 21537: + case 21531: { + var argp = syscallGetVarargP(); + return FS.ioctl(stream, op, argp); + } + case 21523: { + + + if (!stream.tty) return -59; + if (stream.tty.ops.ioctl_tiocgwinsz) { + var winsize = stream.tty.ops.ioctl_tiocgwinsz(stream.tty); + var argp = syscallGetVarargP(); + HEAP16[((argp)>>1)] = winsize[0]; + HEAP16[(((argp)+(2))>>1)] = winsize[1]; + } + return 0; + } + case 21524: { + + + + if (!stream.tty) return -59; + return 0; + } + case 21515: { + if (!stream.tty) return -59; + return 0; + } + default: return -28; + } + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + function ___syscall_lstat64(path, buf) { + try { + + path = SYSCALLS.getStr(path); + return SYSCALLS.writeStat(buf, FS.lstat(path)); + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + function ___syscall_mkdirat(dirfd, path, mode) { + try { + + path = SYSCALLS.getStr(path); + path = SYSCALLS.calculateAt(dirfd, path); + mode &= ~SYSCALLS.currentUmask; + FS.mkdir(path, mode, 0); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + function ___syscall_newfstatat(dirfd, path, buf, flags) { + try { + + path = SYSCALLS.getStr(path); + var nofollow = flags & 256; + var allowEmpty = flags & 4096; + flags = flags & (~6400); + path = SYSCALLS.calculateAt(dirfd, path, allowEmpty); + return SYSCALLS.writeStat(buf, nofollow ? FS.lstat(path) : FS.stat(path)); + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + + function ___syscall_openat(dirfd, path, flags, varargs) { + SYSCALLS.varargs = varargs; + try { + + path = SYSCALLS.getStr(path); + path = SYSCALLS.calculateAt(dirfd, path); + var mode = varargs ? syscallGetVarargI() : 0; + if (flags & 64) { + mode &= ~SYSCALLS.currentUmask; + } + return FS.open(path, flags, mode).fd; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + + + function ___syscall_readlinkat(dirfd, path, buf, bufsize) { + try { + + path = SYSCALLS.getStr(path); + path = SYSCALLS.calculateAt(dirfd, path); + if (bufsize <= 0) return -28; + var ret = FS.readlink(path); + + var len = Math.min(bufsize, lengthBytesUTF8(ret)); + var endChar = HEAP8[buf+len]; + stringToUTF8(ret, buf, bufsize+1); + + + HEAP8[buf+len] = endChar; + return len; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + function ___syscall_rmdir(path) { + try { + + path = SYSCALLS.getStr(path); + FS.rmdir(path); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + function ___syscall_stat64(path, buf) { + try { + + path = SYSCALLS.getStr(path); + return SYSCALLS.writeStat(buf, FS.stat(path)); + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + function ___syscall_unlinkat(dirfd, path, flags) { + try { + + path = SYSCALLS.getStr(path); + path = SYSCALLS.calculateAt(dirfd, path); + if (!flags) { + FS.unlink(path); + } else if (flags === 512) { + FS.rmdir(path); + } else { + return -28; + } + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + var readI53FromI64 = (ptr) => { + return HEAPU32[((ptr)>>2)] + HEAP32[(((ptr)+(4))>>2)] * 4294967296; + }; + + function ___syscall_utimensat(dirfd, path, times, flags) { + try { + + var nofollow = flags & 256; + path = SYSCALLS.getStr(path); + path = SYSCALLS.calculateAt(dirfd, path, true); + var now = Date.now(), atime, mtime; + if (!times) { + atime = now; + mtime = now; + } else { + var seconds = readI53FromI64(times); + var nanoseconds = HEAP32[(((times)+(8))>>2)]; + if (nanoseconds == 1073741823) { + atime = now; + } else if (nanoseconds == 1073741822) { + atime = null; + } else { + atime = (seconds*1000) + (nanoseconds/(1000*1000)); + } + times += 16; + seconds = readI53FromI64(times); + nanoseconds = HEAP32[(((times)+(8))>>2)]; + if (nanoseconds == 1073741823) { + mtime = now; + } else if (nanoseconds == 1073741822) { + mtime = null; + } else { + mtime = (seconds*1000) + (nanoseconds/(1000*1000)); + } + } + + + if ((mtime ?? atime) !== null) { + FS.utime(path, atime, mtime, nofollow); + } + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + var __abort_js = () => + abort(''); + + var isLeapYear = (year) => year%4 === 0 && (year%100 !== 0 || year%400 === 0); + + var MONTH_DAYS_LEAP_CUMULATIVE = [0,31,60,91,121,152,182,213,244,274,305,335]; + + var MONTH_DAYS_REGULAR_CUMULATIVE = [0,31,59,90,120,151,181,212,243,273,304,334]; + var ydayFromDate = (date) => { + var leap = isLeapYear(date.getFullYear()); + var monthDaysCumulative = (leap ? MONTH_DAYS_LEAP_CUMULATIVE : MONTH_DAYS_REGULAR_CUMULATIVE); + var yday = monthDaysCumulative[date.getMonth()] + date.getDate() - 1; + + return yday; + }; + + function __localtime_js(time, tmPtr) { + time = bigintToI53Checked(time); + + + var date = new Date(time*1000); + if (isNaN(date.getTime())) { + return 1; + } + HEAP32[((tmPtr)>>2)] = date.getSeconds(); + HEAP32[(((tmPtr)+(4))>>2)] = date.getMinutes(); + HEAP32[(((tmPtr)+(8))>>2)] = date.getHours(); + HEAP32[(((tmPtr)+(12))>>2)] = date.getDate(); + HEAP32[(((tmPtr)+(16))>>2)] = date.getMonth(); + HEAP32[(((tmPtr)+(20))>>2)] = date.getFullYear()-1900; + HEAP32[(((tmPtr)+(24))>>2)] = date.getDay(); + + var yday = ydayFromDate(date)|0; + HEAP32[(((tmPtr)+(28))>>2)] = yday; + HEAP32[(((tmPtr)+(36))>>2)] = -(date.getTimezoneOffset() * 60); + + + var start = new Date(date.getFullYear(), 0, 1); + var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset(); + var winterOffset = start.getTimezoneOffset(); + var dst = (summerOffset != winterOffset && date.getTimezoneOffset() == Math.min(winterOffset, summerOffset))|0; + HEAP32[(((tmPtr)+(32))>>2)] = dst; + return 0; + ; + } + + + + + + + function __mmap_js(len, prot, flags, fd, offset, allocated, addr) { + offset = bigintToI53Checked(offset); + + + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + var res = FS.mmap(stream, len, offset, prot, flags); + var ptr = res.ptr; + HEAP32[((allocated)>>2)] = res.allocated; + HEAPU32[((addr)>>2)] = ptr; + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + ; + } + + + function __munmap_js(addr, len, prot, flags, fd, offset) { + offset = bigintToI53Checked(offset); + + + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + if (prot & 2) { + SYSCALLS.doMsync(addr, stream, len, flags, offset); + } + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + ; + } + + var __tzset_js = (timezone, daylight, std_name, dst_name) => { + + var currentYear = new Date().getFullYear(); + var winter = new Date(currentYear, 0, 1); + var summer = new Date(currentYear, 6, 1); + var winterOffset = winter.getTimezoneOffset(); + var summerOffset = summer.getTimezoneOffset(); + + + + + + + + var stdTimezoneOffset = Math.max(winterOffset, summerOffset); + + + + + + + HEAPU32[((timezone)>>2)] = stdTimezoneOffset * 60; + + HEAP32[((daylight)>>2)] = Number(winterOffset != summerOffset); + + var extractZone = (timezoneOffset) => { + + + var sign = timezoneOffset >= 0 ? "-" : "+"; + + var absOffset = Math.abs(timezoneOffset) + var hours = String(Math.floor(absOffset / 60)).padStart(2, "0"); + var minutes = String(absOffset % 60).padStart(2, "0"); + + return `UTC${sign}${hours}${minutes}`; + } + + var winterName = extractZone(winterOffset); + var summerName = extractZone(summerOffset); + if (summerOffset < winterOffset) { + + stringToUTF8(winterName, std_name, 17); + stringToUTF8(summerName, dst_name, 17); + } else { + stringToUTF8(winterName, dst_name, 17); + stringToUTF8(summerName, std_name, 17); + } + }; + + var _emscripten_get_now = () => performance.now(); + + var _emscripten_date_now = () => Date.now(); + + var nowIsMonotonic = 1; + + var checkWasiClock = (clock_id) => clock_id >= 0 && clock_id <= 3; + + function _clock_time_get(clk_id, ignored_precision, ptime) { + ignored_precision = bigintToI53Checked(ignored_precision); + + + if (!checkWasiClock(clk_id)) { + return 28; + } + var now; + + if (clk_id === 0) { + now = _emscripten_date_now(); + } else if (nowIsMonotonic) { + now = _emscripten_get_now(); + } else { + return 52; + } + + var nsec = Math.round(now * 1000 * 1000); + HEAP64[((ptime)>>3)] = BigInt(nsec); + return 0; + ; + } + + + var getHeapMax = () => + + + + + 2147483648; + var _emscripten_get_heap_max = () => getHeapMax(); + + + + + var growMemory = (size) => { + var oldHeapSize = wasmMemory.buffer.byteLength; + var pages = ((size - oldHeapSize + 65535) / 65536) | 0; + try { + + wasmMemory.grow(pages); + updateMemoryViews(); + return 1 ; + } catch(e) { + } + + + }; + var _emscripten_resize_heap = (requestedSize) => { + var oldSize = HEAPU8.length; + + requestedSize >>>= 0; + + + + + + + + + + + + + + + + + + + + + + + var maxHeapSize = getHeapMax(); + if (requestedSize > maxHeapSize) { + return false; + } + + + + + for (var cutDown = 1; cutDown <= 4; cutDown *= 2) { + var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown); + + overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296 ); + + var newSize = Math.min(maxHeapSize, alignMemory(Math.max(requestedSize, overGrownHeapSize), 65536)); + + var replacement = growMemory(newSize); + if (replacement) { + + return true; + } + } + return false; + }; + + var ENV = { + }; + + var getExecutableName = () => thisProgram; + var getEnvStrings = () => { + if (!getEnvStrings.strings) { + + var lang = (globalThis.navigator?.language ?? 'C').replace('-', '_') + '.UTF-8'; + var env = { + 'USER': 'web_user', + 'LOGNAME': 'web_user', + 'PATH': '/', + 'PWD': '/', + 'HOME': '/home/web_user', + 'LANG': lang, + '_': getExecutableName() + }; + + for (var x in ENV) { + + + + if (ENV[x] === undefined) delete env[x]; + else env[x] = ENV[x]; + } + var strings = []; + for (var x in env) { + strings.push(`${x}=${env[x]}`); + } + getEnvStrings.strings = strings; + } + return getEnvStrings.strings; + }; + + var _environ_get = (__environ, environ_buf) => { + var bufSize = 0; + var envp = 0; + for (var string of getEnvStrings()) { + var ptr = environ_buf + bufSize; + HEAPU32[(((__environ)+(envp))>>2)] = ptr; + bufSize += stringToUTF8(string, ptr, Infinity) + 1; + envp += 4; + } + return 0; + }; + + + var _environ_sizes_get = (penviron_count, penviron_buf_size) => { + var strings = getEnvStrings(); + HEAPU32[((penviron_count)>>2)] = strings.length; + var bufSize = 0; + for (var string of strings) { + bufSize += lengthBytesUTF8(string) + 1; + } + HEAPU32[((penviron_buf_size)>>2)] = bufSize; + return 0; + }; + + + var runtimeKeepaliveCounter = 0; + var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0; + var _proc_exit = (code) => { + EXITSTATUS = code; + if (!keepRuntimeAlive()) { + Module['onExit']?.(code); + ABORT = true; + } + quit_(code, new ExitStatus(code)); + }; + + var exitJS = (status, implicit) => { + EXITSTATUS = status; + + _proc_exit(status); + }; + var _exit = exitJS; + + function _fd_close(fd) { + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + FS.close(stream); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + } + + + function _fd_fdstat_get(fd, pbuf) { + try { + + var rightsBase = 0; + var rightsInheriting = 0; + var flags = 0; + { + var stream = SYSCALLS.getStreamFromFD(fd); + + + var type = stream.tty ? 2 : + FS.isDir(stream.mode) ? 3 : + FS.isLink(stream.mode) ? 7 : + 4; + } + HEAP8[pbuf] = type; + HEAP16[(((pbuf)+(2))>>1)] = flags; + HEAP64[(((pbuf)+(8))>>3)] = BigInt(rightsBase); + HEAP64[(((pbuf)+(16))>>3)] = BigInt(rightsInheriting); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + } + + + + var doReadv = (stream, iov, iovcnt, offset) => { + var ret = 0; + for (var i = 0; i < iovcnt; i++) { + var ptr = HEAPU32[((iov)>>2)]; + var len = HEAPU32[(((iov)+(4))>>2)]; + iov += 8; + try { + var curr = FS.read(stream, HEAP8, ptr, len, offset); + } catch (e) { + + + + if (ret > 0 && e instanceof FS.ErrnoError && + (e.errno == 6 || e.errno == 6)) { + break; + } + throw e; + } + if (curr < 0) return -1; + ret += curr; + if (curr < len) break; + if (typeof offset != 'undefined') { + offset += curr; + } + } + return ret; + }; + + function _fd_read(fd, iov, iovcnt, pnum) { + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + var num = doReadv(stream, iov, iovcnt); + HEAPU32[((pnum)>>2)] = num; + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + } + + + + function _fd_seek(fd, offset, whence, newOffset) { + offset = bigintToI53Checked(offset); + + + try { + + if (isNaN(offset)) return 22; + var stream = SYSCALLS.getStreamFromFD(fd); + FS.llseek(stream, offset, whence); + HEAP64[((newOffset)>>3)] = BigInt(stream.position); + if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null; + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + ; + } + + function _fd_sync(fd) { + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + var rtn = stream.stream_ops?.fsync?.(stream); + return rtn; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + } + + + + var doWritev = (stream, iov, iovcnt, offset) => { + + + + + if (iovcnt == 1) { + + return FS.write(stream, HEAP8, HEAPU32[((iov)>>2)], HEAPU32[(((iov)+(4))>>2)], offset); + } + var total = 0; + for (var i = 0, p = iov; i < iovcnt; i++, p += 8) { + total += HEAPU32[(((p)+(4))>>2)]; + } + var view = new Uint8Array(total); + var voff = 0; + for (var i = 0; i < iovcnt; i++, iov += 8) { + var ptr = HEAPU32[((iov)>>2)]; + var len = HEAPU32[(((iov)+(4))>>2)]; + view.set(HEAPU8.subarray(ptr, ptr + len), voff); + voff += len; + } + return FS.write(stream, view, 0, total, offset); + }; + + function _fd_write(fd, iov, iovcnt, pnum) { + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + var num = doWritev(stream, iov, iovcnt); + HEAPU32[((pnum)>>2)] = num; + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + } + + + + FS.createPreloadedFile = FS_createPreloadedFile; + FS.preloadFile = FS_preloadFile; + FS.staticInit();; + + + + + + +{ + + + initMemory(); + + + if (Module['noExitRuntime']) noExitRuntime = Module['noExitRuntime']; + +if (Module['print']) out = Module['print']; +if (Module['printErr']) err = Module['printErr']; + + + if (Module['arguments']) programArgs = Module['arguments']; + if (Module['thisProgram']) thisProgram = Module['thisProgram']; + + var preInit = Module['preInit']; + if (preInit) { + if (typeof preInit == 'function') Module['preInit'] = preInit = [preInit]; + + + while (preInit.length > 0) { + preInit.shift()(); + } + } +} + + + Module['wasmMemory'] = wasmMemory; + + + + + + +function wasm_crypto_getrandom(buf,n) { if (typeof crypto === 'undefined' || !crypto.getRandomValues) return -1; try { var view = new Uint8Array(HEAPU8.buffer, buf, n); var chunk = 65536; for (var i = 0; i < n; i += chunk) { crypto.getRandomValues(view.subarray(i, Math.min(i + chunk, n))); } return 0; } catch (e) { return -1; } } + + +var _sqlite3_status64, + _sqlite3_status, + _sqlite3_db_status64, + _sqlite3_msize, + _sqlite3_db_status, + _sqlite3_vfs_find, + _sqlite3_initialize, + _sqlite3_vfs_register, + _sqlite3_vfs_unregister, + _sqlite3_malloc, + _sqlite3_malloc64, + _sqlite3_free, + _sqlite3_realloc, + _sqlite3_realloc64, + _sqlite3_value_text, + _sqlite3_randomness, + _sqlite3_stricmp, + _sqlite3_strnicmp, + _sqlite3_uri_parameter, + _sqlite3_uri_boolean, + _sqlite3_serialize, + _sqlite3_prepare_v2, + _sqlite3_step, + _sqlite3_column_int64, + _sqlite3_reset, + _sqlite3_exec, + _sqlite3_column_int, + _sqlite3_finalize, + _sqlite3_file_control, + _sqlite3_column_name, + _sqlite3_column_text, + _sqlite3_column_type, + _sqlite3_errmsg, + _sqlite3_deserialize, + _sqlite3_backup_init, + _sqlite3_backup_step, + _sqlite3_backup_finish, + _sqlite3_backup_remaining, + _sqlite3_backup_pagecount, + _sqlite3_clear_bindings, + _sqlite3_value_blob, + _sqlite3_value_bytes, + _sqlite3_value_double, + _sqlite3_value_int, + _sqlite3_value_int64, + _sqlite3_value_subtype, + _sqlite3_value_pointer, + _sqlite3_value_type, + _sqlite3_value_nochange, + _sqlite3_value_frombind, + _sqlite3_value_dup, + _sqlite3_value_free, + _sqlite3_result_blob, + _sqlite3_result_error_toobig, + _sqlite3_result_error_nomem, + _sqlite3_result_double, + _sqlite3_result_error, + _sqlite3_result_int, + _sqlite3_result_int64, + _sqlite3_result_null, + _sqlite3_result_pointer, + _sqlite3_result_subtype, + _sqlite3_result_text, + _sqlite3_result_zeroblob, + _sqlite3_result_zeroblob64, + _sqlite3_result_error_code, + _sqlite3_user_data, + _sqlite3_context_db_handle, + _sqlite3_vtab_nochange, + _sqlite3_vtab_in_first, + _sqlite3_vtab_in_next, + _sqlite3_aggregate_context, + _sqlite3_get_auxdata, + _sqlite3_set_auxdata, + _sqlite3_column_count, + _sqlite3_data_count, + _sqlite3_column_blob, + _sqlite3_column_bytes, + _sqlite3_column_double, + _sqlite3_column_value, + _sqlite3_column_decltype, + _sqlite3_column_database_name, + _sqlite3_column_table_name, + _sqlite3_column_origin_name, + _sqlite3_bind_blob, + _sqlite3_bind_double, + _sqlite3_bind_int, + _sqlite3_bind_int64, + _sqlite3_bind_null, + _sqlite3_bind_pointer, + _sqlite3_bind_text, + _sqlite3_bind_zeroblob, + _sqlite3_bind_parameter_count, + _sqlite3_bind_parameter_name, + _sqlite3_bind_parameter_index, + _sqlite3_db_handle, + _sqlite3_stmt_readonly, + _sqlite3_stmt_isexplain, + _sqlite3_stmt_explain, + _sqlite3_stmt_busy, + _sqlite3_next_stmt, + _sqlite3_stmt_status, + _sqlite3_sql, + _sqlite3_expanded_sql, + _sqlite3_preupdate_old, + _sqlite3_preupdate_count, + _sqlite3_preupdate_depth, + _sqlite3_preupdate_blobwrite, + _sqlite3_preupdate_new, + _sqlite3_value_numeric_type, + _sqlite3_set_authorizer, + _sqlite3_strglob, + _sqlite3_strlike, + _sqlite3_auto_extension, + _sqlite3_cancel_auto_extension, + _sqlite3_reset_auto_extension, + _sqlite3_prepare_v3, + _sqlite3_create_module, + _sqlite3_create_module_v2, + _sqlite3_drop_modules, + _sqlite3_declare_vtab, + _sqlite3_vtab_on_conflict, + _sqlite3_vtab_collation, + _sqlite3_vtab_in, + _sqlite3_vtab_rhs_value, + _sqlite3_vtab_distinct, + _sqlite3_keyword_name, + _sqlite3_keyword_count, + _sqlite3_keyword_check, + _sqlite3_complete, + _sqlite3_libversion, + _sqlite3_libversion_number, + _sqlite3mc_vfs_create, + _sqlite3_shutdown, + _sqlite3mc_vfs_shutdown, + _sqlite3_last_insert_rowid, + _sqlite3_set_last_insert_rowid, + _sqlite3_changes64, + _sqlite3_changes, + _sqlite3_total_changes64, + _sqlite3_total_changes, + _sqlite3_txn_state, + _sqlite3_close_v2, + _sqlite3_busy_handler, + _sqlite3_progress_handler, + _sqlite3_busy_timeout, + _sqlite3_interrupt, + _sqlite3_is_interrupted, + _sqlite3_create_function, + _sqlite3_create_function_v2, + _sqlite3_create_window_function, + _sqlite3_overload_function, + _sqlite3_trace_v2, + _sqlite3_commit_hook, + _sqlite3_update_hook, + _sqlite3_rollback_hook, + _sqlite3_preupdate_hook, + _sqlite3_set_errmsg, + _sqlite3_error_offset, + _sqlite3_errcode, + _sqlite3_extended_errcode, + _sqlite3_errstr, + _sqlite3_limit, + _sqlite3_open, + _sqlite3_open_v2, + _sqlite3_create_collation, + _sqlite3_create_collation_v2, + _sqlite3_collation_needed, + _sqlite3_get_autocommit, + _sqlite3_table_column_metadata, + _sqlite3_extended_result_codes, + _sqlite3_uri_key, + _sqlite3_uri_int64, + _sqlite3_db_name, + _sqlite3_db_filename, + _sqlite3_db_readonly, + _sqlite3_compileoption_used, + _sqlite3_compileoption_get, + _sqlite3session_diff, + _sqlite3session_attach, + _sqlite3session_create, + _sqlite3session_delete, + _sqlite3session_table_filter, + _sqlite3session_changeset, + _sqlite3session_changeset_strm, + _sqlite3session_patchset_strm, + _sqlite3session_patchset, + _sqlite3session_enable, + _sqlite3session_indirect, + _sqlite3session_isempty, + _sqlite3session_memory_used, + _sqlite3session_object_config, + _sqlite3session_changeset_size, + _sqlite3changeset_start, + _sqlite3changeset_start_v2, + _sqlite3changeset_start_strm, + _sqlite3changeset_start_v2_strm, + _sqlite3changeset_next, + _sqlite3changeset_op, + _sqlite3changeset_pk, + _sqlite3changeset_old, + _sqlite3changeset_new, + _sqlite3changeset_conflict, + _sqlite3changeset_fk_conflicts, + _sqlite3changeset_finalize, + _sqlite3changeset_invert, + _sqlite3changeset_invert_strm, + _sqlite3changeset_apply_v2, + _sqlite3changeset_apply_v3, + _sqlite3changeset_apply, + _sqlite3changeset_apply_v3_strm, + _sqlite3changeset_apply_v2_strm, + _sqlite3changeset_apply_strm, + _sqlite3changegroup_new, + _sqlite3changegroup_add, + _sqlite3changegroup_output, + _sqlite3changegroup_add_strm, + _sqlite3changegroup_output_strm, + _sqlite3changegroup_delete, + _sqlite3changeset_concat, + _sqlite3changeset_concat_strm, + _sqlite3session_config, + _sqlite3_sourceid, + _sqlite3mc_version, + _sqlite3mc_config, + _sqlite3mc_cipher_count, + _sqlite3mc_cipher_index, + _sqlite3mc_cipher_name, + _sqlite3mc_cipher_name_copy, + _sqlite3mc_config_cipher, + _sqlite3mc_codec_data, + _sqlite3_activate_see, + _sqlite3_key, + _sqlite3_key_v2, + _sqlite3_rekey_v2, + _sqlite3_rekey, + _sqlite3mc_vfs_destroy, + _sqlite3__wasm_pstack_ptr, + _sqlite3__wasm_pstack_restore, + _sqlite3__wasm_pstack_alloc, + _sqlite3__wasm_pstack_remaining, + _sqlite3__wasm_pstack_quota, + _sqlite3__wasm_test_struct, + _sqlite3__wasm_enum_json, + _sqlite3__wasm_vfs_unlink, + _sqlite3__wasm_db_vfs, + _sqlite3__wasm_db_reset, + _sqlite3__wasm_db_export_chunked, + _sqlite3__wasm_db_serialize, + _sqlite3__wasm_vfs_create_file, + _sqlite3__wasm_posix_create_file, + _sqlite3__wasm_kvvfsMakeKey, + _sqlite3__wasm_kvvfs_methods, + _sqlite3__wasm_vtab_config, + _sqlite3__wasm_db_config_ip, + _sqlite3__wasm_db_config_pii, + _sqlite3__wasm_db_config_s, + _sqlite3__wasm_config_i, + _sqlite3__wasm_config_ii, + _sqlite3__wasm_config_j, + _sqlite3__wasm_qfmt_token, + _sqlite3__wasm_kvvfs_decode, + _sqlite3__wasm_kvvfs_encode, + _sqlite3__wasm_init_wasmfs, + _sqlite3__wasm_test_intptr, + _sqlite3__wasm_test_voidptr, + _sqlite3__wasm_test_int64_max, + _sqlite3__wasm_test_int64_min, + _sqlite3__wasm_test_int64_times2, + _sqlite3__wasm_test_int64_minmax, + _sqlite3__wasm_test_int64ptr, + _sqlite3__wasm_test_stack_overflow, + _sqlite3__wasm_test_str_hello, + _sqlite3__wasm_SQLTester_strglob, + _malloc, + _free, + _realloc, + _emscripten_builtin_memalign, + __emscripten_stack_restore, + __emscripten_stack_alloc, + _emscripten_stack_get_current, + __indirect_function_table; + + +function assignWasmExports(wasmExports) { + _sqlite3_status64 = Module['_sqlite3_status64'] = wasmExports['sqlite3_status64']; + _sqlite3_status = Module['_sqlite3_status'] = wasmExports['sqlite3_status']; + _sqlite3_db_status64 = Module['_sqlite3_db_status64'] = wasmExports['sqlite3_db_status64']; + _sqlite3_msize = Module['_sqlite3_msize'] = wasmExports['sqlite3_msize']; + _sqlite3_db_status = Module['_sqlite3_db_status'] = wasmExports['sqlite3_db_status']; + _sqlite3_vfs_find = Module['_sqlite3_vfs_find'] = wasmExports['sqlite3_vfs_find']; + _sqlite3_initialize = Module['_sqlite3_initialize'] = wasmExports['sqlite3_initialize']; + _sqlite3_vfs_register = Module['_sqlite3_vfs_register'] = wasmExports['sqlite3_vfs_register']; + _sqlite3_vfs_unregister = Module['_sqlite3_vfs_unregister'] = wasmExports['sqlite3_vfs_unregister']; + _sqlite3_malloc = Module['_sqlite3_malloc'] = wasmExports['sqlite3_malloc']; + _sqlite3_malloc64 = Module['_sqlite3_malloc64'] = wasmExports['sqlite3_malloc64']; + _sqlite3_free = Module['_sqlite3_free'] = wasmExports['sqlite3_free']; + _sqlite3_realloc = Module['_sqlite3_realloc'] = wasmExports['sqlite3_realloc']; + _sqlite3_realloc64 = Module['_sqlite3_realloc64'] = wasmExports['sqlite3_realloc64']; + _sqlite3_value_text = Module['_sqlite3_value_text'] = wasmExports['sqlite3_value_text']; + _sqlite3_randomness = Module['_sqlite3_randomness'] = wasmExports['sqlite3_randomness']; + _sqlite3_stricmp = Module['_sqlite3_stricmp'] = wasmExports['sqlite3_stricmp']; + _sqlite3_strnicmp = Module['_sqlite3_strnicmp'] = wasmExports['sqlite3_strnicmp']; + _sqlite3_uri_parameter = Module['_sqlite3_uri_parameter'] = wasmExports['sqlite3_uri_parameter']; + _sqlite3_uri_boolean = Module['_sqlite3_uri_boolean'] = wasmExports['sqlite3_uri_boolean']; + _sqlite3_serialize = Module['_sqlite3_serialize'] = wasmExports['sqlite3_serialize']; + _sqlite3_prepare_v2 = Module['_sqlite3_prepare_v2'] = wasmExports['sqlite3_prepare_v2']; + _sqlite3_step = Module['_sqlite3_step'] = wasmExports['sqlite3_step']; + _sqlite3_column_int64 = Module['_sqlite3_column_int64'] = wasmExports['sqlite3_column_int64']; + _sqlite3_reset = Module['_sqlite3_reset'] = wasmExports['sqlite3_reset']; + _sqlite3_exec = Module['_sqlite3_exec'] = wasmExports['sqlite3_exec']; + _sqlite3_column_int = Module['_sqlite3_column_int'] = wasmExports['sqlite3_column_int']; + _sqlite3_finalize = Module['_sqlite3_finalize'] = wasmExports['sqlite3_finalize']; + _sqlite3_file_control = Module['_sqlite3_file_control'] = wasmExports['sqlite3_file_control']; + _sqlite3_column_name = Module['_sqlite3_column_name'] = wasmExports['sqlite3_column_name']; + _sqlite3_column_text = Module['_sqlite3_column_text'] = wasmExports['sqlite3_column_text']; + _sqlite3_column_type = Module['_sqlite3_column_type'] = wasmExports['sqlite3_column_type']; + _sqlite3_errmsg = Module['_sqlite3_errmsg'] = wasmExports['sqlite3_errmsg']; + _sqlite3_deserialize = Module['_sqlite3_deserialize'] = wasmExports['sqlite3_deserialize']; + _sqlite3_backup_init = Module['_sqlite3_backup_init'] = wasmExports['sqlite3_backup_init']; + _sqlite3_backup_step = Module['_sqlite3_backup_step'] = wasmExports['sqlite3_backup_step']; + _sqlite3_backup_finish = Module['_sqlite3_backup_finish'] = wasmExports['sqlite3_backup_finish']; + _sqlite3_backup_remaining = Module['_sqlite3_backup_remaining'] = wasmExports['sqlite3_backup_remaining']; + _sqlite3_backup_pagecount = Module['_sqlite3_backup_pagecount'] = wasmExports['sqlite3_backup_pagecount']; + _sqlite3_clear_bindings = Module['_sqlite3_clear_bindings'] = wasmExports['sqlite3_clear_bindings']; + _sqlite3_value_blob = Module['_sqlite3_value_blob'] = wasmExports['sqlite3_value_blob']; + _sqlite3_value_bytes = Module['_sqlite3_value_bytes'] = wasmExports['sqlite3_value_bytes']; + _sqlite3_value_double = Module['_sqlite3_value_double'] = wasmExports['sqlite3_value_double']; + _sqlite3_value_int = Module['_sqlite3_value_int'] = wasmExports['sqlite3_value_int']; + _sqlite3_value_int64 = Module['_sqlite3_value_int64'] = wasmExports['sqlite3_value_int64']; + _sqlite3_value_subtype = Module['_sqlite3_value_subtype'] = wasmExports['sqlite3_value_subtype']; + _sqlite3_value_pointer = Module['_sqlite3_value_pointer'] = wasmExports['sqlite3_value_pointer']; + _sqlite3_value_type = Module['_sqlite3_value_type'] = wasmExports['sqlite3_value_type']; + _sqlite3_value_nochange = Module['_sqlite3_value_nochange'] = wasmExports['sqlite3_value_nochange']; + _sqlite3_value_frombind = Module['_sqlite3_value_frombind'] = wasmExports['sqlite3_value_frombind']; + _sqlite3_value_dup = Module['_sqlite3_value_dup'] = wasmExports['sqlite3_value_dup']; + _sqlite3_value_free = Module['_sqlite3_value_free'] = wasmExports['sqlite3_value_free']; + _sqlite3_result_blob = Module['_sqlite3_result_blob'] = wasmExports['sqlite3_result_blob']; + _sqlite3_result_error_toobig = Module['_sqlite3_result_error_toobig'] = wasmExports['sqlite3_result_error_toobig']; + _sqlite3_result_error_nomem = Module['_sqlite3_result_error_nomem'] = wasmExports['sqlite3_result_error_nomem']; + _sqlite3_result_double = Module['_sqlite3_result_double'] = wasmExports['sqlite3_result_double']; + _sqlite3_result_error = Module['_sqlite3_result_error'] = wasmExports['sqlite3_result_error']; + _sqlite3_result_int = Module['_sqlite3_result_int'] = wasmExports['sqlite3_result_int']; + _sqlite3_result_int64 = Module['_sqlite3_result_int64'] = wasmExports['sqlite3_result_int64']; + _sqlite3_result_null = Module['_sqlite3_result_null'] = wasmExports['sqlite3_result_null']; + _sqlite3_result_pointer = Module['_sqlite3_result_pointer'] = wasmExports['sqlite3_result_pointer']; + _sqlite3_result_subtype = Module['_sqlite3_result_subtype'] = wasmExports['sqlite3_result_subtype']; + _sqlite3_result_text = Module['_sqlite3_result_text'] = wasmExports['sqlite3_result_text']; + _sqlite3_result_zeroblob = Module['_sqlite3_result_zeroblob'] = wasmExports['sqlite3_result_zeroblob']; + _sqlite3_result_zeroblob64 = Module['_sqlite3_result_zeroblob64'] = wasmExports['sqlite3_result_zeroblob64']; + _sqlite3_result_error_code = Module['_sqlite3_result_error_code'] = wasmExports['sqlite3_result_error_code']; + _sqlite3_user_data = Module['_sqlite3_user_data'] = wasmExports['sqlite3_user_data']; + _sqlite3_context_db_handle = Module['_sqlite3_context_db_handle'] = wasmExports['sqlite3_context_db_handle']; + _sqlite3_vtab_nochange = Module['_sqlite3_vtab_nochange'] = wasmExports['sqlite3_vtab_nochange']; + _sqlite3_vtab_in_first = Module['_sqlite3_vtab_in_first'] = wasmExports['sqlite3_vtab_in_first']; + _sqlite3_vtab_in_next = Module['_sqlite3_vtab_in_next'] = wasmExports['sqlite3_vtab_in_next']; + _sqlite3_aggregate_context = Module['_sqlite3_aggregate_context'] = wasmExports['sqlite3_aggregate_context']; + _sqlite3_get_auxdata = Module['_sqlite3_get_auxdata'] = wasmExports['sqlite3_get_auxdata']; + _sqlite3_set_auxdata = Module['_sqlite3_set_auxdata'] = wasmExports['sqlite3_set_auxdata']; + _sqlite3_column_count = Module['_sqlite3_column_count'] = wasmExports['sqlite3_column_count']; + _sqlite3_data_count = Module['_sqlite3_data_count'] = wasmExports['sqlite3_data_count']; + _sqlite3_column_blob = Module['_sqlite3_column_blob'] = wasmExports['sqlite3_column_blob']; + _sqlite3_column_bytes = Module['_sqlite3_column_bytes'] = wasmExports['sqlite3_column_bytes']; + _sqlite3_column_double = Module['_sqlite3_column_double'] = wasmExports['sqlite3_column_double']; + _sqlite3_column_value = Module['_sqlite3_column_value'] = wasmExports['sqlite3_column_value']; + _sqlite3_column_decltype = Module['_sqlite3_column_decltype'] = wasmExports['sqlite3_column_decltype']; + _sqlite3_column_database_name = Module['_sqlite3_column_database_name'] = wasmExports['sqlite3_column_database_name']; + _sqlite3_column_table_name = Module['_sqlite3_column_table_name'] = wasmExports['sqlite3_column_table_name']; + _sqlite3_column_origin_name = Module['_sqlite3_column_origin_name'] = wasmExports['sqlite3_column_origin_name']; + _sqlite3_bind_blob = Module['_sqlite3_bind_blob'] = wasmExports['sqlite3_bind_blob']; + _sqlite3_bind_double = Module['_sqlite3_bind_double'] = wasmExports['sqlite3_bind_double']; + _sqlite3_bind_int = Module['_sqlite3_bind_int'] = wasmExports['sqlite3_bind_int']; + _sqlite3_bind_int64 = Module['_sqlite3_bind_int64'] = wasmExports['sqlite3_bind_int64']; + _sqlite3_bind_null = Module['_sqlite3_bind_null'] = wasmExports['sqlite3_bind_null']; + _sqlite3_bind_pointer = Module['_sqlite3_bind_pointer'] = wasmExports['sqlite3_bind_pointer']; + _sqlite3_bind_text = Module['_sqlite3_bind_text'] = wasmExports['sqlite3_bind_text']; + _sqlite3_bind_zeroblob = Module['_sqlite3_bind_zeroblob'] = wasmExports['sqlite3_bind_zeroblob']; + _sqlite3_bind_parameter_count = Module['_sqlite3_bind_parameter_count'] = wasmExports['sqlite3_bind_parameter_count']; + _sqlite3_bind_parameter_name = Module['_sqlite3_bind_parameter_name'] = wasmExports['sqlite3_bind_parameter_name']; + _sqlite3_bind_parameter_index = Module['_sqlite3_bind_parameter_index'] = wasmExports['sqlite3_bind_parameter_index']; + _sqlite3_db_handle = Module['_sqlite3_db_handle'] = wasmExports['sqlite3_db_handle']; + _sqlite3_stmt_readonly = Module['_sqlite3_stmt_readonly'] = wasmExports['sqlite3_stmt_readonly']; + _sqlite3_stmt_isexplain = Module['_sqlite3_stmt_isexplain'] = wasmExports['sqlite3_stmt_isexplain']; + _sqlite3_stmt_explain = Module['_sqlite3_stmt_explain'] = wasmExports['sqlite3_stmt_explain']; + _sqlite3_stmt_busy = Module['_sqlite3_stmt_busy'] = wasmExports['sqlite3_stmt_busy']; + _sqlite3_next_stmt = Module['_sqlite3_next_stmt'] = wasmExports['sqlite3_next_stmt']; + _sqlite3_stmt_status = Module['_sqlite3_stmt_status'] = wasmExports['sqlite3_stmt_status']; + _sqlite3_sql = Module['_sqlite3_sql'] = wasmExports['sqlite3_sql']; + _sqlite3_expanded_sql = Module['_sqlite3_expanded_sql'] = wasmExports['sqlite3_expanded_sql']; + _sqlite3_preupdate_old = Module['_sqlite3_preupdate_old'] = wasmExports['sqlite3_preupdate_old']; + _sqlite3_preupdate_count = Module['_sqlite3_preupdate_count'] = wasmExports['sqlite3_preupdate_count']; + _sqlite3_preupdate_depth = Module['_sqlite3_preupdate_depth'] = wasmExports['sqlite3_preupdate_depth']; + _sqlite3_preupdate_blobwrite = Module['_sqlite3_preupdate_blobwrite'] = wasmExports['sqlite3_preupdate_blobwrite']; + _sqlite3_preupdate_new = Module['_sqlite3_preupdate_new'] = wasmExports['sqlite3_preupdate_new']; + _sqlite3_value_numeric_type = Module['_sqlite3_value_numeric_type'] = wasmExports['sqlite3_value_numeric_type']; + _sqlite3_set_authorizer = Module['_sqlite3_set_authorizer'] = wasmExports['sqlite3_set_authorizer']; + _sqlite3_strglob = Module['_sqlite3_strglob'] = wasmExports['sqlite3_strglob']; + _sqlite3_strlike = Module['_sqlite3_strlike'] = wasmExports['sqlite3_strlike']; + _sqlite3_auto_extension = Module['_sqlite3_auto_extension'] = wasmExports['sqlite3_auto_extension']; + _sqlite3_cancel_auto_extension = Module['_sqlite3_cancel_auto_extension'] = wasmExports['sqlite3_cancel_auto_extension']; + _sqlite3_reset_auto_extension = Module['_sqlite3_reset_auto_extension'] = wasmExports['sqlite3_reset_auto_extension']; + _sqlite3_prepare_v3 = Module['_sqlite3_prepare_v3'] = wasmExports['sqlite3_prepare_v3']; + _sqlite3_create_module = Module['_sqlite3_create_module'] = wasmExports['sqlite3_create_module']; + _sqlite3_create_module_v2 = Module['_sqlite3_create_module_v2'] = wasmExports['sqlite3_create_module_v2']; + _sqlite3_drop_modules = Module['_sqlite3_drop_modules'] = wasmExports['sqlite3_drop_modules']; + _sqlite3_declare_vtab = Module['_sqlite3_declare_vtab'] = wasmExports['sqlite3_declare_vtab']; + _sqlite3_vtab_on_conflict = Module['_sqlite3_vtab_on_conflict'] = wasmExports['sqlite3_vtab_on_conflict']; + _sqlite3_vtab_collation = Module['_sqlite3_vtab_collation'] = wasmExports['sqlite3_vtab_collation']; + _sqlite3_vtab_in = Module['_sqlite3_vtab_in'] = wasmExports['sqlite3_vtab_in']; + _sqlite3_vtab_rhs_value = Module['_sqlite3_vtab_rhs_value'] = wasmExports['sqlite3_vtab_rhs_value']; + _sqlite3_vtab_distinct = Module['_sqlite3_vtab_distinct'] = wasmExports['sqlite3_vtab_distinct']; + _sqlite3_keyword_name = Module['_sqlite3_keyword_name'] = wasmExports['sqlite3_keyword_name']; + _sqlite3_keyword_count = Module['_sqlite3_keyword_count'] = wasmExports['sqlite3_keyword_count']; + _sqlite3_keyword_check = Module['_sqlite3_keyword_check'] = wasmExports['sqlite3_keyword_check']; + _sqlite3_complete = Module['_sqlite3_complete'] = wasmExports['sqlite3_complete']; + _sqlite3_libversion = Module['_sqlite3_libversion'] = wasmExports['sqlite3_libversion']; + _sqlite3_libversion_number = Module['_sqlite3_libversion_number'] = wasmExports['sqlite3_libversion_number']; + _sqlite3mc_vfs_create = Module['_sqlite3mc_vfs_create'] = wasmExports['sqlite3mc_vfs_create']; + _sqlite3_shutdown = Module['_sqlite3_shutdown'] = wasmExports['sqlite3_shutdown']; + _sqlite3mc_vfs_shutdown = Module['_sqlite3mc_vfs_shutdown'] = wasmExports['sqlite3mc_vfs_shutdown']; + _sqlite3_last_insert_rowid = Module['_sqlite3_last_insert_rowid'] = wasmExports['sqlite3_last_insert_rowid']; + _sqlite3_set_last_insert_rowid = Module['_sqlite3_set_last_insert_rowid'] = wasmExports['sqlite3_set_last_insert_rowid']; + _sqlite3_changes64 = Module['_sqlite3_changes64'] = wasmExports['sqlite3_changes64']; + _sqlite3_changes = Module['_sqlite3_changes'] = wasmExports['sqlite3_changes']; + _sqlite3_total_changes64 = Module['_sqlite3_total_changes64'] = wasmExports['sqlite3_total_changes64']; + _sqlite3_total_changes = Module['_sqlite3_total_changes'] = wasmExports['sqlite3_total_changes']; + _sqlite3_txn_state = Module['_sqlite3_txn_state'] = wasmExports['sqlite3_txn_state']; + _sqlite3_close_v2 = Module['_sqlite3_close_v2'] = wasmExports['sqlite3_close_v2']; + _sqlite3_busy_handler = Module['_sqlite3_busy_handler'] = wasmExports['sqlite3_busy_handler']; + _sqlite3_progress_handler = Module['_sqlite3_progress_handler'] = wasmExports['sqlite3_progress_handler']; + _sqlite3_busy_timeout = Module['_sqlite3_busy_timeout'] = wasmExports['sqlite3_busy_timeout']; + _sqlite3_interrupt = Module['_sqlite3_interrupt'] = wasmExports['sqlite3_interrupt']; + _sqlite3_is_interrupted = Module['_sqlite3_is_interrupted'] = wasmExports['sqlite3_is_interrupted']; + _sqlite3_create_function = Module['_sqlite3_create_function'] = wasmExports['sqlite3_create_function']; + _sqlite3_create_function_v2 = Module['_sqlite3_create_function_v2'] = wasmExports['sqlite3_create_function_v2']; + _sqlite3_create_window_function = Module['_sqlite3_create_window_function'] = wasmExports['sqlite3_create_window_function']; + _sqlite3_overload_function = Module['_sqlite3_overload_function'] = wasmExports['sqlite3_overload_function']; + _sqlite3_trace_v2 = Module['_sqlite3_trace_v2'] = wasmExports['sqlite3_trace_v2']; + _sqlite3_commit_hook = Module['_sqlite3_commit_hook'] = wasmExports['sqlite3_commit_hook']; + _sqlite3_update_hook = Module['_sqlite3_update_hook'] = wasmExports['sqlite3_update_hook']; + _sqlite3_rollback_hook = Module['_sqlite3_rollback_hook'] = wasmExports['sqlite3_rollback_hook']; + _sqlite3_preupdate_hook = Module['_sqlite3_preupdate_hook'] = wasmExports['sqlite3_preupdate_hook']; + _sqlite3_set_errmsg = Module['_sqlite3_set_errmsg'] = wasmExports['sqlite3_set_errmsg']; + _sqlite3_error_offset = Module['_sqlite3_error_offset'] = wasmExports['sqlite3_error_offset']; + _sqlite3_errcode = Module['_sqlite3_errcode'] = wasmExports['sqlite3_errcode']; + _sqlite3_extended_errcode = Module['_sqlite3_extended_errcode'] = wasmExports['sqlite3_extended_errcode']; + _sqlite3_errstr = Module['_sqlite3_errstr'] = wasmExports['sqlite3_errstr']; + _sqlite3_limit = Module['_sqlite3_limit'] = wasmExports['sqlite3_limit']; + _sqlite3_open = Module['_sqlite3_open'] = wasmExports['sqlite3_open']; + _sqlite3_open_v2 = Module['_sqlite3_open_v2'] = wasmExports['sqlite3_open_v2']; + _sqlite3_create_collation = Module['_sqlite3_create_collation'] = wasmExports['sqlite3_create_collation']; + _sqlite3_create_collation_v2 = Module['_sqlite3_create_collation_v2'] = wasmExports['sqlite3_create_collation_v2']; + _sqlite3_collation_needed = Module['_sqlite3_collation_needed'] = wasmExports['sqlite3_collation_needed']; + _sqlite3_get_autocommit = Module['_sqlite3_get_autocommit'] = wasmExports['sqlite3_get_autocommit']; + _sqlite3_table_column_metadata = Module['_sqlite3_table_column_metadata'] = wasmExports['sqlite3_table_column_metadata']; + _sqlite3_extended_result_codes = Module['_sqlite3_extended_result_codes'] = wasmExports['sqlite3_extended_result_codes']; + _sqlite3_uri_key = Module['_sqlite3_uri_key'] = wasmExports['sqlite3_uri_key']; + _sqlite3_uri_int64 = Module['_sqlite3_uri_int64'] = wasmExports['sqlite3_uri_int64']; + _sqlite3_db_name = Module['_sqlite3_db_name'] = wasmExports['sqlite3_db_name']; + _sqlite3_db_filename = Module['_sqlite3_db_filename'] = wasmExports['sqlite3_db_filename']; + _sqlite3_db_readonly = Module['_sqlite3_db_readonly'] = wasmExports['sqlite3_db_readonly']; + _sqlite3_compileoption_used = Module['_sqlite3_compileoption_used'] = wasmExports['sqlite3_compileoption_used']; + _sqlite3_compileoption_get = Module['_sqlite3_compileoption_get'] = wasmExports['sqlite3_compileoption_get']; + _sqlite3session_diff = Module['_sqlite3session_diff'] = wasmExports['sqlite3session_diff']; + _sqlite3session_attach = Module['_sqlite3session_attach'] = wasmExports['sqlite3session_attach']; + _sqlite3session_create = Module['_sqlite3session_create'] = wasmExports['sqlite3session_create']; + _sqlite3session_delete = Module['_sqlite3session_delete'] = wasmExports['sqlite3session_delete']; + _sqlite3session_table_filter = Module['_sqlite3session_table_filter'] = wasmExports['sqlite3session_table_filter']; + _sqlite3session_changeset = Module['_sqlite3session_changeset'] = wasmExports['sqlite3session_changeset']; + _sqlite3session_changeset_strm = Module['_sqlite3session_changeset_strm'] = wasmExports['sqlite3session_changeset_strm']; + _sqlite3session_patchset_strm = Module['_sqlite3session_patchset_strm'] = wasmExports['sqlite3session_patchset_strm']; + _sqlite3session_patchset = Module['_sqlite3session_patchset'] = wasmExports['sqlite3session_patchset']; + _sqlite3session_enable = Module['_sqlite3session_enable'] = wasmExports['sqlite3session_enable']; + _sqlite3session_indirect = Module['_sqlite3session_indirect'] = wasmExports['sqlite3session_indirect']; + _sqlite3session_isempty = Module['_sqlite3session_isempty'] = wasmExports['sqlite3session_isempty']; + _sqlite3session_memory_used = Module['_sqlite3session_memory_used'] = wasmExports['sqlite3session_memory_used']; + _sqlite3session_object_config = Module['_sqlite3session_object_config'] = wasmExports['sqlite3session_object_config']; + _sqlite3session_changeset_size = Module['_sqlite3session_changeset_size'] = wasmExports['sqlite3session_changeset_size']; + _sqlite3changeset_start = Module['_sqlite3changeset_start'] = wasmExports['sqlite3changeset_start']; + _sqlite3changeset_start_v2 = Module['_sqlite3changeset_start_v2'] = wasmExports['sqlite3changeset_start_v2']; + _sqlite3changeset_start_strm = Module['_sqlite3changeset_start_strm'] = wasmExports['sqlite3changeset_start_strm']; + _sqlite3changeset_start_v2_strm = Module['_sqlite3changeset_start_v2_strm'] = wasmExports['sqlite3changeset_start_v2_strm']; + _sqlite3changeset_next = Module['_sqlite3changeset_next'] = wasmExports['sqlite3changeset_next']; + _sqlite3changeset_op = Module['_sqlite3changeset_op'] = wasmExports['sqlite3changeset_op']; + _sqlite3changeset_pk = Module['_sqlite3changeset_pk'] = wasmExports['sqlite3changeset_pk']; + _sqlite3changeset_old = Module['_sqlite3changeset_old'] = wasmExports['sqlite3changeset_old']; + _sqlite3changeset_new = Module['_sqlite3changeset_new'] = wasmExports['sqlite3changeset_new']; + _sqlite3changeset_conflict = Module['_sqlite3changeset_conflict'] = wasmExports['sqlite3changeset_conflict']; + _sqlite3changeset_fk_conflicts = Module['_sqlite3changeset_fk_conflicts'] = wasmExports['sqlite3changeset_fk_conflicts']; + _sqlite3changeset_finalize = Module['_sqlite3changeset_finalize'] = wasmExports['sqlite3changeset_finalize']; + _sqlite3changeset_invert = Module['_sqlite3changeset_invert'] = wasmExports['sqlite3changeset_invert']; + _sqlite3changeset_invert_strm = Module['_sqlite3changeset_invert_strm'] = wasmExports['sqlite3changeset_invert_strm']; + _sqlite3changeset_apply_v2 = Module['_sqlite3changeset_apply_v2'] = wasmExports['sqlite3changeset_apply_v2']; + _sqlite3changeset_apply_v3 = Module['_sqlite3changeset_apply_v3'] = wasmExports['sqlite3changeset_apply_v3']; + _sqlite3changeset_apply = Module['_sqlite3changeset_apply'] = wasmExports['sqlite3changeset_apply']; + _sqlite3changeset_apply_v3_strm = Module['_sqlite3changeset_apply_v3_strm'] = wasmExports['sqlite3changeset_apply_v3_strm']; + _sqlite3changeset_apply_v2_strm = Module['_sqlite3changeset_apply_v2_strm'] = wasmExports['sqlite3changeset_apply_v2_strm']; + _sqlite3changeset_apply_strm = Module['_sqlite3changeset_apply_strm'] = wasmExports['sqlite3changeset_apply_strm']; + _sqlite3changegroup_new = Module['_sqlite3changegroup_new'] = wasmExports['sqlite3changegroup_new']; + _sqlite3changegroup_add = Module['_sqlite3changegroup_add'] = wasmExports['sqlite3changegroup_add']; + _sqlite3changegroup_output = Module['_sqlite3changegroup_output'] = wasmExports['sqlite3changegroup_output']; + _sqlite3changegroup_add_strm = Module['_sqlite3changegroup_add_strm'] = wasmExports['sqlite3changegroup_add_strm']; + _sqlite3changegroup_output_strm = Module['_sqlite3changegroup_output_strm'] = wasmExports['sqlite3changegroup_output_strm']; + _sqlite3changegroup_delete = Module['_sqlite3changegroup_delete'] = wasmExports['sqlite3changegroup_delete']; + _sqlite3changeset_concat = Module['_sqlite3changeset_concat'] = wasmExports['sqlite3changeset_concat']; + _sqlite3changeset_concat_strm = Module['_sqlite3changeset_concat_strm'] = wasmExports['sqlite3changeset_concat_strm']; + _sqlite3session_config = Module['_sqlite3session_config'] = wasmExports['sqlite3session_config']; + _sqlite3_sourceid = Module['_sqlite3_sourceid'] = wasmExports['sqlite3_sourceid']; + _sqlite3mc_version = Module['_sqlite3mc_version'] = wasmExports['sqlite3mc_version']; + _sqlite3mc_config = Module['_sqlite3mc_config'] = wasmExports['sqlite3mc_config']; + _sqlite3mc_cipher_count = Module['_sqlite3mc_cipher_count'] = wasmExports['sqlite3mc_cipher_count']; + _sqlite3mc_cipher_index = Module['_sqlite3mc_cipher_index'] = wasmExports['sqlite3mc_cipher_index']; + _sqlite3mc_cipher_name = Module['_sqlite3mc_cipher_name'] = wasmExports['sqlite3mc_cipher_name']; + _sqlite3mc_cipher_name_copy = Module['_sqlite3mc_cipher_name_copy'] = wasmExports['sqlite3mc_cipher_name_copy']; + _sqlite3mc_config_cipher = Module['_sqlite3mc_config_cipher'] = wasmExports['sqlite3mc_config_cipher']; + _sqlite3mc_codec_data = Module['_sqlite3mc_codec_data'] = wasmExports['sqlite3mc_codec_data']; + _sqlite3_activate_see = Module['_sqlite3_activate_see'] = wasmExports['sqlite3_activate_see']; + _sqlite3_key = Module['_sqlite3_key'] = wasmExports['sqlite3_key']; + _sqlite3_key_v2 = Module['_sqlite3_key_v2'] = wasmExports['sqlite3_key_v2']; + _sqlite3_rekey_v2 = Module['_sqlite3_rekey_v2'] = wasmExports['sqlite3_rekey_v2']; + _sqlite3_rekey = Module['_sqlite3_rekey'] = wasmExports['sqlite3_rekey']; + _sqlite3mc_vfs_destroy = Module['_sqlite3mc_vfs_destroy'] = wasmExports['sqlite3mc_vfs_destroy']; + _sqlite3__wasm_pstack_ptr = Module['_sqlite3__wasm_pstack_ptr'] = wasmExports['sqlite3__wasm_pstack_ptr']; + _sqlite3__wasm_pstack_restore = Module['_sqlite3__wasm_pstack_restore'] = wasmExports['sqlite3__wasm_pstack_restore']; + _sqlite3__wasm_pstack_alloc = Module['_sqlite3__wasm_pstack_alloc'] = wasmExports['sqlite3__wasm_pstack_alloc']; + _sqlite3__wasm_pstack_remaining = Module['_sqlite3__wasm_pstack_remaining'] = wasmExports['sqlite3__wasm_pstack_remaining']; + _sqlite3__wasm_pstack_quota = Module['_sqlite3__wasm_pstack_quota'] = wasmExports['sqlite3__wasm_pstack_quota']; + _sqlite3__wasm_test_struct = Module['_sqlite3__wasm_test_struct'] = wasmExports['sqlite3__wasm_test_struct']; + _sqlite3__wasm_enum_json = Module['_sqlite3__wasm_enum_json'] = wasmExports['sqlite3__wasm_enum_json']; + _sqlite3__wasm_vfs_unlink = Module['_sqlite3__wasm_vfs_unlink'] = wasmExports['sqlite3__wasm_vfs_unlink']; + _sqlite3__wasm_db_vfs = Module['_sqlite3__wasm_db_vfs'] = wasmExports['sqlite3__wasm_db_vfs']; + _sqlite3__wasm_db_reset = Module['_sqlite3__wasm_db_reset'] = wasmExports['sqlite3__wasm_db_reset']; + _sqlite3__wasm_db_export_chunked = Module['_sqlite3__wasm_db_export_chunked'] = wasmExports['sqlite3__wasm_db_export_chunked']; + _sqlite3__wasm_db_serialize = Module['_sqlite3__wasm_db_serialize'] = wasmExports['sqlite3__wasm_db_serialize']; + _sqlite3__wasm_vfs_create_file = Module['_sqlite3__wasm_vfs_create_file'] = wasmExports['sqlite3__wasm_vfs_create_file']; + _sqlite3__wasm_posix_create_file = Module['_sqlite3__wasm_posix_create_file'] = wasmExports['sqlite3__wasm_posix_create_file']; + _sqlite3__wasm_kvvfsMakeKey = Module['_sqlite3__wasm_kvvfsMakeKey'] = wasmExports['sqlite3__wasm_kvvfsMakeKey']; + _sqlite3__wasm_kvvfs_methods = Module['_sqlite3__wasm_kvvfs_methods'] = wasmExports['sqlite3__wasm_kvvfs_methods']; + _sqlite3__wasm_vtab_config = Module['_sqlite3__wasm_vtab_config'] = wasmExports['sqlite3__wasm_vtab_config']; + _sqlite3__wasm_db_config_ip = Module['_sqlite3__wasm_db_config_ip'] = wasmExports['sqlite3__wasm_db_config_ip']; + _sqlite3__wasm_db_config_pii = Module['_sqlite3__wasm_db_config_pii'] = wasmExports['sqlite3__wasm_db_config_pii']; + _sqlite3__wasm_db_config_s = Module['_sqlite3__wasm_db_config_s'] = wasmExports['sqlite3__wasm_db_config_s']; + _sqlite3__wasm_config_i = Module['_sqlite3__wasm_config_i'] = wasmExports['sqlite3__wasm_config_i']; + _sqlite3__wasm_config_ii = Module['_sqlite3__wasm_config_ii'] = wasmExports['sqlite3__wasm_config_ii']; + _sqlite3__wasm_config_j = Module['_sqlite3__wasm_config_j'] = wasmExports['sqlite3__wasm_config_j']; + _sqlite3__wasm_qfmt_token = Module['_sqlite3__wasm_qfmt_token'] = wasmExports['sqlite3__wasm_qfmt_token']; + _sqlite3__wasm_kvvfs_decode = Module['_sqlite3__wasm_kvvfs_decode'] = wasmExports['sqlite3__wasm_kvvfs_decode']; + _sqlite3__wasm_kvvfs_encode = Module['_sqlite3__wasm_kvvfs_encode'] = wasmExports['sqlite3__wasm_kvvfs_encode']; + _sqlite3__wasm_init_wasmfs = Module['_sqlite3__wasm_init_wasmfs'] = wasmExports['sqlite3__wasm_init_wasmfs']; + _sqlite3__wasm_test_intptr = Module['_sqlite3__wasm_test_intptr'] = wasmExports['sqlite3__wasm_test_intptr']; + _sqlite3__wasm_test_voidptr = Module['_sqlite3__wasm_test_voidptr'] = wasmExports['sqlite3__wasm_test_voidptr']; + _sqlite3__wasm_test_int64_max = Module['_sqlite3__wasm_test_int64_max'] = wasmExports['sqlite3__wasm_test_int64_max']; + _sqlite3__wasm_test_int64_min = Module['_sqlite3__wasm_test_int64_min'] = wasmExports['sqlite3__wasm_test_int64_min']; + _sqlite3__wasm_test_int64_times2 = Module['_sqlite3__wasm_test_int64_times2'] = wasmExports['sqlite3__wasm_test_int64_times2']; + _sqlite3__wasm_test_int64_minmax = Module['_sqlite3__wasm_test_int64_minmax'] = wasmExports['sqlite3__wasm_test_int64_minmax']; + _sqlite3__wasm_test_int64ptr = Module['_sqlite3__wasm_test_int64ptr'] = wasmExports['sqlite3__wasm_test_int64ptr']; + _sqlite3__wasm_test_stack_overflow = Module['_sqlite3__wasm_test_stack_overflow'] = wasmExports['sqlite3__wasm_test_stack_overflow']; + _sqlite3__wasm_test_str_hello = Module['_sqlite3__wasm_test_str_hello'] = wasmExports['sqlite3__wasm_test_str_hello']; + _sqlite3__wasm_SQLTester_strglob = Module['_sqlite3__wasm_SQLTester_strglob'] = wasmExports['sqlite3__wasm_SQLTester_strglob']; + _malloc = Module['_malloc'] = wasmExports['malloc']; + _free = Module['_free'] = wasmExports['free']; + _realloc = Module['_realloc'] = wasmExports['realloc']; + _emscripten_builtin_memalign = wasmExports['emscripten_builtin_memalign']; + __emscripten_stack_restore = wasmExports['_emscripten_stack_restore']; + __emscripten_stack_alloc = wasmExports['_emscripten_stack_alloc']; + _emscripten_stack_get_current = wasmExports['emscripten_stack_get_current']; + __indirect_function_table = wasmExports['__indirect_function_table']; +} + +var wasmImports = { + + __syscall_chmod: ___syscall_chmod, + + __syscall_faccessat: ___syscall_faccessat, + + __syscall_fchmod: ___syscall_fchmod, + + __syscall_fchown32: ___syscall_fchown32, + + __syscall_fcntl64: ___syscall_fcntl64, + + __syscall_fstat64: ___syscall_fstat64, + + __syscall_ftruncate64: ___syscall_ftruncate64, + + __syscall_getcwd: ___syscall_getcwd, + + __syscall_ioctl: ___syscall_ioctl, + + __syscall_lstat64: ___syscall_lstat64, + + __syscall_mkdirat: ___syscall_mkdirat, + + __syscall_newfstatat: ___syscall_newfstatat, + + __syscall_openat: ___syscall_openat, + + __syscall_readlinkat: ___syscall_readlinkat, + + __syscall_rmdir: ___syscall_rmdir, + + __syscall_stat64: ___syscall_stat64, + + __syscall_unlinkat: ___syscall_unlinkat, + + __syscall_utimensat: ___syscall_utimensat, + + _abort_js: __abort_js, + + _localtime_js: __localtime_js, + + _mmap_js: __mmap_js, + + _munmap_js: __munmap_js, + + _tzset_js: __tzset_js, + + clock_time_get: _clock_time_get, + + emscripten_date_now: _emscripten_date_now, + + emscripten_get_heap_max: _emscripten_get_heap_max, + + emscripten_get_now: _emscripten_get_now, + + emscripten_resize_heap: _emscripten_resize_heap, + + environ_get: _environ_get, + + environ_sizes_get: _environ_sizes_get, + + exit: _exit, + + fd_close: _fd_close, + + fd_fdstat_get: _fd_fdstat_get, + + fd_read: _fd_read, + + fd_seek: _fd_seek, + + fd_sync: _fd_sync, + + fd_write: _fd_write, + + memory: wasmMemory, + + wasm_crypto_getrandom +}; + + + + + +async function run() { + + preRun(); + + if (runDependencies) { + await resolveRunDependencies(); + } + + var setStatus = Module['setStatus']; + if (setStatus) { + setStatus('Running...'); + + await new Promise((resolve) => setTimeout(resolve, 1)); + + setTimeout(setStatus, 1, ''); + } + + if (ABORT) return; + + initRuntime(); + + Module['onRuntimeInitialized']?.(); + + postRun(); +} + +var wasmExports; + + + +wasmExports = await createWasm(); +await run(); + + + + + +Module.runSQLite3PostLoadInit = async function( + sqlite3InitScriptInfo, + EmscriptenModule, + sqlite3IsUnderTest +){ + + 'use strict'; + delete EmscriptenModule.runSQLite3PostLoadInit; + + + + + + + +'use strict'; +globalThis.sqlite3ApiBootstrap = async function sqlite3ApiBootstrap( + apiConfig = (globalThis.sqlite3ApiConfig || sqlite3ApiBootstrap.defaultConfig) +){ + if(sqlite3ApiBootstrap.sqlite3){ + (sqlite3ApiBootstrap.sqlite3.config || console).warn( + "sqlite3ApiBootstrap() called multiple times.", + "Config and external initializers are ignored on calls after the first." + ); + return sqlite3ApiBootstrap.sqlite3; + } + const nu = (...obj)=>Object.assign(Object.create(null),...obj); + const config = nu({ + exports: undefined, + memory: undefined, + bigIntEnabled: !!globalThis.BigInt64Array, + debug: console.debug.bind(console), + warn: console.warn.bind(console), + error: console.error.bind(console), + log: console.log.bind(console), + wasmfsOpfsDir: '/opfs', + + useStdAlloc: false + }, apiConfig); + + Object.assign(config, { + allocExportName: config.useStdAlloc ? 'malloc' : 'sqlite3_malloc', + deallocExportName: config.useStdAlloc ? 'free' : 'sqlite3_free', + reallocExportName: config.useStdAlloc ? 'realloc' : 'sqlite3_realloc' + }); + + [ + + + 'exports', 'memory', 'functionTable', 'wasmfsOpfsDir' + ].forEach((k)=>{ + if('function' === typeof config[k]){ + config[k] = config[k](); + } + }); + + + const capi = nu(); + + const wasm = nu(); + + + const __rcStr = (rc)=>{ + return (capi.sqlite3_js_rc_str && capi.sqlite3_js_rc_str(rc)) + || ("Unknown result code #"+rc); + }; + + + const isInt32 = (n)=> + 'number'===typeof n + && n===(n | 0) + && n<=2147483647 && n>=-2147483648; + + + class SQLite3Error extends Error { + + constructor(...args){ + let rc; + if(args.length){ + if(isInt32(args[0])){ + rc = args[0]; + if(1===args.length){ + super(__rcStr(args[0])); + }else{ + const rcStr = __rcStr(rc); + if('object'===typeof args[1]){ + super(rcStr,args[1]); + }else{ + args[0] = rcStr+':'; + super(args.join(' ')); + } + } + }else{ + if(2===args.length && 'object'===typeof args[1]){ + super(...args); + }else{ + super(args.join(' ')); + } + } + } + this.resultCode = rc || capi.SQLITE_ERROR; + this.name = 'SQLite3Error'; + } + }; + + + SQLite3Error.toss = (...args)=>{ + throw new SQLite3Error(...args); + }; + const toss3 = SQLite3Error.toss; + + if(config.wasmfsOpfsDir && !/^\/[^/]+$/.test(config.wasmfsOpfsDir)){ + toss3("config.wasmfsOpfsDir must be falsy or in the form '/dir-name'."); + } + + + const bigIntFits64 = function f(b){ + if(!f._max){ + f._max = BigInt("0x7fffffffffffffff"); + f._min = ~f._max; + } + return b >= f._min && b <= f._max; + }; + + + const bigIntFits32 = (b)=>(b >= (-0x7fffffffn - 1n) && b <= 0x7fffffffn); + + + const bigIntFitsDouble = function f(b){ + if(!f._min){ + f._min = Number.MIN_SAFE_INTEGER; + f._max = Number.MAX_SAFE_INTEGER; + } + return b >= f._min && b <= f._max; + }; + + + const isTypedArray = (v)=>{ + return (v && v.constructor && isInt32(v.constructor.BYTES_PER_ELEMENT)) ? v : false; + }; + + + const isBindableTypedArray = (v)=> + v && (v instanceof Uint8Array + || v instanceof Int8Array + || v instanceof ArrayBuffer); + + + const isSQLableTypedArray = (v)=> + v && (v instanceof Uint8Array + || v instanceof Int8Array + || v instanceof ArrayBuffer); + + + const affirmBindableTypedArray = (v)=> + isBindableTypedArray(v) + || toss3("Value is not of a supported TypedArray type."); + + + const flexibleString = function(v){ + if(isSQLableTypedArray(v)){ + return wasm.typedArrayToString( + (v instanceof ArrayBuffer) ? new Uint8Array(v) : v, + 0, v.length + ); + } + else if(Array.isArray(v)) return v.join(""); + else if(wasm.isPtr(v)) v = wasm.cstrToJs(v); + return v; + }; + + + class WasmAllocError extends Error { + + constructor(...args){ + if(2===args.length && 'object'===typeof args[1]){ + super(...args); + }else if(args.length){ + super(args.join(' ')); + }else{ + super("Allocation failed."); + } + this.resultCode = capi.SQLITE_NOMEM; + this.name = 'WasmAllocError'; + } + }; + + WasmAllocError.toss = (...args)=>{ + throw new WasmAllocError(...args); + }; + + Object.assign(capi, { + + sqlite3_bind_blob: undefined, + + + sqlite3_bind_text: undefined, + + + sqlite3_create_function_v2: ( + pDb, funcName, nArg, eTextRep, pApp, + xFunc, xStep, xFinal, xDestroy + )=>{}, + + sqlite3_create_function: ( + pDb, funcName, nArg, eTextRep, pApp, + xFunc, xStep, xFinal + )=>{}, + + sqlite3_create_window_function: ( + pDb, funcName, nArg, eTextRep, pApp, + xStep, xFinal, xValue, xInverse, xDestroy + )=>{}, + + sqlite3_prepare_v3: (dbPtr, sql, sqlByteLen, prepFlags, + stmtPtrPtr, strPtrPtr)=>{}, + + + sqlite3_prepare_v2: (dbPtr, sql, sqlByteLen, + stmtPtrPtr,strPtrPtr)=>{}, + + + sqlite3_exec: (pDb, sql, callback, pVoid, pErrMsg)=>{}, + + + sqlite3_randomness: (n, outPtr)=>{}, + }); + + + const util = { + affirmBindableTypedArray, flexibleString, + bigIntFits32, bigIntFits64, bigIntFitsDouble, + isBindableTypedArray, + isInt32, isSQLableTypedArray, isTypedArray, + isUIThread: ()=>(globalThis.window===globalThis && !!globalThis.document), + + toss: function(...args){throw new Error(args.join(' '))}, + toss3, + typedArrayPart: wasm.typedArrayPart, + nu, + assert: function(arg,msg){ + if( !arg ){ + util.toss("Assertion failed:",msg); + } + }, + + affirmDbHeader: function(bytes){ + if(bytes instanceof ArrayBuffer) bytes = new Uint8Array(bytes); + const header = "SQLite format 3"; + if( header.length > bytes.byteLength ){ + toss3("Input does not contain an SQLite3 database header."); + } + for(let i = 0; i < header.length; ++i){ + if( header.charCodeAt(i) !== bytes[i] ){ + break ; + } + } + }, + + affirmIsDb: function(bytes){ + if(bytes instanceof ArrayBuffer) bytes = new Uint8Array(bytes); + const n = bytes.byteLength; + if(n<512 || n%512!==0) { + toss3("Byte array size",n,"is invalid for an SQLite3 db."); + } + util.affirmDbHeader(bytes); + } + }; + + + Object.assign(wasm, { + + + exports: config.exports + || toss3("Missing API config.exports (WASM module exports)."), + + + memory: config.memory + || config.exports['memory'] + || toss3("API config object requires a WebAssembly.Memory object", + "in either config.exports.memory (exported)", + "or config.memory (imported)."), + + + pointerSize: ('number'===typeof config.exports.sqlite3_libversion()) ? 4 : 8, + + + bigIntEnabled: !!config.bigIntEnabled, + + + functionTable: config.functionTable, + + + alloc: undefined, + + + realloc: undefined, + + + dealloc: undefined + + + }); + + + wasm.allocFromTypedArray = function(srcTypedArray){ + if(srcTypedArray instanceof ArrayBuffer){ + srcTypedArray = new Uint8Array(srcTypedArray); + } + affirmBindableTypedArray(srcTypedArray); + const pRet = wasm.alloc(srcTypedArray.byteLength || 1); + wasm.heapForSize(srcTypedArray.constructor) + .set(srcTypedArray.byteLength ? srcTypedArray : [0], Number(pRet)) + ; + return pRet; + }; + + { + + const keyAlloc = config.allocExportName, + keyDealloc = config.deallocExportName, + keyRealloc = config.reallocExportName; + for(const key of [keyAlloc, keyDealloc, keyRealloc]){ + const f = wasm.exports[key]; + if(!(f instanceof Function)) toss3("Missing required exports[",key,"] function."); + } + + wasm.alloc = function f(n){ + return f.impl(n) || WasmAllocError.toss("Failed to allocate",n," bytes."); + }; + wasm.alloc.impl = wasm.exports[keyAlloc]; + wasm.realloc = function f(m,n){ + const m2 = f.impl(wasm.ptr.coerce(m),n); + return n ? (m2 || WasmAllocError.toss("Failed to reallocate",n," bytes.")) : wasm.ptr.null; + }; + wasm.realloc.impl = wasm.exports[keyRealloc]; + wasm.dealloc = function f(m){ + f.impl(wasm.ptr.coerce(m)) + ; + }; + wasm.dealloc.impl = wasm.exports[keyDealloc]; + } + + + wasm.compileOptionUsed = function f(optName){ + if(!arguments.length){ + if(f._result) return f._result; + else if(!f._opt){ + f._rx = /^([^=]+)=(.+)/; + f._rxInt = /^-?\d+$/; + f._opt = function(opt, rv){ + const m = f._rx.exec(opt); + rv[0] = (m ? m[1] : opt); + rv[1] = m ? (f._rxInt.test(m[2]) ? +m[2] : m[2]) : true; + }; + } + const rc = nu(), ov = [0,0]; + let i = 0, k; + while((k = capi.sqlite3_compileoption_get(i++))){ + f._opt(k,ov); + rc[ov[0]] = ov[1]; + } + return f._result = rc; + }else if(Array.isArray(optName)){ + const rc = nu(); + optName.forEach((v)=>{ + rc[v] = capi.sqlite3_compileoption_used(v); + }); + return rc; + }else if('object' === typeof optName){ + Object.keys(optName).forEach((k)=> { + optName[k] = capi.sqlite3_compileoption_used(k); + }); + return optName; + } + return ( + 'string'===typeof optName + ) ? !!capi.sqlite3_compileoption_used(optName) : false; + }; + + + wasm.pstack = nu({ + + restore: wasm.exports.sqlite3__wasm_pstack_restore, + + + alloc: function(n){ + if('string'===typeof n && !(n = wasm.sizeofIR(n))){ + WasmAllocError.toss("Invalid value for pstack.alloc(",arguments[0],")"); + } + return wasm.exports.sqlite3__wasm_pstack_alloc(n) + || WasmAllocError.toss("Could not allocate",n, + "bytes from the pstack."); + }, + + + allocChunks: function(n,sz){ + if('string'===typeof sz && !(sz = wasm.sizeofIR(sz))){ + WasmAllocError.toss("Invalid size value for allocChunks(",arguments[1],")"); + } + const mem = wasm.pstack.alloc(n * sz); + const rc = [mem]; + let i = 1, offset = sz; + for(; i < n; ++i, offset += sz) rc.push(wasm.ptr.add(mem, offset)); + return rc; + }, + + + allocPtr: (n=1,safePtrSize=true)=>{ + return 1===n + ? wasm.pstack.alloc(safePtrSize ? 8 : wasm.ptr.size) + : wasm.pstack.allocChunks(n, safePtrSize ? 8 : wasm.ptr.size); + }, + + + call: function(f){ + const stackPos = wasm.pstack.pointer; + try{ return f(sqlite3) } + finally{ wasm.pstack.restore(stackPos); } + } + + }); + + Object.defineProperties(wasm.pstack, { + + pointer: { + configurable: false, iterable: true, writeable: false, + get: wasm.exports.sqlite3__wasm_pstack_ptr + + + + }, + + + quota: { + configurable: false, iterable: true, writeable: false, + get: wasm.exports.sqlite3__wasm_pstack_quota + }, + + + remaining: { + configurable: false, iterable: true, writeable: false, + get: wasm.exports.sqlite3__wasm_pstack_remaining + } + }); + + + capi.sqlite3_randomness = (...args)=>{ + if(1===args.length + && util.isTypedArray(args[0]) + && 1===args[0].BYTES_PER_ELEMENT){ + const ta = args[0]; + if(0===ta.byteLength){ + wasm.exports.sqlite3_randomness(0,wasm.ptr.null); + return ta; + } + const stack = wasm.pstack.pointer; + try { + let n = ta.byteLength, offset = 0; + const r = wasm.exports.sqlite3_randomness; + const heap = wasm.heap8u(); + const nAlloc = n < 512 ? n : 512; + const ptr = wasm.pstack.alloc(nAlloc); + do{ + const j = (n>nAlloc ? nAlloc : n); + r(j, ptr); + ta.set(wasm.typedArrayPart(heap, ptr, wasm.ptr.add(ptr,j)), offset); + n -= j; + offset += j; + } while(n > 0); + }catch(e){ + config.error("Highly unexpected (and ignored!) "+ + "exception in sqlite3_randomness():",e); + }finally{ + wasm.pstack.restore(stack); + } + return ta; + } + wasm.exports.sqlite3_randomness(...args); + }; + + + capi.sqlite3_wasmfs_opfs_dir = function(){ + if(undefined !== this.dir) return this.dir; + + const pdir = config.wasmfsOpfsDir; + if(!pdir + || !globalThis.FileSystemHandle + || !globalThis.FileSystemDirectoryHandle + || !globalThis.FileSystemFileHandle + || !wasm.exports.sqlite3__wasm_init_wasmfs){ + return this.dir = ""; + } + try{ + if(pdir && 0===wasm.xCallWrapped( + 'sqlite3__wasm_init_wasmfs', 'i32', ['string'], pdir + )){ + return this.dir = pdir; + }else{ + return this.dir = ""; + } + }catch(e){ + + return this.dir = ""; + } + }.bind(nu()); + + + capi.sqlite3_wasmfs_filename_is_persistent = function(name){ + const p = capi.sqlite3_wasmfs_opfs_dir(); + return (p && name) ? name.startsWith(p+'/') : false; + }; + + + capi.sqlite3_js_db_uses_vfs = function(pDb,vfsName,dbName=0){ + try{ + const pK = capi.sqlite3_vfs_find(vfsName); + if(!pK) return false; + else if(!pDb){ + return pK===capi.sqlite3_vfs_find(0) ? pK : false; + }else{ + return pK===capi.sqlite3_js_db_vfs(pDb,dbName) ? pK : false; + } + }catch(e){ + + return false; + } + }; + + + capi.sqlite3_js_vfs_list = function(){ + const rc = []; + let pVfs = capi.sqlite3_vfs_find(wasm.ptr.null); + while(pVfs){ + const oVfs = new capi.sqlite3_vfs(pVfs); + rc.push(wasm.cstrToJs(oVfs.$zName)); + pVfs = oVfs.$pNext; + oVfs.dispose(); + } + return rc; + }; + + + capi.sqlite3_js_db_export = function(pDb, schema=0){ + pDb = wasm.xWrap.testConvertArg('sqlite3*', pDb); + if(!pDb) toss3('Invalid sqlite3* argument.'); + if(!wasm.bigIntEnabled) toss3('BigInt support is not enabled.'); + const scope = wasm.scopedAllocPush(); + let pOut; + try{ + const pSize = wasm.scopedAlloc(8 + wasm.ptr.size); + const ppOut = wasm.ptr.add(pSize, 8); + + const zSchema = schema + ? (wasm.isPtr(schema) ? schema : wasm.scopedAllocCString(''+schema)) + : wasm.ptr.null; + let rc = wasm.exports.sqlite3__wasm_db_serialize( + pDb, zSchema, ppOut, pSize, 0 + ); + if(rc){ + toss3("Database serialization failed with code", + sqlite3.capi.sqlite3_js_rc_str(rc)); + } + pOut = wasm.peekPtr(ppOut); + const nOut = wasm.peek(pSize, 'i64'); + rc = nOut + ? wasm.heap8u().slice(Number(pOut), Number(pOut) + Number(nOut)) + : new Uint8Array(); + return rc; + }finally{ + if(pOut) wasm.exports.sqlite3_free(pOut); + wasm.scopedAllocPop(scope); + } + }; + + + capi.sqlite3_js_db_vfs = + (dbPointer, dbName=wasm.ptr.null)=>util.sqlite3__wasm_db_vfs(dbPointer, dbName); + + + capi.sqlite3_js_aggregate_context = (pCtx, n)=>{ + return capi.sqlite3_aggregate_context(pCtx, n) + || (n ? WasmAllocError.toss("Cannot allocate",n, + "bytes for sqlite3_aggregate_context()") + : 0); + }; + + + capi.sqlite3_js_posix_create_file = function(filename, data, dataLen){ + let pData; + if(data && wasm.isPtr(data)){ + pData = data; + }else if(data instanceof ArrayBuffer || data instanceof Uint8Array){ + pData = wasm.allocFromTypedArray(data); + if(arguments.length<3 || !util.isInt32(dataLen) || dataLen<0){ + dataLen = data.byteLength; + } + }else{ + SQLite3Error.toss("Invalid 2nd argument for sqlite3_js_posix_create_file()."); + } + try{ + if(!util.isInt32(dataLen) || dataLen<0){ + SQLite3Error.toss("Invalid 3rd argument for sqlite3_js_posix_create_file()."); + } + const rc = util.sqlite3__wasm_posix_create_file(filename, pData, dataLen); + if(rc) SQLite3Error.toss("Creation of file failed with sqlite3 result code", + capi.sqlite3_js_rc_str(rc)); + }finally{ + if( pData && pData!==data ) wasm.dealloc(pData); + } + }; + + + capi.sqlite3_js_vfs_create_file = function(vfs, filename, data, dataLen){ + config.warn("sqlite3_js_vfs_create_file() is deprecated and", + "should be avoided because it can lead to C-level crashes.", + "See its documentation for alternatives."); + let pData; + if(data){ + if( wasm.isPtr(data) ){ + pData = data; + }else{ + if( data instanceof ArrayBuffer ){ + data = new Uint8Array(data); + } + if( data instanceof Uint8Array ){ + pData = wasm.allocFromTypedArray(data); + if(arguments.length<4 || !util.isInt32(dataLen) || dataLen<0){ + dataLen = data.byteLength; + } + }else{ + SQLite3Error.toss("Invalid 3rd argument type for sqlite3_js_vfs_create_file()."); + } + } + }else{ + pData = 0; + } + if(!util.isInt32(dataLen) || dataLen<0){ + if( pData && pData!==data ) wasm.dealloc(pData); + SQLite3Error.toss("Invalid 4th argument for sqlite3_js_vfs_create_file()."); + } + try{ + const rc = util.sqlite3__wasm_vfs_create_file(vfs, filename, pData, dataLen); + if(rc) SQLite3Error.toss("Creation of file failed with sqlite3 result code", + capi.sqlite3_js_rc_str(rc)); + }finally{ + if( pData && pData!==data ) wasm.dealloc(pData); + } + }; + + + capi.sqlite3_js_sql_to_string = (sql)=>{ + if('string' === typeof sql){ + return sql; + } + const x = flexibleString(v); + return x===v ? undefined : x; + } + + + capi.sqlite3_db_config = function(pDb, op, ...args){ + switch(op){ + case capi.SQLITE_DBCONFIG_ENABLE_FKEY: + case capi.SQLITE_DBCONFIG_ENABLE_TRIGGER: + case capi.SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER: + case capi.SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION: + case capi.SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE: + case capi.SQLITE_DBCONFIG_ENABLE_QPSG: + case capi.SQLITE_DBCONFIG_TRIGGER_EQP: + case capi.SQLITE_DBCONFIG_RESET_DATABASE: + case capi.SQLITE_DBCONFIG_DEFENSIVE: + case capi.SQLITE_DBCONFIG_WRITABLE_SCHEMA: + case capi.SQLITE_DBCONFIG_LEGACY_ALTER_TABLE: + case capi.SQLITE_DBCONFIG_DQS_DML: + case capi.SQLITE_DBCONFIG_DQS_DDL: + case capi.SQLITE_DBCONFIG_ENABLE_VIEW: + case capi.SQLITE_DBCONFIG_LEGACY_FILE_FORMAT: + case capi.SQLITE_DBCONFIG_TRUSTED_SCHEMA: + case capi.SQLITE_DBCONFIG_STMT_SCANSTATUS: + case capi.SQLITE_DBCONFIG_REVERSE_SCANORDER: + case capi.SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE: + case capi.SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE: + case capi.SQLITE_DBCONFIG_ENABLE_COMMENTS: + case capi.SQLITE_DBCONFIG_FP_DIGITS: + if( !this.ip ){ + this.ip = wasm.xWrap('sqlite3__wasm_db_config_ip','int', + ['sqlite3*', 'int', 'int', '*']); + } + return this.ip(pDb, op, args[0], args[1] || 0); + case capi.SQLITE_DBCONFIG_LOOKASIDE: + if( !this.pii ){ + this.pii = wasm.xWrap('sqlite3__wasm_db_config_pii', 'int', + ['sqlite3*', 'int', '*', 'int', 'int']); + } + return this.pii(pDb, op, args[0], args[1], args[2]); + case capi.SQLITE_DBCONFIG_MAINDBNAME: + if(!this.s){ + this.s = wasm.xWrap('sqlite3__wasm_db_config_s','int', + ['sqlite3*', 'int', 'string:static'] + ); + } + return this.s(pDb, op, args[0]); + default: + return capi.SQLITE_MISUSE; + } + }.bind(nu()); + + + capi.sqlite3_value_to_js = function(pVal,throwIfCannotConvert=true){ + let arg; + const valType = capi.sqlite3_value_type(pVal); + switch(valType){ + case capi.SQLITE_INTEGER: + if(wasm.bigIntEnabled){ + arg = capi.sqlite3_value_int64(pVal); + if(util.bigIntFitsDouble(arg)) arg = Number(arg); + } + else arg = capi.sqlite3_value_double(pVal); + break; + case capi.SQLITE_FLOAT: + arg = capi.sqlite3_value_double(pVal); + break; + case capi.SQLITE_TEXT: + arg = capi.sqlite3_value_text(pVal); + break; + case capi.SQLITE_BLOB:{ + const n = capi.sqlite3_value_bytes(pVal); + const pBlob = capi.sqlite3_value_blob(pVal); + if(n && !pBlob) sqlite3.WasmAllocError.toss( + "Cannot allocate memory for blob argument of",n,"byte(s)" + ); + arg = n + ? wasm.heap8u().slice(Number(pBlob), Number(pBlob) + Number(n)) + : null; + break; + } + case capi.SQLITE_NULL: + arg = null; break; + default: + if(throwIfCannotConvert){ + toss3(capi.SQLITE_MISMATCH, + "Unhandled sqlite3_value_type():",valType); + } + arg = undefined; + } + return arg; + }; + + + capi.sqlite3_values_to_js = function(argc,pArgv,throwIfCannotConvert=true){ + let i; + const tgt = []; + for(i = 0; i < argc; ++i){ + + tgt.push(capi.sqlite3_value_to_js( + wasm.peekPtr(wasm.ptr.add(pArgv, wasm.ptr.size * i)), + throwIfCannotConvert + )); + } + return tgt; + }; + + + capi.sqlite3_result_error_js = function(pCtx,e){ + if(e instanceof WasmAllocError){ + capi.sqlite3_result_error_nomem(pCtx); + }else{ + ; + capi.sqlite3_result_error(pCtx, ''+e, -1); + } + }; + + + capi.sqlite3_result_js = function(pCtx,val){ + if(val instanceof Error){ + capi.sqlite3_result_error_js(pCtx, val); + return; + } + try{ + switch(typeof val) { + case 'undefined': + + break; + case 'boolean': + capi.sqlite3_result_int(pCtx, val ? 1 : 0); + break; + case 'bigint': + if(util.bigIntFits32(val)){ + capi.sqlite3_result_int(pCtx, Number(val)); + }else if(util.bigIntFitsDouble(val)){ + capi.sqlite3_result_double(pCtx, Number(val)); + }else if(wasm.bigIntEnabled){ + if(util.bigIntFits64(val)) capi.sqlite3_result_int64(pCtx, val); + else toss3("BigInt value",val.toString(),"is too BigInt for int64."); + }else{ + toss3("BigInt value",val.toString(),"is too BigInt."); + } + break; + case 'number': { + let f; + if(util.isInt32(val)){ + f = capi.sqlite3_result_int; + }else if(wasm.bigIntEnabled + && Number.isInteger(val) + && util.bigIntFits64(BigInt(val))){ + f = capi.sqlite3_result_int64; + }else{ + f = capi.sqlite3_result_double; + } + f(pCtx, val); + break; + } + case 'string': { + const [p, n] = wasm.allocCString(val,true); + capi.sqlite3_result_text(pCtx, p, n, capi.SQLITE_WASM_DEALLOC); + break; + } + case 'object': + if(null===val) { + capi.sqlite3_result_null(pCtx); + break; + }else if(util.isBindableTypedArray(val)){ + const pBlob = wasm.allocFromTypedArray(val); + capi.sqlite3_result_blob( + pCtx, pBlob, val.byteLength, + capi.SQLITE_WASM_DEALLOC + ); + break; + } + + default: + toss3("Don't not how to handle this UDF result value:",(typeof val), val); + } + }catch(e){ + capi.sqlite3_result_error_js(pCtx, e); + } + }; + + + capi.sqlite3_column_js = function(pStmt, iCol, throwIfCannotConvert=true){ + const v = capi.sqlite3_column_value(pStmt, iCol); + return (0===v) ? undefined : capi.sqlite3_value_to_js(v, throwIfCannotConvert); + }; + + if( true ){ + + const __newOldValue = function(pObj, iCol, impl){ + impl = capi[impl]; + if(!this.ptr) this.ptr = wasm.allocPtr(); + else wasm.pokePtr(this.ptr, 0); + const rc = impl(pObj, iCol, this.ptr); + if(rc) return SQLite3Error.toss(rc,arguments[2]+"() failed with code "+rc); + const pv = wasm.peekPtr(this.ptr); + return pv ? capi.sqlite3_value_to_js( pv, true ) : undefined; + }.bind(nu()); + + + capi.sqlite3_preupdate_new_js = + (pDb, iCol)=>__newOldValue(pDb, iCol, 'sqlite3_preupdate_new'); + + + capi.sqlite3_preupdate_old_js = + (pDb, iCol)=>__newOldValue(pDb, iCol, 'sqlite3_preupdate_old'); + + + capi.sqlite3changeset_new_js = + (pChangesetIter, iCol) => __newOldValue(pChangesetIter, iCol, + 'sqlite3changeset_new'); + + + capi.sqlite3changeset_old_js = + (pChangesetIter, iCol)=>__newOldValue(pChangesetIter, iCol, + 'sqlite3changeset_old'); + } + + + capi.sqlite3_js_retry_busy = function(maxTimes, callback, beforeRetry){ + for(let n = 1; n <= maxTimes; ++n){ + try{ + if( beforeRetry && n>1 ) beforeRetry(n); + const rc = callback(); + if( capi.SQLITE_BUSY===rc ){ + if( n===maxTimes ){ + throw new SQLite3Error(rc, [ + "sqlite3_js_retry_busy() max retry attempts (", + maxTimes, + ") reached." + ].join('')); + } + continue; + } + return rc; + }catch(e){ + if( n{ + if(!sqlite3.__isUnderTest){ + + delete sqlite3.util; + delete sqlite3.StructBinder; + delete sqlite3.opfs; + } + return sqlite3; + }; + const catcher = (e)=>{ + config.error("an async sqlite3 initializer failed:",e); + throw e; + }; + if(!lia || !lia.length){ + return ff.isReady = postInit().catch(catcher); + } + lia = lia.map((f)=>{ + return (f instanceof Function) ? async x=>f(sqlite3) : f; + }); + lia.push(postInit); + let p = Promise.resolve(sqlite3); + while(lia.length) p = p.then(lia.shift()); + return ff.isReady = p.catch(catcher); + }.bind(sqlite3ApiBootstrap), + + scriptInfo: undefined + }; + if( 'undefined'!==typeof sqlite3IsUnderTest ){ + sqlite3.__isUnderTest = !!sqlite3IsUnderTest; + } + try{ + sqlite3ApiBootstrap.initializers.forEach((f)=>{ + f(sqlite3); + }); + }catch(e){ + + console.error("sqlite3 bootstrap initializer threw:",e); + throw e; + } + delete sqlite3ApiBootstrap.initializers; + sqlite3ApiBootstrap.sqlite3 = sqlite3; + if( 'undefined'!==typeof sqlite3InitScriptInfo ){ + sqlite3InitScriptInfo.debugModule( + "sqlite3ApiBootstrap() complete", sqlite3 + ); + sqlite3.scriptInfo + = sqlite3InitScriptInfo; + } + if( sqlite3.__isUnderTest ){ + if( 'undefined'!==typeof EmscriptenModule ){ + sqlite3.config.emscripten = EmscriptenModule; + } + + const iw = sqlite3.scriptInfo?.instantiateWasm; + if( iw ){ + + sqlite3.wasm.module = iw.module; + sqlite3.wasm.instance = iw.instance; + sqlite3.wasm.imports = iw.imports; + } + } + + + delete globalThis.sqlite3ApiConfig; + delete globalThis.sqlite3ApiBootstrap; + delete sqlite3ApiBootstrap.defaultConfig; + return sqlite3.asyncPostInit().then((s)=>{ + if( 'undefined'!==typeof sqlite3InitScriptInfo ){ + sqlite3InitScriptInfo.debugModule( + "sqlite3.asyncPostInit() complete", s + ); + } + delete s.asyncPostInit; + delete s.scriptInfo; + delete s.emscripten; + return s; + }); +}; + + +globalThis.sqlite3ApiBootstrap.initializers = []; + + +globalThis.sqlite3ApiBootstrap.initializersAsync = []; + + +globalThis.sqlite3ApiBootstrap.defaultConfig = Object.create(null); + + +globalThis.sqlite3ApiBootstrap.sqlite3 = undefined; +globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ + sqlite3.version = {"libVersion": "3.54.0", "libVersionNumber": 3054000, "sourceId": "2026-10-09 15:46:58 be8d059e9a49089ab2dce5ed26dd87aaf598fdc5fbe0b107c0dd758464bcd5e3","downloadVersion": 3540000,"scm":{ "sha3-256": "be8d059e9a49089ab2dce5ed26dd87aaf598fdc5fbe0b107c0dd758464bcd5e3","branch": "trunk","tags": "release major-release version-3.54.0","datetime": "2026-10-09T15:46:58.543Z"}}; +}); + + +'use strict'; +globalThis.WhWasmUtilInstaller = +function WhWasmUtilInstaller(target){ + 'use strict'; + if(undefined===target.bigIntEnabled){ + target.bigIntEnabled = !!globalThis['BigInt64Array']; + } + + + const toss = (...args)=>{throw new Error(args.join(' '))}; + + if( !target.pointerSize && !target.pointerIR + && target.alloc && target.dealloc ){ + + const ptr = target.alloc(1); + target.pointerSize = ('bigint'===typeof ptr ? 8 : 4); + target.dealloc(ptr); + } + + + if( target.pointerSize && !target.pointerIR ){ + target.pointerIR = (4===target.pointerSize ? 'i32' : 'i64'); + } + const __ptrIR = (target.pointerIR ??= 'i32'); + const __ptrSize = (target.pointerSize ??= + ('i32'===__ptrIR ? 4 : ('i64'===__ptrIR ? 8 : 0))); + delete target.pointerSize; + delete target.pointerIR; + + if( 'i32'!==__ptrIR && 'i64'!==__ptrIR ){ + toss("Invalid pointerIR:",__ptrIR); + }else if( 8!==__ptrSize && 4!==__ptrSize ){ + toss("Invalid pointerSize:",__ptrSize); + } + + + const __BigInt = target.bigIntEnabled + ? (v)=>BigInt(v || 0) + : (v)=>toss("BigInt support is disabled in this build."); + + const __Number = (v)=>Number(v||0); + + + const __asPtrType = (4===__ptrSize) ? __Number : __BigInt; + + + const __NullPtr = __asPtrType(0); + + + const __ptrAdd = function(...args){ + let rc = __asPtrType(0); + for(const v of args) rc += __asPtrType(v); + return rc; + }; + + + { + const __ptr = Object.create(null); + Object.defineProperty(target, 'ptr', { + enumerable: true, + get: ()=>__ptr, + set: ()=>toss("The ptr property is read-only.") + }); + (function f(name, val){ + Object.defineProperty(__ptr, name, { + enumerable: true, + get: ()=>val, + set: ()=>toss("ptr["+name+"] is read-only.") + }); + return f; + })( + 'null', __NullPtr + )( + 'size', __ptrSize + )( + 'ir', __ptrIR + )( + 'coerce', __asPtrType + )( + 'add', __ptrAdd + )( + 'addn', (4===__ptrIR) ? __ptrAdd : (...args)=>Number(__ptrAdd(...args)) + ); + } + + if(!target.exports){ + Object.defineProperty(target, 'exports', { + enumerable: true, configurable: true, + get: ()=>(target.instance?.exports) + }); + } + + + const cache = Object.create(null); + + cache.heapSize = 0; + + cache.memory = null; + + cache.freeFuncIndexes = []; + + cache.scopedAlloc = []; + + + cache.scopedAlloc.pushPtr = (ptr)=>{ + cache.scopedAlloc[cache.scopedAlloc.length-1].push(ptr); + return ptr; + }; + + cache.utf8Decoder = new TextDecoder(); + cache.utf8Encoder = new TextEncoder('utf-8'); + + + target.sizeofIR = (n)=>{ + switch(n){ + case 'i8': return 1; + case 'i16': return 2; + case 'i32': case 'f32': case 'float': return 4; + case 'i64': case 'f64': case 'double': return 8; + case '*': return __ptrSize; + default: + return (''+n).endsWith('*') ? __ptrSize : undefined; + } + }; + + + const heapWrappers = function(){ + if(!cache.memory){ + cache.memory = (target.memory instanceof WebAssembly.Memory) + ? target.memory : target.exports.memory; + }else if(cache.heapSize === cache.memory.buffer.byteLength){ + return cache; + } + + const b = cache.memory.buffer; + cache.HEAP8 = new Int8Array(b); cache.HEAP8U = new Uint8Array(b); + cache.HEAP16 = new Int16Array(b); cache.HEAP16U = new Uint16Array(b); + cache.HEAP32 = new Int32Array(b); cache.HEAP32U = new Uint32Array(b); + cache.HEAP32F = new Float32Array(b); cache.HEAP64F = new Float64Array(b); + if(target.bigIntEnabled){ + if( 'undefined'!==typeof BigInt64Array ){ + cache.HEAP64 = new BigInt64Array(b); cache.HEAP64U = new BigUint64Array(b); + }else{ + toss("BigInt support is enabled, but the BigInt64Array type is missing."); + } + } + cache.heapSize = b.byteLength; + return cache; + }; + + + target.heap8 = ()=>heapWrappers().HEAP8; + + + target.heap8u = ()=>heapWrappers().HEAP8U; + + + target.heap16 = ()=>heapWrappers().HEAP16; + + + target.heap16u = ()=>heapWrappers().HEAP16U; + + + target.heap32 = ()=>heapWrappers().HEAP32; + + + target.heap32u = ()=>heapWrappers().HEAP32U; + + + target.heapForSize = function(n,unsigned = true){ + let ctor; + const c = (cache.memory && cache.heapSize === cache.memory.buffer.byteLength) + ? cache : heapWrappers(); + switch(n){ + case Int8Array: return c.HEAP8; case Uint8Array: return c.HEAP8U; + case Int16Array: return c.HEAP16; case Uint16Array: return c.HEAP16U; + case Int32Array: return c.HEAP32; case Uint32Array: return c.HEAP32U; + case 8: return unsigned ? c.HEAP8U : c.HEAP8; + case 16: return unsigned ? c.HEAP16U : c.HEAP16; + case 32: return unsigned ? c.HEAP32U : c.HEAP32; + case 64: + if(c.HEAP64) return unsigned ? c.HEAP64U : c.HEAP64; + break; + default: + if(target.bigIntEnabled){ + if(n===globalThis['BigUint64Array']) return c.HEAP64U; + else if(n===globalThis['BigInt64Array']) return c.HEAP64; + break; + } + } + toss("Invalid heapForSize() size: expecting 8, 16, 32,", + "or (if BigInt is enabled) 64."); + }; + + const __funcTable = target.functionTable; + delete target.functionTable; + + + target.functionTable = __funcTable + ? ()=>__funcTable + : ()=>target.exports.__indirect_function_table + ; + + + target.functionEntry = function(fptr){ + const ft = target.functionTable(); + + + + return fptr < ft.length ? ft.get(__asPtrType(fptr)) : undefined; + }; + + + target.jsFuncToWasm = function f(func, sig){ + + if(!f._){ + f._ = { + + sigTypes: Object.assign(Object.create(null),{ + i: 'i32', p: __ptrIR, P: __ptrIR, s: __ptrIR, + j: 'i64', f: 'f32', d: 'f64' + }), + + + typeCodes: Object.assign(Object.create(null),{ + f64: 0x7c, f32: 0x7d, i64: 0x7e, i32: 0x7f + }), + + + uleb128Encode: (tgt, method, n)=>{ + if(n<128) tgt[method](n); + else tgt[method]( (n % 128) | 128, n>>7); + }, + + + rxJSig: /^(\w)\((\w*)\)$/, + + + sigParams: (sig)=>{ + const m = f._.rxJSig.exec(sig); + return m ? m[2] : sig.substr(1); + }, + + + letterType: (x)=>f._.sigTypes[x] || toss("Invalid signature letter:",x), + + + pushSigType: (dest, letter)=>dest.push(f._.typeCodes[f._.letterType(letter)]) + + + + }; + } + if('string'===typeof func){ + const x = sig; + sig = func; + func = x; + } + const _ = f._; + const sigParams = _.sigParams(sig); + const wasmCode = [0x01, 0x60]; + _.uleb128Encode(wasmCode, 'push', sigParams.length); + for(const x of sigParams) _.pushSigType(wasmCode, x); + if('v'===sig[0]) wasmCode.push(0); + else{ + wasmCode.push(1); + _.pushSigType(wasmCode, sig[0]); + } + _.uleb128Encode(wasmCode, 'unshift', wasmCode.length); + wasmCode.unshift( + 0x00, 0x61, 0x73, 0x6d, + 0x01, 0x00, 0x00, 0x00, + 0x01 + ); + wasmCode.push( + 0x02, 0x07, + + 0x01, 0x01, 0x65, 0x01, 0x66, 0x00, 0x00, + 0x07, 0x05, + + 0x01, 0x01, 0x66, 0x00, 0x00 + ); + return (new WebAssembly.Instance( + new WebAssembly.Module(new Uint8Array(wasmCode)), { + e: { f: func } + })).exports['f']; + }; + + + const __installFunction = function f(func, sig, scoped){ + if(scoped && !cache.scopedAlloc.length){ + toss("No scopedAllocPush() scope is active."); + } + if('string'===typeof func){ + const x = sig; + sig = func; + func = x; + } + if('string'!==typeof sig || !(func instanceof Function)){ + toss("Invalid arguments: expecting (function,signature) "+ + "or (signature,function)."); + } + const ft = target.functionTable(); + const oldLen = __asPtrType(ft.length); + let ptr; + while( (ptr = cache.freeFuncIndexes.pop()) ){ + if(ft.get(ptr)){ + + ptr = null; + continue; + }else{ + + break; + } + } + if(!ptr){ + ptr = __asPtrType(oldLen); + ft.grow(__asPtrType(1)); + } + try{ + + ft.set(ptr, func); + if(scoped){ + cache.scopedAlloc.pushPtr(ptr); + } + return ptr; + }catch(e){ + if(!(e instanceof TypeError)){ + if(ptr===oldLen) cache.freeFuncIndexes.push(oldLen); + throw e; + } + } + + try { + const fptr = target.jsFuncToWasm(func, sig); + ft.set(ptr, fptr); + if(scoped){ + cache.scopedAlloc.pushPtr(ptr); + } + }catch(e){ + if(ptr===oldLen) cache.freeFuncIndexes.push(oldLen); + throw e; + } + return ptr; + }; + + + target.installFunction = (func, sig)=>__installFunction(func, sig, false); + + + target.scopedInstallFunction = (func, sig)=>__installFunction(func, sig, true); + + + target.uninstallFunction = function(ptr){ + if(!ptr && __NullPtr!==ptr) return undefined; + + const ft = target.functionTable(); + cache.freeFuncIndexes.push(ptr); + const rc = ft.get(ptr); + ft.set(ptr, null); + return rc; + }; + + + target.peek = function f(ptr, type='i8'){ + if(type.endsWith('*')) type = __ptrIR; + const c = (cache.memory && cache.heapSize === cache.memory.buffer.byteLength) + ? cache : heapWrappers(); + const list = Array.isArray(ptr) ? [] : undefined; + let rc; + do{ + if(list) ptr = arguments[0].shift(); + switch(type){ + case 'i1': + case 'i8': rc = c.HEAP8[Number(ptr)>>0]; break; + case 'i16': rc = c.HEAP16[Number(ptr)>>1]; break; + case 'i32': rc = c.HEAP32[Number(ptr)>>2]; break; + case 'float': case 'f32': rc = c.HEAP32F[Number(ptr)>>2]; break; + case 'double': case 'f64': rc = Number(c.HEAP64F[Number(ptr)>>3]); break; + case 'i64': + if(c.HEAP64){ + rc = __BigInt(c.HEAP64[Number(ptr)>>3]); + break; + } + + default: + toss('Invalid type for peek():',type); + } + if(list) list.push(rc); + }while(list && arguments[0].length); + return list || rc; + }; + + + target.poke = function(ptr, value, type='i8'){ + if (type.endsWith('*')) type = __ptrIR; + const c = (cache.memory && cache.heapSize === cache.memory.buffer.byteLength) + ? cache : heapWrappers(); + for(const p of (Array.isArray(ptr) ? ptr : [ptr])){ + switch (type) { + case 'i1': + case 'i8': c.HEAP8[Number(p)>>0] = value; continue; + case 'i16': c.HEAP16[Number(p)>>1] = value; continue; + case 'i32': c.HEAP32[Number(p)>>2] = value; continue; + case 'float': case 'f32': c.HEAP32F[Number(p)>>2] = value; continue; + case 'double': case 'f64': c.HEAP64F[Number(p)>>3] = value; continue; + case 'i64': + if(c.HEAP64){ + c.HEAP64[Number(p)>>3] = __BigInt(value); + continue; + } + + default: + toss('Invalid type for poke(): ' + type); + } + } + return this; + }; + + + target.peekPtr = (...ptr)=>target.peek( (1===ptr.length ? ptr[0] : ptr), __ptrIR ); + + + target.pokePtr = (ptr, value=0)=>target.poke(ptr, value, __ptrIR); + + + target.peek8 = (...ptr)=>target.peek( (1===ptr.length ? ptr[0] : ptr), 'i8' ); + + target.poke8 = (ptr, value)=>target.poke(ptr, value, 'i8'); + + target.peek16 = (...ptr)=>target.peek( (1===ptr.length ? ptr[0] : ptr), 'i16' ); + + target.poke16 = (ptr, value)=>target.poke(ptr, value, 'i16'); + + target.peek32 = (...ptr)=>target.peek( (1===ptr.length ? ptr[0] : ptr), 'i32' ); + + target.poke32 = (ptr, value)=>target.poke(ptr, value, 'i32'); + + target.peek64 = (...ptr)=>target.peek( (1===ptr.length ? ptr[0] : ptr), 'i64' ); + + target.poke64 = (ptr, value)=>target.poke(ptr, value, 'i64'); + + target.peek32f = (...ptr)=>target.peek( (1===ptr.length ? ptr[0] : ptr), 'f32' ); + + target.poke32f = (ptr, value)=>target.poke(ptr, value, 'f32'); + + target.peek64f = (...ptr)=>target.peek( (1===ptr.length ? ptr[0] : ptr), 'f64' ); + + target.poke64f = (ptr, value)=>target.poke(ptr, value, 'f64'); + + + target.getMemValue = target.peek; + + target.getPtrValue = target.peekPtr; + + target.setMemValue = target.poke; + + target.setPtrValue = target.pokePtr; + + + target.isPtr32 = (ptr)=>( + 'number'===typeof ptr && ptr>=0 && ptr===(ptr|0) + ); + + + target.isPtr64 = (ptr)=>( + ('bigint'===typeof ptr) ? ptr >= 0 : target.isPtr32(ptr) + ); + + + target.isPtr = (4===__ptrSize) ? target.isPtr32 : target.isPtr64; + + + target.cstrlen = function(ptr){ + if(!ptr || !target.isPtr(ptr)) return null; + ptr = Number(ptr) ; + const h = heapWrappers().HEAP8U; + let pos = ptr; + for( ; h[pos] !== 0; ++pos ){} + return pos - ptr; + }; + + + const __SAB = ('undefined'===typeof SharedArrayBuffer) + ? function(){} : SharedArrayBuffer; + + const isSharedTypedArray = (aTypedArray)=>(aTypedArray.buffer instanceof __SAB); + + target.isSharedTypedArray = isSharedTypedArray; + + + const typedArrayPart = (aTypedArray, begin, end)=>{ + if( 8===__ptrSize ){ + + if( 'bigint'===typeof begin ) begin = Number(begin); + if( 'bigint'===typeof end ) end = Number(end); + } + return isSharedTypedArray(aTypedArray) + ? aTypedArray.slice(begin, end) + : aTypedArray.subarray(begin, end); + }; + + target.typedArrayPart = typedArrayPart; + + + const typedArrayToString = (typedArray, begin, end)=> + cache.utf8Decoder.decode( + typedArrayPart(typedArray, begin, end) + ); + + target.typedArrayToString = typedArrayToString; + + + target.cstrToJs = function(ptr){ + const n = target.cstrlen(ptr); + return n + ? typedArrayToString(heapWrappers().HEAP8U, Number(ptr), Number(ptr)+n) + : (null===n ? n : ""); + }; + + + target.jstrlen = function(str){ + + if('string'!==typeof str) return null; + const n = str.length; + let len = 0; + for(let i = 0; i < n; ++i){ + let u = str.charCodeAt(i); + if(u>=0xd800 && u<=0xdfff){ + u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF); + } + if(u<=0x7f) ++len; + else if(u<=0x7ff) len += 2; + else if(u<=0xffff) len += 3; + else len += 4; + } + return len; + }; + + + target.jstrcpy = function(jstr, tgt, offset = 0, maxBytes = -1, addNul = true){ + + if(!tgt || (!(tgt instanceof Int8Array) && !(tgt instanceof Uint8Array))){ + toss("jstrcpy() target must be an Int8Array or Uint8Array."); + } + maxBytes = Number(maxBytes); + offset = Number(offset); + if(maxBytes<0) maxBytes = tgt.length - offset; + if(!(maxBytes>0) || !(offset>=0)) return 0; + let i = 0, max = jstr.length; + const begin = offset, end = offset + maxBytes - (addNul ? 1 : 0); + for(; i < max && offset < end; ++i){ + let u = jstr.charCodeAt(i); + if(u>=0xd800 && u<=0xdfff){ + u = 0x10000 + ((u & 0x3FF) << 10) | (jstr.charCodeAt(++i) & 0x3FF); + } + if(u<=0x7f){ + if(offset >= end) break; + tgt[offset++] = u; + }else if(u<=0x7ff){ + if(offset + 1 >= end) break; + tgt[offset++] = 0xC0 | (u >> 6); + tgt[offset++] = 0x80 | (u & 0x3f); + }else if(u<=0xffff){ + if(offset + 2 >= end) break; + tgt[offset++] = 0xe0 | (u >> 12); + tgt[offset++] = 0x80 | ((u >> 6) & 0x3f); + tgt[offset++] = 0x80 | (u & 0x3f); + }else{ + if(offset + 3 >= end) break; + tgt[offset++] = 0xf0 | (u >> 18); + tgt[offset++] = 0x80 | ((u >> 12) & 0x3f); + tgt[offset++] = 0x80 | ((u >> 6) & 0x3f); + tgt[offset++] = 0x80 | (u & 0x3f); + } + } + if(addNul) tgt[offset++] = 0; + return offset - begin; + }; + + + target.cstrncpy = function(tgtPtr, srcPtr, n){ + if(!tgtPtr || !srcPtr) toss("cstrncpy() does not accept NULL strings."); + if(n<0) n = target.cstrlen(strPtr)+1; + else if(!(n>0)) return 0; + const heap = target.heap8u(); + let i = 0, ch; + const tgtNumber = Number(tgtPtr), srcNumber = Number(srcPtr); + for(; i < n && (ch = heap[srcNumber+i]); ++i){ + heap[tgtNumber+i] = ch; + } + if(i{ + return cache.utf8Encoder.encode(addNul ? (str+"\0") : str); + }; + + const __affirmAlloc = (obj,funcName)=>{ + if(!(obj.alloc instanceof Function) || + !(obj.dealloc instanceof Function)){ + toss("Object is missing alloc() and/or dealloc() function(s)", + "required by",funcName+"()."); + } + }; + + const __allocCStr = function(jstr, returnWithLength, allocator, funcName){ + __affirmAlloc(target, funcName); + if('string'!==typeof jstr) return null; + const u = cache.utf8Encoder.encode(jstr), + ptr = allocator(u.length+1); + let toFree = ptr; + try{ + const heap = heapWrappers().HEAP8U; + heap.set(u, Number(ptr)); + heap[__ptrAdd(ptr, u.length)] = 0; + toFree = __NullPtr; + return returnWithLength ? [ptr, u.length] : ptr; + }finally{ + if( toFree ) target.dealloc(toFree); + } + }; + + + target.allocCString = + (jstr, returnWithLength=false)=>__allocCStr(jstr, returnWithLength, + target.alloc, 'allocCString()'); + + + target.scopedAllocPush = function(){ + __affirmAlloc(target, 'scopedAllocPush'); + const a = []; + cache.scopedAlloc.push(a); + return a; + }; + + + target.scopedAllocPop = function(state){ + __affirmAlloc(target, 'scopedAllocPop'); + const n = arguments.length + ? cache.scopedAlloc.indexOf(state) + : cache.scopedAlloc.length-1; + if(n<0) toss("Invalid state object for scopedAllocPop()."); + if(0===arguments.length) state = cache.scopedAlloc[n]; + cache.scopedAlloc.splice(n,1); + for(let p; (p = state.pop()); ){ + if(target.functionEntry(p)){ + + target.uninstallFunction(p); + }else{ + target.dealloc(p); + } + } + }; + + + target.scopedAlloc = function(n){ + if(!cache.scopedAlloc.length){ + toss("No scopedAllocPush() scope is active."); + } + const p = __asPtrType(target.alloc(n)); + return cache.scopedAlloc.pushPtr(p); + }; + + Object.defineProperty(target.scopedAlloc, 'level', { + configurable: false, enumerable: false, + get: ()=>cache.scopedAlloc.length, + set: ()=>toss("The 'active' property is read-only.") + }); + + + target.scopedAllocCString = + (jstr, returnWithLength=false)=>__allocCStr(jstr, returnWithLength, + target.scopedAlloc, + 'scopedAllocCString()'); + + + const __allocMainArgv = function(isScoped, list){ + const pList = target[ + isScoped ? 'scopedAlloc' : 'alloc' + ]((list.length + 1) * target.ptr.size); + let i = 0; + list.forEach((e)=>{ + target.pokePtr(__ptrAdd(pList, target.ptr.size * i++), + target[ + isScoped ? 'scopedAllocCString' : 'allocCString' + ](""+e)); + }); + target.pokePtr(__ptrAdd(pList, target.ptr.size * i), 0); + return pList; + }; + + + target.scopedAllocMainArgv = (list)=>__allocMainArgv(true, list); + + + target.allocMainArgv = (list)=>__allocMainArgv(false, list); + + + target.cArgvToJs = (argc, pArgv)=>{ + const list = []; + for(let i = 0; i < argc; ++i){ + const arg = target.peekPtr(__ptrAdd(pArgv, target.ptr.size * i)); + list.push( arg ? target.cstrToJs(arg) : null ); + } + return list; + }; + + + target.scopedAllocCall = function(func){ + target.scopedAllocPush(); + try{ return func() } finally{ target.scopedAllocPop() } + }; + + + const __allocPtr = function(howMany, safePtrSize, method){ + __affirmAlloc(target, method); + const pIr = safePtrSize ? 'i64' : __ptrIR; + let m = target[method](howMany * (safePtrSize ? 8 : __ptrSize)); + target.poke(m, 0, pIr) + if(1===howMany){ + return m; + } + const a = [m]; + for(let i = 1; i < howMany; ++i){ + m = __ptrAdd(m, (safePtrSize ? 8 : __ptrSize)); + a[i] = m; + target.poke(m, 0, pIr); + } + return a; + }; + + + target.allocPtr = + (howMany=1, safePtrSize=true)=>__allocPtr(howMany, safePtrSize, 'alloc'); + + + target.scopedAllocPtr = + (howMany=1, safePtrSize=true)=>__allocPtr(howMany, safePtrSize, 'scopedAlloc'); + + + target.xGet = function(name){ + return target.exports[name] || toss("Cannot find exported symbol:",name); + }; + + const __argcMismatch = + (f,n)=>toss(f+"() requires",n,"argument(s)."); + + + target.xCall = function(fname, ...args){ + const f = (fname instanceof Function) ? fname : target.xGet(fname); + if(!(f instanceof Function)) toss("Exported symbol",fname,"is not a function."); + if(f.length!==args.length){ + __argcMismatch(((f===fname) ? f.name : fname),f.length) + ; + } + return (2===arguments.length && Array.isArray(arguments[1])) + ? f.apply(null, arguments[1]) + : f.apply(null, args); + }; + + + cache.xWrap = Object.create(null); + cache.xWrap.convert = Object.create(null); + + cache.xWrap.convert.arg = new Map; + + cache.xWrap.convert.result = new Map; + + const xArg = cache.xWrap.convert.arg, xResult = cache.xWrap.convert.result; + + const __xArgPtr = __asPtrType; + xArg + .set('i64', __BigInt) + .set('i32', (i)=>i|0) + .set('i16', (i)=>((i | 0) & 0xFFFF)) + .set('i8', (i)=>((i | 0) & 0xFF)) + .set('f32', (i)=>Number(i).valueOf()) + .set('float', xArg.get('f32')) + .set('f64', xArg.get('f32')) + .set('double', xArg.get('f64')) + .set('int', xArg.get('i32')) + .set('null', (i)=>i) + .set(null, xArg.get('null')) + .set('**', __xArgPtr) + .set('*', __xArgPtr) + ; + xResult.set('*', __xArgPtr) + .set('pointer', __xArgPtr) + .set('number', (v)=>Number(v)) + .set('void', (v)=>undefined) + .set(undefined, xResult.get('void')) + .set('null', (v)=>v) + .set(null, xResult.get('null')) + ; + + + for(const t of [ + 'i8', 'i16', 'i32', 'i64', 'int', + 'f32', 'float', 'f64', 'double' + ]){ + xArg.set(t+'*', __xArgPtr); + xResult.set(t+'*', __xArgPtr); + xResult.set( + t, xArg.get(t) + || toss("Maintenance required: missing arg converter for",t) + ); + } + + + const __xArgString = (v)=>{ + return ('string'===typeof v) + ? target.scopedAllocCString(v) + : __asPtrType(v); + }; + + xArg.set('string', __xArgString) + .set('utf8', __xArgString) + + ; + + xResult + .set('string', (i)=>target.cstrToJs(i)) + .set('utf8', xResult.get('string')) + .set('string:dealloc', (i)=>{ + try { return i ? target.cstrToJs(i) : null } + finally{ target.dealloc(i) } + }) + .set('utf8:dealloc', xResult.get('string:dealloc')) + .set('json', (i)=>JSON.parse(target.cstrToJs(i))) + .set('json:dealloc', (i)=>{ + try{ return i ? JSON.parse(target.cstrToJs(i)) : null } + finally{ target.dealloc(i) } + }); + + + const AbstractArgAdapter = class { + constructor(opt){ + this.name = opt.name || 'unnamed adapter'; + } + + convertArg(v,argv,argIndex){ + toss("AbstractArgAdapter must be subclassed."); + } + }; + + + xArg.FuncPtrAdapter = class FuncPtrAdapter extends AbstractArgAdapter { + constructor(opt) { + super(opt); + if(xArg.FuncPtrAdapter.warnOnUse){ + console.warn('xArg.FuncPtrAdapter is an internal-only API', + 'and is not intended to be invoked from', + 'client-level code. Invoked with:',opt); + } + this.name = opt.name || "unnamed"; + this.signature = opt.signature; + if(opt.contextKey instanceof Function){ + this.contextKey = opt.contextKey; + if(!opt.bindScope) opt.bindScope = 'context'; + } + this.bindScope = opt.bindScope + || toss("FuncPtrAdapter options requires a bindScope (explicit or implied)."); + if(FuncPtrAdapter.bindScopes.indexOf(opt.bindScope)<0){ + toss("Invalid options.bindScope ("+opt.bindMod+") for FuncPtrAdapter. "+ + "Expecting one of: ("+FuncPtrAdapter.bindScopes.join(', ')+')'); + } + this.isTransient = 'transient'===this.bindScope; + this.isContext = 'context'===this.bindScope; + this.isPermanent = 'permanent'===this.bindScope; + this.singleton = ('singleton'===this.bindScope) ? [] : undefined; + + this.callProxy = (opt.callProxy instanceof Function) + ? opt.callProxy : undefined; + } + + + + + contextKey(argv,argIndex){ + return this; + } + + + contextMap(key){ + const cm = (this.__cmap || (this.__cmap = new Map)); + let rc = cm.get(key); + if(undefined===rc) cm.set(key, (rc = [])); + return rc; + } + + + convertArg(v,argv,argIndex){ + let pair = this.singleton; + if(!pair && this.isContext){ + pair = this.contextMap(this.contextKey(argv,argIndex)); + + } + if( 0 ){ + FuncPtrAdapter.debugOut("FuncPtrAdapter.convertArg()",this.name, + 'signature =',this.signature, + 'transient ?=',this.transient, + 'pair =',pair, + 'v =',v); + } + if(pair && 2===pair.length && pair[0]===v){ + + return pair[1]; + } + if(v instanceof Function){ + + + if(this.callProxy){ + v = this.callProxy(v); + } + const fp = __installFunction(v, this.signature, this.isTransient); + if(FuncPtrAdapter.debugFuncInstall){ + FuncPtrAdapter.debugOut("FuncPtrAdapter installed", this, + this.contextKey(argv,argIndex), '@'+fp, v); + } + if(pair){ + + if(pair[1]){ + if(FuncPtrAdapter.debugFuncInstall){ + FuncPtrAdapter.debugOut("FuncPtrAdapter uninstalling", this, + this.contextKey(argv,argIndex), '@'+pair[1], v); + } + try{ + + cache.scopedAlloc.pushPtr(pair[1]); + } + catch(e){} + } + pair[0] = arguments[0] || __NullPtr; + pair[1] = fp; + } + return fp; + }else if(target.isPtr(v) || null===v || undefined===v){ + if(pair && pair[1] && pair[1]!==v){ + + if(FuncPtrAdapter.debugFuncInstall){ + FuncPtrAdapter.debugOut("FuncPtrAdapter uninstalling", this, + this.contextKey(argv,argIndex), '@'+pair[1], v); + } + try{cache.scopedAlloc.pushPtr(pair[1]);} + catch(e){} + pair[0] = pair[1] = (v || __NullPtr); + } + return v || __NullPtr; + }else{ + throw new TypeError("Invalid FuncPtrAdapter argument type. "+ + "Expecting a function pointer or a "+ + (this.name ? this.name+' ' : '')+ + "function matching signature "+ + this.signature+"."); + } + } + }; + + + xArg.FuncPtrAdapter.warnOnUse = false; + + + xArg.FuncPtrAdapter.debugFuncInstall = false; + + + xArg.FuncPtrAdapter.debugOut = console.debug.bind(console); + + + xArg.FuncPtrAdapter.bindScopes = [ + 'transient', 'context', 'singleton', 'permanent' + ]; + + + const __xArgAdapterCheck = + (t)=>xArg.get(t) || toss("Argument adapter not found:",t); + + + const __xResultAdapterCheck = + (t)=>xResult.get(t) || toss("Result adapter not found:",t); + + + cache.xWrap.convertArg = (t,...args)=>__xArgAdapterCheck(t)(...args); + + cache.xWrap.convertArgNoCheck = (t,...args)=>xArg.get(t)(...args); + + + cache.xWrap.convertResult = + (t,v)=>(null===t ? v : (t ? __xResultAdapterCheck(t)(v) : undefined)); + + cache.xWrap.convertResultNoCheck = + (t,v)=>(null===t ? v : (t ? xResult.get(t)(v) : undefined)); + + + target.xWrap = function callee(fArg, resultType, ...argTypes){ + if(3===arguments.length && Array.isArray(arguments[2])){ + argTypes = arguments[2]; + } + if(target.isPtr(fArg)){ + fArg = target.functionEntry(fArg) + || toss("Function pointer not found in WASM function table."); + } + const fIsFunc = (fArg instanceof Function); + const xf = fIsFunc ? fArg : target.xGet(fArg); + if(fIsFunc) fArg = xf.name || 'unnamed function'; + if(argTypes.length!==xf.length) __argcMismatch(fArg, xf.length); + if( 0===xf.length + && (null===resultType || 'null'===resultType) ){ + + return xf; + } + ; + __xResultAdapterCheck(resultType); + for(const t of argTypes){ + if(t instanceof AbstractArgAdapter) xArg.set(t, (...args)=>t.convertArg(...args)); + else __xArgAdapterCheck(t); + } + const cxw = cache.xWrap; + if(0===xf.length){ + + return (...args)=>(args.length + ? __argcMismatch(fArg, xf.length) + : cxw.convertResult(resultType, xf.call(null))); + } + return function(...args){ + if(args.length!==xf.length) __argcMismatch(fArg, xf.length); + const scope = target.scopedAllocPush(); + try{ + + let i = 0; + if( callee.debug ){ + console.debug("xWrap() preparing: resultType ",resultType, 'xf',xf,"argTypes",argTypes,"args",args); + } + for(; i < args.length; ++i) args[i] = cxw.convertArgNoCheck( + argTypes[i], args[i], args, i + ); + if( callee.debug ){ + console.debug("xWrap() calling: resultType ",resultType, 'xf',xf,"argTypes",argTypes,"args",args); + } + return cxw.convertResultNoCheck(resultType, xf.apply(null,args)); + }finally{ + target.scopedAllocPop(scope); + } + }; + }; + + + const __xAdapter = function(func, argc, typeName, adapter, modeName, xcvPart){ + if('string'===typeof typeName){ + if(1===argc) return xcvPart.get(typeName); + else if(2===argc){ + if(!adapter){ + xcvPart.delete(typeName); + return func; + }else if(!(adapter instanceof Function)){ + toss(modeName,"requires a function argument."); + } + xcvPart.set(typeName, adapter); + return func; + } + } + toss("Invalid arguments to",modeName); + }; + + + target.xWrap.resultAdapter = function f(typeName, adapter){ + return __xAdapter(f, arguments.length, typeName, adapter, + 'resultAdapter()', xResult); + }; + + + target.xWrap.argAdapter = function f(typeName, adapter){ + return __xAdapter(f, arguments.length, typeName, adapter, + 'argAdapter()', xArg); + }; + + target.xWrap.FuncPtrAdapter = xArg.FuncPtrAdapter; + + + target.xCallWrapped = function(fArg, resultType, argTypes, ...args){ + if(Array.isArray(arguments[3])) args = arguments[3]; + return target.xWrap(fArg, resultType, argTypes||[]).apply(null, args||[]); + }; + + + target.xWrap.testConvertArg = cache.xWrap.convertArg; + + + target.xWrap.testConvertResult = cache.xWrap.convertResult; + + return target; +}; + + +globalThis.WhWasmUtilInstaller +.yawl = function yawl(config){ + 'use strict'; + const wfetch = ()=>fetch(config.uri, {credentials: 'same-origin'}); + const wui = this; + const finalThen = function(arg){ + + if(config.wasmUtilTarget){ + const toss = (...args)=>{throw new Error(args.join(' '))}; + const tgt = config.wasmUtilTarget; + tgt.module = arg.module; + tgt.instance = arg.instance; + + if(!tgt.instance.exports.memory){ + + tgt.memory = config?.imports?.env?.memory + || toss("Missing 'memory' object!"); + } + if(!tgt.alloc && arg.instance.exports.malloc){ + const exports = arg.instance.exports; + tgt.alloc = function(n){ + return exports.malloc(n) || toss("Allocation of",n,"bytes failed."); + }; + tgt.dealloc = function(m){m && exports.free(m)}; + } + wui(tgt); + } + arg.config = config; + if(config.onload) config.onload(arg); + return arg ; + }; + const loadWasm = WebAssembly.instantiateStreaming + ? ()=>WebAssembly + .instantiateStreaming(wfetch(), config.imports||{}) + .then(finalThen) + : ()=> wfetch() + .then(response => response.arrayBuffer()) + .then(bytes => WebAssembly.instantiate(bytes, config.imports||{})) + .then(finalThen) + ; + return loadWasm; +}.bind( +globalThis.WhWasmUtilInstaller +); + +'use strict'; +globalThis.Jaccwabyt = +function StructBinderFactory(config){ + 'use strict'; + + + + const toss = (...args)=>{throw new Error(args.join(' '))}; + + { + let h = config.heap; + if( h instanceof WebAssembly.Memory ){ + h = function(){return new Uint8Array(this.buffer)}.bind(h); + }else if( !(h instanceof Function) ){ + + toss("config.heap must be WebAssembly.Memory instance or", + "a function which returns one."); + } + config.heap = h; + } + ['alloc','dealloc'].forEach(function(k){ + (config[k] instanceof Function) || + toss("Config option '"+k+"' must be a function."); + }); + const SBF = StructBinderFactory; + const heap = config.heap, + alloc = config.alloc, + dealloc = config.dealloc, + realloc = (config.realloc || function(){ + toss("This StructBinderFactory was configured without realloc()"); + + }), + log = config.log || console.debug.bind(console), + memberPrefix = (config.memberPrefix || ""), + memberSuffix = (config.memberSuffix || ""), + BigInt = globalThis['BigInt'], + BigInt64Array = globalThis['BigInt64Array'], + bigIntEnabled = config.bigIntEnabled ?? !!BigInt64Array; + + + let ptr; + const ptrSize = config.pointerSize + || config.ptrSize + || ('bigint'===typeof (ptr = alloc(1)) ? 8 : 4); + const ptrIR = config.pointerIR + || config.ptrIR + || (4===ptrSize ? 'i32' : 'i64'); + if( ptr ){ + dealloc(ptr); + ptr = undefined; + } + + + if(ptrSize!==4 && ptrSize!==8) toss("Invalid pointer size:",ptrSize); + if(ptrIR!=='i32' && ptrIR!=='i64') toss("Invalid pointer representation:",ptrIR); + + + const __BigInt = (bigIntEnabled && BigInt) + ? (v)=>BigInt(v || 0) + : (v)=>toss("BigInt support is disabled in this build."); + const __asPtrType = ('i32'==ptrIR) ? Number : __BigInt; + const __NullPtr = __asPtrType(0); + + + const __ptrAdd = function(...args){ + let rc = __NullPtr; + for( let i = 0; i < args.length; ++i ){ + rc += __asPtrType(args[i]); + } + return rc; + }; + + const __ptrAddSelf = function(...args){ + return __ptrAdd(this.pointer,...args); + }; + + if(!SBF.debugFlags){ + SBF.__makeDebugFlags = function(deriveFrom=null){ + + if(deriveFrom && deriveFrom.__flags) deriveFrom = deriveFrom.__flags; + const f = function f(flags){ + if(0===arguments.length){ + return f.__flags; + } + if(flags<0){ + delete f.__flags.getter; delete f.__flags.setter; + delete f.__flags.alloc; delete f.__flags.dealloc; + }else{ + f.__flags.getter = 0!==(0x01 & flags); + f.__flags.setter = 0!==(0x02 & flags); + f.__flags.alloc = 0!==(0x04 & flags); + f.__flags.dealloc = 0!==(0x08 & flags); + } + return f._flags; + }; + Object.defineProperty(f,'__flags', { + iterable: false, writable: false, + value: Object.create(deriveFrom) + }); + if(!deriveFrom) f(0); + return f; + }; + SBF.debugFlags = SBF.__makeDebugFlags(); + } + + const isLittleEndian = true || (function() { + const buffer = new ArrayBuffer(2); + new DataView(buffer).setInt16(0, 256, true ); + + return new Int16Array(buffer)[0] === 256; + })() ; + + + + + const isFuncSig = (s)=>'('===s[1]; + + const isPtrSig = (s)=>'p'===s || 'P'===s || 's'===s; + const isAutoPtrSig = (s)=>'P'===s ; + + const sigLetter = (s)=>s ? (isFuncSig(s) ? 'p' : s[0]) : undefined; + + + const sigIR = function(s){ + switch(sigLetter(s)){ + case 'c': case 'C': return 'i8'; + case 'i': return 'i32'; + case 'p': case 'P': case 's': return ptrIR; + case 'j': return 'i64'; + case 'f': return 'float'; + case 'd': return 'double'; + } + toss("Unhandled signature IR:",s); + }; + + + const sigSize = function(s){ + switch(sigLetter(s)){ + case 'c': case 'C': return 1; + case 'i': return 4; + case 'p': case 'P': case 's': return ptrSize; + case 'j': return 8; + case 'f': return 4; + case 'd': return 8; + } + toss("Unhandled signature sizeof:",s); + }; + + const affirmBigIntArray = BigInt64Array + ? ()=>true : ()=>toss('BigInt64Array is not available.'); + + + const sigDVGetter = function(s){ + switch(sigLetter(s)) { + case 'p': case 'P': case 's': { + switch(ptrSize){ + case 4: return 'getInt32'; + case 8: return affirmBigIntArray() && 'getBigInt64'; + } + break; + } + case 'i': return 'getInt32'; + case 'c': return 'getInt8'; + case 'C': return 'getUint8'; + case 'j': return affirmBigIntArray() && 'getBigInt64'; + case 'f': return 'getFloat32'; + case 'd': return 'getFloat64'; + } + toss("Unhandled DataView getter for signature:",s); + }; + + + const sigDVSetter = function(s){ + switch(sigLetter(s)){ + case 'p': case 'P': case 's': { + switch(ptrSize){ + case 4: return 'setInt32'; + case 8: return affirmBigIntArray() && 'setBigInt64'; + } + break; + } + case 'i': return 'setInt32'; + case 'c': return 'setInt8'; + case 'C': return 'setUint8'; + case 'j': return affirmBigIntArray() && 'setBigInt64'; + case 'f': return 'setFloat32'; + case 'd': return 'setFloat64'; + } + toss("Unhandled DataView setter for signature:",s); + }; + + + const sigDVSetWrapper = function(s){ + switch(sigLetter(s)) { + case 'i': case 'f': case 'c': case 'C': case 'd': return Number; + case 'j': return __BigInt; + case 'p': case 'P': case 's': + switch(ptrSize){ + case 4: return Number; + case 8: return __BigInt; + } + break; + } + toss("Unhandled DataView set wrapper for signature:",s); + }; + + + const sPropName = (s,k)=>s+'::'+k; + + const __propThrowOnSet = function(structName,propName){ + return ()=>toss(sPropName(structName,propName),"is read-only."); + }; + + + const getInstanceHandle = function f(obj, create=true){ + let ii = f.map.get(obj); + if( !ii && create ){ + f.map.set(obj, (ii=f.create(obj))); + } + return ii; + }; + getInstanceHandle.map = new WeakMap; + getInstanceHandle.create = (forObj)=>{ + return Object.assign(Object.create(null),{ + o: forObj, + p: undefined, + ownsPointer: false, + zod: false, + xb: 0 + }); + }; + + + const rmInstanceHandle = (obj)=>getInstanceHandle.map.delete(obj) + ; + + const __isPtr32 = (ptr)=>('number'===typeof ptr && (ptr===(ptr|0)) && ptr>=0); + const __isPtr64 = (ptr)=>( + ('bigint'===typeof ptr && ptr >= 0) || __isPtr32(ptr) + ); + + + const __isPtr = (4===ptrSize) ? __isPtr32 : __isPtr64; + + const __isNonNullPtr = (v)=>__isPtr(v) && (v>0); + + + const __freeStruct = function(ctor, obj, m){ + const ii = getInstanceHandle(obj, false); + if( !ii || ii.isDisposing ) return; + ii.isDisposing = true; + if( !m && !(m = ii.p) ){ + console.warn("Cannot(?) happen: __freeStruct() found no instanceInfo"); + return; + } + if(Array.isArray(obj.ondispose)){ + let x; + while((x = obj.ondispose.pop())){ + try{ + if(x instanceof Function) x.call(obj); + else if(x instanceof StructType) x.dispose(); + else if(__isPtr(x)) dealloc(x); + + + }catch(e){ + console.warn("ondispose() for",ctor.structName,'@', + m,'threw. NOT propagating it.',e); + } + } + }else if(obj.ondispose instanceof Function){ + try{obj.ondispose()} + catch(e){ + + console.warn("ondispose() for",ctor.structName,'@', + m,'threw. NOT propagating it.',e); + } + } + rmInstanceHandle(obj); + delete obj.ondispose; + if(ctor.debugFlags.__flags.dealloc){ + log("debug.dealloc:",(ii.ownsPointer?"":"EXTERNAL"), + ctor.structName,"instance:", + ctor.structInfo.sizeof,"bytes @"+m); + } + if(ii.ownsPointer){ + if( ii.zod || ctor.structInfo.zeroOnDispose ){ + heap().fill(0, Number(m), + Number(m) + ctor.structInfo.sizeof + ii.xb); + } + dealloc(m); + } + }; + + + const rop0 = ()=>{return {configurable: false, writable: false, + iterable: false}}; + + + const rop = (v)=>{return {...rop0(), value: v}}; + + + const __allocStruct = function f(ctor, obj, xm){ + let opt; + const checkPtr = (ptr)=>{ + __isNonNullPtr(ptr) || + toss("Invalid pointer value",arguments[0],"for",ctor.structName,"constructor."); + }; + if( arguments.length>=3 ){ + if( xm && ('object'===typeof xm) ){ + opt = xm; + xm = opt?.wrap; + }else{ + checkPtr(xm); + opt = {wrap: xm}; + } + }else{ + opt = {} + } + + const fill = !xm ; + let nAlloc = 0; + let ownsPointer = false; + if(xm){ + + checkPtr(xm); + ownsPointer = !!opt?.takeOwnership; + }else{ + const nX = opt?.extraBytes ?? 0; + if( nX<0 || (nX!==(nX|0)) ){ + toss("Invalid extraBytes value:",opt?.extraBytes); + } + nAlloc = ctor.structInfo.sizeof + nX; + xm = alloc(nAlloc) + || toss("Allocation of",ctor.structName,"structure failed."); + ownsPointer = true; + } + try { + if( opt?.debugFlags ){ + + obj.debugFlags(opt.debugFlags); + } + if(ctor.debugFlags.__flags.alloc){ + log("debug.alloc:",(fill?"":"EXTERNAL"), + ctor.structName,"instance:", + ctor.structInfo.sizeof,"bytes @"+xm); + } + if(fill){ + heap().fill(0, Number(xm), Number(xm) + nAlloc); + } + const ii = getInstanceHandle(obj); + ii.p = xm; + ii.ownsPointer = ownsPointer; + ii.xb = nAlloc ? (nAlloc-ctor.structInfo.sizeof) : 0; + ii.zod = !!opt?.zeroOnDispose; + if( opt?.ondispose && opt.ondispose!==xm ){ + obj.addOnDispose( opt.ondispose ); + } + }catch(e){ + __freeStruct(ctor, obj, xm); + throw e; + } + }; + + + const looksLikeASig = function f(sig){ + f.rxSig1 ??= /^[ipPsjfdcC]$/; + f.rxSig2 ??= /^[vipPsjfdcC]\([ipPsjfdcC]*\)$/; + return f.rxSig1.test(sig) || f.rxSig2.test(sig); + }; + + + const __adaptorsFor = function(who){ + let x = this.get(who); + if( !x ){ + x = [ Object.create(null), Object.create(null), Object.create(null) ]; + this.set(who, x); + } + return x; + }.bind(new WeakMap); + + + const __adaptor = function(who, which, key, proxy){ + const a = __adaptorsFor(who)[which]; + if(3===arguments.length) return a[key]; + if( proxy ) return a[key] = proxy; + return delete a[key]; + }; + + const noopAdapter = (x)=>x; + + + const __adaptGet = function(key, ...args){ + return __adaptor(this, 0, key, ...args); + }; + + const __affirmNotASig = function(ctx,key){ + looksLikeASig(key) && + toss(ctx,"(",key,") collides with a data type signature."); + }; + + + const __adaptSet = function(key, ...args){ + __affirmNotASig('Setter adaptor',key); + return __adaptor(this, 1, key, ...args); + }; + + + const __adaptStruct = function(key, ...args){ + __affirmNotASig('Struct adaptor',key); + return __adaptor(this, 2, key, ...args); + }; + + + const __adaptStruct2 = function(who,key){ + const si = ('string'===typeof key) + ? __adaptor(who, 2, key) : key; + if( 'object'!==typeof si ){ + toss("Invalid struct mapping object. Arg =",key,JSON.stringify(si)); + } + return si; + }; + + const __memberKey = (k)=>memberPrefix + k + memberSuffix; + const __memberKeyProp = rop(__memberKey); + + + + const __lookupMember = function(structInfo, memberName, tossIfNotFound=true){ + let m = structInfo.members[memberName]; + if(!m && (memberPrefix || memberSuffix)){ + + for(const v of Object.values(structInfo.members)){ + if(v.key===memberName){ m = v; break; } + } + if(!m && tossIfNotFound){ + toss(sPropName(structInfo.name || structInfo.structName, memberName), + 'is not a mapped struct member.'); + } + } + return m; + }; + + + const __memberSignature = function f(obj,memberName,emscriptenFormat=false){ + if(!f._) f._ = (x)=>x.replace(/[^vipPsjrdcC]/g,"").replace(/[pPscC]/g,'i'); + const m = __lookupMember(obj.structInfo, memberName, true); + return emscriptenFormat ? f._(m.signature) : m.signature; + }; + + + const __structMemberKeys = rop(function(){ + const a = []; + for(const k of Object.keys(this.structInfo.members)){ + a.push(this.memberKey(k)); + } + return a; + }); + + const __utf8Decoder = new TextDecoder('utf-8'); + const __utf8Encoder = new TextEncoder(); + + const __SAB = ('undefined'===typeof SharedArrayBuffer) + ? function(){} : SharedArrayBuffer; + const __utf8Decode = function(arrayBuffer, begin, end){ + if( 8===ptrSize ){ + begin = Number(begin); + end = Number(end); + } + return __utf8Decoder.decode( + (arrayBuffer.buffer instanceof __SAB) + ? arrayBuffer.slice(begin, end) + : arrayBuffer.subarray(begin, end) + ); + }; + + + const __memberIsString = function(obj,memberName, tossIfNotFound=false){ + const m = __lookupMember(obj.structInfo, memberName, tossIfNotFound); + return (m && 1===m.signature.length && 's'===m.signature[0]) ? m : false; + }; + + + const __affirmCStringSignature = function(member){ + if('s'===member.signature) return; + toss("Invalid member type signature for C-string value:", + JSON.stringify(member)); + }; + + + const __memberToJsString = function f(obj,memberName){ + const m = __lookupMember(obj.structInfo, memberName, true); + __affirmCStringSignature(m); + const addr = obj[m.key]; + + if(!addr) return null; + let pos = addr; + const mem = heap(); + for( ; mem[pos]!==0; ++pos ) { + + }; + + return (addr===pos) ? "" : __utf8Decode(mem, addr, pos); + }; + + + const __addOnDispose = function(obj, ...v){ + if(obj.ondispose){ + if(!Array.isArray(obj.ondispose)){ + obj.ondispose = [obj.ondispose]; + } + }else{ + obj.ondispose = []; + } + obj.ondispose.push(...v); + }; + + + const __allocCString = function(str){ + const u = __utf8Encoder.encode(str); + const mem = alloc(u.length+1); + if(!mem) toss("Allocation error while duplicating string:",str); + const h = heap(); + + + h.set(u, Number(mem)); + h[__ptrAdd(mem, u.length)] = 0; + + return mem; + }; + + + const __setMemberCString = function(obj, memberName, str){ + const m = __lookupMember(obj.structInfo, memberName, true); + __affirmCStringSignature(m); + + const mem = __allocCString(str); + obj[m.key] = mem; + __addOnDispose(obj, mem); + return obj; + }; + + + const StructType = function StructType(structName, structInfo){ + if(arguments[2]!==rop){ + toss("Do not call the StructType constructor", + "from client-level code."); + } + Object.defineProperties(this,{ + + structName: rop(structName), + structInfo: rop(structInfo) + }); + }; + + + StructType.prototype = Object.create(null, { + dispose: rop(function(){__freeStruct(this.constructor, this)}), + lookupMember: rop(function(memberName, tossIfNotFound=true){ + return __lookupMember(this.structInfo, memberName, tossIfNotFound); + }), + memberToJsString: rop(function(memberName){ + return __memberToJsString(this, memberName); + }), + memberIsString: rop(function(memberName, tossIfNotFound=true){ + return __memberIsString(this, memberName, tossIfNotFound); + }), + memberKey: __memberKeyProp, + memberKeys: __structMemberKeys, + memberSignature: rop(function(memberName, emscriptenFormat=false){ + return __memberSignature(this, memberName, emscriptenFormat); + }), + memoryDump: rop(function(){ + const p = this.pointer; + return p + ? new Uint8Array(heap().slice(Number(p), Number(p) + this.structInfo.sizeof)) + : null; + }), + extraBytes: { + configurable: false, enumerable: false, + get: function(){return getInstanceHandle(this, false)?.xb ?? 0;} + }, + zeroOnDispose: { + configurable: false, enumerable: false, + get: function(){ + return getInstanceHandle(this, false)?.zod + ?? !!this.structInfo.zeroOnDispose; + } + }, + pointer: { + configurable: false, enumerable: false, + get: function(){return getInstanceHandle(this, false)?.p}, + set: ()=>toss("Cannot assign the 'pointer' property of a struct.") + + + + }, + setMemberCString: rop(function(memberName, str){ + return __setMemberCString(this, memberName, str); + }) + }); + + Object.assign(StructType.prototype,{ + addOnDispose: function(...v){ + __addOnDispose(this,...v); + return this; + } + }); + + + Object.defineProperties(StructType, { + allocCString: rop(__allocCString), + isA: rop((v)=>v instanceof StructType), + hasExternalPointer: rop((v)=>{ + const ii = getInstanceHandle(v, false); + return !!(ii?.p && !ii?.ownsPointer); + }), + memberKey: __memberKeyProp + + }); + + + const memberGetterProxy = function(si){ + return si.get || (si.adaptGet + ? StructBinder.adaptGet(si.adaptGet) + : undefined); + }; + + + const memberSetterProxy = function(si){ + return si.set || (si.adaptSet + ? StructBinder.adaptSet(si.adaptSet) + : undefined); + }; + + + const makeMemberStructWrapper = function callee(ctor, name, si){ + + const __innerStructs = (callee.innerStructs ??= new Map()); + const key = ctor.memberKey(name); + if( undefined!==si.signature ){ + toss("'signature' cannot be used on an embedded struct (", + ctor.structName,".",key,")."); + } + if( memberSetterProxy(si) ){ + toss("'set' and 'adaptSet' are not permitted for nested struct members."); + } + + si.structName ??= ctor.structName+'::'+name; + si.key = key; + si.name = name; + si.constructor = this.call(this, si.structName, si); + + + const getterProxy = memberGetterProxy(si); + const prop = Object.assign(Object.create(null),{ + configurable: false, + enumerable: false, + set: __propThrowOnSet(ctor.structName, key), + get: function(){ + const dbg = this.debugFlags.__flags; + const p = this.pointer; + const k = p+'.'+key; + let s = __innerStructs.get(k); + if(dbg.getter){ log("debug.getter: k =",k); } + if( !s ){ + s = new si.constructor(__ptrAdd(p, si.offset)); + __innerStructs.set(k, s); + this.addOnDispose(()=>s.dispose()); + s.addOnDispose(()=>__innerStructs.delete(k)); + + } + if(getterProxy) s = getterProxy.apply(this,[s,key]); + if(dbg.getter) log("debug.getter: result =",s); + return s; + } + }); + Object.defineProperty(ctor.prototype, key, prop); + }; + + + const makeMemberWrapper = function f(ctor, name, si){ + si = __adaptStruct2(this, si); + if( si.members ){ + return makeMemberStructWrapper.call(this, ctor, name, si); + } + + if(!f.cache){ + + f.cache = {getters: {}, setters: {}, sw:{}}; + const a = ['i','c','C','p','P','s','f','d','v()']; + if(bigIntEnabled) a.push('j'); + a.forEach(function(v){ + f.cache.getters[v] = sigDVGetter(v) ; + f.cache.setters[v] = sigDVSetter(v) ; + f.cache.sw[v] = sigDVSetWrapper(v) ; + }); + f.sigCheck = function(obj, name, key,sig){ + if(Object.prototype.hasOwnProperty.call(obj, key)){ + toss(obj.structName,'already has a property named',key+'.'); + } + looksLikeASig(sig) + || toss("Malformed signature for", + sPropName(obj.structName,name)+":",sig); + }; + } + const key = ctor.memberKey(name); + f.sigCheck(ctor.prototype, name, key, si.signature); + si.key = key; + si.name = name; + const sigGlyph = sigLetter(si.signature); + const xPropName = sPropName(ctor.structName,key); + const dbg = ctor.debugFlags.__flags; + + const getterProxy = memberGetterProxy(si); + const prop = Object.create(null); + prop.configurable = false; + prop.enumerable = false; + prop.get = function(){ + + if(dbg.getter){ + log("debug.getter:",f.cache.getters[sigGlyph],"for", sigIR(sigGlyph), + xPropName,'@', this.pointer,'+',si.offset,'sz',si.sizeof); + } + let rc = ( + new DataView(heap().buffer, Number(this.pointer) + si.offset, si.sizeof) + )[f.cache.getters[sigGlyph]](0, isLittleEndian); + + if(getterProxy) rc = getterProxy.apply(this,[key,rc]); + if(dbg.getter) log("debug.getter:",xPropName,"result =",rc); + return rc; + }; + if(si.readOnly){ + prop.set = __propThrowOnSet(ctor.prototype.structName,key); + }else{ + const setterProxy = memberSetterProxy(si); + prop.set = function(v){ + + if(dbg.setter){ + log("debug.setter:",f.cache.setters[sigGlyph],"for", sigIR(sigGlyph), + xPropName,'@', this.pointer,'+',si.offset,'sz',si.sizeof, v); + } + if(!this.pointer){ + toss("Cannot set native property on a disposed", + this.structName,"instance."); + } + if( setterProxy ) v = setterProxy.apply(this,[key,v]); + if( null===v || undefined===v ) v = __NullPtr; + else if( isPtrSig(si.signature) && !__isPtr(v) ){ + if(isAutoPtrSig(si.signature) && (v instanceof StructType)){ + + v = v.pointer || __NullPtr; + if(dbg.setter) log("debug.setter:",xPropName,"resolved to",v); + }else{ + toss("Invalid value for pointer-type",xPropName+'.'); + } + } + ( + new DataView(heap().buffer, Number(this.pointer) + si.offset, + si.sizeof) + )[f.cache.setters[sigGlyph]](0, f.cache.sw[sigGlyph](v), isLittleEndian); + }; + } + Object.defineProperty(ctor.prototype, key, prop); + }; + + + const StructBinderImpl = function StructBinderImpl( + structName, si, opt = Object.create(null) + ){ + + const StructCtor = function StructCtor(arg){ + + if(!(this instanceof StructCtor)){ + toss("The",structName,"constructor may only be called via 'new'."); + } + __allocStruct(StructCtor, this, ...arguments); + }; + const self = this; + + const ads = (x)=>{ + + return (('string'===typeof x) && looksLikeASig(x)) + ? {signature: x} : __adaptStruct2(self,x); + }; + if(1===arguments.length){ + si = ads(structName); + structName = si.structName || si.name; + }else if(2===arguments.length){ + si = ads(si); + si.name ??= structName; + }else{ + si = ads(si); + } + structName ??= si.structName; + + structName ??= opt.structName; + if( !structName ) toss("One of 'name' or 'structName' are required."); + if( si.adapt ){ + + Object.keys(si.adapt.struct||{}).forEach((k)=>{ + __adaptStruct.call(StructBinderImpl, k, si.adapt.struct[k]); + }); + Object.keys(si.adapt.set||{}).forEach((k)=>{ + __adaptSet.call(StructBinderImpl, k, si.adapt.set[k]); + }); + Object.keys(si.adapt.get||{}).forEach((k)=>{ + __adaptGet.call(StructBinderImpl, k, si.adapt.get[k]); + }); + } + if(!si.members && !si.sizeof){ + si.sizeof = sigSize(si.signature); + } + + const debugFlags = rop(SBF.__makeDebugFlags(StructBinder.debugFlags)); + Object.defineProperties(StructCtor,{ + debugFlags: debugFlags, + isA: rop((v)=>v instanceof StructCtor), + memberKey: __memberKeyProp, + memberKeys: __structMemberKeys, + + structInfo: rop(si), + structName: rop(structName), + ptrAdd: rop(__ptrAdd) + }); + StructCtor.prototype = new StructType(structName, si, rop); + Object.defineProperties(StructCtor.prototype,{ + debugFlags: debugFlags, + constructor: rop(StructCtor) + , + ptrAdd: rop(__ptrAddSelf) + }); + let lastMember = false; + let offset = 0; + const autoCalc = !!si.autoCalcSizeOffset; + + if( !autoCalc ){ + if( !si.sizeof ){ + toss(structName,"description is missing its sizeof property."); + } + + si.offset ??= 0; + }else{ + si.offset ??= 0; + } + Object.keys(si.members || {}).forEach((k)=>{ + + let m = ads(si.members[k]); + if(!m.members && !m.sizeof){ + + m.sizeof = sigSize(m.signature); + if(!m.sizeof){ + toss(sPropName(structName,k), "is missing a sizeof property.",m); + } + } + if( undefined===m.offset ){ + if( autoCalc ) m.offset = offset; + else{ + toss(sPropName(structName,k),"is missing its offset.", + JSON.stringify(m)); + } + + } + si.members[k] = m ; + if(!lastMember || lastMember.offset < m.offset) lastMember = m; + const oldAutoCalc = !!m.autoCalc; + if( autoCalc ) m.autoCalcSizeOffset = true; + makeMemberWrapper.call(self, StructCtor, k, m); + if( oldAutoCalc ) m.autoCalcSizeOffset = true; + else delete m.autoCalcSizeOffset; + offset += m.sizeof; + + }); + + if( !lastMember ) toss("No member property descriptions found."); + if( !si.sizeof ) si.sizeof = offset; + if(si.sizeof===1){ + (si.signature === 'c' || si.signature === 'C') || + toss("Unexpected sizeof==1 member", + sPropName(structName,k), + "with signature",si.signature); + }else{ + + + if(0!==(si.sizeof%4)){ + console.warn("Invalid struct member description",si); + toss(structName,"sizeof is not aligned. sizeof="+si.sizeof); + } + if(0!==(si.offset%4)){ + console.warn("Invalid struct member description",si); + toss(structName,"offset is not aligned. offset="+si.offset); + } + } + if( si.sizeof < offset ){ + console.warn("Suspect struct description:",si,"offset =",offset); + toss("Mismatch in the calculated vs. the provided sizeof/offset info.", + "Expected sizeof",offset,"but got",si.sizeof,"for",si); + + } + delete si.autoCalcSizeOffset; + return StructCtor; + }; + + const StructBinder = function StructBinder(structName, structInfo){ + return (1==arguments.length) + ? StructBinderImpl.call(StructBinder, structName) + : StructBinderImpl.call(StructBinder, structName, structInfo); + }; + StructBinder.StructType = StructType; + StructBinder.config = config; + StructBinder.allocCString = __allocCString; + StructBinder.adaptGet = __adaptGet; + StructBinder.adaptSet = __adaptSet; + StructBinder.adaptStruct = __adaptStruct; + StructBinder.ptrAdd = __ptrAdd; + if(!StructBinder.debugFlags){ + StructBinder.debugFlags = SBF.__makeDebugFlags(SBF.debugFlags); + } + return StructBinder; +}; + +globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ + 'use strict'; + const toss = (...args)=>{throw new Error(args.join(' '))}; + const capi = sqlite3.capi, wasm = sqlite3.wasm, util = sqlite3.util; + globalThis.WhWasmUtilInstaller(wasm); + delete globalThis.WhWasmUtilInstaller; + + if(0){ + + + const dealloc = wasm.exports[sqlite3.config.deallocExportName]; + const nFunc = wasm.functionTable().length; + let i; + for(i = 0; i < nFunc; ++i){ + const e = wasm.functionEntry(i); + if(dealloc === e){ + capi.SQLITE_WASM_DEALLOC = i; + break; + } + } + if(dealloc !== wasm.functionEntry(capi.SQLITE_WASM_DEALLOC)){ + toss("Internal error: cannot find function pointer for SQLITE_WASM_DEALLOC."); + } + } + + + const bindingSignatures = { + core: [ + + ["sqlite3_aggregate_context","void*", "sqlite3_context*", "int"], + + ["sqlite3_backup_init", "sqlite3_backup*", "sqlite3*", "string", "sqlite3*", "string"], + ["sqlite3_backup_step", "int", "sqlite3_backup*", "int"], + ["sqlite3_backup_finish", "int", "sqlite3_backup*"], + ["sqlite3_backup_remaining", "int", "sqlite3_backup*"], + ["sqlite3_backup_pagecount", "int", "sqlite3_backup*"], + + ["sqlite3_bind_double","int", "sqlite3_stmt*", "int", "f64"], + ["sqlite3_bind_int","int", "sqlite3_stmt*", "int", "int"], + ["sqlite3_bind_null",undefined, "sqlite3_stmt*", "int"], + ["sqlite3_bind_parameter_count", "int", "sqlite3_stmt*"], + ["sqlite3_bind_parameter_index","int", "sqlite3_stmt*", "string"], + ["sqlite3_bind_parameter_name", "string", "sqlite3_stmt*", "int"], + ["sqlite3_bind_pointer", "int", + "sqlite3_stmt*", "int", "*", "string:static", "*"], + + ["sqlite3_bind_zeroblob", "int", "sqlite3_stmt*", "int", "int"], + ["sqlite3_busy_handler","int", [ + "sqlite3*", + new wasm.xWrap.FuncPtrAdapter({ + signature: 'i(pi)', + contextKey: (argv,argIndex)=>argv[0] + }), + "*" + ]], + ["sqlite3_busy_timeout","int", "sqlite3*", "int"], + + + ["sqlite3_changes", "int", "sqlite3*"], + ["sqlite3_clear_bindings","int", "sqlite3_stmt*"], + ["sqlite3_collation_needed", "int", "sqlite3*", "*", "*"], + ["sqlite3_column_blob","*", "sqlite3_stmt*", "int"], + ["sqlite3_column_bytes","int", "sqlite3_stmt*", "int"], + ["sqlite3_column_count", "int", "sqlite3_stmt*"], + ["sqlite3_column_decltype", "string", "sqlite3_stmt*", "int"], + ["sqlite3_column_double","f64", "sqlite3_stmt*", "int"], + ["sqlite3_column_int","int", "sqlite3_stmt*", "int"], + ["sqlite3_column_name","string", "sqlite3_stmt*", "int"], + ["sqlite3_column_type","int", "sqlite3_stmt*", "int"], + ["sqlite3_column_value","sqlite3_value*", "sqlite3_stmt*", "int"], + ["sqlite3_commit_hook", "void*", [ + "sqlite3*", + new wasm.xWrap.FuncPtrAdapter({ + name: 'sqlite3_commit_hook', + signature: 'i(p)', + contextKey: (argv)=>argv[0] + }), + '*' + ]], + ["sqlite3_compileoption_get", "string", "int"], + ["sqlite3_compileoption_used", "int", "string"], + ["sqlite3_complete", "int", "string:flexible"], + ["sqlite3_context_db_handle", "sqlite3*", "sqlite3_context*"], + + + ["sqlite3_data_count", "int", "sqlite3_stmt*"], + ["sqlite3_db_filename", "string", "sqlite3*", "string"], + ["sqlite3_db_handle", "sqlite3*", "sqlite3_stmt*"], + ["sqlite3_db_name", "string", "sqlite3*", "int"], + ["sqlite3_db_readonly", "int", "sqlite3*", "string"], + ["sqlite3_db_status", "int", "sqlite3*", "int", "*", "*", "int"], + ["sqlite3_errcode", "int", "sqlite3*"], + ["sqlite3_errmsg", "string", "sqlite3*"], + ["sqlite3_error_offset", "int", "sqlite3*"], + ["sqlite3_errstr", "string", "int"], + ["sqlite3_exec", "int", [ + "sqlite3*", "string:flexible", + new wasm.xWrap.FuncPtrAdapter({ + signature: 'i(pipp)', + bindScope: 'transient', + callProxy: (callback)=>{ + let aNames; + return (pVoid, nCols, pColVals, pColNames)=>{ + try { + const aVals = wasm.cArgvToJs(nCols, pColVals); + if(!aNames) aNames = wasm.cArgvToJs(nCols, pColNames); + return callback(aVals, aNames) | 0; + }catch(e){ + + return e.resultCode || capi.SQLITE_ERROR; + } + } + } + }), + "*", "**" + ]], + ["sqlite3_expanded_sql", "string", "sqlite3_stmt*"], + ["sqlite3_extended_errcode", "int", "sqlite3*"], + ["sqlite3_extended_result_codes", "int", "sqlite3*", "int"], + ["sqlite3_file_control", "int", "sqlite3*", "string", "int", "*"], + ["sqlite3_finalize", "int", "sqlite3_stmt*"], + ["sqlite3_free", undefined,"*"], + ["sqlite3_get_autocommit", "int", "sqlite3*"], + ["sqlite3_get_auxdata", "*", "sqlite3_context*", "int"], + ["sqlite3_initialize", undefined], + ["sqlite3_interrupt", undefined, "sqlite3*"], + ["sqlite3_is_interrupted", "int", "sqlite3*"], + ["sqlite3_keyword_count", "int"], + ["sqlite3_keyword_name", "int", ["int", "**", "*"]], + ["sqlite3_keyword_check", "int", ["string", "int"]], + ["sqlite3_libversion", "string"], + ["sqlite3_libversion_number", "int"], + ["sqlite3_limit", "int", ["sqlite3*", "int", "int"]], + ["sqlite3_malloc", "*","int"], + ["sqlite3_next_stmt", "sqlite3_stmt*", ["sqlite3*","sqlite3_stmt*"]], + ["sqlite3_open", "int", "string", "*"], + ["sqlite3_open_v2", "int", "string", "*", "int", "string"], + + + ["sqlite3_realloc", "*","*","int"], + ["sqlite3_reset", "int", "sqlite3_stmt*"], + + ["sqlite3_result_blob", undefined, "sqlite3_context*", "*", "int", "*"], + ["sqlite3_result_double", undefined, "sqlite3_context*", "f64"], + ["sqlite3_result_error", undefined, "sqlite3_context*", "string", "int"], + ["sqlite3_result_error_code", undefined, "sqlite3_context*", "int"], + ["sqlite3_result_error_nomem", undefined, "sqlite3_context*"], + ["sqlite3_result_error_toobig", undefined, "sqlite3_context*"], + ["sqlite3_result_int", undefined, "sqlite3_context*", "int"], + ["sqlite3_result_null", undefined, "sqlite3_context*"], + ["sqlite3_result_pointer", undefined, + "sqlite3_context*", "*", "string:static", "*"], + ["sqlite3_result_subtype", undefined, "sqlite3_value*", "int"], + ["sqlite3_result_text", undefined, "sqlite3_context*", "string", "int", "*"], + ["sqlite3_result_zeroblob", undefined, "sqlite3_context*", "int"], + ["sqlite3_rollback_hook", "void*", [ + "sqlite3*", + new wasm.xWrap.FuncPtrAdapter({ + name: 'sqlite3_rollback_hook', + signature: 'v(p)', + contextKey: (argv)=>argv[0] + }), + '*' + ]], + + ["sqlite3_set_auxdata", undefined, [ + "sqlite3_context*", "int", "*", + true + ? "*" + : new wasm.xWrap.FuncPtrAdapter({ + + name: 'xDestroyAuxData', + signature: 'v(p)', + contextKey: (argv, argIndex)=>argv[0] + }) + ]], + ['sqlite3_set_errmsg', 'int', 'sqlite3*', 'int', 'string'], + ["sqlite3_shutdown", undefined], + ["sqlite3_sourceid", "string"], + ["sqlite3_sql", "string", "sqlite3_stmt*"], + ["sqlite3_status", "int", "int", "*", "*", "int"], + ["sqlite3_step", "int", "sqlite3_stmt*"], + ["sqlite3_stmt_busy", "int", "sqlite3_stmt*"], + ["sqlite3_stmt_readonly", "int", "sqlite3_stmt*"], + ["sqlite3_stmt_status", "int", "sqlite3_stmt*", "int", "int"], + ["sqlite3_strglob", "int", "string","string"], + ["sqlite3_stricmp", "int", "string", "string"], + ["sqlite3_strlike", "int", "string", "string","int"], + ["sqlite3_strnicmp", "int", "string", "string", "int"], + ["sqlite3_table_column_metadata", "int", + "sqlite3*", "string", "string", "string", + "**", "**", "*", "*", "*"], + ["sqlite3_total_changes", "int", "sqlite3*"], + ["sqlite3_trace_v2", "int", [ + "sqlite3*", "int", + new wasm.xWrap.FuncPtrAdapter({ + name: 'sqlite3_trace_v2::callback', + signature: 'i(ippp)', + contextKey: (argv,argIndex)=>argv[0] + }), + "*" + ]], + ["sqlite3_txn_state", "int", ["sqlite3*","string"]], + + ["sqlite3_uri_boolean", "int", "sqlite3_filename", "string", "int"], + ["sqlite3_uri_key", "string", "sqlite3_filename", "int"], + ["sqlite3_uri_parameter", "string", "sqlite3_filename", "string"], + ["sqlite3_user_data","void*", "sqlite3_context*"], + ["sqlite3_value_blob", "*", "sqlite3_value*"], + ["sqlite3_value_bytes","int", "sqlite3_value*"], + ["sqlite3_value_double","f64", "sqlite3_value*"], + ["sqlite3_value_dup", "sqlite3_value*", "sqlite3_value*"], + ["sqlite3_value_free", undefined, "sqlite3_value*"], + ["sqlite3_value_frombind", "int", "sqlite3_value*"], + ["sqlite3_value_int","int", "sqlite3_value*"], + ["sqlite3_value_nochange", "int", "sqlite3_value*"], + ["sqlite3_value_numeric_type", "int", "sqlite3_value*"], + ["sqlite3_value_pointer", "*", "sqlite3_value*", "string:static"], + ["sqlite3_value_subtype", "int", "sqlite3_value*"], + ["sqlite3_value_type", "int", "sqlite3_value*"], + ["sqlite3_vfs_find", "*", "string"], + ["sqlite3_vfs_register", "int", "sqlite3_vfs*", "int"], + ["sqlite3_vfs_unregister", "int", "sqlite3_vfs*"] + + + ], + + int64: [ + ["sqlite3_bind_int64","int", ["sqlite3_stmt*", "int", "i64"]], + ["sqlite3_changes64","i64", ["sqlite3*"]], + ["sqlite3_column_int64","i64", ["sqlite3_stmt*", "int"]], + ["sqlite3_deserialize", "int", "sqlite3*", "string", "*", "i64", "i64", "int"] + , + ["sqlite3_last_insert_rowid", "i64", ["sqlite3*"]], + ["sqlite3_malloc64", "*","i64"], + ["sqlite3_msize", "i64", "*"], + ["sqlite3_overload_function", "int", ["sqlite3*","string","int"]], + ["sqlite3_realloc64", "*","*", "i64"], + ["sqlite3_result_int64", undefined, "*", "i64"], + ["sqlite3_result_zeroblob64", "int", "*", "i64"], + ["sqlite3_serialize","*", "sqlite3*", "string", "*", "int"], + ["sqlite3_set_last_insert_rowid", undefined, ["sqlite3*", "i64"]], + ["sqlite3_status64", "int", "int", "*", "*", "int"], + ["sqlite3_db_status64", "int", "sqlite3*", "int", "*", "*", "int"], + ["sqlite3_total_changes64", "i64", ["sqlite3*"]], + ["sqlite3_update_hook", "*", [ + "sqlite3*", + new wasm.xWrap.FuncPtrAdapter({ + name: 'sqlite3_update_hook::callback', + signature: "v(pippj)", + contextKey: (argv)=>argv[0], + callProxy: (callback)=>{ + return (p,op,z0,z1,rowid)=>{ + callback(p, op, wasm.cstrToJs(z0), wasm.cstrToJs(z1), rowid); + }; + } + }), + "*" + ]], + ["sqlite3_uri_int64", "i64", ["sqlite3_filename", "string", "i64"]], + ["sqlite3_value_int64","i64", "sqlite3_value*"] + + ], + + wasmInternal: [ + ["sqlite3__wasm_db_reset", "int", "sqlite3*"], + ["sqlite3__wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"], + [ + "sqlite3__wasm_vfs_create_file", "int", "sqlite3_vfs*","string","*", "int" + ], + ["sqlite3__wasm_posix_create_file", "int", "string","*", "int"], + ["sqlite3__wasm_vfs_unlink", "int", "sqlite3_vfs*","string"], + ["sqlite3__wasm_qfmt_token","string:dealloc", "string","int"] + ] + } ; + + if( !!wasm.exports.sqlite3_progress_handler ){ + bindingSignatures.core.push( + ["sqlite3_progress_handler", undefined, [ + "sqlite3*", "int", new wasm.xWrap.FuncPtrAdapter({ + name: 'xProgressHandler', + signature: 'i(p)', + bindScope: 'context', + contextKey: (argv,argIndex)=>argv[0] + }), "*" + ]] + ); + } + + if( !!wasm.exports.sqlite3_stmt_explain ){ + bindingSignatures.core.push( + ["sqlite3_stmt_explain", "int", "sqlite3_stmt*", "int"], + ["sqlite3_stmt_isexplain", "int", "sqlite3_stmt*"] + ); + } + + if( !!wasm.exports.sqlite3_set_authorizer ){ + bindingSignatures.core.push( + ["sqlite3_set_authorizer", "int", [ + "sqlite3*", + new wasm.xWrap.FuncPtrAdapter({ + name: "sqlite3_set_authorizer::xAuth", + signature: "i(pi"+"ssss)", + contextKey: (argv, argIndex)=>argv[0], + + callProxy: (callback)=>{ + return (pV, iCode, s0, s1, s2, s3)=>{ + try{ + s0 = s0 && wasm.cstrToJs(s0); s1 = s1 && wasm.cstrToJs(s1); + s2 = s2 && wasm.cstrToJs(s2); s3 = s3 && wasm.cstrToJs(s3); + return callback(pV, iCode, s0, s1, s2, s3) | 0; + }catch(e){ + return e.resultCode || capi.SQLITE_ERROR; + } + } + } + }), + "*" + ]] + ); + } + + if( !!wasm.exports.sqlite3_column_origin_name ){ + bindingSignatures.core.push( + ["sqlite3_column_database_name","string", "sqlite3_stmt*", "int"], + ["sqlite3_column_origin_name","string", "sqlite3_stmt*", "int"], + ["sqlite3_column_table_name","string", "sqlite3_stmt*", "int"] + ); + } + + if(false && wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){ + + bindingSignatures.core.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]); + } + + if( !!wasm.exports.sqlite3_key_v2 ){ + + bindingSignatures.core.push( + ["sqlite3_key", "int", "sqlite3*", "string", "int"], + ["sqlite3_key_v2","int","sqlite3*","string","*","int"], + ["sqlite3_rekey", "int", "sqlite3*", "string", "int"], + ["sqlite3_rekey_v2", "int", "sqlite3*", "string", "*", "int"], + ["sqlite3_activate_see", undefined, "string"], + ["sqlite3mc_cipher_count", "int"], + ["sqlite3mc_cipher_index", "int", "string"], + ["sqlite3mc_cipher_name", "string", "int"], + ["sqlite3mc_cipher_name_copy", "int", "int", "string", "int"], + ["sqlite3mc_config", "int", "sqlite3*", "string", "int"], + ["sqlite3mc_config_cipher", "int", "sqlite3*", "string", "string", "int"], + ["sqlite3mc_codec_data", "string", "sqlite3*", "string", "string"], + ["sqlite3mc_version", "string"], + ["sqlite3mc_vfs_create", "int", "string", "int"], + ["sqlite3mc_vfs_destroy", undefined, "string"], + ["sqlite3mc_vfs_shutdown", undefined] + ); + } + + if( wasm.bigIntEnabled && !!wasm.exports.sqlite3_declare_vtab ){ + bindingSignatures.int64.push( + ["sqlite3_create_module", "int", + ["sqlite3*","string","sqlite3_module*","*"]], + ["sqlite3_create_module_v2", "int", + ["sqlite3*","string","sqlite3_module*","*","*"]], + ["sqlite3_declare_vtab", "int", ["sqlite3*", "string:flexible"]], + ["sqlite3_drop_modules", "int", ["sqlite3*", "**"]], + ["sqlite3_vtab_collation","string","sqlite3_index_info*","int"], + + ["sqlite3_vtab_distinct","int", "sqlite3_index_info*"], + ["sqlite3_vtab_in","int", "sqlite3_index_info*", "int", "int"], + ["sqlite3_vtab_in_first", "int", "sqlite3_value*", "**"], + ["sqlite3_vtab_in_next", "int", "sqlite3_value*", "**"], + ["sqlite3_vtab_nochange","int", "sqlite3_context*"], + ["sqlite3_vtab_on_conflict","int", "sqlite3*"], + ["sqlite3_vtab_rhs_value","int", "sqlite3_index_info*", "int", "**"] + ); + } + + if(wasm.bigIntEnabled && !!wasm.exports.sqlite3_preupdate_hook){ + bindingSignatures.int64.push( + ["sqlite3_preupdate_blobwrite", "int", "sqlite3*"], + ["sqlite3_preupdate_count", "int", "sqlite3*"], + ["sqlite3_preupdate_depth", "int", "sqlite3*"], + ["sqlite3_preupdate_hook", "*", [ + "sqlite3*", + new wasm.xWrap.FuncPtrAdapter({ + name: 'sqlite3_preupdate_hook', + signature: "v(ppippjj)", + contextKey: (argv)=>argv[0], + callProxy: (callback)=>{ + return (p,db,op,zDb,zTbl,iKey1,iKey2)=>{ + callback(p, db, op, wasm.cstrToJs(zDb), wasm.cstrToJs(zTbl), + iKey1, iKey2); + }; + } + }), + "*" + ]], + ["sqlite3_preupdate_new", "int", ["sqlite3*", "int", "**"]], + ["sqlite3_preupdate_old", "int", ["sqlite3*", "int", "**"]] + ); + } + + + if(wasm.bigIntEnabled + && !!wasm.exports.sqlite3changegroup_add + && !!wasm.exports.sqlite3session_create + && !!wasm.exports.sqlite3_preupdate_hook ){ + + const __ipsProxy = { + signature: 'i(ps)', + callProxy:(callback)=>{ + return (p,s)=>{ + try{return callback(p, wasm.cstrToJs(s)) | 0} + catch(e){return e.resultCode || capi.SQLITE_ERROR} + } + } + }; + + bindingSignatures.int64.push( + ['sqlite3changegroup_add', 'int', ['sqlite3_changegroup*', 'int', 'void*']], + ['sqlite3changegroup_add_strm', 'int', [ + 'sqlite3_changegroup*', + new wasm.xWrap.FuncPtrAdapter({ + name: 'xInput', signature: 'i(ppp)', bindScope: 'transient' + }), + 'void*' + ]], + ['sqlite3changegroup_delete', undefined, ['sqlite3_changegroup*']], + ['sqlite3changegroup_new', 'int', ['**']], + ['sqlite3changegroup_output', 'int', ['sqlite3_changegroup*', 'int*', '**']], + ['sqlite3changegroup_output_strm', 'int', [ + 'sqlite3_changegroup*', + new wasm.xWrap.FuncPtrAdapter({ + name: 'xOutput', signature: 'i(ppi)', bindScope: 'transient' + }), + 'void*' + ]], + ['sqlite3changeset_apply', 'int', [ + 'sqlite3*', 'int', 'void*', + new wasm.xWrap.FuncPtrAdapter({ + name: 'xFilter', bindScope: 'transient', ...__ipsProxy + }), + new wasm.xWrap.FuncPtrAdapter({ + name: 'xConflict', signature: 'i(pip)', bindScope: 'transient' + }), + 'void*' + ]], + ['sqlite3changeset_apply_strm', 'int', [ + 'sqlite3*', + new wasm.xWrap.FuncPtrAdapter({ + name: 'xInput', signature: 'i(ppp)', bindScope: 'transient' + }), + 'void*', + new wasm.xWrap.FuncPtrAdapter({ + name: 'xFilter', bindScope: 'transient', ...__ipsProxy + }), + new wasm.xWrap.FuncPtrAdapter({ + name: 'xConflict', signature: 'i(pip)', bindScope: 'transient' + }), + 'void*' + ]], + ['sqlite3changeset_apply_v2', 'int', [ + 'sqlite3*', 'int', 'void*', + new wasm.xWrap.FuncPtrAdapter({ + name: 'xFilter', bindScope: 'transient', ...__ipsProxy + }), + new wasm.xWrap.FuncPtrAdapter({ + name: 'xConflict', signature: 'i(pip)', bindScope: 'transient' + }), + 'void*', '**', 'int*', 'int' + + ]], + ['sqlite3changeset_apply_v2_strm', 'int', [ + 'sqlite3*', + new wasm.xWrap.FuncPtrAdapter({ + name: 'xInput', signature: 'i(ppp)', bindScope: 'transient' + }), + 'void*', + new wasm.xWrap.FuncPtrAdapter({ + name: 'xFilter', bindScope: 'transient', ...__ipsProxy + }), + new wasm.xWrap.FuncPtrAdapter({ + name: 'xConflict', signature: 'i(pip)', bindScope: 'transient' + }), + 'void*', '**', 'int*', 'int' + ]], + ['sqlite3changeset_apply_v3', 'int', [ + 'sqlite3*', 'int', 'void*', + new wasm.xWrap.FuncPtrAdapter({ + name: 'xFilter', signature: 'i(pp)', bindScope: 'transient' + }), + new wasm.xWrap.FuncPtrAdapter({ + name: 'xConflict', signature: 'i(pip)', bindScope: 'transient' + }), + 'void*', '**', 'int*', 'int' + + ]], + ['sqlite3changeset_apply_v3_strm', 'int', [ + 'sqlite3*', + new wasm.xWrap.FuncPtrAdapter({ + name: 'xInput', signature: 'i(ppp)', bindScope: 'transient' + }), + 'void*', + new wasm.xWrap.FuncPtrAdapter({ + name: 'xFilter', signature: 'i(pp)', bindScope: 'transient' + }), + new wasm.xWrap.FuncPtrAdapter({ + name: 'xConflict', signature: 'i(pip)', bindScope: 'transient' + }), + 'void*', '**', 'int*', 'int' + ]], + ['sqlite3changeset_concat', 'int', ['int','void*', 'int', 'void*', 'int*', '**']], + ['sqlite3changeset_concat_strm', 'int', [ + new wasm.xWrap.FuncPtrAdapter({ + name: 'xInputA', signature: 'i(ppp)', bindScope: 'transient' + }), + 'void*', + new wasm.xWrap.FuncPtrAdapter({ + name: 'xInputB', signature: 'i(ppp)', bindScope: 'transient' + }), + 'void*', + new wasm.xWrap.FuncPtrAdapter({ + name: 'xOutput', signature: 'i(ppi)', bindScope: 'transient' + }), + 'void*' + ]], + ['sqlite3changeset_conflict', 'int', ['sqlite3_changeset_iter*', 'int', '**']], + ['sqlite3changeset_finalize', 'int', ['sqlite3_changeset_iter*']], + ['sqlite3changeset_fk_conflicts', 'int', ['sqlite3_changeset_iter*', 'int*']], + ['sqlite3changeset_invert', 'int', ['int', 'void*', 'int*', '**']], + ['sqlite3changeset_invert_strm', 'int', [ + new wasm.xWrap.FuncPtrAdapter({ + name: 'xInput', signature: 'i(ppp)', bindScope: 'transient' + }), + 'void*', + new wasm.xWrap.FuncPtrAdapter({ + name: 'xOutput', signature: 'i(ppi)', bindScope: 'transient' + }), + 'void*' + ]], + ['sqlite3changeset_new', 'int', ['sqlite3_changeset_iter*', 'int', '**']], + ['sqlite3changeset_next', 'int', ['sqlite3_changeset_iter*']], + ['sqlite3changeset_old', 'int', ['sqlite3_changeset_iter*', 'int', '**']], + ['sqlite3changeset_op', 'int', [ + 'sqlite3_changeset_iter*', '**', 'int*', 'int*','int*' + ]], + ['sqlite3changeset_pk', 'int', ['sqlite3_changeset_iter*', '**', 'int*']], + ['sqlite3changeset_start', 'int', ['**', 'int', '*']], + ['sqlite3changeset_start_strm', 'int', [ + '**', + new wasm.xWrap.FuncPtrAdapter({ + name: 'xInput', signature: 'i(ppp)', bindScope: 'transient' + }), + 'void*' + ]], + ['sqlite3changeset_start_v2', 'int', ['**', 'int', '*', 'int']], + ['sqlite3changeset_start_v2_strm', 'int', [ + '**', + new wasm.xWrap.FuncPtrAdapter({ + name: 'xInput', signature: 'i(ppp)', bindScope: 'transient' + }), + 'void*', 'int' + ]], + ['sqlite3session_attach', 'int', ['sqlite3_session*', 'string']], + ['sqlite3session_changeset', 'int', ['sqlite3_session*', 'int*', '**']], + ['sqlite3session_changeset_size', 'i64', ['sqlite3_session*']], + ['sqlite3session_changeset_strm', 'int', [ + 'sqlite3_session*', + new wasm.xWrap.FuncPtrAdapter({ + name: 'xOutput', signature: 'i(ppp)', bindScope: 'transient' + }), + 'void*' + ]], + ['sqlite3session_config', 'int', ['int', 'void*']], + ['sqlite3session_create', 'int', ['sqlite3*', 'string', '**']], + + ['sqlite3session_diff', 'int', ['sqlite3_session*', 'string', 'string', '**']], + ['sqlite3session_enable', 'int', ['sqlite3_session*', 'int']], + ['sqlite3session_indirect', 'int', ['sqlite3_session*', 'int']], + ['sqlite3session_isempty', 'int', ['sqlite3_session*']], + ['sqlite3session_memory_used', 'i64', ['sqlite3_session*']], + ['sqlite3session_object_config', 'int', ['sqlite3_session*', 'int', 'void*']], + ['sqlite3session_patchset', 'int', ['sqlite3_session*', '*', '**']], + ['sqlite3session_patchset_strm', 'int', [ + 'sqlite3_session*', + new wasm.xWrap.FuncPtrAdapter({ + name: 'xOutput', signature: 'i(ppp)', bindScope: 'transient' + }), + 'void*' + ]], + ['sqlite3session_table_filter', undefined, [ + 'sqlite3_session*', + new wasm.xWrap.FuncPtrAdapter({ + name: 'xFilter', ...__ipsProxy, + contextKey: (argv,argIndex)=>argv[0] + }), + '*' + ]] + ); + } + + + sqlite3.StructBinder = globalThis.Jaccwabyt({ + heap: wasm.heap8u, + alloc: wasm.alloc, + dealloc: wasm.dealloc, + bigIntEnabled: wasm.bigIntEnabled, + pointerIR: wasm.ptr.ir, + memberPrefix: '$' + }); + delete globalThis.Jaccwabyt; + + { + + + const __xString = wasm.xWrap.argAdapter('string'); + wasm.xWrap.argAdapter( + 'string:flexible', (v)=>__xString(util.flexibleString(v)) + ); + + + wasm.xWrap.argAdapter( + 'string:static', + function(v){ + if(wasm.isPtr(v)) return v; + v = ''+v; + let rc = this[v]; + return rc || (this[v] = wasm.allocCString(v)); + }.bind(Object.create(null)) + ); + + + const __xArgPtr = wasm.xWrap.argAdapter('*'); + const nilType = function(){ + + }; + wasm.xWrap.argAdapter('sqlite3_filename', __xArgPtr) + ('sqlite3_backup*', __xArgPtr) + ('sqlite3_context*', __xArgPtr) + ('sqlite3_value*', __xArgPtr) + ('void*', __xArgPtr) + ('sqlite3_changegroup*', __xArgPtr) + ('sqlite3_changeset_iter*', __xArgPtr) + ('sqlite3_session*', __xArgPtr) + ('sqlite3_stmt*', (v)=> + __xArgPtr((v instanceof (sqlite3?.oo1?.Stmt || nilType)) + ? v.pointer : v)) + ('sqlite3*', (v)=> + __xArgPtr((v instanceof (sqlite3?.oo1?.DB || nilType)) + ? v.pointer : v)) + + ('sqlite3_vfs*', (v)=>{ + if('string'===typeof v){ + + return capi.sqlite3_vfs_find(v) + || sqlite3.SQLite3Error.toss( + capi.SQLITE_NOTFOUND, + "Unknown sqlite3_vfs name:", v + ); + } + return __xArgPtr((v instanceof (capi.sqlite3_vfs || nilType)) + ? v.pointer : v); + }); + if( wasm.exports.sqlite3_declare_vtab ){ + wasm.xWrap.argAdapter('sqlite3_index_info*', (v)=> + __xArgPtr((v instanceof (capi.sqlite3_index_info || nilType)) + ? v.pointer : v)) + ('sqlite3_module*', (v)=> + __xArgPtr((v instanceof (capi.sqlite3_module || nilType)) + ? v.pointer : v) + ); + } + + + const __xRcPtr = wasm.xWrap.resultAdapter('*'); + wasm.xWrap.resultAdapter('sqlite3*', __xRcPtr) + ('sqlite3_backup*', __xRcPtr) + ('sqlite3_context*', __xRcPtr) + ('sqlite3_stmt*', __xRcPtr) + ('sqlite3_value*', __xRcPtr) + ('sqlite3_vfs*', __xRcPtr) + ('void*', __xRcPtr); + + + for(const e of bindingSignatures.core){ + capi[e[0]] = wasm.xWrap.apply(null, e); + } + for(const e of bindingSignatures.wasmInternal){ + util[e[0]] = wasm.xWrap.apply(null, e); + } + + + for(const e of bindingSignatures.int64){ + capi[e[0]] = wasm.bigIntEnabled + ? wasm.xWrap.apply(null, e) + : ()=>toss(e[0]+"() is unavailable due to lack", + "of BigInt support in this build."); + } + + + delete bindingSignatures.core; + delete bindingSignatures.int64; + delete bindingSignatures.wasmInternal; + + + util.sqlite3__wasm_db_error = function(pDb, resultCode, message){ + if( !pDb ) return capi.SQLITE_MISUSE; + if(resultCode instanceof sqlite3.WasmAllocError){ + resultCode = capi.SQLITE_NOMEM; + message = 0 ; + }else if(resultCode instanceof Error){ + message = message || ''+resultCode; + resultCode = (resultCode.resultCode || capi.SQLITE_ERROR); + } + return capi.sqlite3_set_errmsg(pDb, resultCode, message) || resultCode; + }; + } + + { + const cJson = wasm.xCall('sqlite3__wasm_enum_json'); + if(!cJson){ + toss("Maintenance required: increase sqlite3__wasm_enum_json()'s", + "static buffer size!"); + } + wasm.ctype = JSON.parse(wasm.cstrToJs(cJson)); + + const defineGroups = ['access', 'authorizer', + 'blobFinalizers', 'changeset', + 'config', 'dataTypes', + 'dbConfig', 'dbStatus', + 'encodings', 'fcntl', 'flock', 'ioCap', + 'limits', 'openFlags', + 'prepareFlags', 'resultCodes', + 'sqlite3Status', + 'stmtStatus', 'syncFlags', + 'trace', 'txnState', 'udfFlags', + 'version']; + if(wasm.bigIntEnabled){ + defineGroups.push('serialize', 'session', 'vtab'); + } + for(const t of defineGroups){ + for(const e of Object.entries(wasm.ctype[t])){ + + + capi[e[0]] = e[1]; + } + } + if(!wasm.functionEntry(capi.SQLITE_WASM_DEALLOC)){ + toss("Internal error: cannot resolve exported function", + "entry SQLITE_WASM_DEALLOC (=="+capi.SQLITE_WASM_DEALLOC+")."); + } + const __rcMap = Object.create(null); + for(const e of Object.entries(wasm.ctype['resultCodes'])){ + __rcMap[e[1]] = e[0]; + } + + capi.sqlite3_js_rc_str = (rc)=>__rcMap[rc]; + + + const notThese = Object.assign(Object.create(null),{ + + WasmTestStruct: true, + + sqlite3_index_info: !wasm.bigIntEnabled, + sqlite3_index_constraint: !wasm.bigIntEnabled, + sqlite3_index_orderby: !wasm.bigIntEnabled, + sqlite3_index_constraint_usage: !wasm.bigIntEnabled + }); + for(const s of wasm.ctype.structs){ + if(!notThese[s.name]){ + capi[s.name] = sqlite3.StructBinder(s); + } + } + if(capi.sqlite3_index_info){ + + for(const k of ['sqlite3_index_constraint', + 'sqlite3_index_orderby', + 'sqlite3_index_constraint_usage']){ + capi.sqlite3_index_info[k] = capi[k]; + delete capi[k]; + } + capi.sqlite3_vtab_config = wasm.xWrap( + 'sqlite3__wasm_vtab_config','int',[ + 'sqlite3*', 'int', 'int'] + ); + } + } + + + const __dbArgcMismatch = (pDb,f,n)=>{ + return util.sqlite3__wasm_db_error(pDb, capi.SQLITE_MISUSE, + f+"() requires "+n+" argument"+ + (1===n?"":'s')+"."); + }; + + + const __errEncoding = (pDb)=>{ + return util.sqlite3__wasm_db_error( + pDb, capi.SQLITE_FORMAT, "SQLITE_UTF8 is the only supported encoding." + ); + }; + + + const __argPDb = (pDb)=>wasm.xWrap.argAdapter('sqlite3*')(pDb); + const __argStr = (str)=>wasm.isPtr(str) ? wasm.cstrToJs(str) : str; + const __dbCleanupMap = function( + pDb, mode + ){ + pDb = __argPDb(pDb); + let m = this.dbMap.get(pDb); + if(!mode){ + this.dbMap.delete(pDb); + return m; + }else if(!m && mode>0){ + this.dbMap.set(pDb, (m = Object.create(null))); + } + return m; + }.bind(Object.assign(Object.create(null),{ + dbMap: new Map + })); + + __dbCleanupMap.addCollation = function(pDb, name){ + const m = __dbCleanupMap(pDb, 1); + if(!m.collation) m.collation = new Set; + m.collation.add(__argStr(name).toLowerCase()); + }; + + __dbCleanupMap._addUDF = function(pDb, name, arity, map){ + + name = __argStr(name).toLowerCase(); + let u = map.get(name); + if(!u) map.set(name, (u = new Set)); + u.add((arity<0) ? -1 : arity); + }; + + __dbCleanupMap.addFunction = function(pDb, name, arity){ + const m = __dbCleanupMap(pDb, 1); + if(!m.udf) m.udf = new Map; + this._addUDF(pDb, name, arity, m.udf); + }; + + if( wasm.exports.sqlite3_create_window_function ){ + __dbCleanupMap.addWindowFunc = function(pDb, name, arity){ + const m = __dbCleanupMap(pDb, 1); + if(!m.wudf) m.wudf = new Map; + this._addUDF(pDb, name, arity, m.wudf); + }; + } + + + __dbCleanupMap.cleanup = function(pDb){ + pDb = __argPDb(pDb); + + + for(const obj of [ + + ['sqlite3_busy_handler',3], + ['sqlite3_commit_hook',3], + ['sqlite3_preupdate_hook',3], + ['sqlite3_progress_handler',4], + ['sqlite3_rollback_hook',3], + ['sqlite3_set_authorizer',3], + ['sqlite3_trace_v2', 4], + ['sqlite3_update_hook',3] + + ]){ + const [name, arity] = obj; + const x = wasm.exports[name]; + if( !x ){ + + continue; + } + const closeArgs = [pDb]; + closeArgs.length = arity + ; + + try{ capi[name](...closeArgs) } + catch(e){ + + sqlite3.config.warn("close-time call of",name+"(",closeArgs,") threw:",e); + } + + } + const m = __dbCleanupMap(pDb, 0); + if(!m) return; + if(m.collation){ + for(const name of m.collation){ + try{ + capi.sqlite3_create_collation_v2( + pDb, name, capi.SQLITE_UTF8, 0, 0, 0 + ); + }catch(e){ + + } + } + delete m.collation; + } + let i; + for(i = 0; i < 2; ++i){ + const fmap = i ? m.wudf : m.udf; + if(!fmap) continue; + const func = i + ? capi.sqlite3_create_window_function + : capi.sqlite3_create_function_v2; + for(const e of fmap){ + const name = e[0], arities = e[1]; + const fargs = [pDb, name, 0, capi.SQLITE_UTF8, 0, 0, 0, 0, 0]; + if(i) fargs.push(0); + for(const arity of arities){ + try{ fargs[2] = arity; func.apply(null, fargs); } + catch(e){} + } + arities.clear(); + } + fmap.clear(); + } + delete m.udf; + delete m.wudf; + }; + + { + const __sqlite3CloseV2 = wasm.xWrap("sqlite3_close_v2", "int", "sqlite3*"); + capi.sqlite3_close_v2 = function(pDb){ + if(1!==arguments.length) return __dbArgcMismatch(pDb, 'sqlite3_close_v2', 1); + if(pDb){ + try{__dbCleanupMap.cleanup(pDb)} catch(e){} + } + return __sqlite3CloseV2(pDb); + }; + } + + if(capi.sqlite3session_create){ + const __sqlite3SessionDelete = wasm.xWrap( + 'sqlite3session_delete', undefined, ['sqlite3_session*'] + ); + capi.sqlite3session_delete = function(pSession){ + if(1!==arguments.length){ + return __dbArgcMismatch(pDb, 'sqlite3session_delete', 1); + + } + else if(pSession){ + + capi.sqlite3session_table_filter(pSession, 0, 0); + } + __sqlite3SessionDelete(pSession); + }; + } + + { + + const contextKey = (argv,argIndex)=>{ + return 'argv['+argIndex+']:'+argv[0]+ + ':'+wasm.cstrToJs(argv[1]).toLowerCase() + }; + const __sqlite3CreateCollationV2 = wasm.xWrap( + 'sqlite3_create_collation_v2', 'int', [ + 'sqlite3*', 'string', 'int', '*', + new wasm.xWrap.FuncPtrAdapter({ + + name: 'xCompare', signature: 'i(pipip)', contextKey + }), + new wasm.xWrap.FuncPtrAdapter({ + + name: 'xDestroy', signature: 'v(p)', contextKey + }) + ] + ); + + + capi.sqlite3_create_collation_v2 = function(pDb,zName,eTextRep,pArg,xCompare,xDestroy){ + if(6!==arguments.length) return __dbArgcMismatch(pDb, 'sqlite3_create_collation_v2', 6); + else if( 0 === (eTextRep & 0xf) ){ + eTextRep |= capi.SQLITE_UTF8; + }else if( capi.SQLITE_UTF8 !== (eTextRep & 0xf) ){ + return __errEncoding(pDb); + } + try{ + const rc = __sqlite3CreateCollationV2(pDb, zName, eTextRep, pArg, xCompare, xDestroy); + if(0===rc && xCompare instanceof Function){ + __dbCleanupMap.addCollation(pDb, zName); + } + return rc; + }catch(e){ + return util.sqlite3__wasm_db_error(pDb, e); + } + }; + + capi.sqlite3_create_collation = (pDb,zName,eTextRep,pArg,xCompare)=>{ + return (5===arguments.length) + ? capi.sqlite3_create_collation_v2(pDb,zName,eTextRep,pArg,xCompare,0) + : __dbArgcMismatch(pDb, 'sqlite3_create_collation', 5); + }; + + } + + { + + const contextKey = function(argv,argIndex){ + return ( + argv[0] + +':'+(argv[2] < 0 ? -1 : argv[2]) + +':'+argIndex + +':'+wasm.cstrToJs(argv[1]).toLowerCase() + ) + }; + + + const __cfProxy = Object.assign(Object.create(null), { + xInverseAndStep: { + signature:'v(pip)', contextKey, + callProxy: (callback)=>{ + return (pCtx, argc, pArgv)=>{ + try{ callback(pCtx, ...capi.sqlite3_values_to_js(argc, pArgv)) } + catch(e){ capi.sqlite3_result_error_js(pCtx, e) } + }; + } + }, + xFinalAndValue: { + signature:'v(p)', contextKey, + callProxy: (callback)=>{ + return (pCtx)=>{ + try{ capi.sqlite3_result_js(pCtx, callback(pCtx)) } + catch(e){ capi.sqlite3_result_error_js(pCtx, e) } + }; + } + }, + xFunc: { + signature:'v(pip)', contextKey, + callProxy: (callback)=>{ + return (pCtx, argc, pArgv)=>{ + try{ + capi.sqlite3_result_js( + pCtx, + callback(pCtx, ...capi.sqlite3_values_to_js(argc, pArgv)) + ); + }catch(e){ + + capi.sqlite3_result_error_js(pCtx, e); + } + }; + } + }, + xDestroy: { + signature:'v(p)', contextKey, + + callProxy: (callback)=>{ + return (pVoid)=>{ + try{ callback(pVoid) } + catch(e){ console.error("UDF xDestroy method threw:",e) } + }; + } + } + }); + + const __sqlite3CreateFunction = wasm.xWrap( + "sqlite3_create_function_v2", "int", [ + "sqlite3*", "string", "int", + "int", "*", + new wasm.xWrap.FuncPtrAdapter({name: 'xFunc', ...__cfProxy.xFunc}), + new wasm.xWrap.FuncPtrAdapter({name: 'xStep', ...__cfProxy.xInverseAndStep}), + new wasm.xWrap.FuncPtrAdapter({name: 'xFinal', ...__cfProxy.xFinalAndValue}), + new wasm.xWrap.FuncPtrAdapter({name: 'xDestroy', ...__cfProxy.xDestroy}) + ] + ); + + const __sqlite3CreateWindowFunction = + wasm.exports.sqlite3_create_window_function + ? wasm.xWrap( + "sqlite3_create_window_function", "int", [ + "sqlite3*", "string", "int", + "int", "*", + new wasm.xWrap.FuncPtrAdapter({name: 'xStep', ...__cfProxy.xInverseAndStep}), + new wasm.xWrap.FuncPtrAdapter({name: 'xFinal', ...__cfProxy.xFinalAndValue}), + new wasm.xWrap.FuncPtrAdapter({name: 'xValue', ...__cfProxy.xFinalAndValue}), + new wasm.xWrap.FuncPtrAdapter({name: 'xInverse', ...__cfProxy.xInverseAndStep}), + new wasm.xWrap.FuncPtrAdapter({name: 'xDestroy', ...__cfProxy.xDestroy}) + ] + ) + : undefined; + + + capi.sqlite3_create_function_v2 = function f( + pDb, funcName, nArg, eTextRep, pApp, + xFunc, + xStep, + xFinal, + xDestroy + ){ + if( f.length!==arguments.length ){ + return __dbArgcMismatch(pDb,"sqlite3_create_function_v2",f.length); + }else if( 0 === (eTextRep & 0xf) ){ + eTextRep |= capi.SQLITE_UTF8; + }else if( capi.SQLITE_UTF8 !== (eTextRep & 0xf) ){ + return __errEncoding(pDb); + } + try{ + const rc = __sqlite3CreateFunction(pDb, funcName, nArg, eTextRep, + pApp, xFunc, xStep, xFinal, xDestroy); + if(0===rc && (xFunc instanceof Function + || xStep instanceof Function + || xFinal instanceof Function + || xDestroy instanceof Function)){ + __dbCleanupMap.addFunction(pDb, funcName, nArg); + } + return rc; + }catch(e){ + console.error("sqlite3_create_function_v2() setup threw:",e); + return util.sqlite3__wasm_db_error(pDb, e, "Creation of UDF threw: "+e); + } + }; + + + capi.sqlite3_create_function = function f( + pDb, funcName, nArg, eTextRep, pApp, + xFunc, xStep, xFinal + ){ + return (f.length===arguments.length) + ? capi.sqlite3_create_function_v2(pDb, funcName, nArg, eTextRep, + pApp, xFunc, xStep, xFinal, 0) + : __dbArgcMismatch(pDb,"sqlite3_create_function",f.length); + }; + + + if( __sqlite3CreateWindowFunction ){ + capi.sqlite3_create_window_function = function f( + pDb, funcName, nArg, eTextRep, pApp, + xStep, + xFinal, + xValue, + xInverse, + xDestroy + ){ + if( f.length!==arguments.length ){ + return __dbArgcMismatch(pDb,"sqlite3_create_window_function",f.length); + }else if( 0 === (eTextRep & 0xf) ){ + eTextRep |= capi.SQLITE_UTF8; + }else if( capi.SQLITE_UTF8 !== (eTextRep & 0xf) ){ + return __errEncoding(pDb); + } + try{ + const rc = __sqlite3CreateWindowFunction(pDb, funcName, nArg, eTextRep, + pApp, xStep, xFinal, xValue, + xInverse, xDestroy); + if(0===rc && (xStep instanceof Function + || xFinal instanceof Function + || xValue instanceof Function + || xInverse instanceof Function + || xDestroy instanceof Function)){ + __dbCleanupMap.addWindowFunc(pDb, funcName, nArg); + } + return rc; + }catch(e){ + console.error("sqlite3_create_window_function() setup threw:",e); + return util.sqlite3__wasm_db_error(pDb, e, "Creation of UDF threw: "+e); + } + }; + }else{ + delete capi.sqlite3_create_window_function; + } + + capi.sqlite3_create_function_v2.udfSetResult = + capi.sqlite3_create_function.udfSetResult = capi.sqlite3_result_js; + if(capi.sqlite3_create_window_function){ + capi.sqlite3_create_window_function.udfSetResult = capi.sqlite3_result_js; + } + + + capi.sqlite3_create_function_v2.udfConvertArgs = + capi.sqlite3_create_function.udfConvertArgs = capi.sqlite3_values_to_js; + if(capi.sqlite3_create_window_function){ + capi.sqlite3_create_window_function.udfConvertArgs = capi.sqlite3_values_to_js; + } + + + capi.sqlite3_create_function_v2.udfSetError = + capi.sqlite3_create_function.udfSetError = capi.sqlite3_result_error_js; + if(capi.sqlite3_create_window_function){ + capi.sqlite3_create_window_function.udfSetError = capi.sqlite3_result_error_js; + } + + }; + + { + + + const __flexiString = (v,n)=>{ + if('string'===typeof v){ + n = -1; + }else if(util.isSQLableTypedArray(v)){ + n = v.byteLength; + v = wasm.typedArrayToString( + (v instanceof ArrayBuffer) ? new Uint8Array(v) : v + ); + }else if(Array.isArray(v)){ + v = v.join(""); + n = -1; + } + return [v, n]; + }; + + + const __prepare = { + + basic: wasm.xWrap('sqlite3_prepare_v3', + "int", ["sqlite3*", "string", + "int", + "int", "**", + "**"]), + + full: wasm.xWrap('sqlite3_prepare_v3', + "int", ["sqlite3*", "*", "int", "int", + "**", "**"]) + }; + + + capi.sqlite3_prepare_v3 = function f(pDb, sql, sqlLen, prepFlags, ppStmt, pzTail){ + if(f.length!==arguments.length){ + return __dbArgcMismatch(pDb,"sqlite3_prepare_v3",f.length); + } + const [xSql, xSqlLen] = __flexiString(sql, Number(sqlLen)); + switch(typeof xSql){ + case 'string': return __prepare.basic(pDb, xSql, xSqlLen, prepFlags, ppStmt, null); + case (typeof wasm.ptr.null): + return __prepare.full(pDb, wasm.ptr.coerce(xSql), xSqlLen, prepFlags, + ppStmt, pzTail); + default: + return util.sqlite3__wasm_db_error( + pDb, capi.SQLITE_MISUSE, + "Invalid SQL argument type for sqlite3_prepare_v2/v3(). typeof="+(typeof xSql) + ); + } + }; + + + capi.sqlite3_prepare_v2 = function f(pDb, sql, sqlLen, ppStmt, pzTail){ + return (f.length===arguments.length) + ? capi.sqlite3_prepare_v3(pDb, sql, sqlLen, 0, ppStmt, pzTail) + : __dbArgcMismatch(pDb,"sqlite3_prepare_v2",f.length); + }; + + } + + { + const __bindText = wasm.xWrap("sqlite3_bind_text", "int", [ + "sqlite3_stmt*", "int", "string", "int", "*" + ]); + const __bindBlob = wasm.xWrap("sqlite3_bind_blob", "int", [ + "sqlite3_stmt*", "int", "*", "int", "*" + ]); + + + capi.sqlite3_bind_text = function f(pStmt, iCol, text, nText, xDestroy){ + if(f.length!==arguments.length){ + return __dbArgcMismatch(capi.sqlite3_db_handle(pStmt), + "sqlite3_bind_text", f.length); + }else if(wasm.isPtr(text) || null===text){ + return __bindText(pStmt, iCol, text, nText, xDestroy); + }else if(text instanceof ArrayBuffer){ + text = new Uint8Array(text); + }else if(Array.isArray(pMem)){ + text = pMem.join(''); + } + let p, n; + try{ + if(util.isSQLableTypedArray(text)){ + p = wasm.allocFromTypedArray(text); + n = text.byteLength; + }else if('string'===typeof text){ + [p, n] = wasm.allocCString(text); + }else{ + return util.sqlite3__wasm_db_error( + capi.sqlite3_db_handle(pStmt), capi.SQLITE_MISUSE, + "Invalid 3rd argument type for sqlite3_bind_text()." + ); + } + return __bindText(pStmt, iCol, p, n, capi.SQLITE_WASM_DEALLOC); + }catch(e){ + wasm.dealloc(p); + return util.sqlite3__wasm_db_error( + capi.sqlite3_db_handle(pStmt), e + ); + } + }; + + + capi.sqlite3_bind_blob = function f(pStmt, iCol, pMem, nMem, xDestroy){ + if(f.length!==arguments.length){ + return __dbArgcMismatch(capi.sqlite3_db_handle(pStmt), + "sqlite3_bind_blob", f.length); + }else if(wasm.isPtr(pMem) || null===pMem){ + return __bindBlob(pStmt, iCol, pMem, nMem, xDestroy); + }else if(pMem instanceof ArrayBuffer){ + pMem = new Uint8Array(pMem); + }else if(Array.isArray(pMem)){ + pMem = pMem.join(''); + } + let p, n; + try{ + if(util.isBindableTypedArray(pMem)){ + p = wasm.allocFromTypedArray(pMem); + n = nMem>=0 ? nMem : pMem.byteLength; + }else if('string'===typeof pMem){ + [p, n] = wasm.allocCString(pMem); + }else{ + return util.sqlite3__wasm_db_error( + capi.sqlite3_db_handle(pStmt), capi.SQLITE_MISUSE, + "Invalid 3rd argument type for sqlite3_bind_blob()." + ); + } + return __bindBlob(pStmt, iCol, p, n, capi.SQLITE_WASM_DEALLOC); + }catch(e){ + wasm.dealloc(p); + return util.sqlite3__wasm_db_error( + capi.sqlite3_db_handle(pStmt), e + ); + } + }; + + } + + if(!capi.sqlite3_column_text){ + + const argStmt = wasm.xWrap.argAdapter('sqlite3_stmt*'), + argInt = wasm.xWrap.argAdapter('int'), + argValue = wasm.xWrap.argAdapter('sqlite3_value*'), + newStr = + (cstr,n)=>wasm.typedArrayToString(wasm.heap8u(), + Number(cstr), Number(cstr)+n) + capi.sqlite3_column_text = function(stmt, colIndex){ + const a0 = argStmt(stmt), a1 = argInt(colIndex); + const cstr = wasm.exports.sqlite3_column_text(a0, a1); + return cstr + ? newStr(cstr,wasm.exports.sqlite3_column_bytes(a0, a1)) + : null; + }; + capi.sqlite3_value_text = function(val){ + const a0 = argValue(val); + const cstr = wasm.exports.sqlite3_value_text(a0); + return cstr + ? newStr(cstr,wasm.exports.sqlite3_value_bytes(a0)) + : null; + }; + } + + { + + capi.sqlite3_config = function(op, ...args){ + if(arguments.length<2) return capi.SQLITE_MISUSE; + switch(op){ + case capi.SQLITE_CONFIG_COVERING_INDEX_SCAN: + case capi.SQLITE_CONFIG_MEMSTATUS: + case capi.SQLITE_CONFIG_SMALL_MALLOC: + case capi.SQLITE_CONFIG_SORTERREF_SIZE: + case capi.SQLITE_CONFIG_STMTJRNL_SPILL: + case capi.SQLITE_CONFIG_URI: + return wasm.exports.sqlite3__wasm_config_i(op, args[0]); + case capi.SQLITE_CONFIG_LOOKASIDE: + return wasm.exports.sqlite3__wasm_config_ii(op, args[0], args[1]); + case capi.SQLITE_CONFIG_MEMDB_MAXSIZE: + return wasm.exports.sqlite3__wasm_config_j(op, args[0]); + case capi.SQLITE_CONFIG_GETMALLOC: + case capi.SQLITE_CONFIG_GETMUTEX: + case capi.SQLITE_CONFIG_GETPCACHE2: + case capi.SQLITE_CONFIG_GETPCACHE: + case capi.SQLITE_CONFIG_HEAP: + case capi.SQLITE_CONFIG_LOG: + case capi.SQLITE_CONFIG_MALLOC: + case capi.SQLITE_CONFIG_MMAP_SIZE: + case capi.SQLITE_CONFIG_MULTITHREAD: + case capi.SQLITE_CONFIG_MUTEX: + case capi.SQLITE_CONFIG_PAGECACHE: + case capi.SQLITE_CONFIG_PCACHE2: + case capi.SQLITE_CONFIG_PCACHE: + case capi.SQLITE_CONFIG_PCACHE_HDRSZ: + case capi.SQLITE_CONFIG_PMASZ: + case capi.SQLITE_CONFIG_SERIALIZED: + case capi.SQLITE_CONFIG_SINGLETHREAD: + case capi.SQLITE_CONFIG_SQLLOG: + case capi.SQLITE_CONFIG_WIN32_HEAPSIZE: + default: + + return capi.SQLITE_NOTFOUND; + } + }; + } + + { + const __autoExtFptr = new Set; + + capi.sqlite3_auto_extension = function(fPtr){ + if( fPtr instanceof Function ){ + fPtr = wasm.installFunction('i(ppp)', fPtr); + }else if( 1!==arguments.length || !wasm.isPtr(fPtr) ){ + return capi.SQLITE_MISUSE; + } + const rc = wasm.exports.sqlite3_auto_extension(fPtr); + if( fPtr!==arguments[0] ){ + if(0===rc) __autoExtFptr.add(fPtr); + else wasm.uninstallFunction(fPtr); + } + return rc; + }; + + capi.sqlite3_cancel_auto_extension = function(fPtr){ + ; + if(!fPtr || 1!==arguments.length || !wasm.isPtr(fPtr)) return 0; + return wasm.exports.sqlite3_cancel_auto_extension(fPtr); + + }; + + capi.sqlite3_reset_auto_extension = function(){ + wasm.exports.sqlite3_reset_auto_extension(); + for(const fp of __autoExtFptr) wasm.uninstallFunction(fp); + __autoExtFptr.clear(); + }; + } + + + wasm.xWrap.FuncPtrAdapter.warnOnUse = true; + + const StructBinder = sqlite3.StructBinder + ; + + const installMethod = function callee( + tgt, name, func, applyArgcCheck = callee.installMethodArgcCheck + ){ + if(!(tgt instanceof StructBinder.StructType)){ + toss("Usage error: target object is-not-a StructType."); + }else if(!(func instanceof Function) && !wasm.isPtr(func)){ + toss("Usage error: expecting a Function or WASM pointer to one."); + } + if(1===arguments.length){ + return (n,f)=>callee(tgt, n, f, applyArgcCheck); + } + if(!callee.argcProxy){ + callee.argcProxy = function(tgt, funcName, func,sig){ + return function(...args){ + if(func.length!==arguments.length){ + toss("Argument mismatch for", + tgt.structInfo.name+"::"+funcName + +": Native signature is:",sig); + } + return func.apply(this, args); + } + }; + + callee.removeFuncList = function(){ + if(this.ondispose.__removeFuncList){ + this.ondispose.__removeFuncList.forEach( + (v,ndx)=>{ + if(wasm.isPtr(v)){ + try{wasm.uninstallFunction(v)} + catch(e){} + } + + } + ); + delete this.ondispose.__removeFuncList; + } + }; + } + const sigN = tgt.memberSignature(name); + if(sigN.length<2){ + toss("Member",name,"does not have a function pointer signature:",sigN); + } + const memKey = tgt.memberKey(name); + const fProxy = (applyArgcCheck && !wasm.isPtr(func)) + + ? callee.argcProxy(tgt, memKey, func, sigN) + : func; + if(wasm.isPtr(fProxy)){ + if(fProxy && !wasm.functionEntry(fProxy)){ + toss("Pointer",fProxy,"is not a WASM function table entry."); + } + tgt[memKey] = fProxy; + }else{ + const pFunc = wasm.installFunction(fProxy, sigN); + tgt[memKey] = pFunc; + if(!tgt.ondispose || !tgt.ondispose.__removeFuncList){ + tgt.addOnDispose('ondispose.__removeFuncList handler', + callee.removeFuncList); + tgt.ondispose.__removeFuncList = []; + } + tgt.ondispose.__removeFuncList.push(memKey, pFunc); + } + return (n,f)=>callee(tgt, n, f, applyArgcCheck); + }; + installMethod.installMethodArgcCheck = false; + + + const installMethods = function( + structInstance, methods, applyArgcCheck = installMethod.installMethodArgcCheck + ){ + const seen = new Map ; + for(const k of Object.keys(methods)){ + const m = methods[k]; + const prior = seen.get(m); + if(prior){ + const mkey = structInstance.memberKey(k); + structInstance[mkey] = structInstance[structInstance.memberKey(prior)]; + }else{ + installMethod(structInstance, k, m, applyArgcCheck); + seen.set(m, k); + } + } + return structInstance; + }; + + + StructBinder.StructType.prototype.installMethod = function callee( + name, func, applyArgcCheck = installMethod.installMethodArgcCheck + ){ + return (arguments.length < 3 && name && 'object'===typeof name) + ? installMethods(this, ...arguments) + : installMethod(this, ...arguments); + }; + + + StructBinder.StructType.prototype.installMethods = function( + methods, applyArgcCheck = installMethod.installMethodArgcCheck + ){ + return installMethods(this, methods, applyArgcCheck); + }; + +}); + +globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ + const toss3 = (...args)=>{throw new sqlite3.SQLite3Error(...args)}; + + const capi = sqlite3.capi, wasm = sqlite3.wasm, util = sqlite3.util; + + + const outWrapper = function(f){ + return (...args)=>f("sqlite3.oo1:",...args); + }; + + const debug = sqlite3.__isUnderTest + ? outWrapper(console.debug.bind(console)) + : outWrapper(sqlite3.config.debug); + const warn = sqlite3.__isUnderTest + ? outWrapper(console.warn.bind(console)) + : outWrapper(sqlite3.config.warn); + const error = sqlite3.__isUnderTest + ? outWrapper(console.error.bind(console)) + : outWrapper(sqlite3.config.error); + + + const __ptrMap = new WeakMap(); + + const __doesNotOwnHandle = new Set(); + + const __stmtMap = new WeakMap(); + + + const getOwnOption = (opts, p, dflt)=>{ + const d = Object.getOwnPropertyDescriptor(opts,p); + return d ? d.value : dflt; + }; + + + const checkSqlite3Rc = function(dbPtr, sqliteResultCode){ + if(sqliteResultCode){ + if(dbPtr instanceof DB) dbPtr = dbPtr.pointer; + toss3( + sqliteResultCode, + "sqlite3 result code",sqliteResultCode+":", + (dbPtr + ? capi.sqlite3_errmsg(dbPtr) + : capi.sqlite3_errstr(sqliteResultCode)) + ); + } + return arguments[0]; + }; + + + const __dbTraceToConsole = + wasm.installFunction('i(ippp)', function(t,c,p,x){ + if(capi.SQLITE_TRACE_STMT===t){ + + console.log("SQL TRACE #"+(++this.counter), + 'via sqlite3@'+c+'['+capi.sqlite3_db_filename(c,null)+']', + wasm.cstrToJs(x)); + } + }.bind({counter: 0})); + + + const __vfsPostOpenCallback = Object.create(null); + + + const byteArrayToHex = function(ba){ + if( ba instanceof ArrayBuffer ){ + ba = new Uint8Array(ba); + } + const li = []; + const digits = "0123456789abcdef"; + for( const d of ba ){ + li.push( digits[(d & 0xf0) >> 4], digits[d & 0x0f] ); + } + return li.join(''); + }; + + + const dbCtorApplySEEKey = function(db,opt){ + if( !capi.sqlite3_key_v2 ) return; + let keytype; + let key; + const check = (opt.key ? 1 : 0) + (opt.hexkey ? 1 : 0) + (opt.textkey ? 1 : 0); + if( !check ) return; + else if( check>1 ){ + toss3(capi.SQLITE_MISUSE, + "Only ONE of (key, hexkey, textkey) may be provided."); + } + if( opt.key ){ + + keytype = 'key'; + key = opt.key; + if('string'===typeof key){ + key = new TextEncoder('utf-8').encode(key); + } + if((key instanceof ArrayBuffer) || (key instanceof Uint8Array)){ + key = byteArrayToHex(key); + keytype = 'hexkey'; + }else{ + toss3(capi.SQLITE_MISUSE, + "Invalid value for the 'key' option. Expecting a string,", + "ArrayBuffer, or Uint8Array."); + return; + } + }else if( opt.textkey ){ + + keytype = 'textkey'; + key = opt.textkey; + if(key instanceof ArrayBuffer){ + key = new Uint8Array(key); + } + if(key instanceof Uint8Array){ + key = new TextDecoder('utf-8').decode(key); + }else if('string'!==typeof key){ + toss3(capi.SQLITE_MISUSE, + "Invalid value for the 'textkey' option. Expecting a string,", + "ArrayBuffer, or Uint8Array."); + } + }else if( opt.hexkey ){ + keytype = 'hexkey'; + key = opt.hexkey; + if((key instanceof ArrayBuffer) || (key instanceof Uint8Array)){ + key = byteArrayToHex(key); + }else if('string'!==typeof key){ + toss3(capi.SQLITE_MISUSE, + "Invalid value for the 'hexkey' option. Expecting a string,", + "ArrayBuffer, or Uint8Array."); + } + + }else{ + return; + } + let stmt; + try{ + stmt = db.prepare("PRAGMA "+keytype+"="+util.sqlite3__wasm_qfmt_token(key, 1)); + stmt.step(); + return true; + }finally{ + if(stmt) stmt.finalize(); + } + }; + + + const dbCtorHelper = function ctor(...args){ + const opt = ctor.normalizeArgs(...args); + + let pDb; + if( (pDb = opt['sqlite3*']) ){ + + + if( !opt['sqlite3*:takeOwnership'] ){ + + __doesNotOwnHandle.add(this); + } + this.filename = capi.sqlite3_db_filename(pDb,'main'); + }else{ + let fn = opt.filename, vfsName = opt.vfs, flagsStr = opt.flags; + if( ('string'!==typeof fn && !wasm.isPtr(fn)) + || 'string'!==typeof flagsStr + || (vfsName && ('string'!==typeof vfsName && !wasm.isPtr(vfsName))) ){ + sqlite3.config.error("Invalid DB ctor args",opt,arguments); + toss3("Invalid arguments for DB constructor:", arguments, "opts:", opt); + } + let oflags = 0; + if( flagsStr.indexOf('c')>=0 ){ + oflags |= capi.SQLITE_OPEN_CREATE | capi.SQLITE_OPEN_READWRITE; + } + if( flagsStr.indexOf('w')>=0 ) oflags |= capi.SQLITE_OPEN_READWRITE; + if( 0===oflags ) oflags |= capi.SQLITE_OPEN_READONLY; + oflags |= capi.SQLITE_OPEN_EXRESCODE; + const stack = wasm.pstack.pointer; + try { + const pPtr = wasm.pstack.allocPtr() ; + let rc = capi.sqlite3_open_v2(fn, pPtr, oflags, vfsName || wasm.ptr.null); + pDb = wasm.peekPtr(pPtr); + checkSqlite3Rc(pDb, rc); + capi.sqlite3_extended_result_codes(pDb, 1); + if(flagsStr.indexOf('t')>=0){ + capi.sqlite3_trace_v2(pDb, capi.SQLITE_TRACE_STMT, + __dbTraceToConsole, pDb); + } + }catch( e ){ + if( pDb ) capi.sqlite3_close_v2(pDb); + throw e; + }finally{ + wasm.pstack.restore(stack); + } + this.filename = + wasm.isPtr(fn) ? wasm.cstrToJs(fn) : fn; + + } + __ptrMap.set(this, pDb); + __stmtMap.set(this, Object.create(null)); + if( !opt['sqlite3*'] ){ + try{ + dbCtorApplySEEKey(this,opt); + + const pVfs = capi.sqlite3_js_db_vfs(pDb) + || toss3("Internal error: cannot get VFS for new db handle."); + const postInitSql = __vfsPostOpenCallback[pVfs]; + if(postInitSql){ + + if(postInitSql instanceof Function){ + postInitSql(this, sqlite3); + }else{ + checkSqlite3Rc( + pDb, capi.sqlite3_exec(pDb, postInitSql, 0, 0, 0) + ); + } + } + }catch(e){ + this.close(); + throw e; + } + } + }; + + + dbCtorHelper.setVfsPostOpenCallback = function(pVfs, callback){ + if( !(callback instanceof Function)){ + toss3("dbCtorHelper.setVfsPostOpenCallback() should not be used with "+ + "a non-function argument.",arguments); + } + __vfsPostOpenCallback[pVfs] = callback; + }; + + + dbCtorHelper.normalizeArgs = function(filename=':memory:',flags = 'c',vfs = null){ + const arg = {}; + if(1===arguments.length && arguments[0] && 'object'===typeof arguments[0]){ + Object.assign(arg, arguments[0]); + if(undefined===arg.flags) arg.flags = 'c'; + if(undefined===arg.vfs) arg.vfs = null; + if(undefined===arg.filename) arg.filename = ':memory:'; + }else{ + arg.filename = filename; + arg.flags = flags; + arg.vfs = vfs; + } + return arg; + }; + + const DB = function(...args){ + dbCtorHelper.apply(this, args); + }; + DB.dbCtorHelper = dbCtorHelper; + + + const BindTypes = { + null: 1, + number: 2, + string: 3, + boolean: 4, + blob: 5 + }; + if(wasm.bigIntEnabled){ + BindTypes.bigint = BindTypes.number; + } + + + const Stmt = function(){ + if(BindTypes!==arguments[2]){ + toss3(capi.SQLITE_MISUSE, "Do not call the Stmt constructor directly. Use DB.prepare()."); + } + this.db = arguments[0]; + __ptrMap.set(this, arguments[1]); + if( arguments.length>3 && !arguments[3] ){ + __doesNotOwnHandle.add(this); + } + }; + + + const affirmDbOpen = function(db){ + if(!db.pointer) toss3("DB has been closed."); + return db; + }; + + + const affirmColIndex = function(stmt,ndx){ + if((ndx !== (ndx|0)) || ndx<0 || ndx>=stmt.columnCount){ + toss3("Column index",ndx,"is out of range."); + } + return stmt; + }; + + + const parseExecArgs = function(db, args){ + const out = Object.create(null); + out.opt = Object.create(null); + switch(args.length){ + case 1: + if('string'===typeof args[0] || util.isSQLableTypedArray(args[0])){ + out.sql = args[0]; + }else if(Array.isArray(args[0])){ + out.sql = args[0]; + }else if(args[0] && 'object'===typeof args[0]){ + out.opt = args[0]; + out.sql = out.opt.sql; + } + break; + case 2: + out.sql = args[0]; + out.opt = args[1]; + break; + default: toss3("Invalid argument count for exec()."); + }; + out.sql = util.flexibleString(out.sql); + if('string'!==typeof out.sql){ + toss3("Missing SQL argument or unsupported SQL value type."); + } + const opt = out.opt; + switch(opt.returnValue){ + case 'resultRows': + if(!opt.resultRows) opt.resultRows = []; + out.returnVal = ()=>opt.resultRows; + break; + case 'saveSql': + if(!opt.saveSql) opt.saveSql = []; + out.returnVal = ()=>opt.saveSql; + break; + case undefined: + case 'this': + out.returnVal = ()=>db; + break; + default: + toss3("Invalid returnValue value:",opt.returnValue); + } + if(!opt.callback && !opt.returnValue && undefined!==opt.rowMode){ + if(!opt.resultRows) opt.resultRows = []; + out.returnVal = ()=>opt.resultRows; + } + if(opt.callback || opt.resultRows){ + switch((undefined===opt.rowMode) ? 'array' : opt.rowMode) { + case 'object': + out.cbArg = (stmt,cache)=>{ + if( !cache.columnNames ) cache.columnNames = stmt.getColumnNames([]); + + const row = stmt.get([]); + const rv = Object.create(null); + for( const i in cache.columnNames ) rv[cache.columnNames[i]] = row[i]; + return rv; + }; + break; + case 'array': out.cbArg = (stmt)=>stmt.get([]); break; + case 'stmt': + if(Array.isArray(opt.resultRows)){ + toss3("exec(): invalid rowMode for a resultRows array: must", + "be one of 'array', 'object',", + "a result column number, or column name reference."); + } + out.cbArg = (stmt)=>stmt; + break; + default: + if(util.isInt32(opt.rowMode)){ + out.cbArg = (stmt)=>stmt.get(opt.rowMode); + break; + }else if('string'===typeof opt.rowMode + && opt.rowMode.length>1 + && '$'===opt.rowMode[0]){ + + const $colName = opt.rowMode.substr(1); + out.cbArg = (stmt)=>{ + const rc = stmt.get(Object.create(null))[$colName]; + return (undefined===rc) + ? toss3(capi.SQLITE_NOTFOUND, + "exec(): unknown result column:",$colName) + : rc; + }; + break; + } + toss3("Invalid rowMode:",opt.rowMode); + } + } + return out; + }; + + + const __selectFirstRow = (db, sql, bind, ...getArgs)=>{ + const stmt = db.prepare(sql); + try { + const rc = stmt.bind(bind).step() ? stmt.get(...getArgs) : undefined; + stmt.reset(); + return rc; + }finally{ + stmt.finalize(); + } + }; + + + const __selectAll = + (db, sql, bind, rowMode)=>db.exec({ + sql, bind, rowMode, returnValue: 'resultRows' + }); + + + const __stmtGetColumn = (stmt, ndx, asType)=>{ + switch(undefined===asType + ? capi.sqlite3_column_type(stmt.pointer, ndx) + : asType){ + case capi.SQLITE_NULL: return null; + case capi.SQLITE_INTEGER:{ + if(wasm.bigIntEnabled){ + const rc = capi.sqlite3_column_int64(stmt.pointer, ndx); + if(rc>=Number.MIN_SAFE_INTEGER && rc<=Number.MAX_SAFE_INTEGER){ + return Number(rc).valueOf(); + } + return rc; + }else{ + const rc = capi.sqlite3_column_double(stmt.pointer, ndx); + if(rc>Number.MAX_SAFE_INTEGER || rccheckSqlite3Rc(db,resultCode); + + DB.prototype = { + + isOpen: function(){ + return !!this.pointer; + }, + + affirmOpen: function(){ + return affirmDbOpen(this); + }, + + close: function(){ + const pDb = this.pointer; + if(pDb){ + if(this.onclose?.before instanceof Function){ + try{this.onclose.before(this)} + catch(e){} + } + for(const s of Object.values(__stmtMap.get(this))){ + if(s?.pointer){ + try{s.finalize()} + catch(ex){} + } + } + __ptrMap.delete(this); + __stmtMap.delete(this); + if( !__doesNotOwnHandle.delete(this) ){ + capi.sqlite3_close_v2(pDb); + } + if(this.onclose?.after instanceof Function){ + try{this.onclose.after(this)} + catch(e){} + } + delete this.filename; + } + }, + + changes: function(total=false,sixtyFour=false){ + const p = affirmDbOpen(this).pointer; + if(total){ + return sixtyFour + ? capi.sqlite3_total_changes64(p) + : capi.sqlite3_total_changes(p); + }else{ + return sixtyFour + ? capi.sqlite3_changes64(p) + : capi.sqlite3_changes(p); + } + }, + + dbFilename: function(dbName='main'){ + return capi.sqlite3_db_filename(affirmDbOpen(this).pointer, dbName); + }, + + dbName: function(dbNumber=0){ + return capi.sqlite3_db_name(affirmDbOpen(this).pointer, dbNumber); + }, + + dbVfsName: function(dbName=0){ + let rc; + const pVfs = capi.sqlite3_js_db_vfs( + affirmDbOpen(this).pointer, dbName + ); + if(pVfs){ + const v = new capi.sqlite3_vfs(pVfs); + try{ rc = wasm.cstrToJs(v.$zName) } + finally { v.dispose() } + } + return rc; + }, + + prepare: function(sql){ + affirmDbOpen(this); + const stack = wasm.pstack.pointer; + let ppStmt, pStmt; + try{ + ppStmt = wasm.pstack.alloc(8); + DB.checkRc(this, capi.sqlite3_prepare_v2(this.pointer, sql, -1, ppStmt, null)); + pStmt = wasm.peekPtr(ppStmt); + } + finally { + wasm.pstack.restore(stack); + } + if(!pStmt) toss3("Cannot prepare empty SQL."); + const stmt = new Stmt(this, pStmt, BindTypes); + __stmtMap.get(this)[pStmt] = stmt; + return stmt; + }, + + exec: function(){ + affirmDbOpen(this); + const arg = parseExecArgs(this, arguments); + if(!arg.sql){ + return toss3("exec() requires an SQL string."); + } + const opt = arg.opt; + const callback = opt.callback; + const resultRows = + Array.isArray(opt.resultRows) ? opt.resultRows : undefined; + let stmt; + let bind = opt.bind; + let evalFirstResult = !!( + arg.cbArg || opt.columnNames || resultRows + ) ; + const stack = wasm.scopedAllocPush(); + const saveSql = Array.isArray(opt.saveSql) ? opt.saveSql : undefined; + try{ + const isTA = util.isSQLableTypedArray(arg.sql) + ; + + let sqlByteLen = isTA ? arg.sql.byteLength : wasm.jstrlen(arg.sql); + const ppStmt = wasm.scopedAlloc( + + (2 * wasm.ptr.size) + (sqlByteLen + 1) + ); + const pzTail = wasm.ptr.add(ppStmt, wasm.ptr.size) ; + let pSql = wasm.ptr.add(pzTail, wasm.ptr.size); + const pSqlEnd = wasm.ptr.add(pSql, sqlByteLen); + if(isTA) wasm.heap8().set(arg.sql, pSql); + else wasm.jstrcpy(arg.sql, wasm.heap8(), pSql, sqlByteLen, false); + wasm.poke8(wasm.ptr.add(pSql, sqlByteLen), 0); + while(pSql && wasm.peek8(pSql) + ){ + wasm.pokePtr([ppStmt, pzTail], 0); + DB.checkRc(this, capi.sqlite3_prepare_v3( + this.pointer, pSql, sqlByteLen, 0, ppStmt, pzTail + )); + const pStmt = wasm.peekPtr(ppStmt); + pSql = wasm.peekPtr(pzTail); + sqlByteLen = Number(wasm.ptr.add(pSqlEnd,-pSql)); + if(!pStmt) continue; + + if(saveSql) saveSql.push(capi.sqlite3_sql(pStmt).trim()); + stmt = new Stmt(this, pStmt, BindTypes); + if(bind && stmt.parameterCount){ + stmt.bind(bind); + bind = null; + } + if(evalFirstResult && stmt.columnCount){ + + let gotColNames = Array.isArray( + opt.columnNames + ) ? 0 : 1; + evalFirstResult = false; + if(arg.cbArg || resultRows){ + const cbArgCache = Object.create(null) + ; + for( ; stmt.step(); __execLock.delete(stmt) ){ + if(0===gotColNames++){ + stmt.getColumnNames(cbArgCache.columnNames = (opt.columnNames || [])); + } + __execLock.add(stmt); + const row = arg.cbArg(stmt,cbArgCache); + if(resultRows) resultRows.push(row); + if(callback && false === callback.call(opt, row, stmt)){ + break; + } + } + __execLock.delete(stmt); + } + if(0===gotColNames){ + + stmt.getColumnNames(opt.columnNames); + } + }else{ + stmt.step(); + } + stmt.reset( + ).finalize(); + stmt = null; + } + }finally{ + if(stmt){ + __execLock.delete(stmt); + stmt.finalize(); + } + wasm.scopedAllocPop(stack); + } + return arg.returnVal(); + }, + + + + createFunction: function f(name, xFunc, opt){ + const isFunc = (f)=>(f instanceof Function); + switch(arguments.length){ + case 1: + opt = name; + name = opt.name; + xFunc = opt.xFunc || 0; + break; + case 2: + if(!isFunc(xFunc)){ + opt = xFunc; + xFunc = opt.xFunc || 0; + } + break; + case 3: + break; + default: break; + } + if(!opt) opt = {}; + if('string' !== typeof name){ + toss3("Invalid arguments: missing function name."); + } + let xStep = opt.xStep || 0; + let xFinal = opt.xFinal || 0; + const xValue = opt.xValue || 0; + const xInverse = opt.xInverse || 0; + let isWindow = undefined; + if(isFunc(xFunc)){ + isWindow = false; + if(isFunc(xStep) || isFunc(xFinal)){ + toss3("Ambiguous arguments: scalar or aggregate?"); + } + xStep = xFinal = null; + }else if(isFunc(xStep)){ + if(!isFunc(xFinal)){ + toss3("Missing xFinal() callback for aggregate or window UDF."); + } + xFunc = null; + }else if(isFunc(xFinal)){ + toss3("Missing xStep() callback for aggregate or window UDF."); + }else{ + toss3("Missing function-type properties."); + } + if(false === isWindow){ + if(isFunc(xValue) || isFunc(xInverse)){ + toss3("xValue and xInverse are not permitted for non-window UDFs."); + } + }else if(isFunc(xValue)){ + if(!isFunc(xInverse)){ + toss3("xInverse must be provided if xValue is."); + } + isWindow = true; + }else if(isFunc(xInverse)){ + toss3("xValue must be provided if xInverse is."); + } + const pApp = opt.pApp; + if( undefined!==pApp + && null!==pApp + && !wasm.isPtr(pApp) ){ + toss3("Invalid value for pApp property. Must be a legal WASM pointer value."); + } + const xDestroy = opt.xDestroy || 0; + if(xDestroy && !isFunc(xDestroy)){ + toss3("xDestroy property must be a function."); + } + let fFlags = 0 ; + if(getOwnOption(opt, 'deterministic')) fFlags |= capi.SQLITE_DETERMINISTIC; + if(getOwnOption(opt, 'directOnly')) fFlags |= capi.SQLITE_DIRECTONLY; + if(getOwnOption(opt, 'innocuous')) fFlags |= capi.SQLITE_INNOCUOUS; + name = name.toLowerCase(); + const xArity = xFunc || xStep; + const arity = getOwnOption(opt, 'arity'); + const arityArg = ('number'===typeof arity + ? arity + : (xArity.length ? xArity.length-1 : 0)); + let rc; + if( isWindow ){ + rc = capi.sqlite3_create_window_function( + this.pointer, name, arityArg, + capi.SQLITE_UTF8 | fFlags, pApp || 0, + xStep, xFinal, xValue, xInverse, xDestroy); + }else{ + rc = capi.sqlite3_create_function_v2( + this.pointer, name, arityArg, + capi.SQLITE_UTF8 | fFlags, pApp || 0, + xFunc, xStep, xFinal, xDestroy); + } + DB.checkRc(this, rc); + return this; + }, + + selectValue: function(sql,bind,asType){ + return __selectFirstRow(this, sql, bind, 0, asType); + }, + + + selectValues: function(sql,bind,asType){ + const stmt = this.prepare(sql), rc = []; + try { + affirmColIndex(stmt, 0); + stmt.bind(bind); + while(stmt.step()) rc.push( + __stmtGetColumn(stmt, 0, asType) + ); + stmt.reset(); + }finally{ + stmt.finalize(); + } + return rc; + }, + + + selectArray: function(sql,bind){ + return __selectFirstRow(this, sql, bind, []); + }, + + + selectObject: function(sql,bind){ + return __selectFirstRow(this, sql, bind, {}); + }, + + + selectArrays: function(sql,bind){ + return __selectAll(this, sql, bind, 'array'); + }, + + + selectObjects: function(sql,bind){ + return __selectAll(this, sql, bind, 'object'); + }, + + + openStatementCount: function(){ + return this.pointer ? Object.keys(__stmtMap.get(this)).length : 0; + }, + + + transaction: function(callback){ + let opener = 'BEGIN'; + if(arguments.length>1){ + if(/[^a-zA-Z]/.test(arguments[0])){ + toss3(capi.SQLITE_MISUSE, "Invalid argument for BEGIN qualifier."); + } + opener += ' '+arguments[0]; + callback = arguments[1]; + } + affirmDbOpen(this).exec(opener); + try { + const rc = callback(this); + this.exec("COMMIT"); + return rc; + }catch(e){ + this.exec("ROLLBACK"); + throw e; + } + }, + + + savepoint: function(callback){ + affirmDbOpen(this).exec("SAVEPOINT oo1"); + try { + const rc = callback(this); + this.exec("RELEASE oo1"); + return rc; + }catch(e){ + this.exec("ROLLBACK to SAVEPOINT oo1; RELEASE SAVEPOINT oo1"); + throw e; + } + }, + + + checkRc: function(resultCode){ + return checkSqlite3Rc(this, resultCode); + }, + }; + + + DB.wrapHandle = function(pDb, takeOwnership=false){ + if( !pDb || !wasm.isPtr(pDb) ){ + throw new sqlite3.SQLite3Error(capi.SQLITE_MISUSE, + "Argument must be a WASM sqlite3 pointer"); + } + return new DB({ + + "sqlite3*": pDb, + "sqlite3*:takeOwnership": !!takeOwnership + }); + }; + + + const affirmStmtOpen = function(stmt){ + if(!stmt.pointer) toss3("Stmt has been closed."); + return stmt; + }; + + + const isSupportedBindType = function(v){ + let t = BindTypes[(null===v||undefined===v) ? 'null' : typeof v]; + switch(t){ + case BindTypes.boolean: + case BindTypes.null: + case BindTypes.number: + case BindTypes.string: + return t; + case BindTypes.bigint: + return wasm.bigIntEnabled ? t : undefined; + default: + return util.isBindableTypedArray(v) ? BindTypes.blob : undefined; + } + }; + + + const affirmSupportedBindType = function(v){ + + return isSupportedBindType(v) || toss3("Unsupported bind() argument type:",typeof v); + }; + + + const affirmParamIndex = function(stmt,key){ + const n = ('number'===typeof key) + ? key : capi.sqlite3_bind_parameter_index(stmt.pointer, key); + if( 0===n || !util.isInt32(n) ) toss3("Invalid bind() parameter name: "+key); + else if( n<1 || n>stmt.parameterCount ) toss3("Bind index",key,"is out of range."); + return n; + }; + + + const __execLock = new Set(); + + const __stmtMayGet = new Set(); + + + const affirmNotLockedByExec = function(stmt,currentOpName){ + if(__execLock.has(stmt)){ + toss3("Operation is illegal when statement is locked:",currentOpName); + } + return stmt; + }; + + + const bindOne = function f(stmt,ndx,bindType,val){ + affirmNotLockedByExec(affirmStmtOpen(stmt), 'bind()'); + if(!f._){ + f._tooBigInt = (v)=>toss3( + "BigInt value is too big to store without precision loss:", v + ); + f._ = { + string: function(stmt, ndx, val, asBlob){ + const [pStr, n] = wasm.allocCString(val, true); + const f = asBlob ? capi.sqlite3_bind_blob : capi.sqlite3_bind_text; + return f(stmt.pointer, ndx, pStr, n, capi.SQLITE_WASM_DEALLOC); + } + }; + } + affirmSupportedBindType(val); + ndx = affirmParamIndex(stmt,ndx); + let rc = 0; + switch((null===val || undefined===val) ? BindTypes.null : bindType){ + case BindTypes.null: + rc = capi.sqlite3_bind_null(stmt.pointer, ndx); + break; + case BindTypes.string: + rc = f._.string(stmt, ndx, val, false); + break; + case BindTypes.number: { + let m; + if(util.isInt32(val)) m = capi.sqlite3_bind_int; + else if('bigint'===typeof val){ + if(!util.bigIntFits64(val)){ + f._tooBigInt(val); + }else if(wasm.bigIntEnabled){ + m = capi.sqlite3_bind_int64; + }else if(util.bigIntFitsDouble(val)){ + val = Number(val); + m = capi.sqlite3_bind_double; + }else{ + f._tooBigInt(val); + } + }else{ + val = Number(val); + if(wasm.bigIntEnabled && Number.isInteger(val)){ + m = capi.sqlite3_bind_int64; + }else{ + m = capi.sqlite3_bind_double; + } + } + rc = m(stmt.pointer, ndx, val); + break; + } + case BindTypes.boolean: + rc = capi.sqlite3_bind_int(stmt.pointer, ndx, val ? 1 : 0); + break; + case BindTypes.blob: { + if('string'===typeof val){ + rc = f._.string(stmt, ndx, val, true); + break; + }else if(val instanceof ArrayBuffer){ + val = new Uint8Array(val); + }else if(!util.isBindableTypedArray(val)){ + toss3("Binding a value as a blob requires", + "that it be a string, Uint8Array, Int8Array, or ArrayBuffer."); + } + const pBlob = wasm.alloc(val.byteLength || 1); + wasm.heap8().set(val.byteLength ? val : [0], Number(pBlob)) + rc = capi.sqlite3_bind_blob(stmt.pointer, ndx, pBlob, val.byteLength, + capi.SQLITE_WASM_DEALLOC); + break; + } + default: + sqlite3.config.warn("Unsupported bind() argument type:",val); + toss3("Unsupported bind() argument type: "+(typeof val)); + } + if(rc) DB.checkRc(stmt.db.pointer, rc); + return stmt; + }; + + Stmt.prototype = { + + finalize: function(){ + const ptr = this.pointer; + if(ptr){ + affirmNotLockedByExec(this,'finalize()'); + const rc = (__doesNotOwnHandle.delete(this) + ? 0 + : capi.sqlite3_finalize(ptr)); + delete __stmtMap.get(this.db)[ptr]; + __ptrMap.delete(this); + __execLock.delete(this); + __stmtMayGet.delete(this); + delete this.parameterCount; + delete this.db; + return rc; + } + }, + + clearBindings: function(){ + affirmNotLockedByExec(affirmStmtOpen(this), 'clearBindings()') + capi.sqlite3_clear_bindings(this.pointer); + __stmtMayGet.delete(this); + return this; + }, + + reset: function(alsoClearBinds){ + affirmNotLockedByExec(this,'reset()'); + if(alsoClearBinds) this.clearBindings(); + const rc = capi.sqlite3_reset(affirmStmtOpen(this).pointer); + __stmtMayGet.delete(this); + checkSqlite3Rc(this.db, rc); + return this; + }, + + + resetNoThrow: function(alsoClearBinds){ + affirmNotLockedByExec(this,'reset()'); + if(alsoClearBinds) this.clearBindings(); + const rc = capi.sqlite3_reset(affirmStmtOpen(this).pointer); + __stmtMayGet.delete(this); + return rc; + }, + + + bind: function(){ + affirmStmtOpen(this); + let ndx, arg; + switch(arguments.length){ + case 1: ndx = 1; arg = arguments[0]; break; + case 2: ndx = arguments[0]; arg = arguments[1]; break; + default: toss3("Invalid bind() arguments."); + } + if(undefined===arg){ + + return this; + }else if(!this.parameterCount){ + toss3("This statement has no bindable parameters."); + } + __stmtMayGet.delete(this); + if(null===arg){ + + return bindOne(this, ndx, BindTypes.null, arg); + } + else if(Array.isArray(arg)){ + + if(1!==arguments.length){ + toss3("When binding an array, an index argument is not permitted."); + } + arg.forEach((v,i)=>bindOne(this, i+1, affirmSupportedBindType(v), v)); + return this; + }else if(arg instanceof ArrayBuffer){ + arg = new Uint8Array(arg); + } + if('object'===typeof arg + && !util.isBindableTypedArray(arg)){ + + if(1!==arguments.length){ + toss3("When binding an object, an index argument is not permitted."); + } + Object.keys(arg) + .forEach(k=>bindOne(this, k, + affirmSupportedBindType(arg[k]), + arg[k])); + return this; + }else{ + return bindOne(this, ndx, affirmSupportedBindType(arg), arg); + } + toss3("Should not reach this point."); + }, + + bindAsBlob: function(ndx,arg){ + affirmStmtOpen(this); + if(1===arguments.length){ + arg = ndx; + ndx = 1; + } + const t = affirmSupportedBindType(arg); + if(BindTypes.string !== t && BindTypes.blob !== t + && BindTypes.null !== t){ + toss3("Invalid value type for bindAsBlob()"); + } + return bindOne(this, ndx, BindTypes.blob, arg); + }, + + step: function(){ + affirmNotLockedByExec(this, 'step()'); + const rc = capi.sqlite3_step(affirmStmtOpen(this).pointer); + switch(rc){ + case capi.SQLITE_DONE: + __stmtMayGet.delete(this); + return false; + case capi.SQLITE_ROW: + __stmtMayGet.add(this); + return true; + default: + __stmtMayGet.delete(this); + sqlite3.config.warn("sqlite3_step() rc=",rc, + capi.sqlite3_js_rc_str(rc), + "SQL =", capi.sqlite3_sql(this.pointer)); + DB.checkRc(this.db.pointer, rc); + } + }, + + stepReset: function(){ + this.step(); + return this.reset(); + }, + + stepFinalize: function(){ + try{ + const rc = this.step(); + this.reset(); + return rc; + }finally{ + try{this.finalize()} + catch(e){} + } + }, + + + get: function(ndx,asType){ + if(!__stmtMayGet.has(affirmStmtOpen(this))){ + toss3("Stmt.step() has not (recently) returned true."); + } + if(Array.isArray(ndx)){ + let i = 0; + const n = this.columnCount; + while(itoss3("The pointer property is read-only.") + } + Object.defineProperty(Stmt.prototype, 'pointer', prop); + Object.defineProperty(DB.prototype, 'pointer', prop); + } + + Object.defineProperty(Stmt.prototype, 'columnCount', { + enumerable: false, + get: function(){return capi.sqlite3_column_count(this.pointer)}, + set: ()=>toss3("The columnCount property is read-only.") + }); + + Object.defineProperty(Stmt.prototype, 'parameterCount', { + enumerable: false, + get: function(){return capi.sqlite3_bind_parameter_count(this.pointer)}, + set: ()=>toss3("The parameterCount property is read-only.") + }); + + + Stmt.wrapHandle = function(oo1db, pStmt, takeOwnership=false){ + let ctor = Stmt; + if( !(oo1db instanceof DB) || !oo1db.pointer ){ + throw new sqlite3.SQLite3Error(sqlite3.SQLITE_MISUSE, + "First argument must be an opened "+ + "sqlite3.oo1.DB instance"); + } + if( !pStmt || !wasm.isPtr(pStmt) ){ + throw new sqlite3.SQLite3Error(sqlite3.SQLITE_MISUSE, + "Second argument must be a WASM "+ + "sqlite3_stmt pointer"); + } + return new Stmt(oo1db, pStmt, BindTypes, !!takeOwnership); + } + + + sqlite3.oo1 = { + DB, + Stmt + }; + +}); + + + +globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ +const util = sqlite3.util; +sqlite3.initWorker1API = function(){ + 'use strict'; + const toss = (...args)=>{throw new Error(args.join(' '))}; + if(!(globalThis.WorkerGlobalScope instanceof Function)){ + toss("initWorker1API() must be run from a Worker thread."); + } + const sqlite3 = this.sqlite3 || toss("Missing this.sqlite3 object."); + const DB = sqlite3.oo1.DB; + + + const getDbId = function(db){ + let id = wState.idMap.get(db); + if(id) return id; + id = 'db#'+(++wState.idSeq)+':'+ + Math.floor(Math.random() * 100000000)+':'+ + Math.floor(Math.random() * 100000000); + + wState.idMap.set(db, id); + return id; + }; + + + const wState = { + + dbList: [], + + idSeq: 0, + + idMap: new WeakMap, + + xfer: [], + open: function(opt){ + const db = new DB(opt); + this.dbs[getDbId(db)] = db; + if(this.dbList.indexOf(db)<0) this.dbList.push(db); + return db; + }, + close: function(db,alsoUnlink){ + if(db){ + delete this.dbs[getDbId(db)]; + const filename = db.filename; + const pVfs = util.sqlite3__wasm_db_vfs(db.pointer, 0); + db.close(); + const ddNdx = this.dbList.indexOf(db); + if(ddNdx>=0) this.dbList.splice(ddNdx, 1); + if(alsoUnlink && filename && pVfs){ + util.sqlite3__wasm_vfs_unlink(pVfs, filename); + } + } + }, + + post: function(msg,xferList){ + if(xferList && xferList.length){ + globalThis.postMessage( msg, Array.from(xferList) ); + xferList.length = 0; + }else{ + globalThis.postMessage(msg); + } + }, + + dbs: Object.create(null), + + getDb: function(id,require=true){ + return this.dbs[id] + || (require ? toss("Unknown (or closed) DB ID:",id) : undefined); + } + }; + + + const affirmDbOpen = function(db = wState.dbList[0]){ + return (db && db.pointer) ? db : toss("DB is not opened."); + }; + + + const getMsgDb = function(msgData,affirmExists=true){ + const db = wState.getDb(msgData.dbId,false) || wState.dbList[0]; + return affirmExists ? affirmDbOpen(db) : db; + }; + + const getDefaultDbId = function(){ + return wState.dbList[0] && getDbId(wState.dbList[0]); + }; + + const isSpecialDbFilename = (n)=>{ + return ""===n || ':'===n[0]; + }; + + + const wMsgHandler = { + open: function(ev){ + const oargs = Object.create(null), args = (ev.args || Object.create(null)); + if(args.simulateError){ + toss("Throwing because of simulateError flag."); + } + const rc = Object.create(null); + oargs.vfs = args.vfs; + oargs.filename = args.filename || ""; + const db = wState.open(oargs); + rc.filename = db.filename; + rc.persistent = !!sqlite3.capi.sqlite3_js_db_uses_vfs(db.pointer, "opfs"); + rc.dbId = getDbId(db); + rc.vfs = db.dbVfsName(); + return rc; + }, + + close: function(ev){ + const db = getMsgDb(ev,false); + const response = { + filename: db && db.filename + }; + if(db){ + const doUnlink = ((ev.args && 'object'===typeof ev.args) + ? !!ev.args.unlink : false); + wState.close(db, doUnlink); + } + return response; + }, + + exec: function(ev){ + const rc = ( + 'string'===typeof ev.args + ) ? {sql: ev.args} : (ev.args || Object.create(null)); + if('stmt'===rc.rowMode){ + toss("Invalid rowMode for 'exec': stmt mode", + "does not work in the Worker API."); + }else if(!rc.sql){ + toss("'exec' requires input SQL."); + } + const db = getMsgDb(ev); + if(rc.callback || Array.isArray(rc.resultRows)){ + + db._blobXfer = wState.xfer; + } + const theCallback = rc.callback; + let rowNumber = 0; + const hadColNames = !!rc.columnNames; + if('string' === typeof theCallback){ + if(!hadColNames) rc.columnNames = []; + + rc.callback = function(row,stmt){ + wState.post({ + type: theCallback, + columnNames: rc.columnNames, + rowNumber: ++rowNumber, + row: row + }, wState.xfer); + } + } + try { + const changeCount = !!rc.countChanges + ? db.changes(true,(64===rc.countChanges)) + : undefined; + db.exec(rc); + if(undefined !== changeCount){ + rc.changeCount = db.changes(true,64===rc.countChanges) - changeCount; + } + const lastInsertRowId = !!rc.lastInsertRowId + ? sqlite3.capi.sqlite3_last_insert_rowid(db) + : undefined; + if( undefined!==lastInsertRowId ){ + rc.lastInsertRowId = lastInsertRowId; + } + if(rc.callback instanceof Function){ + rc.callback = theCallback; + + wState.post({ + type: theCallback, + columnNames: rc.columnNames, + rowNumber: null , + row: undefined + }); + } + }finally{ + delete db._blobXfer; + if(rc.callback) rc.callback = theCallback; + } + return rc; + }, + + 'config-get': function(){ + const rc = Object.create(null), src = sqlite3.config; + [ + 'bigIntEnabled' + ].forEach(function(k){ + if(Object.getOwnPropertyDescriptor(src, k)) rc[k] = src[k]; + }); + rc.version = sqlite3.version; + rc.vfsList = sqlite3.capi.sqlite3_js_vfs_list(); + return rc; + }, + + + export: function(ev){ + const db = getMsgDb(ev); + const response = { + byteArray: sqlite3.capi.sqlite3_js_db_export(db.pointer), + filename: db.filename, + mimetype: 'application/x-sqlite3' + }; + wState.xfer.push(response.byteArray.buffer); + return response; + }, + + toss: function(ev){ + toss("Testing worker exception"); + } + }; + + globalThis.onmessage = async function(ev){ + ev = ev.data; + let result, dbId = ev.dbId, evType = ev.type; + const arrivalTime = performance.now(); + try { + if(wMsgHandler.hasOwnProperty(evType) && + wMsgHandler[evType] instanceof Function){ + result = await wMsgHandler[evType](ev); + }else{ + toss("Unknown db worker message type:",ev.type); + } + }catch(err){ + evType = 'error'; + result = { + operation: ev.type, + message: err.message, + errorClass: err.name, + input: ev + }; + if(err.stack){ + result.stack = ('string'===typeof err.stack) + ? err.stack.split(/\n\s*/) : err.stack; + } + if(0) sqlite3.config.warn("Worker is propagating an exception to main thread.", + "Reporting it _here_ for the stack trace:",err,result); + } + if(!dbId){ + dbId = result.dbId + || getDefaultDbId(); + } + + + wState.post({ + type: evType, + dbId: dbId, + messageId: ev.messageId, + workerReceivedTime: arrivalTime, + workerRespondTime: performance.now(), + departureTime: ev.departureTime, + + + + + + + result: result + }, wState.xfer); + }; + globalThis.postMessage({type:'sqlite3-api',result:'worker1-ready'}); +}.bind({sqlite3}); +}); + + + +'use strict'; +globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ + const wasm = sqlite3.wasm, capi = sqlite3.capi, toss = sqlite3.util.toss3; + const vfs = Object.create(null); + sqlite3.vfs = vfs; + + + capi.sqlite3_vfs.prototype.registerVfs = function(asDefault=false){ + if(!(this instanceof sqlite3.capi.sqlite3_vfs)){ + toss("Expecting a sqlite3_vfs-type argument."); + } + const rc = capi.sqlite3_vfs_register(this, asDefault ? 1 : 0); + if(rc){ + toss("sqlite3_vfs_register(",this,") failed with rc",rc); + } + if(this.pointer !== capi.sqlite3_vfs_find(this.$zName)){ + toss("BUG: sqlite3_vfs_find(vfs.$zName) failed for just-installed VFS", + this); + } + return this; + }; + + + vfs.installVfs = function(opt){ + let count = 0; + const propList = ['io','vfs']; + for(const key of propList){ + const o = opt[key]; + if(o){ + ++count; + o.struct.installMethods(o.methods, !!o.applyArgcCheck); + if('vfs'===key){ + if(!o.struct.$zName && 'string'===typeof o.name){ + o.struct.addOnDispose( + o.struct.$zName = wasm.allocCString(o.name) + ); + } + o.struct.registerVfs(!!o.asDefault); + } + } + } + if(!count) toss("Misuse: installVfs() options object requires at least", + "one of:", propList); + return this; + }; +}); + + + +'use strict'; +globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ + if( !sqlite3.wasm.exports.sqlite3_declare_vtab ){ + return; + } + const wasm = sqlite3.wasm, capi = sqlite3.capi, toss = sqlite3.util.toss3; + const vtab = Object.create(null); + sqlite3.vtab = vtab; + + const sii = capi.sqlite3_index_info; + + sii.prototype.nthConstraint = function(n, asPtr=false){ + if(n<0 || n>=this.$nConstraint) return false; + const ptr = wasm.ptr.add( + this.$aConstraint, + sii.sqlite3_index_constraint.structInfo.sizeof * n + ); + return asPtr ? ptr : new sii.sqlite3_index_constraint(ptr); + }; + + + sii.prototype.nthConstraintUsage = function(n, asPtr=false){ + if(n<0 || n>=this.$nConstraint) return false; + const ptr = wasm.ptr.add( + this.$aConstraintUsage, + sii.sqlite3_index_constraint_usage.structInfo.sizeof * n + ); + return asPtr ? ptr : new sii.sqlite3_index_constraint_usage(ptr); + }; + + + sii.prototype.nthOrderBy = function(n, asPtr=false){ + if(n<0 || n>=this.$nOrderBy) return false; + const ptr = wasm.ptr.add( + this.$aOrderBy, + sii.sqlite3_index_orderby.structInfo.sizeof * n + ); + return asPtr ? ptr : new sii.sqlite3_index_orderby(ptr); + }; + + + const __xWrapFactory = function(methodName,StructType){ + + return function(ptr,removeMapping=false){ + if(0===arguments.length) ptr = new StructType; + if(ptr instanceof StructType){ + + this.set(ptr.pointer, ptr); + return ptr; + }else if(!wasm.isPtr(ptr)){ + sqlite3.SQLite3Error.toss("Invalid argument to",methodName+"()"); + } + let rc = this.get(ptr); + if(removeMapping) this.delete(ptr); + return rc; + }.bind(new Map); + }; + + + const StructPtrMapper = function(name, StructType){ + const __xWrap = __xWrapFactory(name,StructType); + + return Object.assign(Object.create(null),{ + + StructType, + + create: (ppOut)=>{ + const rc = __xWrap(); + wasm.pokePtr(ppOut, rc.pointer); + return rc; + }, + + get: (pCObj)=>__xWrap(pCObj), + + unget: (pCObj)=>__xWrap(pCObj,true), + + dispose: (pCObj)=>__xWrap(pCObj,true)?.dispose?.() + }); + }; + + + vtab.xVtab = StructPtrMapper('xVtab', capi.sqlite3_vtab); + + + vtab.xCursor = StructPtrMapper('xCursor', capi.sqlite3_vtab_cursor); + + + vtab.xIndexInfo = (pIdxInfo)=>new capi.sqlite3_index_info(pIdxInfo); + + + vtab.xError = function f(methodName, err, defaultRc){ + if(f.errorReporter instanceof Function){ + try{f.errorReporter("sqlite3_module::"+methodName+"(): "+err.message);} + catch(e){} + } + let rc; + if(err instanceof sqlite3.WasmAllocError) rc = capi.SQLITE_NOMEM; + else if(arguments.length>2) rc = defaultRc; + else if(err instanceof sqlite3.SQLite3Error) rc = err.resultCode; + return rc || capi.SQLITE_ERROR; + }; + + vtab.xError.errorReporter = 1 ? sqlite3.config.error.bind(sqlite3.config) : false; + + + vtab.xRowid = (ppRowid64, value)=>wasm.poke(ppRowid64, value, 'i64'); + + + vtab.setupModule = function(opt){ + let createdMod = false; + const mod = (this instanceof capi.sqlite3_module) + ? this : (opt.struct || (createdMod = new capi.sqlite3_module())); + try{ + const methods = opt.methods || toss("Missing 'methods' object."); + for(const e of Object.entries({ + + + xConnect: 'xCreate', xDisconnect: 'xDestroy' + })){ + + const k = e[0], v = e[1]; + if(true === methods[k]) methods[k] = methods[v]; + else if(true === methods[v]) methods[v] = methods[k]; + } + if(opt.catchExceptions){ + const fwrap = function(methodName, func){ + if(['xConnect','xCreate'].indexOf(methodName) >= 0){ + return function(pDb, pAux, argc, argv, ppVtab, pzErr){ + try{return func(...arguments) || 0} + catch(e){ + if(!(e instanceof sqlite3.WasmAllocError)){ + wasm.dealloc(wasm.peekPtr(pzErr)); + wasm.pokePtr(pzErr, wasm.allocCString(e.message)); + } + return vtab.xError(methodName, e); + } + }; + }else{ + return function(...args){ + try{return func(...args) || 0} + catch(e){ + return vtab.xError(methodName, e); + } + }; + } + }; + const mnames = [ + 'xCreate', 'xConnect', 'xBestIndex', 'xDisconnect', + 'xDestroy', 'xOpen', 'xClose', 'xFilter', 'xNext', + 'xEof', 'xColumn', 'xRowid', 'xUpdate', + 'xBegin', 'xSync', 'xCommit', 'xRollback', + 'xFindFunction', 'xRename', 'xSavepoint', 'xRelease', + 'xRollbackTo', 'xShadowName' + ]; + const remethods = Object.create(null); + for(const k of mnames){ + const m = methods[k]; + if(!(m instanceof Function)) continue; + else if('xConnect'===k && methods.xCreate===m){ + remethods[k] = methods.xCreate; + }else if('xCreate'===k && methods.xConnect===m){ + remethods[k] = methods.xConnect; + }else{ + remethods[k] = fwrap(k, m); + } + } + mod.installMethods(remethods, false); + }else{ + + + mod.installMethods( + methods, !!opt.applyArgcCheck + ); + } + if(0===mod.$iVersion){ + let v; + if('number'===typeof opt.iVersion) v = opt.iVersion; + else if(mod.$xIntegrity) v = 4; + else if(mod.$xShadowName) v = 3; + else if(mod.$xSavePoint || mod.$xRelease || mod.$xRollbackTo) v = 2; + else v = 1; + mod.$iVersion = v; + } + }catch(e){ + if(createdMod) createdMod.dispose(); + throw e; + } + return mod; + }; + + + capi.sqlite3_module.prototype.setupModule = function(opt){ + return vtab.setupModule.call(this, opt); + }; +}); + + + +globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ + if( sqlite3.config.disable?.vfs?.kvvfs ){ + return; + } + 'use strict'; + const capi = sqlite3.capi, + sqlite3_kvvfs_methods = capi.sqlite3_kvvfs_methods, + KVVfsFile = capi.KVVfsFile, + pKvvfs = sqlite3.capi.sqlite3_vfs_find("kvvfs") + + + delete capi.sqlite3_kvvfs_methods; + delete capi.KVVfsFile; + + if( !pKvvfs ) return ; + if( 0 ){ + + capi.sqlite3_vfs_register(pKvvfs, 1); + } + + const util = sqlite3.util, + wasm = sqlite3.wasm, + toss3 = util.toss3, + hop = (o,k)=>Object.prototype.hasOwnProperty.call(o,k); + + const kvvfsMethods = new sqlite3_kvvfs_methods( + + wasm.exports.sqlite3__wasm_kvvfs_methods() + ); + util.assert( 32<=kvvfsMethods.$nKeySize, "unexpected kvvfsMethods.$nKeySize: "+kvvfsMethods.$nKeySize); + + + const cache = Object.assign(Object.create(null),{ + + rxJournalSuffix: /-journal$/, + + zKeyJrnl: wasm.allocCString("jrnl"), + + zKeySz: wasm.allocCString("sz"), + + keySize: kvvfsMethods.$nKeySize, + + buffer: Object.assign(Object.create(null),{ + + n: kvvfsMethods.$nBufferSize, + + pool: Object.create(null) + }) + }); + + + cache.memBuffer = (id=0)=>cache.buffer.pool[id] ??= wasm.alloc(cache.buffer.n); + + + cache.memBufferFree = (id)=>{ + const b = cache.buffer.pool[id]; + if( b ){ + wasm.dealloc(b); + delete cache.buffer.pool[id]; + } + }; + + const noop = ()=>{}; + const debug = sqlite3.__isUnderTest + ? (...args)=>sqlite3.config.debug?.("kvvfs:", ...args) + : noop; + const warn = (...args)=>sqlite3.config.warn?.("kvvfs:", ...args); + const error = (...args)=>sqlite3.config.error?.("kvvfs:", ...args); + + + class KVVfsStorage { + #map = Object.create(null); + #keys = null; + #size = 0; + + constructor(){ + this.clear(); + } + + #getKeys(){ + return this.#keys ??= Object.keys(this.#map); + } + + key(n){ + if(n < 0 || n >= this.#size) return null; + return this.#getKeys()[n]; + } + + getItem(k){ + return this.#map[k] ?? null; + } + + setItem(k,v){ + if( !(k in this.#map) ){ + ++this.#size; + this.#keys = null; + } + this.#map[k] = ''+v; + } + + removeItem(k){ + if( k in this.#map ){ + delete this.#map[k]; + --this.#size; + this.#keys = null; + } + } + + clear(){ + this.#map = Object.create(null); + this.#keys = null; + this.#size = 0; + } + + get length() { + return this.#size; + } + }; + + + const kvvfsIsPersistentName = (v)=>'local'===v || 'session'===v; + + + const kvvfsKeyPrefix = (v)=>kvvfsIsPersistentName(v) ? 'kvvfs-'+v+'-' : ''; + + + const validateStorageName = function(n,mayBeJournal=false){ + if( kvvfsIsPersistentName(n) ) return; + const len = (new Blob([n])).size; + if( !len ) toss3(capi.SQLITE_MISUSE, "Empty name is not permitted."); + let maxLen = cache.keySize - 1; + if( cache.rxJournalSuffix.test(n) ){ + if( !mayBeJournal ){ + toss3(capi.SQLITE_MISUSE, + "Storage names may not have a '-journal' suffix."); + } + }else if( ['-wal','-shm'].filter(v=>n.endsWith(v)).length ){ + toss3(capi.SQLITE_MISUSE, + "Storage names may not have a -wal or -shm suffix."); + }else{ + maxLen -= 8 ; + } + if( len > maxLen ){ + toss3(capi.SQLITE_RANGE, "Storage name is too long. Limit =", maxLen); + } + let i; + for( i = 0; i < len; ++i ){ + const ch = n.codePointAt(i); + if( ch<32 ){ + toss3(capi.SQLITE_RANGE, + "Illegal character ("+ch+"d) in storage name:",n); + } + } + }; + + + const newStorageObj = (name,storage=undefined)=>Object.assign(Object.create(null),{ + + jzClass: name, + + refc: 1, + + deleteAtRefc0: false, + + storage: storage || new KVVfsStorage, + + keyPrefix: kvvfsKeyPrefix(name), + + files: [], + + listeners: undefined + }); + + + const kvvfs = sqlite3.kvvfs = Object.create(null); + if( sqlite3.__isUnderTest ){ + + kvvfs.log = Object.assign(Object.create(null),{ + xOpen: false, + xClose: false, + xWrite: false, + xRead: false, + xSync: false, + xAccess: false, + xFileControl: false, + xRcrdRead: false, + xRcrdWrite: false, + xRcrdDelete: false, + }); + } + + + const deleteStorage = function(store){ + const other = cache.rxJournalSuffix.test(store.jzClass) + ? store.jzClass.replace(cache.rxJournalSuffix,'') + : store.jzClass+'-journal'; + kvvfs?.log?.xClose + && debug("cleaning up storage handles [", store.jzClass, other,"]",store); + delete cache.storagePool[store.jzClass]; + delete cache.storagePool[other]; + if( !sqlite3.__isUnderTest ){ + + delete store.storage; + delete store.refc; + } + }; + + + const installStorageAndJournal = (store)=> + cache.storagePool[store.jzClass] = + cache.storagePool[store.jzClass+'-journal'] = store; + + + const nameOfThisThreadStorage = '.'; + + + cache.storagePool = Object.assign(Object.create(null),{ + + [nameOfThisThreadStorage]: newStorageObj(nameOfThisThreadStorage) + }); + + if( globalThis.Storage ){ + + if( globalThis.localStorage instanceof globalThis.Storage ){ + cache.storagePool.local = newStorageObj('local', globalThis.localStorage); + } + if( globalThis.sessionStorage instanceof globalThis.Storage ){ + cache.storagePool.session = newStorageObj('session', globalThis.sessionStorage); + } + } + + cache.builtinStorageNames = Object.keys(cache.storagePool); + + const isBuiltinName = (n)=>cache.builtinStorageNames.indexOf(n)>-1; + + + for(const k of Object.keys(cache.storagePool)){ + + const orig = cache.storagePool[k]; + cache.storagePool[k+'-journal'] = orig; + } + + cache.setError = (e=undefined, dfltErrCode=capi.SQLITE_ERROR)=>{ + if( e ){ + cache.lastError = e; + return (e.resultCode | 0) || dfltErrCode; + } + delete cache.lastError; + return 0; + }; + + cache.popError = ()=>{ + const e = cache.lastError; + delete cache.lastError; + return e; + }; + + + const catchForNotify = (e)=>{ + warn("kvvfs.listener handler threw:",e); + }; + + const kvvfsDecode = wasm.exports.sqlite3__wasm_kvvfs_decode; + const kvvfsEncode = wasm.exports.sqlite3__wasm_kvvfs_encode; + + + const notifyListeners = async function(eventName,store,...args){ + try{ + + if( store.keyPrefix && args[0] ){ + args[0] = args[0].replace(store.keyPrefix,''); + } + let u8enc, z0, z1, wcache; + for(const ear of store.listeners){ + const ev = Object.create(null); + ev.storageName = store.jzClass; + ev.type = eventName; + const decodePages = ear.decodePages; + const f = ear.events[eventName]; + if( f ){ + if( !ear.includeJournal && args[0]==='jrnl' ){ + continue; + } + if( 'write'===eventName && ear.decodePages && +args[0]>0 ){ + + ev.data = [args[0]]; + if( wcache?.[args[0]] ){ + ev.data[1] = wcache[args[0]]; + continue; + } + u8enc ??= new TextEncoder('utf-8'); + z0 ??= cache.memBuffer(10); + z1 ??= cache.memBuffer(11); + const u = u8enc.encode(args[1]); + const heap = wasm.heap8u(); + heap.set(u, Number(z0)); + heap[wasm.ptr.addn(z0, u.length)] = 0; + const rc = kvvfsDecode(z0, z1, cache.buffer.n); + if( rc>0 ){ + wcache ??= Object.create(null); + wcache[args[0]] + = ev.data[1] + = heap.slice(Number(z1), wasm.ptr.addn(z1,rc)); + }else{ + continue; + } + }else{ + ev.data = args.length + ? ((args.length===1) ? args[0] : args) + : undefined; + } + try{f(ev)?.catch?.(catchForNotify)} + catch(e){ + warn("notifyListeners [",store.jzClass,"]",eventName,e); + } + } + } + }catch(e){ + catchForNotify(e); + } + }; + + + const storageForZClass = (zClass)=> + 'string'===typeof zClass + ? cache.storagePool[zClass] + : cache.storagePool[wasm.cstrToJs(zClass)]; + + + const kvvfsMakeKey = wasm.exports.sqlite3__wasm_kvvfsMakeKey; + + const zKeyForStorage = (store, zClass, zKey)=>{ + + return (zClass && store.keyPrefix) ? kvvfsMakeKey(zClass, zKey) : zKey; + }; + + const jsKeyForStorage = (store,zClass,zKey)=> + wasm.cstrToJs(zKeyForStorage(store, zClass, zKey)); + + const storageGetDbSize = (store)=>+store.storage.getItem(store.keyPrefix + "sz"); + + + const pFileHandles = new Map(); + + + const mapPathToLocks = new Map(); + + + const unlockFile = function(fh, lockType){ + if(fh.lockType<=lockType) return; + const lk = mapPathToLocks.get(fh.jzClass); + if(fh.lockType>capi.SQLITE_LOCK_SHARED){ + lk.lockType = capi.SQLITE_LOCK_SHARED; + } + if(lockType===capi.SQLITE_LOCK_NONE && 0===--lk.nShared + ){ + mapPathToLocks.delete(fh.jzClass); + } + fh.lockType = lockType; + }; + + + const originalMethods = { + vfs: Object.create(null), + ioDb: Object.create(null), + ioJrnl: Object.create(null) + }; + + + const originalIoMethods = (kvvfsFile)=> + originalMethods[kvvfsFile.$isJournal ? 'ioJrnl' : 'ioDb']; + + const pVfs = new capi.sqlite3_vfs(kvvfsMethods.$pVfs); + const pIoDb = new capi.sqlite3_io_methods(kvvfsMethods.$pIoDb); + const pIoJrnl = new capi.sqlite3_io_methods(kvvfsMethods.$pIoJrnl); + const recordHandler = + Object.create(null); + const kvvfsInternal = Object.assign(Object.create(null),{ + pFileHandles, + cache, + storageForZClass, + KVVfsStorage, + + disablePageSizeChange: true + }); + if( kvvfs.log ){ + + kvvfs.internal = kvvfsInternal; + } + + + const methodOverrides = { + + + recordHandler: { + xRcrdRead: (zClass, zKey, zBuf, nBuf)=>{ + try{ + const jzClass = wasm.cstrToJs(zClass); + const store = storageForZClass(jzClass); + if( !store ) return -1; + const jXKey = jsKeyForStorage(store, zClass, zKey); + kvvfs?.log?.xRcrdRead && warn("xRcrdRead", jzClass, jXKey, nBuf, store ); + const jV = store.storage.getItem(jXKey); + if(null===jV) return -1; + const nV = jV.length ; + if( 0 ){ + debug("xRcrdRead", jXKey, store, jV); + } + if(nBuf<=0) return nV; + else if(1===nBuf){ + wasm.poke(zBuf, 0); + return nV; + }else if( nBuf nV + 1 ){ + nBuf = nV + 1; + } + if( 0 ){ + debug("xRcrdRead", nBuf, zClass, wasm.cstrToJs(zClass), + wasm.cstrToJs(zKey), nV, jV, store); + } + const nCopy = nV{ + try { + const store = storageForZClass(zClass); + const jxKey = jsKeyForStorage(store, zClass, zKey); + const jData = wasm.cstrToJs(zData); + kvvfs?.log?.xRcrdWrite && warn("xRcrdWrite",jxKey, store); + store.storage.setItem(jxKey, jData); + store.listeners && notifyListeners('write', store, jxKey, jData); + return 0; + }catch(e){ + error("kvrecordWrite()",e); + return cache.setError(e, capi.SQLITE_IOERR); + } + }, + + xRcrdDelete: (zClass, zKey)=>{ + try { + const store = storageForZClass(zClass); + const jxKey = jsKeyForStorage(store, zClass, zKey); + kvvfs?.log?.xRcrdDelete && warn("xRcrdDelete",jxKey, store); + store.storage.removeItem(jxKey); + store.listeners && notifyListeners('delete', store, jxKey); + return 0; + }catch(e){ + error("kvrecordDelete()",e); + return cache.setError(e, capi.SQLITE_IOERR); + } + } + }, + + + vfs:{ + + xOpen: function(pProtoVfs,zName,pProtoFile,flags,pOutFlags){ + cache.popError(); + let zToFree ; + try{ + if( !zName ){ + zToFree = wasm.allocCString(""+pProtoFile+"." + +(Math.random() * 100000 | 0)); + zName = zToFree; + } + const jzClass = wasm.cstrToJs(zName); + kvvfs?.log?.xOpen && debug("xOpen",jzClass,"flags =",flags); + validateStorageName(jzClass, true); + if( (flags & (capi.SQLITE_OPEN_MAIN_DB + | capi.SQLITE_OPEN_TEMP_DB + | capi.SQLITE_OPEN_TRANSIENT_DB)) + && cache.rxJournalSuffix.test(jzClass) ){ + toss3(capi.SQLITE_ERROR, + "DB files may not have a '-journal' suffix."); + } + let s = storageForZClass(jzClass); + if( !s && !(flags & capi.SQLITE_OPEN_CREATE) ){ + toss3(capi.SQLITE_ERROR, "Storage not found:", jzClass); + } + const rc = originalMethods.vfs.xOpen(pProtoVfs, zName, pProtoFile, + flags, pOutFlags); + if( rc ) return rc; + let deleteAt0 = !!(capi.SQLITE_OPEN_DELETEONCLOSE & flags); + if(wasm.isPtr(arguments[1])){ + if(capi.sqlite3_uri_boolean(zName, "delete-on-close", 0)){ + deleteAt0 = true; + } + } + const f = new KVVfsFile(pProtoFile); + util.assert(f.$zClass, "Missing f.$zClass"); + f.addOnDispose(zToFree); + zToFree = undefined; + + if( s ){ + ++s.refc; + + s.files.push(f); + wasm.poke32(pOutFlags, flags); + }else{ + wasm.poke32(pOutFlags, flags | capi.SQLITE_OPEN_CREATE); + util.assert( !f.$isJournal, "Opening a journal before its db? "+jzClass ); + + const nm = jzClass.replace(cache.rxJournalSuffix,''); + s = newStorageObj(nm); + installStorageAndJournal(s); + s.files.push(f); + s.deleteAtRefc0 = deleteAt0; + kvvfs?.log?.xOpen + && debug("xOpen installed storage handle [",nm, nm+"-journal","]", s); + } + pFileHandles.set(pProtoFile, Object.assign(Object.create(null),{ + store: s, + file: f, + jzClass, + lockType: 0 + })); + s.listeners && notifyListeners('open', s, s.files.length); + return 0; + }catch(e){ + warn("xOpen:",e); + return cache.setError(e); + }finally{ + zToFree && wasm.dealloc(zToFree); + } + }, + + xDelete: function(pVfs, zName, iSyncFlag){ + cache.popError(); + try{ + const jzName = wasm.cstrToJs(zName); + if( cache.rxJournalSuffix.test(jzName) ){ + recordHandler.xRcrdDelete(zName, cache.zKeyJrnl); + } + return 0; + }catch(e){ + warn("xDelete",e); + return cache.setError(e); + } + }, + + xAccess: function(pProtoVfs, zPath, flags, pResOut){ + cache.popError(); + try{ + const s = storageForZClass(zPath); + const jzPath = s?.jzClass || wasm.cstrToJs(zPath); + if( kvvfs?.log?.xAccess ){ + debug("xAccess",jzPath,"flags =", + flags,"*pResOut =",wasm.peek32(pResOut), + "store =",s); + } + if( !s ){ + + + + try{validateStorageName(jzPath)} + catch(e){ + + wasm.poke32(pResOut, 0); + return 0; + } + } + if( s ){ + const key = s.keyPrefix+ + (cache.rxJournalSuffix.test(jzPath) ? "jrnl" : "1"); + const res = s.storage.getItem(key) ? 0 : 1; + + + wasm.poke32(pResOut, res); + }else{ + wasm.poke32(pResOut, 0); + } + return 0; + }catch(e){ + error('xAccess',e); + return cache.setError(e); + } + }, + + xRandomness: function(pVfs, nOut, pOut){ + const heap = wasm.heap8u(); + let i = 0; + const npOut = Number(pOut); + for(; i < nOut; ++i) heap[npOut + i] = (Math.random()*255000) & 0xFF; + return nOut; + }, + + xGetLastError: function(pVfs,nOut,pOut){ + const e = cache.popError(); + debug('xGetLastError',e); + if(e){ + const scope = wasm.scopedAllocPush(); + try{ + const [cMsg, n] = wasm.scopedAllocCString(e.message, true); + wasm.cstrncpy(pOut, cMsg, nOut); + if(n > nOut) wasm.poke8(wasm.ptr.add(pOut,nOut,-1), 0); + debug("set xGetLastError",e.message); + return (e.resultCode | 0) || capi.SQLITE_IOERR; + }catch(e){ + return capi.SQLITE_NOMEM; + }finally{ + wasm.scopedAllocPop(scope); + } + } + return 0; + }, + + + xSleep: (pVfs,ms)=>0, + + }, + + + ioDb:{ + + xClose: function(pFile){ + cache.popError(); + try{ + const h = pFileHandles.get(pFile); + kvvfs?.log?.xClose && debug("xClose", pFile, h); + if( h ){ + pFileHandles.delete(pFile); + unlockFile(h, capi.SQLITE_LOCK_NONE); + const s = h.store; + s.files = s.files.filter((v)=>v!==h.file); + if( --s.refc<=0 && s.deleteAtRefc0 ){ + deleteStorage(s); + } + originalMethods.ioDb.xClose(pFile); + h.file.dispose(); + s.listeners && notifyListeners('close', s, s.files.length); + }else{ + + } + return 0; + }catch(e){ + error("xClose",e); + return cache.setError(e); + } + }, + + xFileControl: function(pFile, opId, pArg){ + cache.popError(); + try{ + const h = pFileHandles.get(pFile); + util.assert(h, "Missing KVVfsFile handle"); + kvvfs?.log?.xFileControl && debug("xFileControl",h,'op =',opId); + if( opId===capi.SQLITE_FCNTL_PRAGMA + && kvvfsInternal.disablePageSizeChange ){ + + + const zName = wasm.peekPtr(wasm.ptr.add(pArg, wasm.ptr.size)); + if( "page_size"===wasm.cstrToJs(zName) ){ + kvvfs?.log?.xFileControl + && debug("xFileControl pragma",wasm.cstrToJs(zName)); + const zVal = wasm.peekPtr(wasm.ptr.add(pArg, 2*wasm.ptr.size)); + if( zVal ){ + + kvvfs?.log?.xFileControl + && warn("xFileControl pragma", h, + "NOT setting page size to", wasm.cstrToJs(zVal)); + h.file.$szPage = -1; + return 0; + }else if( h.file.$szPage>0 ){ + kvvfs?.log?.xFileControl && + warn("xFileControl", h, "getting page size",h.file.$szPage); + wasm.pokePtr(pArg, wasm.allocCString(""+h.file.$szPage) + ); + return 0; + } + } + } + const rc = originalMethods.ioDb.xFileControl(pFile, opId, pArg); + if( 0==rc && capi.SQLITE_FCNTL_SYNC===opId ){ + h.store.listeners && notifyListeners('sync', h.store, false); + } + return rc; + }catch(e){ + error("xFileControl",e); + return cache.setError(e); + } + }, + + xSync: function(pFile,flags){ + cache.popError(); + try{ + const h = pFileHandles.get(pFile); + kvvfs?.log?.xSync && debug("xSync", h); + util.assert(h, "Missing KVVfsFile handle"); + const rc = originalMethods.ioDb.xSync(pFile, flags); + if( 0==rc && h.store.listeners ) notifyListeners('sync', h.store, true); + return rc; + }catch(e){ + error("xSync",e); + return cache.setError(e); + } + }, + + xLock: function(pFile, iLock){ + cache.popError(); + try{ + const h = pFileHandles.get(pFile); + if( capi.SQLITE_LOCK_NONE!==iLock ){ + + originalMethods.ioDb.xLock(pFile, iLock); + } + + if(h.lockType>=iLock) return 0; + let lk = mapPathToLocks.get(h.jzClass); + if(!lk){ + lk = Object.assign(Object.create(null),{ + nShared: 0, lockType: capi.SQLITE_LOCK_NONE + }); + mapPathToLocks.set(h.jzClass, lk); + } + if(h.lockType!==lk.lockType + && (lk.lockType>=capi.SQLITE_LOCK_PENDING + || iLock>capi.SQLITE_LOCK_SHARED)){ + return capi.SQLITE_BUSY; + } + if(iLock===capi.SQLITE_LOCK_SHARED){ + ++lk.nShared; + if(lk.lockType===capi.SQLITE_LOCK_NONE) lk.lockType = iLock; + }else if(iLock===capi.SQLITE_LOCK_EXCLUSIVE && lk.nShared>1){ + if(h.lockType===capi.SQLITE_LOCK_RESERVED){ + h.lockType = lk.lockType = capi.SQLITE_LOCK_PENDING; + } + return capi.SQLITE_BUSY; + }else{ + lk.lockType = iLock; + } + h.lockType = iLock; + return 0; + }catch(e){ + error("xLock", e); + return cache.setError(e); + } + }, + + xUnlock: function(pFile, iLock){ + cache.popError(); + try{ + if( capi.SQLITE_LOCK_NONE===iLock ){ + + originalMethods.ioDb.xUnlock(pFile, iLock); + } + const h = pFileHandles.get(pFile); + unlockFile(h, iLock); + return 0; + }catch(e){ + error("xUnlock", e); + return cache.setError(e); + } + }, + + xCheckReservedLock: function(pFile, pOut){ + cache.popError(); + try{ + const h = pFileHandles.get(pFile); + const lk = mapPathToLocks.get(h.jzClass); + wasm.poke32(pOut, + (!!lk && lk.lockType>capi.SQLITE_LOCK_SHARED) + ? 1 : 0) + return 0; + }catch(e){ + error("xCheckReservedLock", e); + return cache.setError(e); + } + }, + + + }, + + ioJrnl:{ + + xClose: true, + xLock: true, + xUnlock: true, + xCheckReservedLock: true, + } + }; + + + try { + util.assert( cache.buffer.n>1024*129, "Heap buffer is not large enough" + ); + for(const e of Object.entries(methodOverrides.recordHandler)){ + + const k = e[0], f = e[1]; + recordHandler[k] = f; + if( 0 ){ + + kvvfsMethods.installMethod(k, f); + }else{ + kvvfsMethods[kvvfsMethods.memberKey(k)] = + wasm.installFunction(kvvfsMethods.memberSignature(k), f); + } + } + for(const e of Object.entries(methodOverrides.vfs)){ + + const k = e[0], f = e[1], km = pVfs.memberKey(k), + member = pVfs.structInfo.members[k] + || util.toss("Missing pVfs.structInfo[",k,"]"); + originalMethods.vfs[k] = wasm.functionEntry(pVfs[km]); + pVfs[km] = wasm.installFunction(member.signature, f); + } + for(const e of Object.entries(methodOverrides.ioDb)){ + + const k = e[0], f = e[1], km = pIoDb.memberKey(k); + originalMethods.ioDb[k] = wasm.functionEntry(pIoDb[km]) + || util.toss("Missing native pIoDb[",km,"]"); + pIoDb[km] = wasm.installFunction(pIoDb.memberSignature(k), f); + } + for(const e of Object.entries(methodOverrides.ioJrnl)){ + + const k = e[0], f = e[1], km = pIoJrnl.memberKey(k); + originalMethods.ioJrnl[k] = wasm.functionEntry(pIoJrnl[km]) + || util.toss("Missing native pIoJrnl[",km,"]"); + if( true===f ){ + + pIoJrnl[km] = pIoDb[km] || util.toss("Missing copied pIoDb[",km,"]"); + }else{ + pIoJrnl[km] = wasm.installFunction(pIoJrnl.memberSignature(k), f); + } + } + }finally{ + kvvfsMethods.dispose(); + pVfs.dispose(); + pIoDb.dispose(); + pIoJrnl.dispose(); + } + + + + + const sqlite3_js_kvvfs_clear = function callee(which){ + if( ''===which ){ + return callee('local') + callee('session'); + } + const store = storageForZClass(which); + if( !store ) return 0; + if( store.files.length ){ + if( globalThis.localStorage===store.storage + || globalThis.sessionStorage===store.storage ){ + + }else{ + + toss3(capi.SQLITE_ACCESS, + "Cannot clear in-use database storage."); + } + } + const s = store.storage; + const toRm = [] ; + let i, n = s.length; + + for( i = 0; i < n; ++i ){ + const k = s.key(i); + + if(!store.keyPrefix || k.startsWith(store.keyPrefix)) toRm.push(k); + } + toRm.forEach((kk)=>s.removeItem(kk)); + + return toRm.length; + }; + + + const sqlite3_js_kvvfs_size = function callee(which){ + if( ''===which ){ + return callee('local') + callee('session'); + } + const store = storageForZClass(which); + if( !store ) return 0; + const s = store.storage; + let i, sz = 0; + for(i = 0; i < s.length; ++i){ + const k = s.key(i); + if(!store.keyPrefix || k.startsWith(store.keyPrefix)){ + sz += k.length; + sz += s.getItem(k).length; + } + } + return sz * 2 ; + }; + + + const sqlite3_js_kvvfs_export = function callee(...args){ + let opt; + if( 1===args.length && 'object'===typeof args[0] ){ + opt = args[0]; + }else if(args.length){ + opt = Object.assign(Object.create(null),{ + name: args[0], + + }); + } + const store = opt ? storageForZClass(opt.name) : null; + if( !store ){ + toss3(capi.SQLITE_NOTFOUND, + "There is no kvvfs storage named",opt?.name); + } + + const s = store.storage; + const rc = Object.assign(Object.create(null),{ + name: store.jzClass, + timestamp: Date.now(), + pages: [] + }); + const pages = Object.create(null); + let xpages; + const keyPrefix = store.keyPrefix; + const rxTail = keyPrefix + ? /^kvvfs-[^-]+-(\w+)/ + : undefined; + let i = 0, n = s.length; + for( ; i < n; ++i ){ + const k = s.key(i); + if( !keyPrefix || k.startsWith(keyPrefix) ){ + let kk = (keyPrefix ? rxTail.exec(k) : undefined)?.[1] ?? k; + switch( kk ){ + case 'jrnl': + if( opt.includeJournal ) rc.journal = s.getItem(k); + break; + case 'sz': + rc.size = +s.getItem(k); + break; + default: + kk = +kk ; + if( !util.isInt32(kk) || kk<=0 ){ + toss3(capi.SQLITE_RANGE, "Malformed kvvfs key: "+k); + } + if( opt.decodePages ){ + const spg = s.getItem(k), + n = spg.length, + z = cache.memBuffer(0), + zDec = cache.memBuffer(1), + heap = wasm.heap8u(); + let i = 0; + for( ; i < n; ++i ){ + heap[wasm.ptr.add(z, i)] = spg.codePointAt(i) & 0xff; + } + heap[wasm.ptr.add(z, i)] = 0; + + const nDec = kvvfsDecode( + z, zDec, cache.buffer.n + ); + + pages[kk] = heap.slice(Number(zDec), wasm.ptr.addn(zDec, nDec)); + }else{ + pages[kk] = s.getItem(k); + } + break; + } + } + } + if( opt.decodePages ) cache.memBufferFree(1); + + Object.keys(pages).map((v)=>+v).sort().forEach( + (v)=>rc.pages.push(pages[v]) + ); + return rc; + }; + + + const sqlite3_js_kvvfs_import = function(exp, overwrite=false){ + if( !exp?.timestamp + || !exp.name + || undefined===exp.size + || !Array.isArray(exp.pages) ){ + toss3(capi.SQLITE_MISUSE, "Malformed export object."); + }else if( !exp.size + || (exp.size !== (exp.size | 0)) + + || exp.size>=0x7fffffff ){ + toss3(capi.SQLITE_RANGE, "Invalid db size: "+exp.size); + } + + validateStorageName(exp.name); + let store = storageForZClass(exp.name); + const isNew = !store; + if( store ){ + if( !overwrite ){ + + toss3(capi.SQLITE_ACCESS, + "Storage '"+exp.name+"' already exists and", + "overwrite was not specified."); + }else if( !store.files || !store.jzClass ){ + toss3(capi.SQLITE_ERROR, + "Internal storage object", exp.name,"seems to be malformed."); + }else if( store.files.length ){ + toss3(capi.SQLITE_IOERR_ACCESS, + "Cannot import db storage while it is in use."); + } + sqlite3_js_kvvfs_clear(exp.name); + }else{ + store = newStorageObj(exp.name); + + } + + + const keyPrefix = kvvfsKeyPrefix(exp.name); + let zEnc; + try{ + ; + const s = store.storage; + s.setItem(keyPrefix+'sz', exp.size); + if( exp.journal ) s.setItem(keyPrefix+'jrnl', exp.journal); + if( exp.pages[0] instanceof Uint8Array ){ + + + exp.pages.forEach((u,ndx)=>{ + const n = u.length; + if( 0 && cache.fixedPageSize !== n ){ + util.toss3(capi.SQLITE_RANGE,"Unexpected page size:", n); + } + zEnc ??= cache.memBuffer(1); + const zBin = cache.memBuffer(0), + heap = wasm.heap8u(); + + heap.set(u, Number(zBin)); + heap[wasm.ptr.addn(zBin,n)] = 0; + const rc = kvvfsEncode(zBin, n, zEnc); + util.assert( rc < cache.buffer.n, + "Impossibly long output - possibly smashed the heap" ); + util.assert( 0===wasm.peek8(wasm.ptr.add(zEnc,rc)), + "Expecting NUL-terminated encoded output" ); + const jenc = wasm.cstrToJs(zEnc); + + s.setItem(keyPrefix+(ndx+1), jenc); + }); + }else if( exp.pages[0] ){ + + exp.pages.forEach((v,ndx)=>s.setItem(keyPrefix+(ndx+1), v)); + } + if( isNew ) installStorageAndJournal(store); + }catch{ + if( !isNew ){ + try{sqlite3_js_kvvfs_clear(exp.name);}catch(ee){} + } + }finally{ + if( zEnc ) cache.memBufferFree(1); + } + return this; + }; + + + const sqlite3_js_kvvfs_reserve = function(name){ + let store = storageForZClass(name); + if( store ){ + ++store.refc; + return; + } + validateStorageName(name); + installStorageAndJournal(newStorageObj(name)); + }; + + + const sqlite3_js_kvvfs_unlink = function(name){ + const store = storageForZClass(name); + if( !store + || kvvfsIsPersistentName(store.jzClass) + || isBuiltinName(store.jzClass) + || cache.rxJournalSuffix.test(name) ) return false; + if( store.refc > store.files.length || 0===store.files.length ){ + if( --store.refc<=0 ){ + + deleteStorage(store); + } + return true; + } + return false; + }; + + + const sqlite3_js_kvvfs_listen = function(opt){ + if( !opt || 'object'!==typeof opt ){ + toss3(capi.SQLITE_MISUSE, "Expecting a listener object."); + } + let store = storageForZClass(opt.storage); + if( !store ){ + if( opt.storage && opt.reserve ){ + sqlite3_js_kvvfs_reserve(opt.storage); + store = storageForZClass(opt.storage); + util.assert(store, + "Unexpectedly cannot fetch reserved storage " + +opt.storage); + }else{ + toss3(capi.SQLITE_NOTFOUND,"No such storage:",opt.storage); + } + } + if( opt.events ){ + (store.listeners ??= []).push(opt); + } + }; + + + const sqlite3_js_kvvfs_unlisten = function(opt){ + const store = storageForZClass(opt?.storage); + if( store?.listeners && opt.events ){ + const n = store.listeners.length; + store.listeners = store.listeners.filter((v)=>v!==opt); + const rc = n>store.listeners.length; + if( !store.listeners.length ){ + + store.listeners = undefined; + } + return rc; + } + return false; + }; + + sqlite3.kvvfs.reserve = sqlite3_js_kvvfs_reserve; + sqlite3.kvvfs.import = sqlite3_js_kvvfs_import; + sqlite3.kvvfs.export = sqlite3_js_kvvfs_export; + sqlite3.kvvfs.unlink = sqlite3_js_kvvfs_unlink; + sqlite3.kvvfs.listen = sqlite3_js_kvvfs_listen; + sqlite3.kvvfs.unlisten = sqlite3_js_kvvfs_unlisten; + sqlite3.kvvfs.exists = (name)=>!!storageForZClass(name); + sqlite3.kvvfs.estimateSize = sqlite3_js_kvvfs_size; + sqlite3.kvvfs.clear = sqlite3_js_kvvfs_clear; + + + if( globalThis.Storage ){ + + capi.sqlite3_js_kvvfs_size = (which="")=>sqlite3_js_kvvfs_size(which); + capi.sqlite3_js_kvvfs_clear = (which="")=>sqlite3_js_kvvfs_clear(which); + } + + if(sqlite3.oo1?.DB){ + + const DB = sqlite3.oo1.DB; + sqlite3.oo1.JsStorageDb = function( + storageName = sqlite3.oo1.JsStorageDb.defaultStorageName + ){ + const opt = DB.dbCtorHelper.normalizeArgs(...arguments); + opt.vfs = 'kvvfs'; + if( 0 ){ + + if( opt.flags ) opt.flags = 'cw'+opt.flags; + else opt.flags = 'cw'; + } + switch( opt.filename ){ + + case ":sessionStorage:": opt.filename = 'session'; break; + case ":localStorage:": opt.filename = 'local'; break; + } + const m = /(file:(\/\/)?)([^?]+)/.exec(opt.filename); + validateStorageName( m ? m[3] : opt.filename); + DB.dbCtorHelper.call(this, opt); + }; + sqlite3.oo1.JsStorageDb.defaultStorageName + = cache.storagePool.session ? 'session' : nameOfThisThreadStorage; + const jdb = sqlite3.oo1.JsStorageDb; + jdb.prototype = Object.create(DB.prototype); + jdb.clearStorage = sqlite3_js_kvvfs_clear; + + jdb.prototype.clearStorage = function(){ + return jdb.clearStorage(this.affirmOpen().dbFilename(), true); + }; + + jdb.storageSize = sqlite3_js_kvvfs_size; + + jdb.prototype.storageSize = function(){ + return jdb.storageSize(this.affirmOpen().dbFilename(), true); + }; + } + + if( sqlite3.__isUnderTest && sqlite3.vtab ){ + + const cols = Object.assign(Object.create(null),{ + rowid: {type: 'INTEGER'}, + name: {type: 'TEXT'}, + nRef: {type: 'INTEGER'}, + nOpen: {type: 'INTEGER'}, + isTransient: {type: 'INTEGER'}, + dbSize: {type: 'INTEGER'} + }); + Object.keys(cols).forEach((v,i)=>cols[v].colId = i); + + const VT = sqlite3.vtab; + const ProtoCursor = Object.assign(Object.create(null),{ + row: function(){ + return cache.storagePool[this.names[this.rowid]]; + } + }); + Object.assign(Object.create(ProtoCursor),{ + rowid: 0, + names: Object.keys(cache.storagePool) + .filter(v=>!cache.rxJournalSuffix.test(v)) + }); + const cursorState = function(cursor, reset){ + const o = (cursor instanceof capi.sqlite3_vtab_cursor) + ? cursor + : VT.xCursor.get(cursor); + if( reset || !o.vTabState ){ + o.vTabState = Object.assign(Object.create(ProtoCursor),{ + rowid: 0, + names: Object.keys(cache.storagePool) + .filter(v=>!cache.rxJournalSuffix.test(v)) + }); + } + return o.vTabState; + }; + + const dbg = 1 ? ()=>{} : (...args)=>debug("vtab",...args); + + const theModule = function f(){ + return f.mod ??= new sqlite3.capi.sqlite3_module().setupModule({ + catchExceptions: true, + methods: { + xConnect: function(pDb, pAux, argc, argv, ppVtab, pzErr){ + dbg("xConnect"); + try{ + const xcol = []; + Object.keys(cols).forEach((k)=>{ + xcol.push(k+" "+cols[k].type); + }); + const rc = capi.sqlite3_declare_vtab( + pDb, "CREATE TABLE ignored("+xcol.join(',')+")" + ); + if(0===rc){ + const t = VT.xVtab.create(ppVtab); + util.assert( + (t === VT.xVtab.get(wasm.peekPtr(ppVtab))), + "output pointer check failed" + ); + } + return rc; + }catch(e){ + return VT.xError('xConnect', e, capi.SQLITE_ERROR); + } + }, + xCreate: wasm.ptr.null, + + xDisconnect: function(pVtab){ + dbg("xDisconnect",...arguments); + VT.xVtab.dispose(pVtab); + return 0; + }, + xOpen: function(pVtab, ppCursor){ + dbg("xOpen",...arguments); + VT.xCursor.create(ppCursor); + return 0; + }, + xClose: function(pCursor){ + dbg("xClose",...arguments); + const c = VT.xCursor.unget(pCursor); + delete c.vTabState; + c.dispose(); + return 0; + }, + xNext: function(pCursor){ + dbg("xNext",...arguments); + const c = VT.xCursor.get(pCursor); + ++cursorState(c).rowid; + return 0; + }, + xColumn: function(pCursor, pCtx, iCol){ + dbg("xColumn",...arguments); + + const st = cursorState(pCursor); + const store = st.row(); + util.assert(store, "Unexpected xColumn call"); + switch(iCol){ + case cols.rowid.colId: + capi.sqlite3_result_int(pCtx, st.rowid); + break; + case cols.name.colId: + capi.sqlite3_result_text(pCtx, store.jzClass, -1, capi.SQLITE_TRANSIENT); + break; + case cols.nRef.colId: + capi.sqlite3_result_int(pCtx, store.refc); + break; + case cols.nOpen.colId: + capi.sqlite3_result_int(pCtx, store.files.length); + break; + case cols.isTransient.colId: + capi.sqlite3_result_int(pCtx, !!store.deleteAtRefc0); + break; + case cols.dbSize.colId: + capi.sqlite3_result_int(pCtx, storageGetDbSize(store)); + break; + default: + capi.sqlite3_result_error(pCtx, "Invalid column id: "+iCol); + return capi.SQLITE_RANGE; + } + return 0; + }, + xRowid: function(pCursor, ppRowid64){ + dbg("xRowid",...arguments); + const st = cursorState(pCursor); + VT.xRowid(ppRowid64, st.rowid); + return 0; + }, + xEof: function(pCursor){ + const st = cursorState(pCursor); + dbg("xEof?="+(!st.row()),...arguments); + return !st.row(); + }, + xFilter: function(pCursor, idxNum, idxCStr, + argc, argv){ + dbg("xFilter",...arguments); + const st = cursorState(pCursor, true); + return 0; + }, + xBestIndex: function(pVtab, pIdxInfo){ + dbg("xBestIndex",...arguments); + + const pii = new capi.sqlite3_index_info(pIdxInfo); + pii.$estimatedRows = cache.storagePool.size; + pii.$estimatedCost = 1.0; + pii.dispose(); + return 0; + } + } + }); + }; + + sqlite3.kvvfs.create_module = function(pDb, name="sqlite_kvvfs"){ + return capi.sqlite3_create_module(pDb, name, theModule(), + wasm.ptr.null); + }; + + } + + +}); + +globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ + 'use strict'; + if( sqlite3.config.disable?.vfs?.opfs && + sqlite3.config.disable.vfs['opfs-vfs'] ){ + return; + } + const toss = sqlite3.util.toss, + capi = sqlite3.capi, + util = sqlite3.util, + wasm = sqlite3.wasm; + + + const opfsUtil = sqlite3.opfs = Object.create(null); + + + opfsUtil.thisThreadHasOPFS = ()=>{ + return globalThis.FileSystemHandle && + globalThis.FileSystemDirectoryHandle && + globalThis.FileSystemFileHandle && + globalThis.FileSystemFileHandle.prototype.createSyncAccessHandle && + navigator?.storage?.getDirectory; + }; + + + opfsUtil.getRootDir = async function f(){ + return f.promise ??= navigator.storage.getDirectory().then(d=>{ + opfsUtil.rootDirectory = d; + return d; + }).catch(e=>{ + delete f.promise; + throw e; + }); + }; + + + opfsUtil.getResolvedPath = function(filename,splitIt){ + const p = new URL(filename, "file://irrelevant").pathname; + return splitIt ? p.split('/').filter((v)=>!!v) : p; + }; + + + opfsUtil.getDirForFilename = async function f(absFilename, createDirs = false){ + const path = opfsUtil.getResolvedPath(absFilename, true); + const filename = path.pop(); + let dh = await opfsUtil.getRootDir(); + for(const dirName of path){ + if(dirName){ + dh = await dh.getDirectoryHandle(dirName, {create: !!createDirs}); + } + } + return [dh, filename]; + }; + + + opfsUtil.mkdir = async function(absDirName){ + try { + await opfsUtil.getDirForFilename(absDirName+"/filepart", true); + return true; + }catch(e){ + + return false; + } + }; + + + opfsUtil.entryExists = async function(fsEntryName){ + try { + const [dh, fn] = await opfsUtil.getDirForFilename(fsEntryName); + await dh.getFileHandle(fn); + return true; + }catch(e){ + return false; + } + }; + + + opfsUtil.randomFilename = function f(len=16){ + if(!f._chars){ + f._chars = "abcdefghijklmnopqrstuvwxyz"+ + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"+ + "012346789"; + f._n = f._chars.length; + } + const a = []; + let i = 0; + for( ; i < len; ++i){ + const ndx = Math.random() * (f._n * 64) % f._n | 0; + a[i] = f._chars[ndx]; + } + return a.join(""); + + }; + + + opfsUtil.treeList = async function(){ + const doDir = async function callee(dirHandle,tgt){ + tgt.name = dirHandle.name; + tgt.dirs = []; + tgt.files = []; + for await (const handle of dirHandle.values()){ + if('directory' === handle.kind){ + const subDir = Object.create(null); + tgt.dirs.push(subDir); + await callee(handle, subDir); + }else{ + tgt.files.push(handle.name); + } + } + }; + const root = Object.create(null); + const dir = await opfsUtil.getRootDir(); + await doDir(dir, root); + return root; + }; + + + opfsUtil.rmfr = async function(){ + const rd = await opfsUtil.getRootDir(); + const dir = rd, opt = {recurse: true}; + for await (const handle of dir.values()){ + dir.removeEntry(handle.name, opt); + } + }; + + + opfsUtil.unlink = async function(fsEntryName, recursive = false, + throwOnError = false){ + try { + const [hDir, filenamePart] = + await opfsUtil.getDirForFilename(fsEntryName, false); + await hDir.removeEntry(filenamePart, {recursive}); + return true; + }catch(e){ + if(throwOnError){ + throw new Error("unlink(",arguments[0],") failed: "+e.message,{ + cause: e + }); + } + return false; + } + }; + + + opfsUtil.traverse = async function(opt){ + const defaultOpt = { + recursive: true, + directory: await opfsUtil.getRootDir() + }; + if('function'===typeof opt){ + opt = {callback:opt}; + } + opt = Object.assign(defaultOpt, opt||{}); + const doDir = async function callee(dirHandle, depth){ + for await (const handle of dirHandle.values()){ + if(false === opt.callback(handle, dirHandle, depth)) return false; + else if(opt.recursive && 'directory' === handle.kind){ + if(false === await callee(handle, depth + 1)) break; + } + } + }; + doDir(opt.directory, 0); + }; + + + const importDbChunked = async function(filename, callback){ + const [hDir, fnamePart] = await opfsUtil.getDirForFilename(filename, true); + const hFile = await hDir.getFileHandle(fnamePart, {create:true}); + let sah = await hFile.createSyncAccessHandle(); + let nWrote = 0, chunk, checkedHeader = false, err = false; + try{ + sah.truncate(0); + while( undefined !== (chunk = await callback()) ){ + if(chunk instanceof ArrayBuffer) chunk = new Uint8Array(chunk); + if( !checkedHeader && 0===nWrote && chunk.byteLength>=15 ){ + util.affirmDbHeader(chunk); + checkedHeader = true; + } + sah.write(chunk, {at: nWrote}); + nWrote += chunk.byteLength; + } + if( nWrote < 512 || 0!==nWrote % 512 ){ + toss("Input size",nWrote,"is not correct for an SQLite database."); + } + if( !checkedHeader ){ + const header = new Uint8Array(20); + sah.read( header, {at: 0} ); + util.affirmDbHeader( header ); + } + sah.write(new Uint8Array([1,1]), {at: 18}); + return nWrote; + }catch(e){ + await sah.close(); + sah = undefined; + await hDir.removeEntry( fnamePart ).catch(()=>{}); + throw e; + }finally { + if( sah ) await sah.close(); + } + }; + + + opfsUtil.importDb = async function(filename, bytes){ + if( bytes instanceof Function ){ + return importDbChunked(filename, bytes); + } + if(bytes instanceof ArrayBuffer) bytes = new Uint8Array(bytes); + util.affirmIsDb(bytes); + const n = bytes.byteLength; + const [hDir, fnamePart] = await opfsUtil.getDirForFilename(filename, true); + let sah, err, nWrote = 0; + try { + const hFile = await hDir.getFileHandle(fnamePart, {create:true}); + sah = await hFile.createSyncAccessHandle(); + sah.truncate(0); + nWrote = sah.write(bytes, {at: 0}); + if(nWrote != n){ + toss("Expected to write "+n+" bytes but wrote "+nWrote+"."); + } + sah.write(new Uint8Array([1,1]), {at: 18}) ; + return nWrote; + }catch(e){ + if( sah ){ await sah.close(); sah = undefined; } + await hDir.removeEntry( fnamePart ).catch(()=>{}); + throw e; + }finally{ + if( sah ) await sah.close(); + } + }; + + + opfsUtil.vfsInstallationFeatureCheck = function(vfsName){ + if( !globalThis.SharedArrayBuffer || !globalThis.Atomics ){ + toss("Cannot install OPFS: Missing SharedArrayBuffer and/or Atomics.", + "The server must emit the COOP/COEP response headers to enable those.", + "See https://sqlite.org/wasm/doc/trunk/persistence.md#coop-coep"); + }else if( 'undefined'===typeof WorkerGlobalScope ){ + toss("The OPFS sqlite3_vfs cannot run in the main thread", + "because it requires Atomics.wait()."); + }else if( !globalThis.FileSystemHandle || + !globalThis.FileSystemDirectoryHandle || + !globalThis.FileSystemFileHandle?.prototype?.createSyncAccessHandle || + !navigator?.storage?.getDirectory ){ + toss("Missing required OPFS APIs."); + }else if( 'opfs-wl'===vfsName && !globalThis.Atomics.waitAsync ){ + toss('The',vfsName,'VFS requires Atomics.waitAsync(), which is not available.'); + } + }; + + + opfsUtil.initOptions = function callee(vfsName, options){ + const urlParams = new URL(globalThis.location.href).searchParams; + if( urlParams.has(vfsName+'-disable') ){ + + return; + } + try{ + opfsUtil.vfsInstallationFeatureCheck(vfsName); + }catch(e){ + return; + } + options = util.nu(options); + options.vfsName = vfsName; + options.verbose ??= urlParams.has('opfs-verbose') + ? +urlParams.get('opfs-verbose') : 1; + options.sanityChecks ??= urlParams.has('opfs-sanity-check'); + + if( !opfsUtil.proxyUri ){ + opfsUtil.proxyUri = "sqlite3-opfs-async-proxy.js"; + if( sqlite3.scriptInfo?.sqlite3Dir ){ + + opfsUtil.proxyUri = ( + sqlite3.scriptInfo.sqlite3Dir + opfsUtil.proxyUri + ); + } + } + options.proxyUri ??= opfsUtil.proxyUri; + if('function' === typeof options.proxyUri){ + options.proxyUri = options.proxyUri(); + } + + return opfsUtil.options = options; + }; + + + opfsUtil.createVfsState = function(){ + const state = util.nu(); + const options = opfsUtil.options; + state.verbose = options.verbose; + + const loggers = [ + sqlite3.config.error, + sqlite3.config.warn, + sqlite3.config.log + ]; + const vfsName = options.vfsName + || toss("Maintenance required: missing VFS name"); + const logImpl = (level,...args)=>{ + if(state.verbose>level) loggers[level](vfsName+":",...args); + }; + const log = (...args)=>logImpl(2, ...args), + warn = (...args)=>logImpl(1, ...args), + error = (...args)=>logImpl(0, ...args), + capi = sqlite3.capi, + wasm = sqlite3.wasm; + + const opfsVfs = state.vfs = new capi.sqlite3_vfs(); + const opfsIoMethods = opfsVfs.ioMethods = new capi.sqlite3_io_methods(); + + opfsIoMethods.$iVersion = 1; + opfsVfs.$iVersion = 2; + opfsVfs.$szOsFile = capi.sqlite3_file.structInfo.sizeof; + opfsVfs.$mxPathname = 1024; + opfsVfs.$zName = wasm.allocCString(vfsName); + opfsVfs.addOnDispose( + '$zName', opfsVfs.$zName, opfsIoMethods + + ); + + opfsVfs.metrics = util.nu({ + counters: util.nu(), + dump: function(){ + let k, n = 0, t = 0, w = 0; + for(k in state.opIds){ + const m = metrics[k]; + n += m.count; + t += m.time; + w += m.wait; + m.avgTime = (m.count && m.time) ? (m.time / m.count) : 0; + m.avgWait = (m.count && m.wait) ? (m.wait / m.count) : 0; + } + sqlite3.config.log(globalThis.location.href, + "metrics for",globalThis.location.href,":",metrics, + "\nTotal of",n,"op(s) for",t, + "ms (incl. "+w+" ms of waiting on the async side)"); + sqlite3.config.log("Serialization metrics:",opfsVfs.metrics.counters.s11n); + opfsVfs.worker?.postMessage?.({type:'opfs-async-metrics'}); + }, + reset: function(){ + let k; + const r = (m)=>(m.count = m.time = m.wait = 0); + const m = opfsVfs.metrics.counters; + for(k in state.opIds){ + r(m[k] = Object.create(null)); + } + let s = m.s11n = Object.create(null); + s = s.serialize = Object.create(null); + s.count = s.time = 0; + s = m.s11n.deserialize = Object.create(null); + s.count = s.time = 0; + } + }); + + + state.asyncIdleWaitTime = 150; + + + state.asyncS11nExceptions = 1; + + state.fileBufferSize = 1024 * 64; + state.sabS11nOffset = state.fileBufferSize; + + state.sabS11nSize = opfsVfs.$mxPathname * 2; + + state.sabIO = new SharedArrayBuffer( + state.fileBufferSize + + state.sabS11nSize + ); + + + state.opIds = Object.create(null); + { + + let i = 0; + + state.opIds.whichOp = i++; + + state.opIds.rc = i++; + + state.opIds.xAccess = i++; + state.opIds.xClose = i++; + state.opIds.xDelete = i++; + state.opIds.xDeleteNoWait = i++; + state.opIds.xFileSize = i++; + state.opIds.xLock = i++; + state.opIds.xOpen = i++; + state.opIds.xRead = i++; + state.opIds.xSleep = i++; + state.opIds.xSync = i++; + state.opIds.xTruncate = i++; + state.opIds.xUnlock = i++; + state.opIds.xWrite = i++; + state.opIds.mkdir = i++ ; + + state.opIds['opfs-async-metrics'] = i++; + state.opIds['opfs-async-shutdown'] = i++; + + state.opIds.retry = i++; + state.sabOP = new SharedArrayBuffer( + i * 4); + } + + state.sq3Codes = Object.create(null); + for(const k of [ + 'SQLITE_ACCESS_EXISTS', + 'SQLITE_ACCESS_READWRITE', + 'SQLITE_BUSY', + 'SQLITE_CANTOPEN', + 'SQLITE_ERROR', + 'SQLITE_IOERR', + 'SQLITE_IOERR_ACCESS', + 'SQLITE_IOERR_CLOSE', + 'SQLITE_IOERR_DELETE', + 'SQLITE_IOERR_FSYNC', + 'SQLITE_IOERR_LOCK', + 'SQLITE_IOERR_READ', + 'SQLITE_IOERR_SHORT_READ', + 'SQLITE_IOERR_TRUNCATE', + 'SQLITE_IOERR_UNLOCK', + 'SQLITE_IOERR_WRITE', + 'SQLITE_LOCK_EXCLUSIVE', + 'SQLITE_LOCK_NONE', + 'SQLITE_LOCK_PENDING', + 'SQLITE_LOCK_RESERVED', + 'SQLITE_LOCK_SHARED', + 'SQLITE_LOCKED', + 'SQLITE_MISUSE', + 'SQLITE_NOTFOUND', + 'SQLITE_OPEN_CREATE', + 'SQLITE_OPEN_DELETEONCLOSE', + 'SQLITE_OPEN_MAIN_DB', + 'SQLITE_OPEN_READONLY', + 'SQLITE_LOCK_NONE', + 'SQLITE_LOCK_SHARED', + 'SQLITE_LOCK_RESERVED', + 'SQLITE_LOCK_PENDING', + 'SQLITE_LOCK_EXCLUSIVE' + ]){ + state.sq3Codes[k] = + capi[k] ?? toss("Maintenance required: not found:",k); + } + + state.opfsFlags = Object.assign(Object.create(null),{ + + OPFS_UNLOCK_ASAP: 0x01, + + OPFS_UNLINK_BEFORE_OPEN: 0x02, + + defaultUnlockAsap: false + }); + + opfsVfs.metrics.reset(); + const metrics = opfsVfs.metrics.counters; + + + const opRun = opfsVfs.opRun = (op,...args)=>{ + const opNdx = state.opIds[op] || toss(opfsVfs.vfsName+": Invalid op ID:",op); + state.s11n.serialize(...args); + Atomics.store(state.sabOPView, state.opIds.rc, -1); + Atomics.store(state.sabOPView, state.opIds.whichOp, opNdx); + Atomics.notify(state.sabOPView, state.opIds.whichOp) + ; + const t = performance.now(); + while('not-equal'!==Atomics.wait(state.sabOPView, state.opIds.rc, -1)){ + + } + + const rc = Atomics.load(state.sabOPView, state.opIds.rc); + metrics[op].wait += performance.now() - t; + if(rc && state.asyncS11nExceptions){ + const err = state.s11n.deserialize(); + if(err) error(op+"() async error:",...err); + } + return rc; + }; + + const opTimer = Object.create(null); + opTimer.op = undefined; + opTimer.start = undefined; + const mTimeStart = opfsVfs.mTimeStart = (op)=>{ + opTimer.start = performance.now(); + opTimer.op = op; + ++metrics[op].count; + }; + const mTimeEnd = opfsVfs.mTimeEnd = ()=>( + metrics[opTimer.op].time += performance.now() - opTimer.start + ); + + + const __openFiles = opfsVfs.__openFiles = Object.create(null); + + + const ioSyncWrappers = opfsVfs.ioSyncWrappers = util.nu({ + xCheckReservedLock: function(pFile,pOut){ + + wasm.poke(pOut, 0, 'i32'); + return 0; + }, + xClose: function(pFile){ + mTimeStart('xClose'); + let rc = 0; + const f = __openFiles[pFile]; + if(f){ + delete __openFiles[pFile]; + rc = opRun('xClose', pFile); + if(f.sq3File) f.sq3File.dispose(); + } + mTimeEnd(); + return rc; + }, + xDeviceCharacteristics: function(pFile){ + return capi.SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN; + }, + xFileControl: function(pFile, opId, pArg){ + + return capi.SQLITE_NOTFOUND; + }, + xFileSize: function(pFile,pSz64){ + mTimeStart('xFileSize'); + let rc = opRun('xFileSize', pFile); + if(0==rc){ + try { + const sz = state.s11n.deserialize()[0]; + wasm.poke(pSz64, sz, 'i64'); + }catch(e){ + error("Unexpected error reading xFileSize() result:",e); + rc = state.sq3Codes.SQLITE_IOERR; + } + } + mTimeEnd(); + return rc; + }, + xRead: function(pFile,pDest,n,offset64){ + mTimeStart('xRead'); + const f = __openFiles[pFile]; + let rc; + try { + rc = opRun('xRead',pFile, n, Number(offset64)); + if(0===rc || capi.SQLITE_IOERR_SHORT_READ===rc){ + + wasm.heap8u().set(f.sabView.subarray(0, n), Number(pDest)); + } + }catch(e){ + error("xRead(",arguments,") failed:",e,f); + rc = capi.SQLITE_IOERR_READ; + } + mTimeEnd(); + return rc; + }, + xSync: function(pFile,flags){ + mTimeStart('xSync'); + const rc = opRun('xSync', pFile, flags); + mTimeEnd(); + return rc; + }, + xTruncate: function(pFile,sz64){ + mTimeStart('xTruncate'); + const rc = opRun('xTruncate', pFile, Number(sz64)); + mTimeEnd(); + return rc; + }, + xWrite: function(pFile,pSrc,n,offset64){ + mTimeStart('xWrite'); + const f = __openFiles[pFile]; + let rc; + try { + f.sabView.set(wasm.heap8u().subarray( + Number(pSrc), Number(pSrc) + n + )); + rc = opRun('xWrite', pFile, n, Number(offset64)); + }catch(e){ + error("xWrite(",arguments,") failed:",e,f); + rc = capi.SQLITE_IOERR_WRITE; + } + mTimeEnd(); + return rc; + } + }); + + + const vfsSyncWrappers = opfsVfs.vfsSyncWrappers = { + xAccess: function(pVfs,zName,flags,pOut){ + mTimeStart('xAccess'); + const rc = opRun('xAccess', wasm.cstrToJs(zName)); + wasm.poke( pOut, (rc ? 0 : 1), 'i32' ); + mTimeEnd(); + return 0; + }, + xCurrentTime: function(pVfs,pOut){ + wasm.poke(pOut, 2440587.5 + (new Date().getTime()/86400000), + 'double'); + return 0; + }, + xCurrentTimeInt64: function(pVfs,pOut){ + wasm.poke(pOut, (2440587.5 * 86400000) + new Date().getTime(), + 'i64'); + return 0; + }, + xDelete: function(pVfs, zName, doSyncDir){ + mTimeStart('xDelete'); + const rc = opRun('xDelete', wasm.cstrToJs(zName), doSyncDir, false); + mTimeEnd(); + return rc; + }, + xFullPathname: function(pVfs,zName,nOut,pOut){ + + const i = wasm.cstrncpy(pOut, zName, nOut); + return i( + TypeIds[typeof v] + || toss("Maintenance required: this value type cannot be serialized.",v) + ); + const getTypeIdById = (tid)=>{ + switch(tid){ + case TypeIds.number.id: return TypeIds.number; + case TypeIds.bigint.id: return TypeIds.bigint; + case TypeIds.boolean.id: return TypeIds.boolean; + case TypeIds.string.id: return TypeIds.string; + default: toss("Invalid type ID:",tid); + } + }; + + + state.s11n.deserialize = function(clear=false){ + const t = performance.now(); + const argc = viewU8[0]; + const rc = argc ? [] : null; + if(argc){ + const typeIds = []; + let offset = 1, i, n, v; + for(i = 0; i < argc; ++i, ++offset){ + typeIds.push(getTypeIdById(viewU8[offset])); + } + for(i = 0; i < argc; ++i){ + const t = typeIds[i]; + if(t.getter){ + v = viewDV[t.getter](offset, state.littleEndian); + offset += t.size; + }else{ + n = viewDV.getInt32(offset, state.littleEndian); + offset += 4; + v = textDecoder.decode(viewU8.slice(offset, offset+n)); + offset += n; + } + rc.push(v); + } + } + if(clear) viewU8[0] = 0; + + return rc; + }; + + + state.s11n.serialize = function(...args){ + const t = performance.now(); + if(args.length){ + + const typeIds = []; + let i = 0, offset = 1; + viewU8[0] = args.length & 0xff ; + for(; i < args.length; ++i, ++offset){ + + typeIds.push(getTypeId(args[i])); + viewU8[offset] = typeIds[i].id; + } + for(i = 0; i < args.length; ++i) { + + const t = typeIds[i]; + if(t.setter){ + viewDV[t.setter](offset, args[i], state.littleEndian); + offset += t.size; + }else{ + const s = textEncoder.encode(args[i]); + viewDV.setInt32(offset, s.byteLength, state.littleEndian); + offset += 4; + viewU8.set(s, offset); + offset += s.byteLength; + } + } + + }else{ + viewU8[0] = 0; + } + }; + + + return state.s11n; +}; + opfsVfs.initS11n = initS11n; + + + opfsVfs.bindVfs = function(ioMethods, callback){ + Object.assign(opfsVfs.ioSyncWrappers, ioMethods); + const thePromise = new Promise(function(promiseResolve_, promiseReject_){ + let promiseWasRejected = undefined; + const promiseReject = (err)=>{ + promiseWasRejected = true; + opfsVfs.dispose(); + return promiseReject_(err); + }; + const promiseResolve = ()=>{ + try{ + callback(sqlite3, opfsVfs); + }catch(e){ + return promiseReject(e); + } + promiseWasRejected = false; + return promiseResolve_(sqlite3); + }; + const options = opfsUtil.options; + const proxyUri = options.proxyUri +( + (options.proxyUri.indexOf('?')<0) ? '?' : '&' + )+'vfs='+vfsName; + + const W = opfsVfs.worker = + new Worker(new URL(proxyUri, import.meta.url)); + let zombieTimer = setTimeout(()=>{ + + if(undefined===promiseWasRejected){ + promiseReject( + new Error("Timeout while waiting for OPFS async proxy worker.") + ); + } + }, 4000); + W._originalOnError = W.onerror ; + W.onerror = function(err){ + + + error("Error initializing OPFS asyncer:",err); + promiseReject(new Error("Loading OPFS async Worker failed for unknown reasons.")); + }; + + const opRun = opfsVfs.opRun; + + const sanityCheck = function(){ + const scope = wasm.scopedAllocPush(); + const sq3File = new capi.sqlite3_file(); + try{ + const fid = sq3File.pointer; + const openFlags = capi.SQLITE_OPEN_CREATE + | capi.SQLITE_OPEN_READWRITE + + | capi.SQLITE_OPEN_MAIN_DB; + const pOut = wasm.scopedAlloc(8); + const dbFile = "/sanity/check/file"+opfsUtil.randomFilename(8); + const zDbFile = wasm.scopedAllocCString(dbFile); + let rc; + state.s11n.serialize("This is ä string."); + rc = state.s11n.deserialize(); + log("deserialize() says:",rc); + if("This is ä string."!==rc[0]) toss("String d13n error."); + opfsVfs.vfsSyncWrappers.xAccess(opfsVfs.pointer, zDbFile, 0, pOut); + rc = wasm.peek(pOut,'i32'); + log("xAccess(",dbFile,") exists ?=",rc); + rc = opfsVfs.vfsSyncWrappers.xOpen(opfsVfs.pointer, zDbFile, + fid, openFlags, pOut); + log("open rc =",rc,"state.sabOPView[xOpen] =", + state.sabOPView[state.opIds.xOpen]); + if(0!==rc){ + error("open failed with code",rc); + return; + } + opfsVfs.vfsSyncWrappers.xAccess(opfsVfs.pointer, zDbFile, 0, pOut); + rc = wasm.peek(pOut,'i32'); + if(!rc) toss("xAccess() failed to detect file."); + rc = opfsVfs.ioSyncWrappers.xSync(sq3File.pointer, 0); + if(rc) toss('sync failed w/ rc',rc); + rc = opfsVfs.ioSyncWrappers.xTruncate(sq3File.pointer, 1024); + if(rc) toss('truncate failed w/ rc',rc); + wasm.poke(pOut,0,'i64'); + rc = opfsVfs.ioSyncWrappers.xFileSize(sq3File.pointer, pOut); + if(rc) toss('xFileSize failed w/ rc',rc); + log("xFileSize says:",wasm.peek(pOut, 'i64')); + rc = opfsVfs.ioSyncWrappers.xWrite(sq3File.pointer, zDbFile, 10, 1); + if(rc) toss("xWrite() failed!"); + const readBuf = wasm.scopedAlloc(16); + rc = opfsVfs.ioSyncWrappers.xRead(sq3File.pointer, readBuf, 6, 2); + wasm.poke(readBuf+6,0); + let jRead = wasm.cstrToJs(readBuf); + log("xRead() got:",jRead); + if("sanity"!==jRead) toss("Unexpected xRead() value."); + if(opfsVfs.vfsSyncWrappers.xSleep){ + log("xSleep()ing before close()ing..."); + opfsVfs.vfsSyncWrappers.xSleep(opfsVfs.pointer,2000); + log("waking up from xSleep()"); + } + rc = opfsVfs.ioSyncWrappers.xClose(fid); + log("xClose rc =",rc,"sabOPView =",state.sabOPView); + log("Deleting file:",dbFile); + opfsVfs.vfsSyncWrappers.xDelete(opfsVfs.pointer, zDbFile, 0x1234); + opfsVfs.vfsSyncWrappers.xAccess(opfsVfs.pointer, zDbFile, 0, pOut); + rc = wasm.peek(pOut,'i32'); + if(rc) toss("Expecting 0 from xAccess(",dbFile,") after xDelete()."); + warn("End of OPFS sanity checks."); + }finally{ + sq3File.dispose(); + wasm.scopedAllocPop(scope); + } + }; + + W.onmessage = function({data}){ + + switch(data.type){ + case 'opfs-unavailable': + + promiseReject(new Error(data.payload.join(' '))); + break; + case 'opfs-async-loaded': + + delete state.vfs; + W.postMessage({type: 'opfs-async-init', args: util.nu(state)}); + break; + case 'opfs-async-inited': { + + if(true===promiseWasRejected){ + break ; + } + clearTimeout(zombieTimer); + zombieTimer = null; + try { + sqlite3.vfs.installVfs({ + io: {struct: opfsVfs.ioMethods, methods: opfsVfs.ioSyncWrappers}, + vfs: {struct: opfsVfs, methods: opfsVfs.vfsSyncWrappers} + }); + state.sabOPView = new Int32Array(state.sabOP); + state.sabFileBufView = new Uint8Array(state.sabIO, 0, state.fileBufferSize); + state.sabS11nView = new Uint8Array(state.sabIO, state.sabS11nOffset, state.sabS11nSize); + opfsVfs.initS11n(); + opfsVfs.initS11n = null; + if(options.sanityChecks){ + warn("Running sanity checks because of opfs-sanity-check URL arg..."); + sanityCheck(); + } + if(opfsUtil.thisThreadHasOPFS()){ + opfsUtil.getRootDir().then((d)=>{ + W.onerror = W._originalOnError; + delete W._originalOnError; + log("End of OPFS sqlite3_vfs setup.", opfsVfs); + promiseResolve(); + }).catch(promiseReject); + }else{ + promiseResolve(); + } + }catch(e){ + error(e); + promiseReject(e); + } + break; + } + case 'debug': + warn("debug message from worker:",data); + break; + default: { + const errMsg = ( + "Unexpected message from the OPFS async worker: " + + JSON.stringify(data) + ); + error(errMsg); + promiseReject(new Error(errMsg)); + break; + } + } + }; + }); + return thePromise; + }; + + return state; + }; + +}); + +'use strict'; +globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ + if( !sqlite3.opfs || sqlite3.config.disable?.vfs?.opfs ){ + return; + } + const util = sqlite3.util, + opfsUtil = sqlite3.opfs || sqlite3.util.toss("Missing sqlite3.opfs"); + +const installOpfsVfs = async function(options){ + options = opfsUtil.initOptions('opfs',options); + if( !options ) return sqlite3; + const capi = sqlite3.capi, + state = opfsUtil.createVfsState(), + opfsVfs = state.vfs, + metrics = opfsVfs.metrics.counters, + mTimeStart = opfsVfs.mTimeStart, + mTimeEnd = opfsVfs.mTimeEnd, + opRun = opfsVfs.opRun, + debug = (...args)=>sqlite3.config.debug("opfs:",...args), + warn = (...args)=>sqlite3.config.warn("opfs:",...args), + __openFiles = opfsVfs.__openFiles; + + + + return opfsVfs.bindVfs(util.nu({ + xLock: function(pFile,lockType){ + mTimeStart('xLock'); + ++metrics.xLock.count; + const f = __openFiles[pFile]; + let rc = 0; + + if( f.lockType ) { + f.lockType = lockType; + }else{ + rc = opRun('xLock', pFile, lockType); + if( 0===rc ) f.lockType = lockType; + } + mTimeEnd(); + return rc; + }, + xUnlock: function(pFile,lockType){ + mTimeStart('xUnlock'); + ++metrics.xUnlock.count; + const f = __openFiles[pFile]; + let rc = 0; + if( capi.SQLITE_LOCK_NONE === lockType + && f.lockType ){ + rc = opRun('xUnlock', pFile, lockType); + } + if( 0===rc ) f.lockType = lockType; + mTimeEnd(); + return rc; + } + }), function(sqlite3, vfs){ + + if(sqlite3.oo1){ + const OpfsDb = function(...args){ + const opt = sqlite3.oo1.DB.dbCtorHelper.normalizeArgs(...args); + opt.vfs = vfs.$zName; + sqlite3.oo1.DB.dbCtorHelper.call(this, opt); + }; + OpfsDb.prototype = Object.create(sqlite3.oo1.DB.prototype); + sqlite3.oo1.OpfsDb = OpfsDb; + OpfsDb.importDb = opfsUtil.importDb; + if( true ){ + + sqlite3.oo1.DB.dbCtorHelper.setVfsPostOpenCallback( + opfsVfs.pointer, + function(oo1Db, sqlite3){ + + sqlite3.capi.sqlite3_busy_timeout(oo1Db, 10000); + } + ); + } + } + }); +}; +globalThis.sqlite3ApiBootstrap.initializersAsync.push(async (sqlite3)=>{ + return installOpfsVfs().catch((e)=>{ + sqlite3.config.warn("Ignoring inability to install 'opfs' sqlite3_vfs:",e); + }) +}); +}); + +globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ + 'use strict'; + if( sqlite3.config.disable?.vfs?.['opfs-sahpool'] ){ + return; + } + + const toss = sqlite3.util.toss; + const toss3 = sqlite3.util.toss3; + const initPromises = Object.create(null) ; + const capi = sqlite3.capi; + const util = sqlite3.util; + const wasm = sqlite3.wasm; + + const SECTOR_SIZE = 4096; + const HEADER_MAX_PATH_SIZE = 512; + const HEADER_FLAGS_SIZE = 4; + const HEADER_DIGEST_SIZE = 8; + const HEADER_CORPUS_SIZE = HEADER_MAX_PATH_SIZE + HEADER_FLAGS_SIZE; + const HEADER_OFFSET_FLAGS = HEADER_MAX_PATH_SIZE; + const HEADER_OFFSET_DIGEST = HEADER_CORPUS_SIZE; + const HEADER_OFFSET_DATA = SECTOR_SIZE; + + const PERSISTENT_FILE_TYPES = + capi.SQLITE_OPEN_MAIN_DB | + capi.SQLITE_OPEN_MAIN_JOURNAL | + capi.SQLITE_OPEN_SUPER_JOURNAL | + capi.SQLITE_OPEN_WAL; + const FLAG_COMPUTE_DIGEST_V2 = capi.SQLITE_OPEN_MEMORY + ; + + + const OPAQUE_DIR_NAME = ".opaque"; + + + const getRandomName = ()=>Math.random().toString(36).slice(2); + + const textDecoder = new TextDecoder(); + const textEncoder = new TextEncoder(); + + const optionDefaults = Object.assign(Object.create(null),{ + name: 'opfs-sahpool', + directory: undefined , + initialCapacity: 6, + clearOnInit: false, + + verbosity: 2, + forceReinitIfPreviouslyFailed: false, + preserveOnInitFailure: false + }); + + + const loggers = [ + sqlite3.config.error, + sqlite3.config.warn, + sqlite3.config.log + ]; + const log = sqlite3.config.log; + const warn = sqlite3.config.warn; + const error = sqlite3.config.error; + + + const __mapVfsToPool = new Map(); + const getPoolForVfs = (pVfs)=>__mapVfsToPool.get(pVfs); + const setPoolForVfs = (pVfs,pool)=>{ + if(pool) __mapVfsToPool.set(pVfs, pool); + else __mapVfsToPool.delete(pVfs); + }; + + const __mapSqlite3File = new Map(); + const getPoolForPFile = (pFile)=>__mapSqlite3File.get(pFile); + const setPoolForPFile = (pFile,pool)=>{ + if(pool) __mapSqlite3File.set(pFile, pool); + else __mapSqlite3File.delete(pFile); + }; + + + const ioMethods = { + xCheckReservedLock: function(pFile,pOut){ + const pool = getPoolForPFile(pFile); + pool.log('xCheckReservedLock'); + pool.storeErr(); + const file = pool.getOFileForS3File(pFile); + wasm.poke32( + pOut, + pool.hasReservedLock(file.path) ? 1 : 0 + + ); + return 0; + }, + xClose: function(pFile){ + const pool = getPoolForPFile(pFile); + pool.storeErr(); + const file = pool.getOFileForS3File(pFile); + if(file) { + try{ + pool.log(`xClose ${file.path}`); + pool.unlockFile(file, capi.SQLITE_LOCK_NONE); + pool.mapS3FileToOFile(pFile, false); + file.sah.flush(); + if(file.flags & capi.SQLITE_OPEN_DELETEONCLOSE){ + pool.deletePath(file.path); + } + }catch(e){ + return pool.storeErr(e, capi.SQLITE_IOERR); + } + } + return 0; + }, + xDeviceCharacteristics: function(pFile){ + return capi.SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN; + }, + xFileControl: function(pFile, opId, pArg){ + return capi.SQLITE_NOTFOUND; + }, + xFileSize: function(pFile,pSz64){ + const pool = getPoolForPFile(pFile); + pool.log(`xFileSize`); + const file = pool.getOFileForS3File(pFile); + const size = file.sah.getSize() - HEADER_OFFSET_DATA; + + wasm.poke64(pSz64, BigInt(size)); + return 0; + }, + xLock: function(pFile,lockType){ + const pool = getPoolForPFile(pFile); + pool.log(`xLock ${lockType}`); + pool.storeErr(); + const file = pool.getOFileForS3File(pFile); + return pool.lockFile(file, lockType); + }, + xRead: function(pFile,pDest,n,offset64){ + const pool = getPoolForPFile(pFile); + pool.storeErr(); + const file = pool.getOFileForS3File(pFile); + pool.log(`xRead ${file.path} ${n} @ ${offset64}`); + try { + const nRead = file.sah.read( + wasm.heap8u().subarray(Number(pDest), Number(pDest)+n), + {at: HEADER_OFFSET_DATA + Number(offset64)} + ); + if(nRead < n){ + wasm.heap8u().fill(0, Number(pDest) + nRead, Number(pDest) + n); + return capi.SQLITE_IOERR_SHORT_READ; + } + return 0; + }catch(e){ + return pool.storeErr(e, capi.SQLITE_IOERR); + } + }, + xSectorSize: function(pFile){ + return SECTOR_SIZE; + }, + xSync: function(pFile,flags){ + const pool = getPoolForPFile(pFile); + pool.log(`xSync ${flags}`); + pool.storeErr(); + const file = pool.getOFileForS3File(pFile); + + try{ + file.sah.flush(); + return 0; + }catch(e){ + return pool.storeErr(e, capi.SQLITE_IOERR); + } + }, + xTruncate: function(pFile,sz64){ + const pool = getPoolForPFile(pFile); + pool.log(`xTruncate ${sz64}`); + pool.storeErr(); + const file = pool.getOFileForS3File(pFile); + + try{ + file.sah.truncate(HEADER_OFFSET_DATA + Number(sz64)); + return 0; + }catch(e){ + return pool.storeErr(e, capi.SQLITE_IOERR); + } + }, + xUnlock: function(pFile,lockType){ + const pool = getPoolForPFile(pFile); + pool.log('xUnlock'); + const file = pool.getOFileForS3File(pFile); + pool.unlockFile(file, lockType); + return 0; + }, + xWrite: function(pFile,pSrc,n,offset64){ + const pool = getPoolForPFile(pFile); + pool.storeErr(); + const file = pool.getOFileForS3File(pFile); + pool.log(`xWrite ${file.path} ${n} ${offset64}`); + try{ + const nBytes = file.sah.write( + wasm.heap8u().subarray(Number(pSrc), Number(pSrc)+n), + { at: HEADER_OFFSET_DATA + Number(offset64) } + ); + return n===nBytes ? 0 : toss("Unknown write() failure."); + }catch(e){ + return pool.storeErr(e, capi.SQLITE_IOERR); + } + } + }; + + const opfsIoMethods = new capi.sqlite3_io_methods(); + opfsIoMethods.$iVersion = 1; + sqlite3.vfs.installVfs({ + io: {struct: opfsIoMethods, methods: ioMethods} + }); + + + const vfsMethods = { + xAccess: function(pVfs,zName,flags,pOut){ + + const pool = getPoolForVfs(pVfs); + pool.storeErr(); + try{ + const name = pool.getPath(zName); + wasm.poke32(pOut, pool.hasFilename(name) ? 1 : 0); + }catch(e){ + + wasm.poke32(pOut, 0); + } + return 0; + }, + xCurrentTime: function(pVfs,pOut){ + wasm.poke(pOut, 2440587.5 + (new Date().getTime()/86400000), + 'double'); + return 0; + }, + xCurrentTimeInt64: function(pVfs,pOut){ + wasm.poke(pOut, (2440587.5 * 86400000) + new Date().getTime(), + 'i64'); + return 0; + }, + xDelete: function(pVfs, zName, doSyncDir){ + const pool = getPoolForVfs(pVfs); + pool.log(`xDelete ${wasm.cstrToJs(zName)}`); + pool.storeErr(); + try{ + pool.deletePath(pool.getPath(zName)); + return 0; + }catch(e){ + pool.storeErr(e); + return capi.SQLITE_IOERR_DELETE; + } + }, + xFullPathname: function(pVfs,zName,nOut,pOut){ + + + const i = wasm.cstrncpy(pOut, zName, nOut); + return i nOut) wasm.poke8(wasm.ptr.add(pOut,nOut,-1), 0); + }catch(e){ + return capi.SQLITE_NOMEM; + }finally{ + wasm.scopedAllocPop(scope); + } + } + return e ? (e.sqlite3Rc || capi.SQLITE_IOERR) : 0; + }, + + xOpen: function f(pVfs, zName, pFile, flags, pOutFlags){ + const pool = getPoolForVfs(pVfs); + try{ + flags &= ~FLAG_COMPUTE_DIGEST_V2; + pool.log(`xOpen ${wasm.cstrToJs(zName)} ${flags}`); + + const path = (zName && wasm.peek8(zName)) + ? pool.getPath(zName) + : getRandomName(); + let sah = pool.getSAHForPath(path); + if(sah && (flags & capi.SQLITE_OPEN_CREATE) + && (flags & capi.SQLITE_OPEN_EXCLUSIVE)){ + toss('file already exists:', path); + } + if(!sah && (flags & capi.SQLITE_OPEN_CREATE)) { + + if(pool.getFileCount() < pool.getCapacity()) { + + sah = pool.nextAvailableSAH(); + pool.setAssociatedPath(sah, path, flags); + }else{ + + toss('SAH pool is full. Cannot create file',path); + } + } + if(!sah){ + toss('file not found:',path); + } + + + const file = {path, flags, sah}; + pool.mapS3FileToOFile(pFile, file); + file.lockType = capi.SQLITE_LOCK_NONE; + const sq3File = new capi.sqlite3_file(pFile); + sq3File.$pMethods = opfsIoMethods.pointer; + sq3File.dispose(); + wasm.poke32(pOutFlags, flags); + return 0; + }catch(e){ + pool.storeErr(e); + return capi.SQLITE_CANTOPEN; + } + } + }; + + + const createOpfsVfs = function(vfsName){ + if( sqlite3.capi.sqlite3_vfs_find(vfsName)){ + toss3("VFS name is already registered:", vfsName); + } + const opfsVfs = new capi.sqlite3_vfs(); + + const pDVfs = capi.sqlite3_vfs_find(null); + const dVfs = pDVfs + ? new capi.sqlite3_vfs(pDVfs) + : null ; + opfsVfs.$iVersion = 2; + opfsVfs.$szOsFile = capi.sqlite3_file.structInfo.sizeof; + opfsVfs.$mxPathname = HEADER_MAX_PATH_SIZE; + opfsVfs.addOnDispose( + opfsVfs.$zName = wasm.allocCString(vfsName), + ()=>setPoolForVfs(opfsVfs.pointer, 0) + ); + + if(dVfs){ + + opfsVfs.$xRandomness = dVfs.$xRandomness; + dVfs.dispose(); + } + if(!opfsVfs.$xRandomness && !vfsMethods.xRandomness){ + + vfsMethods.xRandomness = function(pVfs, nOut, pOut){ + const heap = wasm.heap8u(); + let i = 0; + const npOut = Number(pOut); + for(; i < nOut; ++i) heap[npOut + i] = (Math.random()*255000) & 0xFF; + return i; + }; + } + + vfsMethods.xSleep = (pVfs,ms)=>0; + sqlite3.vfs.installVfs({ + vfs: {struct: opfsVfs, methods: vfsMethods} + }); + return opfsVfs; + }; + + + class OpfsSAHPool { + + vfsDir; + + #dhVfsRoot; + + #dhOpaque; + + #dhVfsParent; + + #mapSAHToName = new Map(); + + #mapFilenameToSAH = new Map(); + + #availableSAH = new Set(); + + #mapS3FileToOFile = new Map(); + + #mapPathToLock = new Map(); + + + + + #apBody = new Uint8Array(HEADER_CORPUS_SIZE); + + #dvBody; + + + #cVfs; + + + #verbosity; + + + constructor(options = Object.create(null)){ + this.#verbosity = options.verbosity ?? optionDefaults.verbosity; + this.vfsName = options.name || optionDefaults.name; + this.#cVfs = createOpfsVfs(this.vfsName); + setPoolForVfs(this.#cVfs.pointer, this); + this.vfsDir = options.directory || ("."+this.vfsName); + this.#dvBody = + new DataView(this.#apBody.buffer, this.#apBody.byteOffset); + this.isReady = this + .reset(!!(options.clearOnInit ?? optionDefaults.clearOnInit)) + .then(()=>{ + if(this.$error) throw this.$error; + return this.getCapacity() + ? Promise.resolve(undefined) + : this.addCapacity(options.initialCapacity + || optionDefaults.initialCapacity); + }); + } + + #logImpl(level,...args){ + if(this.#verbosity>level) loggers[level](this.vfsName+":",...args); + }; + log(...args){this.#logImpl(2, ...args)}; + warn(...args){this.#logImpl(1, ...args)}; + error(...args){this.#logImpl(0, ...args)}; + + + getVfs(){return this.#cVfs} + + + getCapacity(){return this.#mapSAHToName.size} + + + getFileCount(){return this.#mapFilenameToSAH.size} + + + getFileNames(){ + const rc = []; + for(const n of this.#mapFilenameToSAH.keys()) rc.push(n); + return rc; + } + + + async addCapacity(n){ + for(let i = 0; i < n; ++i){ + const name = getRandomName(); + const h = await this.#dhOpaque.getFileHandle(name, {create:true}); + const ah = await h.createSyncAccessHandle(); + this.#mapSAHToName.set(ah,name); + this.setAssociatedPath(ah, '', 0); + + } + return this.getCapacity(); + } + + + async reduceCapacity(n){ + if(!Number.isSafeInteger(n) || n < 0){ + toss('Invalid capacity reduction:', n); + } + let nRm = 0; + for(const ah of Array.from(this.#availableSAH)){ + if(nRm === n || this.getFileCount() === this.getCapacity()){ + break; + } + const name = this.#mapSAHToName.get(ah); + ah.close(); + this.#mapSAHToName.delete(ah); + this.#availableSAH.delete(ah); + await this.#dhOpaque.removeEntry(name); + ++nRm; + } + return nRm; + } + + + releaseAccessHandles(){ + for(const ah of this.#mapSAHToName.keys()) ah.close(); + this.#mapSAHToName.clear(); + this.#mapFilenameToSAH.clear(); + this.#availableSAH.clear(); + this.#mapS3FileToOFile.clear(); + this.#mapPathToLock.clear(); + } + + + async acquireAccessHandles(clearFiles=false){ + const files = []; + for await (const [name,h] of this.#dhOpaque){ + if('file'===h.kind){ + files.push([name,h]); + } + } + const results = await Promise.allSettled(files.map(async([name,h])=>{ + const ah = await h.createSyncAccessHandle() + this.#mapSAHToName.set(ah, name); + if(clearFiles){ + ah.truncate(HEADER_OFFSET_DATA); + this.setAssociatedPath(ah, '', 0); + }else{ + const path = this.getAssociatedPath(ah); + if(path){ + this.#mapFilenameToSAH.set(path, ah); + }else{ + this.#availableSAH.add(ah); + } + } + })); + const failure = results.find((r)=>'rejected'===r.status) + ; + if( failure ){ + this.storeErr(failure.reason); + this.releaseAccessHandles(); + throw failure.reason; + } + } + + + getAssociatedPath(sah){ + sah.read(this.#apBody, {at: 0}); + + + const flags = this.#dvBody.getUint32(HEADER_OFFSET_FLAGS); + if(this.#apBody[0] && + ((flags & capi.SQLITE_OPEN_DELETEONCLOSE) || + (flags & PERSISTENT_FILE_TYPES)===0)){ + warn(`Removing file with unexpected flags ${flags.toString(16)}`, + this.#apBody); + this.setAssociatedPath(sah, '', 0); + return ''; + } + + const fileDigest = new Uint32Array(HEADER_DIGEST_SIZE / 4); + sah.read(fileDigest, {at: HEADER_OFFSET_DIGEST}); + const compDigest = this.computeDigest(this.#apBody, flags); + + if(fileDigest.every((v,i) => v===compDigest[i])){ + + const pathBytes = this.#apBody.findIndex((v)=>0===v); + if(0===pathBytes){ + + + sah.truncate(HEADER_OFFSET_DATA); + } + + return pathBytes + ? textDecoder.decode(this.#apBody.subarray(0,pathBytes)) + : ''; + }else{ + + warn('Disassociating file with bad digest.'); + this.setAssociatedPath(sah, '', 0); + return ''; + } + } + + + setAssociatedPath(sah, path, flags){ + const enc = textEncoder.encodeInto(path, this.#apBody); + if(HEADER_MAX_PATH_SIZE <= enc.written + 1){ + toss("Path too long:",path); + } + if(path && flags){ + + flags |= FLAG_COMPUTE_DIGEST_V2; + } + this.#apBody.fill(0, enc.written, HEADER_MAX_PATH_SIZE); + this.#dvBody.setUint32(HEADER_OFFSET_FLAGS, flags); + const digest = this.computeDigest(this.#apBody, flags); + + sah.write(this.#apBody, {at: 0}); + sah.write(digest, {at: HEADER_OFFSET_DIGEST}); + sah.flush(); + + if(path){ + this.#mapFilenameToSAH.set(path, sah); + this.#availableSAH.delete(sah); + }else{ + + sah.truncate(HEADER_OFFSET_DATA); + this.#availableSAH.add(sah); + } + } + + + computeDigest(byteArray, fileFlags){ + if( fileFlags & FLAG_COMPUTE_DIGEST_V2 ){ + let h1 = 0xdeadbeef; + let h2 = 0x41c6ce57; + for(const v of byteArray){ + h1 = Math.imul(h1 ^ v, 2654435761); + h2 = Math.imul(h2 ^ v, 104729); + } + return new Uint32Array([h1>>>0, h2>>>0]); + }else{ + + return new Uint32Array([0,0]); + } + } + + + async reset(clearFiles){ + await this.isReady; + let h = await navigator.storage.getDirectory(); + let prev, prevName; + for(const d of this.vfsDir.split('/')){ + if(d){ + prev = h; + h = await h.getDirectoryHandle(d,{create:true}); + } + } + this.#dhVfsRoot = h; + this.#dhVfsParent = prev; + this.#dhOpaque = await this.#dhVfsRoot.getDirectoryHandle( + OPAQUE_DIR_NAME,{create:true} + ); + this.releaseAccessHandles(); + return this.acquireAccessHandles(clearFiles); + } + + + getPath(arg) { + if(wasm.isPtr(arg)) arg = wasm.cstrToJs(arg); + return ((arg instanceof URL) + ? arg + : new URL(arg, 'file://localhost/')).pathname; + } + + + deletePath(path) { + const sah = this.#mapFilenameToSAH.get(path); + if(sah) { + + this.#mapFilenameToSAH.delete(path); + this.setAssociatedPath(sah, '', 0); + } + return !!sah; + } + + + storeErr(e,code){ + if(e){ + e.sqlite3Rc = code || capi.SQLITE_IOERR; + this.error(e); + } + this.$error = e; + return code; + } + + popErr(){ + const rc = this.$error; + this.$error = undefined; + return rc; + } + + + nextAvailableSAH(){ + const [rc] = this.#availableSAH.keys(); + return rc; + } + + + getOFileForS3File(pFile){ + return this.#mapS3FileToOFile.get(pFile); + } + + mapS3FileToOFile(pFile,file){ + if(file){ + this.#mapS3FileToOFile.set(pFile, file); + setPoolForPFile(pFile, this); + }else{ + this.#mapS3FileToOFile.delete(pFile); + setPoolForPFile(pFile, false); + } + } + + + hasFilename(name){ + return this.#mapFilenameToSAH.has(name) + } + + + getSAHForPath(path){ + return this.#mapFilenameToSAH.get(path); + } + + + async removeVfs(){ + if(!this.#cVfs.pointer || !this.#dhOpaque) return false; + capi.sqlite3_vfs_unregister(this.#cVfs.pointer); + this.#cVfs.dispose(); + delete initPromises[this.vfsName]; + try{ + this.releaseAccessHandles(); + await this.#dhVfsRoot.removeEntry(OPAQUE_DIR_NAME, {recursive: true}); + this.#dhOpaque = undefined; + await this.#dhVfsParent.removeEntry( + this.#dhVfsRoot.name, {recursive: true} + ); + this.#dhVfsRoot = this.#dhVfsParent = undefined; + }catch(e){ + sqlite3.config.error(this.vfsName,"removeVfs() failed with no recovery strategy:",e); + + } + return true; + } + + + pauseVfs(){ + if(this.#mapS3FileToOFile.size>0){ + sqlite3.SQLite3Error.toss( + capi.SQLITE_MISUSE, "Cannot pause VFS", + this.vfsName,"because it has opened files." + ); + } + if(this.#mapSAHToName.size>0){ + capi.sqlite3_vfs_unregister(this.vfsName); + this.releaseAccessHandles(); + } + return this; + } + + + isPaused(){ + return 0===this.#mapSAHToName.size; + } + + + async unpauseVfs(){ + if(0===this.#mapSAHToName.size){ + return this.acquireAccessHandles(false). + then(()=>capi.sqlite3_vfs_register(this.#cVfs, 0),this); + } + return this; + } + + + exportFile(name){ + const sah = this.#mapFilenameToSAH.get(name) || toss("File not found:",name); + const n = sah.getSize() - HEADER_OFFSET_DATA; + const b = new Uint8Array(n>0 ? n : 0); + if(n>0){ + const nRead = sah.read(b, {at: HEADER_OFFSET_DATA}); + if(nRead != n){ + toss("Expected to read "+n+" bytes but read "+nRead+"."); + } + } + return b; + } + + + async importDbChunked(name, callback){ + const sah = this.#mapFilenameToSAH.get(name) + || this.nextAvailableSAH() + || toss("No available handles to import to."); + sah.truncate(0); + let nWrote = 0, chunk, checkedHeader = false, err = false; + try{ + while( undefined !== (chunk = await callback()) ){ + if(chunk instanceof ArrayBuffer) chunk = new Uint8Array(chunk); + if( !checkedHeader && 0===nWrote && chunk.byteLength>=15 ){ + util.affirmDbHeader(chunk); + checkedHeader = true; + } + const n = sah.write(chunk, {at: HEADER_OFFSET_DATA + nWrote}); + if( n!==chunk.byteLength ){ + toss("Expected to write "+chunk.byteLength+ + "bytes but wrote"+n+"."); + } + nWrote += chunk.byteLength; + } + if( nWrote < 512 || 0!==nWrote % 512 ){ + toss("Input size",nWrote,"is not correct for an SQLite database."); + } + if( !checkedHeader ){ + const header = new Uint8Array(20); + sah.read( header, {at: HEADER_OFFSET_DATA} ); + util.affirmDbHeader( header ); + } + sah.write(new Uint8Array([1,1]), { + at: HEADER_OFFSET_DATA + 18 + }); + }catch(e){ + this.setAssociatedPath(sah, '', 0); + throw e; + } + this.setAssociatedPath(sah, name, capi.SQLITE_OPEN_MAIN_DB); + return nWrote; + } + + + importDb(name, bytes){ + if( bytes instanceof ArrayBuffer ) bytes = new Uint8Array(bytes); + else if( bytes instanceof Function ) return this.importDbChunked(name, bytes); + util.affirmIsDb(bytes); + const sah = this.#mapFilenameToSAH.get(name) + || this.nextAvailableSAH() + || toss("No available handles to import to."); + const n = bytes.byteLength; + const nWrote = sah.write(bytes, {at: HEADER_OFFSET_DATA}); + if(nWrote != n){ + this.setAssociatedPath(sah, '', 0); + toss("Expected to write "+n+" bytes but wrote "+nWrote+"."); + }else{ + sah.truncate(HEADER_OFFSET_DATA + n + ); + sah.write(new Uint8Array([1,1]), {at: HEADER_OFFSET_DATA+18} + ); + this.setAssociatedPath(sah, name, capi.SQLITE_OPEN_MAIN_DB); + } + return nWrote; + } + + + hasReservedLock(filename){ + const lk = this.#mapPathToLock.get(filename); + return !!lk && lk.lockType>capi.SQLITE_LOCK_SHARED; + } + + + lockFile(file, lockType){ + if(file.lockType>=lockType) return 0; + let lk = this.#mapPathToLock.get(file.path); + if(!lk){ + lk = Object.assign(Object.create(null),{ + nShared: 0, lockType: capi.SQLITE_LOCK_NONE + }); + this.#mapPathToLock.set(file.path, lk); + } + if(file.lockType!==lk.lockType + && (lk.lockType>=capi.SQLITE_LOCK_PENDING + || lockType>capi.SQLITE_LOCK_SHARED)){ + return capi.SQLITE_BUSY; + } + if(lockType===capi.SQLITE_LOCK_SHARED){ + ++lk.nShared; + if(lk.lockType===capi.SQLITE_LOCK_NONE) lk.lockType = lockType; + }else if(lockType===capi.SQLITE_LOCK_EXCLUSIVE && lk.nShared>1){ + if(file.lockType===capi.SQLITE_LOCK_RESERVED){ + file.lockType = lk.lockType = capi.SQLITE_LOCK_PENDING; + } + return capi.SQLITE_BUSY; + }else{ + lk.lockType = lockType; + } + file.lockType = lockType; + return 0; + } + + + unlockFile(file, lockType){ + if(file.lockType<=lockType) return; + const lk = this.#mapPathToLock.get(file.path); + if(file.lockType>capi.SQLITE_LOCK_SHARED){ + lk.lockType = capi.SQLITE_LOCK_SHARED; + } + if(lockType===capi.SQLITE_LOCK_NONE && 0===--lk.nShared + ){ + this.#mapPathToLock.delete(file.path); + } + file.lockType = lockType; + } + + }; + + + class OpfsSAHPoolUtil { + + #p; + + constructor(sahPool){ + this.#p = sahPool; + this.vfsName = sahPool.vfsName; + } + + async addCapacity(n){ return this.#p.addCapacity(n) } + + async reduceCapacity(n){ return this.#p.reduceCapacity(n) } + + getCapacity(){ return this.#p.getCapacity(this.#p) } + + getFileCount(){ return this.#p.getFileCount() } + getFileNames(){ return this.#p.getFileNames() } + + async reserveMinimumCapacity(min){ + const c = this.#p.getCapacity(); + return (c < min) ? this.#p.addCapacity(min - c) : c; + } + + exportFile(name){ return this.#p.exportFile(name) } + + importDb(name, bytes){ return this.#p.importDb(name,bytes) } + + async wipeFiles(){ return this.#p.reset(true) } + + unlink(filename){ return this.#p.deletePath(filename) } + + async removeVfs(){ return this.#p.removeVfs() } + + pauseVfs(){ this.#p.pauseVfs(); return this; } + async unpauseVfs(){ return this.#p.unpauseVfs().then(()=>this); } + isPaused(){ return this.#p.isPaused() } + + }; + + + const apiVersionCheck = async ()=>{ + const dh = await navigator.storage.getDirectory(); + const fn = '.opfs-sahpool-sync-check-'+getRandomName(); + const fh = await dh.getFileHandle(fn, { create: true }); + const ah = await fh.createSyncAccessHandle(); + const close = ah.close(); + await close; + await dh.removeEntry(fn); + if(close?.then){ + toss("The local OPFS API is too old for opfs-sahpool:", + "it has an async FileSystemSyncAccessHandle.close() method."); + } + return true; + }; + + + sqlite3.installOpfsSAHPoolVfs = async function(options=Object.create(null)){ + options = Object.assign(Object.create(null), optionDefaults, (options||{})); + const vfsName = options.name; + if(options.$testThrowPhase1){ + throw options.$testThrowPhase1; + } + if(initPromises[vfsName]){ + try { + const p = await initPromises[vfsName]; + + return p; + }catch(e){ + + if( options.forceReinitIfPreviouslyFailed ){ + delete initPromises[vfsName]; + + }else{ + throw e; + } + } + } + if(!globalThis.FileSystemHandle || + !globalThis.FileSystemDirectoryHandle || + !globalThis.FileSystemFileHandle || + !globalThis.FileSystemFileHandle.prototype.createSyncAccessHandle || + !navigator?.storage?.getDirectory){ + return (initPromises[vfsName] = Promise.reject(new Error("Missing required OPFS APIs."))); + } + + + const unregisterVfs = (thePool)=>{ + const cVfs = thePool.getVfs(); + if( cVfs?.pointer ){ + capi.sqlite3_vfs_unregister(cVfs.pointer); + cVfs.dispose(); + thePool.releaseAccessHandles(); + } + }; + + + return initPromises[vfsName] = apiVersionCheck().then(async function(){ + if(options.$testThrowPhase2){ + throw options.$testThrowPhase2; + } + const thePool = new OpfsSAHPool(options); + return thePool.isReady.then(async()=>{ + + const poolUtil = new OpfsSAHPoolUtil(thePool); + if(sqlite3.oo1){ + const oo1 = sqlite3.oo1; + const theVfs = thePool.getVfs(); + const OpfsSAHPoolDb = function(...args){ + const opt = oo1.DB.dbCtorHelper.normalizeArgs(...args); + opt.vfs = theVfs.$zName; + oo1.DB.dbCtorHelper.call(this, opt); + }; + OpfsSAHPoolDb.prototype = Object.create(oo1.DB.prototype); + poolUtil.OpfsSAHPoolDb = OpfsSAHPoolDb; + } + thePool.log("VFS initialized."); + return poolUtil; + }).catch(async (e)=>{ + if( options.preserveOnInitFailure ){ + unregisterVfs(thePool); + }else{ + await thePool.removeVfs().catch(()=>{}); + } + throw e; + }); + }).catch((err)=>{ + + return initPromises[vfsName] = Promise.reject(err); + }); + }; +}); + +'use strict'; +globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ + if( !sqlite3.opfs || sqlite3.config.disable?.vfs?.['opfs-wl'] ){ + return; + } + const util = sqlite3.util, + toss = sqlite3.util.toss; + const opfsUtil = sqlite3.opfs; + const vfsName = 'opfs-wl'; + +const installOpfsWlVfs = async function(options){ + options = opfsUtil.initOptions(vfsName,options); + if( !options ) return sqlite3; + const capi = sqlite3.capi, + state = opfsUtil.createVfsState(), + opfsVfs = state.vfs, + metrics = opfsVfs.metrics.counters, + mTimeStart = opfsVfs.mTimeStart, + mTimeEnd = opfsVfs.mTimeEnd, + opRun = opfsVfs.opRun, + debug = (...args)=>sqlite3.config.debug(vfsName+":",...args), + warn = (...args)=>sqlite3.config.warn(vfsName+":",...args), + __openFiles = opfsVfs.__openFiles; + + + + return opfsVfs.bindVfs(util.nu({ + xLock: function(pFile,lockType){ + mTimeStart('xLock'); + + const f = __openFiles[pFile]; + const rc = opRun('xLock', pFile, lockType); + if( !rc ) f.lockType = lockType; + mTimeEnd(); + return rc; + }, + xUnlock: function(pFile,lockType){ + mTimeStart('xUnlock'); + const f = __openFiles[pFile]; + const rc = opRun('xUnlock', pFile, lockType); + if( !rc ) f.lockType = lockType; + mTimeEnd(); + return rc; + } + }), function(sqlite3, vfs){ + + if(sqlite3.oo1){ + const OpfsWlDb = function(...args){ + const opt = sqlite3.oo1.DB.dbCtorHelper.normalizeArgs(...args); + opt.vfs = vfs.$zName; + sqlite3.oo1.DB.dbCtorHelper.call(this, opt); + }; + OpfsWlDb.prototype = Object.create(sqlite3.oo1.DB.prototype); + sqlite3.oo1.OpfsWlDb = OpfsWlDb; + OpfsWlDb.importDb = opfsUtil.importDb; + + } + }); +}; +globalThis.sqlite3ApiBootstrap.initializersAsync.push(async (sqlite3)=>{ + return installOpfsWlVfs().catch((e)=>{ + sqlite3.config.warn("Ignoring inability to install the",vfsName,"sqlite3_vfs:",e); + }); +}); +}); + +try{ + + + + const bootstrapConfig = Object.assign( + Object.create(null), + + { + memory: ('undefined'!==typeof wasmMemory) + ? wasmMemory + : EmscriptenModule['wasmMemory'], + exports: ('undefined'!==typeof wasmExports) + ? wasmExports + : (Object.prototype.hasOwnProperty.call(EmscriptenModule,'wasmExports') + ? EmscriptenModule['wasmExports'] + : EmscriptenModule['asm']) + }, + globalThis.sqlite3ApiBootstrap.defaultConfig, + globalThis.sqlite3ApiConfig || {} + ); + + sqlite3InitScriptInfo.debugModule("Bootstrapping lib config", bootstrapConfig); + + + const p = globalThis.sqlite3ApiBootstrap(bootstrapConfig); + delete globalThis.sqlite3ApiBootstrap; + return p ; +}catch(e){ + console.error("sqlite3ApiBootstrap() error:",e); + throw e; +} + + +}; + + + + + + + + + + + + return Module; +} + + + + + +const toExportForESM = +(function(){ + + + const originalInit = sqlite3InitModule; + if(!originalInit){ + throw new Error("Expecting sqlite3InitModule to be defined by the Emscripten build."); + } + + const sIMS = globalThis.sqlite3InitModuleState = Object.assign(Object.create(null),{ + moduleScript: globalThis?.document?.currentScript, + isWorker: ('undefined' !== typeof WorkerGlobalScope), + location: globalThis.location, + urlParams: globalThis?.location?.href + ? new URL(globalThis.location.href).searchParams + : new URLSearchParams(), + + wasmFilename: 'sqlite3.wasm' + }); + sIMS.debugModule = + sIMS.urlParams.has('sqlite3.debugModule') + ? (...args)=>console.warn('sqlite3.debugModule:',...args) + : ()=>{}; + + if(sIMS.urlParams.has('sqlite3.dir')){ + sIMS.sqlite3Dir = sIMS.urlParams.get('sqlite3.dir') +'/'; + }else if(sIMS.moduleScript){ + const li = sIMS.moduleScript.src.split('/'); + li.pop(); + sIMS.sqlite3Dir = li.join('/') + '/'; + } + + const sIM = globalThis.sqlite3InitModule = function ff(...args){ + + sIMS.emscriptenLocateFile = args[0]?.locateFile ; + sIMS.emscriptenInstantiateWasm = args[0]?.instantiateWasm ; + return originalInit(...args).then((EmscriptenModule)=>{ + sIMS.debugModule("sqlite3InitModule() sIMS =",sIMS); + sIMS.debugModule("sqlite3InitModule() EmscriptenModule =",EmscriptenModule); + const s = EmscriptenModule.runSQLite3PostLoadInit( + sIMS, + EmscriptenModule , + !!ff.__isUnderTest + ); + sIMS.debugModule("sqlite3InitModule() sqlite3 =",s); + + + return s; + }).catch((e)=>{ + console.error("Exception loading sqlite3 module:",e); + throw e; + }); + }; + sIM.ready = originalInit.ready; + + if(sIMS.moduleScript){ + let src = sIMS.moduleScript.src.split('/'); + src.pop(); + sIMS.scriptDir = src.join('/') + '/'; + } + sIMS.debugModule('extern-post-js.c-pp.js sqlite3InitModuleState =',sIMS); + return sIM; +})(); +sqlite3InitModule = toExportForESM; +export default sqlite3InitModule; diff --git a/vendor/sqlite3mc/2.6.1-3.54.0/sqlite3.wasm b/vendor/sqlite3mc/2.6.1-3.54.0/sqlite3.wasm new file mode 100644 index 0000000000000000000000000000000000000000..97011627911de83621a42e260e7a0dcc9ae40c2e GIT binary patch literal 1072003 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

Bc+`{!!J4f;K64o@9Er@eaq;5i9FzLVZ+ z3lXmG#yzSMa0t;R;}mO)r*7(2>j`q)6pv)lY+Tsl@DheKYsi(s`B5epV^I!-e%NR@ zltCNEYpa@`9e}XVRG~v16b&(+et+}50dJwzm)CVUrkemxOHaF*52h5 z1(jcl(|(_aM2DWKbWNVl`k!Tl$cB*hY-$u@LoISL{0ILB`0OLfuX*XQksnJf#^ebq zL6hX*8}%ET)3pndh~XO1_Oo-evxglL9ds!3tHNcY^O7u8 zGAivGG4IF$$k{L#vPIG6F6k=Fgh0@`R2` zvEzi!IqAnYd3KH#z>KoQ=pR27i70O_2hi-#@JxQR6NI$CfS;*e!J%Pwho#K~p{&_9 zfJWnF=Wac-v+lh(a_?FjMQnEx$j-*B(AvSPjFZk^RB=SB3G?$8OrWg()(-(iDtkfS%?W(~7UNL8+6Jg7y22`3!7W zmz|3kX2R5tQUlQ^g%gLt zvk9>A|FEy^tz!2a?8nufKL+=`p+*nQu%z_;^hq!eD$af;4oIlO9r zdAjf2PfKuNpzGjQTuTm&Op7ZK>pNZzst{hx!b|8Gp-aPm8mIg5<)aBC;su7)!7UIr znK76^)OG5Q{4N38y9A8zFHg{vel?aUMf7+3MtIoeH}N=}zqwn=~h^;qYzcLwEbtE<)nJrsP;daM(1+j%#f1wxKv%OY%{^d5fMPCy^D4dmPh=VoD{BLG zR$(=_`TS_Hb7HxA`7e~sk-Q=BL&>Hr0{ev|m_(1TR~rO4hgwBEPzSs*@oaCK7hBqi zR{TMd1O{A|Z< z3-4@OxZ^W^duO!ZV4UEDUUWrf9T^pu&9(bGY?T&$lxN`O@$EJz0q7oHz95xVJlvCq zWL$3E9w~+pju4-@6fTlk$g5#BMDmIIUHdd|na1uy{F*M;Wt(-`p23s2Y$pz$0W}cO zW`$-FIbb)59E4vaLrNy`4W!(+4WDjb*hKzW<+zLTTL^JyJg+yS4w;B<#N-<#YGsNZ zo#AlUO|pZ3_&UR@8?0KG^55f#QtRHMY~1-D?PN&obZrP=6j z^0vtcRTG6Jx6+Qg<+tI3MO~lQ{GJTC4cvf1nIEGsH!gnTX%cga2$cUT^cYbb5OJ>P z z8&qP|5eIqs3*9zxcJQzf+Ywl0NvJU(WDi%hilXGJ-(!MU@f70bdf=@0u@0W?+o9sO zb(mI3O#zM)gQI8E6(9Ej<)RJnNfbilu)K)h*iK-OT^}NBAOR^KB-cCU%a;9hSD^su z)L(x8H1SH?cT!j;OCKmo`;fw$FzvbAEI-#=b2FBw510}#wl2E>K07hHAc1lKMasen zMhYtKFBqbegZ&cq4$<;2+5sBJ{^rn(C|AuJC(Va3Y4&2wG_wsg)I!Oq9Fr=P9u&#< z`-!=RY6a{QGn#FnVY3jRG0-MKvaI+i3A=l9Z11#GY%kb-H_|A{fLmgFnezq=GMo2} zg^|$!2P74vXbgh{jaLTccjrlQ_%vnKalE1%dd{InkQ_7%UXoT+42tcK^?a7e*O21R z7Uu3>=NsKNJX@eb7c7DWHK=73(Xqy0_O*7(g)NB*aA$6wf^xkSv+|Hh5Kly3UdmBB?#%?KsE2SG%|#VbROC^t3kz&`qpCSc&_OeUot|L zw-yxbgTR3Dt!5gAHk5NeIPq2q#@Cw{p-<;+uDBIOYRn&}*o{esq&Pe({|39BoT~NHz@Hd^bRa1TdoA7LSv~UFf0BRJ-c?|*|qWP zQuXyi22U0&{Om;@gv^8akNHgRq}4!LobXgX=5!8Y|1{#Q0`lAZob)5GvE@2;IQ$!H zOgx5(H}}1-m3V`vIMI-$o{7ReNz{|_5bp3Qcac2fW6C?{*KiKcaXuBfFoh2!>ilLe~A2ZTd>(1#= zS`7M*;tY8+Mvtzc_G{V(x~T#A70xM}2B3R{IgyI({8_rI{x44W7H6lFuSJ#g zczWmA$3Xg94N18tZU`8uj``fR<##w+)hw##(bCjb!{7J|VC1W6S@9!9w?Shfiicz{4%E zjTM9wAXks69*eBP1#TZZYvG}&Q@R4zGQW~Ds*t#^nXd16?{xk7y&hgbAFqL7K`=B| z=%24*Ky(5s2+4%830H-`EIdrle?{U+APT5(f#Vun094&Azdx_WkR(mJryq)_QBGG2 z7)UjZ53=ma1&i~8Lr5S|LY*pmAV6$`h5%u|gua#r4@iS_f->7x_e@;EH>Zp=J7Vuu z(_dY(%%^Bz`C}@6ARjebw(+-rS}cr5Rq`UXiqCQzMZhBzv+2Auy4fasF$v69#e7T z$%I@yc|24`4o0yret#dM88V0ttN%Fg8Y^PMxhk1~1-Ar-0dsw|@!ZwkFapML_3O(g zTdx>uz8dUegSXylG)D-R)N5dlP#b*$*_?nAKt7odPJ3J{6r0^+3vU?AFWXtaY&Q|1 z&6Y*!+dz407+$B$BuF%lzi&JW1Ae`yBjs5)jVvR(4_9BdfG z?@rREhw^ERZFqixDv|B2{J>UCK`o?g}Kwt~Ngy;o!=7J1Y2;}?e-fa%TeK=68 zCS#O{!1;`Y0lF&V2 zPlg10Z!JSaE$zhm-e(C!*kM#FZtbS!zTi%!;FQ*-(qZUC28D%oDj!f7g+>~!^vtGg zw2WC}3*K_?lJQFFLTY)LW?39C;I2`F1VFXy%xc=bXoodcXSIwnayvQ8J$|I%WX?ap zNX1HyH#xMUkHQ)1#qx?JvB5Shh>^)o_|;%LyR)r~omvsAXVW+@7U6MdmFF+6%U`KC zg8=d(RP@+tKpEd=5^7ohSWS-~$#x$cH+aR8!15!F)WW6!_hR`@6Bwap__tuzn^Z)? zK~8^xcibF0ZF-boHU`y~A155r=Ph)E??UqUODRn-!e(BknY}EgDpOKuzZxAoF~n>&n{TcKezRA z4YeqPftHH$$|dC;U384gnx~L~=MJBkzLn1yo;-Nsq0E#V>9C`cJBXN*iCCWOehvf| zDL~>q?5n2xt4OiI`q3$~hp3nar7| zhL+M#40aHqU~w*Kd<`G>eZuYTp=#tJJ33RK#&Rg}1{KFc7FrbB?3*XD;S&^Cv*mkx zgD22w3Pa?FU{&)dD!Ick_fd8#HKyPqJW}GDowo=v#J*>Z|I^HaiUPZrKaex!dVv+j zu~6T-HH8b(YPFA(#n*X-T?u8G>#GC&_IoAO{iz8NTF$8d`X-eWx`O4BX>@&J|UN8~W$M zT=^QxZ*(vk!vzn7Sg9wC;!#-OwJ@SaX>zGsUI%1}fTi9;OF(0}plZm6LP`;TcdZeI zr%=a?4>seME1LMjpv$Y5@N_%me0aj(#DxKZ^_ehi9%Rp_l+L!bgU3vJF;`un6(@LM zdHus2Wv$4RxQG?q=&bnLANRvT=`wl%V?G6tyqOSd6R@A-kUAQtBpBu+9lW@ z0+DzEjAZO!_KPQjIjSB_WA6{qkh%4l{xEU&Rx4Yj%!i}Zmkyqu~Vd!;Y} zan6(b%TG;_o$ilSolh;5DP;q^HT#^HvXl}|gz?3^%HT&!16de-Q_ymBE< z7ac9*Tu29a@p$Qm{4kh1e{%AZqFoHn#7-;dy1%m$Tx|B!T3QnqL3RgF>x>6PLHUUg z*>4u*(WTdlrdfqhE!$re`^W1qHFLfRFj+9P{|cNPH-_O!cmb2ZK&QzYgV-Xx0=xlttM-8qmal!~WhT2w2y zk-MvwZM!JuD4GvL3Za0F*#UWB74VlBDh3=$gye-pp&GGNEBzK#Bja3Ijht00OvhDa z;yv2YM60_M%Pm?J{5#kvWfOD7h$z7pcQ=p0stv3Z^q4yVcDljYveRQyLyTj5)$Aj| z9uZ2iwxz%ppf^ft+wk!%gB{9FF8rJHrwDp0)NU`7LB$qkq!m-(G~^ThI$-`3>6GfU zBLBtfdiP0A#WppHAWr;c9PHuK2%WYqnILuthHS$}P+!_b4lrMLI+c9I#l6R&E#?0ZU~&|Z9c$!sY$TmiM#qypv%rX~Q#!u5 z*ET{dcESwjH4Iwz6;SfvBTR4`Ze{ z*>KGIiS+kVc$C0EG^~A=%pM{gL8F z_fu>?TJl3!>457 zS}K0nQYfw&{6P9i&@HCW22_l}B9E;)j|Ds9O{Zk>-@TuDezj>~m;Q@*U{kZ}fVH;O zru(NC?tkj}M6^Ekyy0UdjmENMX7yGMAy63xAs@87PY#0E0`2?ofL@hcka@!&91yv4 z*K^eZbh|I?;5C)jD2V9|js1S(x8^ey$AWELlx@ScgM_>C5D?h0{LJBF4+RY)VN&v` zJEAt7eo(Cjp&@lvqO)L?-WkVS8b=eR#%_jj7DD>z(Hd2J;fh=b-Xt@8R3DuMi%n-Cdr19~p$<%_@QWb^(IRn_ z`&MiUa%woLxK>yKo*9V79nK9vPceLS$op>nP){Gp)*7;iNw^JpEJfW_%XEE}s?pecQ+N;Mb%-*Vb zcM~+|Af$lCP{dQ*ba<;x*Dm>;Pg;tp1xO z*AfCybUsKvjPl^bkm0h0SYWDx{h3u}8S)62+Dg zJbmXIB7_y@UD?2xSlsdx`rtE;cX(XW-Q6!;g3@#6u>_o$YUzX_` zpR|z}z!4Tf8r(!uY6J1Tf?#ueq&Jjlj+2=5!W+0CK^90zh7iOFgZdZ@v`zBv zi%a3zMmTxf5Q>4RXt%q1XQD(oH@RnBXeY(`!vx@&@`DZYB?b?*10nK|on?bZL4Tq! z>N41lqzMi^T7)Bwn8*}51BQhFQ4=@Ph+Xrb6byMxDo|E`j0UrlJyD5jPayk|h|7@b z;1F@4f`wnKG}(~rZ8AZ(S}aN(KTpi2Qs6e40j4m{G}5l}SB@)0^YpCy0qS-ccZCu_2d3bjc#rRPs zEg>1L^r?&Lcl65lMPLef+C|@_UZSe>4iMr`YT9u|-cM&>-^uA|`BZ29UXfL?px8l2+!BR)gFT{%8Iz(!AjX%e&%XH8@JA(GOE zVg$WYSH}>$9B~uDdW4vtKl#yq^(ZT-%vtnEFh6GL5A%$ws+i(CVV+tSjH>djC3#8B8<#aAXLvX z9!}R<%u5h~R60nA3n_?FXyIMZj8dCD2cboIsc*a&Eup2EbWz&Nq{E(unoynks+a}k zk35*@y=S=2m=ybsMO%@JVvPql_&0NOOnW4hoh8_z$8N)ROySm<+Dh(lMIl%PH0g{- zwnDv#N65B>kK5=V%6M4!#i$^nb{3#J-S%-&|0u;55#2@oU+j>;8pK4QNIv<(ABg-k zL9pwH=OXft>2PAkTOyT%Z<-lsctttVB#ougM$^C@&LE6qWRu>4&KOY&B(lof%mUo} zaOvfs62dVf2n7+kWI(M};;Ui{2$SWp1Def!d2-+-{(w1xXL2ogZ%TOQr(nK-n9Nbp z*&=R<^T%>&+A}lz*pMI_CyTLA&B_3*oZ6>@w{x=_tusJKpKCM}x6=$Z%U#Ekqn zkYSQZ7gThz&YlTey!B1kh59TH8!(+M!8Fh&C7BEgO7?g;Hc;wp!Vb~DT+`_A1Iirn z;)p;%yXDV;z3juog-+ea8CLcm$gVsmZKGd>kX_tkB$`w1rtu#n3#N&A46CL@#x>HM zA*HR4S!Fy1GA_>wV7vCU^57ommNH($FyR42Wdf>Z(VBC76!>ljN zt@GsJ&S(u@s=tLF87r#TT;b@T5^CdQRQiP7MUi>?87^5pIDYjn~e0-V-qdjqG&(LonbqR7_A&kJ74bqzZt6 z<_eQci2$`gKJ=x3k}_DJu_Z)h+_P;R6iDwugV#ud$3uB4NBX-T^JEpb=+K2gElDA4 z{VGYhkyEh+(E=G}Z6T)?@g=c2L%k|ePP95otMVcydm*^~(AVWqPwWzFDtF>VvM14` z*vF>95Yx=lKR6geB+AhpB9%AjdzBJkUG{8Ur&C4WwrD4c3KL}{E1`??z|{X#!Vo2Z zw1_HDEKnGNys9@gGalv)V?xB@DVA?Az90*}A|dAK2W@nX^;a=DPC_6f=BRnx zwFLc8GJ!UPTD*ctgwo=)i|eCyALqt})P@<0Q`yRM7-D%QhBv_lM@zl|_7JW^_`aF+ z`>8`qYrY7@Z&l2dUIkyHuF${u3l+lM4Gqs&b{YIz&k z1>hfLkxxr~7aN>R2OVt4SLs@z{}~}3{eHr)oh$dW8{`*{&sXt7hM{CIZD8^mwCsj_ zyA@gH%viR$YTP~BScXN1`OcH_?R-@#rl-i`AxT9m`kX@5b=eZu`$jG=U2y+IzUfWp z7+~FXcqctJ&;qE7c5^OVK_;lYj?lH!#IRB!QwTw&h{)=w_HQX1y}BecaKvYiY|7tK zOgp))#z|86$#t5^*5eQm0Gy_4(UEGstL}lcQ!EiLVfqU;r^y_ZCx&=_0zZJ6?Ok`* zl^eG*?6fc|h!{DhNk?uAsFzercShCFG%!A1I3W`bSRtL$Q6`Y~vRz(`*d;u5#KrZ| zzgjP4p^uI$92ObpE)g36jSG?=OLwg*Tyz%&7ZCuiY-^Wrw5!H zZpP}?HAmZ_1#Hz&HWLjY^XdaR?{Wuy;GJUP&I6rv3+d{u&g88JX3{;xmG`=f?mh6p z(djO-$-C3d-Su00d}EAN4Av?HN=>Q_ZivfgxBfd(+7qQwN$Mhvr~<-sn0TXUW)eBM z+oVdD7_1P}MJ{(_bvvuocofMnpWO0Q`B&204y90UpC1e2&%y%_?T+3A^m?8h;v3D%ap0`3RZ z<6|U)`uf<6pWi?0dO2Fd=aLsmrV}DXxuQ(60MFK^tBt13r^%%|4u=)wh-?-Z@2)XHcA5y0<1plbfj3! zexb$1#H1mEg|;Xrq!v_>xQS%EVqtYFONC2l14wKUgGSMk$6K;-cNa zp^+h&j0edOv}q$ly7j-#6Fd!zRav3wi&4n!j8$<`*y$0Hr3)p}?%)Vd%NrD;)S)6& z>I~^ZVU26*G1~DAdIpj3bs~6l3Lh8;l;Eubxv_4d=h+RIVReof$Gd3}#Wc0&gq4_W zY$&rl$J?*v&1ON>uIwplbptoup*%iLNjHo7%DvNP3@QBZsnaM?@E}#bo-&H6<6K<}n5j`KJbi3jG8N&`jMow3YPQ|u&TPuTuA3~nIx?=MSzK#8FSaCC&)!~) zLNMROiHs!PD}2i#FzI44_yhxNg_1q4NXiq%=}M5Lq9iJ5DC2>dk+;Ij!k&pKL z=UxydggV*~vm{UHh8fugbrgGts_)p0bFw!-8{yEasVL7cA$QQyHOF9Da!;`*oG4uK z8uLh>2$c=U3fLLo2gVmH0if0dTGwjvtD$H<&H!^Hl8!4*dn(w*5=lRvIYj1*TV!2K z8UV?|HXHJqBAr*O9_=V~HK3b{v8T1yauWwZ167F?v^F)-%u?*75@=UewUg_P zAet1-Tz4^S6n4BI&$Ne)dD26`Os#DKEIeU{?m(gh z0PDTj@?ig(S?C@%$nv7o^*F}fk_;;q)>6wngqAlli|e@%YsVrRk;&aT5KC8(1nfP3 zn=2S87rEXn*pb36pYmZu%pnhxV!4<%%8M^buTUnJ&n<2-_x>Tf(T|FL2d=)l9$Y6AlVDE2F-aDL@%hzH_PQ2!jmP^Op zF#(T6tPNuto?z9#{~_PArxLGLp8MbTAIPqp`2N(@Vimqyz*pVd6?;r`EHA=Yl@%Yh zownG80*crTjE`>O5WSZHBo6c8B`V)m>5ioG%O`QpZkj$`n8rikNU!BSgT_mI$oER; zvWJ7kYoLvj?3cQH!l#h>It&1?@Pi3Xq+;qSzqoz{YG*_4wmTAL1D?ivlLrE}2-zM` zQqYAQ?v6dv^*~jG6~MxqUVXrA4&W)yjmyqRUmAr557)Qsck5XWa-nLp;X5S&;wYqa zMU8Lyx;AEq#XEpd4#(E#gB8rBtdrGmbSZXnP7l`<9)Rb=w1c=T&JN@0`Q7<7qw8Sewqiu&c8XpI_JK9~V*Q6+#ZNar|N+QE=J#bqs%(JE51{ud7N>Q2d9woIy& za=h0s**2UZz{Csgwgn6uTIzY=0ZM50o`>++ur+JR#;S$&doO(!q6^!KSDwWXx$m3& zntW`--b*=H!N<7oWAk+AHe*~&M9JUFpF&;!R@%9AqHlh$zjW`@hXlV6u9qq8$VPQ( z<=~e&>cJ&JmrGAP!jG+rSRY({MN|w^o-;A#e;|5BYu)nP(Iz&0KX-H-h}zR4OKQ;w z2yAr|wvMYdy-QKOsXFd=Y^km9$g<}G5qIA$cqx6$G?dRz1vZC5^Rdw;pQN34_Q#v5 zP0!Q+EUHb~)K~y`7wH(WWL7ium~ncB;?ut8i=Ru!jR8>{K-60x9y&SbQtM!L@Dq=% z9`|%8ACL1Ym;Lkg*lOlDPGR0N;tOFy^a^{mVrEGxQBFcB{js7T$^z1%*~GNol|$7Z zd}K@1sZyCCH7`M_{ZvAfup2qRdL~?CA}i0(t`9F82Dp~PxUgA2{3jCp$Tm`iBz!Yh z?16-@U9~+`6C(0Hg?$6#)v>}p7%F8Ec-XgQ_4>l#VMdIpdPrCy?w$Zb{Ct3 zZi105x{C)#w_=8oCsJKNIt_%3xizmIceAAxEr{%e&uQD9tv<6%nUEsq&&~78ACa+9 z;JDxpxKnudc9!qdfww#gE0JAT@=LcKxatX)sW)&zf00Zhz!P+g(64KM zyoQUc7MacZ57V|vgZ15KKtEs-#Fwuw`u*>67K;GvEt+${nPb|z-8luN0)!Q5WdQHK zDW(Vq5DNOOJjMEym-NL{NGam4L%(CPiAu_X?NXya3kch<#1h)Cp;;R6G3S_a=>f-r zc<`vXj=nM+&UH+*1X&vI?OeKDh}utpy@!|li(AfDkR@8Ybg!5A3VI#Ki7^(B8V61M zt!D$uc;Tba0u#pvlLY(m{`$N;OX?>U@uD%%aHcCS@)v~{2deT$3_d2d9Xc9$7R-D^ ze0RXGbD#H*CyrCllwJ|PIjvs1w6nkba6XoYE7xmqqv|BRn&B-F%Kljhr3!PC1q#cW zxp`S~t{Bz^&a)<91ZISBCz{Hss~=i^C|5@HA4+G@u9v+xTfQH>5nKEX<4Rr~(M*KS zCO8g2xmDr33^Rd_&|o5wJrEMTl)s%H<*f5EjUHcYiJtdF*cr?b=*u)s_HfzHm)Qmh z37*~EKM6>@NCL%xET=T4l>_{I1=Ro?-pvJ9C$sS@$FW)x3Ov5CvHuv}b>_DSmUBas z5w@fwu=<%?6u9o^l>Q1HO*mz5Q!eM_>HU7Z4jq4`=&y|L<$g9x9noX?ft+cg72DZw z3~B!A#6dv)hsA`5Fx-!<{9vByxA}T3ub($RT_1d;vn7tp$0>5&_{DyCj2M#{`R)Ch z&WP4A`$wg5xY;>u<;DIuLx3t`^ZvhuiL~14j2Mzu57FSNwTBh_Rj$OkE#{ zC|^6%UlT7g(L!-V{l?9V{-w2yPRoDNK@JpK1nRl<%@Kaj${*#@D3AS^rpSnheS+5d zf__;kPwig^dZI-9RU(|AtT+$J4i2;(yqylj39zKZ2hi{~!PP5;tSGNa;nl3Z zv3-SehXZxD6y+<0@e7dsb9q*@nr=P8Z&xv%M9^R{4^XoDv+2oo+3ki>cBvo;vIgush8P!r6UD`fC zYW+{ag%tN^_(5dV|14~rLHR~>Uwi$(+~mEz@izLWiN+am?%&YJOz_bi?qs49G?uE_=2*A6CqfggSRMxhsfan*SqVDT48wQh-+j;gaHiHTM=oX{yhPJDVB-LSoUKAuVoA0$ETHoSH}IW0A< zD=^)v$metAm`%*ZDc{R_?ThO7UDI=iL^t6F#3w0ixwWx*4EY&543^-=Ezi9dTU5;P zLz{#gI{OOIsmK{0PgwZP9^B)p`na@FU{vr>{G{ISVOMr+igY3k zGJGArsYWryApblcnV`qwE%^!@fp$KiL2(U~8uM(P2Ge<{2nb}2 zxA~;N)o-w$nr$(r0U$8Vt&K?=`$7_tzlQvLM3`z_=z^Y5KGFLp=>p1;IDqU!VFd9S z+9)m|zVkL=8#)sLggjn5F;|WYEPzGT*_`*8(+uFuN|Adfv2Z1zI z{v}umlClyPyTlnTgRZ{w4?G5xL0THp^KaQ1FCs)CXGW5;oVXV}k1q=X8*LWGJfhZe zt)-`i%aDl+B&q?+0_95g4wW;2RI#G+OeB41v#oPcu*m3u*yYd2Y$6NX?e9()`EJ%2 zwsXbHh$d-=os_TPlgHie4fE2?2tLhEYv=et{Bxm#=3Ht;6&yGNk!OR6UCdL*wS2KV zNQTj?Wk(8|@f7`S3zk#|fCP$hq^X4wFolX_B!WBoVVI3meSi&TSB8BPCCtLdi3?Q|JyX;y3l5#48lzfTr)o#-dq$8zya5-;;g`#&yh@=UF?z z>mare-Nx2Tku*->ZTJJP%@KBq%5g{v?ln_^dRi&}tjqopWy=l6#qU*N=+e;qLwU=y8nK0B-Or}i7zMe#15VisuT3CR+We4K>11ZiS-&j0?Pod^!gKbZ7&*%1W!EptX0 zNa3DQsDuA$X3QrcDn=7bdK2__UD3aPNzuQ&d)d4|03%^oz4gr~hRCbhV}%DaeMSwE zF0TKPWy@+8F0%?jg$0LYBTk|9UB1fHP}j=Z+!u%#P}gGbh)6W6zhg5pU<7M-P<29W zWqK8xBQ>nE7EpGP#$FVkD!ArVdZnX&qkibL951Olavho*#tz`(q1pMlG5F?_BP%hh z4vL6Qmw+EGrmdElFCKvmtdrt_ig^fcPI+&{(!ug)b~H25!Dy=3LQ7l+|5Fs`#Hu=g z4S-D?$9}qemfJ$2W30^>^b-ueiX8dc zSr8sSS*;mFw^G=7CbZZ}>>^x6F{x9q1?gcKJM$h`!v~(@S!|d9ZCAX54+)G3KyR## zN9RFg%IAs;Qh_3@bpaCr*4;Rb<~>-1Cxs14QQ|vhIT7|0M3nN~@rT{SiVspDfl+?+Z z5yhMMHzTGa+4_ug$r(Y5Tmbl=)Bu1H+f9?f*ZIldy7S;^ITKSL;+r~$seK$$-rINC z=&&kg4!er__`5>n9M(V!;4?e-joG`kI_$jFBV<-JwR7KS*kP`?Rz53K6f-S>QcIcJ8QJ{42yL<`5L%R#=TXS33Ga5<|5CM`VT56v4s4*s@AUa6c zxQC(6eZtPsP`P~IO`2jH7MJW!CJfMEoY4j_xZ*ibSE{f7f&=X6zrx-M@vO+V|wlkCZU{ zJxlh24+=g!e@BxNOBnHh4l$btL@bjEHm_$R)eCBvOP7Nq0Z6y(tYT@--tMk?@BN)1 zJa}iXrENuBk?GBOZf|!xSzg?R@{@#9=}()M+A3FB1)y+ev|9}?yYyzV{FOeK40zbhoM05bK!PA1g~m((u{?-umg+8MsgcBEg0hPfax?SC zRz>H^OuE{WBqTtF57zB}OFMv>2U{B@H@Z@LZU!ZMxMyZML#w{!Z>GjZO;5;7uk#D% z&w_{CcV;;#>%=SqBOCHZotQ1>kt>RmIC_Yiu59!fa7oDQKz34g1YfEXvxo39b55lw ztAT=eR%u+_k@j$}hvi$*Y7=vAU*uR%%ue8akU?^nJb$(+T|Yb)y?A|Vy3U{!*yI|G zfl*mj^q<}sl3^iWFgZ|b=J^ss%|L-rn#xwrE=qA038S;zS4A=ta1A-htp6)Cix>ku zv`Z7a;VbxPDtMD$VR!1af~btDmL4|bXGQJMSqZ-^>aRpySIu`Y%l@qvK1`%qSLxS zRxNruaH6^bCnshr(#PSx*Z`k8rnjooe_n&zl{$t_)S9+t1g?w$MR6DBQnw;0EB`?W z2B%O^A!7LUc4UJ`Z&|283^B#n?!}FB`aU}a!{>`lLth5O`uo?($>S*owsb^7pi@oZ z;U}9)s)^k+11Wj=k8ND@g7T|k+{>OZMxWiJfB1P{UVaT-EL_l0tA@A{Y|Uv)$d_@) z$1%jD25zlE>)kh@B$M?KZGFA%2z)0-(``-w9o%@Rl}6((eE%otOGs$4xsT;>q7M@TY&p*IRQ~SL)HThb+K%Q{2rRn;2 zK8bV4t=^s}1et6pfI@h!+_|5H?dPOXVv=AzhJu4@l41uez^6a8yGhr;M+Y#}gRo{& z@oFB3{+}I*fh_LCw3q+0xzbFXH`eISAjX0+L0SBIPriLu`7eP82sG?RLMUPPU|rC< zWM%jD6jIS7hBMbXVb6hOlCsBK)7k`K&R0<*A%%1f*PN`}z!@cM?fVeHx@^WK*JVrR z<;s>ZZ`m9FTL}tuuJZnSb5y(?G}Ain9M&oFtR;B%2)9f6g@v4QgbAnoKocBa!z=hl zoI0qe;~Q1k@d?Sq6-jEjkqKV%{z^#yTY35I7`sDG;}<4wp~NZA4l=~={$Gll@;hOl zVwvtP(Fqa=x^rhYP4K3>DN)po_#mBj4O*tL5-LDKqX(;Z<#qS%i`NGa%2 znW?QhBl6Qcw%1Z9){(_dm59n26nmfJcbOU0*v#pxJ;gJXE6H}9v^5+GkcX!^*mB&V zV5TBoosr7MGO& zsmYsgp3xDrwt|lMf|-E@&2wlfP3R=p-`3BEO>m@_?6}5bpF;gdZq~ zFaWdh3>{3>hw&VOS=K&Ey5T8IGXmo_OT)Gqpm3|aer7y{m(rS_%NONBNAIB0JBX1FpnWO`cb307GoGO> zU=?Bg@_w0r$|YS?kMFEs``!*qx7+TPQ+sCfrR86AvG>P16-#&1$=1vX5K;dm0ZSjpN7UsI5XOMr|74&8 zS>8o;R9j7w=2vdbpMr_;zPsX>*;o@bQ{T(>+%n#SG|!mgR2#TXTUers!)oF;79%#i zJkxRaT|%Ll?vL1YQvUGxHg$2mx3h~vikH+6*)^uVui`QvL{@ojn!D4Jcil>w0;RNW z0k6l6$j)Y;fg=LFD4Q9@Q$k2MGEjaHf?Ib=!x%EeVR1~3!n?y1aQ@g&4Uwc;m_opX zp8=n_THH-S;Iris_y%JCV@cjw&F-`SGNW(Nwdhm_$1`kO-)5J{d1_mwCmeF?nrWp2A z^5HSlmshN1&|=`=Tva*2(>cELF`GW{!8^om`hb99Z%iQQ9VCQ4T#Lx65pt|gbA>Q= z1az0AGt+~0g}&WpfhvN;KWt$HM<#yU&UJo;H9h5Uxf2h@d@T~ISTZ42Ef<@rU&;A` z1m9lStz%+Vx^YJs0SJ2&9>V-)qC-*E#!q@7QH_fEv?f*@1AR29Exd{%0 zN=sJCRR7@_f)<03kHtD56WIQ2L@cUYX}lwrl&#BRGYUj}`Iea^;D4B7>JZYslZx*g z2@m(zw{$(Li}#KxSd4T#tDnU!d|0Ea}rJXpP^LFVvu)QmegP0WEl2!QixqX+}8nK09b`~^l0}g8!>$5 ztKa{kE_q#y3jUw_lpRdEm5@!U3s6X@DiFKCOiHN}+J-UnQjw}pDQb0{5_NN+7VQ+@ zzyhWO10aCMvwpUoCz{JdBAvSf0zH>w0I2WjP)ZYy1!YsksuPOu!6tq!Pbj|Ce5L*S zny++lPkc4;u7yzc`)qmC!+VR-n1kA3`qfw(h87l*xabsH7%+iClvXG!9(w^+d{J*? zmns4oWR&zG`9@BuydAOS^T1DZar!JMzj;Quaa524N3ftDJrFJ6L*%;{VCOg;Y)UBKmtW5MoL##C5Ykyge2m=y zNC*;*L0t0}IzjXAtftRc-Dh?JiA)tl83vGZbe0GGDEVWiz`y6x39l-cR@wHW{0w8z zYY|sm!d+5G@uP{7ajlJ#fhxvb-kbBV--04RA5WKmG-Gm-G>r{Ks+Z~^B_(+$c|s@E|s6CaVf)jK+mK+LsJmim@gFGOVzo>G|feKK#<4 zm4vEzoe!aXpsn!HcYs>(nIdkg{=_8&45l}{KyI?1UO02mQiNZ)wWhocU&n1y41&}Y zF$O}pb4vJx(0ja?QfDSgvU;iN|9=hIi_Yt}hPX$7T{PPEKxX_^YeNiH+^Gs=~_5%Gaea z)NLk5IUBz${EfwMJ8GA*)fxOpRH@HEq{K0(1Hl?~xd~bvkD~wL5XUJARufe@etYfeMpgxHZl|BCC6Lj%W{FY=mY^o8C^of9ri2TSM<7bFu14N%I|* z`EtAm36r12Ko}`U`u!`4rbLwUTndz8bditdU+}`*Sm9Z9(ko1PR`1Q3d>S=e#ppPi z2l^Hu2Iy|7S$(t|2nJ#q5G)p9F(py?otY6tA6kOjj365n!D5mTm7$b2y8<+vYl@9| zo(jXbp|ug3k%1==>&oTI#e7fp6XA=9u5}Xs(pz-OjHT|P9mbF<6+SR5mZfCxos<(q zjg<*>W3omh=qjq7X510O;1y#K(il4SiNBfVs(A9atGABTY8*YVk`x+3n_&gLc#bgl z<6L0h3LBO&{*$-YW&P0r`vb{1S|Q>U(Gw;pK>>|WWTd)>p;$37>H#O4n9T(q_|Clx zq#wM0_*5sR=AV`=C!9#c)5x4y5z;GPkJgC0Z*=Vf-p?mBYguJ>Qa-1kN|Tvdswv=N zxaGTS=yDojGH8n3TW=mM6$WL6>7tpffAr(GTz}0wU-Pf4-1u>(T5)o=+7Fg9o{X*U zw~}uUjc=>?<{kvRejye#5^d7OX9sm`QDV1K&VxLe1p&pZZd~pulBY|o@a1S`}C3Ug9 zuC}7LA-zUt27=dR8)ax#gk8eEFw~0iBVI6zhyBmP2FW~TfZVIMX5pCn&VAwEC5qEG z*c@-M1dmvbkjzwU@p>9aM#gR77dvsD3_`1`Q@KfJ&(`Wy<0Gpj`!CyC?SYJ_;3~FA zwMk2Yq0NwN7#P%MWl@k^fCov6k}|59)4VfeE-^FC`8RNyz!&SdtDd$`_!2wN=TC;o z12;SH70T;-<31VuX|!!*%P66Pjcu7jJf^D^ny3N*BV4UC;XMd(rF}7nJrllW_Ii=+ zlv3ChY3F!Z{Dfj?TA?5>?cf$0W+)#ef|L$Vje=LkYIiZxYR@>1`ffUib1<4d2o`Wu zE^NiTj1Mp008a?jbai;W3aAogMH)KXH^i&{8qq;YG^g=Jsa0l&ItdbLW1VWP9*}+4 zWydy`96U@K4VQm1vwysD&({1>ka0w{@(Mm7Jm0KVj8-y~mDLfZu7j=)W4c$SS$3%? zor@`^HysPNqB_DDMijaX!GO_{#0C_t2*HNn5_i2@LFK9(!|Y>N?F?#$tXJ^w$a7bh zHz*3=#SK9zr)Y&G*}N^C{Q-QS*!<6d%oXtDIDrPcSDG&GC-6E+EHNQq;>-w70{1T9 zo_~c^Vd<5?W0Ic4PEO$o!$KWHLggip^44G`j8++xAOhwHoywox@<#|PBQ66i(THXs zq;on(?T4LkLDC{9g>LzAif^Ulw2Fk{9iW}5?~F>c>HaEg2VMkoS@?2!d0Lk%0wGzt z-D9#<3oWw3I6>X1@A+y6XyWO43}D#Q*M^N*q+HrG#R^g2U>pceV2BH;7L#4!HSvCE z5npPM0!WzWVMjbOtffXP6~m6^LI<#$wreV+n|ABYb{4;1l#Jp)Zq!rE^CwOOaXg-e z7Q*V@W?2;@QmzpOX^n8r<@u)qBJ9^Z1xBRT0_uc1l>Yyfgf`>GmTh7rl07;PeAdLX zmcuHv*QH!DXyer#XrpLSuhWS(u$RL@L39O0jTt08Fa*|j{^O6|)!SV^{30$fGpk61 z;O}r-Z`o2e+UK_hZp<}>d#H6oeEkl(2tJRvKRq%5Hchm^=cxVC!C1qdch0iLAB2Rji`qd7@#R!X&IJb} zG2I_wtOW?+OBp(yxfv;`k=-y9;lMyhHFZo@ozQt1gXSCN*oE=tY*m=j3Ghg;(5-f9 z$STZJep~A*07#X^<9yOnc|ulmLkajWqxn6(v>g(&o0pi9m}Kz$6i; zO$0eFtUfgj7TQ_>2{ICh1g0^I=oFScye?SR?2^3l4`vdQPD!FEki;>VH%9tvs{CV2 ztSIwI`dIfn{j(YB;US17aVjFuac!;ZbQwpRNA^KPMJG|U;(|VcuoV}?++xU)neDiI zv{QH80D-r7P625!Ajk&4lr#Y%QHbpCh(frRcVPYM{ig&j52O@`7pK?>f(WFSjMrj#J~M60yf zL>mAmM4%rhhtcW0`RcO7gN3yoK|>Rn{QIz1#1^d}A&HfDFj9hfpjd1NCFH+15|X`` zsBzW&Gk*Y;_!>?sQk};Ol7ly}&Lx!>=H=UG+$0C|7_`ZB znIa8Ub%^FUtBoi*E(?66b@5AC7N6xgwf>2qD2)O@ce78c;+bFrnzy4%9EGuWC--M zP#G8nx#P|mJlr{bH-)*tUPKgD45fB*(%Dsq!b+rL-v5Pml;JU^aWbExFqKJ5$M(8~ z>aC#Y`7zrdiuFz6v{CZn<}1c2RkZzgcJgVB#MZ1!jmB6EN=%jmr%GZ86?J9?E2<@6 zCh7>_nlLf6ypBeR06_U>9Q_olr%}9!qX|&7d#Tp9-o218O?B9ozVPBo%InDZ-Q>%( zh8%6q6$cn@mxMS|t{Zv~NhAmee1S_syom}n; #7__N5(#+AE9NaXA?BVOc6L6OJ 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 U<5B)S$O=cc+9Ixkw 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 z

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

} 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

?R;@0&rX@IuP9{KA~6W54ewibCq1~T0O}r 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 z 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

Nevmb40GwDP@4#!|U;;&C`AI7n~4igO0p;tev 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 z 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 BdZGXT literal 0 HcmV?d00001