@livestore/wa-sqlite 0.4.0-dev.22 → 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.
- package/README.md +46 -36
- package/dist/README.md +13 -13
- package/dist/fts5/wa-sqlite.mjs +1 -1
- package/dist/fts5/wa-sqlite.node.mjs +1 -1
- package/dist/fts5/wa-sqlite.node.wasm +0 -0
- package/dist/fts5/wa-sqlite.wasm +0 -0
- package/dist/wa-sqlite-async.mjs +1 -1
- package/dist/wa-sqlite-async.wasm +0 -0
- package/dist/wa-sqlite-jspi.mjs +1 -1
- package/dist/wa-sqlite-jspi.wasm +0 -0
- package/dist/wa-sqlite.mjs +1 -1
- package/dist/wa-sqlite.node.mjs +1 -1
- package/dist/wa-sqlite.node.wasm +0 -0
- package/dist/wa-sqlite.wasm +0 -0
- package/package.json +40 -29
- package/src/FacadeVFS.js +252 -261
- package/src/VFS.js +84 -85
- package/src/WebLocksMixin.js +357 -351
- package/src/examples/AccessHandlePoolVFS.js +185 -194
- package/src/examples/IDBBatchAtomicVFS.js +429 -409
- package/src/examples/IDBMirrorVFS.js +402 -409
- package/src/examples/MemoryAsyncVFS.js +32 -37
- package/src/examples/MemoryVFS.js +71 -75
- package/src/examples/OPFSAdaptiveVFS.js +206 -206
- package/src/examples/OPFSAnyContextVFS.js +141 -140
- package/src/examples/OPFSCoopSyncVFS.js +297 -299
- package/src/examples/OPFSPermutedVFS.js +529 -540
- package/src/examples/README.md +27 -15
- package/src/examples/tag.js +27 -27
- package/src/sqlite-api.js +910 -941
- package/src/sqlite-constants.js +246 -232
- package/src/types/globals.d.ts +52 -52
- package/src/types/index.d.ts +586 -576
- package/test/AccessHandlePoolVFS.test.js +21 -21
- package/test/IDBBatchAtomicVFS.test.js +69 -69
- package/test/IDBMirrorVFS.test.js +21 -21
- package/test/MemoryAsyncVFS.test.js +21 -21
- package/test/MemoryVFS.test.js +21 -21
- package/test/OPFSAdaptiveVFS.test.js +21 -21
- package/test/OPFSAnyContextVFS.test.js +21 -21
- package/test/OPFSCoopSyncVFS.test.js +21 -21
- package/test/OPFSPermutedVFS.test.js +21 -21
- package/test/TestContext.js +44 -41
- package/test/WebLocksMixin.test.js +369 -360
- package/test/api.test.js +23 -23
- package/test/api_exec.js +72 -61
- package/test/api_misc.js +53 -54
- package/test/api_statements.js +271 -279
- package/test/callbacks.test.js +492 -478
- package/test/data/idbv5.json +1135 -1
- package/test/sql.test.js +30 -30
- package/test/sql_0001.js +49 -33
- package/test/sql_0002.js +55 -34
- package/test/sql_0003.js +85 -49
- package/test/sql_0004.js +76 -47
- package/test/sql_0005.js +60 -44
- package/test/test-worker.js +171 -163
- package/test/vfs_xAccess.js +1 -2
- package/test/vfs_xClose.js +50 -49
- package/test/vfs_xOpen.js +73 -72
- package/test/vfs_xRead.js +31 -31
- 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(
|
|
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(
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
69
|
-
|
|
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
|
}
|
package/test/test-worker.js
CHANGED
|
@@ -1,204 +1,212 @@
|
|
|
1
1
|
// Copyright 2024 Roy T. Hashimoto. All Rights Reserved.
|
|
2
2
|
|
|
3
|
-
import * as Comlink from 'comlink'
|
|
4
|
-
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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(
|
|
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
|
+
}
|
package/test/vfs_xAccess.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export function vfs_xAccess(context) {
|
|
2
|
-
}
|
|
1
|
+
export function vfs_xAccess(context) {}
|
package/test/vfs_xClose.js
CHANGED
|
@@ -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
|
-
|
|
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
|
+
}
|