]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
JavaScript: add sqlite3.wasm.realloc(), sqlite3.capi.SQLITE_MAX_ALLOCATION_SIZE,...
authorstephan <stephan@noemail.net>
Sat, 3 Dec 2022 11:16:55 +0000 (11:16 +0000)
committerstephan <stephan@noemail.net>
Sat, 3 Dec 2022 11:16:55 +0000 (11:16 +0000)
FossilOrigin-Name: eeb84ba5de1152ef0f42105b8b285fdee9f5ad58281e60a4e0c8b1d6de1dead8

ext/wasm/GNUmakefile
ext/wasm/api/sqlite3-api-glue.js
ext/wasm/api/sqlite3-api-prologue.js
ext/wasm/api/sqlite3-wasm.c
ext/wasm/tester1-worker.html
ext/wasm/tester1.c-pp.js
manifest
manifest.uuid

index 71c508f7c20d05f8f9e77f3d8ff530a543805fe8..968d4f440c9b7bcfe13f9f0242bbe5b3e7ae4dbb 100644 (file)
@@ -489,7 +489,7 @@ emcc.jsflags += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.$(emcc.INITIAL_MEMORY))
 
 emcc.jsflags += $(emcc.environment)
 emcc.jsflags += -sSTACK_SIZE=1MB
-# ^^^ ACHTUNG: emsdk 3.1.27 reduced the default stack size from 4MB to
+# ^^^ 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.
 ########################################################################
index e60baeb7f3a07e1fde7742dd52ad3cbfdfbfa8ec..ac1e9fd6d62885cc7b46e54c35efd5633fe02702 100644 (file)
@@ -605,6 +605,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
     //console.debug('wasm.ctype length =',wasm.cstrlen(cJson));
     for(const t of ['access', 'blobFinalizers', 'dataTypes',
                     'encodings', 'fcntl', 'flock', 'ioCap',
+                    'limits',
                     'openFlags', 'prepareFlags', 'resultCodes',
                     'serialize', 'syncFlags', 'trace', 'udfFlags',
                     'version'
index a99065663de5970428bcdaa6cba47fab32c79a89..b6ff94dfe42b5c67991a6cf7f52fcfbca95120cb 100644 (file)
      the `free(3)`-compatible routine for the WASM
      environment. Defaults to `"sqlite3_free"`.
 
+   - `reallocExportName`: the name of the function, in `exports`, of
+     the `realloc(3)`-compatible routine for the WASM
+     environment. Defaults to `"sqlite3_realloc"`.
+
    - `wasmfsOpfsDir`[^1]: if the environment supports persistent
      storage using OPFS-over-WASMFS , this directory names the "mount
      point" for that directory. It must be prefixed by `/` and may
@@ -110,6 +114,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
     })(),
     allocExportName: 'sqlite3_malloc',
     deallocExportName: 'sqlite3_free',
+    reallocExportName: 'sqlite3_realloc',
     wasmfsOpfsDir: '/opfs'
   }, apiConfig || {});
 
