︙ | | |
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
|
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
|
-
+
-
+
-
+
+
+
|
emcc.jsflags += $(emcc.exportedRuntimeMethods)
emcc.jsflags += -sUSE_CLOSURE_COMPILER=0
emcc.jsflags += -sIMPORTED_MEMORY
emcc.jsflags += -sSTRICT_JS=0
# STRICT_JS disabled due to:
# https://github.com/emscripten-core/emscripten/issues/18610
# TL;DR: does not work with MODULARIZE or EXPORT_ES6 as of version 3.1.31.
emcc.environment := -sENVIRONMENT=web,worker
emcc.environment := -sENVIRONMENT=web,worker,node
########################################################################
# -sINITIAL_MEMORY: How much memory we need to start with is governed
# at least in part by whether -sALLOW_MEMORY_GROWTH is enabled. If so,
# we can start with less. If not, we need as much as we'll ever
# possibly use (which, of course, we can't know for sure). Note,
# however, that speedtest1 shows that performance for even moderate
# workloads MAY suffer considerably if we start small and have to grow
# at runtime. e.g. OPFS-backed (speedtest1 --size 75) take MAY take X
# time with 16mb+ memory and 3X time when starting with 8MB. However,
# such test results are inconsistent due to browser internals which
# are opaque to us.
emcc.jsflags += -sALLOW_MEMORY_GROWTH
emcc.INITIAL_MEMORY.128 := 13107200
emcc.INITIAL_MEMORY.128 := 134217728
emcc.INITIAL_MEMORY.96 := 100663296
emcc.INITIAL_MEMORY.64 := 64225280
emcc.INITIAL_MEMORY.64 := 67108864
emcc.INITIAL_MEMORY.32 := 33554432
emcc.INITIAL_MEMORY.16 := 16777216
emcc.INITIAL_MEMORY.8 := 8388608
emcc.INITIAL_MEMORY ?= 16
ifeq (,$(emcc.INITIAL_MEMORY.$(emcc.INITIAL_MEMORY)))
$(error emcc.INITIAL_MEMORY must be one of: 8, 16, 32, 64, 96, 128 (megabytes))
endif
emcc.jsflags += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.$(emcc.INITIAL_MEMORY))
# /INITIAL_MEMORY
########################################################################
emcc.jsflags += $(emcc.environment)
emcc.jsflags += -sSTACK_SIZE=512KB
# ^^^ ACHTUNG: emsdk 3.1.27 reduced the default stack size from 5MB to
# a mere 64KB, which leads to silent memory corruption via the kvvfs
# VFS, which requires twice that for its xRead() and xWrite() methods.
# 2023-03: those methods have since been adapted to use a malloc()'d
# buffer.
########################################################################
# $(sqlite3.js.init-func) is the name Emscripten assigns our exported
# module init/load function. This symbol name is hard-coded in
# $(extern-post-js.js) as well as in numerous docs.
#
# "sqlite3InitModule" is the symbol we document for client use, so
# that's the symbol name which must be exported, whether it comes from
|
︙ | | |
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
|
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
|
-
+
|
# file. The result is that the generated JS file is, because of the
# -g3 debugging info, _huge_.
########################################################################
$(sqlite3-api-build-version.js): $(bin.version-info) $(MAKEFILE)
@echo "Making $@..."
@{ \
echo 'self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){'; \
echo 'globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){'; \
echo -n ' sqlite3.version = '; \
$(bin.version-info) --json; \
echo ';'; \
echo '});'; \
} > $@
$(sqlite3-license-version.js): $(sqlite3.h) $(sqlite3-license-version-header.js) \
$(MAKEFILE)
|
︙ | | |
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
|
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
|
-
+
|
# $3 = resulting sqlite-api JS/MJS file
# $4 = resulting JS/MJS file
# $5 = -D... flags for $(bin.c-pp)
# $6 = emcc -sXYZ flags
define SETUP_LIB_BUILD_MODE
$(info Setting up build [$(1)]: $(4))
c-pp.D.$(1) := $(5)
pre-js.js.$(1) := $$(dir.api)/pre-js.$(1).js
pre-js.js.$(1) := $$(dir.tmp)/pre-js.$(1).js
$$(eval $$(call C-PP.FILTER,$$(pre-js.js.in),$$(pre-js.js.$(1)),$$(c-pp.D.$(1))))
post-js.js.$(1) := $$(dir.tmp)/post-js.$(1).js
$$(eval $$(call C-PP.FILTER,$$(post-js.js.in),$$(post-js.js.$(1)),$$(c-pp.D.$(1))))
extern-post-js.js.$(1) := $$(dir.tmp)/extern-post-js.$(1).js
$$(eval $$(call C-PP.FILTER,$$(extern-post-js.js.in),$$(extern-post-js.js.$(1)),$$(c-pp.D.$(1))))
pre-post-common.flags.$(1) := \
$$(pre-post-common.flags) \
|
︙ | | |
︙ | | |
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
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
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
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
-
+
-
+
-
-
+
+
+
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
|
this.
*/
const originalInit =
/* Maintenance reminder: DO NOT use `self.` here. It's correct
for non-ES6 Module cases but wrong for ES6 modules because those
resolve this symbol differently. */ sqlite3InitModule;
if(!originalInit){
throw new Error("Expecting self.sqlite3InitModule to be defined by the Emscripten build.");
throw new Error("Expecting globalThis.sqlite3InitModule to be defined by the Emscripten build.");
}
/**
We need to add some state which our custom Module.locateFile()
can see, but an Emscripten limitation currently prevents us from
attaching it to the sqlite3InitModule function object:
https://github.com/emscripten-core/emscripten/issues/18071
The only(?) current workaround is to temporarily stash this state
into the global scope and delete it when sqlite3InitModule()
is called.
*/
const initModuleState = self.sqlite3InitModuleState = Object.assign(Object.create(null),{
const initModuleState = globalThis.sqlite3InitModuleState = Object.assign(Object.create(null),{
moduleScript: self?.document?.currentScript,
isWorker: ('undefined' !== typeof WorkerGlobalScope),
location: self.location,
urlParams: new URL(self.location.href).searchParams
location: globalThis.location,
urlParams: globalThis?.location?.href
? new URL(globalThis.location.href).searchParams
: new URLSearchParams()
});
initModuleState.debugModule =
initModuleState.urlParams.has('sqlite3.debugModule')
? (...args)=>console.warn('sqlite3.debugModule:',...args)
: ()=>{};
if(initModuleState.urlParams.has('sqlite3.dir')){
initModuleState.sqlite3Dir = initModuleState.urlParams.get('sqlite3.dir') +'/';
}else if(initModuleState.moduleScript){
const li = initModuleState.moduleScript.src.split('/');
li.pop();
initModuleState.sqlite3Dir = li.join('/') + '/';
}
self.sqlite3InitModule = function ff(...args){
globalThis.sqlite3InitModule = function ff(...args){
//console.warn("Using replaced sqlite3InitModule()",self.location);
return originalInit(...args).then((EmscriptenModule)=>{
if(self.window!==self &&
if('undefined'!==typeof WorkerGlobalScope &&
(EmscriptenModule['ENVIRONMENT_IS_PTHREAD']
|| EmscriptenModule['_pthread_self']
|| 'function'===typeof threadAlert
|| self.location.pathname.endsWith('.worker.js')
|| globalThis?.location?.pathname?.endsWith?.('.worker.js')
)){
/** Workaround for wasmfs-generated worker, which calls this
routine from each individual thread and requires that its
argument be returned. All of the criteria above are fragile,
based solely on inspection of the offending code, not public
Emscripten details. */
return EmscriptenModule;
}
const s = EmscriptenModule.sqlite3;
s.scriptInfo = initModuleState;
//console.warn("sqlite3.scriptInfo =",s.scriptInfo);
if(ff.__isUnderTest) s.__isUnderTest = true;
const f = s.asyncPostInit;
delete s.asyncPostInit;
return f();
}).catch((e)=>{
console.error("Exception loading sqlite3 module:",e);
throw e;
});
};
self.sqlite3InitModule.ready = originalInit.ready;
globalThis.sqlite3InitModule.ready = originalInit.ready;
if(self.sqlite3InitModuleState.moduleScript){
const sim = self.sqlite3InitModuleState;
if(globalThis.sqlite3InitModuleState.moduleScript){
const sim = globalThis.sqlite3InitModuleState;
let src = sim.moduleScript.src.split('/');
src.pop();
sim.scriptDir = src.join('/') + '/';
}
initModuleState.debugModule('sqlite3InitModuleState =',initModuleState);
if(0){
console.warn("Replaced sqlite3InitModule()");
console.warn("self.location.href =",self.location.href);
console.warn("globalThis.location.href =",globalThis.location.href);
if('undefined' !== typeof document){
console.warn("document.currentScript.src =",
document?.currentScript?.src);
}
}
//#ifnot target=es6-module
// Emscripten does not inject these module-loader bits in ES6 module
// builds and including them here breaks JS bundlers, so elide them
// from ESM builds.
/* Replace the various module exports performed by the Emscripten
glue... */
if (typeof exports === 'object' && typeof module === 'object'){
module.exports = sqlite3InitModule;
}else if (typeof exports === 'object'){
exports["sqlite3InitModule"] = sqlite3InitModule;
}
/* AMD modules get injected in a way we cannot override,
so we can't handle those here. */
//#endif // !target=es6-module
return self.sqlite3InitModule /* required for ESM */;
return globalThis.sqlite3InitModule /* required for ESM */;
})();
//#if target=es6-module
export default toExportForESM;
//#endif
|
︙ | | |
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
-
+
-
-
+
+
|
This file glues together disparate pieces of JS which are loaded in
previous steps of the sqlite3-api.js bootstrapping process:
sqlite3-api-prologue.js, whwasmutil.js, and jaccwabyt.js. It
initializes the main API pieces so that the downstream components
(e.g. sqlite3-api-oo1.js) have all that they need.
*/
self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
'use strict';
const toss = (...args)=>{throw new Error(args.join(' '))};
const toss3 = sqlite3.SQLite3Error.toss;
const capi = sqlite3.capi, wasm = sqlite3.wasm, util = sqlite3.util;
self.WhWasmUtilInstaller(wasm);
delete self.WhWasmUtilInstaller;
globalThis.WhWasmUtilInstaller(wasm);
delete globalThis.WhWasmUtilInstaller;
if(0){
/**
Please keep this block around as a maintenance reminder
that we cannot rely on this type of check.
This block fails on Safari, per a report at
|
︙ | | |
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
|
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
|
-
+
-
+
|
"sqlite3_vfs*","string","*", "int"],
["sqlite3_wasm_vfs_unlink", "int", "sqlite3_vfs*","string"]
];
/**
Install JS<->C struct bindings for the non-opaque struct types we
need... */
sqlite3.StructBinder = self.Jaccwabyt({
sqlite3.StructBinder = globalThis.Jaccwabyt({
heap: 0 ? wasm.memory : wasm.heap8u,
alloc: wasm.alloc,
dealloc: wasm.dealloc,
bigIntEnabled: wasm.bigIntEnabled,
memberPrefix: /* Never change this: this prefix is baked into any
amount of code and client-facing docs. */ '$'
});
delete self.Jaccwabyt;
delete globalThis.Jaccwabyt;
{// wasm.xWrap() bindings...
/* Convert Arrays and certain TypedArrays to strings for
'string:flexible'-type arguments */
const __xString = wasm.xWrap.argAdapter('string');
wasm.xWrap.argAdapter(
|
︙ | | |
︙ | | |
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
-
+
|
*/
/**
sqlite3ApiBootstrap() is the only global symbol persistently
exposed by this API. It is intended to be called one time at the
end of the API amalgamation process, passed configuration details
for the current environment, and then optionally be removed from
the global object using `delete self.sqlite3ApiBootstrap`.
the global object using `delete globalThis.sqlite3ApiBootstrap`.
This function is not intended for client-level use. It is intended
for use in creating bundles configured for specific WASM
environments.
This function expects a configuration object, intended to abstract
away details specific to any given WASM environment, primarily so
|
︙ | | |
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
-
+
|
- `memory`[^1]: optional WebAssembly.Memory object, defaulting to
`exports.memory`. In Emscripten environments this should be set
to `Module.wasmMemory` if the build uses `-sIMPORT_MEMORY`, or be
left undefined/falsy to default to `exports.memory` when using
WASM-exported memory.
- `bigIntEnabled`: true if BigInt support is enabled. Defaults to
true if `self.BigInt64Array` is available, else false. Some APIs
true if `globalThis.BigInt64Array` is available, else false. Some APIs
will throw exceptions if called without BigInt support, as BigInt
is required for marshalling C-side int64 into and out of JS.
(Sidebar: it is technically possible to add int64 support via
marshalling of int32 pairs, but doing so is unduly invasive.)
- `allocExportName`: the name of the function, in `exports`, of the
`malloc(3)`-compatible routine for the WASM environment. Defaults
|
︙ | | |
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
-
-
+
+
-
+
|
function re-assigns calls that function to fetch the value,
enabling delayed evaluation.
The returned object is the top-level sqlite3 namespace object.
*/
'use strict';
self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
apiConfig = (self.sqlite3ApiConfig || sqlite3ApiBootstrap.defaultConfig)
globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
apiConfig = (globalThis.sqlite3ApiConfig || sqlite3ApiBootstrap.defaultConfig)
){
if(sqlite3ApiBootstrap.sqlite3){ /* already initalized */
console.warn("sqlite3ApiBootstrap() called multiple times.",
"Config and external initializers are ignored on calls after the first.");
return sqlite3ApiBootstrap.sqlite3;
}
const config = Object.assign(Object.create(null),{
exports: undefined,
memory: undefined,
bigIntEnabled: (()=>{
if('undefined'!==typeof Module){
/* Emscripten module will contain HEAPU64 when built with
-sWASM_BIGINT=1, else it will not. */
return !!Module.HEAPU64;
}
return !!self.BigInt64Array;
return !!globalThis.BigInt64Array;
})(),
debug: console.debug.bind(console),
warn: console.warn.bind(console),
error: console.error.bind(console),
log: console.log.bind(console),
wasmfsOpfsDir: '/opfs',
/**
|
︙ | | |
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
|
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
|
-
+
|
*/
const util = {
affirmBindableTypedArray, flexibleString,
bigIntFits32, bigIntFits64, bigIntFitsDouble,
isBindableTypedArray,
isInt32, isSQLableTypedArray, isTypedArray,
typedArrayToString,
isUIThread: ()=>(self.window===self && !!self.document),
isUIThread: ()=>(globalThis.window===globalThis && !!globalThis.document),
// is this true for ESM?: 'undefined'===typeof WorkerGlobalScope
isSharedTypedArray,
toss: function(...args){throw new Error(args.join(' '))},
toss3,
typedArrayPart
};
|
︙ | | |
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
|
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
|
-
-
-
+
+
+
|
capi.sqlite3_wasmfs_opfs_dir = function(){
if(undefined !== __wasmfsOpfsDir) return __wasmfsOpfsDir;
// If we have no OPFS, there is no persistent dir
const pdir = config.wasmfsOpfsDir;
console.error("sqlite3_wasmfs_opfs_dir() can no longer work due "+
"to incompatible WASMFS changes. It will be removed.");
if(!pdir
|| !self.FileSystemHandle
|| !self.FileSystemDirectoryHandle
|| !self.FileSystemFileHandle){
|| !globalThis.FileSystemHandle
|| !globalThis.FileSystemDirectoryHandle
|| !globalThis.FileSystemFileHandle){
return __wasmfsOpfsDir = "";
}
try{
if(pdir && 0===wasm.xCallWrapped(
'sqlite3_wasm_init_wasmfs', 'i32', ['string'], pdir
)){
return __wasmfsOpfsDir = pdir;
|
︙ | | |
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
|
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
|
-
-
+
+
|
Internal helper for sqlite3_js_kvvfs_clear() and friends.
Its argument should be one of ('local','session',"").
*/
const __kvvfsInfo = function(which){
const rc = Object.create(null);
rc.prefix = 'kvvfs-'+which;
rc.stores = [];
if('session'===which || ""===which) rc.stores.push(self.sessionStorage);
if('local'===which || ""===which) rc.stores.push(self.localStorage);
if('session'===which || ""===which) rc.stores.push(globalThis.sessionStorage);
if('local'===which || ""===which) rc.stores.push(globalThis.localStorage);
return rc;
};
/**
Clears all storage used by the kvvfs DB backend, deleting any
DB(s) stored there. Its argument must be either 'session',
'local', or "". In the first two cases, only sessionStorage
|
︙ | | |
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
|
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
|
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
|
throw e;
}
delete sqlite3ApiBootstrap.initializers;
sqlite3ApiBootstrap.sqlite3 = sqlite3;
return sqlite3;
}/*sqlite3ApiBootstrap()*/;
/**
self.sqlite3ApiBootstrap.initializers is an internal detail used by
globalThis.sqlite3ApiBootstrap.initializers is an internal detail used by
the various pieces of the sqlite3 API's amalgamation process. It
must not be modified by client code except when plugging such code
into the amalgamation process.
Each component of the amalgamation is expected to append a function
to this array. When sqlite3ApiBootstrap() is called for the first
time, each such function will be called (in their appended order)
and passed the sqlite3 namespace object, into which they can install
their features (noting that most will also require that certain
features alread have been installed). At the end of that process,
this array is deleted.
Note that the order of insertion into this array is significant for
some pieces. e.g. sqlite3.capi and sqlite3.wasm cannot be fully
utilized until the whwasmutil.js part is plugged in via
sqlite3-api-glue.js.
*/
self.sqlite3ApiBootstrap.initializers = [];
globalThis.sqlite3ApiBootstrap.initializers = [];
/**
self.sqlite3ApiBootstrap.initializersAsync is an internal detail
globalThis.sqlite3ApiBootstrap.initializersAsync is an internal detail
used by the sqlite3 API's amalgamation process. It must not be
modified by client code except when plugging such code into the
amalgamation process.
The counterpart of self.sqlite3ApiBootstrap.initializers,
The counterpart of globalThis.sqlite3ApiBootstrap.initializers,
specifically for initializers which are asynchronous. All entries in
this list must be either async functions, non-async functions which
return a Promise, or a Promise. Each function in the list is called
with the sqlite3 ojbect as its only argument.
The resolved value of any Promise is ignored and rejection will kill
the asyncPostInit() process (at an indeterminate point because all
of them are run asynchronously in parallel).
This list is not processed until the client calls
sqlite3.asyncPostInit(). This means, for example, that intializers
added to self.sqlite3ApiBootstrap.initializers may push entries to
added to globalThis.sqlite3ApiBootstrap.initializers may push entries to
this list.
*/
self.sqlite3ApiBootstrap.initializersAsync = [];
globalThis.sqlite3ApiBootstrap.initializersAsync = [];
/**
Client code may assign sqlite3ApiBootstrap.defaultConfig an
object-type value before calling sqlite3ApiBootstrap() (without
arguments) in order to tell that call to use this object as its
default config value. The intention of this is to provide
downstream clients with a reasonably flexible approach for plugging in
an environment-suitable configuration without having to define a new
global-scope symbol.
*/
self.sqlite3ApiBootstrap.defaultConfig = Object.create(null);
globalThis.sqlite3ApiBootstrap.defaultConfig = Object.create(null);
/**
Placeholder: gets installed by the first call to
self.sqlite3ApiBootstrap(). However, it is recommended that the
globalThis.sqlite3ApiBootstrap(). However, it is recommended that the
caller of sqlite3ApiBootstrap() capture its return value and delete
self.sqlite3ApiBootstrap after calling it. It returns the same
globalThis.sqlite3ApiBootstrap after calling it. It returns the same
value which will be stored here.
*/
self.sqlite3ApiBootstrap.sqlite3 = undefined;
globalThis.sqlite3ApiBootstrap.sqlite3 = undefined;
|
︙ | | |
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
|
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
|
-
+
-
+
|
to wait until the first exec() is completed.
The response is the input options object (or a synthesized one if
passed only a string), noting that options.resultRows and
options.columnNames may be populated by the call to db.exec().
*/
self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
sqlite3.initWorker1API = function(){
'use strict';
const toss = (...args)=>{throw new Error(args.join(' '))};
if('function' !== typeof importScripts){
if(!(globalThis.WorkerGlobalScope instanceof Function)){
toss("initWorker1API() must be run from a Worker thread.");
}
const self = this.self;
const sqlite3 = this.sqlite3 || toss("Missing this.sqlite3 object.");
const DB = sqlite3.oo1.DB;
/**
|
︙ | | |
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
|
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
|
-
+
-
+
|
Posts the given worker message value. If xferList is provided,
it must be an array, in which case a copy of it passed as
postMessage()'s second argument and xferList.length is set to
0.
*/
post: function(msg,xferList){
if(xferList && xferList.length){
self.postMessage( msg, Array.from(xferList) );
globalThis.postMessage( msg, Array.from(xferList) );
xferList.length = 0;
}else{
self.postMessage(msg);
globalThis.postMessage(msg);
}
},
/** Map of DB IDs to DBs. */
dbs: Object.create(null),
/** Fetch the DB for the given id. Throw if require=true and the
id is not valid, else return the db or undefined. */
getDb: function(id,require=true){
|
︙ | | |
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
|
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
|
-
+
|
'opfs-tree': async function(ev){
if(!sqlite3.opfs) toss("OPFS support is unavailable.");
const response = await sqlite3.opfs.treeList();
return response;
}
}/*wMsgHandler*/;
self.onmessage = async function(ev){
globalThis.onmessage = async function(ev){
ev = ev.data;
let result, dbId = ev.dbId, evType = ev.type;
const arrivalTime = performance.now();
try {
if(wMsgHandler.hasOwnProperty(evType) &&
wMsgHandler[evType] instanceof Function){
result = await wMsgHandler[evType](ev);
|
︙ | | |
633
634
635
636
637
638
639
640
641
642
|
633
634
635
636
637
638
639
640
641
642
|
-
+
|
// departure: ev.departureTime,
// workerReceived: arrivalTime,
// workerResponse: performance.now();
//},
result: result
}, wState.xfer);
};
self.postMessage({type:'sqlite3-api',result:'worker1-ready'});
globalThis.postMessage({type:'sqlite3-api',result:'worker1-ready'});
}.bind({self, sqlite3});
});
|
︙ | | |
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
-
+
-
+
|
versions (approximately) 104-107 are extinct) should change our
usage of those methods to remove the "await".
*/
"use strict";
const wPost = (type,...args)=>postMessage({type, payload:args});
const installAsyncProxy = function(self){
const toss = function(...args){throw new Error(args.join(' '))};
if(self.window === self){
if(globalThis.window === globalThis){
toss("This code cannot run from the main thread.",
"Load it as a Worker from a separate Worker.");
}else if(!navigator.storage.getDirectory){
}else if(!navigator?.storage?.getDirectory){
toss("This API requires navigator.storage.getDirectory.");
}
/**
Will hold state copied to this object from the syncronous side of
this API.
*/
|
︙ | | |
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
-
-
+
+
|
for(k in state.opIds){
const m = metrics[k];
n += m.count;
t += m.time;
w += m.wait;
m.avgTime = (m.count && m.time) ? (m.time / m.count) : 0;
}
console.log(self.location.href,
"metrics for",self.location.href,":\n",
console.log(globalThis?.location?.href,
"metrics for",globalThis?.location?.href,":\n",
metrics,
"\nTotal of",n,"op(s) for",t,"ms",
"approx",w,"ms spent waiting on OPFS APIs.");
console.log("Serialization metrics:",metrics.s11n);
};
/**
|
︙ | | |
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
|
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
|
-
+
|
error('in waitLoop():',e);
}
}
};
navigator.storage.getDirectory().then(function(d){
state.rootDir = d;
self.onmessage = function({data}){
globalThis.onmessage = function({data}){
switch(data.type){
case 'opfs-async-init':{
/* Receive shared state from synchronous partner */
const opt = data.args;
for(const k in opt) state[k] = opt[k];
state.verbose = opt.verbose ?? 1;
state.sabOPView = new Int32Array(state.sabOP);
|
︙ | | |
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
|
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
|
-
+
-
+
-
-
-
-
-
+
+
+
+
+
|
metrics.dump();
break;
}
};
wPost('opfs-async-loaded');
}).catch((e)=>error("error initializing OPFS asyncer:",e));
}/*installAsyncProxy()*/;
if(!self.SharedArrayBuffer){
if(!globalThis.SharedArrayBuffer){
wPost('opfs-unavailable', "Missing SharedArrayBuffer API.",
"The server must emit the COOP/COEP response headers to enable that.");
}else if(!self.Atomics){
}else if(!globalThis.Atomics){
wPost('opfs-unavailable', "Missing Atomics API.",
"The server must emit the COOP/COEP response headers to enable that.");
}else if(!self.FileSystemHandle ||
!self.FileSystemDirectoryHandle ||
!self.FileSystemFileHandle ||
!self.FileSystemFileHandle.prototype.createSyncAccessHandle ||
!navigator.storage.getDirectory){
}else if(!globalThis.FileSystemHandle ||
!globalThis.FileSystemDirectoryHandle ||
!globalThis.FileSystemFileHandle ||
!globalThis.FileSystemFileHandle.prototype.createSyncAccessHandle ||
!navigator?.storage?.getDirectory){
wPost('opfs-unavailable',"Missing required OPFS APIs.");
}else{
installAsyncProxy(self);
}
|
︙ | | |
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
-
+
+
+
+
|
/**
This file installs sqlite3.vfs, and object which exists to assist
in the creation of JavaScript implementations of sqlite3_vfs, along
with its virtual table counterpart, sqlite3.vtab.
*/
'use strict';
self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
const wasm = sqlite3.wasm, capi = sqlite3.capi, toss = sqlite3.util.toss3;
const vfs = Object.create(null), vtab = Object.create(null);
const StructBinder = sqlite3.StructBinder
/* we require a local alias b/c StructBinder is removed from the sqlite3
object during the final steps of the API cleanup. */;
sqlite3.vfs = vfs;
sqlite3.vtab = vtab;
const sii = capi.sqlite3_index_info;
/**
If n is >=0 and less than this.$nConstraint, this function
returns either a WASM pointer to the 0-based nth entry of
|
︙ | | |
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
-
+
-
+
|
argument count does not match expectations. That is only intended
for dev-time usage for sanity checking, and will leave the C
environment in an undefined state.
*/
const installMethod = function callee(
tgt, name, func, applyArgcCheck = callee.installMethodArgcCheck
){
if(!(tgt instanceof sqlite3.StructBinder.StructType)){
if(!(tgt instanceof StructBinder.StructType)){
toss("Usage error: target object is-not-a StructType.");
}else if(!(func instanceof Function) && !wasm.isPtr(func)){
toss("Usage errror: expecting a Function or WASM pointer to one.");
}
if(1===arguments.length){
return (n,f)=>callee(tgt, n, f, applyArgcCheck);
}
if(!callee.argcProxy){
callee.argcProxy = function(tgt, funcName, func,sig){
return function(...args){
if(func.length!==arguments.length){
toss("Argument mismatch for",
tgt.structInfo.name+"::"+funcName
+": Native signature is:",sig);
}
return func.apply(this, args);
}
};
/* An ondispose() callback for use with
sqlite3.StructBinder-created types. */
StructBinder-created types. */
callee.removeFuncList = function(){
if(this.ondispose.__removeFuncList){
this.ondispose.__removeFuncList.forEach(
(v,ndx)=>{
if('number'===typeof v){
try{wasm.uninstallFunction(v)}
catch(e){/*ignore*/}
|
︙ | | |
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
|
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
|
-
+
-
+
|
/**
Equivalent to calling installMethod(this,...arguments) with a
first argument of this object. If called with 1 or 2 arguments
and the first is an object, it's instead equivalent to calling
installMethods(this,...arguments).
*/
sqlite3.StructBinder.StructType.prototype.installMethod = function callee(
StructBinder.StructType.prototype.installMethod = function callee(
name, func, applyArgcCheck = installMethod.installMethodArgcCheck
){
return (arguments.length < 3 && name && 'object'===typeof name)
? installMethods(this, ...arguments)
: installMethod(this, ...arguments);
};
/**
Equivalent to calling installMethods() with a first argument
of this object.
*/
sqlite3.StructBinder.StructType.prototype.installMethods = function(
StructBinder.StructType.prototype.installMethods = function(
methods, applyArgcCheck = installMethod.installMethodArgcCheck
){
return installMethods(this, methods, applyArgcCheck);
};
/**
Uses sqlite3_vfs_register() to register this
|
︙ | | |
︙ | | |
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
-
+
|
implementation which proxies, in a synchronous fashion, the
asynchronous Origin-Private FileSystem (OPFS) APIs using a second
Worker, implemented in sqlite3-opfs-async-proxy.js. This file is
intended to be appended to the main sqlite3 JS deliverable somewhere
after sqlite3-api-oo1.js and before sqlite3-api-cleanup.js.
*/
'use strict';
self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
/**
installOpfsVfs() returns a Promise which, on success, installs an
sqlite3_vfs named "opfs", suitable for use with all sqlite3 APIs
which accept a VFS. It is intended to be called via
sqlite3ApiBootstrap.initializersAsync or an equivalent mechanism.
The installed VFS uses the Origin-Private FileSystem API for
|
︙ | | |
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
-
-
+
+
-
+
-
-
-
-
-
+
+
+
+
+
-
+
-
+
|
returned Promise resolves.
On success, the Promise resolves to the top-most sqlite3 namespace
object and that object gets a new object installed in its
`opfs` property, containing several OPFS-specific utilities.
*/
const installOpfsVfs = function callee(options){
if(!self.SharedArrayBuffer
|| !self.Atomics){
if(!globalThis.SharedArrayBuffer
|| !globalThis.Atomics){
return Promise.reject(
new Error("Cannot install OPFS: Missing SharedArrayBuffer and/or Atomics. "+
"The server must emit the COOP/COEP response headers to enable those. "+
"See https://sqlite.org/wasm/doc/trunk/persistence.md#coop-coep")
);
}else if(self.window===self && self.document){
}else if('undefined'===typeof WorkerGlobalScope){
return Promise.reject(
new Error("The OPFS sqlite3_vfs cannot run in the main thread "+
"because it requires Atomics.wait().")
);
}else if(!self.FileSystemHandle ||
!self.FileSystemDirectoryHandle ||
!self.FileSystemFileHandle ||
!self.FileSystemFileHandle.prototype.createSyncAccessHandle ||
!navigator.storage.getDirectory){
}else if(!globalThis.FileSystemHandle ||
!globalThis.FileSystemDirectoryHandle ||
!globalThis.FileSystemFileHandle ||
!globalThis.FileSystemFileHandle.prototype.createSyncAccessHandle ||
!navigator?.storage?.getDirectory){
return Promise.reject(
new Error("Missing required OPFS APIs.")
);
}
if(!options || 'object'!==typeof options){
options = Object.create(null);
}
const urlParams = new URL(self.location.href).searchParams;
const urlParams = new URL(globalThis.location.href).searchParams;
if(undefined===options.verbose){
options.verbose = urlParams.has('opfs-verbose')
? (+urlParams.get('opfs-verbose') || 2) : 1;
}
if(undefined===options.sanityChecks){
options.sanityChecks = urlParams.has('opfs-sanity-check');
}
if(undefined===options.proxyUri){
options.proxyUri = callee.defaultProxyUri;
}
//sqlite3.config.warn("OPFS options =",options,self.location);
//sqlite3.config.warn("OPFS options =",options,globalThis.location);
if('function' === typeof options.proxyUri){
options.proxyUri = options.proxyUri();
}
const thePromise = new Promise(function(promiseResolve, promiseReject_){
const loggers = {
0:sqlite3.config.error,
|
︙ | | |
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
|
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
|
-
-
-
-
-
+
+
+
+
+
-
-
+
+
|
*/
const opfsUtil = Object.create(null);
/**
Returns true if _this_ thread has access to the OPFS APIs.
*/
const thisThreadHasOPFS = ()=>{
return self.FileSystemHandle &&
self.FileSystemDirectoryHandle &&
self.FileSystemFileHandle &&
self.FileSystemFileHandle.prototype.createSyncAccessHandle &&
navigator.storage.getDirectory;
return globalThis.FileSystemHandle &&
globalThis.FileSystemDirectoryHandle &&
globalThis.FileSystemFileHandle &&
globalThis.FileSystemFileHandle.prototype.createSyncAccessHandle &&
navigator?.storage?.getDirectory;
};
/**
Not part of the public API. Solely for internal/development
use.
*/
opfsUtil.metrics = {
dump: function(){
let k, n = 0, t = 0, w = 0;
for(k in state.opIds){
const m = metrics[k];
n += m.count;
t += m.time;
w += m.wait;
m.avgTime = (m.count && m.time) ? (m.time / m.count) : 0;
m.avgWait = (m.count && m.wait) ? (m.wait / m.count) : 0;
}
sqlite3.config.log(self.location.href,
"metrics for",self.location.href,":",metrics,
sqlite3.config.log(globalThis.location.href,
"metrics for",globalThis.location.href,":",metrics,
"\nTotal of",n,"op(s) for",t,
"ms (incl. "+w+" ms of waiting on the async side)");
sqlite3.config.log("Serialization metrics:",metrics.s11n);
W.postMessage({type:'opfs-async-metrics'});
},
reset: function(){
let k;
|
︙ | | |
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
|
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
|
-
+
|
}/*switch(data.type)*/
}/*W.onmessage()*/;
})/*thePromise*/;
return thePromise;
}/*installOpfsVfs()*/;
installOpfsVfs.defaultProxyUri =
"sqlite3-opfs-async-proxy.js";
self.sqlite3ApiBootstrap.initializersAsync.push(async (sqlite3)=>{
globalThis.sqlite3ApiBootstrap.initializersAsync.push(async (sqlite3)=>{
try{
let proxyJs = installOpfsVfs.defaultProxyUri;
if(sqlite3.scriptInfo.sqlite3Dir){
installOpfsVfs.defaultProxyUri =
sqlite3.scriptInfo.sqlite3Dir + proxyJs;
//sqlite3.config.warn("installOpfsVfs.defaultProxyUri =",installOpfsVfs.defaultProxyUri);
}
|
︙ | | |
︙ | | |
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
-
+
|
- This API was not designed with ES6 modules in mind. Neither Firefox
nor Safari support, as of March 2023, the {type:"module"} flag to the
Worker constructor, so that particular usage is not something we're going
to target for the time being:
https://developer.mozilla.org/en-US/docs/Web/API/Worker/Worker
*/
self.sqlite3Worker1Promiser = function callee(config = callee.defaultConfig){
globalThis.sqlite3Worker1Promiser = function callee(config = callee.defaultConfig){
// Inspired by: https://stackoverflow.com/a/52439530
if(1===arguments.length && 'function'===typeof arguments[0]){
const f = config;
config = Object.assign(Object.create(null), callee.defaultConfig);
config.onready = f;
}else{
config = Object.assign(Object.create(null), callee.defaultConfig, config);
|
︙ | | |
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
|
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
|
-
+
-
-
-
+
+
+
-
+
-
+
|
debug("Posting",msg.type,"message to Worker dbId="+(dbId||'default')+':',msg);
config.worker.postMessage(msg);
});
if(rowCallbackId) p = p.finally(()=>delete handlerMap[rowCallbackId]);
return p;
};
}/*sqlite3Worker1Promiser()*/;
self.sqlite3Worker1Promiser.defaultConfig = {
globalThis.sqlite3Worker1Promiser.defaultConfig = {
worker: function(){
//#if target=es6-bundler-friendly
return new Worker("sqlite3-worker1-bundler-friendly.mjs",{
type: 'module' /* Noting that neither Firefox nor Safari suppor this,
as of this writing. */
});
//#else
let theJs = "sqlite3-worker1.js";
if(this.currentScript){
const src = this.currentScript.src.split('/');
src.pop();
theJs = src.join('/')+'/' + theJs;
//sqlite3.config.warn("promiser currentScript, theJs =",this.currentScript,theJs);
}else{
//sqlite3.config.warn("promiser self.location =",self.location);
const urlParams = new URL(self.location.href).searchParams;
}else if(globalThis.location){
//sqlite3.config.warn("promiser globalThis.location =",globalThis.location);
const urlParams = new URL(globalThis.location.href).searchParams;
if(urlParams.has('sqlite3.dir')){
theJs = urlParams.get('sqlite3.dir') + '/' + theJs;
}
}
return new Worker(theJs + self.location.search);
return new Worker(theJs + globalThis.location.search);
//#endif
}.bind({
currentScript: self?.document?.currentScript
currentScript: globalThis?.document?.currentScript
}),
onerror: (...args)=>console.error('worker1 promiser error',...args)
};
|
︙ | | |
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
-
-
+
+
|
things still requires using Emscripten's glue, but the post-load
utility APIs provided by this code are still usable as replacements
for their sub-optimally-documented Emscripten counterparts.
Intended usage:
```
self.WhWasmUtilInstaller(appObject);
delete self.WhWasmUtilInstaller;
globalThis.WhWasmUtilInstaller(appObject);
delete globalThis.WhWasmUtilInstaller;
```
Its global-scope symbol is intended only to provide an easy way to
make it available to 3rd-party scripts and "should" be deleted
after calling it. That symbols is _not_ used within the library.
Forewarning: this API explicitly targets only browser
|
︙ | | |
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
-
+
|
https://fossil.wanderinghorse.net/r/jaccwabbyt
More specifically:
https://fossil.wanderinghorse.net/r/jaccwabbyt/file/common/whwasmutil.js
*/
self.WhWasmUtilInstaller = function(target){
globalThis.WhWasmUtilInstaller = function(target){
'use strict';
if(undefined===target.bigIntEnabled){
target.bigIntEnabled = !!self['BigInt64Array'];
}
/** Throws a new Error, the message of which is the concatenation of
all args with a space between each. */
|
︙ | | |
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
|
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
|
-
+
|
(Note that the initial `then()` attached to the promise gets only
that object, and not the `config` one.)
Error handling is up to the caller, who may attach a `catch()` call
to the promise.
*/
self.WhWasmUtilInstaller.yawl = function(config){
globalThis.WhWasmUtilInstaller.yawl = function(config){
const wfetch = ()=>fetch(config.uri, {credentials: 'same-origin'});
const wui = this;
const finalThen = function(arg){
//log("finalThen()",arg);
if(config.wasmUtilTarget){
const toss = (...args)=>{throw new Error(args.join(' '))};
const tgt = config.wasmUtilTarget;
|
︙ | | |
2236
2237
2238
2239
2240
2241
2242
2243
|
2236
2237
2238
2239
2240
2241
2242
2243
|
-
+
|
: function loadWasmOldSchool(){ // Safari < v15
return wfetch()
.then(response => response.arrayBuffer())
.then(bytes => WebAssembly.instantiate(bytes, config.imports||{}))
.then(finalThen);
};
return loadWasm;
}.bind(self.WhWasmUtilInstaller)/*yawl()*/;
}.bind(globalThis.WhWasmUtilInstaller)/*yawl()*/;
|