@powersync/web 0.0.0-dev-20260414110516 → 0.0.0-dev-20260503073249
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/2075a31bb151adbb9767.wasm +0 -0
- package/dist/3322bc84de986b63c2cd.wasm +0 -0
- package/dist/8e97452e297be23b5e50.wasm +0 -0
- package/dist/fbc178b70d530e8ce02b.wasm +0 -0
- package/dist/index.umd.js +4323 -156
- package/dist/index.umd.js.map +1 -1
- package/dist/worker/SharedSyncImplementation.umd.js +24 -15
- package/dist/worker/SharedSyncImplementation.umd.js.map +1 -1
- package/dist/worker/WASQLiteDB.umd.js +86 -78
- package/dist/worker/WASQLiteDB.umd.js.map +1 -1
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-9af0a7.umd.js +31 -0
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-9af0a7.umd.js.map +1 -0
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-bbf5a9.umd.js +31 -0
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-bbf5a9.umd.js.map +1 -0
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_dist_wa-sqli-c26e0f.umd.js +31 -0
- package/dist/worker/{node_modules_pnpm_journeyapps_wa-sqlite_1_5_0_node_modules_journeyapps_wa-sqlite_dist_wa-sqli-cc5fcc.umd.js.map → node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_dist_wa-sqli-c26e0f.umd.js.map} +1 -1
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js +31 -0
- package/dist/worker/{node_modules_pnpm_journeyapps_wa-sqlite_1_5_0_node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js.map → node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js.map} +1 -1
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-2fb422.umd.js +3562 -0
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-2fb422.umd.js.map +1 -0
- package/dist/worker/{node_modules_pnpm_journeyapps_wa-sqlite_1_5_0_node_modules_journeyapps_wa-sqlite_src_examples-0df390.umd.js → node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-96fb23.umd.js} +16 -16
- package/dist/worker/{node_modules_pnpm_journeyapps_wa-sqlite_1_5_0_node_modules_journeyapps_wa-sqlite_src_examples-0df390.umd.js.map → node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-96fb23.umd.js.map} +1 -1
- package/dist/worker/{node_modules_pnpm_journeyapps_wa-sqlite_1_5_0_node_modules_journeyapps_wa-sqlite_src_examples-151024.umd.js → node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-c89911.umd.js} +12 -12
- package/dist/worker/{node_modules_pnpm_journeyapps_wa-sqlite_1_5_0_node_modules_journeyapps_wa-sqlite_src_examples-151024.umd.js.map → node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-c89911.umd.js.map} +1 -1
- package/dist/worker/{node_modules_pnpm_journeyapps_wa-sqlite_1_5_0_node_modules_journeyapps_wa-sqlite_src_examples-c01ef0.umd.js → node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-ec4eb1.umd.js} +14 -14
- package/dist/worker/{node_modules_pnpm_journeyapps_wa-sqlite_1_5_0_node_modules_journeyapps_wa-sqlite_src_examples-c01ef0.umd.js.map → node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-ec4eb1.umd.js.map} +1 -1
- package/lib/package.json +3 -3
- package/lib/src/db/PowerSyncDatabase.d.ts +1 -1
- package/lib/src/db/PowerSyncDatabase.js +0 -8
- package/lib/src/db/adapters/AsyncWebAdapter.d.ts +13 -3
- package/lib/src/db/adapters/AsyncWebAdapter.js +115 -21
- package/lib/src/db/adapters/wa-sqlite/DatabaseServer.js +1 -2
- package/lib/src/db/adapters/wa-sqlite/RawSqliteConnection.js +1 -1
- package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.d.ts +16 -2
- package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.js +60 -38
- package/lib/src/db/adapters/wa-sqlite/vfs.d.ts +7 -18
- package/lib/src/db/adapters/wa-sqlite/vfs.js +34 -49
- package/lib/src/db/sync/SSRWebStreamingSyncImplementation.d.ts +4 -0
- package/lib/src/db/sync/SSRWebStreamingSyncImplementation.js +4 -0
- package/lib/src/worker/db/MultiDatabaseServer.js +4 -1
- package/lib/src/worker/db/open-worker-database.js +2 -2
- package/lib/src/worker/sync/SharedSyncImplementation.js +4 -8
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/db/PowerSyncDatabase.ts +1 -9
- package/src/db/adapters/AsyncWebAdapter.ts +138 -22
- package/src/db/adapters/wa-sqlite/DatabaseServer.ts +4 -2
- package/src/db/adapters/wa-sqlite/RawSqliteConnection.ts +4 -1
- package/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.ts +89 -44
- package/src/db/adapters/wa-sqlite/vfs.ts +33 -49
- package/src/db/sync/SSRWebStreamingSyncImplementation.ts +5 -0
- package/src/worker/db/MultiDatabaseServer.ts +4 -1
- package/src/worker/db/open-worker-database.ts +2 -2
- package/src/worker/sync/SharedSyncImplementation.ts +4 -8
- package/dist/26d61ca9f5694d064635.wasm +0 -0
- package/dist/b4c6283dc473b6b3fd24.wasm +0 -0
- package/dist/c78985091a0b22aaef03.wasm +0 -0
- package/dist/ca59e199e1138b553fad.wasm +0 -0
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_5_0_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-b9c070.umd.js +0 -31
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_5_0_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-b9c070.umd.js.map +0 -1
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_5_0_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-c99c07.umd.js +0 -31
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_5_0_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-c99c07.umd.js.map +0 -1
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_5_0_node_modules_journeyapps_wa-sqlite_dist_wa-sqli-cc5fcc.umd.js +0 -31
- package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_5_0_node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js +0 -31
|
@@ -0,0 +1,3562 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
(self["webpackChunksdk_web"] = self["webpackChunksdk_web"] || []).push([["node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-2fb422"],{
|
|
3
|
+
|
|
4
|
+
/***/ "../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/FacadeVFS.js"
|
|
5
|
+
/*!******************************************************************************************************************!*\
|
|
6
|
+
!*** ../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/FacadeVFS.js ***!
|
|
7
|
+
\******************************************************************************************************************/
|
|
8
|
+
(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
9
|
+
|
|
10
|
+
__webpack_require__.r(__webpack_exports__);
|
|
11
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
12
|
+
/* harmony export */ FacadeVFS: () => (/* binding */ FacadeVFS)
|
|
13
|
+
/* harmony export */ });
|
|
14
|
+
/* harmony import */ var _VFS_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./VFS.js */ "../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/VFS.js");
|
|
15
|
+
// Copyright 2024 Roy T. Hashimoto. All Rights Reserved.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
|
|
19
|
+
|
|
20
|
+
// Milliseconds since Julian epoch as a BigInt.
|
|
21
|
+
// https://github.com/sqlite/sqlite/blob/e57527c14f7b7cfa6e32eeab5c549d50c4fa3674/src/os_unix.c#L6872-L6882
|
|
22
|
+
const UNIX_EPOCH = 24405875n * 8640000n;
|
|
23
|
+
|
|
24
|
+
// Convenience base class for a JavaScript VFS.
|
|
25
|
+
// The raw xOpen, xRead, etc. function signatures receive only C primitives
|
|
26
|
+
// which aren't easy to work with. This class provides corresponding calls
|
|
27
|
+
// like jOpen, jRead, etc., which receive JavaScript-friendlier arguments
|
|
28
|
+
// such as string, Uint8Array, and DataView.
|
|
29
|
+
class FacadeVFS extends _VFS_js__WEBPACK_IMPORTED_MODULE_0__.Base {
|
|
30
|
+
/**
|
|
31
|
+
* @param {string} name
|
|
32
|
+
* @param {object} module
|
|
33
|
+
*/
|
|
34
|
+
constructor(name, module) {
|
|
35
|
+
super(name, module);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Override to indicate which methods are asynchronous.
|
|
40
|
+
* @param {string} methodName
|
|
41
|
+
* @returns {boolean}
|
|
42
|
+
*/
|
|
43
|
+
hasAsyncMethod(methodName) {
|
|
44
|
+
// The input argument is a string like "xOpen", so convert to "jOpen".
|
|
45
|
+
// Then check if the method exists and is async.
|
|
46
|
+
const jMethodName = `j${methodName.slice(1)}`;
|
|
47
|
+
return this[jMethodName] instanceof AsyncFunction;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Return the filename for a file id for use by mixins.
|
|
52
|
+
* @param {number} pFile
|
|
53
|
+
* @returns {string}
|
|
54
|
+
*/
|
|
55
|
+
getFilename(pFile) {
|
|
56
|
+
throw new Error('unimplemented');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @param {string?} filename
|
|
61
|
+
* @param {number} pFile
|
|
62
|
+
* @param {number} flags
|
|
63
|
+
* @param {DataView} pOutFlags
|
|
64
|
+
* @returns {number|Promise<number>}
|
|
65
|
+
*/
|
|
66
|
+
jOpen(filename, pFile, flags, pOutFlags) {
|
|
67
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CANTOPEN;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @param {string} filename
|
|
72
|
+
* @param {number} syncDir
|
|
73
|
+
* @returns {number|Promise<number>}
|
|
74
|
+
*/
|
|
75
|
+
jDelete(filename, syncDir) {
|
|
76
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @param {string} filename
|
|
81
|
+
* @param {number} flags
|
|
82
|
+
* @param {DataView} pResOut
|
|
83
|
+
* @returns {number|Promise<number>}
|
|
84
|
+
*/
|
|
85
|
+
jAccess(filename, flags, pResOut) {
|
|
86
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @param {string} filename
|
|
91
|
+
* @param {Uint8Array} zOut
|
|
92
|
+
* @returns {number|Promise<number>}
|
|
93
|
+
*/
|
|
94
|
+
jFullPathname(filename, zOut) {
|
|
95
|
+
// Copy the filename to the output buffer.
|
|
96
|
+
const { read, written } = new TextEncoder().encodeInto(filename, zOut);
|
|
97
|
+
if (read < filename.length) return _VFS_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR;
|
|
98
|
+
if (written >= zOut.length) return _VFS_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR;
|
|
99
|
+
zOut[written] = 0;
|
|
100
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* @param {Uint8Array} zBuf
|
|
105
|
+
* @returns {number|Promise<number>}
|
|
106
|
+
*/
|
|
107
|
+
jGetLastError(zBuf) {
|
|
108
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @param {number} pFile
|
|
113
|
+
* @returns {number|Promise<number>}
|
|
114
|
+
*/
|
|
115
|
+
jClose(pFile) {
|
|
116
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* @param {number} pFile
|
|
121
|
+
* @param {Uint8Array} pData
|
|
122
|
+
* @param {number} iOffset
|
|
123
|
+
* @returns {number|Promise<number>}
|
|
124
|
+
*/
|
|
125
|
+
jRead(pFile, pData, iOffset) {
|
|
126
|
+
pData.fill(0);
|
|
127
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_SHORT_READ;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* @param {number} pFile
|
|
132
|
+
* @param {Uint8Array} pData
|
|
133
|
+
* @param {number} iOffset
|
|
134
|
+
* @returns {number|Promise<number>}
|
|
135
|
+
*/
|
|
136
|
+
jWrite(pFile, pData, iOffset) {
|
|
137
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_WRITE;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @param {number} pFile
|
|
142
|
+
* @param {number} size
|
|
143
|
+
* @returns {number|Promise<number>}
|
|
144
|
+
*/
|
|
145
|
+
jTruncate(pFile, size) {
|
|
146
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* @param {number} pFile
|
|
151
|
+
* @param {number} flags
|
|
152
|
+
* @returns {number|Promise<number>}
|
|
153
|
+
*/
|
|
154
|
+
jSync(pFile, flags) {
|
|
155
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* @param {number} pFile
|
|
160
|
+
* @param {DataView} pSize
|
|
161
|
+
* @returns {number|Promise<number>}
|
|
162
|
+
*/
|
|
163
|
+
jFileSize(pFile, pSize) {
|
|
164
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* @param {number} pFile
|
|
169
|
+
* @param {number} lockType
|
|
170
|
+
* @returns {number|Promise<number>}
|
|
171
|
+
*/
|
|
172
|
+
jLock(pFile, lockType) {
|
|
173
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* @param {number} pFile
|
|
178
|
+
* @param {number} lockType
|
|
179
|
+
* @returns {number|Promise<number>}
|
|
180
|
+
*/
|
|
181
|
+
jUnlock(pFile, lockType) {
|
|
182
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* @param {number} pFile
|
|
187
|
+
* @param {DataView} pResOut
|
|
188
|
+
* @returns {number|Promise<number>}
|
|
189
|
+
*/
|
|
190
|
+
jCheckReservedLock(pFile, pResOut) {
|
|
191
|
+
pResOut.setInt32(0, 0, true);
|
|
192
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* @param {number} pFile
|
|
197
|
+
* @param {number} op
|
|
198
|
+
* @param {DataView} pArg
|
|
199
|
+
* @returns {number|Promise<number>}
|
|
200
|
+
*/
|
|
201
|
+
jFileControl(pFile, op, pArg) {
|
|
202
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_NOTFOUND;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* @param {number} pFile
|
|
207
|
+
* @returns {number|Promise<number>}
|
|
208
|
+
*/
|
|
209
|
+
jSectorSize(pFile) {
|
|
210
|
+
return super.xSectorSize(pFile);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* @param {number} pFile
|
|
215
|
+
* @returns {number|Promise<number>}
|
|
216
|
+
*/
|
|
217
|
+
jDeviceCharacteristics(pFile) {
|
|
218
|
+
return 0;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* @param {number} pVfs
|
|
223
|
+
* @param {number} zName
|
|
224
|
+
* @param {number} pFile
|
|
225
|
+
* @param {number} flags
|
|
226
|
+
* @param {number} pOutFlags
|
|
227
|
+
* @returns {number|Promise<number>}
|
|
228
|
+
*/
|
|
229
|
+
xOpen(pVfs, zName, pFile, flags, pOutFlags) {
|
|
230
|
+
const filename = this.#decodeFilename(zName, flags);
|
|
231
|
+
const pOutFlagsView = this.#makeTypedDataView('Int32', pOutFlags);
|
|
232
|
+
this['log']?.('jOpen', filename, pFile, '0x' + flags.toString(16));
|
|
233
|
+
return this.jOpen(filename, pFile, flags, pOutFlagsView);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* @param {number} pVfs
|
|
238
|
+
* @param {number} nByte
|
|
239
|
+
* @param {number} pCharOut
|
|
240
|
+
* @returns {number|Promise<number>}
|
|
241
|
+
*/
|
|
242
|
+
xRandomness(pVfs, nByte, pCharOut) {
|
|
243
|
+
const randomArray = new Uint8Array(nByte);
|
|
244
|
+
crypto.getRandomValues(randomArray);
|
|
245
|
+
// Copy randomArray to the WebAssembly memory
|
|
246
|
+
const buffer = pCharOut; // Pointer to memory in WebAssembly
|
|
247
|
+
this._module.HEAPU8.set(randomArray, buffer); // Copy randomArray into memory starting at buffer
|
|
248
|
+
return nByte;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Gets the current time as milliseconds since Unix epoch
|
|
253
|
+
* @param {number} pVfs pointer to the VFS
|
|
254
|
+
* @param {number} pTime pointer to write the time value
|
|
255
|
+
* @returns {number} SQLite error code
|
|
256
|
+
*/
|
|
257
|
+
xCurrentTimeInt64(pVfs, pTime) {
|
|
258
|
+
// Create a DataView to write the current time
|
|
259
|
+
const timeView = this.#makeTypedDataView('BigInt64', pTime);
|
|
260
|
+
|
|
261
|
+
const currentTime = BigInt(Date.now());
|
|
262
|
+
// Convert the current time to milliseconds since Unix epoch
|
|
263
|
+
const value = UNIX_EPOCH + currentTime;
|
|
264
|
+
|
|
265
|
+
// Write the time value to the pointer location
|
|
266
|
+
timeView.setBigInt64(0, value, true);
|
|
267
|
+
|
|
268
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* @param {number} pVfs
|
|
273
|
+
* @param {number} zName
|
|
274
|
+
* @param {number} syncDir
|
|
275
|
+
* @returns {number|Promise<number>}
|
|
276
|
+
*/
|
|
277
|
+
xDelete(pVfs, zName, syncDir) {
|
|
278
|
+
const filename = this._module.UTF8ToString(zName);
|
|
279
|
+
this['log']?.('jDelete', filename, syncDir);
|
|
280
|
+
return this.jDelete(filename, syncDir);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* @param {number} pVfs
|
|
285
|
+
* @param {number} zName
|
|
286
|
+
* @param {number} flags
|
|
287
|
+
* @param {number} pResOut
|
|
288
|
+
* @returns {number|Promise<number>}
|
|
289
|
+
*/
|
|
290
|
+
xAccess(pVfs, zName, flags, pResOut) {
|
|
291
|
+
const filename = this._module.UTF8ToString(zName);
|
|
292
|
+
const pResOutView = this.#makeTypedDataView('Int32', pResOut);
|
|
293
|
+
this['log']?.('jAccess', filename, flags);
|
|
294
|
+
return this.jAccess(filename, flags, pResOutView);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* @param {number} pVfs
|
|
299
|
+
* @param {number} zName
|
|
300
|
+
* @param {number} nOut
|
|
301
|
+
* @param {number} zOut
|
|
302
|
+
* @returns {number|Promise<number>}
|
|
303
|
+
*/
|
|
304
|
+
xFullPathname(pVfs, zName, nOut, zOut) {
|
|
305
|
+
const filename = this._module.UTF8ToString(zName);
|
|
306
|
+
const zOutArray = this._module.HEAPU8.subarray(zOut, zOut + nOut);
|
|
307
|
+
this['log']?.('jFullPathname', filename, nOut);
|
|
308
|
+
return this.jFullPathname(filename, zOutArray);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* @param {number} pVfs
|
|
313
|
+
* @param {number} nBuf
|
|
314
|
+
* @param {number} zBuf
|
|
315
|
+
* @returns {number|Promise<number>}
|
|
316
|
+
*/
|
|
317
|
+
xGetLastError(pVfs, nBuf, zBuf) {
|
|
318
|
+
const zBufArray = this._module.HEAPU8.subarray(zBuf, zBuf + nBuf);
|
|
319
|
+
this['log']?.('jGetLastError', nBuf);
|
|
320
|
+
return this.jGetLastError(zBufArray);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* @param {number} pFile
|
|
325
|
+
* @returns {number|Promise<number>}
|
|
326
|
+
*/
|
|
327
|
+
xClose(pFile) {
|
|
328
|
+
this['log']?.('jClose', pFile);
|
|
329
|
+
return this.jClose(pFile);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* @param {number} pFile
|
|
334
|
+
* @param {number} pData
|
|
335
|
+
* @param {number} iAmt
|
|
336
|
+
* @param {number} iOffsetLo
|
|
337
|
+
* @param {number} iOffsetHi
|
|
338
|
+
* @returns {number|Promise<number>}
|
|
339
|
+
*/
|
|
340
|
+
xRead(pFile, pData, iAmt, iOffsetLo, iOffsetHi) {
|
|
341
|
+
const pDataArray = this.#makeDataArray(pData, iAmt);
|
|
342
|
+
const iOffset = delegalize(iOffsetLo, iOffsetHi);
|
|
343
|
+
this['log']?.('jRead', pFile, iAmt, iOffset);
|
|
344
|
+
return this.jRead(pFile, pDataArray, iOffset);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* @param {number} pFile
|
|
349
|
+
* @param {number} pData
|
|
350
|
+
* @param {number} iAmt
|
|
351
|
+
* @param {number} iOffsetLo
|
|
352
|
+
* @param {number} iOffsetHi
|
|
353
|
+
* @returns {number|Promise<number>}
|
|
354
|
+
*/
|
|
355
|
+
xWrite(pFile, pData, iAmt, iOffsetLo, iOffsetHi) {
|
|
356
|
+
const pDataArray = this.#makeDataArray(pData, iAmt);
|
|
357
|
+
const iOffset = delegalize(iOffsetLo, iOffsetHi);
|
|
358
|
+
this['log']?.('jWrite', pFile, pDataArray, iOffset);
|
|
359
|
+
return this.jWrite(pFile, pDataArray, iOffset);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* @param {number} pFile
|
|
364
|
+
* @param {number} sizeLo
|
|
365
|
+
* @param {number} sizeHi
|
|
366
|
+
* @returns {number|Promise<number>}
|
|
367
|
+
*/
|
|
368
|
+
xTruncate(pFile, sizeLo, sizeHi) {
|
|
369
|
+
const size = delegalize(sizeLo, sizeHi);
|
|
370
|
+
this['log']?.('jTruncate', pFile, size);
|
|
371
|
+
return this.jTruncate(pFile, size);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* @param {number} pFile
|
|
376
|
+
* @param {number} flags
|
|
377
|
+
* @returns {number|Promise<number>}
|
|
378
|
+
*/
|
|
379
|
+
xSync(pFile, flags) {
|
|
380
|
+
this['log']?.('jSync', pFile, flags);
|
|
381
|
+
return this.jSync(pFile, flags);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
*
|
|
386
|
+
* @param {number} pFile
|
|
387
|
+
* @param {number} pSize
|
|
388
|
+
* @returns {number|Promise<number>}
|
|
389
|
+
*/
|
|
390
|
+
xFileSize(pFile, pSize) {
|
|
391
|
+
const pSizeView = this.#makeTypedDataView('BigInt64', pSize);
|
|
392
|
+
this['log']?.('jFileSize', pFile);
|
|
393
|
+
return this.jFileSize(pFile, pSizeView);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* @param {number} pFile
|
|
398
|
+
* @param {number} lockType
|
|
399
|
+
* @returns {number|Promise<number>}
|
|
400
|
+
*/
|
|
401
|
+
xLock(pFile, lockType) {
|
|
402
|
+
this['log']?.('jLock', pFile, lockType);
|
|
403
|
+
return this.jLock(pFile, lockType);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* @param {number} pFile
|
|
408
|
+
* @param {number} lockType
|
|
409
|
+
* @returns {number|Promise<number>}
|
|
410
|
+
*/
|
|
411
|
+
xUnlock(pFile, lockType) {
|
|
412
|
+
this['log']?.('jUnlock', pFile, lockType);
|
|
413
|
+
return this.jUnlock(pFile, lockType);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* @param {number} pFile
|
|
418
|
+
* @param {number} pResOut
|
|
419
|
+
* @returns {number|Promise<number>}
|
|
420
|
+
*/
|
|
421
|
+
xCheckReservedLock(pFile, pResOut) {
|
|
422
|
+
const pResOutView = this.#makeTypedDataView('Int32', pResOut);
|
|
423
|
+
this['log']?.('jCheckReservedLock', pFile);
|
|
424
|
+
return this.jCheckReservedLock(pFile, pResOutView);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* @param {number} pFile
|
|
429
|
+
* @param {number} op
|
|
430
|
+
* @param {number} pArg
|
|
431
|
+
* @returns {number|Promise<number>}
|
|
432
|
+
*/
|
|
433
|
+
xFileControl(pFile, op, pArg) {
|
|
434
|
+
const pArgView = new DataView(
|
|
435
|
+
this._module.HEAPU8.buffer,
|
|
436
|
+
this._module.HEAPU8.byteOffset + pArg);
|
|
437
|
+
this['log']?.('jFileControl', pFile, op, pArgView);
|
|
438
|
+
return this.jFileControl(pFile, op, pArgView);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* @param {number} pFile
|
|
443
|
+
* @returns {number|Promise<number>}
|
|
444
|
+
*/
|
|
445
|
+
xSectorSize(pFile) {
|
|
446
|
+
this['log']?.('jSectorSize', pFile);
|
|
447
|
+
return this.jSectorSize(pFile);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* @param {number} pFile
|
|
452
|
+
* @returns {number|Promise<number>}
|
|
453
|
+
*/
|
|
454
|
+
xDeviceCharacteristics(pFile) {
|
|
455
|
+
this['log']?.('jDeviceCharacteristics', pFile);
|
|
456
|
+
return this.jDeviceCharacteristics(pFile);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Wrapped DataView for pointer arguments.
|
|
461
|
+
* Pointers to a single value are passed using a DataView-like class.
|
|
462
|
+
* This wrapper class prevents use of incorrect type or endianness, and
|
|
463
|
+
* reacquires the underlying buffer when the WebAssembly memory is resized.
|
|
464
|
+
* @param {'Int32'|'BigInt64'} type
|
|
465
|
+
* @param {number} byteOffset
|
|
466
|
+
* @returns {DataView}
|
|
467
|
+
*/
|
|
468
|
+
#makeTypedDataView(type, byteOffset) {
|
|
469
|
+
// @ts-ignore
|
|
470
|
+
return new DataViewProxy(this._module, byteOffset, type);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Wrapped Uint8Array for buffer arguments.
|
|
475
|
+
* Memory blocks are passed as a Uint8Array-like class. This wrapper
|
|
476
|
+
* class reacquires the underlying buffer when the WebAssembly memory
|
|
477
|
+
* is resized.
|
|
478
|
+
* @param {number} byteOffset
|
|
479
|
+
* @param {number} byteLength
|
|
480
|
+
* @returns {Uint8Array}
|
|
481
|
+
*/
|
|
482
|
+
#makeDataArray(byteOffset, byteLength) {
|
|
483
|
+
// @ts-ignore
|
|
484
|
+
return new Uint8ArrayProxy(this._module, byteOffset, byteLength);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
#decodeFilename(zName, flags) {
|
|
488
|
+
if (flags & _VFS_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_URI) {
|
|
489
|
+
// The first null-terminated string is the URI path. Subsequent
|
|
490
|
+
// strings are query parameter keys and values.
|
|
491
|
+
// https://www.sqlite.org/c3ref/open.html#urifilenamesinsqlite3open
|
|
492
|
+
let pName = zName;
|
|
493
|
+
let state = 1;
|
|
494
|
+
const charCodes = [];
|
|
495
|
+
while (state) {
|
|
496
|
+
const charCode = this._module.HEAPU8[pName++];
|
|
497
|
+
if (charCode) {
|
|
498
|
+
charCodes.push(charCode);
|
|
499
|
+
} else {
|
|
500
|
+
if (!this._module.HEAPU8[pName]) state = null;
|
|
501
|
+
switch (state) {
|
|
502
|
+
case 1: // path
|
|
503
|
+
charCodes.push('?'.charCodeAt(0));
|
|
504
|
+
state = 2;
|
|
505
|
+
break;
|
|
506
|
+
case 2: // key
|
|
507
|
+
charCodes.push('='.charCodeAt(0));
|
|
508
|
+
state = 3;
|
|
509
|
+
break;
|
|
510
|
+
case 3: // value
|
|
511
|
+
charCodes.push('&'.charCodeAt(0));
|
|
512
|
+
state = 2;
|
|
513
|
+
break;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
return new TextDecoder().decode(new Uint8Array(charCodes));
|
|
518
|
+
}
|
|
519
|
+
return zName ? this._module.UTF8ToString(zName) : null;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// Emscripten "legalizes" 64-bit integer arguments by passing them as
|
|
524
|
+
// two 32-bit signed integers.
|
|
525
|
+
function delegalize(lo32, hi32) {
|
|
526
|
+
return (hi32 * 0x100000000) + lo32 + (lo32 < 0 ? 2**32 : 0);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// This class provides a Uint8Array-like interface for a WebAssembly memory
|
|
530
|
+
// buffer. It is used to access memory blocks passed as arguments to
|
|
531
|
+
// xRead, xWrite, etc. The class reacquires the underlying buffer when the
|
|
532
|
+
// WebAssembly memory is resized, which can happen when the memory is
|
|
533
|
+
// detached and resized by the WebAssembly module.
|
|
534
|
+
//
|
|
535
|
+
// Note that although this class implements the same methods as Uint8Array,
|
|
536
|
+
// it is not a real Uint8Array and passing it to functions that expect
|
|
537
|
+
// a Uint8Array may not work. Use subarray() to get a real Uint8Array
|
|
538
|
+
// if needed.
|
|
539
|
+
class Uint8ArrayProxy {
|
|
540
|
+
#module;
|
|
541
|
+
|
|
542
|
+
#_array = new Uint8Array()
|
|
543
|
+
get #array() {
|
|
544
|
+
if (this.#_array.buffer.byteLength === 0) {
|
|
545
|
+
// WebAssembly memory resize detached the buffer so re-create the
|
|
546
|
+
// array with the new buffer.
|
|
547
|
+
this.#_array = this.#module.HEAPU8.subarray(
|
|
548
|
+
this.byteOffset,
|
|
549
|
+
this.byteOffset + this.byteLength);
|
|
550
|
+
}
|
|
551
|
+
return this.#_array;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* @param {*} module
|
|
556
|
+
* @param {number} byteOffset
|
|
557
|
+
* @param {number} byteLength
|
|
558
|
+
*/
|
|
559
|
+
constructor(module, byteOffset, byteLength) {
|
|
560
|
+
this.#module = module;
|
|
561
|
+
this.byteOffset = byteOffset;
|
|
562
|
+
this.length = this.byteLength = byteLength;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
get buffer() {
|
|
566
|
+
return this.#array.buffer;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
at(index) {
|
|
570
|
+
return this.#array.at(index);
|
|
571
|
+
}
|
|
572
|
+
copyWithin(target, start, end) {
|
|
573
|
+
this.#array.copyWithin(target, start, end);
|
|
574
|
+
}
|
|
575
|
+
entries() {
|
|
576
|
+
return this.#array.entries();
|
|
577
|
+
}
|
|
578
|
+
every(predicate) {
|
|
579
|
+
return this.#array.every(predicate);
|
|
580
|
+
}
|
|
581
|
+
fill(value, start, end) {
|
|
582
|
+
this.#array.fill(value, start, end);
|
|
583
|
+
}
|
|
584
|
+
filter(predicate) {
|
|
585
|
+
return this.#array.filter(predicate);
|
|
586
|
+
}
|
|
587
|
+
find(predicate) {
|
|
588
|
+
return this.#array.find(predicate);
|
|
589
|
+
}
|
|
590
|
+
findIndex(predicate) {
|
|
591
|
+
return this.#array.findIndex(predicate);
|
|
592
|
+
}
|
|
593
|
+
findLast(predicate) {
|
|
594
|
+
return this.#array.findLast(predicate);
|
|
595
|
+
}
|
|
596
|
+
findLastIndex(predicate) {
|
|
597
|
+
return this.#array.findLastIndex(predicate);
|
|
598
|
+
}
|
|
599
|
+
forEach(callback) {
|
|
600
|
+
this.#array.forEach(callback);
|
|
601
|
+
}
|
|
602
|
+
includes(value, start) {
|
|
603
|
+
return this.#array.includes(value, start);
|
|
604
|
+
}
|
|
605
|
+
indexOf(value, start) {
|
|
606
|
+
return this.#array.indexOf(value, start);
|
|
607
|
+
}
|
|
608
|
+
join(separator) {
|
|
609
|
+
return this.#array.join(separator);
|
|
610
|
+
}
|
|
611
|
+
keys() {
|
|
612
|
+
return this.#array.keys();
|
|
613
|
+
}
|
|
614
|
+
lastIndexOf(value, start) {
|
|
615
|
+
return this.#array.lastIndexOf(value, start);
|
|
616
|
+
}
|
|
617
|
+
map(callback) {
|
|
618
|
+
return this.#array.map(callback);
|
|
619
|
+
}
|
|
620
|
+
reduce(callback, initialValue) {
|
|
621
|
+
return this.#array.reduce(callback, initialValue);
|
|
622
|
+
}
|
|
623
|
+
reduceRight(callback, initialValue) {
|
|
624
|
+
return this.#array.reduceRight(callback, initialValue);
|
|
625
|
+
}
|
|
626
|
+
reverse() {
|
|
627
|
+
this.#array.reverse();
|
|
628
|
+
}
|
|
629
|
+
set(array, offset) {
|
|
630
|
+
this.#array.set(array, offset);
|
|
631
|
+
}
|
|
632
|
+
slice(start, end) {
|
|
633
|
+
return this.#array.slice(start, end);
|
|
634
|
+
}
|
|
635
|
+
some(predicate) {
|
|
636
|
+
return this.#array.some(predicate);
|
|
637
|
+
}
|
|
638
|
+
sort(compareFn) {
|
|
639
|
+
this.#array.sort(compareFn);
|
|
640
|
+
}
|
|
641
|
+
subarray(begin, end) {
|
|
642
|
+
return this.#array.subarray(begin, end);
|
|
643
|
+
}
|
|
644
|
+
toLocaleString(locales, options) {
|
|
645
|
+
// @ts-ignore
|
|
646
|
+
return this.#array.toLocaleString(locales, options);
|
|
647
|
+
}
|
|
648
|
+
toReversed() {
|
|
649
|
+
return this.#array.toReversed();
|
|
650
|
+
}
|
|
651
|
+
toSorted(compareFn) {
|
|
652
|
+
return this.#array.toSorted(compareFn);
|
|
653
|
+
}
|
|
654
|
+
toString() {
|
|
655
|
+
return this.#array.toString();
|
|
656
|
+
}
|
|
657
|
+
values() {
|
|
658
|
+
return this.#array.values();
|
|
659
|
+
}
|
|
660
|
+
with(index, value) {
|
|
661
|
+
return this.#array.with(index, value);
|
|
662
|
+
}
|
|
663
|
+
[Symbol.iterator]() {
|
|
664
|
+
return this.#array[Symbol.iterator]();
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// This class provides a DataView-like interface for a WebAssembly memory
|
|
669
|
+
// buffer, restricted to either Int32 or BigInt64 types. It also reacquires
|
|
670
|
+
// the underlying buffer when the WebAssembly memory is resized, which can
|
|
671
|
+
// happen when the memory is detached and resized by the WebAssembly module.
|
|
672
|
+
class DataViewProxy {
|
|
673
|
+
#module;
|
|
674
|
+
#type;
|
|
675
|
+
|
|
676
|
+
#_view = new DataView(new ArrayBuffer(0));
|
|
677
|
+
get #view() {
|
|
678
|
+
if (this.#_view.buffer.byteLength === 0) {
|
|
679
|
+
// WebAssembly memory resize detached the buffer so re-create the
|
|
680
|
+
// view with the new buffer.
|
|
681
|
+
this.#_view = new DataView(
|
|
682
|
+
this.#module.HEAPU8.buffer,
|
|
683
|
+
this.#module.HEAPU8.byteOffset + this.byteOffset);
|
|
684
|
+
}
|
|
685
|
+
return this.#_view;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* @param {*} module
|
|
690
|
+
* @param {number} byteOffset
|
|
691
|
+
* @param {'Int32'|'BigInt64'} type
|
|
692
|
+
*/
|
|
693
|
+
constructor(module, byteOffset, type) {
|
|
694
|
+
this.#module = module;
|
|
695
|
+
this.byteOffset = byteOffset;
|
|
696
|
+
this.#type = type;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
get buffer() {
|
|
700
|
+
return this.#view.buffer;
|
|
701
|
+
}
|
|
702
|
+
get byteLength() {
|
|
703
|
+
return this.#type === 'Int32' ? 4 : 8;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
getInt32(byteOffset, littleEndian) {
|
|
707
|
+
if (this.#type !== 'Int32') {
|
|
708
|
+
throw new Error('invalid type');
|
|
709
|
+
}
|
|
710
|
+
if (!littleEndian) throw new Error('must be little endian');
|
|
711
|
+
return this.#view.getInt32(byteOffset, littleEndian);
|
|
712
|
+
}
|
|
713
|
+
setInt32(byteOffset, value, littleEndian) {
|
|
714
|
+
if (this.#type !== 'Int32') {
|
|
715
|
+
throw new Error('invalid type');
|
|
716
|
+
}
|
|
717
|
+
if (!littleEndian) throw new Error('must be little endian');
|
|
718
|
+
this.#view.setInt32(byteOffset, value, littleEndian);
|
|
719
|
+
}
|
|
720
|
+
getBigInt64(byteOffset, littleEndian) {
|
|
721
|
+
if (this.#type !== 'BigInt64') {
|
|
722
|
+
throw new Error('invalid type');
|
|
723
|
+
}
|
|
724
|
+
if (!littleEndian) throw new Error('must be little endian');
|
|
725
|
+
return this.#view.getBigInt64(byteOffset, littleEndian);
|
|
726
|
+
}
|
|
727
|
+
setBigInt64(byteOffset, value, littleEndian) {
|
|
728
|
+
if (this.#type !== 'BigInt64') {
|
|
729
|
+
throw new Error('invalid type');
|
|
730
|
+
}
|
|
731
|
+
if (!littleEndian) throw new Error('must be little endian');
|
|
732
|
+
this.#view.setBigInt64(byteOffset, value, littleEndian);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/***/ },
|
|
737
|
+
|
|
738
|
+
/***/ "../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/VFS.js"
|
|
739
|
+
/*!************************************************************************************************************!*\
|
|
740
|
+
!*** ../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/VFS.js ***!
|
|
741
|
+
\************************************************************************************************************/
|
|
742
|
+
(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
743
|
+
|
|
744
|
+
__webpack_require__.r(__webpack_exports__);
|
|
745
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
746
|
+
/* harmony export */ Base: () => (/* binding */ Base),
|
|
747
|
+
/* harmony export */ FILE_TYPE_MASK: () => (/* binding */ FILE_TYPE_MASK),
|
|
748
|
+
/* harmony export */ SQLITE_ABORT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_ABORT),
|
|
749
|
+
/* harmony export */ SQLITE_ACCESS_EXISTS: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_ACCESS_EXISTS),
|
|
750
|
+
/* harmony export */ SQLITE_ACCESS_READ: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_ACCESS_READ),
|
|
751
|
+
/* harmony export */ SQLITE_ACCESS_READWRITE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_ACCESS_READWRITE),
|
|
752
|
+
/* harmony export */ SQLITE_ALTER_TABLE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_ALTER_TABLE),
|
|
753
|
+
/* harmony export */ SQLITE_ANALYZE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_ANALYZE),
|
|
754
|
+
/* harmony export */ SQLITE_ATTACH: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_ATTACH),
|
|
755
|
+
/* harmony export */ SQLITE_AUTH: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_AUTH),
|
|
756
|
+
/* harmony export */ SQLITE_BLOB: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_BLOB),
|
|
757
|
+
/* harmony export */ SQLITE_BUSY: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_BUSY),
|
|
758
|
+
/* harmony export */ SQLITE_CANTOPEN: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CANTOPEN),
|
|
759
|
+
/* harmony export */ SQLITE_CONSTRAINT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CONSTRAINT),
|
|
760
|
+
/* harmony export */ SQLITE_CONSTRAINT_CHECK: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CONSTRAINT_CHECK),
|
|
761
|
+
/* harmony export */ SQLITE_CONSTRAINT_COMMITHOOK: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CONSTRAINT_COMMITHOOK),
|
|
762
|
+
/* harmony export */ SQLITE_CONSTRAINT_FOREIGNKEY: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CONSTRAINT_FOREIGNKEY),
|
|
763
|
+
/* harmony export */ SQLITE_CONSTRAINT_FUNCTION: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CONSTRAINT_FUNCTION),
|
|
764
|
+
/* harmony export */ SQLITE_CONSTRAINT_NOTNULL: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CONSTRAINT_NOTNULL),
|
|
765
|
+
/* harmony export */ SQLITE_CONSTRAINT_PINNED: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CONSTRAINT_PINNED),
|
|
766
|
+
/* harmony export */ SQLITE_CONSTRAINT_PRIMARYKEY: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CONSTRAINT_PRIMARYKEY),
|
|
767
|
+
/* harmony export */ SQLITE_CONSTRAINT_ROWID: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CONSTRAINT_ROWID),
|
|
768
|
+
/* harmony export */ SQLITE_CONSTRAINT_TRIGGER: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CONSTRAINT_TRIGGER),
|
|
769
|
+
/* harmony export */ SQLITE_CONSTRAINT_UNIQUE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CONSTRAINT_UNIQUE),
|
|
770
|
+
/* harmony export */ SQLITE_CONSTRAINT_VTAB: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CONSTRAINT_VTAB),
|
|
771
|
+
/* harmony export */ SQLITE_COPY: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_COPY),
|
|
772
|
+
/* harmony export */ SQLITE_CORRUPT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CORRUPT),
|
|
773
|
+
/* harmony export */ SQLITE_CREATE_INDEX: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CREATE_INDEX),
|
|
774
|
+
/* harmony export */ SQLITE_CREATE_TABLE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CREATE_TABLE),
|
|
775
|
+
/* harmony export */ SQLITE_CREATE_TEMP_INDEX: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CREATE_TEMP_INDEX),
|
|
776
|
+
/* harmony export */ SQLITE_CREATE_TEMP_TABLE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CREATE_TEMP_TABLE),
|
|
777
|
+
/* harmony export */ SQLITE_CREATE_TEMP_TRIGGER: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CREATE_TEMP_TRIGGER),
|
|
778
|
+
/* harmony export */ SQLITE_CREATE_TEMP_VIEW: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CREATE_TEMP_VIEW),
|
|
779
|
+
/* harmony export */ SQLITE_CREATE_TRIGGER: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CREATE_TRIGGER),
|
|
780
|
+
/* harmony export */ SQLITE_CREATE_VIEW: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CREATE_VIEW),
|
|
781
|
+
/* harmony export */ SQLITE_CREATE_VTABLE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CREATE_VTABLE),
|
|
782
|
+
/* harmony export */ SQLITE_DELETE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_DELETE),
|
|
783
|
+
/* harmony export */ SQLITE_DENY: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_DENY),
|
|
784
|
+
/* harmony export */ SQLITE_DETACH: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_DETACH),
|
|
785
|
+
/* harmony export */ SQLITE_DETERMINISTIC: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_DETERMINISTIC),
|
|
786
|
+
/* harmony export */ SQLITE_DIRECTONLY: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_DIRECTONLY),
|
|
787
|
+
/* harmony export */ SQLITE_DONE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_DONE),
|
|
788
|
+
/* harmony export */ SQLITE_DROP_INDEX: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_DROP_INDEX),
|
|
789
|
+
/* harmony export */ SQLITE_DROP_TABLE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_DROP_TABLE),
|
|
790
|
+
/* harmony export */ SQLITE_DROP_TEMP_INDEX: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_DROP_TEMP_INDEX),
|
|
791
|
+
/* harmony export */ SQLITE_DROP_TEMP_TABLE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_DROP_TEMP_TABLE),
|
|
792
|
+
/* harmony export */ SQLITE_DROP_TEMP_TRIGGER: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_DROP_TEMP_TRIGGER),
|
|
793
|
+
/* harmony export */ SQLITE_DROP_TEMP_VIEW: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_DROP_TEMP_VIEW),
|
|
794
|
+
/* harmony export */ SQLITE_DROP_TRIGGER: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_DROP_TRIGGER),
|
|
795
|
+
/* harmony export */ SQLITE_DROP_VIEW: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_DROP_VIEW),
|
|
796
|
+
/* harmony export */ SQLITE_DROP_VTABLE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_DROP_VTABLE),
|
|
797
|
+
/* harmony export */ SQLITE_EMPTY: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_EMPTY),
|
|
798
|
+
/* harmony export */ SQLITE_ERROR: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_ERROR),
|
|
799
|
+
/* harmony export */ SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_BEGIN_ATOMIC_WRITE),
|
|
800
|
+
/* harmony export */ SQLITE_FCNTL_BUSYHANDLER: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_BUSYHANDLER),
|
|
801
|
+
/* harmony export */ SQLITE_FCNTL_CHUNK_SIZE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_CHUNK_SIZE),
|
|
802
|
+
/* harmony export */ SQLITE_FCNTL_CKPT_DONE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_CKPT_DONE),
|
|
803
|
+
/* harmony export */ SQLITE_FCNTL_CKPT_START: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_CKPT_START),
|
|
804
|
+
/* harmony export */ SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_COMMIT_ATOMIC_WRITE),
|
|
805
|
+
/* harmony export */ SQLITE_FCNTL_COMMIT_PHASETWO: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_COMMIT_PHASETWO),
|
|
806
|
+
/* harmony export */ SQLITE_FCNTL_DATA_VERSION: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_DATA_VERSION),
|
|
807
|
+
/* harmony export */ SQLITE_FCNTL_FILE_POINTER: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_FILE_POINTER),
|
|
808
|
+
/* harmony export */ SQLITE_FCNTL_GET_LOCKPROXYFILE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_GET_LOCKPROXYFILE),
|
|
809
|
+
/* harmony export */ SQLITE_FCNTL_HAS_MOVED: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_HAS_MOVED),
|
|
810
|
+
/* harmony export */ SQLITE_FCNTL_JOURNAL_POINTER: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_JOURNAL_POINTER),
|
|
811
|
+
/* harmony export */ SQLITE_FCNTL_LAST_ERRNO: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_LAST_ERRNO),
|
|
812
|
+
/* harmony export */ SQLITE_FCNTL_LOCKSTATE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_LOCKSTATE),
|
|
813
|
+
/* harmony export */ SQLITE_FCNTL_LOCK_TIMEOUT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_LOCK_TIMEOUT),
|
|
814
|
+
/* harmony export */ SQLITE_FCNTL_MMAP_SIZE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_MMAP_SIZE),
|
|
815
|
+
/* harmony export */ SQLITE_FCNTL_OVERWRITE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_OVERWRITE),
|
|
816
|
+
/* harmony export */ SQLITE_FCNTL_PDB: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_PDB),
|
|
817
|
+
/* harmony export */ SQLITE_FCNTL_PERSIST_WAL: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_PERSIST_WAL),
|
|
818
|
+
/* harmony export */ SQLITE_FCNTL_POWERSAFE_OVERWRITE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_POWERSAFE_OVERWRITE),
|
|
819
|
+
/* harmony export */ SQLITE_FCNTL_PRAGMA: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_PRAGMA),
|
|
820
|
+
/* harmony export */ SQLITE_FCNTL_RBU: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_RBU),
|
|
821
|
+
/* harmony export */ SQLITE_FCNTL_RESERVE_BYTES: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_RESERVE_BYTES),
|
|
822
|
+
/* harmony export */ SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE),
|
|
823
|
+
/* harmony export */ SQLITE_FCNTL_SET_LOCKPROXYFILE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_SET_LOCKPROXYFILE),
|
|
824
|
+
/* harmony export */ SQLITE_FCNTL_SIZE_HINT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_SIZE_HINT),
|
|
825
|
+
/* harmony export */ SQLITE_FCNTL_SIZE_LIMIT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_SIZE_LIMIT),
|
|
826
|
+
/* harmony export */ SQLITE_FCNTL_SYNC: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_SYNC),
|
|
827
|
+
/* harmony export */ SQLITE_FCNTL_SYNC_OMITTED: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_SYNC_OMITTED),
|
|
828
|
+
/* harmony export */ SQLITE_FCNTL_TEMPFILENAME: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_TEMPFILENAME),
|
|
829
|
+
/* harmony export */ SQLITE_FCNTL_TRACE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_TRACE),
|
|
830
|
+
/* harmony export */ SQLITE_FCNTL_VFSNAME: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_VFSNAME),
|
|
831
|
+
/* harmony export */ SQLITE_FCNTL_VFS_POINTER: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_VFS_POINTER),
|
|
832
|
+
/* harmony export */ SQLITE_FCNTL_WAL_BLOCK: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_WAL_BLOCK),
|
|
833
|
+
/* harmony export */ SQLITE_FCNTL_WIN32_AV_RETRY: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_WIN32_AV_RETRY),
|
|
834
|
+
/* harmony export */ SQLITE_FCNTL_WIN32_GET_HANDLE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_WIN32_GET_HANDLE),
|
|
835
|
+
/* harmony export */ SQLITE_FCNTL_WIN32_SET_HANDLE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_WIN32_SET_HANDLE),
|
|
836
|
+
/* harmony export */ SQLITE_FCNTL_ZIPVFS: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FCNTL_ZIPVFS),
|
|
837
|
+
/* harmony export */ SQLITE_FLOAT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FLOAT),
|
|
838
|
+
/* harmony export */ SQLITE_FORMAT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FORMAT),
|
|
839
|
+
/* harmony export */ SQLITE_FULL: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FULL),
|
|
840
|
+
/* harmony export */ SQLITE_FUNCTION: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_FUNCTION),
|
|
841
|
+
/* harmony export */ SQLITE_IGNORE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IGNORE),
|
|
842
|
+
/* harmony export */ SQLITE_INDEX_CONSTRAINT_EQ: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_INDEX_CONSTRAINT_EQ),
|
|
843
|
+
/* harmony export */ SQLITE_INDEX_CONSTRAINT_FUNCTION: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_INDEX_CONSTRAINT_FUNCTION),
|
|
844
|
+
/* harmony export */ SQLITE_INDEX_CONSTRAINT_GE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_INDEX_CONSTRAINT_GE),
|
|
845
|
+
/* harmony export */ SQLITE_INDEX_CONSTRAINT_GLOB: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_INDEX_CONSTRAINT_GLOB),
|
|
846
|
+
/* harmony export */ SQLITE_INDEX_CONSTRAINT_GT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_INDEX_CONSTRAINT_GT),
|
|
847
|
+
/* harmony export */ SQLITE_INDEX_CONSTRAINT_IS: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_INDEX_CONSTRAINT_IS),
|
|
848
|
+
/* harmony export */ SQLITE_INDEX_CONSTRAINT_ISNOT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_INDEX_CONSTRAINT_ISNOT),
|
|
849
|
+
/* harmony export */ SQLITE_INDEX_CONSTRAINT_ISNOTNULL: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_INDEX_CONSTRAINT_ISNOTNULL),
|
|
850
|
+
/* harmony export */ SQLITE_INDEX_CONSTRAINT_ISNULL: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_INDEX_CONSTRAINT_ISNULL),
|
|
851
|
+
/* harmony export */ SQLITE_INDEX_CONSTRAINT_LE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_INDEX_CONSTRAINT_LE),
|
|
852
|
+
/* harmony export */ SQLITE_INDEX_CONSTRAINT_LIKE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_INDEX_CONSTRAINT_LIKE),
|
|
853
|
+
/* harmony export */ SQLITE_INDEX_CONSTRAINT_LT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_INDEX_CONSTRAINT_LT),
|
|
854
|
+
/* harmony export */ SQLITE_INDEX_CONSTRAINT_MATCH: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_INDEX_CONSTRAINT_MATCH),
|
|
855
|
+
/* harmony export */ SQLITE_INDEX_CONSTRAINT_NE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_INDEX_CONSTRAINT_NE),
|
|
856
|
+
/* harmony export */ SQLITE_INDEX_CONSTRAINT_REGEXP: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_INDEX_CONSTRAINT_REGEXP),
|
|
857
|
+
/* harmony export */ SQLITE_INDEX_SCAN_UNIQUE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_INDEX_SCAN_UNIQUE),
|
|
858
|
+
/* harmony export */ SQLITE_INNOCUOUS: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_INNOCUOUS),
|
|
859
|
+
/* harmony export */ SQLITE_INSERT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_INSERT),
|
|
860
|
+
/* harmony export */ SQLITE_INTEGER: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_INTEGER),
|
|
861
|
+
/* harmony export */ SQLITE_INTERNAL: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_INTERNAL),
|
|
862
|
+
/* harmony export */ SQLITE_INTERRUPT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_INTERRUPT),
|
|
863
|
+
/* harmony export */ SQLITE_IOCAP_ATOMIC: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOCAP_ATOMIC),
|
|
864
|
+
/* harmony export */ SQLITE_IOCAP_ATOMIC16K: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOCAP_ATOMIC16K),
|
|
865
|
+
/* harmony export */ SQLITE_IOCAP_ATOMIC1K: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOCAP_ATOMIC1K),
|
|
866
|
+
/* harmony export */ SQLITE_IOCAP_ATOMIC2K: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOCAP_ATOMIC2K),
|
|
867
|
+
/* harmony export */ SQLITE_IOCAP_ATOMIC32K: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOCAP_ATOMIC32K),
|
|
868
|
+
/* harmony export */ SQLITE_IOCAP_ATOMIC4K: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOCAP_ATOMIC4K),
|
|
869
|
+
/* harmony export */ SQLITE_IOCAP_ATOMIC512: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOCAP_ATOMIC512),
|
|
870
|
+
/* harmony export */ SQLITE_IOCAP_ATOMIC64K: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOCAP_ATOMIC64K),
|
|
871
|
+
/* harmony export */ SQLITE_IOCAP_ATOMIC8K: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOCAP_ATOMIC8K),
|
|
872
|
+
/* harmony export */ SQLITE_IOCAP_BATCH_ATOMIC: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOCAP_BATCH_ATOMIC),
|
|
873
|
+
/* harmony export */ SQLITE_IOCAP_IMMUTABLE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOCAP_IMMUTABLE),
|
|
874
|
+
/* harmony export */ SQLITE_IOCAP_POWERSAFE_OVERWRITE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOCAP_POWERSAFE_OVERWRITE),
|
|
875
|
+
/* harmony export */ SQLITE_IOCAP_SAFE_APPEND: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOCAP_SAFE_APPEND),
|
|
876
|
+
/* harmony export */ SQLITE_IOCAP_SEQUENTIAL: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOCAP_SEQUENTIAL),
|
|
877
|
+
/* harmony export */ SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN),
|
|
878
|
+
/* harmony export */ SQLITE_IOERR: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR),
|
|
879
|
+
/* harmony export */ SQLITE_IOERR_ACCESS: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_ACCESS),
|
|
880
|
+
/* harmony export */ SQLITE_IOERR_BEGIN_ATOMIC: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_BEGIN_ATOMIC),
|
|
881
|
+
/* harmony export */ SQLITE_IOERR_CHECKRESERVEDLOCK: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_CHECKRESERVEDLOCK),
|
|
882
|
+
/* harmony export */ SQLITE_IOERR_CLOSE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_CLOSE),
|
|
883
|
+
/* harmony export */ SQLITE_IOERR_COMMIT_ATOMIC: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_COMMIT_ATOMIC),
|
|
884
|
+
/* harmony export */ SQLITE_IOERR_DATA: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_DATA),
|
|
885
|
+
/* harmony export */ SQLITE_IOERR_DELETE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_DELETE),
|
|
886
|
+
/* harmony export */ SQLITE_IOERR_DELETE_NOENT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_DELETE_NOENT),
|
|
887
|
+
/* harmony export */ SQLITE_IOERR_DIR_FSYNC: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_DIR_FSYNC),
|
|
888
|
+
/* harmony export */ SQLITE_IOERR_FSTAT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_FSTAT),
|
|
889
|
+
/* harmony export */ SQLITE_IOERR_FSYNC: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_FSYNC),
|
|
890
|
+
/* harmony export */ SQLITE_IOERR_GETTEMPPATH: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_GETTEMPPATH),
|
|
891
|
+
/* harmony export */ SQLITE_IOERR_LOCK: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_LOCK),
|
|
892
|
+
/* harmony export */ SQLITE_IOERR_NOMEM: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_NOMEM),
|
|
893
|
+
/* harmony export */ SQLITE_IOERR_RDLOCK: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_RDLOCK),
|
|
894
|
+
/* harmony export */ SQLITE_IOERR_READ: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_READ),
|
|
895
|
+
/* harmony export */ SQLITE_IOERR_ROLLBACK_ATOMIC: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_ROLLBACK_ATOMIC),
|
|
896
|
+
/* harmony export */ SQLITE_IOERR_SEEK: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_SEEK),
|
|
897
|
+
/* harmony export */ SQLITE_IOERR_SHORT_READ: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_SHORT_READ),
|
|
898
|
+
/* harmony export */ SQLITE_IOERR_TRUNCATE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_TRUNCATE),
|
|
899
|
+
/* harmony export */ SQLITE_IOERR_UNLOCK: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_UNLOCK),
|
|
900
|
+
/* harmony export */ SQLITE_IOERR_VNODE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_VNODE),
|
|
901
|
+
/* harmony export */ SQLITE_IOERR_WRITE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_IOERR_WRITE),
|
|
902
|
+
/* harmony export */ SQLITE_LIMIT_ATTACHED: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_LIMIT_ATTACHED),
|
|
903
|
+
/* harmony export */ SQLITE_LIMIT_COLUMN: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_LIMIT_COLUMN),
|
|
904
|
+
/* harmony export */ SQLITE_LIMIT_COMPOUND_SELECT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_LIMIT_COMPOUND_SELECT),
|
|
905
|
+
/* harmony export */ SQLITE_LIMIT_EXPR_DEPTH: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_LIMIT_EXPR_DEPTH),
|
|
906
|
+
/* harmony export */ SQLITE_LIMIT_FUNCTION_ARG: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_LIMIT_FUNCTION_ARG),
|
|
907
|
+
/* harmony export */ SQLITE_LIMIT_LENGTH: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_LIMIT_LENGTH),
|
|
908
|
+
/* harmony export */ SQLITE_LIMIT_LIKE_PATTERN_LENGTH: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_LIMIT_LIKE_PATTERN_LENGTH),
|
|
909
|
+
/* harmony export */ SQLITE_LIMIT_SQL_LENGTH: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_LIMIT_SQL_LENGTH),
|
|
910
|
+
/* harmony export */ SQLITE_LIMIT_TRIGGER_DEPTH: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_LIMIT_TRIGGER_DEPTH),
|
|
911
|
+
/* harmony export */ SQLITE_LIMIT_VARIABLE_NUMBER: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_LIMIT_VARIABLE_NUMBER),
|
|
912
|
+
/* harmony export */ SQLITE_LIMIT_VDBE_OP: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_LIMIT_VDBE_OP),
|
|
913
|
+
/* harmony export */ SQLITE_LIMIT_WORKER_THREADS: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_LIMIT_WORKER_THREADS),
|
|
914
|
+
/* harmony export */ SQLITE_LOCKED: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_LOCKED),
|
|
915
|
+
/* harmony export */ SQLITE_LOCK_EXCLUSIVE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_LOCK_EXCLUSIVE),
|
|
916
|
+
/* harmony export */ SQLITE_LOCK_NONE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_LOCK_NONE),
|
|
917
|
+
/* harmony export */ SQLITE_LOCK_PENDING: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_LOCK_PENDING),
|
|
918
|
+
/* harmony export */ SQLITE_LOCK_RESERVED: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_LOCK_RESERVED),
|
|
919
|
+
/* harmony export */ SQLITE_LOCK_SHARED: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_LOCK_SHARED),
|
|
920
|
+
/* harmony export */ SQLITE_MISMATCH: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_MISMATCH),
|
|
921
|
+
/* harmony export */ SQLITE_MISUSE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_MISUSE),
|
|
922
|
+
/* harmony export */ SQLITE_NOLFS: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_NOLFS),
|
|
923
|
+
/* harmony export */ SQLITE_NOMEM: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_NOMEM),
|
|
924
|
+
/* harmony export */ SQLITE_NOTADB: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_NOTADB),
|
|
925
|
+
/* harmony export */ SQLITE_NOTFOUND: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_NOTFOUND),
|
|
926
|
+
/* harmony export */ SQLITE_NOTICE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_NOTICE),
|
|
927
|
+
/* harmony export */ SQLITE_NULL: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_NULL),
|
|
928
|
+
/* harmony export */ SQLITE_OK: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK),
|
|
929
|
+
/* harmony export */ SQLITE_OPEN_AUTOPROXY: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_AUTOPROXY),
|
|
930
|
+
/* harmony export */ SQLITE_OPEN_CREATE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_CREATE),
|
|
931
|
+
/* harmony export */ SQLITE_OPEN_DELETEONCLOSE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_DELETEONCLOSE),
|
|
932
|
+
/* harmony export */ SQLITE_OPEN_EXCLUSIVE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_EXCLUSIVE),
|
|
933
|
+
/* harmony export */ SQLITE_OPEN_FULLMUTEX: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_FULLMUTEX),
|
|
934
|
+
/* harmony export */ SQLITE_OPEN_MAIN_DB: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_MAIN_DB),
|
|
935
|
+
/* harmony export */ SQLITE_OPEN_MAIN_JOURNAL: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_MAIN_JOURNAL),
|
|
936
|
+
/* harmony export */ SQLITE_OPEN_MEMORY: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_MEMORY),
|
|
937
|
+
/* harmony export */ SQLITE_OPEN_NOFOLLOW: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_NOFOLLOW),
|
|
938
|
+
/* harmony export */ SQLITE_OPEN_NOMUTEX: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_NOMUTEX),
|
|
939
|
+
/* harmony export */ SQLITE_OPEN_PRIVATECACHE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_PRIVATECACHE),
|
|
940
|
+
/* harmony export */ SQLITE_OPEN_READONLY: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_READONLY),
|
|
941
|
+
/* harmony export */ SQLITE_OPEN_READWRITE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_READWRITE),
|
|
942
|
+
/* harmony export */ SQLITE_OPEN_SHAREDCACHE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_SHAREDCACHE),
|
|
943
|
+
/* harmony export */ SQLITE_OPEN_SUBJOURNAL: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_SUBJOURNAL),
|
|
944
|
+
/* harmony export */ SQLITE_OPEN_SUPER_JOURNAL: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_SUPER_JOURNAL),
|
|
945
|
+
/* harmony export */ SQLITE_OPEN_TEMP_DB: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_TEMP_DB),
|
|
946
|
+
/* harmony export */ SQLITE_OPEN_TEMP_JOURNAL: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_TEMP_JOURNAL),
|
|
947
|
+
/* harmony export */ SQLITE_OPEN_TRANSIENT_DB: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_TRANSIENT_DB),
|
|
948
|
+
/* harmony export */ SQLITE_OPEN_URI: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_URI),
|
|
949
|
+
/* harmony export */ SQLITE_OPEN_WAL: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_WAL),
|
|
950
|
+
/* harmony export */ SQLITE_PERM: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_PERM),
|
|
951
|
+
/* harmony export */ SQLITE_PRAGMA: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_PRAGMA),
|
|
952
|
+
/* harmony export */ SQLITE_PREPARE_NORMALIZED: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_PREPARE_NORMALIZED),
|
|
953
|
+
/* harmony export */ SQLITE_PREPARE_NO_VTAB: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_PREPARE_NO_VTAB),
|
|
954
|
+
/* harmony export */ SQLITE_PREPARE_PERSISTENT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_PREPARE_PERSISTENT),
|
|
955
|
+
/* harmony export */ SQLITE_PROTOCOL: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_PROTOCOL),
|
|
956
|
+
/* harmony export */ SQLITE_RANGE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_RANGE),
|
|
957
|
+
/* harmony export */ SQLITE_READ: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_READ),
|
|
958
|
+
/* harmony export */ SQLITE_READONLY: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_READONLY),
|
|
959
|
+
/* harmony export */ SQLITE_RECURSIVE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_RECURSIVE),
|
|
960
|
+
/* harmony export */ SQLITE_REINDEX: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_REINDEX),
|
|
961
|
+
/* harmony export */ SQLITE_ROW: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_ROW),
|
|
962
|
+
/* harmony export */ SQLITE_SAVEPOINT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_SAVEPOINT),
|
|
963
|
+
/* harmony export */ SQLITE_SCHEMA: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_SCHEMA),
|
|
964
|
+
/* harmony export */ SQLITE_SELECT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_SELECT),
|
|
965
|
+
/* harmony export */ SQLITE_STATIC: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_STATIC),
|
|
966
|
+
/* harmony export */ SQLITE_SUBTYPE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_SUBTYPE),
|
|
967
|
+
/* harmony export */ SQLITE_SYNC_DATAONLY: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_SYNC_DATAONLY),
|
|
968
|
+
/* harmony export */ SQLITE_SYNC_FULL: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_SYNC_FULL),
|
|
969
|
+
/* harmony export */ SQLITE_SYNC_NORMAL: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_SYNC_NORMAL),
|
|
970
|
+
/* harmony export */ SQLITE_TEXT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_TEXT),
|
|
971
|
+
/* harmony export */ SQLITE_TOOBIG: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_TOOBIG),
|
|
972
|
+
/* harmony export */ SQLITE_TRANSACTION: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_TRANSACTION),
|
|
973
|
+
/* harmony export */ SQLITE_TRANSIENT: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_TRANSIENT),
|
|
974
|
+
/* harmony export */ SQLITE_UPDATE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_UPDATE),
|
|
975
|
+
/* harmony export */ SQLITE_UTF16: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_UTF16),
|
|
976
|
+
/* harmony export */ SQLITE_UTF16BE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_UTF16BE),
|
|
977
|
+
/* harmony export */ SQLITE_UTF16LE: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_UTF16LE),
|
|
978
|
+
/* harmony export */ SQLITE_UTF8: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_UTF8),
|
|
979
|
+
/* harmony export */ SQLITE_WARNING: () => (/* reexport safe */ _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_WARNING)
|
|
980
|
+
/* harmony export */ });
|
|
981
|
+
/* harmony import */ var _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./sqlite-constants.js */ "../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/sqlite-constants.js");
|
|
982
|
+
// Copyright 2024 Roy T. Hashimoto. All Rights Reserved.
|
|
983
|
+
|
|
984
|
+
|
|
985
|
+
|
|
986
|
+
const DEFAULT_SECTOR_SIZE = 512;
|
|
987
|
+
|
|
988
|
+
// Base class for a VFS.
|
|
989
|
+
class Base {
|
|
990
|
+
name;
|
|
991
|
+
mxPathname = 64;
|
|
992
|
+
_module;
|
|
993
|
+
|
|
994
|
+
/**
|
|
995
|
+
* @param {string} name
|
|
996
|
+
* @param {object} module
|
|
997
|
+
*/
|
|
998
|
+
constructor(name, module) {
|
|
999
|
+
this.name = name;
|
|
1000
|
+
this._module = module;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
/**
|
|
1004
|
+
* @returns {void|Promise<void>}
|
|
1005
|
+
*/
|
|
1006
|
+
close() {
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
/**
|
|
1010
|
+
* @returns {boolean|Promise<boolean>}
|
|
1011
|
+
*/
|
|
1012
|
+
isReady() {
|
|
1013
|
+
return true;
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
/**
|
|
1017
|
+
* Overload in subclasses to indicate which methods are asynchronous.
|
|
1018
|
+
* @param {string} methodName
|
|
1019
|
+
* @returns {boolean}
|
|
1020
|
+
*/
|
|
1021
|
+
hasAsyncMethod(methodName) {
|
|
1022
|
+
return false;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
/**
|
|
1026
|
+
* @param {number} pVfs
|
|
1027
|
+
* @param {number} zName
|
|
1028
|
+
* @param {number} pFile
|
|
1029
|
+
* @param {number} flags
|
|
1030
|
+
* @param {number} pOutFlags
|
|
1031
|
+
* @returns {number|Promise<number>}
|
|
1032
|
+
*/
|
|
1033
|
+
xOpen(pVfs, zName, pFile, flags, pOutFlags) {
|
|
1034
|
+
return _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_CANTOPEN;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
/**
|
|
1038
|
+
* @param {number} pVfs
|
|
1039
|
+
* @param {number} zName
|
|
1040
|
+
* @param {number} syncDir
|
|
1041
|
+
* @returns {number|Promise<number>}
|
|
1042
|
+
*/
|
|
1043
|
+
xDelete(pVfs, zName, syncDir) {
|
|
1044
|
+
return _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
/**
|
|
1048
|
+
* @param {number} pVfs
|
|
1049
|
+
* @param {number} zName
|
|
1050
|
+
* @param {number} flags
|
|
1051
|
+
* @param {number} pResOut
|
|
1052
|
+
* @returns {number|Promise<number>}
|
|
1053
|
+
*/
|
|
1054
|
+
xAccess(pVfs, zName, flags, pResOut) {
|
|
1055
|
+
return _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
/**
|
|
1059
|
+
* @param {number} pVfs
|
|
1060
|
+
* @param {number} zName
|
|
1061
|
+
* @param {number} nOut
|
|
1062
|
+
* @param {number} zOut
|
|
1063
|
+
* @returns {number|Promise<number>}
|
|
1064
|
+
*/
|
|
1065
|
+
xFullPathname(pVfs, zName, nOut, zOut) {
|
|
1066
|
+
return _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
/**
|
|
1070
|
+
* @param {number} pVfs
|
|
1071
|
+
* @param {number} nBuf
|
|
1072
|
+
* @param {number} zBuf
|
|
1073
|
+
* @returns {number|Promise<number>}
|
|
1074
|
+
*/
|
|
1075
|
+
xGetLastError(pVfs, nBuf, zBuf) {
|
|
1076
|
+
return _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
/**
|
|
1080
|
+
* @param {number} pFile
|
|
1081
|
+
* @returns {number|Promise<number>}
|
|
1082
|
+
*/
|
|
1083
|
+
xClose(pFile) {
|
|
1084
|
+
return _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
/**
|
|
1088
|
+
* @param {number} pFile
|
|
1089
|
+
* @param {number} pData
|
|
1090
|
+
* @param {number} iAmt
|
|
1091
|
+
* @param {number} iOffsetLo
|
|
1092
|
+
* @param {number} iOffsetHi
|
|
1093
|
+
* @returns {number|Promise<number>}
|
|
1094
|
+
*/
|
|
1095
|
+
xRead(pFile, pData, iAmt, iOffsetLo, iOffsetHi) {
|
|
1096
|
+
return _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
/**
|
|
1100
|
+
* @param {number} pFile
|
|
1101
|
+
* @param {number} pData
|
|
1102
|
+
* @param {number} iAmt
|
|
1103
|
+
* @param {number} iOffsetLo
|
|
1104
|
+
* @param {number} iOffsetHi
|
|
1105
|
+
* @returns {number|Promise<number>}
|
|
1106
|
+
*/
|
|
1107
|
+
xWrite(pFile, pData, iAmt, iOffsetLo, iOffsetHi) {
|
|
1108
|
+
return _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
/**
|
|
1112
|
+
* @param {number} pFile
|
|
1113
|
+
* @param {number} sizeLo
|
|
1114
|
+
* @param {number} sizeHi
|
|
1115
|
+
* @returns {number|Promise<number>}
|
|
1116
|
+
*/
|
|
1117
|
+
xTruncate(pFile, sizeLo, sizeHi) {
|
|
1118
|
+
return _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
/**
|
|
1122
|
+
* @param {number} pFile
|
|
1123
|
+
* @param {number} flags
|
|
1124
|
+
* @returns {number|Promise<number>}
|
|
1125
|
+
*/
|
|
1126
|
+
xSync(pFile, flags) {
|
|
1127
|
+
return _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
/**
|
|
1131
|
+
*
|
|
1132
|
+
* @param {number} pFile
|
|
1133
|
+
* @param {number} pSize
|
|
1134
|
+
* @returns {number|Promise<number>}
|
|
1135
|
+
*/
|
|
1136
|
+
xFileSize(pFile, pSize) {
|
|
1137
|
+
return _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
/**
|
|
1141
|
+
* @param {number} pFile
|
|
1142
|
+
* @param {number} lockType
|
|
1143
|
+
* @returns {number|Promise<number>}
|
|
1144
|
+
*/
|
|
1145
|
+
xLock(pFile, lockType) {
|
|
1146
|
+
return _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
/**
|
|
1150
|
+
* @param {number} pFile
|
|
1151
|
+
* @param {number} lockType
|
|
1152
|
+
* @returns {number|Promise<number>}
|
|
1153
|
+
*/
|
|
1154
|
+
xUnlock(pFile, lockType) {
|
|
1155
|
+
return _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
/**
|
|
1159
|
+
* @param {number} pFile
|
|
1160
|
+
* @param {number} pResOut
|
|
1161
|
+
* @returns {number|Promise<number>}
|
|
1162
|
+
*/
|
|
1163
|
+
xCheckReservedLock(pFile, pResOut) {
|
|
1164
|
+
return _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OK;
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
/**
|
|
1168
|
+
* @param {number} pFile
|
|
1169
|
+
* @param {number} op
|
|
1170
|
+
* @param {number} pArg
|
|
1171
|
+
* @returns {number|Promise<number>}
|
|
1172
|
+
*/
|
|
1173
|
+
xFileControl(pFile, op, pArg) {
|
|
1174
|
+
return _sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_NOTFOUND;
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
/**
|
|
1178
|
+
* @param {number} pFile
|
|
1179
|
+
* @returns {number|Promise<number>}
|
|
1180
|
+
*/
|
|
1181
|
+
xSectorSize(pFile) {
|
|
1182
|
+
return DEFAULT_SECTOR_SIZE;
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
/**
|
|
1186
|
+
* @param {number} pFile
|
|
1187
|
+
* @returns {number|Promise<number>}
|
|
1188
|
+
*/
|
|
1189
|
+
xDeviceCharacteristics(pFile) {
|
|
1190
|
+
return 0;
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
const FILE_TYPE_MASK = [
|
|
1195
|
+
_sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_MAIN_DB,
|
|
1196
|
+
_sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_MAIN_JOURNAL,
|
|
1197
|
+
_sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_TEMP_DB,
|
|
1198
|
+
_sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_TEMP_JOURNAL,
|
|
1199
|
+
_sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_TRANSIENT_DB,
|
|
1200
|
+
_sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_SUBJOURNAL,
|
|
1201
|
+
_sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_SUPER_JOURNAL,
|
|
1202
|
+
_sqlite_constants_js__WEBPACK_IMPORTED_MODULE_0__.SQLITE_OPEN_WAL
|
|
1203
|
+
].reduce((mask, element) => mask | element);
|
|
1204
|
+
|
|
1205
|
+
/***/ },
|
|
1206
|
+
|
|
1207
|
+
/***/ "../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/examples/LazyLock.js"
|
|
1208
|
+
/*!**************************************************************************************************************************!*\
|
|
1209
|
+
!*** ../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/examples/LazyLock.js ***!
|
|
1210
|
+
\**************************************************************************************************************************/
|
|
1211
|
+
(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
1212
|
+
|
|
1213
|
+
__webpack_require__.r(__webpack_exports__);
|
|
1214
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
1215
|
+
/* harmony export */ LazyLock: () => (/* binding */ LazyLock)
|
|
1216
|
+
/* harmony export */ });
|
|
1217
|
+
/* harmony import */ var _Lock_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Lock.js */ "../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/examples/Lock.js");
|
|
1218
|
+
|
|
1219
|
+
|
|
1220
|
+
class LazyLock extends _Lock_js__WEBPACK_IMPORTED_MODULE_0__.Lock {
|
|
1221
|
+
#channel;
|
|
1222
|
+
#isBusy = false;
|
|
1223
|
+
#hasReleaseRequest = false;
|
|
1224
|
+
|
|
1225
|
+
/**
|
|
1226
|
+
* @param {string} name
|
|
1227
|
+
*/
|
|
1228
|
+
constructor(name) {
|
|
1229
|
+
super(name);
|
|
1230
|
+
this.#channel = new BroadcastChannel(name);
|
|
1231
|
+
this.#channel.onmessage = (event) => {
|
|
1232
|
+
if (this.#isBusy) {
|
|
1233
|
+
// We're using the lock so postpone the release.
|
|
1234
|
+
this.#hasReleaseRequest = true;
|
|
1235
|
+
} else {
|
|
1236
|
+
this.release();
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
close() {
|
|
1242
|
+
super.close();
|
|
1243
|
+
this.#channel.onmessage = null;
|
|
1244
|
+
this.#channel.close();
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
/**
|
|
1248
|
+
* @param {LockMode} mode
|
|
1249
|
+
* @param {number} timeout
|
|
1250
|
+
* @returns {Promise<boolean>}
|
|
1251
|
+
*/
|
|
1252
|
+
async acquire(mode, timeout = -1) {
|
|
1253
|
+
this.#isBusy = true;
|
|
1254
|
+
try {
|
|
1255
|
+
if (mode === this.mode) {
|
|
1256
|
+
// We never had to release the lock.
|
|
1257
|
+
return true;
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
if (this.mode) {
|
|
1261
|
+
// Release the lock to acquire it in a different mode.
|
|
1262
|
+
super.release();
|
|
1263
|
+
} else {
|
|
1264
|
+
// Poll for the lock. This isn't necessary but if it works it avoids
|
|
1265
|
+
// the BroadcastChannel traffic.
|
|
1266
|
+
if (await super.acquire(mode, 0)) {
|
|
1267
|
+
return true;
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
// Request the lock.
|
|
1272
|
+
const pResult = super.acquire(mode, timeout)
|
|
1273
|
+
this.#channel.postMessage({});
|
|
1274
|
+
|
|
1275
|
+
return await pResult;
|
|
1276
|
+
} catch (e) {
|
|
1277
|
+
this.release();
|
|
1278
|
+
throw e;
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
/**
|
|
1283
|
+
* @param {LockMode} mode
|
|
1284
|
+
* @returns {boolean}
|
|
1285
|
+
*/
|
|
1286
|
+
acquireIfHeld(mode) {
|
|
1287
|
+
if (mode === this.mode) {
|
|
1288
|
+
this.#isBusy = true;
|
|
1289
|
+
return true;
|
|
1290
|
+
}
|
|
1291
|
+
return false;
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
release() {
|
|
1295
|
+
super.release();
|
|
1296
|
+
this.#isBusy = false;
|
|
1297
|
+
this.#hasReleaseRequest = false;
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
releaseLazy() {
|
|
1301
|
+
// Release the lock only if someone else wants it.
|
|
1302
|
+
this.#isBusy = false;
|
|
1303
|
+
if (this.#hasReleaseRequest) {
|
|
1304
|
+
this.release();
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
/***/ },
|
|
1310
|
+
|
|
1311
|
+
/***/ "../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/examples/Lock.js"
|
|
1312
|
+
/*!**********************************************************************************************************************!*\
|
|
1313
|
+
!*** ../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/examples/Lock.js ***!
|
|
1314
|
+
\**********************************************************************************************************************/
|
|
1315
|
+
(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
1316
|
+
|
|
1317
|
+
__webpack_require__.r(__webpack_exports__);
|
|
1318
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
1319
|
+
/* harmony export */ Lock: () => (/* binding */ Lock)
|
|
1320
|
+
/* harmony export */ });
|
|
1321
|
+
// This is a convenience wrapper for the Web Locks API.
|
|
1322
|
+
class Lock {
|
|
1323
|
+
#name;
|
|
1324
|
+
/** @type {LockMode?} */ #mode = null;
|
|
1325
|
+
/** @type {Promise<Function|null>} */ #releaser = Promise.resolve(null);
|
|
1326
|
+
#isAcquiring = false;
|
|
1327
|
+
|
|
1328
|
+
/**
|
|
1329
|
+
* @param {string} name
|
|
1330
|
+
*/
|
|
1331
|
+
constructor(name) {
|
|
1332
|
+
this.#name = name;
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
get name() { return this.#name; }
|
|
1336
|
+
get mode() { return this.#mode; }
|
|
1337
|
+
|
|
1338
|
+
close() {
|
|
1339
|
+
this.release();
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
/**
|
|
1343
|
+
* @param {'shared'|'exclusive'} mode
|
|
1344
|
+
* @param {number} timeout -1 for infinite, 0 for poll, >0 for milliseconds
|
|
1345
|
+
* @return {Promise<boolean>} true if lock acquired, false on failed poll
|
|
1346
|
+
*/
|
|
1347
|
+
async acquire(mode, timeout = -1) {
|
|
1348
|
+
if (this.#isAcquiring) throw new Error('Lock is already being acquired');
|
|
1349
|
+
this.#isAcquiring = true;
|
|
1350
|
+
try {
|
|
1351
|
+
if (this.#mode) {
|
|
1352
|
+
throw new Error(`Lock ${this.#name} is already acquired`);
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
this.#releaser = new Promise((resolve, reject) => {
|
|
1356
|
+
/** @type {LockOptions} */
|
|
1357
|
+
const options = { mode, ifAvailable: timeout === 0 };
|
|
1358
|
+
if (timeout > 0) {
|
|
1359
|
+
options.signal = AbortSignal.timeout(timeout);
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
navigator.locks.request(this.#name, options, lock => {
|
|
1363
|
+
if (lock === null) {
|
|
1364
|
+
// Polling (with timeout = 0) did not acquire the lock.
|
|
1365
|
+
return resolve(null);
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
// Lock acquired. The lock is released when this returned
|
|
1369
|
+
// Promise is resolved.
|
|
1370
|
+
this.#mode = mode;
|
|
1371
|
+
return new Promise(releaser => {
|
|
1372
|
+
resolve(releaser);
|
|
1373
|
+
})
|
|
1374
|
+
}).catch(e => {
|
|
1375
|
+
return reject(e);
|
|
1376
|
+
});
|
|
1377
|
+
});
|
|
1378
|
+
|
|
1379
|
+
return this.#releaser.then(releaser => !!releaser)
|
|
1380
|
+
} finally {
|
|
1381
|
+
this.#isAcquiring = false;
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
release() {
|
|
1386
|
+
this.#releaser.then(releaser => releaser?.(), () => {});
|
|
1387
|
+
this.#mode = null;
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
|
|
1392
|
+
/***/ },
|
|
1393
|
+
|
|
1394
|
+
/***/ "../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/examples/OPFSWriteAheadVFS.js"
|
|
1395
|
+
/*!***********************************************************************************************************************************!*\
|
|
1396
|
+
!*** ../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/examples/OPFSWriteAheadVFS.js ***!
|
|
1397
|
+
\***********************************************************************************************************************************/
|
|
1398
|
+
(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
1399
|
+
|
|
1400
|
+
__webpack_require__.r(__webpack_exports__);
|
|
1401
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
1402
|
+
/* harmony export */ OPFSWriteAheadVFS: () => (/* binding */ OPFSWriteAheadVFS)
|
|
1403
|
+
/* harmony export */ });
|
|
1404
|
+
/* harmony import */ var _FacadeVFS_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../FacadeVFS.js */ "../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/FacadeVFS.js");
|
|
1405
|
+
/* harmony import */ var _VFS_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../VFS.js */ "../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/VFS.js");
|
|
1406
|
+
/* harmony import */ var _LazyLock_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./LazyLock.js */ "../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/examples/LazyLock.js");
|
|
1407
|
+
/* harmony import */ var _WriteAhead_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./WriteAhead.js */ "../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/examples/WriteAhead.js");
|
|
1408
|
+
|
|
1409
|
+
|
|
1410
|
+
|
|
1411
|
+
|
|
1412
|
+
|
|
1413
|
+
const LIBRARY_FILES_ROOT = '.wa-sqlite';
|
|
1414
|
+
const DEFAULT_TEMP_FILES = 6;
|
|
1415
|
+
|
|
1416
|
+
const finalizationRegistry = new FinalizationRegistry((/** @type {() => void} */ f) => f());
|
|
1417
|
+
|
|
1418
|
+
/**
|
|
1419
|
+
* @typedef FileEntry
|
|
1420
|
+
* @property {string} zName
|
|
1421
|
+
* @property {number} flags
|
|
1422
|
+
* @property {FileSystemSyncAccessHandle} [accessHandle]
|
|
1423
|
+
|
|
1424
|
+
* Main database file properties:
|
|
1425
|
+
* @property {*} [retryResult]
|
|
1426
|
+
* @property {FileSystemSyncAccessHandle[]} [waHandles]
|
|
1427
|
+
*
|
|
1428
|
+
* @property {'reserved'|'exclusive'|null} [writeHint]
|
|
1429
|
+
* @property {'normal'|'exclusive'} [lockingMode]
|
|
1430
|
+
* @property {number} [lockState] SQLITE_LOCK_*
|
|
1431
|
+
* @property {LazyLock} [readLock]
|
|
1432
|
+
* @property {LazyLock} [writeLock]
|
|
1433
|
+
* @property {'none'|'read'|'write'|'readwrite'} [useLazyLock]
|
|
1434
|
+
* @property {number} [timeout]
|
|
1435
|
+
* @property {0|1|2|3} [synchronous]
|
|
1436
|
+
* @property {number?} [pageSize]
|
|
1437
|
+
* @property {boolean} [overwrite]
|
|
1438
|
+
*
|
|
1439
|
+
* @property {WriteAhead} [writeAhead]
|
|
1440
|
+
*/
|
|
1441
|
+
|
|
1442
|
+
/**
|
|
1443
|
+
* @typedef OPFSWriteAheadOptions
|
|
1444
|
+
* @property {number} [nTmpFiles]
|
|
1445
|
+
* @property {number} [autoCheckpoint]
|
|
1446
|
+
* @property {number} [backstopInterval]
|
|
1447
|
+
*/
|
|
1448
|
+
|
|
1449
|
+
class OPFSWriteAheadVFS extends _FacadeVFS_js__WEBPACK_IMPORTED_MODULE_0__.FacadeVFS {
|
|
1450
|
+
lastError = null;
|
|
1451
|
+
log = null;
|
|
1452
|
+
|
|
1453
|
+
/** @type {Map<number, FileEntry>} */ mapIdToFile = new Map();
|
|
1454
|
+
/** @type {Map<string, FileEntry>} */ mapPathToFile = new Map();
|
|
1455
|
+
|
|
1456
|
+
/** @type {Map<string, FileSystemSyncAccessHandle>} */ boundTempFiles = new Map();
|
|
1457
|
+
/** @type {Set<FileSystemSyncAccessHandle>} */ unboundTempFiles = new Set();
|
|
1458
|
+
/** @type {OPFSWriteAheadOptions} */ options = {
|
|
1459
|
+
nTmpFiles: DEFAULT_TEMP_FILES
|
|
1460
|
+
};
|
|
1461
|
+
|
|
1462
|
+
_ready;
|
|
1463
|
+
|
|
1464
|
+
static async create(name, module, options) {
|
|
1465
|
+
const vfs = new OPFSWriteAheadVFS(name, module);
|
|
1466
|
+
Object.assign(vfs.options, options);
|
|
1467
|
+
await vfs.isReady();
|
|
1468
|
+
return vfs;
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
constructor(name, module) {
|
|
1472
|
+
super(name, module);
|
|
1473
|
+
this._ready = (async () => {
|
|
1474
|
+
// Ensure the library files root directory exists.
|
|
1475
|
+
let dirHandle = await navigator.storage.getDirectory();
|
|
1476
|
+
dirHandle = await dirHandle.getDirectoryHandle(LIBRARY_FILES_ROOT, { create: true });
|
|
1477
|
+
|
|
1478
|
+
// Clean up any stale session directories.
|
|
1479
|
+
// @ts-ignore
|
|
1480
|
+
for await (const name of dirHandle.keys()) {
|
|
1481
|
+
if (name.startsWith('.session-')) {
|
|
1482
|
+
// Acquire a lock on the session directory to ensure it is not in use.
|
|
1483
|
+
await navigator.locks.request(name, { ifAvailable: true }, async lock => {
|
|
1484
|
+
if (lock) {
|
|
1485
|
+
// This directory is not in use.
|
|
1486
|
+
try {
|
|
1487
|
+
await dirHandle.removeEntry(name, { recursive: true });
|
|
1488
|
+
} catch (e) {
|
|
1489
|
+
// Ignore errors, will try again next time.
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
});
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
// Create our session directory.
|
|
1497
|
+
const dirName = `.session-${Math.random().toString(16).slice(2)}`;
|
|
1498
|
+
await new Promise(resolve => {
|
|
1499
|
+
navigator.locks.request(dirName, () => {
|
|
1500
|
+
// @ts-ignore
|
|
1501
|
+
resolve();
|
|
1502
|
+
return new Promise(release => {
|
|
1503
|
+
// @ts-ignore
|
|
1504
|
+
finalizationRegistry.register(this, release);
|
|
1505
|
+
});
|
|
1506
|
+
});
|
|
1507
|
+
});
|
|
1508
|
+
dirHandle = await dirHandle.getDirectoryHandle(dirName, { create: true });
|
|
1509
|
+
|
|
1510
|
+
// Create temporary files.
|
|
1511
|
+
for (let i = 0; i < this.options.nTmpFiles; i++) {
|
|
1512
|
+
const fileHandle= await dirHandle.getFileHandle(i.toString(), { create: true });
|
|
1513
|
+
const accessHandle = await fileHandle.createSyncAccessHandle();
|
|
1514
|
+
finalizationRegistry.register(this, () => accessHandle.close());
|
|
1515
|
+
this.unboundTempFiles.add(accessHandle);
|
|
1516
|
+
}
|
|
1517
|
+
})();
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
isReady() {
|
|
1521
|
+
return Promise.all([super.isReady(), this._ready]).then(() => true);
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
/**
|
|
1525
|
+
* @param {string?} zName
|
|
1526
|
+
* @param {number} fileId
|
|
1527
|
+
* @param {number} flags
|
|
1528
|
+
* @param {DataView} pOutFlags
|
|
1529
|
+
* @returns {number}
|
|
1530
|
+
*/
|
|
1531
|
+
jOpen(zName, fileId, flags, pOutFlags) {
|
|
1532
|
+
try {
|
|
1533
|
+
if (zName === null) {
|
|
1534
|
+
// Generate a temporary filename. This will only be used as a
|
|
1535
|
+
// key to map to a pre-opened temporary file access handle.
|
|
1536
|
+
zName = Math.random().toString(16).slice(2);
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
const file = this.mapPathToFile.get(zName) ?? {
|
|
1540
|
+
zName,
|
|
1541
|
+
flags,
|
|
1542
|
+
retryResult: null,
|
|
1543
|
+
};
|
|
1544
|
+
this.mapPathToFile.set(zName, file);
|
|
1545
|
+
|
|
1546
|
+
if (flags & _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OPEN_MAIN_DB) {
|
|
1547
|
+
// Open database and journal files with a retry operation.
|
|
1548
|
+
if (file.retryResult === null) {
|
|
1549
|
+
// This is the initial open attempt. Start the asynchronous task
|
|
1550
|
+
// and return SQLITE_BUSY to force a retry.
|
|
1551
|
+
this._module.retryOps.push(this.#retryOpen(zName, flags, fileId, pOutFlags));
|
|
1552
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_BUSY;
|
|
1553
|
+
} else if (file.retryResult instanceof Error) {
|
|
1554
|
+
const e = file.retryResult;
|
|
1555
|
+
file.retryResult = null;
|
|
1556
|
+
throw e;
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1559
|
+
// Initialize database file state.
|
|
1560
|
+
file.accessHandle = file.retryResult.accessHandle;
|
|
1561
|
+
file.waHandles = file.retryResult.waHandles;
|
|
1562
|
+
file.writeAhead = file.retryResult.writeAhead;
|
|
1563
|
+
file.retryResult = null;
|
|
1564
|
+
|
|
1565
|
+
file.lockState = _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_LOCK_NONE;
|
|
1566
|
+
file.lockingMode = 'normal';
|
|
1567
|
+
file.readLock = new _LazyLock_js__WEBPACK_IMPORTED_MODULE_2__.LazyLock(`${zName}#read`);
|
|
1568
|
+
file.writeLock = new _LazyLock_js__WEBPACK_IMPORTED_MODULE_2__.LazyLock(`${zName}#write`);
|
|
1569
|
+
file.useLazyLock = 'readwrite';
|
|
1570
|
+
file.timeout = -1;
|
|
1571
|
+
file.synchronous = 1; // NORMAL
|
|
1572
|
+
file.writeHint = null;
|
|
1573
|
+
file.pageSize = null;
|
|
1574
|
+
file.overwrite = false;
|
|
1575
|
+
} else if (flags & (_VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OPEN_WAL | _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OPEN_SUPER_JOURNAL)) {
|
|
1576
|
+
throw new Error('WAL and super-journal files are not supported');
|
|
1577
|
+
} else if (file.accessHandle) {
|
|
1578
|
+
// This temporary file already has an access handle, which happens
|
|
1579
|
+
// only for tests. Just use it as is.
|
|
1580
|
+
} else {
|
|
1581
|
+
// This is a temporary file. Use an unbound pre-opened accessHandle.
|
|
1582
|
+
if (!(flags & _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OPEN_CREATE)) throw new Error('file not found');
|
|
1583
|
+
file.accessHandle = this.#openTemporaryFile(zName);
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
this.mapIdToFile.set(fileId, file);
|
|
1587
|
+
pOutFlags.setInt32(0, flags, true);
|
|
1588
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
|
|
1589
|
+
} catch (e) {
|
|
1590
|
+
console.error(e.stack);
|
|
1591
|
+
this.lastError = e;
|
|
1592
|
+
this.mapPathToFile.delete(zName);
|
|
1593
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_CANTOPEN;
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
/**
|
|
1598
|
+
* @param {string} zName
|
|
1599
|
+
* @param {number} syncDir
|
|
1600
|
+
* @returns {number}
|
|
1601
|
+
*/
|
|
1602
|
+
jDelete(zName, syncDir) {
|
|
1603
|
+
try {
|
|
1604
|
+
if (this.boundTempFiles.has(zName)) {
|
|
1605
|
+
const file = this.mapPathToFile.get(zName);
|
|
1606
|
+
this.#deleteTemporaryFile(file);
|
|
1607
|
+
} else {
|
|
1608
|
+
throw new Error(`unexpected file deletion: ${zName}`);
|
|
1609
|
+
}
|
|
1610
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
|
|
1611
|
+
} catch (e) {
|
|
1612
|
+
console.error(e.stack);
|
|
1613
|
+
this.lastError = e;
|
|
1614
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_IOERR_DELETE;
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
/**
|
|
1619
|
+
* @param {string} zName
|
|
1620
|
+
* @param {number} flags
|
|
1621
|
+
* @param {DataView} pResOut
|
|
1622
|
+
* @returns {number}
|
|
1623
|
+
*/
|
|
1624
|
+
jAccess(zName, flags, pResOut) {
|
|
1625
|
+
try {
|
|
1626
|
+
const file = this.mapPathToFile.get(zName);
|
|
1627
|
+
pResOut.setInt32(0, file ? 1 : 0, true);
|
|
1628
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
|
|
1629
|
+
} catch (e) {
|
|
1630
|
+
console.error(e.stack);
|
|
1631
|
+
this.lastError = e;
|
|
1632
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_IOERR_ACCESS;
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
/**
|
|
1637
|
+
* @param {number} fileId
|
|
1638
|
+
* @returns {number}
|
|
1639
|
+
*/
|
|
1640
|
+
jClose(fileId) {
|
|
1641
|
+
try {
|
|
1642
|
+
const file = this.mapIdToFile.get(fileId);
|
|
1643
|
+
if (file?.flags & _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OPEN_MAIN_DB) {
|
|
1644
|
+
file.writeAhead.close();
|
|
1645
|
+
file.accessHandle.close();
|
|
1646
|
+
file.waHandles.forEach(handle => handle.close());
|
|
1647
|
+
this.mapPathToFile.delete(file?.zName);
|
|
1648
|
+
|
|
1649
|
+
file.readLock.close();
|
|
1650
|
+
file.writeLock.close();
|
|
1651
|
+
} else if (file?.flags & _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OPEN_DELETEONCLOSE) {
|
|
1652
|
+
this.#deleteTemporaryFile(file);
|
|
1653
|
+
}
|
|
1654
|
+
|
|
1655
|
+
// Disassociate fileId from file entry.
|
|
1656
|
+
this.mapIdToFile.delete(fileId);
|
|
1657
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
|
|
1658
|
+
} catch (e) {
|
|
1659
|
+
console.error(e.stack);
|
|
1660
|
+
this.lastError = e;
|
|
1661
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_IOERR_CLOSE;
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
/**
|
|
1666
|
+
* @param {number} fileId
|
|
1667
|
+
* @param {Uint8Array} pData
|
|
1668
|
+
* @param {number} iOffset
|
|
1669
|
+
* @returns {number}
|
|
1670
|
+
*/
|
|
1671
|
+
jRead(fileId, pData, iOffset) {
|
|
1672
|
+
try {
|
|
1673
|
+
const file = this.mapIdToFile.get(fileId);
|
|
1674
|
+
|
|
1675
|
+
let bytesRead = null;
|
|
1676
|
+
if (file.flags & _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OPEN_MAIN_DB) {
|
|
1677
|
+
// Try reading from the write-ahead overlays first. A read on the
|
|
1678
|
+
// database file is always a complete page, except when reading
|
|
1679
|
+
// from the 100-byte header.
|
|
1680
|
+
const pageOffset = iOffset < 100 ? iOffset : 0;
|
|
1681
|
+
const page = file.writeAhead.read(iOffset - pageOffset);
|
|
1682
|
+
if (page) {
|
|
1683
|
+
const readData = page.subarray(pageOffset, pageOffset + pData.byteLength);
|
|
1684
|
+
pData.set(readData);
|
|
1685
|
+
bytesRead = readData.byteLength;
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1689
|
+
if (bytesRead === null) {
|
|
1690
|
+
// Read directly from the OPFS file.
|
|
1691
|
+
|
|
1692
|
+
// On Chrome (at least), passing pData to accessHandle.read() is
|
|
1693
|
+
// an error because pData is a Proxy of a Uint8Array. Calling
|
|
1694
|
+
// subarray() produces a real Uint8Array and that works.
|
|
1695
|
+
bytesRead = file.accessHandle.read(pData.subarray(), { at: iOffset });
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
if (bytesRead < pData.byteLength) {
|
|
1699
|
+
pData.fill(0, bytesRead);
|
|
1700
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_IOERR_SHORT_READ;
|
|
1701
|
+
}
|
|
1702
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
|
|
1703
|
+
} catch (e) {
|
|
1704
|
+
console.error(e.stack);
|
|
1705
|
+
this.lastError = e;
|
|
1706
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_IOERR_READ;
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
/**
|
|
1711
|
+
* @param {number} fileId
|
|
1712
|
+
* @param {Uint8Array} pData
|
|
1713
|
+
* @param {number} iOffset
|
|
1714
|
+
* @returns {number}
|
|
1715
|
+
*/
|
|
1716
|
+
jWrite(fileId, pData, iOffset) {
|
|
1717
|
+
try {
|
|
1718
|
+
const file = this.mapIdToFile.get(fileId);
|
|
1719
|
+
if (file.flags & _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OPEN_MAIN_DB) {
|
|
1720
|
+
// Write to the write-ahead overlay.
|
|
1721
|
+
const isPageResize = file.overwrite && file.pageSize !== pData.byteLength;
|
|
1722
|
+
file.writeAhead.write(iOffset, pData, {
|
|
1723
|
+
dstPageSize: isPageResize ? file.pageSize : null
|
|
1724
|
+
});
|
|
1725
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
// On Chrome (at least), passing pData to accessHandle.write() is
|
|
1729
|
+
// an error because pData is a Proxy of a Uint8Array. Calling
|
|
1730
|
+
// subarray() produces a real Uint8Array and that works.
|
|
1731
|
+
file.accessHandle.write(pData.subarray(), { at: iOffset });
|
|
1732
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
|
|
1733
|
+
} catch (e) {
|
|
1734
|
+
console.error(e.stack);
|
|
1735
|
+
this.lastError = e;
|
|
1736
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_IOERR_WRITE;
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
/**
|
|
1741
|
+
* @param {number} fileId
|
|
1742
|
+
* @param {number} iSize
|
|
1743
|
+
* @returns {number}
|
|
1744
|
+
*/
|
|
1745
|
+
jTruncate(fileId, iSize) {
|
|
1746
|
+
try {
|
|
1747
|
+
const file = this.mapIdToFile.get(fileId);
|
|
1748
|
+
if (file.flags & _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OPEN_MAIN_DB) {
|
|
1749
|
+
file.writeAhead.truncate(iSize);
|
|
1750
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
|
|
1751
|
+
}
|
|
1752
|
+
file.accessHandle.truncate(iSize);
|
|
1753
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
|
|
1754
|
+
} catch (e) {
|
|
1755
|
+
console.error(e.stack);
|
|
1756
|
+
this.lastError = e;
|
|
1757
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_IOERR_TRUNCATE;
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
/**
|
|
1762
|
+
* @param {number} fileId
|
|
1763
|
+
* @param {number} flags
|
|
1764
|
+
* @returns {number}
|
|
1765
|
+
*/
|
|
1766
|
+
jSync(fileId, flags) {
|
|
1767
|
+
try {
|
|
1768
|
+
const file = this.mapIdToFile.get(fileId);
|
|
1769
|
+
if (file.flags & _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OPEN_MAIN_DB) {
|
|
1770
|
+
const durability = file.synchronous > 1 ? 'strict' : 'relaxed';
|
|
1771
|
+
file.writeAhead.sync({ durability });
|
|
1772
|
+
} else {
|
|
1773
|
+
// This is a temporary file so sync is not needed.
|
|
1774
|
+
// Temporary journals are only used for rollback by the
|
|
1775
|
+
// connection that created them, not for recovery.
|
|
1776
|
+
}
|
|
1777
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
|
|
1778
|
+
} catch (e) {
|
|
1779
|
+
console.error(e.stack);
|
|
1780
|
+
this.lastError = e;
|
|
1781
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_IOERR_FSYNC;
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
|
|
1785
|
+
/**
|
|
1786
|
+
* @param {number} fileId
|
|
1787
|
+
* @param {DataView} pSize64
|
|
1788
|
+
* @returns {number}
|
|
1789
|
+
*/
|
|
1790
|
+
jFileSize(fileId, pSize64) {
|
|
1791
|
+
try {
|
|
1792
|
+
const file = this.mapIdToFile.get(fileId);
|
|
1793
|
+
|
|
1794
|
+
let size;
|
|
1795
|
+
if (file.flags & _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OPEN_MAIN_DB) {
|
|
1796
|
+
size = file.writeAhead.getFileSize() || file.accessHandle.getSize();
|
|
1797
|
+
} else {
|
|
1798
|
+
size = file.accessHandle.getSize();
|
|
1799
|
+
}
|
|
1800
|
+
pSize64.setBigInt64(0, BigInt(size), true);
|
|
1801
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
|
|
1802
|
+
} catch (e) {
|
|
1803
|
+
console.error(e.stack);
|
|
1804
|
+
this.lastError = e;
|
|
1805
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_IOERR_FSTAT;
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1808
|
+
|
|
1809
|
+
/**
|
|
1810
|
+
* @param {number} pFile
|
|
1811
|
+
* @param {number} lockType
|
|
1812
|
+
* @returns {number|Promise<number>}
|
|
1813
|
+
*/
|
|
1814
|
+
jLock(pFile, lockType) {
|
|
1815
|
+
try {
|
|
1816
|
+
const file = this.mapIdToFile.get(pFile);
|
|
1817
|
+
if (file.lockState === _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_LOCK_NONE && lockType === _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_LOCK_SHARED) {
|
|
1818
|
+
// We do all our locking work in this transition.
|
|
1819
|
+
if (file.retryResult === null) {
|
|
1820
|
+
if (file.lockingMode === 'exclusive') {
|
|
1821
|
+
// Exclusive locking mode is treated as a write, and the
|
|
1822
|
+
// read lock is also acquired to block readers.
|
|
1823
|
+
file.retryResult = {};
|
|
1824
|
+
this._module.retryOps.push(this.#retryLockWrite(file));
|
|
1825
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_BUSY;
|
|
1826
|
+
}
|
|
1827
|
+
|
|
1828
|
+
// With WAL, read and write transactions use separate locks. In
|
|
1829
|
+
// each case if the required lock is already held then we can
|
|
1830
|
+
// proceed synchronously. Otherwise we need to acquire state
|
|
1831
|
+
// asynchronously and retry.
|
|
1832
|
+
if (file.writeHint) {
|
|
1833
|
+
// Write transaction.
|
|
1834
|
+
if (!file.writeLock.acquireIfHeld('exclusive')) {
|
|
1835
|
+
file.retryResult = {};
|
|
1836
|
+
this._module.retryOps.push(this.#retryLockWrite(file));
|
|
1837
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_BUSY;
|
|
1838
|
+
} else {
|
|
1839
|
+
file.writeAhead.isolateForWrite();
|
|
1840
|
+
}
|
|
1841
|
+
} else {
|
|
1842
|
+
// Read transaction.
|
|
1843
|
+
if (!file.readLock.acquireIfHeld('shared')) {
|
|
1844
|
+
file.retryResult = {};
|
|
1845
|
+
this._module.retryOps.push(this.#retryLockRead(file));
|
|
1846
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_BUSY;
|
|
1847
|
+
} else {
|
|
1848
|
+
file.writeAhead.isolateForRead();
|
|
1849
|
+
}
|
|
1850
|
+
}
|
|
1851
|
+
} else if (file.retryResult instanceof Error) {
|
|
1852
|
+
const e = file.retryResult;
|
|
1853
|
+
file.retryResult = null;
|
|
1854
|
+
throw e;
|
|
1855
|
+
}
|
|
1856
|
+
|
|
1857
|
+
// We have acquired the needed locks, either synchronously or
|
|
1858
|
+
// via retry.
|
|
1859
|
+
file.retryResult = null;
|
|
1860
|
+
} else if (lockType >= _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_LOCK_RESERVED && !file.writeLock.mode) {
|
|
1861
|
+
// This is a write transaction but we don't already have the write
|
|
1862
|
+
// lock. This happens when the write hint was not used, which this
|
|
1863
|
+
// VFS treats as an error.
|
|
1864
|
+
throw new Error('Write transaction cannot use BEGIN DEFERRED');
|
|
1865
|
+
}
|
|
1866
|
+
file.lockState = lockType;
|
|
1867
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
|
|
1868
|
+
} catch (e) {
|
|
1869
|
+
if (e.name === 'TimeoutError') {
|
|
1870
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_BUSY;
|
|
1871
|
+
}
|
|
1872
|
+
|
|
1873
|
+
console.error(e.stack);
|
|
1874
|
+
this.lastError = e;
|
|
1875
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_IOERR_LOCK;
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1879
|
+
/**
|
|
1880
|
+
* @param {number} pFile
|
|
1881
|
+
* @param {number} lockType
|
|
1882
|
+
* @returns {number}
|
|
1883
|
+
*/
|
|
1884
|
+
jUnlock(pFile, lockType) {
|
|
1885
|
+
try {
|
|
1886
|
+
const file = this.mapIdToFile.get(pFile);
|
|
1887
|
+
|
|
1888
|
+
// If retryResult is non-null, an asynchronous lock operation is in
|
|
1889
|
+
// progress. In that case, don't change any locks.
|
|
1890
|
+
if (!file.retryResult && lockType === _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_LOCK_NONE) {
|
|
1891
|
+
// In this VFS, this is the only unlock transition that matters.
|
|
1892
|
+
// Exit write-ahead isolation.
|
|
1893
|
+
file.writeAhead.rejoin();
|
|
1894
|
+
|
|
1895
|
+
// Release any locks.
|
|
1896
|
+
switch (file.useLazyLock) {
|
|
1897
|
+
case 'none':
|
|
1898
|
+
file.writeLock.release();
|
|
1899
|
+
file.readLock.release();
|
|
1900
|
+
break;
|
|
1901
|
+
case 'read':
|
|
1902
|
+
file.writeLock.release();
|
|
1903
|
+
file.readLock.releaseLazy();
|
|
1904
|
+
break;
|
|
1905
|
+
case 'write':
|
|
1906
|
+
file.writeLock.releaseLazy();
|
|
1907
|
+
file.readLock.release();
|
|
1908
|
+
break;
|
|
1909
|
+
case 'readwrite':
|
|
1910
|
+
file.writeLock.releaseLazy();
|
|
1911
|
+
file.readLock.releaseLazy();
|
|
1912
|
+
break;
|
|
1913
|
+
}
|
|
1914
|
+
|
|
1915
|
+
// Reset state for the next transaction.
|
|
1916
|
+
file.writeHint = null;
|
|
1917
|
+
}
|
|
1918
|
+
file.lockState = lockType;
|
|
1919
|
+
} catch (e) {
|
|
1920
|
+
console.error(e.stack);
|
|
1921
|
+
this.lastError = e;
|
|
1922
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_IOERR_UNLOCK;
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1926
|
+
/**
|
|
1927
|
+
* @param {number} pFile
|
|
1928
|
+
* @param {DataView} pResOut
|
|
1929
|
+
* @returns {number}
|
|
1930
|
+
*/
|
|
1931
|
+
jCheckReservedLock(pFile, pResOut) {
|
|
1932
|
+
// A hot journal cannot exist so this method should never be called.
|
|
1933
|
+
console.assert(false, 'unexpected');
|
|
1934
|
+
pResOut.setInt32(0, 0, true);
|
|
1935
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
|
|
1936
|
+
}
|
|
1937
|
+
|
|
1938
|
+
/**
|
|
1939
|
+
* @param {number} pFile
|
|
1940
|
+
* @param {number} op
|
|
1941
|
+
* @param {DataView} pArg
|
|
1942
|
+
* @returns {number}
|
|
1943
|
+
*/
|
|
1944
|
+
jFileControl(pFile, op, pArg) {
|
|
1945
|
+
try {
|
|
1946
|
+
const file = this.mapIdToFile.get(pFile);
|
|
1947
|
+
switch (op) {
|
|
1948
|
+
case _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_FCNTL_PRAGMA:
|
|
1949
|
+
const key = this._module.UTF8ToString(pArg.getUint32(4, true));
|
|
1950
|
+
const valueAddress = pArg.getUint32(8, true);
|
|
1951
|
+
const value = valueAddress ? this._module.UTF8ToString(valueAddress) : null;
|
|
1952
|
+
this.log?.(`PRAGMA ${key} ${value}`);
|
|
1953
|
+
switch (key.toLowerCase()) {
|
|
1954
|
+
case 'experimental_pragma_20251114':
|
|
1955
|
+
// After entering the SHARED locking state on the next
|
|
1956
|
+
// transaction, SQLite intends to immediately transition to
|
|
1957
|
+
// RESERVED if value is '1', or EXCLUSIVE if value is '2'.
|
|
1958
|
+
switch (value) {
|
|
1959
|
+
case '1':
|
|
1960
|
+
file.writeHint = 'reserved';
|
|
1961
|
+
break;
|
|
1962
|
+
case '2':
|
|
1963
|
+
file.writeHint = 'exclusive';
|
|
1964
|
+
break;
|
|
1965
|
+
default:
|
|
1966
|
+
throw new Error(`unexpected write hint value: ${value}`);
|
|
1967
|
+
}
|
|
1968
|
+
break;
|
|
1969
|
+
case 'backstop_interval':
|
|
1970
|
+
if (value !== null) {
|
|
1971
|
+
const millis = parseInt(value);
|
|
1972
|
+
file.writeAhead.setBackstopInterval(millis);
|
|
1973
|
+
} else {
|
|
1974
|
+
// Return current interval.
|
|
1975
|
+
const s = file.writeAhead.options.backstopInterval.toString();
|
|
1976
|
+
const ptr = this._module._sqlite3_malloc64(s.length + 1);
|
|
1977
|
+
this._module.stringToUTF8(s, ptr, s.length + 1);
|
|
1978
|
+
pArg.setUint32(0, ptr, true);
|
|
1979
|
+
}
|
|
1980
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
|
|
1981
|
+
case 'busy_timeout':
|
|
1982
|
+
// Override SQLite's handling of busy timeouts with our
|
|
1983
|
+
// blocking lock timeouts.
|
|
1984
|
+
if (value !== null) {
|
|
1985
|
+
file.timeout = parseInt(value);
|
|
1986
|
+
} else {
|
|
1987
|
+
// Return current timeout.
|
|
1988
|
+
const s = file.timeout.toString();
|
|
1989
|
+
const ptr = this._module._sqlite3_malloc64(s.length + 1);
|
|
1990
|
+
this._module.stringToUTF8(s, ptr, s.length + 1);
|
|
1991
|
+
pArg.setUint32(0, ptr, true);
|
|
1992
|
+
}
|
|
1993
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
|
|
1994
|
+
case 'journal_size_limit':
|
|
1995
|
+
if (value !== null) {
|
|
1996
|
+
const nPages = parseInt(value);
|
|
1997
|
+
file.writeAhead.options.journalSizeLimit = nPages;
|
|
1998
|
+
}
|
|
1999
|
+
break;
|
|
2000
|
+
case 'locking_mode':
|
|
2001
|
+
// Track SQLite locking mode. Exclusive mode requires a
|
|
2002
|
+
// write lock.
|
|
2003
|
+
switch (value?.toLowerCase()) {
|
|
2004
|
+
case 'normal':
|
|
2005
|
+
file.lockingMode = 'normal';
|
|
2006
|
+
break;
|
|
2007
|
+
case 'exclusive':
|
|
2008
|
+
file.lockingMode = 'exclusive';
|
|
2009
|
+
break;
|
|
2010
|
+
}
|
|
2011
|
+
break;
|
|
2012
|
+
case 'page_size':
|
|
2013
|
+
if (value !== null) {
|
|
2014
|
+
// Valid page sizes are 1 (which maps to 65536) or powers of
|
|
2015
|
+
// two from 512 to 32768.
|
|
2016
|
+
const n = parseInt(value);
|
|
2017
|
+
if (n === 1 || (n >= 512 && n <= 32768 && (n & (n - 1)) === 0)) {
|
|
2018
|
+
file.pageSize = n === 1 ? 65536 : n;
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
break;
|
|
2022
|
+
case 'synchronous':
|
|
2023
|
+
// Track SQLite synchronous mode. Write-ahead transactions
|
|
2024
|
+
// trade durability for performance on values 1 (NORMAL) or
|
|
2025
|
+
// lower.
|
|
2026
|
+
if (value !== null) {
|
|
2027
|
+
switch (value.toLowerCase()) {
|
|
2028
|
+
case 'off':
|
|
2029
|
+
case '0':
|
|
2030
|
+
file.synchronous = 0;
|
|
2031
|
+
break;
|
|
2032
|
+
case 'normal':
|
|
2033
|
+
case '1':
|
|
2034
|
+
file.synchronous = 1;
|
|
2035
|
+
break;
|
|
2036
|
+
case 'full':
|
|
2037
|
+
case '2':
|
|
2038
|
+
file.synchronous = 2;
|
|
2039
|
+
break;
|
|
2040
|
+
case 'extra':
|
|
2041
|
+
case '3':
|
|
2042
|
+
file.synchronous = 3;
|
|
2043
|
+
break;
|
|
2044
|
+
default:
|
|
2045
|
+
throw new Error(`unexpected synchronous value: ${value}`);
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
break;
|
|
2049
|
+
case 'vfs_trace':
|
|
2050
|
+
// This is a trace feature for debugging only.
|
|
2051
|
+
if (value !== null) {
|
|
2052
|
+
this.log = parseInt(value) !== 0 ? console.debug : null;
|
|
2053
|
+
file.writeAhead.log = this.log;
|
|
2054
|
+
}
|
|
2055
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
|
|
2056
|
+
case 'wal_autocheckpoint':
|
|
2057
|
+
// A setting greater than zero enables automatic checkpoints
|
|
2058
|
+
// with this connection (enabled by default).
|
|
2059
|
+
if (value !== null) {
|
|
2060
|
+
file.writeAhead.options.autoCheckpoint = parseInt(value);
|
|
2061
|
+
}
|
|
2062
|
+
break;
|
|
2063
|
+
case 'wal_checkpoint':
|
|
2064
|
+
const checkpointMode = (value ?? 'passive').toLowerCase();
|
|
2065
|
+
switch (checkpointMode) {
|
|
2066
|
+
case 'passive':
|
|
2067
|
+
this._module.pendingOps.push(this.#pendingCheckpoint(file, checkpointMode));
|
|
2068
|
+
break;
|
|
2069
|
+
case 'full':
|
|
2070
|
+
case 'restart':
|
|
2071
|
+
case 'truncate':
|
|
2072
|
+
if (file.writeAhead.isTransactionPending()) {
|
|
2073
|
+
throw new Error('invalid while a transaction is in progress');
|
|
2074
|
+
}
|
|
2075
|
+
this._module.pendingOps.push(this.#pendingCheckpoint(file, checkpointMode));
|
|
2076
|
+
break;
|
|
2077
|
+
case 'noop':
|
|
2078
|
+
break;
|
|
2079
|
+
default:
|
|
2080
|
+
throw new Error(`unexpected wal_checkpoint mode: ${value}`);
|
|
2081
|
+
}
|
|
2082
|
+
|
|
2083
|
+
// Return the approximate number of pages in the WAL before
|
|
2084
|
+
// checkpointing. SQLite returns different information, but
|
|
2085
|
+
// that is not feasible from a VFS.
|
|
2086
|
+
{
|
|
2087
|
+
const s = file.writeAhead.getWriteAheadSize().toString();
|
|
2088
|
+
const ptr = this._module._sqlite3_malloc64(s.length + 1);
|
|
2089
|
+
this._module.stringToUTF8(s, ptr, s.length + 1);
|
|
2090
|
+
pArg.setUint32(0, ptr, true);
|
|
2091
|
+
}
|
|
2092
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
|
|
2093
|
+
case 'lazy_lock':
|
|
2094
|
+
// Lazy locks don't actually release their Web Lock until
|
|
2095
|
+
// they receive a message requesting it. Typically a setting
|
|
2096
|
+
// of 'readwrite' (default) or 'read' is best.
|
|
2097
|
+
if (value !== null) {
|
|
2098
|
+
const useLazyLock = value.toLowerCase();
|
|
2099
|
+
switch (useLazyLock) {
|
|
2100
|
+
case 'read':
|
|
2101
|
+
case 'write':
|
|
2102
|
+
case 'readwrite':
|
|
2103
|
+
case 'none':
|
|
2104
|
+
file.useLazyLock = useLazyLock;
|
|
2105
|
+
break;
|
|
2106
|
+
default:
|
|
2107
|
+
throw new Error(`unexpected value for lazy_lock: ${value}`);
|
|
2108
|
+
}
|
|
2109
|
+
}
|
|
2110
|
+
{
|
|
2111
|
+
const s = file.useLazyLock;
|
|
2112
|
+
const ptr = this._module._sqlite3_malloc64(s.length + 1);
|
|
2113
|
+
this._module.stringToUTF8(s, ptr, s.length + 1);
|
|
2114
|
+
pArg.setUint32(0, ptr, true);
|
|
2115
|
+
}
|
|
2116
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
|
|
2117
|
+
}
|
|
2118
|
+
break;
|
|
2119
|
+
|
|
2120
|
+
// Support SQLite batch atomic write transactions.
|
|
2121
|
+
case _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_FCNTL_BEGIN_ATOMIC_WRITE:
|
|
2122
|
+
case _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_FCNTL_COMMIT_ATOMIC_WRITE:
|
|
2123
|
+
if (file.flags & _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OPEN_MAIN_DB) {
|
|
2124
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
|
|
2125
|
+
}
|
|
2126
|
+
break;
|
|
2127
|
+
case _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE:
|
|
2128
|
+
if (file.flags & _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OPEN_MAIN_DB) {
|
|
2129
|
+
file.writeAhead.rollback();
|
|
2130
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK;
|
|
2131
|
+
}
|
|
2132
|
+
break;
|
|
2133
|
+
|
|
2134
|
+
case _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_FCNTL_SYNC:
|
|
2135
|
+
if (file.flags & _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OPEN_MAIN_DB) {
|
|
2136
|
+
file.writeAhead.commit();
|
|
2137
|
+
}
|
|
2138
|
+
break;
|
|
2139
|
+
|
|
2140
|
+
case _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_FCNTL_OVERWRITE:
|
|
2141
|
+
file.overwrite = true;
|
|
2142
|
+
break;
|
|
2143
|
+
}
|
|
2144
|
+
} catch (e) {
|
|
2145
|
+
console.error(e.stack);
|
|
2146
|
+
this.lastError = e;
|
|
2147
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_IOERR;
|
|
2148
|
+
}
|
|
2149
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_NOTFOUND;
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2152
|
+
/**
|
|
2153
|
+
* @param {number} pFile
|
|
2154
|
+
* @returns {number}
|
|
2155
|
+
*/
|
|
2156
|
+
jDeviceCharacteristics(pFile) {
|
|
2157
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
|
|
2158
|
+
| _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_IOCAP_BATCH_ATOMIC;
|
|
2159
|
+
}
|
|
2160
|
+
|
|
2161
|
+
/**
|
|
2162
|
+
* @param {Uint8Array} zBuf
|
|
2163
|
+
* @returns {number}
|
|
2164
|
+
*/
|
|
2165
|
+
jGetLastError(zBuf) {
|
|
2166
|
+
if (this.lastError) {
|
|
2167
|
+
console.error(this.lastError);
|
|
2168
|
+
const outputArray = zBuf.subarray(0, zBuf.byteLength - 1);
|
|
2169
|
+
const { written } = new TextEncoder().encodeInto(this.lastError.message, outputArray);
|
|
2170
|
+
zBuf[written] = 0;
|
|
2171
|
+
}
|
|
2172
|
+
return _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OK
|
|
2173
|
+
}
|
|
2174
|
+
|
|
2175
|
+
/**
|
|
2176
|
+
* @param {string} zName
|
|
2177
|
+
* @returns {FileSystemSyncAccessHandle}
|
|
2178
|
+
*/
|
|
2179
|
+
#openTemporaryFile(zName) {
|
|
2180
|
+
if (this.unboundTempFiles.size === 0) {
|
|
2181
|
+
throw new Error('no temporary files available');
|
|
2182
|
+
}
|
|
2183
|
+
|
|
2184
|
+
// Bind an access handle from the temporary pool.
|
|
2185
|
+
const accessHandle = this.unboundTempFiles.values().next().value;
|
|
2186
|
+
this.unboundTempFiles.delete(accessHandle);
|
|
2187
|
+
this.boundTempFiles.set(zName, accessHandle);
|
|
2188
|
+
return accessHandle;
|
|
2189
|
+
}
|
|
2190
|
+
|
|
2191
|
+
/**
|
|
2192
|
+
* @param {FileEntry} file
|
|
2193
|
+
*/
|
|
2194
|
+
#deleteTemporaryFile(file) {
|
|
2195
|
+
file.accessHandle.truncate(0);
|
|
2196
|
+
|
|
2197
|
+
// Temporary files are not actually deleted, just returned to the pool.
|
|
2198
|
+
this.mapPathToFile.delete(file.zName);
|
|
2199
|
+
this.unboundTempFiles.add(file.accessHandle);
|
|
2200
|
+
this.boundTempFiles.delete(file.zName);
|
|
2201
|
+
}
|
|
2202
|
+
|
|
2203
|
+
/**
|
|
2204
|
+
* @param {string} dbName
|
|
2205
|
+
* @param {number} i
|
|
2206
|
+
* @returns {string}
|
|
2207
|
+
*/
|
|
2208
|
+
#getWriteAheadNameFromDbName(dbName, i) {
|
|
2209
|
+
// Our WAL file is not compatible with SQLite WAL, so use a distinct name.
|
|
2210
|
+
return `${dbName}-wa${i}`;
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
/**
|
|
2214
|
+
* Asynchronous PRAGMA operation to checkpoint the write-ahead log.
|
|
2215
|
+
* @param {FileEntry} file
|
|
2216
|
+
* @param {'passive'|'full'|'restart'|'truncate'} mode
|
|
2217
|
+
*/
|
|
2218
|
+
async #pendingCheckpoint(file, mode) {
|
|
2219
|
+
const onFinally = [];
|
|
2220
|
+
try {
|
|
2221
|
+
if (mode !== 'passive' && file.lockState === _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_LOCK_NONE) {
|
|
2222
|
+
await file.writeLock.acquire('exclusive');
|
|
2223
|
+
onFinally.push(() => file.writeLock.release());
|
|
2224
|
+
|
|
2225
|
+
file.writeAhead.isolateForWrite();
|
|
2226
|
+
onFinally.push(() => file.writeAhead.rejoin());
|
|
2227
|
+
}
|
|
2228
|
+
|
|
2229
|
+
await file.writeAhead.checkpoint({ isPassive: mode === 'passive' });
|
|
2230
|
+
} catch (e) {
|
|
2231
|
+
if (e.name === 'AbortError') {
|
|
2232
|
+
e.code = _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_BUSY;
|
|
2233
|
+
}
|
|
2234
|
+
throw e;
|
|
2235
|
+
} finally {
|
|
2236
|
+
while (onFinally.length) {
|
|
2237
|
+
onFinally.pop()();
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
|
|
2242
|
+
/**
|
|
2243
|
+
* @param {FileEntry} file
|
|
2244
|
+
*/
|
|
2245
|
+
async #retryLockRead(file) {
|
|
2246
|
+
const onError = [];
|
|
2247
|
+
try {
|
|
2248
|
+
await file.readLock.acquire('shared', file.timeout);
|
|
2249
|
+
onError.push(() => file.readLock.release());
|
|
2250
|
+
|
|
2251
|
+
file.writeAhead.isolateForRead();
|
|
2252
|
+
file.retryResult = {};
|
|
2253
|
+
} catch (e) {
|
|
2254
|
+
while (onError.length) {
|
|
2255
|
+
onError.pop()();
|
|
2256
|
+
}
|
|
2257
|
+
file.retryResult = e;
|
|
2258
|
+
}
|
|
2259
|
+
}
|
|
2260
|
+
|
|
2261
|
+
/**
|
|
2262
|
+
* @param {FileEntry} file
|
|
2263
|
+
*/
|
|
2264
|
+
async #retryLockWrite(file) {
|
|
2265
|
+
const onError = [];
|
|
2266
|
+
try {
|
|
2267
|
+
// Exclusive locking mode requires both read and write locks.
|
|
2268
|
+
// Otherwise, only the write lock is needed.
|
|
2269
|
+
if (file.lockingMode === 'exclusive') {
|
|
2270
|
+
await file.readLock.acquire('exclusive', file.timeout);
|
|
2271
|
+
onError.push(() => file.readLock.release());
|
|
2272
|
+
}
|
|
2273
|
+
|
|
2274
|
+
await file.writeLock.acquire('exclusive', file.timeout);
|
|
2275
|
+
onError.push(() => file.writeLock.release());
|
|
2276
|
+
|
|
2277
|
+
file.writeAhead.isolateForWrite();
|
|
2278
|
+
file.retryResult = {};
|
|
2279
|
+
} catch (e) {
|
|
2280
|
+
while (onError.length) {
|
|
2281
|
+
onError.pop()();
|
|
2282
|
+
}
|
|
2283
|
+
file.retryResult = e;
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
|
|
2287
|
+
/**
|
|
2288
|
+
* Handle asynchronous jOpen() tasks.
|
|
2289
|
+
* @param {string} zName
|
|
2290
|
+
* @param {number} flags
|
|
2291
|
+
* @param {number} fileId
|
|
2292
|
+
* @param {DataView} pOutFlags
|
|
2293
|
+
* @returns {Promise<void>}
|
|
2294
|
+
*/
|
|
2295
|
+
async #retryOpen(zName, flags, fileId, pOutFlags) {
|
|
2296
|
+
/** @type {(() => void)[]} */ const onError = [];
|
|
2297
|
+
const file = this.mapPathToFile.get(zName);
|
|
2298
|
+
try {
|
|
2299
|
+
await navigator.locks.request(`${zName}#ckpt`, async lock => {
|
|
2300
|
+
// Parse the path components.
|
|
2301
|
+
const directoryNames = zName.split('/').filter(d => d);
|
|
2302
|
+
const dbName = directoryNames.pop();
|
|
2303
|
+
|
|
2304
|
+
// Get the OPFS directory handle.
|
|
2305
|
+
let dirHandle = await navigator.storage.getDirectory();
|
|
2306
|
+
const create = !!(flags & _VFS_js__WEBPACK_IMPORTED_MODULE_1__.SQLITE_OPEN_CREATE);
|
|
2307
|
+
for (const directoryName of directoryNames) {
|
|
2308
|
+
dirHandle = await dirHandle.getDirectoryHandle(directoryName, { create });
|
|
2309
|
+
}
|
|
2310
|
+
|
|
2311
|
+
const isNewDatabase = create && await (async function() {
|
|
2312
|
+
try {
|
|
2313
|
+
await dirHandle.getFileHandle(dbName);
|
|
2314
|
+
return false;
|
|
2315
|
+
} catch (e) {
|
|
2316
|
+
if (e.name === 'NotFoundError') {
|
|
2317
|
+
return true;
|
|
2318
|
+
}
|
|
2319
|
+
throw e;
|
|
2320
|
+
}
|
|
2321
|
+
})();
|
|
2322
|
+
|
|
2323
|
+
// Convenience function for opening access handles.
|
|
2324
|
+
async function openFile(
|
|
2325
|
+
/** @type {string} */ filename,
|
|
2326
|
+
/** @type {FileSystemGetFileOptions} */ options) {
|
|
2327
|
+
const fileHandle = await dirHandle.getFileHandle(filename, options);
|
|
2328
|
+
// @ts-ignore
|
|
2329
|
+
const accessHandle = await fileHandle.createSyncAccessHandle({
|
|
2330
|
+
mode: 'readwrite-unsafe'
|
|
2331
|
+
});
|
|
2332
|
+
onError.push(() => {
|
|
2333
|
+
accessHandle.close();
|
|
2334
|
+
if (isNewDatabase) {
|
|
2335
|
+
dirHandle.removeEntry(filename);
|
|
2336
|
+
}
|
|
2337
|
+
});
|
|
2338
|
+
return accessHandle;
|
|
2339
|
+
}
|
|
2340
|
+
|
|
2341
|
+
// Open the main database OPFS file.
|
|
2342
|
+
const accessHandle = await openFile(dbName, { create });
|
|
2343
|
+
|
|
2344
|
+
// Open WAL files.
|
|
2345
|
+
const waHandles = await Promise.all([0, 1].map(async i => {
|
|
2346
|
+
const waName = this.#getWriteAheadNameFromDbName(dbName, i);
|
|
2347
|
+
const waHandle = await openFile(waName, { create: true });
|
|
2348
|
+
if (isNewDatabase) {
|
|
2349
|
+
waHandle.truncate(0);
|
|
2350
|
+
}
|
|
2351
|
+
return waHandle;
|
|
2352
|
+
}));
|
|
2353
|
+
|
|
2354
|
+
// Create the write-ahead manager.
|
|
2355
|
+
const writeAhead = new _WriteAhead_js__WEBPACK_IMPORTED_MODULE_3__.WriteAhead(zName, accessHandle, waHandles);
|
|
2356
|
+
await writeAhead.ready();
|
|
2357
|
+
|
|
2358
|
+
file.retryResult = { accessHandle, waHandles, writeAhead };
|
|
2359
|
+
});
|
|
2360
|
+
} catch (e) {
|
|
2361
|
+
while (onError.length) {
|
|
2362
|
+
onError.pop()();
|
|
2363
|
+
}
|
|
2364
|
+
file.retryResult = e;
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
|
|
2369
|
+
|
|
2370
|
+
/***/ },
|
|
2371
|
+
|
|
2372
|
+
/***/ "../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/examples/WriteAhead.js"
|
|
2373
|
+
/*!****************************************************************************************************************************!*\
|
|
2374
|
+
!*** ../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/examples/WriteAhead.js ***!
|
|
2375
|
+
\****************************************************************************************************************************/
|
|
2376
|
+
(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
2377
|
+
|
|
2378
|
+
__webpack_require__.r(__webpack_exports__);
|
|
2379
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
2380
|
+
/* harmony export */ WriteAhead: () => (/* binding */ WriteAhead)
|
|
2381
|
+
/* harmony export */ });
|
|
2382
|
+
/* harmony import */ var _Lock_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Lock.js */ "../../node_modules/.pnpm/@journeyapps+wa-sqlite@1.7.0/node_modules/@journeyapps/wa-sqlite/src/examples/Lock.js");
|
|
2383
|
+
|
|
2384
|
+
|
|
2385
|
+
const DEFAULT_JOURNAL_SIZE_LIMIT = 1000;
|
|
2386
|
+
const DEFAULT_BACKSTOP_INTERVAL = 30_000;
|
|
2387
|
+
|
|
2388
|
+
const MAGIC = 0x377f0684;
|
|
2389
|
+
const FILE_HEADER_SIZE = 32;
|
|
2390
|
+
const FRAME_HEADER_SIZE = 32;
|
|
2391
|
+
const FRAME_TYPE_PAGE = 0;
|
|
2392
|
+
const FRAME_TYPE_COMMIT = 1;
|
|
2393
|
+
const FRAME_TYPE_END = 2;
|
|
2394
|
+
|
|
2395
|
+
/**
|
|
2396
|
+
* @typedef PageEntry
|
|
2397
|
+
* @property {number} waOffset location in WAL file
|
|
2398
|
+
* @property {number} waSalt1 WAL2 file identifier
|
|
2399
|
+
* @property {number} pageSize
|
|
2400
|
+
* @property {Uint8Array} [pageData]
|
|
2401
|
+
*/
|
|
2402
|
+
|
|
2403
|
+
/**
|
|
2404
|
+
* @typedef Transaction
|
|
2405
|
+
* @property {number} id
|
|
2406
|
+
* @property {Map<number, PageEntry>} pages address to page data mapping
|
|
2407
|
+
* @property {number} dbFileSize
|
|
2408
|
+
* @property {number} [newPageSize]
|
|
2409
|
+
* @property {number} waSalt1 WAL2 file identifier
|
|
2410
|
+
* @property {number} waOffsetEnd
|
|
2411
|
+
*/
|
|
2412
|
+
|
|
2413
|
+
/**
|
|
2414
|
+
* @typedef WriteAheadOptions
|
|
2415
|
+
* @property {number} [autoCheckpoint]
|
|
2416
|
+
* @property {number} [backstopInterval]
|
|
2417
|
+
* @property {number} [journalSizeLimit]
|
|
2418
|
+
*/
|
|
2419
|
+
|
|
2420
|
+
class WriteAhead {
|
|
2421
|
+
|
|
2422
|
+
log = null;
|
|
2423
|
+
/** @type {WriteAheadOptions} */ options = {
|
|
2424
|
+
autoCheckpoint: 1,
|
|
2425
|
+
backstopInterval: DEFAULT_BACKSTOP_INTERVAL,
|
|
2426
|
+
journalSizeLimit: DEFAULT_JOURNAL_SIZE_LIMIT,
|
|
2427
|
+
};
|
|
2428
|
+
|
|
2429
|
+
#zName;
|
|
2430
|
+
#dbHandle;
|
|
2431
|
+
|
|
2432
|
+
/** @type {FileSystemSyncAccessHandle[]} */ #waHandles;
|
|
2433
|
+
/** @type {FileSystemSyncAccessHandle} */ #activeHandle;
|
|
2434
|
+
/** @type {{nextTxId: number, salt1: number, salt2: number}} */ #activeHeader;
|
|
2435
|
+
/** @type {number} */ #activeOffset;
|
|
2436
|
+
/** @type {number} */ #txId = 0;
|
|
2437
|
+
/** @type {Transaction} */ #txInProgress = null;
|
|
2438
|
+
|
|
2439
|
+
#dbFileSize = 0;
|
|
2440
|
+
|
|
2441
|
+
/** @type {Promise<any>} */ #ready;
|
|
2442
|
+
/** @type {'read'|'write'} */ #isolationState = null;
|
|
2443
|
+
|
|
2444
|
+
/** @type {Lock} */ #txIdLock = null;
|
|
2445
|
+
|
|
2446
|
+
/** @type {Map<number, PageEntry>} */ #waOverlay = new Map();
|
|
2447
|
+
/** @type {Map<number, Transaction>} */ #mapIdToTx = new Map();
|
|
2448
|
+
/** @type {Map<number, Transaction>} */ #mapIdToPendingTx = new Map();
|
|
2449
|
+
#approxPageCount = 0;
|
|
2450
|
+
|
|
2451
|
+
/** @type {BroadcastChannel} */ #broadcastChannel;
|
|
2452
|
+
|
|
2453
|
+
/** @type {number} */ #backstopTimer;
|
|
2454
|
+
/** @type {number} */ #backstopTimestamp = 0;
|
|
2455
|
+
|
|
2456
|
+
#abortController = new AbortController();
|
|
2457
|
+
|
|
2458
|
+
/**
|
|
2459
|
+
* @param {string} zName
|
|
2460
|
+
* @param {FileSystemSyncAccessHandle} dbHandle
|
|
2461
|
+
* @param {FileSystemSyncAccessHandle[]} waHandles
|
|
2462
|
+
* @param {WriteAheadOptions} options
|
|
2463
|
+
*/
|
|
2464
|
+
constructor(zName, dbHandle, waHandles, options = {}) {
|
|
2465
|
+
this.#zName = zName;
|
|
2466
|
+
this.#dbHandle = dbHandle;
|
|
2467
|
+
this.#waHandles = waHandles;
|
|
2468
|
+
this.options = Object.assign(this.options, options);
|
|
2469
|
+
|
|
2470
|
+
// All the asynchronous initialization is done here.
|
|
2471
|
+
this.#ready = (async () => {
|
|
2472
|
+
// Set our advertised txId to zero until we know the proper value.
|
|
2473
|
+
await this.#updateTxIdLock();
|
|
2474
|
+
|
|
2475
|
+
// Listen for transactions and checkpoints from other connections.
|
|
2476
|
+
this.#broadcastChannel = new BroadcastChannel(`${zName}#wa`);
|
|
2477
|
+
this.#broadcastChannel.onmessage = (event) => {
|
|
2478
|
+
this.#handleMessage(event);
|
|
2479
|
+
};
|
|
2480
|
+
|
|
2481
|
+
// Read headers from both WAL files and use the one with the
|
|
2482
|
+
// lower nextTxId. If neither header is valid, create a new header.
|
|
2483
|
+
const fileHeader = this.#waHandles
|
|
2484
|
+
.map(handle => this.#readFileHeader(handle))
|
|
2485
|
+
.filter(h => h)
|
|
2486
|
+
.sort((a, b) => a.nextTxId - b.nextTxId)[0]
|
|
2487
|
+
?? this.#writeFileHeader(Math.floor(Math.random() * 0xffffffff));
|
|
2488
|
+
|
|
2489
|
+
this.#activeHeader = fileHeader;
|
|
2490
|
+
this.#activeHandle = this.#waHandles[fileHeader.salt1 & 1];
|
|
2491
|
+
this.#activeOffset = FILE_HEADER_SIZE;
|
|
2492
|
+
this.#txId = fileHeader.nextTxId - 1;
|
|
2493
|
+
|
|
2494
|
+
// Load all the transactions from the WAL.
|
|
2495
|
+
for (const tx of this.#readAllTx()) {
|
|
2496
|
+
this.#activateTx(tx);
|
|
2497
|
+
}
|
|
2498
|
+
this.#updateTxIdLock(); // doesn't need await
|
|
2499
|
+
|
|
2500
|
+
// Schedule backstop. The backstop is a guard against a crash in
|
|
2501
|
+
// another context between persisting a transaction and broadcasting
|
|
2502
|
+
// it.
|
|
2503
|
+
this.#backstopTimestamp = performance.now();
|
|
2504
|
+
this.#backstop();
|
|
2505
|
+
})();
|
|
2506
|
+
}
|
|
2507
|
+
|
|
2508
|
+
/**
|
|
2509
|
+
* @returns {Promise<void>}
|
|
2510
|
+
*/
|
|
2511
|
+
ready() {
|
|
2512
|
+
return this.#ready;
|
|
2513
|
+
}
|
|
2514
|
+
|
|
2515
|
+
close() {
|
|
2516
|
+
this.#abortController.abort();
|
|
2517
|
+
|
|
2518
|
+
// Stop asynchronous maintenance.
|
|
2519
|
+
this.#broadcastChannel.onmessage = null;
|
|
2520
|
+
clearTimeout(this.#backstopTimer);
|
|
2521
|
+
|
|
2522
|
+
this.#txIdLock?.release();
|
|
2523
|
+
this.#broadcastChannel.close();
|
|
2524
|
+
}
|
|
2525
|
+
|
|
2526
|
+
/**
|
|
2527
|
+
* Freeze our view of the database.
|
|
2528
|
+
* The view includes the transactions received so far but is not
|
|
2529
|
+
* guaranteed to be completely up to date. Unfreeze the view with rejoin().
|
|
2530
|
+
*/
|
|
2531
|
+
isolateForRead() {
|
|
2532
|
+
if (this.#isolationState !== null) {
|
|
2533
|
+
throw new Error('Already in isolated state');
|
|
2534
|
+
}
|
|
2535
|
+
this.#isolationState = 'read';
|
|
2536
|
+
|
|
2537
|
+
// Disable backstop during isolation.
|
|
2538
|
+
clearTimeout(this.#backstopTimer);
|
|
2539
|
+
this.#backstopTimer = null;
|
|
2540
|
+
}
|
|
2541
|
+
|
|
2542
|
+
/**
|
|
2543
|
+
* Freeze our view of the database for writing.
|
|
2544
|
+
* The view includes all transactions. Unfreeze the view with rejoin().
|
|
2545
|
+
*/
|
|
2546
|
+
isolateForWrite() {
|
|
2547
|
+
if (this.#isolationState !== null) {
|
|
2548
|
+
throw new Error('Already in isolated state');
|
|
2549
|
+
}
|
|
2550
|
+
this.#isolationState = 'write';
|
|
2551
|
+
|
|
2552
|
+
// Disable backstop during isolation.
|
|
2553
|
+
clearTimeout(this.#backstopTimer);
|
|
2554
|
+
this.#backstopTimer = null;
|
|
2555
|
+
|
|
2556
|
+
// A writer needs all previous transactions assimilated.
|
|
2557
|
+
this.#advanceTxId({ readToCurrent: true });
|
|
2558
|
+
}
|
|
2559
|
+
|
|
2560
|
+
rejoin() {
|
|
2561
|
+
if (this.#isolationState === 'read') {
|
|
2562
|
+
// Catch up on new transactions that arrived while isolated.
|
|
2563
|
+
this.#advanceTxId({ autoCheckpoint: true });
|
|
2564
|
+
}
|
|
2565
|
+
this.#isolationState = null;
|
|
2566
|
+
|
|
2567
|
+
// Resume backstop after isolation.
|
|
2568
|
+
this.#backstop();
|
|
2569
|
+
}
|
|
2570
|
+
|
|
2571
|
+
/**
|
|
2572
|
+
* @param {number} offset
|
|
2573
|
+
* @return {Uint8Array?}
|
|
2574
|
+
*/
|
|
2575
|
+
read(offset) {
|
|
2576
|
+
// First look for the page in any write transaction in progress.
|
|
2577
|
+
// If the page is not found in the transaction overlay, look in the
|
|
2578
|
+
// write-ahead overlay.
|
|
2579
|
+
const pageEntry = this.#txInProgress?.pages.get(offset) ?? this.#waOverlay.get(offset);
|
|
2580
|
+
if (pageEntry) {
|
|
2581
|
+
if (pageEntry.pageData) {
|
|
2582
|
+
// Page data is cached.
|
|
2583
|
+
this.log?.(`%cread page at ${offset} from WAL ${pageEntry.waSalt1 & 1}:${pageEntry.waOffset} (cached)`, 'background-color: gold;');
|
|
2584
|
+
return pageEntry.pageData;
|
|
2585
|
+
}
|
|
2586
|
+
|
|
2587
|
+
// Read the page from the WAL file.
|
|
2588
|
+
this.log?.(`%cread page at ${offset} from WAL ${pageEntry.waSalt1 & 1}:${pageEntry.waOffset}`, 'background-color: gold;');
|
|
2589
|
+
return this.#fetchPage(pageEntry);
|
|
2590
|
+
}
|
|
2591
|
+
return null;
|
|
2592
|
+
}
|
|
2593
|
+
|
|
2594
|
+
/**
|
|
2595
|
+
* @param {number} offset
|
|
2596
|
+
* @param {Uint8Array} data
|
|
2597
|
+
* @param {{dstPageSize: number?}} options
|
|
2598
|
+
*/
|
|
2599
|
+
write(offset, data, options) {
|
|
2600
|
+
if (this.#isolationState !== 'write') {
|
|
2601
|
+
throw new Error('Not in write isolated state');
|
|
2602
|
+
}
|
|
2603
|
+
|
|
2604
|
+
if (!this.#txInProgress) {
|
|
2605
|
+
// There is no active transaction so we need to create one. But
|
|
2606
|
+
// first check whether to move to the other WAL file.
|
|
2607
|
+
const nPageThreshold = this.options.journalSizeLimit > 0 ?
|
|
2608
|
+
this.options.journalSizeLimit :
|
|
2609
|
+
DEFAULT_JOURNAL_SIZE_LIMIT;
|
|
2610
|
+
if (this.#approxPageCount >= nPageThreshold && this.#isInactiveFileEmpty()) {
|
|
2611
|
+
this.log?.(`%cchange WAL file at ${this.#approxPageCount} pages`, 'background-color: lightskyblue;');
|
|
2612
|
+
this.#swapActiveFile();
|
|
2613
|
+
}
|
|
2614
|
+
|
|
2615
|
+
this.#beginTx();
|
|
2616
|
+
if (options.dstPageSize !== data.byteLength) {
|
|
2617
|
+
// This is a VACUUM to a new page size. The incoming writes are at
|
|
2618
|
+
// the old page size, but we want to write to the WAL with the new
|
|
2619
|
+
// size.
|
|
2620
|
+
this.#txInProgress.newPageSize = options.dstPageSize;
|
|
2621
|
+
}
|
|
2622
|
+
}
|
|
2623
|
+
|
|
2624
|
+
if (this.#txInProgress.newPageSize) {
|
|
2625
|
+
// The incoming data is not a single page because the page size
|
|
2626
|
+
// is changing. The two cases are when the new page size is
|
|
2627
|
+
// smaller or larger than the old page size.
|
|
2628
|
+
const frameSize = FRAME_HEADER_SIZE + this.#txInProgress.newPageSize;
|
|
2629
|
+
if (data.byteLength > this.#txInProgress.newPageSize) {
|
|
2630
|
+
// New page size is smaller. Write multiple pages of the new
|
|
2631
|
+
// page size.
|
|
2632
|
+
for (let i = 0; i < data.byteLength; i += this.#txInProgress.newPageSize) {
|
|
2633
|
+
const pageData = data.slice(i, i + this.#txInProgress.newPageSize);
|
|
2634
|
+
const waOffset = this.#writePage(offset + i, pageData);
|
|
2635
|
+
this.log?.(`%cwrite page at ${offset + i} to WAL ${this.#activeHeader.salt1 & 1}:${waOffset}`, 'background-color: lightskyblue;');
|
|
2636
|
+
}
|
|
2637
|
+
} else {
|
|
2638
|
+
// New page size is larger. Save the page data to the WAL file
|
|
2639
|
+
// so it can be read back and rewritten as frames with the new
|
|
2640
|
+
// page size.
|
|
2641
|
+
const pageOffset = offset % this.#txInProgress.newPageSize;
|
|
2642
|
+
const waOffset = this.#activeOffset +
|
|
2643
|
+
(offset - pageOffset) / this.#txInProgress.newPageSize * frameSize +
|
|
2644
|
+
FRAME_HEADER_SIZE +
|
|
2645
|
+
pageOffset;
|
|
2646
|
+
this.#activeHandle.write(data.subarray(), { at: waOffset });
|
|
2647
|
+
this.log?.(`%cwrite page at ${offset} to WAL ${this.#activeHeader.salt1 & 1}:${waOffset}`, 'background-color: lightskyblue;');
|
|
2648
|
+
}
|
|
2649
|
+
} else {
|
|
2650
|
+
// This is the normal case without a page size change.
|
|
2651
|
+
const waOffset = this.#writePage(offset, data.slice());
|
|
2652
|
+
this.log?.(`%cwrite page at ${offset} to WAL ${this.#activeHeader.salt1 & 1}:${waOffset}`, 'background-color: lightskyblue;');
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2655
|
+
|
|
2656
|
+
/**
|
|
2657
|
+
* @param {number} newSize
|
|
2658
|
+
*/
|
|
2659
|
+
truncate(newSize) {
|
|
2660
|
+
// Ignore truncation that happens outside of a transaction. That
|
|
2661
|
+
// only happens (e.g. post-VACUUM) to ensure the file size matches
|
|
2662
|
+
// the database header.
|
|
2663
|
+
if (this.#txInProgress) {
|
|
2664
|
+
// Remove any pages past the truncation point.
|
|
2665
|
+
for (const offset of this.#txInProgress.pages.keys()) {
|
|
2666
|
+
if (offset >= newSize) {
|
|
2667
|
+
this.#txInProgress.pages.delete(offset);
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
}
|
|
2671
|
+
}
|
|
2672
|
+
|
|
2673
|
+
getFileSize() {
|
|
2674
|
+
return this.#txInProgress?.dbFileSize ?? this.#dbFileSize;
|
|
2675
|
+
}
|
|
2676
|
+
|
|
2677
|
+
commit() {
|
|
2678
|
+
const tx = this.#txInProgress;
|
|
2679
|
+
if (tx.newPageSize && tx.pages.size === 0) {
|
|
2680
|
+
// This transaction is a VACUUM with a page size increase. All
|
|
2681
|
+
// the database pages have been written to the WAL file at their
|
|
2682
|
+
// new size with blank frame headers. Read the page data back
|
|
2683
|
+
// from the WAL file and rewrite as frames.
|
|
2684
|
+
let pageCount = 1; // to be replaced on the first iteration
|
|
2685
|
+
for (let i = 0; i < pageCount; i++) {
|
|
2686
|
+
// Read the page data.
|
|
2687
|
+
const pageData = new Uint8Array(tx.newPageSize);
|
|
2688
|
+
const waOffset = this.#activeOffset +
|
|
2689
|
+
i * (FRAME_HEADER_SIZE + tx.newPageSize) +
|
|
2690
|
+
FRAME_HEADER_SIZE;
|
|
2691
|
+
this.#activeHandle.read(pageData, { at: waOffset });
|
|
2692
|
+
|
|
2693
|
+
if (i === 0) {
|
|
2694
|
+
// Get the actual page count from the file header.
|
|
2695
|
+
const headerView = new DataView(pageData.buffer);
|
|
2696
|
+
pageCount = headerView.getUint32(28);
|
|
2697
|
+
}
|
|
2698
|
+
|
|
2699
|
+
// Write back as a frame.
|
|
2700
|
+
this.#writePage(i * tx.newPageSize, pageData);
|
|
2701
|
+
}
|
|
2702
|
+
}
|
|
2703
|
+
|
|
2704
|
+
const page1 = this.#txInProgress.pages.get(0)?.pageData;
|
|
2705
|
+
if (page1) {
|
|
2706
|
+
const page1View = new DataView(page1.buffer, page1.byteOffset, page1.byteLength);
|
|
2707
|
+
const pageCount = page1View.getUint32(28);
|
|
2708
|
+
this.#txInProgress.dbFileSize = pageCount * page1.byteLength;
|
|
2709
|
+
} else {
|
|
2710
|
+
// The transaction doesn't include page 1, so this must be a
|
|
2711
|
+
// non-batch-atomic rollback.
|
|
2712
|
+
this.rollback();
|
|
2713
|
+
return;
|
|
2714
|
+
}
|
|
2715
|
+
|
|
2716
|
+
// Persist the final pending transaction page with the database size.
|
|
2717
|
+
this.#commitTx();
|
|
2718
|
+
|
|
2719
|
+
// Incorporate the transaction locally.
|
|
2720
|
+
this.#activateTx(tx);
|
|
2721
|
+
this.#updateTxIdLock();
|
|
2722
|
+
|
|
2723
|
+
// Send the transaction to other connections.
|
|
2724
|
+
const payload = { type: 'tx', tx };
|
|
2725
|
+
this.#broadcastChannel.postMessage(payload);
|
|
2726
|
+
|
|
2727
|
+
this.#autoCheckpoint();
|
|
2728
|
+
this.#backstopTimestamp = performance.now();
|
|
2729
|
+
}
|
|
2730
|
+
|
|
2731
|
+
rollback() {
|
|
2732
|
+
// Discard transaction pages.
|
|
2733
|
+
this.#abortTx();
|
|
2734
|
+
}
|
|
2735
|
+
|
|
2736
|
+
/**
|
|
2737
|
+
* @param {{durability: 'strict'|'relaxed'}} options
|
|
2738
|
+
*/
|
|
2739
|
+
sync(options) {
|
|
2740
|
+
if (options.durability === 'strict') {
|
|
2741
|
+
this.#flushActiveFile();
|
|
2742
|
+
}
|
|
2743
|
+
}
|
|
2744
|
+
|
|
2745
|
+
/**
|
|
2746
|
+
* Move pages from write-ahead to main database file.
|
|
2747
|
+
*
|
|
2748
|
+
* @param {{isPassive: boolean}} options
|
|
2749
|
+
*/
|
|
2750
|
+
async checkpoint(options = { isPassive: true }) {
|
|
2751
|
+
// Passive checkpointing is abandoned if another connection is
|
|
2752
|
+
// already checkpointing.
|
|
2753
|
+
const lockOptions = {
|
|
2754
|
+
ifAvailable: options.isPassive,
|
|
2755
|
+
};
|
|
2756
|
+
|
|
2757
|
+
await navigator.locks.request(`${this.#zName}#ckpt`, lockOptions, async lock => {
|
|
2758
|
+
if (!lock) return;
|
|
2759
|
+
if (this.#abortController.signal.aborted) return;
|
|
2760
|
+
|
|
2761
|
+
let ckptId = this.#getActiveFileStartingTxId() - 1;
|
|
2762
|
+
if (options.isPassive) {
|
|
2763
|
+
if (!this.#mapIdToTx.has(ckptId)) {
|
|
2764
|
+
// There are no transactions to checkpoint.
|
|
2765
|
+
return;
|
|
2766
|
+
}
|
|
2767
|
+
|
|
2768
|
+
// Scan the txId locks to find the oldest txId.
|
|
2769
|
+
const busyTxId = (await this.#getTxIdLocks())
|
|
2770
|
+
.reduce((min, value) => Math.min(min, value.maxTxId), this.#txId);
|
|
2771
|
+
|
|
2772
|
+
if (busyTxId < ckptId) {
|
|
2773
|
+
// The inactive WAL file is still being used.
|
|
2774
|
+
return;
|
|
2775
|
+
}
|
|
2776
|
+
} else {
|
|
2777
|
+
// Wait for all connections to reach the current txId.
|
|
2778
|
+
await this.#waitForTxIdLocks(value => value.maxTxId >= this.#txId);
|
|
2779
|
+
ckptId = this.#txId;
|
|
2780
|
+
}
|
|
2781
|
+
this.log?.(`%ccheckpoint through txId ${ckptId}`, 'background-color: lightgreen;');
|
|
2782
|
+
|
|
2783
|
+
// Sync the WAL file. This ensures that if there is a crash after
|
|
2784
|
+
// part of the WAL has been copied, the uncopied part will still be
|
|
2785
|
+
// available afterwards.
|
|
2786
|
+
this.#flushInactiveFile();
|
|
2787
|
+
if (!options.isPassive) {
|
|
2788
|
+
this.#flushActiveFile();
|
|
2789
|
+
}
|
|
2790
|
+
|
|
2791
|
+
// Starting at ckptId and going backwards (higher to lower txId),
|
|
2792
|
+
// write transaction pages to the main database file. Do not overwrite
|
|
2793
|
+
// a page written by a more recent transaction.
|
|
2794
|
+
const writtenOffsets = new Set();
|
|
2795
|
+
let dbFileSize = this.#dbHandle.getSize();
|
|
2796
|
+
for (let tx = this.#mapIdToTx.get(ckptId); tx; tx = this.#mapIdToTx.get(tx.id - 1)) {
|
|
2797
|
+
if (tx.id === ckptId && dbFileSize !== tx.dbFileSize) {
|
|
2798
|
+
// Set the file size from the latest transaction.
|
|
2799
|
+
dbFileSize = tx.dbFileSize;
|
|
2800
|
+
this.#dbHandle.truncate(dbFileSize);
|
|
2801
|
+
}
|
|
2802
|
+
|
|
2803
|
+
for (const [offset, pageEntry] of tx.pages) {
|
|
2804
|
+
if (offset < dbFileSize && !writtenOffsets.has(offset)) {
|
|
2805
|
+
// Fetch the page data from the WAL file if not cached.
|
|
2806
|
+
const pageData = pageEntry.pageData ?? this.#fetchPage(pageEntry);
|
|
2807
|
+
|
|
2808
|
+
// Write the page to the database file.
|
|
2809
|
+
const nWritten = this.#dbHandle.write(pageData, { at: offset });
|
|
2810
|
+
if (nWritten !== pageData.byteLength) {
|
|
2811
|
+
throw new Error('Checkpoint write failed');
|
|
2812
|
+
}
|
|
2813
|
+
writtenOffsets.add(offset);
|
|
2814
|
+
this.log?.(`%ccheckpoint wrote txId ${tx.id} page at ${offset} to database`, 'background-color: lightgreen;');
|
|
2815
|
+
}
|
|
2816
|
+
}
|
|
2817
|
+
|
|
2818
|
+
if (tx.newPageSize) {
|
|
2819
|
+
// This transaction used a new page size to overwrite the entire
|
|
2820
|
+
// database file so no older pages need to be written. This is
|
|
2821
|
+
// not just an optimization; it prevents incorrectly writing
|
|
2822
|
+
// older smaller pages at addresses that aren't multiples of
|
|
2823
|
+
// the new page size.
|
|
2824
|
+
break;
|
|
2825
|
+
}
|
|
2826
|
+
}
|
|
2827
|
+
|
|
2828
|
+
// Ensure that database writes are durable.
|
|
2829
|
+
this.log?.(`%ccheckpoint flush database file`, 'background-color: lightgreen;');
|
|
2830
|
+
this.#dbHandle.flush();
|
|
2831
|
+
|
|
2832
|
+
// Notify other connections and ourselves of the checkpoint.
|
|
2833
|
+
this.#broadcastChannel.postMessage({
|
|
2834
|
+
type: 'ckpt',
|
|
2835
|
+
ckptId,
|
|
2836
|
+
});
|
|
2837
|
+
this.#handleCheckpoint(ckptId);
|
|
2838
|
+
|
|
2839
|
+
// Wait for all connections to update their overlay.
|
|
2840
|
+
this.log?.(`%ccheckpoint waiting for connection updates`, 'background-color: lightgreen;');
|
|
2841
|
+
await this.#waitForTxIdLocks(value => value.minTxId > ckptId);
|
|
2842
|
+
|
|
2843
|
+
// Truncate the inactive WAL file. This prevents new connections from
|
|
2844
|
+
// unnecessarily reading checkpointed data, and allows writers to make
|
|
2845
|
+
// it active when their conditions are met.
|
|
2846
|
+
this.#truncateInactiveFile();
|
|
2847
|
+
this.log?.(`%ccheckpoint complete`, 'background-color: lightgreen;');
|
|
2848
|
+
});
|
|
2849
|
+
}
|
|
2850
|
+
|
|
2851
|
+
/**
|
|
2852
|
+
* Return the approximate number of write-ahead pages. This is the
|
|
2853
|
+
* sum of the number of unique page indices for each transaction,
|
|
2854
|
+
* so it can be fewer than the number of pages if any transaction
|
|
2855
|
+
* contains multiple frames for the same page.
|
|
2856
|
+
* @returns {number}
|
|
2857
|
+
*/
|
|
2858
|
+
getWriteAheadSize() {
|
|
2859
|
+
return this.#approxPageCount;
|
|
2860
|
+
}
|
|
2861
|
+
|
|
2862
|
+
isTransactionPending() {
|
|
2863
|
+
return !!this.#txInProgress;
|
|
2864
|
+
}
|
|
2865
|
+
|
|
2866
|
+
setBackstopInterval(intervalMillis) {
|
|
2867
|
+
this.options.backstopInterval = intervalMillis;
|
|
2868
|
+
if (intervalMillis > 0 && this.#isolationState) {
|
|
2869
|
+
this.#backstop();
|
|
2870
|
+
}
|
|
2871
|
+
}
|
|
2872
|
+
|
|
2873
|
+
/**
|
|
2874
|
+
* Incorporate a transaction into our view of the database.
|
|
2875
|
+
* @param {Transaction} tx
|
|
2876
|
+
*/
|
|
2877
|
+
#activateTx(tx) {
|
|
2878
|
+
// Transfer to the active collection of transactions.
|
|
2879
|
+
this.#mapIdToTx.set(tx.id, tx);
|
|
2880
|
+
this.#approxPageCount += tx.pages.size;
|
|
2881
|
+
|
|
2882
|
+
// Add transaction pages to the write-ahead overlay.
|
|
2883
|
+
for (const [offset, pageEntry] of tx.pages) {
|
|
2884
|
+
this.#waOverlay.set(offset, pageEntry);
|
|
2885
|
+
}
|
|
2886
|
+
this.#dbFileSize = tx.dbFileSize;
|
|
2887
|
+
}
|
|
2888
|
+
|
|
2889
|
+
/**
|
|
2890
|
+
* Advance the local view of the database. By default, advance to the
|
|
2891
|
+
* last broadcast transaction. Optionally, also advance through any
|
|
2892
|
+
* additional transactions in the WAL file to be fully current.
|
|
2893
|
+
*
|
|
2894
|
+
* @param {{readToCurrent?: boolean, autoCheckpoint?: boolean}} options
|
|
2895
|
+
*/
|
|
2896
|
+
#advanceTxId(options = {}) {
|
|
2897
|
+
let didAdvance = false;
|
|
2898
|
+
while (this.#mapIdToPendingTx.size) {
|
|
2899
|
+
// Fetch the next transaction in sequence. Usually this will come
|
|
2900
|
+
// from pendingTx, but if it is missing then read it from the file.
|
|
2901
|
+
const nextTxId = this.#txId + 1;
|
|
2902
|
+
let tx;
|
|
2903
|
+
if (this.#mapIdToPendingTx.has(nextTxId)) {
|
|
2904
|
+
// This transaction arrived via message.
|
|
2905
|
+
tx = this.#mapIdToPendingTx.get(nextTxId);
|
|
2906
|
+
this.#mapIdToPendingTx.delete(tx.id);
|
|
2907
|
+
|
|
2908
|
+
// Move the WAL file offset past this transaction.
|
|
2909
|
+
this.#skipTx(tx);
|
|
2910
|
+
} else {
|
|
2911
|
+
// Read the transaction from the WAL file.
|
|
2912
|
+
tx = this.#readTx();
|
|
2913
|
+
}
|
|
2914
|
+
|
|
2915
|
+
this.#activateTx(tx);
|
|
2916
|
+
didAdvance = true;
|
|
2917
|
+
}
|
|
2918
|
+
|
|
2919
|
+
if (options.readToCurrent) {
|
|
2920
|
+
// Read all additional transactions from the WAL file.
|
|
2921
|
+
for (const tx of this.#readAllTx()) {
|
|
2922
|
+
this.#activateTx(tx);
|
|
2923
|
+
didAdvance = true;
|
|
2924
|
+
}
|
|
2925
|
+
}
|
|
2926
|
+
|
|
2927
|
+
if (didAdvance) {
|
|
2928
|
+
// Publish our new view txId.
|
|
2929
|
+
this.#updateTxIdLock();
|
|
2930
|
+
|
|
2931
|
+
if (options.autoCheckpoint) {
|
|
2932
|
+
this.#autoCheckpoint();
|
|
2933
|
+
}
|
|
2934
|
+
}
|
|
2935
|
+
|
|
2936
|
+
if (options.readToCurrent || didAdvance) {
|
|
2937
|
+
// The WAL has been accessed, so reset the backstop.
|
|
2938
|
+
// Calling #backstop() here is not necessary because if we are
|
|
2939
|
+
// in an isolated state then rejoin() will schedule the next call,
|
|
2940
|
+
// and if we are not in an isolated state then the next call
|
|
2941
|
+
// should already be scheduled.
|
|
2942
|
+
this.#backstopTimestamp = performance.now();
|
|
2943
|
+
}
|
|
2944
|
+
}
|
|
2945
|
+
|
|
2946
|
+
#autoCheckpoint() {
|
|
2947
|
+
if (this.options.autoCheckpoint > 0) {
|
|
2948
|
+
this.checkpoint({ isPassive: true });
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
|
|
2952
|
+
/**
|
|
2953
|
+
* After a checkpoint, remove checkpointed pages from write-ahead.
|
|
2954
|
+
* The checkpoint may be been done locally or by another connection.
|
|
2955
|
+
* @param {number} ckptId
|
|
2956
|
+
*/
|
|
2957
|
+
#handleCheckpoint(ckptId) {
|
|
2958
|
+
this.log?.(`%capply checkpoint through txId ${ckptId}`, 'background-color: lightgreen;');
|
|
2959
|
+
|
|
2960
|
+
// Loop backwards from ckptId.
|
|
2961
|
+
for (let tx = this.#mapIdToTx.get(ckptId); tx; tx = this.#mapIdToTx.get(tx.id - 1)) {
|
|
2962
|
+
// Remove pages from write-ahead overlay.
|
|
2963
|
+
for (const [offset, pageEntry] of tx.pages.entries()) {
|
|
2964
|
+
// Be sure not to remove a newer version of the page.
|
|
2965
|
+
const overlayEntry = this.#waOverlay.get(offset);
|
|
2966
|
+
if (overlayEntry === pageEntry) {
|
|
2967
|
+
this.log?.(`%cremove txId ${tx.id} page at offset ${offset}`, 'background-color: lightgreen;');
|
|
2968
|
+
this.#waOverlay.delete(offset);
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2971
|
+
|
|
2972
|
+
// Remove transaction.
|
|
2973
|
+
this.#mapIdToTx.delete(tx.id);
|
|
2974
|
+
this.#approxPageCount -= tx.pages.size;
|
|
2975
|
+
}
|
|
2976
|
+
this.#updateTxIdLock();
|
|
2977
|
+
}
|
|
2978
|
+
|
|
2979
|
+
/**
|
|
2980
|
+
* @param {MessageEvent} event
|
|
2981
|
+
*/
|
|
2982
|
+
#handleMessage(event) {
|
|
2983
|
+
if (event.data.type === 'tx') {
|
|
2984
|
+
// New transaction from another connection. Don't use it if we
|
|
2985
|
+
// already have it.
|
|
2986
|
+
/** @type {Transaction} */ const tx = event.data.tx;
|
|
2987
|
+
if (tx.id > this.#txId) {
|
|
2988
|
+
this.#mapIdToPendingTx.set(tx.id, tx);
|
|
2989
|
+
if (this.#isolationState === null) {
|
|
2990
|
+
// Not in an isolated state, so advance our view of the database.
|
|
2991
|
+
this.#advanceTxId({ autoCheckpoint: true });
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
} else if (event.data.type === 'ckpt') {
|
|
2995
|
+
// Checkpoint notification from another connection.
|
|
2996
|
+
/** @type {number} */ const ckptId = event.data.ckptId;
|
|
2997
|
+
this.#handleCheckpoint(ckptId);
|
|
2998
|
+
}
|
|
2999
|
+
}
|
|
3000
|
+
|
|
3001
|
+
/**
|
|
3002
|
+
* Periodic check for recovering from lost transaction broadcasts.
|
|
3003
|
+
*/
|
|
3004
|
+
#backstop() {
|
|
3005
|
+
if (this.options.backstopInterval <= 0) {
|
|
3006
|
+
// Backstop is disabled.
|
|
3007
|
+
return;
|
|
3008
|
+
}
|
|
3009
|
+
|
|
3010
|
+
if (this.#isolationState) {
|
|
3011
|
+
throw new Error('Backstop was invoked in an isolated state');
|
|
3012
|
+
}
|
|
3013
|
+
|
|
3014
|
+
const now = performance.now();
|
|
3015
|
+
if (now >= this.#backstopTimestamp + this.options.backstopInterval) {
|
|
3016
|
+
// The time since the last WAL access (read, write, or skip) has
|
|
3017
|
+
// exceeded the backstop interval. Check for transactions in the
|
|
3018
|
+
// write-ahead log that have not arrived via message.
|
|
3019
|
+
const oldTxId = this.#txId;
|
|
3020
|
+
this.#advanceTxId({ readToCurrent: true });
|
|
3021
|
+
if (this.#txId > oldTxId) {
|
|
3022
|
+
this.log?.(`%cbackstop txId ${oldTxId} -> ${this.#txId}`, 'background-color: lightyellow;');
|
|
3023
|
+
}
|
|
3024
|
+
this.#backstopTimestamp = performance.now();
|
|
3025
|
+
}
|
|
3026
|
+
|
|
3027
|
+
// Schedule next backstop.
|
|
3028
|
+
const delay = this.#backstopTimestamp + this.options.backstopInterval - performance.now();
|
|
3029
|
+
clearTimeout(this.#backstopTimer);
|
|
3030
|
+
this.#backstopTimer = self.setTimeout(() => {
|
|
3031
|
+
this.#backstop();
|
|
3032
|
+
}, delay);
|
|
3033
|
+
}
|
|
3034
|
+
|
|
3035
|
+
/**
|
|
3036
|
+
* Update the lock that publishes our current txId.
|
|
3037
|
+
*/
|
|
3038
|
+
async #updateTxIdLock() {
|
|
3039
|
+
// Our view of the database, i.e. the txId, is encoded into the name
|
|
3040
|
+
// of a lock so other connections can see it. When our txId changes,
|
|
3041
|
+
// we acquire a new lock and release the old one. We must not release
|
|
3042
|
+
// the old lock until the new one is in place.
|
|
3043
|
+
const oldLock = this.#txIdLock;
|
|
3044
|
+
const newLockName = this.#encodeTxIdLockName();
|
|
3045
|
+
if (oldLock?.name !== newLockName) {
|
|
3046
|
+
this.#txIdLock = new _Lock_js__WEBPACK_IMPORTED_MODULE_0__.Lock(newLockName);
|
|
3047
|
+
await this.#txIdLock.acquire('shared').then(() => {
|
|
3048
|
+
// The new lock is acquired.
|
|
3049
|
+
oldLock?.release();
|
|
3050
|
+
});
|
|
3051
|
+
|
|
3052
|
+
if (this.log) {
|
|
3053
|
+
const { minTxId, maxTxId } = this.#decodeTxIdLockName(newLockName);
|
|
3054
|
+
this.log?.(`%ctxId to ${minTxId}:${maxTxId}`, 'background-color: pink;');
|
|
3055
|
+
}
|
|
3056
|
+
}
|
|
3057
|
+
}
|
|
3058
|
+
|
|
3059
|
+
/**
|
|
3060
|
+
* Get all txId locks for this database.
|
|
3061
|
+
* @returns {Promise<{name: string, minTxId: number, maxTxId: number, encoded: string}[]>}
|
|
3062
|
+
*/
|
|
3063
|
+
async #getTxIdLocks() {
|
|
3064
|
+
const { held } = await navigator.locks.query();
|
|
3065
|
+
return held
|
|
3066
|
+
.map(lock => this.#decodeTxIdLockName(lock.name))
|
|
3067
|
+
.filter(value => value !== null);
|
|
3068
|
+
}
|
|
3069
|
+
|
|
3070
|
+
/**
|
|
3071
|
+
* @returns {string}
|
|
3072
|
+
*/
|
|
3073
|
+
#encodeTxIdLockName() {
|
|
3074
|
+
// The maxTxId is our current view of the database. The minTxId is
|
|
3075
|
+
// the lowest txId we get pages from the WAL for, which is the lowest
|
|
3076
|
+
// key in mapIdToTx. If mapIdToTx is empty then we aren't reading
|
|
3077
|
+
// from the WAL at all - in this case we arbitrarily set minTxId to
|
|
3078
|
+
// invalid value maxTxId + 1.
|
|
3079
|
+
//
|
|
3080
|
+
// Use radix 36 to encode integer values to reduce the lock name length.
|
|
3081
|
+
const maxTxId = this.#txId;
|
|
3082
|
+
const minTxId = this.#mapIdToTx.keys().next().value ?? (maxTxId + 1);
|
|
3083
|
+
return `${this.#zName}-txId<${minTxId.toString(36)}:${maxTxId.toString(36)}>`;
|
|
3084
|
+
}
|
|
3085
|
+
|
|
3086
|
+
/**
|
|
3087
|
+
* @param {string} lockName
|
|
3088
|
+
* @returns {{name: string, minTxId: number, maxTxId: number, encoded: string}?}
|
|
3089
|
+
*/
|
|
3090
|
+
#decodeTxIdLockName(lockName) {
|
|
3091
|
+
const match = lockName.match(/^(.*)-txId<([0-9a-z]+):([0-9a-z]+)>$/);
|
|
3092
|
+
if (match?.[1] === this.#zName) {
|
|
3093
|
+
// This txId lock is for this database.
|
|
3094
|
+
return {
|
|
3095
|
+
name: match[1],
|
|
3096
|
+
minTxId: parseInt(match[2], 36),
|
|
3097
|
+
maxTxId: parseInt(match[3], 36),
|
|
3098
|
+
encoded: lockName
|
|
3099
|
+
};
|
|
3100
|
+
}
|
|
3101
|
+
return null;
|
|
3102
|
+
}
|
|
3103
|
+
|
|
3104
|
+
/**
|
|
3105
|
+
* Wait for all txId locks that fail the provided predicate.
|
|
3106
|
+
* @param {(lock: {name: string, minTxId: number, maxTxId: number}) => boolean} predicate
|
|
3107
|
+
*/
|
|
3108
|
+
async #waitForTxIdLocks(predicate) {
|
|
3109
|
+
/** @type {string[]} */ let failingLockNames = [];
|
|
3110
|
+
do {
|
|
3111
|
+
// Wait for all connections that fail the predicate.
|
|
3112
|
+
if (failingLockNames.length > 0) {
|
|
3113
|
+
await Promise.all(
|
|
3114
|
+
failingLockNames.map(name => navigator.locks.request(name, async () => {}))
|
|
3115
|
+
);
|
|
3116
|
+
}
|
|
3117
|
+
|
|
3118
|
+
// Refresh the list of failing locks.
|
|
3119
|
+
failingLockNames = (await this.#getTxIdLocks())
|
|
3120
|
+
.filter(value => !predicate(value))
|
|
3121
|
+
.map(value => value.encoded);
|
|
3122
|
+
} while (failingLockNames.length > 0);
|
|
3123
|
+
}
|
|
3124
|
+
|
|
3125
|
+
/**
|
|
3126
|
+
* @param {PageEntry} pageEntry
|
|
3127
|
+
* @returns {Uint8Array}
|
|
3128
|
+
*/
|
|
3129
|
+
#fetchPage(pageEntry) {
|
|
3130
|
+
// Get the appropriate access handle based on salt parity.
|
|
3131
|
+
const accessHandle = this.#waHandles[pageEntry.waSalt1 & 1];
|
|
3132
|
+
|
|
3133
|
+
// Read the page.
|
|
3134
|
+
const pageData = new Uint8Array(pageEntry.pageSize);
|
|
3135
|
+
const nBytesRead = accessHandle.read(pageData, { at: pageEntry.waOffset });
|
|
3136
|
+
|
|
3137
|
+
if (nBytesRead !== pageEntry.pageSize) {
|
|
3138
|
+
throw new Error(`Short WAL read: expected ${pageEntry.pageSize} bytes, got ${nBytesRead}`);
|
|
3139
|
+
}
|
|
3140
|
+
return pageData;
|
|
3141
|
+
}
|
|
3142
|
+
|
|
3143
|
+
*#readAllTx() {
|
|
3144
|
+
while (true) {
|
|
3145
|
+
const tx = this.#readTx();
|
|
3146
|
+
if (!tx) break;
|
|
3147
|
+
yield tx;
|
|
3148
|
+
}
|
|
3149
|
+
}
|
|
3150
|
+
|
|
3151
|
+
/**
|
|
3152
|
+
* @returns {Transaction?}
|
|
3153
|
+
*/
|
|
3154
|
+
#readTx() {
|
|
3155
|
+
// Read the next complete transaction or return null.
|
|
3156
|
+
/** @type {Transaction} */ const tx = {
|
|
3157
|
+
id: 0, // placeholder
|
|
3158
|
+
pages: new Map(),
|
|
3159
|
+
dbFileSize: 0, // placeholder
|
|
3160
|
+
waSalt1: 0, // placeholder
|
|
3161
|
+
waOffsetEnd: 0, // placeholder
|
|
3162
|
+
};
|
|
3163
|
+
|
|
3164
|
+
// The property this.#activeOffset is only advanced on a successful
|
|
3165
|
+
// transition to the other WAL file or on reading a complete
|
|
3166
|
+
// transaction. Use a local variable to track our progress.
|
|
3167
|
+
let offset = this.#activeOffset;
|
|
3168
|
+
while (true) {
|
|
3169
|
+
const frame = this.#readFrame(offset);
|
|
3170
|
+
if (!frame) return null;
|
|
3171
|
+
|
|
3172
|
+
if (frame.frameType === FRAME_TYPE_PAGE) {
|
|
3173
|
+
tx.pages.set(
|
|
3174
|
+
frame.pageOffset,
|
|
3175
|
+
{
|
|
3176
|
+
pageSize: frame.pageData.byteLength,
|
|
3177
|
+
waOffset: offset + FRAME_HEADER_SIZE,
|
|
3178
|
+
waSalt1: this.#activeHeader.salt1,
|
|
3179
|
+
}
|
|
3180
|
+
);
|
|
3181
|
+
} else if (frame.frameType === FRAME_TYPE_COMMIT) {
|
|
3182
|
+
// The transaction is complete. Update the instance state.
|
|
3183
|
+
this.#txId += 1;
|
|
3184
|
+
this.#activeOffset = offset + frame.byteLength;
|
|
3185
|
+
|
|
3186
|
+
// Finalize the transaction fields and return it.
|
|
3187
|
+
tx.id = this.#txId;
|
|
3188
|
+
tx.dbFileSize = frame.dbFileSize;
|
|
3189
|
+
tx.waSalt1 = this.#activeHeader.salt1;
|
|
3190
|
+
tx.newPageSize = (frame.flags & 1) ? tx.pages.get(0).pageSize : null;
|
|
3191
|
+
tx.waOffsetEnd = this.#activeOffset;
|
|
3192
|
+
return tx;
|
|
3193
|
+
} else if (frame.frameType === FRAME_TYPE_END) {
|
|
3194
|
+
// No more transactions on the current WAL file. Switch to the
|
|
3195
|
+
// other file.
|
|
3196
|
+
this.#followFileChange(frame.fileHeader);
|
|
3197
|
+
offset = this.#activeOffset;
|
|
3198
|
+
continue;
|
|
3199
|
+
}
|
|
3200
|
+
|
|
3201
|
+
offset += frame.byteLength;
|
|
3202
|
+
}
|
|
3203
|
+
}
|
|
3204
|
+
|
|
3205
|
+
/**
|
|
3206
|
+
* This method is called when transaction(s) have been received by other
|
|
3207
|
+
* means than readTx(), e.g. via BroadcastChannel.
|
|
3208
|
+
*
|
|
3209
|
+
* @param {Transaction} tx
|
|
3210
|
+
*/
|
|
3211
|
+
#skipTx(tx) {
|
|
3212
|
+
if (tx.waSalt1 !== this.#activeHeader.salt1) {
|
|
3213
|
+
// This transaction is on the other WAL file.
|
|
3214
|
+
if (!this.#followFileChange(null)) {
|
|
3215
|
+
throw new Error('invalid WAL file');
|
|
3216
|
+
}
|
|
3217
|
+
}
|
|
3218
|
+
|
|
3219
|
+
this.#txId = tx.id;
|
|
3220
|
+
this.#activeOffset = tx.waOffsetEnd;
|
|
3221
|
+
}
|
|
3222
|
+
|
|
3223
|
+
/**
|
|
3224
|
+
* @param {{overwrite?: boolean}} options
|
|
3225
|
+
* @returns {Transaction}
|
|
3226
|
+
*/
|
|
3227
|
+
#beginTx(options = {}) {
|
|
3228
|
+
this.#txInProgress = {
|
|
3229
|
+
id: this.#txId + 1,
|
|
3230
|
+
pages: new Map(),
|
|
3231
|
+
dbFileSize: this.#dbFileSize,
|
|
3232
|
+
waSalt1: this.#activeHeader.salt1,
|
|
3233
|
+
waOffsetEnd: this.#activeOffset,
|
|
3234
|
+
};
|
|
3235
|
+
return this.#txInProgress;
|
|
3236
|
+
}
|
|
3237
|
+
|
|
3238
|
+
/**
|
|
3239
|
+
* Write a page frame to the WAL file.
|
|
3240
|
+
*
|
|
3241
|
+
* @param {number} pageOffset
|
|
3242
|
+
* @param {Uint8Array} pageData
|
|
3243
|
+
*/
|
|
3244
|
+
#writePage(pageOffset, pageData) {
|
|
3245
|
+
const headerView = new DataView(new ArrayBuffer(FRAME_HEADER_SIZE));
|
|
3246
|
+
headerView.setUint8(0, FRAME_TYPE_PAGE);
|
|
3247
|
+
headerView.setUint16(2, pageData.byteLength === 65536 ? 1 : pageData.byteLength);
|
|
3248
|
+
headerView.setBigUint64(8, BigInt(pageOffset));
|
|
3249
|
+
headerView.setUint32(16, this.#activeHeader.salt1);
|
|
3250
|
+
headerView.setUint32(20, this.#activeHeader.salt2);
|
|
3251
|
+
|
|
3252
|
+
const checksum = new Checksum();
|
|
3253
|
+
checksum.update(new Uint8Array(headerView.buffer, 0, FRAME_HEADER_SIZE - 8));
|
|
3254
|
+
checksum.update(pageData);
|
|
3255
|
+
headerView.setUint32(24, checksum.s0);
|
|
3256
|
+
headerView.setUint32(28, checksum.s1);
|
|
3257
|
+
|
|
3258
|
+
const bytesWritten =
|
|
3259
|
+
this.#activeHandle.write(headerView, { at: this.#txInProgress.waOffsetEnd }) +
|
|
3260
|
+
this.#activeHandle.write(pageData, {
|
|
3261
|
+
at: this.#txInProgress.waOffsetEnd + FRAME_HEADER_SIZE,
|
|
3262
|
+
});
|
|
3263
|
+
if (bytesWritten !== headerView.byteLength + pageData.byteLength) {
|
|
3264
|
+
throw new Error('write failed');
|
|
3265
|
+
}
|
|
3266
|
+
|
|
3267
|
+
// Cache page 1 as a performance optimization and to exercise the
|
|
3268
|
+
// cache code path.
|
|
3269
|
+
const pageEntry = {
|
|
3270
|
+
pageSize: pageData.byteLength,
|
|
3271
|
+
waOffset: this.#txInProgress.waOffsetEnd + FRAME_HEADER_SIZE,
|
|
3272
|
+
waSalt1: this.#activeHeader.salt1,
|
|
3273
|
+
pageData: pageOffset === 0 ? pageData : undefined
|
|
3274
|
+
};
|
|
3275
|
+
this.#txInProgress.pages.set(pageOffset, pageEntry);
|
|
3276
|
+
this.#txInProgress.waOffsetEnd += bytesWritten;
|
|
3277
|
+
|
|
3278
|
+
return pageEntry.waOffset;
|
|
3279
|
+
}
|
|
3280
|
+
|
|
3281
|
+
/**
|
|
3282
|
+
* @returns {Transaction}
|
|
3283
|
+
*/
|
|
3284
|
+
#commitTx() {
|
|
3285
|
+
// Write a commit frame - which is a special frame header with no
|
|
3286
|
+
// body - to the WAL file.
|
|
3287
|
+
const headerView = new DataView(new ArrayBuffer(FRAME_HEADER_SIZE));
|
|
3288
|
+
headerView.setUint8(0, FRAME_TYPE_COMMIT);
|
|
3289
|
+
headerView.setUint8(1, this.#txInProgress.newPageSize ? 1 : 0);
|
|
3290
|
+
headerView.setBigUint64(8, BigInt(this.#txInProgress.dbFileSize));
|
|
3291
|
+
headerView.setUint32(16, this.#activeHeader.salt1);
|
|
3292
|
+
headerView.setUint32(20, this.#activeHeader.salt2);
|
|
3293
|
+
|
|
3294
|
+
const checksum = new Checksum();
|
|
3295
|
+
checksum.update(new Uint8Array(headerView.buffer, 0, FRAME_HEADER_SIZE - 8));
|
|
3296
|
+
headerView.setUint32(24, checksum.s0);
|
|
3297
|
+
headerView.setUint32(28, checksum.s1);
|
|
3298
|
+
|
|
3299
|
+
const bytesWritten = this.#activeHandle.write(headerView, {
|
|
3300
|
+
at: this.#txInProgress.waOffsetEnd,
|
|
3301
|
+
});
|
|
3302
|
+
if (bytesWritten !== headerView.byteLength) {
|
|
3303
|
+
throw new Error('write failed');
|
|
3304
|
+
}
|
|
3305
|
+
this.#txInProgress.waOffsetEnd += bytesWritten;
|
|
3306
|
+
|
|
3307
|
+
const tx = this.#txInProgress;
|
|
3308
|
+
this.#txInProgress = null;
|
|
3309
|
+
this.#activeOffset = tx.waOffsetEnd;
|
|
3310
|
+
this.#txId = tx.id;
|
|
3311
|
+
return tx;
|
|
3312
|
+
}
|
|
3313
|
+
|
|
3314
|
+
#abortTx() {
|
|
3315
|
+
this.#txInProgress = null;
|
|
3316
|
+
this.#activeHandle.truncate(this.#activeOffset);
|
|
3317
|
+
}
|
|
3318
|
+
|
|
3319
|
+
/**
|
|
3320
|
+
* Switch the active WAL file prior to writing the next transaction.
|
|
3321
|
+
*/
|
|
3322
|
+
#swapActiveFile() {
|
|
3323
|
+
// Write an end frame to terminate the currently active WAL file.
|
|
3324
|
+
const frameView = new DataView(new ArrayBuffer(FRAME_HEADER_SIZE));
|
|
3325
|
+
frameView.setUint8(0, FRAME_TYPE_END);
|
|
3326
|
+
frameView.setUint32(16, this.#activeHeader.salt1);
|
|
3327
|
+
frameView.setUint32(20, this.#activeHeader.salt2);
|
|
3328
|
+
|
|
3329
|
+
const checksum = new Checksum();
|
|
3330
|
+
checksum.update(new Uint8Array(frameView.buffer, 0, FRAME_HEADER_SIZE - 8));
|
|
3331
|
+
frameView.setUint32(24, checksum.s0);
|
|
3332
|
+
frameView.setUint32(28, checksum.s1);
|
|
3333
|
+
|
|
3334
|
+
const bytesWritten = this.#activeHandle.write(frameView, { at: this.#activeOffset });
|
|
3335
|
+
if (bytesWritten !== frameView.byteLength) {
|
|
3336
|
+
throw new Error('write failed');
|
|
3337
|
+
}
|
|
3338
|
+
|
|
3339
|
+
// Initialize the other WAL file and make it active.
|
|
3340
|
+
this.#activeHeader = this.#writeFileHeader();
|
|
3341
|
+
this.#activeHandle = this.#getInactiveHandle();
|
|
3342
|
+
this.#activeOffset = FILE_HEADER_SIZE;
|
|
3343
|
+
}
|
|
3344
|
+
|
|
3345
|
+
#getActiveFileStartingTxId() {
|
|
3346
|
+
return this.#activeHeader.nextTxId;
|
|
3347
|
+
}
|
|
3348
|
+
|
|
3349
|
+
#flushActiveFile() {
|
|
3350
|
+
this.#activeHandle.flush();
|
|
3351
|
+
}
|
|
3352
|
+
|
|
3353
|
+
#flushInactiveFile() {
|
|
3354
|
+
const accessHandle = this.#getInactiveHandle();
|
|
3355
|
+
accessHandle.flush();
|
|
3356
|
+
}
|
|
3357
|
+
|
|
3358
|
+
#isInactiveFileEmpty() {
|
|
3359
|
+
if (this.#mapIdToTx.has(this.#activeHeader.nextTxId - 1)) {
|
|
3360
|
+
// At least one transaction on the inactive file has not been
|
|
3361
|
+
// checkpointed.
|
|
3362
|
+
return false;
|
|
3363
|
+
}
|
|
3364
|
+
|
|
3365
|
+
const inactiveHandle = this.#getInactiveHandle();
|
|
3366
|
+
if (inactiveHandle.getSize() < FILE_HEADER_SIZE) {
|
|
3367
|
+
// The inactive file is smaller than the minimum size for a valid
|
|
3368
|
+
// WAL file.
|
|
3369
|
+
return true;
|
|
3370
|
+
}
|
|
3371
|
+
|
|
3372
|
+
// This test is sufficient by itself but the previous tests are
|
|
3373
|
+
// less expensive.
|
|
3374
|
+
return this.#readFileHeader(inactiveHandle) === null;
|
|
3375
|
+
}
|
|
3376
|
+
|
|
3377
|
+
#truncateInactiveFile() {
|
|
3378
|
+
const accessHandle = this.#getInactiveHandle();
|
|
3379
|
+
accessHandle.truncate(0);
|
|
3380
|
+
}
|
|
3381
|
+
|
|
3382
|
+
/**
|
|
3383
|
+
* This method is called after reading an end frame to switch to the
|
|
3384
|
+
* other WAL file.
|
|
3385
|
+
* @param {{nextTxId: number, salt1: number, salt2: number}?} fileHeader
|
|
3386
|
+
*/
|
|
3387
|
+
#followFileChange(fileHeader) {
|
|
3388
|
+
// As an optimization, the file header can be passed as an argument
|
|
3389
|
+
// if it has already been read and validated. Otherwise that is
|
|
3390
|
+
// done here.
|
|
3391
|
+
const accessHandle = this.#getInactiveHandle();
|
|
3392
|
+
if (!fileHeader) {
|
|
3393
|
+
fileHeader = this.#readFileHeader(accessHandle);
|
|
3394
|
+
if (fileHeader?.salt1 !== ((this.#activeHeader.salt1 + 1) >>> 0)) return null;
|
|
3395
|
+
}
|
|
3396
|
+
|
|
3397
|
+
this.#activeHandle = accessHandle;
|
|
3398
|
+
this.#activeHeader = fileHeader;
|
|
3399
|
+
this.#activeOffset = FILE_HEADER_SIZE;
|
|
3400
|
+
return fileHeader;
|
|
3401
|
+
}
|
|
3402
|
+
|
|
3403
|
+
#getInactiveHandle() {
|
|
3404
|
+
return this.#activeHandle !== this.#waHandles[0] ?
|
|
3405
|
+
this.#waHandles[0] :
|
|
3406
|
+
this.#waHandles[1];
|
|
3407
|
+
}
|
|
3408
|
+
|
|
3409
|
+
/**
|
|
3410
|
+
* @param {FileSystemSyncAccessHandle} accessHandle
|
|
3411
|
+
*/
|
|
3412
|
+
#readFileHeader(accessHandle) {
|
|
3413
|
+
const headerView = new DataView(new ArrayBuffer(FILE_HEADER_SIZE));
|
|
3414
|
+
if (accessHandle.read(headerView, { at: 0 }) !== headerView.byteLength) {
|
|
3415
|
+
return null;
|
|
3416
|
+
}
|
|
3417
|
+
|
|
3418
|
+
if (headerView.getUint32(0) !== MAGIC) return null;
|
|
3419
|
+
|
|
3420
|
+
const checksum = new Checksum();
|
|
3421
|
+
checksum.update(new Uint8Array(headerView.buffer, 0, FILE_HEADER_SIZE - 8));
|
|
3422
|
+
if (!checksum.matches(headerView.getUint32(24), headerView.getUint32(28))) {
|
|
3423
|
+
return null;
|
|
3424
|
+
}
|
|
3425
|
+
|
|
3426
|
+
return {
|
|
3427
|
+
nextTxId: Number(headerView.getBigUint64(8)),
|
|
3428
|
+
salt1: headerView.getUint32(16),
|
|
3429
|
+
salt2: headerView.getUint32(20),
|
|
3430
|
+
};
|
|
3431
|
+
}
|
|
3432
|
+
|
|
3433
|
+
/**
|
|
3434
|
+
* @param {number} offset
|
|
3435
|
+
*/
|
|
3436
|
+
#readFrame(offset) {
|
|
3437
|
+
const headerView = new DataView(new ArrayBuffer(FRAME_HEADER_SIZE));
|
|
3438
|
+
if (this.#activeHandle.read(headerView, { at: offset }) !== headerView.byteLength) {
|
|
3439
|
+
// EOF, not an error.
|
|
3440
|
+
return null;
|
|
3441
|
+
}
|
|
3442
|
+
|
|
3443
|
+
// Verify the frame header salt values match the file header.
|
|
3444
|
+
const frameSalt1 = headerView.getUint32(16);
|
|
3445
|
+
const frameSalt2 = headerView.getUint32(20);
|
|
3446
|
+
if (frameSalt1 !== this.#activeHeader.salt1 || frameSalt2 !== this.#activeHeader.salt2) {
|
|
3447
|
+
// Not necessarily an error, could be from a restart without truncation.
|
|
3448
|
+
return null;
|
|
3449
|
+
}
|
|
3450
|
+
|
|
3451
|
+
const payloadSize = (size => size === 1 ? 65536 : size)(headerView.getUint16(2));
|
|
3452
|
+
/** @type {Uint8Array} */ let payloadData;
|
|
3453
|
+
if (payloadSize) {
|
|
3454
|
+
payloadData = new Uint8Array(payloadSize);
|
|
3455
|
+
const payloadBytesRead = this.#activeHandle.read(
|
|
3456
|
+
payloadData,
|
|
3457
|
+
{ at: offset + FRAME_HEADER_SIZE }
|
|
3458
|
+
);
|
|
3459
|
+
if (payloadBytesRead !== payloadSize) return null;
|
|
3460
|
+
}
|
|
3461
|
+
|
|
3462
|
+
const checksum = new Checksum();
|
|
3463
|
+
checksum.update(new Uint8Array(headerView.buffer, 0, FRAME_HEADER_SIZE - 8));
|
|
3464
|
+
if (payloadData) {
|
|
3465
|
+
checksum.update(payloadData);
|
|
3466
|
+
}
|
|
3467
|
+
if (!checksum.matches(headerView.getUint32(24), headerView.getUint32(28))) {
|
|
3468
|
+
// Not necessarily an error, could be from a restart without truncation.
|
|
3469
|
+
return null;
|
|
3470
|
+
}
|
|
3471
|
+
|
|
3472
|
+
const frameType = headerView.getUint8(0);
|
|
3473
|
+
if (frameType === FRAME_TYPE_PAGE) {
|
|
3474
|
+
return {
|
|
3475
|
+
frameType,
|
|
3476
|
+
byteLength: FRAME_HEADER_SIZE + payloadSize,
|
|
3477
|
+
pageOffset: Number(headerView.getBigUint64(8)),
|
|
3478
|
+
pageData: payloadData,
|
|
3479
|
+
};
|
|
3480
|
+
} else if (frameType === FRAME_TYPE_COMMIT) {
|
|
3481
|
+
return {
|
|
3482
|
+
frameType,
|
|
3483
|
+
byteLength: FRAME_HEADER_SIZE,
|
|
3484
|
+
flags: headerView.getUint8(1),
|
|
3485
|
+
dbFileSize: Number(headerView.getBigUint64(8)),
|
|
3486
|
+
};
|
|
3487
|
+
} else if (frameType === FRAME_TYPE_END) {
|
|
3488
|
+
// Handling the end frame and new file header must be atomic, so
|
|
3489
|
+
// we validate the new file header before returning the frame.
|
|
3490
|
+
// If the file header is corrupt, the end frame effectively does
|
|
3491
|
+
// not exist.
|
|
3492
|
+
//
|
|
3493
|
+
// A corrupt file header should be repaired by the next writer
|
|
3494
|
+
// that attempts to swap WAL files.
|
|
3495
|
+
const fileHeader = this.#readFileHeader(this.#getInactiveHandle());
|
|
3496
|
+
if (fileHeader?.salt1 !== ((this.#activeHeader.salt1 + 1) >>> 0)) return null;
|
|
3497
|
+
|
|
3498
|
+
return {
|
|
3499
|
+
frameType,
|
|
3500
|
+
byteLength: FRAME_HEADER_SIZE,
|
|
3501
|
+
fileHeader,
|
|
3502
|
+
};
|
|
3503
|
+
}
|
|
3504
|
+
throw new Error(`Invalid frame type: ${frameType}`);
|
|
3505
|
+
}
|
|
3506
|
+
|
|
3507
|
+
#writeFileHeader(prevSalt1 = this.#activeHeader.salt1) {
|
|
3508
|
+
// Derive new values from the previous values.
|
|
3509
|
+
const nextTxId = this.#txId + 1;
|
|
3510
|
+
const salt1 = (prevSalt1 + 1) >>> 0;
|
|
3511
|
+
const salt2 = Math.floor(Math.random() * 0xffffffff) >>> 0;
|
|
3512
|
+
const headerView = new DataView(new ArrayBuffer(FILE_HEADER_SIZE));
|
|
3513
|
+
headerView.setUint32(0, MAGIC);
|
|
3514
|
+
headerView.setBigUint64(8, BigInt(nextTxId));
|
|
3515
|
+
headerView.setUint32(16, salt1);
|
|
3516
|
+
headerView.setUint32(20, salt2);
|
|
3517
|
+
|
|
3518
|
+
const checksum = new Checksum();
|
|
3519
|
+
checksum.update(new Uint8Array(headerView.buffer, 0, FILE_HEADER_SIZE - 8));
|
|
3520
|
+
headerView.setUint32(24, checksum.s0);
|
|
3521
|
+
headerView.setUint32(28, checksum.s1);
|
|
3522
|
+
|
|
3523
|
+
// The even/odd parity of salt1 determines which file is written to.
|
|
3524
|
+
const accessHandle = this.#waHandles[salt1 & 1];
|
|
3525
|
+
const bytesWritten = accessHandle.write(headerView, { at: 0 });
|
|
3526
|
+
if (bytesWritten !== headerView.byteLength) {
|
|
3527
|
+
throw new Error('write failed');
|
|
3528
|
+
}
|
|
3529
|
+
|
|
3530
|
+
return { nextTxId, salt1, salt2 };
|
|
3531
|
+
}
|
|
3532
|
+
}
|
|
3533
|
+
|
|
3534
|
+
// https://www.sqlite.org/fileformat.html#checksum_algorithm
|
|
3535
|
+
class Checksum {
|
|
3536
|
+
/** @type {number} */ s0 = 0;
|
|
3537
|
+
/** @type {number} */ s1 = 0;
|
|
3538
|
+
|
|
3539
|
+
/**
|
|
3540
|
+
* @param {ArrayBuffer|ArrayBufferView} data
|
|
3541
|
+
*/
|
|
3542
|
+
update(data) {
|
|
3543
|
+
if ((data.byteLength % 8) !== 0) throw new Error('Data must be a multiple of 8 bytes');
|
|
3544
|
+
const words = ArrayBuffer.isView(data) ?
|
|
3545
|
+
new Uint32Array(data.buffer, data.byteOffset, data.byteLength / 4) :
|
|
3546
|
+
new Uint32Array(data);
|
|
3547
|
+
for (let i = 0; i < words.length; i += 2) {
|
|
3548
|
+
this.s0 = (this.s0 + words[i] + this.s1) >>> 0;
|
|
3549
|
+
this.s1 = (this.s1 + words[i + 1] + this.s0) >>> 0;
|
|
3550
|
+
}
|
|
3551
|
+
}
|
|
3552
|
+
|
|
3553
|
+
matches(s0, s1) {
|
|
3554
|
+
return this.s0 === s0 && this.s1 === s1;
|
|
3555
|
+
}
|
|
3556
|
+
}
|
|
3557
|
+
|
|
3558
|
+
|
|
3559
|
+
/***/ }
|
|
3560
|
+
|
|
3561
|
+
}]);
|
|
3562
|
+
//# sourceMappingURL=node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-2fb422.umd.js.map
|