@livestore/wa-sqlite 0.0.0-snapshot-b9a2e1dee494215d8c403be013e25cbf4d2cf380
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/LICENSE +21 -0
- package/README.md +111 -0
- package/dist/README.md +64 -0
- package/dist/fts5/wa-sqlite.mjs +2 -0
- package/dist/fts5/wa-sqlite.node.mjs +2 -0
- package/dist/fts5/wa-sqlite.node.wasm +0 -0
- package/dist/fts5/wa-sqlite.wasm +0 -0
- package/dist/wa-sqlite-async.mjs +2 -0
- package/dist/wa-sqlite-async.wasm +0 -0
- package/dist/wa-sqlite-jspi.mjs +2 -0
- package/dist/wa-sqlite-jspi.wasm +0 -0
- package/dist/wa-sqlite.mjs +2 -0
- package/dist/wa-sqlite.node.mjs +2 -0
- package/dist/wa-sqlite.node.wasm +0 -0
- package/dist/wa-sqlite.wasm +0 -0
- package/package.json +57 -0
- package/src/FacadeVFS.js +681 -0
- package/src/VFS.js +222 -0
- package/src/WebLocksMixin.js +414 -0
- package/src/examples/AccessHandlePoolVFS.js +458 -0
- package/src/examples/IDBBatchAtomicVFS.js +827 -0
- package/src/examples/IDBMirrorVFS.js +889 -0
- package/src/examples/MemoryAsyncVFS.js +100 -0
- package/src/examples/MemoryVFS.js +176 -0
- package/src/examples/OPFSAdaptiveVFS.js +437 -0
- package/src/examples/OPFSAnyContextVFS.js +300 -0
- package/src/examples/OPFSCoopSyncVFS.js +590 -0
- package/src/examples/OPFSPermutedVFS.js +1217 -0
- package/src/examples/README.md +89 -0
- package/src/examples/tag.js +82 -0
- package/src/sqlite-api.js +1339 -0
- package/src/sqlite-constants.js +275 -0
- package/src/types/globals.d.ts +60 -0
- package/src/types/index.d.ts +1531 -0
- package/src/types/tsconfig.json +6 -0
- package/test/AccessHandlePoolVFS.test.js +27 -0
- package/test/IDBBatchAtomicVFS.test.js +97 -0
- package/test/IDBMirrorVFS.test.js +27 -0
- package/test/MemoryAsyncVFS.test.js +27 -0
- package/test/MemoryVFS.test.js +27 -0
- package/test/OPFSAdaptiveVFS.test.js +27 -0
- package/test/OPFSAnyContextVFS.test.js +27 -0
- package/test/OPFSCoopSyncVFS.test.js +27 -0
- package/test/OPFSPermutedVFS.test.js +27 -0
- package/test/TestContext.js +96 -0
- package/test/WebLocksMixin.test.js +521 -0
- package/test/api.test.js +49 -0
- package/test/api_exec.js +89 -0
- package/test/api_misc.js +63 -0
- package/test/api_statements.js +447 -0
- package/test/callbacks.test.js +581 -0
- package/test/data/idbv5.json +1 -0
- package/test/sql.test.js +64 -0
- package/test/sql_0001.js +49 -0
- package/test/sql_0002.js +52 -0
- package/test/sql_0003.js +83 -0
- package/test/sql_0004.js +81 -0
- package/test/sql_0005.js +76 -0
- package/test/test-worker.js +204 -0
- package/test/vfs_xAccess.js +2 -0
- package/test/vfs_xClose.js +52 -0
- package/test/vfs_xOpen.js +91 -0
- package/test/vfs_xRead.js +38 -0
- package/test/vfs_xWrite.js +36 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
// Copyright 2024 Roy T. Hashimoto. All Rights Reserved.
|
|
2
|
+
|
|
3
|
+
import * as Comlink from 'comlink';
|
|
4
|
+
import * as SQLite from '../src/sqlite-api.js';
|
|
5
|
+
|
|
6
|
+
const BUILDS = new Map([
|
|
7
|
+
['default', '../dist/wa-sqlite.mjs'],
|
|
8
|
+
['asyncify', '../dist/wa-sqlite-async.mjs'],
|
|
9
|
+
['jspi', '../dist/wa-sqlite-jspi.mjs'],
|
|
10
|
+
]);
|
|
11
|
+
|
|
12
|
+
const MODULE = Symbol('module');
|
|
13
|
+
const VFS_CONFIGS = new Map([
|
|
14
|
+
{
|
|
15
|
+
name: 'default',
|
|
16
|
+
vfsModule: null
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: 'AccessHandlePoolVFS',
|
|
20
|
+
vfsModule: '../src/examples/AccessHandlePoolVFS.js',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: 'OPFSCoopSyncVFS',
|
|
24
|
+
vfsModule: '../src/examples/OPFSCoopSyncVFS.js',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'FLOOR',
|
|
28
|
+
vfsModule: '../src/examples/FLOOR.js',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'MemoryVFS',
|
|
32
|
+
vfsModule: '../src/examples/MemoryVFS.js',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: 'MemoryAsyncVFS',
|
|
36
|
+
vfsModule: '../src/examples/MemoryAsyncVFS.js',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'IDBBatchAtomicVFS',
|
|
40
|
+
vfsModule: '../src/examples/IDBBatchAtomicVFS.js',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'IDBMirrorVFS',
|
|
44
|
+
vfsModule: '../src/examples/IDBMirrorVFS.js',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: 'OPFSAdaptiveVFS',
|
|
48
|
+
vfsModule: '../src/examples/OPFSAdaptiveVFS.js',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'OPFSAnyContextVFS',
|
|
52
|
+
vfsModule: '../src/examples/OPFSAnyContextVFS.js',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: 'OPFSPermutedVFS',
|
|
56
|
+
vfsModule: '../src/examples/OPFSPermutedVFS.js',
|
|
57
|
+
},
|
|
58
|
+
].map(config => [config.name, config]));
|
|
59
|
+
|
|
60
|
+
const INDEXEDDB_DBNAMES = ['demo'];
|
|
61
|
+
|
|
62
|
+
const searchParams = new URLSearchParams(location.search);
|
|
63
|
+
|
|
64
|
+
maybeReset().then(async () => {
|
|
65
|
+
const buildName = searchParams.get('build') || BUILDS.keys().next().value;
|
|
66
|
+
const configName = searchParams.get('config') || VFS_CONFIGS.keys().next().value;
|
|
67
|
+
const config = VFS_CONFIGS.get(configName);
|
|
68
|
+
|
|
69
|
+
// Instantiate SQLite.
|
|
70
|
+
const { default: moduleFactory } = await import(BUILDS.get(buildName));
|
|
71
|
+
const module = await moduleFactory();
|
|
72
|
+
const sqlite3 = SQLite.Factory(module);
|
|
73
|
+
|
|
74
|
+
const vfs = await (async function() {
|
|
75
|
+
if (config.vfsModule) {
|
|
76
|
+
// Create the VFS and register it as the default file system.
|
|
77
|
+
const namespace = await import(config.vfsModule);
|
|
78
|
+
const className = config.vfsClass ?? config.vfsModule.match(/([^/]+)\.js$/)[1];
|
|
79
|
+
const vfsArgs = (config.vfsArgs ?? ['demo', MODULE])
|
|
80
|
+
.map(arg => arg === MODULE ? module : arg);
|
|
81
|
+
const vfs = await namespace[className].create(...vfsArgs);
|
|
82
|
+
sqlite3.vfs_register(vfs, true);
|
|
83
|
+
return vfs;
|
|
84
|
+
}
|
|
85
|
+
return {};
|
|
86
|
+
})();
|
|
87
|
+
|
|
88
|
+
const sqlite3Proxy = new Proxy(sqlite3, {
|
|
89
|
+
get(target, p, receiver) {
|
|
90
|
+
// Comlink intercepts some function property names, e.g. "bind",
|
|
91
|
+
// so allow aliases to avoid the problem.
|
|
92
|
+
if (typeof p === 'string') p = p.replaceAll('$', '');
|
|
93
|
+
|
|
94
|
+
const value = Reflect.get(target, p, receiver);
|
|
95
|
+
if (typeof value === 'function') {
|
|
96
|
+
return async (...args) => {
|
|
97
|
+
const result = await value.apply(target, args);
|
|
98
|
+
if (p === 'statements') {
|
|
99
|
+
return Comlink.proxy(result);
|
|
100
|
+
}
|
|
101
|
+
return result;
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const vfsProxy = new Proxy(vfs, {
|
|
108
|
+
get(target, p, receiver) {
|
|
109
|
+
const value = Reflect.get(target, p, receiver);
|
|
110
|
+
if (typeof value === 'function') {
|
|
111
|
+
return async (...args) => {
|
|
112
|
+
if (p === 'jRead') {
|
|
113
|
+
// The read buffer Uint8Array will be passed by proxy so all
|
|
114
|
+
// access is asynchronous. Pass a local buffer to the VFS
|
|
115
|
+
// and copy the local buffer to the proxy on completion.
|
|
116
|
+
const proxyBuffer = args[1];
|
|
117
|
+
args[1] = new Uint8Array(await proxyBuffer.length);
|
|
118
|
+
const result = await value.apply(target, args);
|
|
119
|
+
await proxyBuffer.set(args[1]);
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
return value.apply(target, args);
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
const { port1, port2 } = new MessageChannel();
|
|
129
|
+
Comlink.expose({
|
|
130
|
+
module,
|
|
131
|
+
sqlite3: sqlite3Proxy,
|
|
132
|
+
vfs: vfsProxy,
|
|
133
|
+
}, port1);
|
|
134
|
+
postMessage(null, [port2]);
|
|
135
|
+
}).catch(e => {
|
|
136
|
+
console.error(e);
|
|
137
|
+
postMessage(cvtErrorToCloneable(e));
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
async function maybeReset() {
|
|
141
|
+
if (searchParams.get('reset') !== 'true') {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Limit the amount of time in this function.
|
|
146
|
+
const abortController = new AbortController();
|
|
147
|
+
setTimeout(() => abortController.abort(), 10_000);
|
|
148
|
+
|
|
149
|
+
// Clear OPFS.
|
|
150
|
+
const root = await navigator.storage?.getDirectory();
|
|
151
|
+
if (root) {
|
|
152
|
+
let opfsDeleted = false;
|
|
153
|
+
while (!opfsDeleted) {
|
|
154
|
+
abortController.signal.throwIfAborted();
|
|
155
|
+
try {
|
|
156
|
+
// @ts-ignore
|
|
157
|
+
for await (const name of root.keys()) {
|
|
158
|
+
await root.removeEntry(name, { recursive: true });
|
|
159
|
+
}
|
|
160
|
+
opfsDeleted = true;
|
|
161
|
+
} catch (e) {
|
|
162
|
+
// A NoModificationAllowedError is thrown if an entry can't be
|
|
163
|
+
// deleted because it isn't closed. Just try again.
|
|
164
|
+
if (e.name === 'NoModificationAllowedError') {
|
|
165
|
+
await new Promise(resolve => setTimeout(resolve));
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
throw e;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Clear IndexedDB.
|
|
174
|
+
const dbList = indexedDB.databases ?
|
|
175
|
+
await indexedDB.databases() :
|
|
176
|
+
INDEXEDDB_DBNAMES.map(name => ({ name }));
|
|
177
|
+
await Promise.all(dbList.map(({name}) => {
|
|
178
|
+
return new Promise((resolve, reject) => {
|
|
179
|
+
const request = indexedDB.deleteDatabase(name);
|
|
180
|
+
request.onsuccess = resolve;
|
|
181
|
+
request.onerror = reject;
|
|
182
|
+
});
|
|
183
|
+
}));
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function cvtErrorToCloneable(e) {
|
|
187
|
+
if (e instanceof Error) {
|
|
188
|
+
const props = new Set([
|
|
189
|
+
...['name', 'message', 'stack'].filter(k => e[k] !== undefined),
|
|
190
|
+
...Object.getOwnPropertyNames(e)
|
|
191
|
+
]);
|
|
192
|
+
return Object.fromEntries(Array.from(props, k => [k, e[k]])
|
|
193
|
+
.filter(([_, v]) => {
|
|
194
|
+
// Skip any non-cloneable properties.
|
|
195
|
+
try {
|
|
196
|
+
structuredClone(v);
|
|
197
|
+
return true;
|
|
198
|
+
} catch (e) {
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
}));
|
|
202
|
+
}
|
|
203
|
+
return e;
|
|
204
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as Comlink from 'comlink';
|
|
2
|
+
import * as VFS from '../src/VFS.js';
|
|
3
|
+
|
|
4
|
+
const FILEID = 1;
|
|
5
|
+
|
|
6
|
+
export function vfs_xClose(context) {
|
|
7
|
+
describe('vfs_xClose', function() {
|
|
8
|
+
let proxy, vfs;
|
|
9
|
+
beforeEach(async function() {
|
|
10
|
+
proxy = await context.create();
|
|
11
|
+
vfs = proxy.vfs;
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
afterEach(async function() {
|
|
15
|
+
await context.destroy(proxy);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should leave an accessible file', async function() {
|
|
19
|
+
let rc;
|
|
20
|
+
const pOpenOutput = Comlink.proxy(new DataView(new ArrayBuffer(4)));
|
|
21
|
+
const openFlags = VFS.SQLITE_OPEN_CREATE | VFS.SQLITE_OPEN_READWRITE;
|
|
22
|
+
rc = await vfs.jOpen('test', FILEID, openFlags, pOpenOutput);
|
|
23
|
+
expect(rc).toEqual(VFS.SQLITE_OK);
|
|
24
|
+
|
|
25
|
+
await vfs.jClose(FILEID);
|
|
26
|
+
|
|
27
|
+
const pAccessOutput = Comlink.proxy(new DataView(new ArrayBuffer(4)));
|
|
28
|
+
rc = await vfs.jAccess('test', VFS.SQLITE_ACCESS_READWRITE, pAccessOutput);
|
|
29
|
+
expect(rc).toEqual(VFS.SQLITE_OK);
|
|
30
|
+
expect(pAccessOutput.getInt32(0, true)).not.toEqual(0);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should delete on close', async function() {
|
|
34
|
+
let rc;
|
|
35
|
+
const pOpenOutput = Comlink.proxy(new DataView(new ArrayBuffer(4)));
|
|
36
|
+
const openFlags = VFS.SQLITE_OPEN_CREATE | VFS.SQLITE_OPEN_READWRITE | VFS.SQLITE_OPEN_DELETEONCLOSE;
|
|
37
|
+
rc = await vfs.jOpen('test', FILEID, openFlags, pOpenOutput);
|
|
38
|
+
expect(rc).toEqual(VFS.SQLITE_OK);
|
|
39
|
+
|
|
40
|
+
const pAccessOutput = Comlink.proxy(new DataView(new ArrayBuffer(4)));
|
|
41
|
+
rc = await vfs.jAccess('test', VFS.SQLITE_ACCESS_READWRITE, pAccessOutput);
|
|
42
|
+
expect(rc).toEqual(VFS.SQLITE_OK);
|
|
43
|
+
expect(pAccessOutput.getInt32(0, true)).toEqual(1);
|
|
44
|
+
|
|
45
|
+
await vfs.jClose(FILEID);
|
|
46
|
+
|
|
47
|
+
rc = await vfs.jAccess('test', VFS.SQLITE_ACCESS_READWRITE, pAccessOutput);
|
|
48
|
+
expect(rc).toEqual(VFS.SQLITE_OK);
|
|
49
|
+
expect(pAccessOutput.getInt32(0, true)).toEqual(0);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import * as Comlink from 'comlink';
|
|
2
|
+
import * as VFS from '../src/VFS.js';
|
|
3
|
+
|
|
4
|
+
const FILEID = 1;
|
|
5
|
+
|
|
6
|
+
export function vfs_xOpen(context) {
|
|
7
|
+
describe('vfs_xOpen', function() {
|
|
8
|
+
let proxy, vfs;
|
|
9
|
+
beforeEach(async function() {
|
|
10
|
+
proxy = await context.create();
|
|
11
|
+
vfs = proxy.vfs;
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
afterEach(async function() {
|
|
15
|
+
await context.destroy(proxy);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should create a file', async function() {
|
|
19
|
+
let rc;
|
|
20
|
+
const pOpenOutput = Comlink.proxy(new DataView(new ArrayBuffer(4)));
|
|
21
|
+
const openFlags = VFS.SQLITE_OPEN_CREATE | VFS.SQLITE_OPEN_READWRITE;
|
|
22
|
+
rc = await vfs.jOpen('test', FILEID, openFlags, pOpenOutput);
|
|
23
|
+
expect(rc).toEqual(VFS.SQLITE_OK);
|
|
24
|
+
expect(pOpenOutput.getInt32(0, true)).toEqual(openFlags);
|
|
25
|
+
|
|
26
|
+
const pAccessOutput = Comlink.proxy(new DataView(new ArrayBuffer(4)));
|
|
27
|
+
rc = await vfs.jAccess('test', VFS.SQLITE_ACCESS_READWRITE, pAccessOutput);
|
|
28
|
+
expect(rc).toEqual(VFS.SQLITE_OK);
|
|
29
|
+
expect(pAccessOutput.getInt32(0, true)).not.toEqual(0);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should create a database file', async function() {
|
|
33
|
+
let rc;
|
|
34
|
+
const pOpenOutput = Comlink.proxy(new DataView(new ArrayBuffer(4)));
|
|
35
|
+
const openFlags = VFS.SQLITE_OPEN_CREATE | VFS.SQLITE_OPEN_READWRITE | VFS.SQLITE_OPEN_MAIN_DB;
|
|
36
|
+
|
|
37
|
+
do {
|
|
38
|
+
const nRetryOps = await proxy.module.retryOps.length;
|
|
39
|
+
for (let i = 0; i < nRetryOps; i++) {
|
|
40
|
+
await proxy.module.retryOps[i];
|
|
41
|
+
}
|
|
42
|
+
rc = await vfs.jOpen('test', 1, openFlags, pOpenOutput);
|
|
43
|
+
} while (rc === VFS.SQLITE_BUSY);
|
|
44
|
+
expect(rc).toEqual(VFS.SQLITE_OK);
|
|
45
|
+
expect(pOpenOutput.getInt32(0, true)).toEqual(openFlags);
|
|
46
|
+
|
|
47
|
+
const pAccessOutput = Comlink.proxy(new DataView(new ArrayBuffer(4)));
|
|
48
|
+
rc = await vfs.jAccess('test', VFS.SQLITE_ACCESS_READWRITE, pAccessOutput);
|
|
49
|
+
expect(rc).toEqual(VFS.SQLITE_OK);
|
|
50
|
+
expect(pAccessOutput.getInt32(0, true)).not.toEqual(0);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('should not create a file', async function() {
|
|
54
|
+
let rc;
|
|
55
|
+
const pOpenOutput = Comlink.proxy(new DataView(new ArrayBuffer(4)));
|
|
56
|
+
const openFlags = VFS.SQLITE_OPEN_READWRITE;
|
|
57
|
+
rc = await vfs.jOpen('test', 1, openFlags, pOpenOutput);
|
|
58
|
+
expect(rc).toEqual(VFS.SQLITE_CANTOPEN);
|
|
59
|
+
|
|
60
|
+
const pAccessOutput = Comlink.proxy(new DataView(new ArrayBuffer(4)));
|
|
61
|
+
rc = await vfs.jAccess('test', VFS.SQLITE_ACCESS_READWRITE, pAccessOutput);
|
|
62
|
+
expect(rc).toEqual(VFS.SQLITE_OK);
|
|
63
|
+
expect(pAccessOutput.getInt32(0, true)).toEqual(0);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should open an existing file', async function() {
|
|
67
|
+
let rc;
|
|
68
|
+
const pOpenOutput = Comlink.proxy(new DataView(new ArrayBuffer(4)));
|
|
69
|
+
const openFlags = VFS.SQLITE_OPEN_CREATE | VFS.SQLITE_OPEN_READWRITE;
|
|
70
|
+
rc = await vfs.jOpen('test', FILEID, openFlags, pOpenOutput);
|
|
71
|
+
expect(rc).toEqual(VFS.SQLITE_OK);
|
|
72
|
+
|
|
73
|
+
// Close the file because some VFS implementations don't allow
|
|
74
|
+
// multiple open handles.
|
|
75
|
+
await vfs.jClose(FILEID);
|
|
76
|
+
|
|
77
|
+
rc = await vfs.jOpen('test', FILEID, VFS.SQLITE_OPEN_READWRITE, pOpenOutput);
|
|
78
|
+
expect(rc).toEqual(VFS.SQLITE_OK);
|
|
79
|
+
expect(pOpenOutput.getInt32(0, true)).toEqual(VFS.SQLITE_OPEN_READWRITE);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('should create an anonymous file', async function() {
|
|
83
|
+
let rc;
|
|
84
|
+
const pOpenOutput = Comlink.proxy(new DataView(new ArrayBuffer(4)));
|
|
85
|
+
const openFlags = VFS.SQLITE_OPEN_CREATE | VFS.SQLITE_OPEN_READWRITE;
|
|
86
|
+
rc = await vfs.jOpen(null, FILEID, openFlags, pOpenOutput);
|
|
87
|
+
expect(rc).toEqual(VFS.SQLITE_OK);
|
|
88
|
+
expect(pOpenOutput.getInt32(0, true)).toEqual(openFlags);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as Comlink from 'comlink';
|
|
2
|
+
import * as VFS from '../src/VFS.js';
|
|
3
|
+
|
|
4
|
+
const FILEID = 1;
|
|
5
|
+
|
|
6
|
+
export function vfs_xRead(context) {
|
|
7
|
+
describe('vfs_xRead', function() {
|
|
8
|
+
let proxy, vfs;
|
|
9
|
+
beforeEach(async function() {
|
|
10
|
+
proxy = await context.create();
|
|
11
|
+
vfs = proxy.vfs;
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
afterEach(async function() {
|
|
15
|
+
await context.destroy(proxy);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should signal short read', async function() {
|
|
19
|
+
let rc;
|
|
20
|
+
const pOpenOutput = Comlink.proxy(new DataView(new ArrayBuffer(4)));
|
|
21
|
+
const openFlags = VFS.SQLITE_OPEN_CREATE | VFS.SQLITE_OPEN_READWRITE;
|
|
22
|
+
rc = await vfs.jOpen('test', FILEID, openFlags, pOpenOutput);
|
|
23
|
+
expect(rc).toEqual(VFS.SQLITE_OK);
|
|
24
|
+
|
|
25
|
+
const pData = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
|
|
26
|
+
const iOffset = 0;
|
|
27
|
+
rc = await vfs.jWrite(FILEID, pData, iOffset);
|
|
28
|
+
expect(rc).toEqual(VFS.SQLITE_OK);
|
|
29
|
+
|
|
30
|
+
const pReadData = Comlink.proxy(new Uint8Array(pData.length * 2).fill(0xfb));
|
|
31
|
+
rc = await vfs.jRead(FILEID, pReadData, iOffset);
|
|
32
|
+
expect(rc).toEqual(VFS.SQLITE_IOERR_SHORT_READ);
|
|
33
|
+
expect(pReadData.subarray(0, pData.length)).toEqual(pData);
|
|
34
|
+
expect(pReadData.subarray(pData.length))
|
|
35
|
+
.toEqual(new Uint8Array(pReadData.length - pData.length));
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as Comlink from 'comlink';
|
|
2
|
+
import * as VFS from '../src/VFS.js';
|
|
3
|
+
|
|
4
|
+
const FILEID = 1;
|
|
5
|
+
|
|
6
|
+
export function vfs_xWrite(context) {
|
|
7
|
+
describe('vfs_xWrite', function() {
|
|
8
|
+
let proxy, vfs;
|
|
9
|
+
beforeEach(async function() {
|
|
10
|
+
proxy = await context.create();
|
|
11
|
+
vfs = proxy.vfs;
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
afterEach(async function() {
|
|
15
|
+
await context.destroy(proxy);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should round-trip data', async function() {
|
|
19
|
+
let rc;
|
|
20
|
+
const pOpenOutput = Comlink.proxy(new DataView(new ArrayBuffer(4)));
|
|
21
|
+
const openFlags = VFS.SQLITE_OPEN_CREATE | VFS.SQLITE_OPEN_READWRITE;
|
|
22
|
+
rc = await vfs.jOpen('test', FILEID, openFlags, pOpenOutput);
|
|
23
|
+
expect(rc).toEqual(VFS.SQLITE_OK);
|
|
24
|
+
|
|
25
|
+
const pData = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
|
|
26
|
+
const iOffset = 0;
|
|
27
|
+
rc = await vfs.jWrite(FILEID, pData, iOffset);
|
|
28
|
+
expect(rc).toEqual(VFS.SQLITE_OK);
|
|
29
|
+
|
|
30
|
+
const pReadData = Comlink.proxy(new Uint8Array(pData.length));
|
|
31
|
+
rc = await vfs.jRead(FILEID, pReadData, iOffset);
|
|
32
|
+
expect(rc).toEqual(VFS.SQLITE_OK);
|
|
33
|
+
expect([...pReadData]).toEqual([...pData]);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
}
|