]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Rework how JS's oo1.DB.exec() flags its Stmt objects to make certain Stmt APIs illega...
authorstephan <stephan@noemail.net>
Sat, 21 Jun 2025 14:38:53 +0000 (14:38 +0000)
committerstephan <stephan@noemail.net>
Sat, 21 Jun 2025 14:38:53 +0000 (14:38 +0000)
FossilOrigin-Name: 8c187140a60b62dc3b6066b8615766d52b7a29a5de992cbb6d312dbb225a980b

ext/wasm/api/sqlite3-api-glue.c-pp.js
ext/wasm/api/sqlite3-api-oo1.c-pp.js
ext/wasm/tester1.c-pp.js
manifest
manifest.uuid

index 553911018c3a0ca178aade0653dd49921bb3b567..8d2d4a5891603a3af0b65b780bf25c51c4cacfce 100644 (file)
@@ -20,7 +20,6 @@
 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;
   globalThis.WhWasmUtilInstaller(wasm);
   delete globalThis.WhWasmUtilInstaller;
index 3d6a24c77bb73ccff0aa7e1a6c084c934aa2573a..41caf04da9f5367dfa8e957531ac51b270f26013 100644 (file)
@@ -16,7 +16,6 @@
   and it installs its deliverable as globalThis.sqlite3.oo1.
 */
 globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
-  const toss = (...args)=>{throw new Error(args.join(' '))};
   const toss3 = (...args)=>{throw new sqlite3.SQLite3Error(...args)};
 
   const capi = sqlite3.capi, wasm = sqlite3.wasm, util = sqlite3.util;
@@ -1061,18 +1060,18 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
               const cbArgCache = Object.create(null)
               /* 2nd arg for arg.cbArg, used by (at least) row-to-object
                  converter */;
-              for(; stmt.step(); stmt._lockedByExec = false){
+              for( ; stmt.step(); __execLock.delete(stmt) ){
                 if(0===gotColNames++){
                   stmt.getColumnNames(cbArgCache.columnNames = (opt.columnNames || []));
                 }
-                stmt._lockedByExec = true;
+                __execLock.add(stmt);
                 const row = arg.cbArg(stmt,cbArgCache);
                 if(resultRows) resultRows.push(row);
                 if(callback && false === callback.call(opt, row, stmt)){
                   break;
                 }
               }
-              stmt._lockedByExec = false;
+              __execLock.delete(stmt);
             }
             if(0===gotColNames){
               /* opt.columnNames was provided but we visited no result rows */
@@ -1094,7 +1093,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
       }*/finally{
         wasm.scopedAllocPop(stack);
         if(stmt){
-          delete stmt._lockedByExec;
+          __execLock.delete(stmt);
           stmt.finalize();
         }
       }
@@ -1388,7 +1387,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
 
     /**
        Starts a transaction, calls the given callback, and then either
-       rolls back or commits the savepoint, depending on whether the
+       rolls back or commits the transaction, depending on whether the
        callback throws. The callback is passed this db object as its
        only argument. On success, returns the result of the
        callback. Throws on error.
@@ -1511,7 +1510,20 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
   };
 
   /**
-     If stmt._lockedByExec is truthy, this throws an exception
+     Each Stmt object which is "locked" by DB.exec() gets an entry
+     here to note that "lock".
+
+     The reason this is in place is because exec({callback:...})'s
+     callback gets access to the Stmt objects created internally by
+     exec() but it must not use certain Stmt APIs.
+  */
+  const __execLock = new Set();
+
+  /**
+     Stmt APIs which are prohibited on locked objects must call
+     affirmNotLockedByExec() before doing any work.
+
+     If __execLock.has(stmt) is truthy, this throws an exception
      complaining that the 2nd argument (an operation name,
      e.g. "bind()") is not legal while the statement is "locked".
      Locking happens before an exec()-like callback is passed a
@@ -1519,7 +1531,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
      finalize the statement. If it does not throw, it returns stmt.
   */
   const affirmNotLockedByExec = function(stmt,currentOpName){
-    if(stmt._lockedByExec){
+    if(__execLock.has(stmt)){
       toss3("Operation is illegal when statement is locked:",currentOpName);
     }
     return stmt;
@@ -1627,9 +1639,9 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
         const rc = capi.sqlite3_finalize(this.pointer);
         delete __stmtMap.get(this.db)[this.pointer];
         __ptrMap.delete(this);
+        __execLock.delete(this);
         delete this._mayGet;
         delete this.parameterCount;
-        delete this._lockedByExec;
         delete this.db;
         return rc;
       }
index 2fe0c2377075a41e6ddf0704ff1a938ab574a188..c32b795ddaf2a79b8cc8aed60183612c8c8ae770 100644 (file)
@@ -3323,6 +3323,44 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
       db.close();
     })
 
