1f71c954cSstephan/* extern-post-js.js must be appended to the resulting sqlite3.js
2f861b36bSstephan   file. It gets its name from being used as the value for the
3f861b36bSstephan   --extern-post-js=... Emscripten flag. Note that this code, unlike
4f861b36bSstephan   most of the associated JS code, runs outside of the
5f861b36bSstephan   Emscripten-generated module init scope, in the current
6f861b36bSstephan   global scope. */
7b94a9860Sstephan(function(){
8b94a9860Sstephan  /**
9b94a9860Sstephan     In order to hide the sqlite3InitModule()'s resulting Emscripten
10b94a9860Sstephan     module from downstream clients (and simplify our documentation by
11b94a9860Sstephan     being able to elide those details), we rewrite
12b94a9860Sstephan     sqlite3InitModule() to return the sqlite3 object.
13b94a9860Sstephan
14b94a9860Sstephan     Unfortunately, we cannot modify the module-loader/exporter-based
15b94a9860Sstephan     impls which Emscripten installs at some point in the file above
16b94a9860Sstephan     this.
17b94a9860Sstephan  */
18b94a9860Sstephan  const originalInit = self.sqlite3InitModule;
19b94a9860Sstephan  if(!originalInit){
20b94a9860Sstephan    throw new Error("Expecting self.sqlite3InitModule to be defined by the Emscripten build.");
21b94a9860Sstephan  }
22cd0df83cSstephan  /**
23cd0df83cSstephan     We need to add some state which our custom Module.locateFile()
24cd0df83cSstephan     can see, but an Emscripten limitation currently prevents us from
25cd0df83cSstephan     attaching it to the sqlite3InitModule function object:
26cd0df83cSstephan
27cd0df83cSstephan     https://github.com/emscripten-core/emscripten/issues/18071
28cd0df83cSstephan
29d89a66ecSstephan     The only(?) current workaround is to temporarily stash this state
30cd0df83cSstephan     into the global scope and delete it when sqlite3InitModule()
31cd0df83cSstephan     is called.
32cd0df83cSstephan  */
33cd0df83cSstephan  const initModuleState = self.sqlite3InitModuleState = Object.assign(Object.create(null),{
34cd0df83cSstephan    moduleScript: self?.document?.currentScript,
35d89a66ecSstephan    isWorker: ('undefined' !== typeof WorkerGlobalScope),
36cd0df83cSstephan    location: self.location,
37cd0df83cSstephan    urlParams: new URL(self.location.href).searchParams
38cd0df83cSstephan  });
39*1fc6ffccSstephan  initModuleState.debugModule =
40*1fc6ffccSstephan    (new URL(self.location.href).searchParams).has('sqlite3.debugModule')
41*1fc6ffccSstephan    ? (...args)=>console.warn('sqlite3.debugModule:',...args)
42*1fc6ffccSstephan    : ()=>{};
43*1fc6ffccSstephan
44cd0df83cSstephan  if(initModuleState.urlParams.has('sqlite3.dir')){
45cd0df83cSstephan    initModuleState.sqlite3Dir = initModuleState.urlParams.get('sqlite3.dir') +'/';
46d89a66ecSstephan  }else if(initModuleState.moduleScript){
47d89a66ecSstephan    const li = initModuleState.moduleScript.src.split('/');
48d89a66ecSstephan    li.pop();
49d89a66ecSstephan    initModuleState.sqlite3Dir = li.join('/') + '/';
50d89a66ecSstephan  }
51cd0df83cSstephan
52b94a9860Sstephan  self.sqlite3InitModule = (...args)=>{
53b94a9860Sstephan    //console.warn("Using replaced sqlite3InitModule()",self.location);
54b94a9860Sstephan    return originalInit(...args).then((EmscriptenModule)=>{
55b94a9860Sstephan      if(self.window!==self &&
56b94a9860Sstephan         (EmscriptenModule['ENVIRONMENT_IS_PTHREAD']
57b94a9860Sstephan          || EmscriptenModule['_pthread_self']
58b94a9860Sstephan          || 'function'===typeof threadAlert
59b94a9860Sstephan          || self.location.pathname.endsWith('.worker.js')
60b94a9860Sstephan         )){
61b94a9860Sstephan        /** Workaround for wasmfs-generated worker, which calls this
62b94a9860Sstephan            routine from each individual thread and requires that its
63b94a9860Sstephan            argument be returned. All of the criteria above are fragile,
64b94a9860Sstephan            based solely on inspection of the offending code, not public
65b94a9860Sstephan            Emscripten details. */
66b94a9860Sstephan        return EmscriptenModule;
67b94a9860Sstephan      }
68cd0df83cSstephan      EmscriptenModule.sqlite3.scriptInfo = initModuleState;
69cd0df83cSstephan      //console.warn("sqlite3.scriptInfo =",EmscriptenModule.sqlite3.scriptInfo);
70b94a9860Sstephan      const f = EmscriptenModule.sqlite3.asyncPostInit;
71b94a9860Sstephan      delete EmscriptenModule.sqlite3.asyncPostInit;
72b94a9860Sstephan      return f();
73e67a0f40Sstephan    }).catch((e)=>{
74e67a0f40Sstephan      console.error("Exception loading sqlite3 module:",e);
75e67a0f40Sstephan      throw e;
76b94a9860Sstephan    });
77b94a9860Sstephan  };
78e67a0f40Sstephan  self.sqlite3InitModule.ready = originalInit.ready;
7971de8e02Sstephan
80cd0df83cSstephan  if(self.sqlite3InitModuleState.moduleScript){
81cd0df83cSstephan    const sim = self.sqlite3InitModuleState;
82cd0df83cSstephan    let src = sim.moduleScript.src.split('/');
83cd0df83cSstephan    src.pop();
84cd0df83cSstephan    sim.scriptDir = src.join('/') + '/';
85cd0df83cSstephan  }
86*1fc6ffccSstephan  initModuleState.debugModule('sqlite3InitModuleState =',initModuleState);
8771de8e02Sstephan  if(0){
88cd0df83cSstephan    console.warn("Replaced sqlite3InitModule()");
8971de8e02Sstephan    console.warn("self.location.href =",self.location.href);
9071de8e02Sstephan    if('undefined' !== typeof document){
9171de8e02Sstephan      console.warn("document.currentScript.src =",
9271de8e02Sstephan                   document?.currentScript?.src);
9371de8e02Sstephan    }
9471de8e02Sstephan  }
95d89a66ecSstephan  /* Replace the various module exports performed by the Emscripten
96d89a66ecSstephan     glue... */
97d89a66ecSstephan  if (typeof exports === 'object' && typeof module === 'object')
98d89a66ecSstephan    module.exports = sqlite3InitModule;
99d89a66ecSstephan  else if (typeof exports === 'object')
100d89a66ecSstephan    exports["sqlite3InitModule"] = sqlite3InitModule;
101d89a66ecSstephan  /* AMD modules get injected in a way we cannot override,
102d89a66ecSstephan     so we can't handle those here. */
103cd0df83cSstephan})();
104