@livestore/wa-sqlite 0.4.0-dev.21 → 0.4.0-dev.23

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.
Files changed (62) hide show
  1. package/README.md +46 -36
  2. package/dist/README.md +13 -13
  3. package/dist/fts5/wa-sqlite.mjs +1 -1
  4. package/dist/fts5/wa-sqlite.node.mjs +1 -1
  5. package/dist/fts5/wa-sqlite.node.wasm +0 -0
  6. package/dist/fts5/wa-sqlite.wasm +0 -0
  7. package/dist/wa-sqlite-async.mjs +1 -1
  8. package/dist/wa-sqlite-async.wasm +0 -0
  9. package/dist/wa-sqlite-jspi.mjs +1 -1
  10. package/dist/wa-sqlite-jspi.wasm +0 -0
  11. package/dist/wa-sqlite.mjs +1 -1
  12. package/dist/wa-sqlite.node.mjs +1 -1
  13. package/dist/wa-sqlite.node.wasm +0 -0
  14. package/dist/wa-sqlite.wasm +0 -0
  15. package/package.json +40 -29
  16. package/src/FacadeVFS.js +252 -261
  17. package/src/VFS.js +84 -85
  18. package/src/WebLocksMixin.js +357 -351
  19. package/src/examples/AccessHandlePoolVFS.js +185 -194
  20. package/src/examples/IDBBatchAtomicVFS.js +429 -409
  21. package/src/examples/IDBMirrorVFS.js +402 -409
  22. package/src/examples/MemoryAsyncVFS.js +32 -37
  23. package/src/examples/MemoryVFS.js +71 -75
  24. package/src/examples/OPFSAdaptiveVFS.js +206 -206
  25. package/src/examples/OPFSAnyContextVFS.js +141 -140
  26. package/src/examples/OPFSCoopSyncVFS.js +297 -299
  27. package/src/examples/OPFSPermutedVFS.js +529 -540
  28. package/src/examples/README.md +27 -15
  29. package/src/examples/tag.js +27 -27
  30. package/src/sqlite-api.js +910 -941
  31. package/src/sqlite-constants.js +246 -232
  32. package/src/types/globals.d.ts +52 -52
  33. package/src/types/index.d.ts +586 -576
  34. package/test/AccessHandlePoolVFS.test.js +21 -21
  35. package/test/IDBBatchAtomicVFS.test.js +69 -69
  36. package/test/IDBMirrorVFS.test.js +21 -21
  37. package/test/MemoryAsyncVFS.test.js +21 -21
  38. package/test/MemoryVFS.test.js +21 -21
  39. package/test/OPFSAdaptiveVFS.test.js +21 -21
  40. package/test/OPFSAnyContextVFS.test.js +21 -21
  41. package/test/OPFSCoopSyncVFS.test.js +21 -21
  42. package/test/OPFSPermutedVFS.test.js +21 -21
  43. package/test/TestContext.js +44 -41
  44. package/test/WebLocksMixin.test.js +369 -360
  45. package/test/api.test.js +23 -23
  46. package/test/api_exec.js +72 -61
  47. package/test/api_misc.js +53 -54
  48. package/test/api_statements.js +271 -279
  49. package/test/callbacks.test.js +492 -478
  50. package/test/data/idbv5.json +1135 -1
  51. package/test/sql.test.js +30 -30
  52. package/test/sql_0001.js +49 -33
  53. package/test/sql_0002.js +55 -34
  54. package/test/sql_0003.js +85 -49
  55. package/test/sql_0004.js +76 -47
  56. package/test/sql_0005.js +60 -44
  57. package/test/test-worker.js +171 -163
  58. package/test/vfs_xAccess.js +1 -2
  59. package/test/vfs_xClose.js +50 -49
  60. package/test/vfs_xOpen.js +73 -72
  61. package/test/vfs_xRead.js +31 -31
  62. package/test/vfs_xWrite.js +30 -29
package/test/sql_0005.js CHANGED
@@ -1,75 +1,91 @@
1
- import * as Comlink from 'comlink';
1
+ import * as Comlink from 'comlink'
2
2
 
