SQLite

Check-in [0e272123ac]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Initial work at getting sqlite3Worker1Promiser.v2() to return a Promise instead of using an onready() callback, and also creating an ESM build for promiser1 per user request. It seems to work but requires more testing.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | wasm-promiser1-v2
Files: files | file ages | folders
SHA3-256: 0e272123ace55ed63fe86632671cca48e8965a28fc3625324984028729fc203f
User & Date: stephan 2024-03-07 16:04:43.823
Context
2024-03-07
17:56
wasm promiser.v2 is essentially working but the demo code is double-loading the module for as-yet-undetermined reasons. (check-in: aa877ce0c3 user: stephan tags: wasm-promiser1-v2)
16:04
Initial work at getting sqlite3Worker1Promiser.v2() to return a Promise instead of using an onready() callback, and also creating an ESM build for promiser1 per user request. It seems to work but requires more testing. (check-in: 0e272123ac user: stephan tags: wasm-promiser1-v2)
2024-03-06
12:28
Correction to the previous check-in. (check-in: 483fa2969e user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to ext/wasm/GNUmakefile.
303
304
305
306
307
308
309
310

311
312
313
314
315
316
317
318
bin.stripccomments := $(dir.tool)/stripccomments
$(bin.stripccomments): $(bin.stripccomments).c $(MAKEFILE)
	$(CC) -o $@ $<
DISTCLEAN_FILES += $(bin.stripccomments)


########################################################################
# C-PP.FILTER: a $(call)able to transform $(1) to $(2) via ./c-pp -f

# $(1) ...
#
# Historical notes:
#
# - We first attempted to use gcc and/or clang to preprocess JS files
#   in the same way we would normally do C files, but C-specific quirks
#   of each makes that untennable.
#







|
>
|







303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
bin.stripccomments := $(dir.tool)/stripccomments
$(bin.stripccomments): $(bin.stripccomments).c $(MAKEFILE)
	$(CC) -o $@ $<
DISTCLEAN_FILES += $(bin.stripccomments)


########################################################################
# C-PP.FILTER: a $(call)able to transform $(1) to $(2) via:
#
#   ./c-pp -f $(1) -o $(2) $(3)
#
# Historical notes:
#
# - We first attempted to use gcc and/or clang to preprocess JS files
#   in the same way we would normally do C files, but C-specific quirks
#   of each makes that untennable.
#
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
#
# $1 = one of: $(JS_BUILD_NAMES)
# $2 = build mode name: one of $(JS_BUILD_MODES)
# $3 = 1 for ESM build mode, else 0
# $4 = resulting sqlite-api JS/MJS file
# $5 = resulting JS/MJS file
# $6 = -D... flags for $(bin.c-pp)
# $7 = emcc -sXYZ flags (CURRENTLY UNUSED - was factored out)
#
# Maintenance reminder: be careful not to introduce spaces around args
# ($1, $2), otherwise string concatenation will malfunction.
#
# emcc.environment.$(2) must be set to a value for emcc's
# -sENVIRONMENT flag.
#
# $(cflags.$(1)) and $(cflags.$(1).$(2)) may be defined to append
# CFLAGS to a given build mode.
#
# $(emcc.flags.$(1)) and $(emcc.flags.$(1).$(2)) may be defined to
# append emcc-specific flags to a given build mode.
define SETUP_LIB_BUILD_MODE







|




|
|







822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
#
# $1 = one of: $(JS_BUILD_NAMES)
# $2 = build mode name: one of $(JS_BUILD_MODES)
# $3 = 1 for ESM build mode, else 0
# $4 = resulting sqlite-api JS/MJS file
# $5 = resulting JS/MJS file
# $6 = -D... flags for $(bin.c-pp)
# $7 = optional extra flags for emcc
#
# Maintenance reminder: be careful not to introduce spaces around args
# ($1, $2), otherwise string concatenation will malfunction.
#
# Before calling this, emcc.environment.$(2) must be set to a value
# for emcc's -sENVIRONMENT flag.
#
# $(cflags.$(1)) and $(cflags.$(1).$(2)) may be defined to append
# CFLAGS to a given build mode.
#
# $(emcc.flags.$(1)) and $(emcc.flags.$(1).$(2)) may be defined to
# append emcc-specific flags to a given build mode.
define SETUP_LIB_BUILD_MODE
934
935
936
937
938
939
940

941
942
943
944
945
946
947
948
949


950
951
952
953
954
955
956
957
958
959
960
# themselves use importScripts() or Workers or URL() constructors
# which refer to other in-tree (m)JS files quire a bundler-friendly
# copy.
sqlite3-worker1.js.in := $(dir.api)/sqlite3-worker1.c-pp.js
sqlite3-worker1-promiser.js.in := $(dir.api)/sqlite3-worker1-promiser.c-pp.js
sqlite3-worker1.js := $(dir.dout)/sqlite3-worker1.js
sqlite3-worker1-promiser.js := $(dir.dout)/sqlite3-worker1-promiser.js

sqlite3-worker1-bundler-friendly.js := $(dir.dout)/sqlite3-worker1-bundler-friendly.mjs
sqlite3-worker1-promiser-bundler-friendly.js := $(dir.dout)/sqlite3-worker1-promiser-bundler-friendly.js
$(eval $(call C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1.js)))
$(eval $(call C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1-bundler-friendly.js),\
    $(c-pp.D.sqlite3-bundler-friendly)))