@@ -284,12 +289,14 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
   };
 
   /**
-     Returns true if v appears to be one of our bind()-able
-     TypedArray types: Uint8Array or Int8Array. Support for
-     TypedArrays with element sizes >1 is TODO.
+     Returns true if v appears to be one of our bind()-able TypedArray
+     types: Uint8Array or Int8Array. Support for TypedArrays with
+     element sizes >1 is a potential TODO just waiting on a use case
+     to justify them.
   */
   const isBindableTypedArray = (v)=>{
-    return v && v.constructor && (1===v.constructor.BYTES_PER_ELEMENT);
+    return v && (v instanceof Uint8Array || v instanceof Int8Array);
+    //v && v.constructor && (1===v.constructor.BYTES_PER_ELEMENT);
   };
 
   /**
@@ -302,7 +309,8 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
      isSQLableTypedArray() list.
   */
   const isSQLableTypedArray = (v)=>{
-    return v && v.constructor && (1===v.constructor.BYTES_PER_ELEMENT);
+    return v && (v instanceof Uint8Array || v instanceof Int8Array);
+    //v && v.constructor && (1===v.constructor.BYTES_PER_ELEMENT);
   };
 
   /** Returns true if isBindableTypedArray(v) does, else throws with a message
@@ -664,12 +672,12 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
               "or config.memory (imported)."),
 
     /**
-       The API's one single point of access to the WASM-side memory
-       allocator. Works like malloc(3) (and is likely bound to
-       malloc()) but throws an WasmAllocError if allocation fails. It is
-       important that any code which might pass through the sqlite3 C
-       API NOT throw and must instead return SQLITE_NOMEM (or
-       equivalent, depending on the context).
+       The API's primary point of access to the WASM-side memory
+       allocator.  Works like sqlite3_malloc() but throws a
+       WasmAllocError if allocation fails. It is important that any
+       code which might pass through the sqlite3 C API NOT throw and
+       must instead return SQLITE_NOMEM (or equivalent, depending on
+       the context).
 
        Very few cases in the sqlite3 JS APIs can result in
        client-defined functions propagating exceptions via the C-style
@@ -681,7 +689,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
        catch exceptions and convert them to appropriate error codes.
 
        For cases where non-throwing allocation is required, use
-       sqlite3.wasm.alloc.impl(), which is direct binding of the
+       this.alloc.impl(), which is direct binding of the
        underlying C-level allocator.
 
        Design note: this function is not named "malloc" primarily
@@ -692,9 +700,27 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
     alloc: undefined/*installed later*/,
 
     /**
-       The API's one single point of access to the WASM-side memory
-       deallocator. Works like free(3) (and is likely bound to
-       free()).
+       Rarely necessary in JS code, this routine works like
+       sqlite3_realloc(M,N), where M is either NULL or a pointer
+       obtained from this function or this.alloc() and N is the number
+       of bytes to reallocate the block to. Returns a pointer to the
+       reallocated block or 0 if allocation fails.
+
+       If M is NULL and N is positive, this behaves like
+       this.alloc(N). If N is 0, it behaves like this.dealloc().
+       Results are undefined if N is negative (sqlite3_realloc()
+       treats that as 0, but if this code is built with a different
+       allocator it may misbehave with negative values).
+
+       Like this.alloc.impl(), this.realloc.impl() is a direct binding
+       to the underlying realloc() implementation which does not throw
+       exceptions, instead returning 0 on allocation error.
+    */
+    realloc: undefined/*installed later*/,
+
+    /**
+       The API's primary point of access to the WASM-side memory
+       deallocator. Works like sqlite3_free().
 
        Design note: this function is not named "free" for the same
        reason that this.alloc() is not called this.malloc().
@@ -731,20 +757,30 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
     return pRet;
   };
 
-  const keyAlloc = config.allocExportName,
-        keyDealloc =  config.deallocExportName;
-  for(const key of [keyAlloc, keyDealloc]){
-    const f = wasm.exports[key];
-    if(!(f instanceof Function)) toss3("Missing required exports[",key,"] function.");
-  }
+  {
+    // Set up allocators...
+    const keyAlloc = config.allocExportName,
+          keyDealloc = config.deallocExportName,
+          keyRealloc = config.reallocExportName;
+    for(const key of [keyAlloc, keyDealloc, keyRealloc]){
+      const f = wasm.exports[key];
+      if(!(f instanceof Function)) toss3("Missing required exports[",key,"] function.");
+    }
 
-  wasm.alloc = function f(n){
-    const m = f.impl(n);
-    if(!m) throw new WasmAllocError("Failed to allocate",n," bytes.");
-    return m;
-  };
-  wasm.alloc.impl = wasm.exports[keyAlloc];
-  wasm.dealloc = wasm.exports[keyDealloc];
+    wasm.alloc = function f(n){
+      const m = f.impl(n);
+      if(!m) throw new WasmAllocError("Failed to allocate",n," bytes.");
+      return m;
+    };
+    wasm.alloc.impl = wasm.exports[keyAlloc];
+    wasm.realloc = function f(m,n){
+      const m2 = f.impl(m,n);
+      if(n && !m2) throw new WasmAllocError("Failed to reallocate",n," bytes.");
+      return n ? m2 : 0;
+    };
+    wasm.realloc.impl = wasm.exports[keyRealloc];
+    wasm.dealloc = wasm.exports[keyDealloc];
+  }
 
   /**
      Reports info about compile-time options using
index 9acc8020e57a538043fa94cae209030194616332..cbc4499760a2642c6f8c74e421ba6bd5a4b658d7 100644 (file)
 #  define SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
 #endif
 
+/**********************************************************************/
+/* SQLITE_M... */
+#ifndef SQLITE_MAX_ALLOCATION_SIZE
+# define SQLITE_MAX_ALLOCATION_SIZE 0x1fffffff
+#endif
+
 /**********************************************************************/
 /* SQLITE_O... */
 #ifndef SQLITE_OMIT_DEPRECATED
@@ -497,6 +503,10 @@ const char * sqlite3_wasm_enum_json(void){
     DefInt(SQLITE_IOCAP_BATCH_ATOMIC);
   } _DefGroup;
 