3
3
  export function sql_0005(context) {
4
- describe('sql_0005', function() {
5
- beforeAll(async function() {
4
+ describe('sql_0005', function () {
5
+ beforeAll(async function () {
6
6
  // Clear persistent storage.
7
- const proxy = await context.create();
8
- await context.destroy(proxy);
9
- });
10
-
11
- const cleanup = [];
12
- beforeEach(async function() {
13
- cleanup.splice(0);
14
- });
15
-
16
- afterEach(async function() {
7
+ const proxy = await context.create()
8
+ await context.destroy(proxy)
9
+ })
10
+
11
+ const cleanup = []
12
+ beforeEach(async function () {
13
+ cleanup.splice(0)
14
+ })
15
+
16
+ afterEach(async function () {
17
17
  for (const fn of cleanup) {
18
- await fn();
18
+ await fn()
19
19
  }
20
- });
21
-
22
- it('should transact atomically', async function() {
23
- const instances = [];
20
+ })
21
+
22
+ it('should transact atomically', async function () {
23
+ const instances = []
24
24
  for (let i = 0; i < 8; ++i) {
25
- const proxy = await context.create({ reset: false });
26
- const sqlite3 = proxy.sqlite3;
27
- const db = await sqlite3.open_v2('demo');
28
- instances.push({ sqlite3, db });
25
+ const proxy = await context.create({ reset: false })
26
+ const sqlite3 = proxy.sqlite3
27
+ const db = await sqlite3.open_v2('demo')
28
+ instances.push({ sqlite3, db })
29
29
  cleanup.push(async () => {
30
- await sqlite3.close(db);
31
- await context.destroy(proxy);
32
- });
30
+ await sqlite3.close(db)
31
+ await context.destroy(proxy)
32
+ })
33
33
 
34
34
  if (i === 0) {
35
- await sqlite3.exec(db, `
35
+ await sqlite3.exec(
36
+ db,
37
+ `
36
38
  BEGIN IMMEDIATE;
37
39
  CREATE TABLE IF NOT EXISTS t(key PRIMARY KEY, value);
38
40
  INSERT OR IGNORE INTO t VALUES ('foo', 0);
39
41
  COMMIT;
40
- `);
42
+ `,
43
+ )
41
44
  }
42
45
  }
43
46
 
44
- const iterations = 32;
45
- const values = new Set();
46
- await Promise.all(instances.map(async instance => {
47
- for (let i = 0; i < iterations; ++i) {
48
- const rows = await transact(instance, `
47
+ const iterations = 32
48
+ const values = new Set()
49
+ await Promise.all(
50
+ instances.map(async (instance) => {
51
+ for (let i = 0; i < iterations; ++i) {
52
+ const rows = await transact(
53
+ instance,
54
+ `
49
55
  BEGIN IMMEDIATE;
50
56
  UPDATE t SET value = value + 1 WHERE key = 'foo';
51
57
  SELECT value FROM t WHERE key = 'foo';
52
58
  COMMIT;
53
- `);
54
- values.add(rows[0][0]);
55
- }
56
- }));
59
+ `,
60
+ )
61
+ values.add(rows[0][0])
62
+ }
63
+ }),
64
+ )
57
65
 
58
- expect(values.size).toBe(instances.length * iterations);
59
- expect(Array.from(values).sort((a, b) => b - a).at(0)).toBe(values.size);
60
- });
61
- });
66
+ expect(values.size).toBe(instances.length * iterations)
67
+ expect(
68
+ Array.from(values)
69
+ .sort((a, b) => b - a)
70
+ .at(0),
71
+ ).toBe(values.size)
72
+ })
73
+ })
62
74
  }
63
75
 
