koffi 2.2.1 → 2.2.2-beta.1

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 (74) hide show
  1. package/package.json +1 -1
  2. package/src/koffi/build/2.2.2-beta.1/koffi_darwin_arm64.tar.gz +0 -0
  3. package/src/koffi/build/2.2.2-beta.1/koffi_darwin_x64.tar.gz +0 -0
  4. package/src/koffi/build/2.2.2-beta.1/koffi_freebsd_arm64.tar.gz +0 -0
  5. package/src/koffi/build/2.2.2-beta.1/koffi_freebsd_ia32.tar.gz +0 -0
  6. package/src/koffi/build/2.2.2-beta.1/koffi_freebsd_x64.tar.gz +0 -0
  7. package/src/koffi/build/2.2.2-beta.1/koffi_linux_arm32hf.tar.gz +0 -0
  8. package/src/koffi/build/2.2.2-beta.1/koffi_linux_arm64.tar.gz +0 -0
  9. package/src/koffi/build/2.2.2-beta.1/koffi_linux_ia32.tar.gz +0 -0
  10. package/src/koffi/build/2.2.2-beta.1/koffi_linux_riscv64hf64.tar.gz +0 -0
  11. package/src/koffi/build/2.2.2-beta.1/koffi_linux_x64.tar.gz +0 -0
  12. package/src/koffi/build/2.2.2-beta.1/koffi_openbsd_ia32.tar.gz +0 -0
  13. package/src/koffi/build/2.2.2-beta.1/koffi_openbsd_x64.tar.gz +0 -0
  14. package/src/koffi/build/2.2.2-beta.1/koffi_win32_arm64.tar.gz +0 -0
  15. package/src/koffi/build/2.2.2-beta.1/koffi_win32_ia32.tar.gz +0 -0
  16. package/src/koffi/build/2.2.2-beta.1/koffi_win32_x64.tar.gz +0 -0
  17. package/src/koffi/qemu/qemu.js +12 -10
  18. package/src/koffi/src/abi_arm32.cc +7 -12
  19. package/src/koffi/src/abi_arm64.cc +7 -12
  20. package/src/koffi/src/abi_riscv64.cc +7 -12
  21. package/src/koffi/src/abi_x64_sysv.cc +7 -12
  22. package/src/koffi/src/abi_x64_win.cc +7 -12
  23. package/src/koffi/src/abi_x86.cc +7 -12
  24. package/src/koffi/src/call.cc +51 -2
  25. package/src/koffi/src/call.hh +6 -1
  26. package/src/koffi/src/ffi.cc +61 -7
  27. package/src/koffi/src/ffi.hh +2 -0
  28. package/src/koffi/src/index.js +6 -2
  29. package/src/koffi/test/CMakeLists.txt +1 -1
  30. package/src/koffi/test/async.js +3 -0
  31. package/src/koffi/test/callbacks.js +11 -0
  32. package/vendor/{sqlite3mc → sqlite3}/sqlite3.c +139 -43
  33. package/vendor/{sqlite3mc → sqlite3}/sqlite3.h +10 -3
  34. package/vendor/{sqlite3mc → sqlite3}/sqlite3ext.h +0 -0
  35. package/vendor/{sqlite3mc → sqlite3}/sqlite3mc.c +156 -53
  36. package/vendor/{sqlite3mc → sqlite3}/sqlite3mc.def +0 -0
  37. package/vendor/{sqlite3mc → sqlite3}/sqlite3mc.h +12 -5
  38. package/vendor/sqlite3/wasm/README.txt +23 -0
  39. package/vendor/sqlite3/wasm/common/SqliteTestUtil.js +236 -0
  40. package/vendor/sqlite3/wasm/common/emscripten.css +24 -0
  41. package/vendor/sqlite3/wasm/common/testing.css +63 -0
  42. package/vendor/sqlite3/wasm/demo-123-worker.html +44 -0
  43. package/vendor/sqlite3/wasm/demo-123.html +24 -0
  44. package/vendor/sqlite3/wasm/demo-123.js +289 -0
  45. package/vendor/sqlite3/wasm/demo-jsstorage.html +49 -0
  46. package/vendor/sqlite3/wasm/demo-jsstorage.js +114 -0
  47. package/vendor/sqlite3/wasm/demo-worker1-promiser.html +34 -0
  48. package/vendor/sqlite3/wasm/demo-worker1-promiser.js +270 -0
  49. package/vendor/sqlite3/wasm/demo-worker1.html +34 -0
  50. package/vendor/sqlite3/wasm/demo-worker1.js +345 -0
  51. package/vendor/sqlite3/wasm/index.html +90 -0
  52. package/vendor/sqlite3/wasm/jswasm/sqlite3-opfs-async-proxy.js +830 -0
  53. package/vendor/sqlite3/wasm/jswasm/sqlite3-worker1-promiser.js +259 -0
  54. package/vendor/sqlite3/wasm/jswasm/sqlite3-worker1.js +49 -0
  55. package/vendor/sqlite3/wasm/jswasm/sqlite3.js +10119 -0
  56. package/vendor/sqlite3/wasm/jswasm/sqlite3.wasm +0 -0
  57. package/vendor/sqlite3/wasm/tester1-worker.html +63 -0
  58. package/vendor/sqlite3/wasm/tester1.html +28 -0
  59. package/vendor/sqlite3/wasm/tester1.js +1864 -0
  60. package/src/koffi/build/2.2.1/koffi_darwin_arm64.tar.gz +0 -0
  61. package/src/koffi/build/2.2.1/koffi_darwin_x64.tar.gz +0 -0
  62. package/src/koffi/build/2.2.1/koffi_freebsd_arm64.tar.gz +0 -0
  63. package/src/koffi/build/2.2.1/koffi_freebsd_ia32.tar.gz +0 -0
  64. package/src/koffi/build/2.2.1/koffi_freebsd_x64.tar.gz +0 -0
  65. package/src/koffi/build/2.2.1/koffi_linux_arm32hf.tar.gz +0 -0
  66. package/src/koffi/build/2.2.1/koffi_linux_arm64.tar.gz +0 -0
  67. package/src/koffi/build/2.2.1/koffi_linux_ia32.tar.gz +0 -0
  68. package/src/koffi/build/2.2.1/koffi_linux_riscv64hf64.tar.gz +0 -0
  69. package/src/koffi/build/2.2.1/koffi_linux_x64.tar.gz +0 -0
  70. package/src/koffi/build/2.2.1/koffi_openbsd_ia32.tar.gz +0 -0
  71. package/src/koffi/build/2.2.1/koffi_openbsd_x64.tar.gz +0 -0
  72. package/src/koffi/build/2.2.1/koffi_win32_arm64.tar.gz +0 -0
  73. package/src/koffi/build/2.2.1/koffi_win32_ia32.tar.gz +0 -0
  74. package/src/koffi/build/2.2.1/koffi_win32_x64.tar.gz +0 -0