$(eval $(call C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),$(sqlite3-worker1-promiser.js)))
$(eval $(call C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),\
    $(sqlite3-worker1-promiser-bundler-friendly.js),\
    $(c-pp.D.sqlite3-bundler-friendly)))


$(sqlite3-bundler-friendly.mjs): $(sqlite3-worker1-bundler-friendly.js) \
    $(sqlite3-worker1-promiser-bundler-friendly.js)
$(sqlite3.js) $(sqlite3.mjs): $(sqlite3-worker1.js) $(sqlite3-worker1-promiser.js)

########################################################################
# batch-runner.js is part of one of the test apps which reads in SQL
# dumps generated by $(speedtest1) and executes them.
dir.sql := sql
speedtest1 := ../../speedtest1
speedtest1.c := ../../test/speedtest1.c
speedtest1.sql := $(dir.sql)/speedtest1.sql







>









>
>


|
|







935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
# themselves use importScripts() or Workers or URL() constructors
# which refer to other in-tree (m)JS files quire a bundler-friendly
# copy.
sqlite3-worker1.js.in := $(dir.api)/sqlite3-worker1.c-pp.js
sqlite3-worker1-promiser.js.in := $(dir.api)/sqlite3-worker1-promiser.c-pp.js
sqlite3-worker1.js := $(dir.dout)/sqlite3-worker1.js
sqlite3-worker1-promiser.js := $(dir.dout)/sqlite3-worker1-promiser.js
sqlite3-worker1-promiser.mjs := $(dir.dout)/sqlite3-worker1-promiser.mjs
sqlite3-worker1-bundler-friendly.js := $(dir.dout)/sqlite3-worker1-bundler-friendly.mjs
sqlite3-worker1-promiser-bundler-friendly.js := $(dir.dout)/sqlite3-worker1-promiser-bundler-friendly.js
$(eval $(call C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1.js)))
$(eval $(call C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1-bundler-friendly.js),\
    $(c-pp.D.sqlite3-bundler-friendly)))
$(eval $(call C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),$(sqlite3-worker1-promiser.js)))
$(eval $(call C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),\
    $(sqlite3-worker1-promiser-bundler-friendly.js),\
    $(c-pp.D.sqlite3-bundler-friendly)))
$(eval $(call C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),$(sqlite3-worker1-promiser.mjs),\
    -Dtarget=es6-module -Dtarget=es6-bundler-friendly))