64
76
  async function transact({ sqlite3, db }, sql) {
65
77
  while (true) {
66
78
  try {
67
- const rows = [];
68
- await sqlite3.exec(db, sql, Comlink.proxy(row => rows.push(row)));
69
- return rows;
79
+ const rows = []
80
+ await sqlite3.exec(
81
+ db,
82
+ sql,
83
+ Comlink.proxy((row) => rows.push(row)),
84
+ )
85
+ return rows
70
86
  } catch (e) {
71
87
  if (e.message !== 'database is locked') {
72
- throw e;
88
+ throw e
73
89
  }
74
90
  }
75
91
  }
@@ -1,204 +1,212 @@
1
1
  // Copyright 2024 Roy T. Hashimoto. All Rights Reserved.
2
2
 
3
- import * as Comlink from 'comlink';
4
- import * as SQLite from '../src/sqlite-api.js';
3
+ import * as Comlink from 'comlink'
4
+
5
+ import * as SQLite from '../src/sqlite-api.js'
5
6
 
6
7
  const BUILDS = new Map([
7
8
  ['default', '../dist/wa-sqlite.mjs'],
8
9
  ['asyncify', '../dist/wa-sqlite-async.mjs'],
9
10
  ['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
- };
11
+ ])
12
+
13
+ const MODULE = Symbol('module')
14
+ const VFS_CONFIGS = new Map(
15
+ [
16
+ {
17
+ name: 'default',
18
+ vfsModule: null,
19
+ },
20
+ {
21
+ name: 'AccessHandlePoolVFS',
22
+ vfsModule: '../src/examples/AccessHandlePoolVFS.js',
23
+ },
24
+ {
25
+ name: 'OPFSCoopSyncVFS',
26
+ vfsModule: '../src/examples/OPFSCoopSyncVFS.js',
27
+ },
28
+ {
29
+ name: 'FLOOR',
30
+ vfsModule: '../src/examples/FLOOR.js',
31
+ },
32
+ {
33
+ name: 'MemoryVFS',
34
+ vfsModule: '../src/examples/MemoryVFS.js',
35
+ },
36
+ {
37
+ name: 'MemoryAsyncVFS',
38
+ vfsModule: '../src/examples/MemoryAsyncVFS.js',
39
+ },
40
+ {
41
+ name: 'IDBBatchAtomicVFS',
42
+ vfsModule: '../src/examples/IDBBatchAtomicVFS.js',
43
+ },
44
+ {
45
+ name: 'IDBMirrorVFS',
46
+ vfsModule: '../src/examples/IDBMirrorVFS.js',
47
+ },
48
+ {
49
+ name: 'OPFSAdaptiveVFS',
50
+ vfsModule: '../src/examples/OPFSAdaptiveVFS.js',
51
+ },
52
+ {
53
+ name: 'OPFSAnyContextVFS',
54
+ vfsModule: '../src/examples/OPFSAnyContextVFS.js',
55
+ },
56
+ {
57
+ name: 'OPFSPermutedVFS',
58
+ vfsModule: '../src/examples/OPFSPermutedVFS.js',
59
+ },
60
+ ].map((config) => [config.name, config]),
61
+ )
62
+
63
+ const INDEXEDDB_DBNAMES = ['demo']
64
+
65
+ const searchParams = new URLSearchParams(location.search)
66
+
67
+ maybeReset()
68
+ .then(async () => {
69
+ const buildName = searchParams.get('build') || BUILDS.keys().next().value
70
+ const configName = searchParams.get('config') || VFS_CONFIGS.keys().next().value
71
+ const config = VFS_CONFIGS.get(configName)
72
+
73
+ // Instantiate SQLite.
74
+ const { default: moduleFactory } = await import(BUILDS.get(buildName))
75
+ const module = await moduleFactory()
76
+ const sqlite3 = SQLite.Factory(module)
77
+
78
+ const vfs = await (async function () {
79
+ if (config.vfsModule) {
80
+ // Create the VFS and register it as the default file system.
81
+ const namespace = await import(config.vfsModule)
82
+ const className = config.vfsClass ?? config.vfsModule.match(/([^/]+)\.js$/)[1]
83
+ const vfsArgs = (config.vfsArgs ?? ['demo', MODULE]).map((arg) => (arg === MODULE ? module : arg))
84
+ const vfs = await namespace[className].create(...vfsArgs)
85
+ sqlite3.vfs_register(vfs, true)
86
+ return vfs
103
87
  }
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;
88
+ return {}
89
+ })()
90
+
91
+ const sqlite3Proxy = new Proxy(sqlite3, {
92
+ get(target, p, receiver) {
93
+ // Comlink intercepts some function property names, e.g. "bind",
94
+ // so allow aliases to avoid the problem.
95
+ if (typeof p === 'string') p = p.replaceAll('$', '')
96
+
97
+ const value = Reflect.get(target, p, receiver)
98
+ if (typeof value === 'function') {
99
+ return async (...args) => {
100
+ const result = await value.apply(target, args)
101
+ if (p === 'statements') {
102
+ return Comlink.proxy(result)
103
+ }
104
+ return result
121
105
  }
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
- });
106
+ }
107
+ },
108
+ })
109
+
110
+ const vfsProxy = new Proxy(vfs, {
111
+ get(target, p, receiver) {
112
+ const value = Reflect.get(target, p, receiver)
113
+ if (typeof value === 'function') {
114
+ return async (...args) => {
115
+ if (p === 'jRead') {
116
+ // The read buffer Uint8Array will be passed by proxy so all
117
+ // access is asynchronous. Pass a local buffer to the VFS
118
+ // and copy the local buffer to the proxy on completion.
119
+ const proxyBuffer = args[1]
120
+ args[1] = new Uint8Array(await proxyBuffer.length)
121
+ const result = await value.apply(target, args)
122
+ await proxyBuffer.set(args[1])
123
+ return result
124
+ }
125
+ return value.apply(target, args)
126
+ }
127
+ }
128
+ },
129
+ })
130
+
131
+ const { port1, port2 } = new MessageChannel()
132
+ Comlink.expose(
133
+ {
134
+ module,
135
+ sqlite3: sqlite3Proxy,
136
+ vfs: vfsProxy,
137
+ },
138
+ port1,
139
+ )
140
+ postMessage(null, [port2])
141
+ })
142
+ .catch((e) => {
143
+ console.error(e)
144
+ postMessage(cvtErrorToCloneable(e))
145
+ })
139
146
 