@@ -0,0 +1,345 @@
1
+ /*
2
+ 2022-05-22
3
+
4
+ The author disclaims copyright to this source code. In place of a
5
+ legal notice, here is a blessing:
6
+
7
+ * May you do good and not evil.
8
+ * May you find forgiveness for yourself and forgive others.
9
+ * May you share freely, never taking more than you give.
10
+
11
+ ***********************************************************************
12
+
13
+ A basic test script for sqlite3-worker1.js.
14
+
15
+ Note that the wrapper interface demonstrated in
16
+ demo-worker1-promiser.js is much easier to use from client code, as it
17
+ lacks the message-passing acrobatics demonstrated in this file.
18
+ */
19
+ 'use strict';
20
+ (function(){
21
+ const T = self.SqliteTestUtil;
22
+ const SW = new Worker("jswasm/sqlite3-worker1.js");
23
+ const DbState = {
24
+ id: undefined
25
+ };
26
+ const eOutput = document.querySelector('#test-output');
27
+ const log = console.log.bind(console);
28
+ const logHtml = function(cssClass,...args){
29
+ log.apply(this, args);
30
+ const ln = document.createElement('div');
31
+ if(cssClass) ln.classList.add(cssClass);
32
+ ln.append(document.createTextNode(args.join(' ')));
33
+ eOutput.append(ln);
34
+ };
35
+ const warn = console.warn.bind(console);
36
+ const error = console.error.bind(console);
37
+ const toss = (...args)=>{throw new Error(args.join(' '))};
38
+
39
+ SW.onerror = function(event){
40
+ error("onerror",event);
41
+ };
42
+
43
+ let startTime;
44
+
45
+ /**
46
+ A queue for callbacks which are to be run in response to async
47
+ DB commands. See the notes in runTests() for why we need
48
+ this. The event-handling plumbing of this file requires that
49
+ any DB command which includes a `messageId` property also have
50
+ a queued callback entry, as the existence of that property in
51
+ response payloads is how it knows whether or not to shift an
52
+ entry off of the queue.
53
+ */
54
+ const MsgHandlerQueue = {
55
+ queue: [],
56
+ id: 0,
57
+ push: function(type,callback){
58
+ this.queue.push(callback);
59
+ return type + '-' + (++this.id);
60
+ },
61
+ shift: function(){
62
+ return this.queue.shift();
63
+ }
64
+ };
65
+
66
+ const testCount = ()=>{
67
+ logHtml("","Total test count:",T.counter+". Total time =",(performance.now() - startTime),"ms");
68
+ };
69
+
70
+ const logEventResult = function(ev){
71
+ const evd = ev.result;
72
+ logHtml(evd.errorClass ? 'error' : '',
73
+ "runOneTest",ev.messageId,"Worker time =",
74
+ (ev.workerRespondTime - ev.workerReceivedTime),"ms.",
75
+ "Round-trip event time =",
76
+ (performance.now() - ev.departureTime),"ms.",
77
+ (evd.errorClass ? ev.message : "")//, JSON.stringify(evd)
78
+ );
79
+ };
80
+
81
+ const runOneTest = function(eventType, eventArgs, callback){
82
+ T.assert(eventArgs && 'object'===typeof eventArgs);
83
+ /* ^^^ that is for the testing and messageId-related code, not
84
+ a hard requirement of all of the Worker-exposed APIs. */
85
+ const messageId = MsgHandlerQueue.push(eventType,function(ev){
86
+ logEventResult(ev);
87
+ if(callback instanceof Function){
88
+ callback(ev);
89
+ testCount();
90
+ }
91
+ });
92
+ const msg = {
93
+ type: eventType,
94
+ args: eventArgs,
95
+ dbId: DbState.id,
96
+ messageId: messageId,
97
+ departureTime: performance.now()
98
+ };
99
+ log("Posting",eventType,"message to worker dbId="+(DbState.id||'default')+':',msg);
100
+ SW.postMessage(msg);
101
+ };
102
+
103
+ /** Methods which map directly to onmessage() event.type keys.
104
+ They get passed the inbound event.data. */
105
+ const dbMsgHandler = {
106
+ open: function(ev){
107
+ DbState.id = ev.dbId;
108
+ log("open result",ev);
109
+ },
110
+ exec: function(ev){
111
+ log("exec result",ev);
112
+ },
113
+ export: function(ev){
114
+ log("export result",ev);
115
+ },
116
+ error: function(ev){
117
+ error("ERROR from the worker:",ev);
118
+ logEventResult(ev);
119
+ },
120
+ resultRowTest1: function f(ev){
121
+ if(undefined === f.counter) f.counter = 0;
122
+ if(null === ev.rowNumber){
123
+ /* End of result set. */
124
+ T.assert(undefined === ev.row)
125
+ .assert(Array.isArray(ev.columnNames))
126
+ .assert(ev.columnNames.length);
127
+ }else{
128
+ T.assert(ev.rowNumber > 0);
129
+ ++f.counter;
130
+ }
131
+ //log("exec() result row:",ev);
132
+ T.assert(null === ev.rowNumber || 'number' === typeof ev.row.b);
133
+ }
134
+ };
135
+
136
+ /**
137
+ "The problem" now is that the test results are async. We
138
+ know, however, that the messages posted to the worker will
139
+ be processed in the order they are passed to it, so we can
140
+ create a queue of callbacks to handle them. The problem
141
+ with that approach is that it's not error-handling
142
+ friendly, in that an error can cause us to bypass a result
143
+ handler queue entry. We have to perform some extra
144
+ acrobatics to account for that.
145
+
146
+ Problem #2 is that we cannot simply start posting events: we
147
+ first have to post an 'open' event, wait for it to respond, and
148
+ collect its db ID before continuing. If we don't wait, we may
149
+ well fire off 10+ messages before the open actually responds.
150
+ */
151
+ const runTests2 = function(){
152
+ const mustNotReach = ()=>{
153
+ throw new Error("This is not supposed to be reached.");
154
+ };
155
+ runOneTest('exec',{
156
+ sql: ["create table t(a,b);",
157
+ "insert into t(a,b) values(1,2),(3,4),(5,6)"
158
+ ],
159
+ resultRows: [], columnNames: []
160
+ }, function(ev){
161
+ ev = ev.result;
162
+ T.assert(0===ev.resultRows.length)
163
+ .assert(0===ev.columnNames.length);
164
+ });
165
+ runOneTest('exec',{
166
+ sql: 'select a a, b b from t order by a',
167
+ resultRows: [], columnNames: [], saveSql:[]
168
+ }, function(ev){
169
+ ev = ev.result;
170
+ T.assert(3===ev.resultRows.length)
171
+ .assert(1===ev.resultRows[0][0])
172
+ .assert(6===ev.resultRows[2][1])
173
+ .assert(2===ev.columnNames.length)
174
+ .assert('b'===ev.columnNames[1]);
175
+ });
176
+ //if(1){ error("Returning prematurely for testing."); return; }
177
+ runOneTest('exec',{
178
+ sql: 'select a a, b b from t order by a',
179
+ resultRows: [], columnNames: [],
180
+ rowMode: 'object'
181
+ }, function(ev){
182
+ ev = ev.result;
183
+ T.assert(3===ev.resultRows.length)
184
+ .assert(1===ev.resultRows[0].a)
185
+ .assert(6===ev.resultRows[2].b)
186
+ });
187
+ runOneTest('exec',{sql:'intentional_error'}, mustNotReach);
188
+ // Ensure that the message-handler queue survives ^^^ that error...
189
+ runOneTest('exec',{
190
+ sql:'select 1',
191
+ resultRows: [],
192
+ //rowMode: 'array', // array is the default in the Worker interface
193
+ }, function(ev){
194
+ ev = ev.result;
195
+ T.assert(1 === ev.resultRows.length)
196
+ .assert(1 === ev.resultRows[0][0]);
197
+ });
198
+ runOneTest('exec',{
199
+ sql: 'select a a, b b from t order by a',
200
+ callback: 'resultRowTest1',
201
+ rowMode: 'object'
202
+ }, function(ev){
203
+ T.assert(3===dbMsgHandler.resultRowTest1.counter);
204
+ dbMsgHandler.resultRowTest1.counter = 0;
205
+ });
206
+ runOneTest('exec',{
207
+ sql:[
208
+ "pragma foreign_keys=0;",
209
+ // ^^^ arbitrary query with no result columns
210
+ "select a, b from t order by a desc;",
211
+ "select a from t;"
212
+ // multi-statement exec only honors results from the first
213
+ // statement with result columns (regardless of whether)
214
+ // it has any rows).
215
+ ],
216
+ rowMode: 1,
217
+ resultRows: []
218
+ },function(ev){
219
+ const rows = ev.result.resultRows;
220
+ T.assert(3===rows.length).
221
+ assert(6===rows[0]);
222
+ });
223
+ runOneTest('exec',{sql: 'delete from t where a>3'});
224
+ runOneTest('exec',{
225
+ sql: 'select count(a) from t',
226
+ resultRows: []
227
+ },function(ev){
228
+ ev = ev.result;
229
+ T.assert(1===ev.resultRows.length)
230
+ .assert(2===ev.resultRows[0][0]);
231
+ });
232
+ runOneTest('export',{}, function(ev){
233
+ ev = ev.result;
234
+ log("export result:",ev);
235
+ T.assert('string' === typeof ev.filename)
236
+ .assert(ev.byteArray instanceof Uint8Array)
237
+ .assert(ev.byteArray.length > 1024)
238
+ .assert('application/x-sqlite3' === ev.mimetype);
239
+ });
240
+ /***** close() tests must come last. *****/
241
+ runOneTest('close',{unlink:true},function(ev){
242
+ ev = ev.result;
243
+ T.assert('string' === typeof ev.filename);
244
+ });
245
+ runOneTest('close',{unlink:true},function(ev){
246
+ ev = ev.result;
247
+ T.assert(undefined === ev.filename);
248
+ logHtml('warning',"This is the final test.");
249
+ });
250
+ logHtml('warning',"Finished posting tests. Waiting on async results.");
251
+ };
252
+
253
+ const runTests = function(){
254
+ /**
255
+ Design decision time: all remaining tests depend on the 'open'
256
+ command having succeeded. In order to support multiple DBs, the
257
+ upcoming commands ostensibly have to know the ID of the DB they
258
+ want to talk to. We have two choices:
259
+
260
+ 1) We run 'open' and wait for its response, which contains the
261
+ db id.
262
+
263
+ 2) We have the Worker automatically use the current "default
264
+ db" (the one which was most recently opened) if no db id is
265
+ provided in the message. When we do this, the main thread may
266
+ well fire off _all_ of the test messages before the 'open'
267
+ actually responds, but because the messages are handled on a
268
+ FIFO basis, those after the initial 'open' will pick up the
269
+ "default" db. However, if the open fails, then all pending
270
+ messages (until next next 'open', at least) except for 'close'
271
+ will fail and we have no way of cancelling them once they've
272
+ been posted to the worker.
273
+
274
+ Which approach we use below depends on the boolean value of
275
+ waitForOpen.
276
+ */
277
+ const waitForOpen = 1,
278
+ simulateOpenError = 0 /* if true, the remaining tests will
279
+ all barf if waitForOpen is
280
+ false. */;
281
+ logHtml('',
282
+ "Sending 'open' message and",(waitForOpen ? "" : "NOT ")+
283
+ "waiting for its response before continuing.");
284
+ startTime = performance.now();
285
+ runOneTest('open', {
286
+ filename:'testing2.sqlite3',
287
+ simulateError: simulateOpenError
288
+ }, function(ev){
289
+ log("open result",ev);
290
+ T.assert('testing2.sqlite3'===ev.result.filename)
291
+ .assert(ev.dbId)
292
+ .assert(ev.messageId)
293
+ .assert('string' === typeof ev.result.vfs);
294
+ DbState.id = ev.dbId;
295
+ if(waitForOpen) setTimeout(runTests2, 0);
296
+ });
297
+ if(!waitForOpen) runTests2();
298
+ };
299
+
300
+ SW.onmessage = function(ev){
301
+ if(!ev.data || 'object'!==typeof ev.data){
302
+ warn("Unknown sqlite3-worker message type:",ev);
303
+ return;
304
+ }
305
+ ev = ev.data/*expecting a nested object*/;
306
+ //log("main window onmessage:",ev);
307
+ if(ev.result && ev.messageId){
308
+ /* We're expecting a queued-up callback handler. */
309
+ const f = MsgHandlerQueue.shift();
310
+ if('error'===ev.type){
311
+ dbMsgHandler.error(ev);
312
+ return;
313
+ }
314
+ T.assert(f instanceof Function);
315
+ f(ev);
316
+ return;
317
+ }
318
+ switch(ev.type){
319
+ case 'sqlite3-api':
320
+ switch(ev.result){
321
+ case 'worker1-ready':
322
+ log("Message:",ev);
323
+ self.sqlite3TestModule.setStatus(null);
324
+ runTests();
325
+ return;
326
+ default:
327
+ warn("Unknown sqlite3-api message type:",ev);
328
+ return;
329
+ }
330
+ default:
331
+ if(dbMsgHandler.hasOwnProperty(ev.type)){
332
+ try{dbMsgHandler[ev.type](ev);}
333
+ catch(err){
334
+ error("Exception while handling db result message",
335
+ ev,":",err);
336
+ }
337
+ return;
338
+ }
339
+ warn("Unknown sqlite3-api message type:",ev);
340
+ }
341
+ };
342
+ log("Init complete, but async init bits may still be running.");
343
+ log("Installing Worker into global scope SW for dev purposes.");
344
+ self.SW = SW;
345
+ })();
@@ -0,0 +1,90 @@
1
+ <!doctype html>
2
+ <html lang="en-us">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6
+ <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
7
+ <title>sqlite3 WASM Demo Page Index</title>
8
+ </head>
9
+ <body>
10
+ <style>
11
+ body {
12
+ display: flex;
13
+ flex-direction: column;
14
+ flex-wrap: wrap;
15
+ }
16
+ textarea {
17
+ font-family: monospace;
18
+ }
19
+ header {
20
+ font-size: 130%;
21
+ font-weight: bold;
22
+ }
23
+ .hidden, .initially-hidden {
24
+ position: absolute !important;
25
+ opacity: 0 !important;
26
+ pointer-events: none !important;
27
+ display: none !important;
28
+ }
29
+ .warning { color: firebrick; }
30
+ </style>
31
+ <header id='titlebar'><span>sqlite3 WASM demo pages</span></header>
32
+ <hr>
33
+ <div>Below is the list of demo pages for the sqlite3 WASM
34
+ builds. The intent is that <em>this</em> page be run
35
+ using the functional equivalent of:</div>
36
+ <blockquote><pre><a href='https://sqlite.org/althttpd'>althttpd</a> -enable-sab -page index.html</pre></blockquote>
37
+ <div>and the individual pages be started in their own tab.
38
+ Warnings and Caveats:
39
+ <ul class='warning'>
40
+ <li>Some of these pages require that the web server emit the
41
+ so-called
42
+ <a href='https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy'>COOP</a>
43
+ and
44
+ <a href='https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy'>COEP</a>
45
+ headers. <a href='https://sqlite.org/althttpd'>althttpd</a> requires the
46
+ <code>-enable-sab</code> flag for that.
47
+ </li>
48
+ </ul>
49
+ </div>
50
+ <div>The tests and demos...
51
+ <ul id='test-list'>
52
+ <li>Core-most tests
53
+ <ul>
54
+ <li><a href='tester1.html'>tester1</a>: Core unit and
55
+ regression tests for the various APIs and surrounding
56
+ utility code.</li>
57
+ <li><a href='tester1-worker.html'>tester1-worker</a>: same thing
58
+ but running in a Worker.</li>
59
+ </ul>
60
+ </li>
61
+ <li>Higher-level apps and demos...
62
+ <ul>
63
+ <li><a href='demo-123.html'>demo-123</a> provides a
64
+ no-nonsense example of adding sqlite3 support to a web
65
+ page in the UI thread.</li>
66
+ <li><a href='demo-123-worker.html'>demo-123-worker</a> is
67
+ the same as <code>demo-123</code> but loads and runs
68
+ sqlite3 from a Worker thread.</li>
69
+ <li><a href='demo-jsstorage.html'>demo-jsstorage</a>: very basic
70
+ demo of using the key-value VFS for storing a persistent db
71
+ in JS <code>localStorage</code> or <code>sessionStorage</code>.</li>
72
+ <li><a href='demo-worker1.html'>demo-worker1</a>:
73
+ Worker-based wrapper of the OO API #1. Its Promise-based
74
+ wrapper is significantly easier to use, however.</li>
75
+ <li><a href='demo-worker1-promiser.html'>demo-worker1-promiser</a>:
76
+ a demo of the Promise-based wrapper of the Worker1 API.</li>
77
+ </ul>
78
+ </li>
79
+ </ul>
80
+ </div>
81
+ <style>
82
+ #test-list { font-size: 120%; }
83
+ </style>
84
+ <script>//Assign a distinct target tab name for each test page...
85
+ document.querySelectorAll('a').forEach(function(e){
86
+ e.target = e.href;
87
+ });
88
+ </script>
89
+ </body>
90
+ </html>