+    /**
+       Ensure that certain Stmt members throw when called
+       via DB.exec().
+    */
+    .t('locked-by-exec() APIs', function(sqlite3){
+      const db = new sqlite3.oo1.DB();
+      db.exec("create table t(a);insert into t(a) values(1);");
+      let checkCount = 0;
+      const checkOp = function(op){
+        ++checkCount;
+        T.mustThrowMatching(() => {
+          db.exec({
+            sql: "select ?1",
+            bind: op,
+            callback: (row, stmt) => {
+              switch (row[0]) {
+                case 'bind': stmt.bind(1); break;
+                case 'finalize':
+                case 'clearBindings':
+                case 'reset':
+                case 'step': stmt[op](); break;
+              }
+            }
+          });
+        }, /^Operation is illegal when statement is locked.*/)
+      };
+      try{
+        checkOp('bind');
+        checkOp('finalize');
+        checkOp('clearBindings');
+        checkOp('reset');
+        checkOp('step');
+        T.assert(5===checkCount);
+      }finally{
+        db.close();
+      }
+    })
+
   ////////////////////////////////////////////////////////////////////
     .t("Misc. stmt_...", function(sqlite3){
       const db = new sqlite3.oo1.DB();
index a7c2b8ad82334248c085d642fad7365582d60c2b..8ee3eeaed17be584bbb83dadae7168df23245e5b 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Numerous\ssmall\sdoc\stypo\sfrom\sBrickViking.
-D 2025-06-21T06:07:13.675
+C Rework\show\sJS's\soo1.DB.exec()\sflags\sits\sStmt\sobjects\sto\smake\scertain\sStmt\sAPIs\sillegal\s(i.e.\sthrowing)\sif\scalled\swhile\sthat\sStmt\sis\sbeing\sstep()ped\sby\sDB.exec()\s(which\scan\shappen\svia\sclient-provided\sper-result-row\scallbacks).\sThis\sis\san\sinternal\schange\sonly\s-\sthe\sAPI\sis\sunaffected.\sRemove\ssome\sunrelated\sdead\scode.
+D 2025-06-21T14:38:53.743
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -640,8 +640,8 @@ F ext/wasm/api/post-js-footer.js 365405929f41ca0e6d389ed8a8da3f3c93e11d3ef43a90a
 F ext/wasm/api/post-js-header.js 53740d824e5d9027eb1e6fd59e216abbd2136740ce260ea5f0699ff2acb0a701
 F ext/wasm/api/pre-js.c-pp.js a614a2c82b12c4d96d8e3ba77330329efc53c4d56a8a7e60ade900f341866cfb
 F ext/wasm/api/sqlite3-api-cleanup.js 3ac1786e461ada63033143be8c3b00b26b939540661f3e839515bb92f2e35359
-F ext/wasm/api/sqlite3-api-glue.c-pp.js 098a2887ce4c1668c7621a0bd4e5457677b89cbd3c4735fa3f99cfa254c0c322
-F ext/wasm/api/sqlite3-api-oo1.c-pp.js f3a8e2004c6625d17946c11f2fb32008be78bc5207bf746fc77d59848813225f
+F ext/wasm/api/sqlite3-api-glue.c-pp.js 0b76510f3650053bac67ca8947cb6ab9d050ad2218118a2e7796dd37be832ffa
+F ext/wasm/api/sqlite3-api-oo1.c-pp.js 29b3188237535b290e89f26d9ea22168deed4e428a62cf37177ad95f8a7b6447
 F ext/wasm/api/sqlite3-api-prologue.js 8708570165f5b4bce9a78ccd91bc9ddf8735970ac1c4d659e36c9a7d9a644bb4
 F ext/wasm/api/sqlite3-api-worker1.c-pp.js f646a65257973b8c4481f8a6a216370b85644f23e64b126e7ae113570587c0ab
 F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
@@ -698,7 +698,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
 F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c
 F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
 F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
-F ext/wasm/tester1.c-pp.js 9019cc013fced0f26fc09526ce9b6ce95af84a59d2c79bf06787d3ac541f0b83
+F ext/wasm/tester1.c-pp.js 244527fbe4084ac1877418c30d73ebb7f6ee8d129aa02ebe8dbf467f61c2f3d7
 F ext/wasm/tests/opfs/concurrency/index.html 657578a6e9ce1e9b8be951549ed93a6a471f4520a99e5b545928668f4285fb5e
 F ext/wasm/tests/opfs/concurrency/test.js d08889a5bb6e61937d0b8cbb78c9efbefbf65ad09f510589c779b7cc6a803a88
 F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
@@ -2208,8 +2208,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
 F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P c978aed3b6f82b3d9d2e0ca0283c611351bca5e5496e86a9d5d0731ebcd27c84
-R 714065a090a6f7eddbb12d99b162de52
+P 3aab4415de615c178205936372c625bb571bad1016c3d2e7bb2a45932356f3d6
+R e2684543da36503b9406a7062fcc92f4
 U stephan
-Z cbd4eab64e0d2b9e7c3a78b27d31e046
+Z ff902b31a6fe33b3746d44bf2fb21fa2
 # Remove this line to create a well-formed Fossil manifest.
index e277b6994f028b604941c87b9718d608a965001a..e091ef79b800f753b2b3642fc1db038b13303552 100644 (file)
@@ -1 +1 @@
-3aab4415de615c178205936372c625bb571bad1016c3d2e7bb2a45932356f3d6
+8c187140a60b62dc3b6066b8615766d52b7a29a5de992cbb6d312dbb225a980b