140
147
  async function maybeReset() {
141
148
  if (searchParams.get('reset') !== 'true') {
142
- return;
143
- }
144
-
149
+ return
150
+ }
151
+
145
152
  // Limit the amount of time in this function.
146
- const abortController = new AbortController();
147
- setTimeout(() => abortController.abort(), 10_000);
153
+ const abortController = new AbortController()
154
+ setTimeout(() => abortController.abort(), 10_000)
148
155
 
149
156
  // Clear OPFS.
150
- const root = await navigator.storage?.getDirectory();
157
+ const root = await navigator.storage?.getDirectory()
151
158
  if (root) {
152
- let opfsDeleted = false;
159
+ let opfsDeleted = false
153
160
  while (!opfsDeleted) {
154
- abortController.signal.throwIfAborted();
161
+ abortController.signal.throwIfAborted()
155
162
  try {
156
163
  // @ts-ignore
157
164
  for await (const name of root.keys()) {
158
- await root.removeEntry(name, { recursive: true });
165
+ await root.removeEntry(name, { recursive: true })
159
166
  }
160
- opfsDeleted = true;
167
+ opfsDeleted = true
161
168
  } catch (e) {
162
169
  // A NoModificationAllowedError is thrown if an entry can't be
163
170
  // deleted because it isn't closed. Just try again.
164
171
  if (e.name === 'NoModificationAllowedError') {
165
- await new Promise(resolve => setTimeout(resolve));
166
- continue;
172
+ await new Promise((resolve) => setTimeout(resolve))
173
+ continue
167
174
  }
168
- throw e;
175
+ throw e
169
176
  }
170
177
  }
171
178
  }
172
179
 
173
180
  // 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
- }));
181
+ const dbList = indexedDB.databases ? await indexedDB.databases() : INDEXEDDB_DBNAMES.map((name) => ({ name }))
182
+ await Promise.all(
183
+ dbList.map(({ name }) => {
184
+ return new Promise((resolve, reject) => {
185
+ const request = indexedDB.deleteDatabase(name)
186
+ request.onsuccess = resolve
187
+ request.onerror = reject
188
+ })
189
+ }),
190
+ )
184
191
  }