+  DefGroup(limits) {
+    DefInt(SQLITE_MAX_ALLOCATION_SIZE);
+  } _DefGroup;
+
   DefGroup(openFlags) {
     /* Noting that not all of these will have any effect in
     ** WASM-space. */
index ee03874df3820ddd0f8661180e9c998a0dc18523..eba3fdeb4ef99bcd10a1f02cc7336ab4b5a96f0a 100644 (file)
@@ -45,7 +45,7 @@
       if(urlParams.has('esm')){
           logHtml('warning',"Attempting to run an ES6 Worker Module, "+
                   "which is not supported by all browsers! "+
-                  "e.g. Firefox (as of 2022-11) cannot do this.");
+                  "e.g. Firefox (as of 2022-12) cannot do this.");
         workerArgs.push("tester1.mjs",{type:"module"});
         document.querySelectorAll('title,#color-target').forEach((e)=>{
           e.innerText = "sqlite3 tester #1: ES6 Worker Module";
index 1db8499ef6c2136a668d922bddc12a17de748628..949d2365c4b325c1c0015bd75bcada7787e4c149 100644 (file)
@@ -424,6 +424,38 @@ self.sqlite3InitModule = sqlite3InitModule;
         }
       }
 
+      // alloc(), realloc(), allocFromTypedArray()
+      {
+        let m = w.alloc(14);
+        let m2 = w.realloc(m, 16);
+        T.assert(m === m2/* because of alignment */);
+        T.assert(0 === w.realloc(m, 0));
+        m = m2 = 0;
+
+        // Check allocation limits and allocator's responses...
+        T.assert('number' === typeof sqlite3.capi.SQLITE_MAX_ALLOCATION_SIZE);
+        const tooMuch = sqlite3.capi.SQLITE_MAX_ALLOCATION_SIZE + 1,
+              isAllocErr = (e)=>e instanceof sqlite3.WasmAllocError;
+        T.mustThrowMatching(()=>w.alloc(tooMuch), isAllocErr)
+          .assert(0 === w.alloc.impl(tooMuch))
+          .mustThrowMatching(()=>w.realloc(0, tooMuch), isAllocErr)
+          .assert(0 === w.realloc.impl(0, tooMuch));
+
+        // Check allocFromTypedArray()...
+        const byteList = [11,22,33]
+        const u = new Uint8Array(byteList);
+        m = w.allocFromTypedArray(u);
+        for(let i = 0; i < u.length; ++i){
+          T.assert(u[i] === byteList[i])
+            .assert(u[i] === w.getMemValue(m + i, 'i8'));
+        }
+        w.dealloc(m);
+        T.mustThrowMatching(
+          ()=>w.allocFromTypedArray(1),
+          'Value is not of a supported TypedArray type.'
+        );
+      }
+
       // isPtr32()
       {
         const ip = w.isPtr32;
index da738ab08ba23bb45e933feb7c4cc99cb072c688..696930b4d7f367c9d3801cba65917271320e53a7 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C wasm\sbuild:\srename\sthe\spath\sto\sthe\swasm\sdocs\scheckout,\sfor\sclarity\sand\sconsistency.
-D 2022-12-03T03:06:16.365
+C JavaScript:\sadd\ssqlite3.wasm.realloc(),\ssqlite3.capi.SQLITE_MAX_ALLOCATION_SIZE,\sand\srelated\stests.
+D 2022-12-03T11:16:55.292
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -491,7 +491,7 @@ F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
 F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
 F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
-F ext/wasm/GNUmakefile 004f3662abc5588d0e460893ad8f0fd94c970957159b6bba97087bac27d78007
+F ext/wasm/GNUmakefile bfa47f169468ca9db031105b0e336db29a88e93c3abd217d0bbb2b8731fa5413
 F ext/wasm/README-dist.txt 2d670b426fc7c613b90a7d2f2b05b433088fe65181abead970980f0a4a75ea20
 F ext/wasm/README.md ef39861aa21632fdbca0bdd469f78f0096f6449a720f3f39642594af503030e9
 F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api b4d68c97d14944b48d55e06aa44f544a6f56a7fa2bcb6f9e030936a5b2a9479a
@@ -503,16 +503,16 @@ F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08
 F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62
 F ext/wasm/api/pre-js.c-pp.js b88499dc303c21fc3f55f2c364a0f814f587b60a95784303881169f9e91c1d5f
 F ext/wasm/api/sqlite3-api-cleanup.js 680d5ccfff54459db136a49b2199d9f879c8405d9c99af1dda0cc5e7c29056f4
-F ext/wasm/api/sqlite3-api-glue.js b528207ba43f7740d1ade623f3f6b08a49f44ce7e9126915b78e1818c2466d8e
+F ext/wasm/api/sqlite3-api-glue.js 6fe39964605fda3b699f69365eed565b5172d29cab2c49bc057a43f9a93f9f36
 F ext/wasm/api/sqlite3-api-oo1.js 91a7d7b9203fb0f031e6ba380a644a7f871e1798b388de399c01ed4087bac9e0
-F ext/wasm/api/sqlite3-api-prologue.js 42d6b316b542cf8e086f2f272460deb72dff184f1438a3377383cab99b08070b
+F ext/wasm/api/sqlite3-api-prologue.js 3d9550021269fd97636595ea2d2a1ec3ce00866f0a5d3b5fab94d4583afdafe0
 F ext/wasm/api/sqlite3-api-worker1.js e94ba98e44afccfa482874cd9acb325883ade50ed1f9f9526beb9de1711f182f
 F ext/wasm/api/sqlite3-license-version-header.js a661182fc93fc2cf212dfd0b987f8e138a3ac98f850b1112e29b5fbdaecc87c3
 F ext/wasm/api/sqlite3-opfs-async-proxy.js f79dd8d98ef3e0b55c10bb2bee7a3840fa967318e1f577c156aafc34664271d1
 F ext/wasm/api/sqlite3-vfs-helper.js 4ad4faf02e1524bf0296be8452c00b5708dce6faf649468d0377e26a0b299263
 F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 29d6487a26b2fb6a471cde52c37ffee7c27ed6a91914b308c247e0706f454ffb
 F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
-F ext/wasm/api/sqlite3-wasm.c 733bc939f93caef0df0b3ebfea14cbd528da580fdef1a35b1f69c2b3e044c7b7
+F ext/wasm/api/sqlite3-wasm.c 69c2c1bf555dd25596137bf282d721657d5c49243061e0cb420375203107adcd
 F ext/wasm/api/sqlite3-worker1-promiser.js 0c7a9826dbf82a5ed4e4f7bf7816e825a52aff253afbf3350431f5773faf0e4b
 F ext/wasm/api/sqlite3-worker1.js 1e54ea3d540161bcfb2100368a2fc0cad871a207b8336afee1c445715851ec54
 F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8
@@ -553,9 +553,9 @@ F ext/wasm/sql/000-mandelbrot.sql 775337a4b80938ac8146aedf88808282f04d02d983d826
 F ext/wasm/sql/001-sudoku.sql 35b7cb7239ba5d5f193bc05ec379bcf66891bce6f2a5b3879f2f78d0917299b5
 F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555e685bce3da8c3f
 F ext/wasm/test-opfs-vfs.js 44363db07b2a20e73b0eb1808de4400ca71b703af718d0fa6d962f15e73bf2ac
-F ext/wasm/tester1-worker.html ead6bdcc6cca221deb0dc9855a56f376351dbf2294fd7978cd1609b3a56b245b
+F ext/wasm/tester1-worker.html 29b1d87f7d51f70d61645719fee657f3787fe939bb695f27034c75404e8f1e6f
 F ext/wasm/tester1.c-pp.html 74aa9b31c75f12490653f814b53c3dd39f40cd3f70d6a53a716f4e8587107399
-F ext/wasm/tester1.c-pp.js e73a91eba4b59aaadd98f383c00a5101dbbbc52d937fff3162fc4761986f4a88
+F ext/wasm/tester1.c-pp.js d25cea43933bf86590aab63038a6a0b6e7002ffba7e85d8df2720b7a69f85690
 F ext/wasm/tests/opfs/concurrency/index.html 86d8ac435074d1e7007b91105f4897f368c165e8cecb6a9aa3d81f5cf5dcbe70
 F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
 F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
@@ -2065,8 +2065,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 13eb1abd06f55fb88fc7f7be6149fd94b12057d9c38cc6b97bec3940e7e01f04
-R f5c92ee96049664c2a17edeac52c505f
+P b820db32365b2ca8e2397fd6ea85883e4555ffd82948e248a0f98415b7328349
+R c074a7899efe7412c63b603c13447040
 U stephan
-Z a6b554242e7c212e38bd6fdb1ff7082c
+Z 037a89bfec293517ee42832df5b904a5
 # Remove this line to create a well-formed Fossil manifest.
index 65b7f302f24e9ecca0453d22155be54e3f7a0fa6..ba0da199e43c7f7ed34b503a7dedecf395b1947e 100644 (file)
@@ -1 +1 @@
-b820db32365b2ca8e2397fd6ea85883e4555ffd82948e248a0f98415b7328349
\ No newline at end of file
+eeb84ba5de1152ef0f42105b8b285fdee9f5ad58281e60a4e0c8b1d6de1dead8
\ No newline at end of file