Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 2 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@sqlite.org/sqlite-wasm",
"version": "3.51.2-build2",
"version": "3.51.2-build3",
"description": "SQLite Wasm conveniently wrapped as an ES Module.",
"type": "module",
"repository": {
Expand Down
50 changes: 50 additions & 0 deletions src/__tests__/bundler-compatibility.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { describe, test, expect } from 'vitest';
import { execSync } from 'node:child_process';
import path from 'node:path';
import fs from 'node:fs';

describe('Vite bundler compatibility', () => {
test('should rename sqlite3.wasm with a hash and update the import URL', () => {
const testDir = path.resolve(__dirname, 'vite-repro');
const distDir = path.resolve(testDir, 'dist');

// Clean up previous build
if (fs.existsSync(distDir)) {
fs.rmSync(distDir, { recursive: true, force: true });
}

// Run vite build
execSync('npx vite build', { cwd: testDir, stdio: 'inherit' });

// 1. Check if hashed WASM file exists in dist/assets
const assetsDir = path.resolve(distDir, 'assets');
const files = fs.readdirSync(assetsDir);
const wasmFile = files.find(
(f) => f.startsWith('sqlite3-') && f.endsWith('.wasm'),
);

expect(wasmFile).toBeDefined();

// 2. Check if the JS bundle contains the hashed WASM filename
const assetsDirJs = path.resolve(distDir, 'assets');
const jsFiles = fs
.readdirSync(assetsDirJs)
.filter((f) => f.endsWith('.js'));
const mainBundle = jsFiles.find((f) => f.startsWith('index-'));
expect(mainBundle).toBeDefined();

const bundleContent = fs.readFileSync(
path.resolve(assetsDirJs, mainBundle),
'utf8',
);

// It should contain something like: new URL("/assets/sqlite3-hash.wasm", import.meta.url)
expect(bundleContent).toContain(wasmFile);

// Specifically check that it's part of a new URL call or at least correctly referenced
const urlPattern = new RegExp(
`new URL\\(".*${wasmFile}",\\s*import\\.meta\\.url\\)`,
);
expect(bundleContent).toMatch(urlPattern);
});
});
6 changes: 6 additions & 0 deletions src/__tests__/vite-repro/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<!doctype html>
<html>
<body>
<script type="module" src="./main.js"></script>
</body>
</html>
3 changes: 3 additions & 0 deletions src/__tests__/vite-repro/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import sqlite3InitModule from '../../../src/index.js';

await sqlite3InitModule();
87 changes: 5 additions & 82 deletions src/bin/sqlite3-bundler-friendly.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
**
** SQLITE_VERSION "3.52.0"
** SQLITE_VERSION_NUMBER 3052000
** SQLITE_SOURCE_ID "2026-01-20 10:57:44 346ad366a8ebed1e7936c59f8a40e9c8e7e31d0153bc4f654a47b2ddc39b18ca"
** SQLITE_SOURCE_ID "2026-01-20 18:30:48 2b3b36da9d60c265dceec5964ea51c752d81f41459fb6849c8faea658b253552"
**
** Emscripten SDK: 4.0.23
*/
Expand Down Expand Up @@ -94,85 +94,6 @@ var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIR

./c-pp-lite -o ./bld/pre-js.bundler.js -Dtarget:es6-module -Dtarget:es6-bundler-friendly -DModule.instantiateWasm api/pre-js.c-pp.js
*/
(function(Module){
const sIMS =
globalThis.sqlite3InitModuleState/*from extern-post-js.c-pp.js*/
|| Object.assign(Object.create(null),{
/* In WASMFS builds this file gets loaded once per thread,
but sqlite3InitModuleState is not getting set for the
worker threads? That those workers seem to function fine
despite that is curious. */
debugModule: function(){
console.warn("globalThis.sqlite3InitModuleState is missing",arguments);
}
});
delete globalThis.sqlite3InitModuleState;
sIMS.debugModule('pre-js.js sqlite3InitModuleState =',sIMS);

/**
This custom locateFile() tries to figure out where to load `path`
from. The intent is to provide a way for foo/bar/X.js loaded from a
Worker constructor or importScripts() to be able to resolve
foo/bar/X.wasm (in the latter case, with some help):

1) If URL param named the same as `path` is set, it is returned.

2) If sqlite3InitModuleState.sqlite3Dir is set, then (thatName + path)
is returned (it's assumed to end with '/').

3) If this code is running in the main UI thread AND it was loaded
from a SCRIPT tag, the directory part of that URL is used
as the prefix. (This form of resolution unfortunately does not
function for scripts loaded via importScripts().)

4) If none of the above apply, (prefix+path) is returned.

None of the above apply in ES6 builds, which uses a much simpler
approach.
*/
Module['locateFile'] = function(path, prefix) {
return new URL(path, import.meta.url).href;
}.bind(sIMS);

/**
Override Module.instantiateWasm().

A custom Module.instantiateWasm() does not work in WASMFS builds:

https://github.com/emscripten-core/emscripten/issues/17951

In such builds we must disable this.

It's disabled in the (unsupported/untested) node builds because
node does not do fetch().
*/
Module['instantiateWasm'] = function callee(imports,onSuccess){
const sims = this;
const uri = Module.locateFile(
sims.wasmFilename, (
('undefined'===typeof scriptDirectory/*var defined by Emscripten glue*/)
? "" : scriptDirectory)
);
sims.debugModule("instantiateWasm() uri =", uri, "sIMS =",this);
const wfetch = ()=>fetch(uri, {credentials: 'same-origin'});
const finalThen = (arg)=>{
arg.imports = imports;
sims.instantiateWasm = arg /* used by sqlite3-api-prologue.c-pp.js */;
onSuccess(arg.instance, arg.module);
};
const loadWasm = WebAssembly.instantiateStreaming
? async ()=>
WebAssembly
.instantiateStreaming(wfetch(), imports)
.then(finalThen)
: async ()=>// Safari < v15
wfetch()
.then(response => response.arrayBuffer())
.then(bytes => WebAssembly.instantiate(bytes, imports))
.then(finalThen)
return loadWasm();
}.bind(sIMS);
})(Module);
/* END FILE: api/pre-js.js. */
// end include: ./bld/pre-js.bundler.js

Expand Down Expand Up @@ -4824,7 +4745,7 @@ Module.runSQLite3PostLoadInit = async function(
**
** SQLITE_VERSION "3.52.0"
** SQLITE_VERSION_NUMBER 3052000
** SQLITE_SOURCE_ID "2026-01-20 10:57:44 346ad366a8ebed1e7936c59f8a40e9c8e7e31d0153bc4f654a47b2ddc39b18ca"
** SQLITE_SOURCE_ID "2026-01-20 18:30:48 2b3b36da9d60c265dceec5964ea51c752d81f41459fb6849c8faea658b253552"
**
** Emscripten SDK: 4.0.23
*/
Expand Down Expand Up @@ -6999,7 +6920,7 @@ globalThis.sqlite3ApiBootstrap.defaultConfig = Object.create(null);
*/
globalThis.sqlite3ApiBootstrap.sqlite3 = undefined;
globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
sqlite3.version = {"libVersion": "3.52.0", "libVersionNumber": 3052000, "sourceId": "2026-01-20 10:57:44 346ad366a8ebed1e7936c59f8a40e9c8e7e31d0153bc4f654a47b2ddc39b18ca","downloadVersion": 3520000,"scm":{ "sha3-256": "346ad366a8ebed1e7936c59f8a40e9c8e7e31d0153bc4f654a47b2ddc39b18ca","branch": "trunk","tags": "","datetime": "2026-01-20T10:57:44.925Z"}};
sqlite3.version = {"libVersion": "3.52.0", "libVersionNumber": 3052000, "sourceId": "2026-01-20 18:30:48 2b3b36da9d60c265dceec5964ea51c752d81f41459fb6849c8faea658b253552","downloadVersion": 3520000,"scm":{ "sha3-256": "2b3b36da9d60c265dceec5964ea51c752d81f41459fb6849c8faea658b253552","branch": "trunk","tags": "","datetime": "2026-01-20T18:30:48.704Z"}};
});
/**
2022-07-08
Expand Down Expand Up @@ -21047,6 +20968,8 @@ const toExportForESM =

const sIM = globalThis.sqlite3InitModule = function ff(...args){
//console.warn("Using replaced sqlite3InitModule()",globalThis.location);
sIMS.emscriptenLocateFile = args[0]?.locateFile /* see pre-js.c-pp.js [tag:locateFile] */;
sIMS.emscriptenInstantiateWasm = args[0]?.instantiateWasm /* see pre-js.c-pp.js [tag:locateFile] */;
return originalInit(...args).then((EmscriptenModule)=>{
sIMS.debugModule("sqlite3InitModule() sIMS =",sIMS);
sIMS.debugModule("sqlite3InitModule() EmscriptenModule =",EmscriptenModule);
Expand Down
55 changes: 9 additions & 46 deletions src/bin/sqlite3-node.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
**
** SQLITE_VERSION "3.52.0"
** SQLITE_VERSION_NUMBER 3052000
** SQLITE_SOURCE_ID "2026-01-20 10:57:44 346ad366a8ebed1e7936c59f8a40e9c8e7e31d0153bc4f654a47b2ddc39b18ca"
** SQLITE_SOURCE_ID "2026-01-20 18:30:48 2b3b36da9d60c265dceec5964ea51c752d81f41459fb6849c8faea658b253552"
**
** Emscripten SDK: 4.0.23
*/
Expand Down Expand Up @@ -105,50 +105,11 @@ if (ENVIRONMENT_IS_NODE) {

This SQLite JS build configuration is entirely unsupported! It has
not been tested beyond the ability to compile it. It may not
load. It may not work properly. Only builds targeting browser
environments are supported and tested.
load. It may not work properly. Only builds _directly_ targeting
browser environments ("vanilla" JS and ESM modules) are supported
and tested. Builds which _indirectly_ target browsers (namely
bundler-friendly builds) are not supported deliverables.
*/
(function(Module){
const sIMS =
globalThis.sqlite3InitModuleState/*from extern-post-js.c-pp.js*/
|| Object.assign(Object.create(null),{
/* In WASMFS builds this file gets loaded once per thread,
but sqlite3InitModuleState is not getting set for the
worker threads? That those workers seem to function fine
despite that is curious. */
debugModule: function(){
console.warn("globalThis.sqlite3InitModuleState is missing",arguments);
}
});
delete globalThis.sqlite3InitModuleState;
sIMS.debugModule('pre-js.js sqlite3InitModuleState =',sIMS);

/**
This custom locateFile() tries to figure out where to load `path`
from. The intent is to provide a way for foo/bar/X.js loaded from a
Worker constructor or importScripts() to be able to resolve
foo/bar/X.wasm (in the latter case, with some help):

1) If URL param named the same as `path` is set, it is returned.

2) If sqlite3InitModuleState.sqlite3Dir is set, then (thatName + path)
is returned (it's assumed to end with '/').

3) If this code is running in the main UI thread AND it was loaded
from a SCRIPT tag, the directory part of that URL is used
as the prefix. (This form of resolution unfortunately does not
function for scripts loaded via importScripts().)

4) If none of the above apply, (prefix+path) is returned.

None of the above apply in ES6 builds, which uses a much simpler
approach.
*/
Module['locateFile'] = function(path, prefix) {
return new URL(path, import.meta.url).href;
}.bind(sIMS);

})(Module);
/* END FILE: api/pre-js.js. */
// end include: ./bld/pre-js.node.js

Expand Down Expand Up @@ -4842,7 +4803,7 @@ Module.runSQLite3PostLoadInit = async function(
**
** SQLITE_VERSION "3.52.0"
** SQLITE_VERSION_NUMBER 3052000
** SQLITE_SOURCE_ID "2026-01-20 10:57:44 346ad366a8ebed1e7936c59f8a40e9c8e7e31d0153bc4f654a47b2ddc39b18ca"
** SQLITE_SOURCE_ID "2026-01-20 18:30:48 2b3b36da9d60c265dceec5964ea51c752d81f41459fb6849c8faea658b253552"
**
** Emscripten SDK: 4.0.23
*/
Expand Down Expand Up @@ -7017,7 +6978,7 @@ globalThis.sqlite3ApiBootstrap.defaultConfig = Object.create(null);
*/
globalThis.sqlite3ApiBootstrap.sqlite3 = undefined;
globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
sqlite3.version = {"libVersion": "3.52.0", "libVersionNumber": 3052000, "sourceId": "2026-01-20 10:57:44 346ad366a8ebed1e7936c59f8a40e9c8e7e31d0153bc4f654a47b2ddc39b18ca","downloadVersion": 3520000,"scm":{ "sha3-256": "346ad366a8ebed1e7936c59f8a40e9c8e7e31d0153bc4f654a47b2ddc39b18ca","branch": "trunk","tags": "","datetime": "2026-01-20T10:57:44.925Z"}};
sqlite3.version = {"libVersion": "3.52.0", "libVersionNumber": 3052000, "sourceId": "2026-01-20 18:30:48 2b3b36da9d60c265dceec5964ea51c752d81f41459fb6849c8faea658b253552","downloadVersion": 3520000,"scm":{ "sha3-256": "2b3b36da9d60c265dceec5964ea51c752d81f41459fb6849c8faea658b253552","branch": "trunk","tags": "","datetime": "2026-01-20T18:30:48.704Z"}};
});
/**
2022-07-08
Expand Down Expand Up @@ -18157,6 +18118,8 @@ const toExportForESM =

const sIM = globalThis.sqlite3InitModule = function ff(...args){
//console.warn("Using replaced sqlite3InitModule()",globalThis.location);
sIMS.emscriptenLocateFile = args[0]?.locateFile /* see pre-js.c-pp.js [tag:locateFile] */;
sIMS.emscriptenInstantiateWasm = args[0]?.instantiateWasm /* see pre-js.c-pp.js [tag:locateFile] */;
return originalInit(...args).then((EmscriptenModule)=>{
sIMS.debugModule("sqlite3InitModule() sIMS =",sIMS);
sIMS.debugModule("sqlite3InitModule() EmscriptenModule =",EmscriptenModule);
Expand Down
Loading