$(sqlite3-bundler-friendly.mjs): $(sqlite3-worker1-bundler-friendly.js) \
    $(sqlite3-worker1-promiser-bundler-friendly.js)
$(sqlite3.js) $(sqlite3.mjs): $(sqlite3-worker1.js) \
    $(sqlite3-worker1-promiser.js) $(sqlite3-worker1-promiser.mjs)
########################################################################
# batch-runner.js is part of one of the test apps which reads in SQL
# dumps generated by $(speedtest1) and executes them.
dir.sql := sql
speedtest1 := ../../speedtest1
speedtest1.c := ../../test/speedtest1.c
speedtest1.sql := $(dir.sql)/speedtest1.sql
Changes to ext/wasm/api/sqlite3-worker1-promiser.c-pp.js.
38
39
40
41
42
43
44
45
46
47




48
49
50
51
52
53
54
   config option may alternately be a function, in which case this
   function re-assigns this property with the result of calling that
   function, enabling delayed instantiation of a Worker.

   - `onready` (optional, but...): this callback is called with no
   arguments when the worker fires its initial
   'sqlite3-api'/'worker1-ready' message, which it does when
   sqlite3.initWorker1API() completes its initialization. This is
   the simplest way to tell the worker to kick off work at the
   earliest opportunity.





   - `onunhandled` (optional): a callback which gets passed the
   message event object for any worker.onmessage() events which
   are not handled by this proxy. Ideally that "should" never
   happen, as this proxy aims to handle all known message types.

   - `generateMessageId` (optional): a function which, when passed an







|
|
|
>
>
>
>







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
   config option may alternately be a function, in which case this
   function re-assigns this property with the result of calling that
   function, enabling delayed instantiation of a Worker.

   - `onready` (optional, but...): this callback is called with no
   arguments when the worker fires its initial
   'sqlite3-api'/'worker1-ready' message, which it does when
   sqlite3.initWorker1API() completes its initialization. This is the
   simplest way to tell the worker to kick off work at the earliest
   opportunity, and the only way to know when the worker module has
   completed loading. The irony of using a callback for this, instead
   of returning a promise from sqlite3Worker1Promiser() is not lost on
   the developers, but initial attempts to return a promise resulted
   in a much clumsier interface.

   - `onunhandled` (optional): a callback which gets passed the
   message event object for any worker.onmessage() events which
   are not handled by this proxy. Ideally that "should" never
   happen, as this proxy aims to handle all known message types.

   - `generateMessageId` (optional): a function which, when passed an
273
274
275
276
277
278
279


































280




281
282
283
//#ifnot target=es6-bundler-friendly
  .bind({
    currentScript: globalThis?.document?.currentScript
  })
//#endif
  ,
  onerror: (...args)=>console.error('worker1 promiser error',...args)


































};




//#else
/* Built with the omit-oo1 flag. */
//#endif ifnot omit-oo1







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>



277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
//#ifnot target=es6-bundler-friendly
  .bind({
    currentScript: globalThis?.document?.currentScript
  })
//#endif
  ,
  onerror: (...args)=>console.error('worker1 promiser error',...args)
}/*defaultConfig*/;

/**
   sqlite3Worker1Promiser.v2() works identically to
   sqlite3Worker1Promiser() except that it returns a promise instead
   of relying an an onready callback in the config object.
*/
sqlite3Worker1Promiser.v2 = function(config){
  const x = Object.create(null);
  let oldFunc;
  if( 'function' == typeof config ){
    oldFunc = config;
    config = {};
  }else if('function'===typeof config?.onready){
    oldFunc = config.onready;
    delete config.onready;
  }
  config = Object.assign((config || Object.create(null)),{
    onready: function(func){
      try {
        if( oldFunc ){
          oldFunc(func);
        }
        x.resolve(func);
      }
      catch(e){x.reject(e)}
    }
  });
  const p = new Promise(function(resolve,reject){
    x.resolve = resolve;
    x.reject = reject;
  });
  sqlite3Worker1Promiser(config);
  return p;
};