185
192
 
186
193
  function cvtErrorToCloneable(e) {
187
194
  if (e instanceof Error) {
188
195
  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]) => {
196
+ ...['name', 'message', 'stack'].filter((k) => e[k] !== undefined),
197
+ ...Object.getOwnPropertyNames(e),
198
+ ])
199
+ return Object.fromEntries(
200
+ Array.from(props, (k) => [k, e[k]]).filter(([_, v]) => {
194
201
  // Skip any non-cloneable properties.
195
202
  try {
196
- structuredClone(v);
197
- return true;
203
+ structuredClone(v)
204
+ return true
198
205
  } catch (e) {
199
- return false;
206
+ return false
200
207
  }
201
- }));
208
+ }),
209
+ )
202
210
  }
203
- return e;
204
- }
211
+ return e
212
+ }
@@ -1,2 +1 @@
1
- export function vfs_xAccess(context) {
2
- }
1
+ export function vfs_xAccess(context) {}
@@ -1,52 +1,53 @@
1
- import * as Comlink from 'comlink';
2
- import * as VFS from '../src/VFS.js';
1
+ import * as Comlink from 'comlink'
3
2
 
4
- const FILEID = 1;
3
+ import * as VFS from '../src/VFS.js'
4
+
5
+ const FILEID = 1
5
6
 
6
7
  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
- }
8
+ describe('vfs_xClose', function () {
9
+ let proxy, vfs
10
+ beforeEach(async function () {
11
+ proxy = await context.create()
12
+ vfs = proxy.vfs
13
+ })
14
+
15
+ afterEach(async function () {
16
+ await context.destroy(proxy)
17
+ })
18
+
19
+ it('should leave an accessible file', async function () {
20
+ let rc
21
+ const pOpenOutput = Comlink.proxy(new DataView(new ArrayBuffer(4)))
22
+ const openFlags = VFS.SQLITE_OPEN_CREATE | VFS.SQLITE_OPEN_READWRITE
23
+ rc = await vfs.jOpen('test', FILEID, openFlags, pOpenOutput)
24
+ expect(rc).toEqual(VFS.SQLITE_OK)
25
+
26
+ await vfs.jClose(FILEID)
27
+
28
+ const pAccessOutput = Comlink.proxy(new DataView(new ArrayBuffer(4)))
29
+ rc = await vfs.jAccess('test', VFS.SQLITE_ACCESS_READWRITE, pAccessOutput)
30
+ expect(rc).toEqual(VFS.SQLITE_OK)
31
+ expect(pAccessOutput.getInt32(0, true)).not.toEqual(0)
32
+ })
33
+
34
+ it('should delete on close', async function () {
35
+ let rc
36
+ const pOpenOutput = Comlink.proxy(new DataView(new ArrayBuffer(4)))
37
+ const openFlags = VFS.SQLITE_OPEN_CREATE | VFS.SQLITE_OPEN_READWRITE | VFS.SQLITE_OPEN_DELETEONCLOSE
38
+ rc = await vfs.jOpen('test', FILEID, openFlags, pOpenOutput)
39
+ expect(rc).toEqual(VFS.SQLITE_OK)
40
+
41
+ const pAccessOutput = Comlink.proxy(new DataView(new ArrayBuffer(4)))
42
+ rc = await vfs.jAccess('test', VFS.SQLITE_ACCESS_READWRITE, pAccessOutput)
43
+ expect(rc).toEqual(VFS.SQLITE_OK)
44
+ expect(pAccessOutput.getInt32(0, true)).toEqual(1)
45
+
46
+ await vfs.jClose(FILEID)
47
+
48
+ rc = await vfs.jAccess('test', VFS.SQLITE_ACCESS_READWRITE, pAccessOutput)
49
+ expect(rc).toEqual(VFS.SQLITE_OK)
50
+ expect(pAccessOutput.getInt32(0, true)).toEqual(0)
51
+ })
52
+ })
53
+ }