//#if target=es6-module
export default sqlite3Worker1Promiser.v2;
//#endif /* target=es6-module */
//#else
/* Built with the omit-oo1 flag. */
//#endif ifnot omit-oo1
Changes to ext/wasm/demo-worker1-promiser.js.
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

  ***********************************************************************

  Demonstration of the sqlite3 Worker API #1 Promiser: a Promise-based
  proxy for for the sqlite3 Worker #1 API.
*/
'use strict';
(function(){
  const T = self.SqliteTestUtil;
  const eOutput = document.querySelector('#test-output');
  const warn = console.warn.bind(console);
  const error = console.error.bind(console);
  const log = console.log.bind(console);
  const logHtml = async function(cssClass,...args){
    log.apply(this, args);
    const ln = document.createElement('div');







|
|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

  ***********************************************************************

  Demonstration of the sqlite3 Worker API #1 Promiser: a Promise-based
  proxy for for the sqlite3 Worker #1 API.
*/
'use strict';
(async function(){
  const T = globalThis.SqliteTestUtil;
  const eOutput = document.querySelector('#test-output');
  const warn = console.warn.bind(console);
  const error = console.error.bind(console);
  const log = console.log.bind(console);
  const logHtml = async function(cssClass,...args){
    log.apply(this, args);
    const ln = document.createElement('div');
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
      w.onerror = (event)=>error("worker.onerror",event);
      return w;
    },
    debug: 1 ? undefined : (...args)=>console.debug('worker debug',...args),
    onunhandled: function(ev){
      error("Unhandled worker message:",ev.data);
    },
    onready: function(){
      T.affirm(arguments[0] === workerPromise
               /* as of version 3.46. Prior to that this callback had no arguments */);
      self.sqlite3TestModule.setStatus(null)/*hide the HTML-side is-loading spinner*/;
      runTests();
    },
    onerror: function(ev){
      error("worker1 error:",ev);

    }
  };
  const workerPromise = self.sqlite3Worker1Promiser(promiserConfig);





  delete self.sqlite3Worker1Promiser;

  const wtest = async function(msgType, msgArgs, callback){
    if(2===arguments.length && 'function'===typeof msgArgs){
      callback = msgArgs;
      msgArgs = undefined;
    }
    const p = 1







|
|
<
<
<

|
<
>


|
>
>
>
>
>
|







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
      w.onerror = (event)=>error("worker.onerror",event);
      return w;
    },
    debug: 1 ? undefined : (...args)=>console.debug('worker debug',...args),
    onunhandled: function(ev){
      error("Unhandled worker message:",ev.data);
    },
    onerror: function(ev){
      error("worker1 error:",ev);



    },
    onready: function(f){

      warn("This is the v2 interface - don't pass an onready() function.");
    }
  };
  const workerPromise = await globalThis.sqlite3Worker1Promiser.v2(promiserConfig)
        .then((func)=>{
          log("Init complete. Starting tests momentarily.");
          globalThis.sqlite3TestModule.setStatus(null)/*hide the HTML-side is-loading spinner*/;
          return func;
        });
  delete globalThis.sqlite3Worker1Promiser;

  const wtest = async function(msgType, msgArgs, callback){
    if(2===arguments.length && 'function'===typeof msgArgs){
      callback = msgArgs;
      msgArgs = undefined;
    }
    const p = 1
269
270
271
272
273
274
275
276
277
    });

    await wtest('close', (ev)=>{
      T.assert(undefined === ev.result.filename);
    }).finally(()=>logHtml('',"That's all, folks!"));
  }/*runTests2()*/;

  log("Init complete, but async init bits may still be running.");
})();







|

271
272
273
274
275
276
277
278
279
    });

    await wtest('close', (ev)=>{
      T.assert(undefined === ev.result.filename);
    }).finally(()=>logHtml('',"That's all, folks!"));
  }/*runTests2()*/;

  runTests();
})();