diff --git a/demos/in-worker-demo/package.json b/demos/in-worker-demo/package.json index 6a72e30..ebd7ee5 100644 --- a/demos/in-worker-demo/package.json +++ b/demos/in-worker-demo/package.json @@ -10,6 +10,6 @@ "@sqlite.org/sqlite-wasm": "file:../.." }, "devDependencies": { - "vite": "^8.2.2" + "vite": "^8.3.4" } } diff --git a/demos/kvvfs-demo/package.json b/demos/kvvfs-demo/package.json index fd77904..32b2907 100644 --- a/demos/kvvfs-demo/package.json +++ b/demos/kvvfs-demo/package.json @@ -10,6 +10,6 @@ "@sqlite.org/sqlite-wasm": "file:../.." }, "devDependencies": { - "vite": "^8.2.2" + "vite": "^8.3.4" } } diff --git a/demos/main-thread-demo/package.json b/demos/main-thread-demo/package.json index cf2509b..e403cce 100644 --- a/demos/main-thread-demo/package.json +++ b/demos/main-thread-demo/package.json @@ -10,6 +10,6 @@ "@sqlite.org/sqlite-wasm": "file:../.." }, "devDependencies": { - "vite": "^8.2.2" + "vite": "^8.3.4" } } diff --git a/demos/opfs-demo/package.json b/demos/opfs-demo/package.json index 681e338..991bc98 100644 --- a/demos/opfs-demo/package.json +++ b/demos/opfs-demo/package.json @@ -10,6 +10,6 @@ "@sqlite.org/sqlite-wasm": "file:../.." }, "devDependencies": { - "vite": "^8.2.2" + "vite": "^8.3.4" } } diff --git a/demos/opfs-wl-demo/package.json b/demos/opfs-wl-demo/package.json index 8592c2e..4bc6a5b 100644 --- a/demos/opfs-wl-demo/package.json +++ b/demos/opfs-wl-demo/package.json @@ -10,6 +10,6 @@ "@sqlite.org/sqlite-wasm": "file:../.." }, "devDependencies": { - "vite": "^8.2.2" + "vite": "^8.3.4" } } diff --git a/demos/sahpool-demo/package.json b/demos/sahpool-demo/package.json index 2268a58..8c1b47e 100644 --- a/demos/sahpool-demo/package.json +++ b/demos/sahpool-demo/package.json @@ -10,6 +10,6 @@ "@sqlite.org/sqlite-wasm": "file:../.." }, "devDependencies": { - "vite": "^8.2.2" + "vite": "^8.3.4" } } diff --git a/demos/sahpool-rsbuild-demo/package.json b/demos/sahpool-rsbuild-demo/package.json index 72df949..fd59403 100644 --- a/demos/sahpool-rsbuild-demo/package.json +++ b/demos/sahpool-rsbuild-demo/package.json @@ -9,6 +9,6 @@ "@sqlite.org/sqlite-wasm": "file:../.." }, "devDependencies": { - "@rsbuild/core": "^2.2.3" + "@rsbuild/core": "^2.2.13" } } diff --git a/demos/sahpool-webpack-demo/package.json b/demos/sahpool-webpack-demo/package.json index e858acd..bc6100f 100644 --- a/demos/sahpool-webpack-demo/package.json +++ b/demos/sahpool-webpack-demo/package.json @@ -9,7 +9,7 @@ "@sqlite.org/sqlite-wasm": "file:../.." }, "devDependencies": { - "webpack": "^5.110.3", + "webpack": "^5.112.0", "webpack-cli": "^7.2.3", "webpack-dev-server": "^6.0.0" } diff --git a/package-lock.json b/package-lock.json index 791463c..cb862cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,28 +1,28 @@ { "name": "@sqlite.org/sqlite-wasm", - "version": "3.53.4-build2", + "version": "3.54.1-build1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@sqlite.org/sqlite-wasm", - "version": "3.53.4-build2", + "version": "3.54.1-build1", "license": "Apache-2.0", "workspaces": [ "demos/*" ], "devDependencies": { - "@types/node": "^26.5.0", - "@vitest/browser": "^5.0.0", - "@vitest/browser-playwright": "^5.0.0", - "happy-dom": "20.14.0", - "lefthook": "2.1.12", - "oxfmt": "^0.67.0", - "playwright": "^1.63.0", - "publint": "^0.3.24", - "tsdown": "^0.23.0", + "@types/node": "^26.6.5", + "@vitest/browser": "^5.0.5", + "@vitest/browser-playwright": "^5.0.5", + "happy-dom": "21.0.3", + "lefthook": "2.2.2", + "oxfmt": "^0.73.0", + "playwright": "^1.64.1", + "publint": "^0.3.25", + "tsdown": "^0.23.1", "typescript": "7.0.2", - "vitest": "^5.0.0" + "vitest": "^5.0.5" }, "engines": { "node": ">=22" @@ -34,7 +34,7 @@ "@sqlite.org/sqlite-wasm": "file:../.." }, "devDependencies": { - "vite": "^8.2.2" + "vite": "^8.3.4" } }, "demos/kvvfs-demo": { @@ -43,7 +43,7 @@ "@sqlite.org/sqlite-wasm": "file:../.." }, "devDependencies": { - "vite": "^8.2.2" + "vite": "^8.3.4" } }, "demos/main-thread-demo": { @@ -52,7 +52,7 @@ "@sqlite.org/sqlite-wasm": "file:../.." }, "devDependencies": { - "vite": "^8.2.2" + "vite": "^8.3.4" } }, "demos/opfs-demo": { @@ -61,7 +61,7 @@ "@sqlite.org/sqlite-wasm": "file:../.." }, "devDependencies": { - "vite": "^8.2.2" + "vite": "^8.3.4" } }, "demos/opfs-wl-demo": { @@ -70,7 +70,7 @@ "@sqlite.org/sqlite-wasm": "file:../.." }, "devDependencies": { - "vite": "^8.2.2" + "vite": "^8.3.4" } }, "demos/sahpool-demo": { @@ -79,7 +79,7 @@ "@sqlite.org/sqlite-wasm": "file:../.." }, "devDependencies": { - "vite": "^8.2.2" + "vite": "^8.3.4" } }, "demos/sahpool-parcel-demo": { @@ -97,7 +97,7 @@ "@sqlite.org/sqlite-wasm": "file:../.." }, "devDependencies": { - "@rsbuild/core": "^2.2.3" + "@rsbuild/core": "^2.2.13" } }, "demos/sahpool-webpack-demo": { @@ -106,7 +106,7 @@ "@sqlite.org/sqlite-wasm": "file:../.." }, "devDependencies": { - "webpack": "^5.110.3", + "webpack": "^5.112.0", "webpack-cli": "^7.2.3", "webpack-dev-server": "^6.0.0" } @@ -195,9 +195,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", "dev": true, "license": "MIT" }, @@ -883,9 +883,9 @@ } }, "node_modules/@oxc-project/types": { - "version": "0.148.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.148.0.tgz", - "integrity": "sha512-Nm4s/jB+4FpFsPhWGEC4h7rzksesmtnMXomo6rCMcg/b8zLQuOziRgkCS1fxDCXOlJB/6Q8oABOZ/OP6RIPj9A==", + "version": "0.153.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.153.0.tgz", + "integrity": "sha512-jSNrRIyvPVLL5E1z/tS5zLAprosGz/FuI1PWwEOz59j3E4TTTzSpqKb/RDGqJhhW0QHYISGXxq582wGx6T11Tw==", "dev": true, "license": "MIT", "funding": { @@ -893,9 +893,9 @@ } }, "node_modules/@oxfmt/binding-android-arm-eabi": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.67.0.tgz", - "integrity": "sha512-2olh3ioEmc4gRzQm7jxyB1b/PFBoFvTq8KdgYySeNpysDtA6DEg2Mvya4/I6flhL7G0eOrE8RD7JCNCIMhE16Q==", + "version": "0.73.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.73.0.tgz", + "integrity": "sha512-dhunAdMbi/4o0Y66/+Wl6rpsNqpvE4i26Qw6bB77A97L2lJoktWg6m+X9QOon8iOEEqzD9rEZqFi5uZ4oIzhCA==", "cpu": [ "arm" ], @@ -910,9 +910,9 @@ } }, "node_modules/@oxfmt/binding-android-arm64": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.67.0.tgz", - "integrity": "sha512-ulfw8EHN1MBq/MFFDXw2/M1VAFu5mRUcnuZ8Hqbv9viAnFzO9t1jKSAsDqKYYDGMlytF/uj6Z5z5n/tHupnKhw==", + "version": "0.73.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.73.0.tgz", + "integrity": "sha512-dBoypjC2/xeyKyIhN2waX0/XeoccH9k0lVVe+sGRc4X8HSJVRtqyZDoXdr7bGY9A75c51dX0z0dLDpGQKwCdCg==", "cpu": [ "arm64" ], @@ -927,9 +927,9 @@ } }, "node_modules/@oxfmt/binding-darwin-arm64": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.67.0.tgz", - "integrity": "sha512-MfONZx/O2o9M5v2jDFol556G9+A+P9xCuJ4DZ+qhE+RnaCdoscy6Eu5nq1dbuNxhwdJyZ6kLI7fnG9mwEeOeGg==", + "version": "0.73.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.73.0.tgz", + "integrity": "sha512-Tn7Y+qWIpCQK+qdYwBcn6YvqeBuPiuG3tcNlYg16a5QL2o3rSmrgBB1nCyYqo0uvc1LNrfQW9/CK2tzFuID/Fg==", "cpu": [ "arm64" ], @@ -944,9 +944,9 @@ } }, "node_modules/@oxfmt/binding-darwin-x64": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.67.0.tgz", - "integrity": "sha512-CYnIx5LvFVJnyJcCqwH2jxMKjFjqo5678MPjdmNFoSGMhlOvZ/xRZqvhDcolKrXc8fezW3AKh+C4wyoFuWOSSg==", + "version": "0.73.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.73.0.tgz", + "integrity": "sha512-yVb0E0tg/+9Xc9YJCBq66qF1DC/aN5mhb5nnHz0k4ikwkMANtSul2VPDSwjYdXR6/DFimc+pPUgLBqkIa5Ctuw==", "cpu": [ "x64" ], @@ -961,9 +961,9 @@ } }, "node_modules/@oxfmt/binding-freebsd-x64": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.67.0.tgz", - "integrity": "sha512-7/iF1orvIS9mxhKUqnmtMgm+OrSQ5acPwuvdQrm6ECgqbwPmC+Pw9cdke3sNfVN6pT2hbJ58+jP8BCThl5HXOg==", + "version": "0.73.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.73.0.tgz", + "integrity": "sha512-IKR4lFnBkYNL9Uqdxa5GMTQLvnLj+3sDwTvh2atHCzah0xeo+1xR5bigRU8uyXlOsA4VpXUn0UAimq4E4RBGmQ==", "cpu": [ "x64" ], @@ -978,9 +978,9 @@ } }, "node_modules/@oxfmt/binding-linux-arm-gnueabihf": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.67.0.tgz", - "integrity": "sha512-yy+OGys07IZOpOmYPZoObKyUQLkfxeQqeCypk+1jaZd8HGo77hzvU1Jg8X3+W75o+9lszOjBfg0nkGtlwYywXw==", + "version": "0.73.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.73.0.tgz", + "integrity": "sha512-7qnZ4g0ZCO3aZevOOQpZIABYwwXJW1lLDo2elviGdPQ0i11255xKEMFsi97fC1/nauQFseCJfELUy/k2JoOP+g==", "cpu": [ "arm" ], @@ -995,9 +995,9 @@ } }, "node_modules/@oxfmt/binding-linux-arm-musleabihf": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.67.0.tgz", - "integrity": "sha512-wPIeeigXgJpwNw3wydYRt3U9iN9Y/ejpOZuYL9IA7igxWs7LIQMOkhKxTumRvy6dIv0iXKk3RTw3Vmjg0i+2sg==", + "version": "0.73.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.73.0.tgz", + "integrity": "sha512-36eBico2j/WPB84gb4FYd/jjqGCKOwU4M+TWLBUIqlnzTozQueLy0joA5BwsSp2OZFVkOlpCwvA3ndPamdiyLw==", "cpu": [ "arm" ], @@ -1012,9 +1012,9 @@ } }, "node_modules/@oxfmt/binding-linux-arm64-gnu": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.67.0.tgz", - "integrity": "sha512-0+XNxcdbkTfxdcD4qW6Ci9n+mBNJ8xTBumnxKvKBmRFOdx0Wf8/KiHjCJayooXmYkqRpRVd98Q5egvzx5BLSgQ==", + "version": "0.73.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.73.0.tgz", + "integrity": "sha512-VZ3cSgCAT18knKo52DcACmAuIoqG6qVEyeZRFbJd0xmYQ8GyYjuBc6IAh6MZHijT6q7p4/HPI+6ZWsCuhdV6iw==", "cpu": [ "arm64" ], @@ -1032,9 +1032,9 @@ } }, "node_modules/@oxfmt/binding-linux-arm64-musl": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.67.0.tgz", - "integrity": "sha512-I75LKPJyNOYUzkqAiAMIE31+Ye7xtQXZdoty1IXn4B+bw5Zpmez5wfG19ejGpNnS/BzQ7LFS+7jxuTPb+vHiZw==", + "version": "0.73.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.73.0.tgz", + "integrity": "sha512-8YVzH59XSHcqwXNgc5qK851zCqwpmBgOifARXEPPe5/xTsIbHceYoPZAyqfpYV0CfKmzSaEDBgYHFza4rhx+Zw==", "cpu": [ "arm64" ], @@ -1052,9 +1052,9 @@ } }, "node_modules/@oxfmt/binding-linux-ppc64-gnu": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.67.0.tgz", - "integrity": "sha512-c2M5iRpe1QMZSRE/UvZoPdXBWb5Ic/ycvOyNiKCqPwQ/OyOKIMiJs02ynlNnjb7ZZJnRXYLmGcohoINOcwDK3w==", + "version": "0.73.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.73.0.tgz", + "integrity": "sha512-MqRJnmCys0rwOgpWyEidSA7v/bvOqfNDJhPkQoR9mPVYrvSmMaW2Xhdpl28cbTA+brOM1is62GjIvJplVlUVpw==", "cpu": [ "ppc64" ], @@ -1072,9 +1072,9 @@ } }, "node_modules/@oxfmt/binding-linux-riscv64-gnu": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.67.0.tgz", - "integrity": "sha512-dQzzYlV24Udhfm5ECuSdgqRvFJU/CGHzcYYEO3dLM6W6+CHiBFrq9OjIllkdCcPhsoSQ8o223Dja84MOSzed9A==", + "version": "0.73.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.73.0.tgz", + "integrity": "sha512-4t2F3SWJSK/O/kRRFnL0elJzn75fJGGu71gs1HtiWcS80SmJOpkHiwwLnTp9suGdns8VHEPxYS0GTcyVwHKWBA==", "cpu": [ "riscv64" ], @@ -1092,9 +1092,9 @@ } }, "node_modules/@oxfmt/binding-linux-riscv64-musl": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.67.0.tgz", - "integrity": "sha512-rFNq1CgX4qMJANOq42LkAs90JE80GpiaEohAV2qn/gT2hGjQTW1zBO5zQBxArI4926pM1OSzo3CN0tBszGBIaA==", + "version": "0.73.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.73.0.tgz", + "integrity": "sha512-D8b4I8I1kLdJQFwdFXNV+cwh3xWSiNKofjdGUk0nDpc0AHOds8T+poGbP9RWQMvgsvMb9OMgp/aV7ahBR37TbQ==", "cpu": [ "riscv64" ], @@ -1112,9 +1112,9 @@ } }, "node_modules/@oxfmt/binding-linux-s390x-gnu": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.67.0.tgz", - "integrity": "sha512-Sky6rEdz2o5IGq01lPhS12yEvDdChVEcaYrcLHkveh4Fx0qPjljE/Iul6SX/bRMl6lNc8J7J/mDQdzgBdA++Pg==", + "version": "0.73.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.73.0.tgz", + "integrity": "sha512-QrC1S5VL1+N5rvorB15jH7CPvjVHA7GyUI5oVEd8Bd9m5605RDBQYTxDQ920DuylRoZOh2V7/xXpfCtFUrojUQ==", "cpu": [ "s390x" ], @@ -1132,9 +1132,9 @@ } }, "node_modules/@oxfmt/binding-linux-x64-gnu": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.67.0.tgz", - "integrity": "sha512-vPXmlNORV8AZq2Ocxh07pxwMjfENUWCV/eZArnao0qC3NO/hDeTVkQvee7SJJUbIiF5PZbBa4kYmaXnu7Rk58w==", + "version": "0.73.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.73.0.tgz", + "integrity": "sha512-dFcUKQPltCEPa+YlkF3zqufn6nJPZdG73LpnjBvZFFsU3laCMssDXSYB99mVaj43FqdEgjpz5TO6gbYXcczd9g==", "cpu": [ "x64" ], @@ -1152,9 +1152,9 @@ } }, "node_modules/@oxfmt/binding-linux-x64-musl": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.67.0.tgz", - "integrity": "sha512-x/WAtFqYtVr3vZ9ni8nr4kn9whSitg8fOljq/pZzBpxopRdY1BMLZCZkrbIbaBcYkm46qGbqVea2FCWmtQ2P9w==", + "version": "0.73.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.73.0.tgz", + "integrity": "sha512-LmQe+nV8e+eUwfPNCxDF+owbsg88toBiR/8rZRgVOeKQP3MaGefXZRvBoc1UG37iWEQ/9JlCXG9Mc4nf4N3agw==", "cpu": [ "x64" ], @@ -1172,9 +1172,9 @@ } }, "node_modules/@oxfmt/binding-openharmony-arm64": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.67.0.tgz", - "integrity": "sha512-eRw9Neh4/aA6i+q/R3WU1gGQINhVM0J4fXIm6t27caOamkr/37uAkp1IdBx4zlJH97hmXR63z/q9n5c5dN7MzA==", + "version": "0.73.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.73.0.tgz", + "integrity": "sha512-8weOr1OKknE0G2DbR6ejJUT9AOsoBU6cXlsetmbihHv1K+bK7qP61T6lJxY0k/aAO7GyOJiRGNlL+04r4eH8Xg==", "cpu": [ "arm64" ], @@ -1189,9 +1189,9 @@ } }, "node_modules/@oxfmt/binding-win32-arm64-msvc": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.67.0.tgz", - "integrity": "sha512-YIMvb+sGNYN2uc6+QK2HLPeEKM2vl7QZ5onQzpAJRb6pnf0DwUFP5R8tdS9R0l8hdUil2gu4Uxd0Yxrop0iT4w==", + "version": "0.73.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.73.0.tgz", + "integrity": "sha512-mZV+QxXYgb8E18gzAFItb937VIsE4dqWdStrD3tRRC52UubOYEuU+e7NaIqUsGdB5YsJqNeuck3Ue/af2r9wyA==", "cpu": [ "arm64" ], @@ -1206,9 +1206,9 @@ } }, "node_modules/@oxfmt/binding-win32-ia32-msvc": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.67.0.tgz", - "integrity": "sha512-LzmU9MyACPzwNDIK0ItMedHPz735Ug7ELWguxo4/kuy6zWuDoeglOAEFCY8jLg0PzRpFO3hDyLFe2Gu2eFDeGA==", + "version": "0.73.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.73.0.tgz", + "integrity": "sha512-QJPUsbgUb97ZPPMkFUq6VQq0fLhC4Np19KL9aB/qKVwXnpKE6MIiILXqzhKnQ/UbnEDjKJ7Xv1d6zH4bYPCUdQ==", "cpu": [ "ia32" ], @@ -1223,9 +1223,9 @@ } }, "node_modules/@oxfmt/binding-win32-x64-msvc": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.67.0.tgz", - "integrity": "sha512-sbQOIDNLUEeVZcAJcSL5VURn7kfjvilPviody4Yl5n8lQCDtUm+C9oHTTwZS/m4d/Z6Vv3jNEiAofH932NPPCg==", + "version": "0.73.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.73.0.tgz", + "integrity": "sha512-cGcze2fu+ykIaFtkEvZlkZ3HvnCLk+WISthtq99zWTWn0x13t5L9TxvGdLZMUMvtfYR+ICkiCwKnguVubdcw0w==", "cpu": [ "x64" ], @@ -3121,9 +3121,9 @@ } }, "node_modules/@rolldown/binding-android-arm-eabi": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.7.tgz", - "integrity": "sha512-EypzgnYCwyVY4NDHKzGmNJT5b+XaQEBniHxsMdeIQLB/tcCzZnhqrzHpZFbX9iaxx+5RiB8caATBtfvZP7zVxQ==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.13.tgz", + "integrity": "sha512-Vu/NICrgdRvUOeaJZIyB2FP63s6fO/4ud5l8dXmxDx9yDyn+mN0y+gsvsVviSli+T361Aqo0h46EuMoobrwawA==", "cpu": [ "arm" ], @@ -3138,9 +3138,9 @@ } }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.7.tgz", - "integrity": "sha512-l17HE9EweWaqJZhuUuNBN/FzM62xw+DECVnJyvMsxn8vJFAGLy5QfLDoYAcronkAN8VxKZHezDpulHDPx95vFw==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.13.tgz", + "integrity": "sha512-6LEoIrGy5vvCd2boNnv2soPSUZj/PRvhp8R/t9KlX+mIZxThIE/ZqxrGXxmuNX0FuvQFvLdZr7S4HrYpYBVhEQ==", "cpu": [ "arm64" ], @@ -3155,9 +3155,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.7.tgz", - "integrity": "sha512-8ED8ELFvHXc6OCETIn4gXObPiaR6bckM/ipXtbzlPVDRMBfEGjCKgO90F9YtfdpDatVx/ZQw7aZ1vUMf/+T3Mw==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.13.tgz", + "integrity": "sha512-CaJSRzlQ6Q+zkDMVA9OkVxBjVoPRCDEE3v0FSJ9kIQBgRjFApA3Si4ijhbNVUji7ZJt+PfO0e46qy4nPInHUPA==", "cpu": [ "arm64" ], @@ -3172,9 +3172,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.7.tgz", - "integrity": "sha512-/WPripjtiAIZ2tWY7ddijORT0Ujg87wxWW/qcoFVCKAWVDPhtY0xr7Dj0M3GyNGz60jGwTElhro/mkF9dT7dDQ==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.13.tgz", + "integrity": "sha512-e4r340I5hxSzJkD3YJBxgzq/rJ3wwxwdLLb2FPt1Zpyem20nrQPT11DDEEkazwxaHumH8wpglsp/Ozgj/wT6mw==", "cpu": [ "x64" ], @@ -3189,9 +3189,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.7.tgz", - "integrity": "sha512-14DI4NcqpvbICxSnGLx3PmtDaWqRP/KGSGb6C+JLLVPeZRl6dKdHba3pGsqT3vpdTqhEYIPG0MMQ8c0xYqoJxA==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.13.tgz", + "integrity": "sha512-hoBWDZ4/K/mJKVMbsgUd1jfpA2DiOrJ54mpegObU9TBHBBrtX4FLIXJJQRDPZ/2Dn91GvPob+Z2hwKJzf4E5SQ==", "cpu": [ "x64" ], @@ -3206,9 +3206,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.7.tgz", - "integrity": "sha512-bxrWIRvHWQvbJwi+VIie/kDJmQxcNE6xxWwZdqF/ExVAigtHkv54WTLQPb+QsZdnFy18fg7JPfWGL0RH6vwIlQ==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.13.tgz", + "integrity": "sha512-oF9fZu3vTWnTiVAkDFxU9PJLt1nh20K9RRpuHsR7ZnE2L7XookBbDBVLojCVSLGbvtSlxeUNnjAj6DbNsKyzbg==", "cpu": [ "arm" ], @@ -3223,9 +3223,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.7.tgz", - "integrity": "sha512-toOY2BChBZyuxU7OYX6Tn389di4IzAqPTycVcci0O7FSfBqzRB3RZn+K5Is6ANf4tmgRd/K1yZTsNTXbkXsnLg==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.13.tgz", + "integrity": "sha512-DTpb/+jMiqWMPgphn4ksW1zW+XLJ6dJJ9FMvnIk9I291LhCctMPhMYJrP5t9p6C9qa3KXadDdUEZHBaPh3kNxQ==", "cpu": [ "arm64" ], @@ -3243,9 +3243,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.7.tgz", - "integrity": "sha512-lAIXTH/aiLRLxsTgQvfhjo4K1ydWIp00+V0voOr9beb/9ZmkUFrSIb03dXNFRgMNvkE6oGsF10ioQ6UsI+vS5Q==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.13.tgz", + "integrity": "sha512-xU+Kvv9N2A3SY35zFh1FWWNjxbadE/BKeqnkXe7vScU4GZsw757BlVmDLITZEq8DPpk6m7uoDYkK7P+x/uU5Ow==", "cpu": [ "arm64" ], @@ -3263,9 +3263,9 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.7.tgz", - "integrity": "sha512-kdnwS28Pkenp/mZMRwjXXXwxQ7pIsm+bF919LUK93BOyhcLsrVKdP2p9fxpiPNPAbNuch8ypQt0pm2P2LYCAGg==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.13.tgz", + "integrity": "sha512-XMk/hnhh25oQ756Lclb1Q11h4ll0xC0Esa5w4Vzp+mAE2S3AGJgeM0SonrIgY8fHhjarb6hcoTuwoFG0VVP2ig==", "cpu": [ "ppc64" ], @@ -3283,9 +3283,9 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.7.tgz", - "integrity": "sha512-516OdsyLdr5E65paF3yBF55t8mfm9+gmtCsK3xI7XKXIT7EfRlHhxL8K/NR6Hu8BWSgF5+1w74lTL0+nxcc8Qw==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.13.tgz", + "integrity": "sha512-U1BoTHYmlywE2n3HUWjzZ+8EQsKr+OwpxYuDWaubx42tUL8QSL7nOqRz/NVHanibbFP3M1Rxuprz/wNcbMKjqw==", "cpu": [ "s390x" ], @@ -3303,9 +3303,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.7.tgz", - "integrity": "sha512-r8/z8n7GFaYRln3xmP1Cxy0HH/HLM0uBUPkEuSVEfKGDA89M0FsZRZJRSwe/tJjRx+fpH/gjorfhB8tmEbSFLA==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.13.tgz", + "integrity": "sha512-J4cm80Pc6wEwV5AZ42o62sIQgDk+Y7R2s646jIwuvO+4V46QB58N4vVuMPWCBaNgursXLpmUWJV//WQAkPvHBQ==", "cpu": [ "x64" ], @@ -3323,9 +3323,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.7.tgz", - "integrity": "sha512-pAsE8iiDxUg1xBqdhrTfg45AVDVpirjz00sblEYClGNNcMnDb+e8beQgqIAw6LvauX/APvgxUnwrgun/YYGBhw==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.13.tgz", + "integrity": "sha512-W0euZS40U4V6JkmEnVCIX9mcsL6cbXQ4X8c2w+MMOIjFg68TXUW+u3RT+2e1t1pv9mg/EP3pDtK3POXdQ7Rxyw==", "cpu": [ "x64" ], @@ -3343,9 +3343,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.7.tgz", - "integrity": "sha512-lTcIYmmnQQA8Or/2DatS6oSqcdLHvendjS+zLu+FwgToynWMRSmQdpM65fTANJgIS4mjbMOo5KT2lnT9SAb96w==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.13.tgz", + "integrity": "sha512-do/AF/4n9MRshia3a5aXoy8xM2c6mgfT6D7H/dY6my5z+hfCIR4ab7mk4IRj++nsEQpKy39kd0DQnDq+r692tw==", "cpu": [ "arm64" ], @@ -3360,9 +3360,9 @@ } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.7.tgz", - "integrity": "sha512-e3Gu3WxbNk/UqQhxqU7YIYO+9ZBvWNz3U+h/qRFosscMFzdRPbXYSaSWgSnklv2fz1TgzBTcti2z35c/7irsHw==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.13.tgz", + "integrity": "sha512-6FtUf2cJZobutJdxnGYX8z0vtbgqU0b2v8vfBhkXb9wp2MppMFtkunE+IaOntyi01rkIQoPW2GHABtfzsC0BRQ==", "cpu": [ "arm64" ], @@ -3377,9 +3377,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.7.tgz", - "integrity": "sha512-W/jg5qoRSqjsEv0+dZi4e687mcHqmVuU0P4fK6qS/xjetW2Gmc1W8j//z5nAeNcC8Ttm0hV46IjcYeuVwYhuiw==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.13.tgz", + "integrity": "sha512-UKhFaZTeTcbKrb3iU82m17jVcPEAoqDkCN5MBqgPyZSwp/cQmib21crTS0DdH7T1B7wZRWEI89YQAOJMet5yhg==", "cpu": [ "x64" ], @@ -3401,13 +3401,13 @@ "license": "MIT" }, "node_modules/@rsbuild/core": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@rsbuild/core/-/core-2.2.3.tgz", - "integrity": "sha512-oJrYtYDhb7AMwY8HIda2hgMuuxHkYPYar4svdS5uTq0fXY0M1wLfllkTQz0d729pNJ4S//6GUM1WX5LsW2mFLw==", + "version": "2.2.13", + "resolved": "https://registry.npmjs.org/@rsbuild/core/-/core-2.2.13.tgz", + "integrity": "sha512-UDSDrokgG70tmx+0bz9kuc64SkPQ5A1/Zhqsp8pD0L3Cko/xEnukAbrjouGihUTk55imhC4zx62DnQN/1VJ+GQ==", "dev": true, "license": "MIT", "dependencies": { - "@rspack/core": "~2.2.2", + "@rspack/core": "~2.2.9", "@swc/helpers": "^0.5.23" }, "bin": { @@ -3426,32 +3426,32 @@ } }, "node_modules/@rspack/binding": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-2.2.2.tgz", - "integrity": "sha512-gWjKDQfVQJSBh/I+y9WTlyERsiShSJ7eI6Yl0SJs/6gjx8t4ixuwWCsaEFFjwSL4nSn6ML5hNQ7UFY3gj72BWA==", + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-2.2.9.tgz", + "integrity": "sha512-Y8wDJoRo8n0KXDGq6J3KGVekkUQcOcUHSppMHoJv8JLbNBEsyaaKiDx4ljNTGEDtTON0CRbMEWbSiLRe+bJxOQ==", "dev": true, "license": "MIT", "optionalDependencies": { - "@rspack/binding-darwin-arm64": "2.2.2", - "@rspack/binding-darwin-x64": "2.2.2", - "@rspack/binding-linux-arm64-gnu": "2.2.2", - "@rspack/binding-linux-arm64-musl": "2.2.2", - "@rspack/binding-linux-ppc64-gnu": "2.2.2", - "@rspack/binding-linux-riscv64-gnu": "2.2.2", - "@rspack/binding-linux-riscv64-musl": "2.2.2", - "@rspack/binding-linux-s390x-gnu": "2.2.2", - "@rspack/binding-linux-x64-gnu": "2.2.2", - "@rspack/binding-linux-x64-musl": "2.2.2", - "@rspack/binding-wasm32-wasi": "2.2.2", - "@rspack/binding-win32-arm64-msvc": "2.2.2", - "@rspack/binding-win32-ia32-msvc": "2.2.2", - "@rspack/binding-win32-x64-msvc": "2.2.2" + "@rspack/binding-darwin-arm64": "2.2.9", + "@rspack/binding-darwin-x64": "2.2.9", + "@rspack/binding-linux-arm64-gnu": "2.2.9", + "@rspack/binding-linux-arm64-musl": "2.2.9", + "@rspack/binding-linux-ppc64-gnu": "2.2.9", + "@rspack/binding-linux-riscv64-gnu": "2.2.9", + "@rspack/binding-linux-riscv64-musl": "2.2.9", + "@rspack/binding-linux-s390x-gnu": "2.2.9", + "@rspack/binding-linux-x64-gnu": "2.2.9", + "@rspack/binding-linux-x64-musl": "2.2.9", + "@rspack/binding-wasm32-wasi": "2.2.9", + "@rspack/binding-win32-arm64-msvc": "2.2.9", + "@rspack/binding-win32-ia32-msvc": "2.2.9", + "@rspack/binding-win32-x64-msvc": "2.2.9" } }, "node_modules/@rspack/binding-darwin-arm64": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-2.2.2.tgz", - "integrity": "sha512-/le/AvV4HSinXTPs2Lqpujxt189Z5T10Ggt96QzckLRPvIchzqoavVDDjltzC7XcaZ87XCH/X06jNKgzkcBBNA==", + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-2.2.9.tgz", + "integrity": "sha512-aIHkk/wngpwgWkwVQFz2AIkmG9WpWtWlkqy4BlYhs5a7l9z0BrB0kXnUb6VSbqZ7Tc3cRepKw7ipkGjKa8KKXw==", "cpu": [ "arm64" ], @@ -3463,9 +3463,9 @@ ] }, "node_modules/@rspack/binding-darwin-x64": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-2.2.2.tgz", - "integrity": "sha512-uFIcUPUXiPxM6ljenLafp5TemT8eLZm1riRn8fJYmpqNCK+aCcTaud18XHZpI5SjzzcY+xUHfVShgvNzKXuf2g==", + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-2.2.9.tgz", + "integrity": "sha512-QtUS7lyOE5oxdMm7RH/Fw176jqwdHiTW2qEsmbdCYzPw3t7QkmI5ohoyiuxOp3czJfaayXP6bVyvm2FqqnWPAw==", "cpu": [ "x64" ], @@ -3477,9 +3477,9 @@ ] }, "node_modules/@rspack/binding-linux-arm64-gnu": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-2.2.2.tgz", - "integrity": "sha512-Pjby4pDSMNJQK2VBzpgCj6lb+DGuenS1fEDb6xi5/apbJb9v5WE+e43Mz7i+XqgXS8e846pjaONV3KM5WKB1LQ==", + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-2.2.9.tgz", + "integrity": "sha512-GMKxtBJAMoqBPqXZVi0QanDkneWwgiKRpTgHW/pbKPY/2XMfZJ98thm4YlATO18XZJ2KET+GfsNfaf1o5Y+aaA==", "cpu": [ "arm64" ], @@ -3494,9 +3494,9 @@ ] }, "node_modules/@rspack/binding-linux-arm64-musl": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-2.2.2.tgz", - "integrity": "sha512-0u9O7tTVT2z+F6o/eEY6f6+My8Jn9U56QiBwkfy90ZaoAfZyQSSTxqaK/zA7W43oFxQefeCpiPas27VUzrSakw==", + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-2.2.9.tgz", + "integrity": "sha512-aW3fcM64R5mY2+ym6Q8okAo/pcVIjAliqxFOc9lf9hCyS7hHaabWo30smeMX3neEjsqw+iyNbzWMuH0G5AugTw==", "cpu": [ "arm64" ], @@ -3511,9 +3511,9 @@ ] }, "node_modules/@rspack/binding-linux-ppc64-gnu": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@rspack/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-2.2.2.tgz", - "integrity": "sha512-N3lVnhq5qOvpmP5n386JzR1GcE8HzAqq4/r440Z6yle9m7PhVFJ6oXVWxgaDTYV0mtv9YLJmaG+YrjYfUa1vuA==", + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-2.2.9.tgz", + "integrity": "sha512-dVEiyZdANq+g/qugI64vKnxO+PCVicidu/GQ6sO0QEWGVzdSUbxHztHviSnMwdvRs6OLrN7Lwhaw536hJ/cU8w==", "cpu": [ "ppc64" ], @@ -3528,9 +3528,9 @@ ] }, "node_modules/@rspack/binding-linux-riscv64-gnu": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@rspack/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-2.2.2.tgz", - "integrity": "sha512-ReClZyp32/rJkUDV/oGDU0X6BCFyEkTR6r4stFwm/qOOaG6mUMRzZe4gur8Yh979p4Hiz9EdkmfEHY02GBXcaQ==", + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-2.2.9.tgz", + "integrity": "sha512-uBHWmfMm502145le0EUOsBoV6bJ9XA5s3NQLL4smSMoSEuMbNrRhqDJ2+B1u8aXVfjfhxCPyNlMDmgbsdVaO0Q==", "cpu": [ "riscv64" ], @@ -3545,9 +3545,9 @@ ] }, "node_modules/@rspack/binding-linux-riscv64-musl": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@rspack/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-2.2.2.tgz", - "integrity": "sha512-mqsorvTNerr3r8zI35NFTPYATPDlhepdiUhZjKT6ylqpHlP7vLU9fp4aEMK/CuTv2f+IVsa0+iZqtMxHs2tSjw==", + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-2.2.9.tgz", + "integrity": "sha512-MR7e6PP7KcG3jHYWznk17npBBvjUXQg7qQbS+yrAu0R3p/27wLp+aP5m/zk4ev1Iq93ccIBIAGVRGA3v1fSKew==", "cpu": [ "riscv64" ], @@ -3562,9 +3562,9 @@ ] }, "node_modules/@rspack/binding-linux-s390x-gnu": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@rspack/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-2.2.2.tgz", - "integrity": "sha512-ql2Jub8QYWSugBppmj2u0SjcIj6fOQuAaLCYQOqU7zbvz/uuWTfoqmdWKExwrxeCU9Tzt7emVM0ETuVEpoca+A==", + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-2.2.9.tgz", + "integrity": "sha512-Tc9Nuv7XvkrAG79Ps/6F7vT4bxZqiaiQ3Rd3BidKUjVYiwTPJogk1W3gPXp7Lw+AMoN/dY63W22bMJ7Oh0FeZw==", "cpu": [ "s390x" ], @@ -3579,9 +3579,9 @@ ] }, "node_modules/@rspack/binding-linux-x64-gnu": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-2.2.2.tgz", - "integrity": "sha512-MNYKYEHrtIVEno2q5rgpou/JVffRwn109xPK3kxct95EojHsniNa8jwy6eEHeOazP4EN60Si7NElE3aQ6JssHw==", + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-2.2.9.tgz", + "integrity": "sha512-xQYhQwC8q3mSCzHV+yi76Gt2Lt9BhnmeJnQgXGjuhyvjZWBB9jFNp9Uj6umun7tlMliMRhoqTesqvK4Vo/kkcQ==", "cpu": [ "x64" ], @@ -3596,9 +3596,9 @@ ] }, "node_modules/@rspack/binding-linux-x64-musl": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-2.2.2.tgz", - "integrity": "sha512-y9/9CmE8lrECaF17GAhacibTL+SvlEPEotQnUuBFC/WFtXh8hU2E7a7bAkpYGSLH6kM0nrJZHO3hTvM1wdWOJw==", + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-2.2.9.tgz", + "integrity": "sha512-FfEYdFhOd1nZL+U/up8nlbcRTTyWX4ohXUQcApQMYKIZoR1EJ0g/oBhS915+TSray0DchA+NT6yVL1sqWJOFaQ==", "cpu": [ "x64" ], @@ -3613,9 +3613,9 @@ ] }, "node_modules/@rspack/binding-wasm32-wasi": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-2.2.2.tgz", - "integrity": "sha512-VbDIjjeFwZvMSKAOGY5IbU6lLzt6AHHHncTdMMkZ94Xk7O2BOHe9BXDV32Ln29TIW2C8m1fdxfPZWDiecVghUQ==", + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-2.2.9.tgz", + "integrity": "sha512-+29JEBiUi2TMDOGYmT3Tm3JGk3f19+CbjxNEt1bVreR8axuZZj+wOSwB/sx85lKQkL5fuNPh0BhOZ7cdkDxQpA==", "cpu": [ "wasm32" ], @@ -3629,9 +3629,9 @@ } }, "node_modules/@rspack/binding-win32-arm64-msvc": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-2.2.2.tgz", - "integrity": "sha512-rfcNg0W3ZPZvXma1gTyEt9/Z8FxASIaQr+sMWTSaTPPaeU3xY1+0hYcrD0kUFNs3/5L4u63myI4R8qRXiuW3pA==", + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-2.2.9.tgz", + "integrity": "sha512-x/BDAwQCkR+ANWAAWV+15PFWuae2z9DzL+QcVeb+5taOri+tHa/iQdG8e3GJ60d0amsR+u9BJ2CBtJLK1fQkxw==", "cpu": [ "arm64" ], @@ -3643,9 +3643,9 @@ ] }, "node_modules/@rspack/binding-win32-ia32-msvc": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-2.2.2.tgz", - "integrity": "sha512-TFPvr9RZw9oHIhooDhXHzWjKcHpGPTxkznSeM2poIWU0CdEuua2rVUfsrriTF1Dmx+9kMly61DQmyOHCbb+b2g==", + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-2.2.9.tgz", + "integrity": "sha512-i622t0Mom3STiDi8VHLaX62LKwhbT2kg37fKjzv3wQT+9bJvQ/+St6QQzFZg9C7fV53LXqAw8jFi5yIPIjg0Qw==", "cpu": [ "ia32" ], @@ -3657,9 +3657,9 @@ ] }, "node_modules/@rspack/binding-win32-x64-msvc": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-2.2.2.tgz", - "integrity": "sha512-GvEGyL594dtWN9SoVnKWh0exrM8WLInaUjwcuA2JKbCi1ak/9iHxip/U1dY3DuVqBYBhmvYq96JPbl91xnzFjg==", + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-2.2.9.tgz", + "integrity": "sha512-K98FPCAv0VpDPAz5ZqZ0XI1CmdJu9Kw1FmUDl4rN/zQIt9iqYn+Hgxq6Nk6Zx7g938jiG7ABLwITXSIKGbs6aw==", "cpu": [ "x64" ], @@ -3671,13 +3671,13 @@ ] }, "node_modules/@rspack/core": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@rspack/core/-/core-2.2.2.tgz", - "integrity": "sha512-/yztfDZR5syIPBrUpzBpL+6fhhl0IHBPcXlNr4tOMBULbocFIz7Z4/cqvf1ix0DBbKpIGx99v6N1IDbk2gi8hw==", + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@rspack/core/-/core-2.2.9.tgz", + "integrity": "sha512-Tp6/ZdM5UrGB3BeLfvh69l1iX03PZ46IgXjKqubVEuJVAhnOjpshooH/YAxcxR0AymcBLKA997Z4v+LV2aXzCw==", "dev": true, "license": "MIT", "dependencies": { - "@rspack/binding": "2.2.2" + "@rspack/binding": "2.2.9" }, "engines": { "node": "^20.19.0 || >=22.12.0" @@ -4008,9 +4008,9 @@ } }, "node_modules/@tybys/wasm-util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", - "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.4.tgz", + "integrity": "sha512-W3c4gRigFS0T/Ma4qIYF3GDAc5AQdHb1yL5znJT1Zv1YaD9Kitx656wBjvr19qbiosmZT8lWDM5BEMynUqX65A==", "dev": true, "license": "MIT", "optional": true, @@ -4132,9 +4132,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "26.5.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-26.5.0.tgz", - "integrity": "sha512-dVSGpriSoCgz8WnDNTuSSuSv1PC/ALXihO4ulRZt7Md8k9mlbdin3lGOcDE8SnWOgf513ByWlXd7BK4azmyg/A==", + "version": "26.6.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.6.5.tgz", + "integrity": "sha512-uMzsv9stDdofIZBx4UGh4Z9ZgXnGC9seRDscilBcTHAeOFk67MZg/k9bWVfO+bk4qZmG+l52hRnLwUiH2LnJTg==", "dev": true, "license": "MIT", "dependencies": { @@ -4545,46 +4545,46 @@ } }, "node_modules/@vitest/browser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-5.0.0.tgz", - "integrity": "sha512-JC9FG5xIRxPHXJPcdCaluIJcEoeM0IwGQ3xneuJk09LXKHRNs40BqWDWymQikbb20yOpYvzpKzmYgPRuSzKmvg==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-5.0.5.tgz", + "integrity": "sha512-IDMoZX/iZ8rkilw7weaSgN8tJ7iZ9hUv0wYoKXyiyjWjWFwLSWAY707DcVTgxTYOudWC1E3HA9LYn7kVa9a7uQ==", "dev": true, "license": "MIT", "dependencies": { "@blazediff/core": "1.10.0", - "@vitest/mocker": "5.0.0", - "@vitest/ui": "5.0.0", - "@vitest/utils": "5.0.0", - "magic-string": "^1.2.3", + "@vitest/mocker": "5.0.5", + "@vitest/ui": "5.0.5", + "@vitest/utils": "5.0.5", + "magic-string": "^1.4.3", "pngjs": "^7.0.0", "sirv": "^3.0.2", - "tinyrainbow": "^3.1.1", - "ws": "^8.21.3" + "tinyrainbow": "^3.2.0", + "ws": "^8.22.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "5.0.0" + "vitest": "5.0.5" } }, "node_modules/@vitest/browser-playwright": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@vitest/browser-playwright/-/browser-playwright-5.0.0.tgz", - "integrity": "sha512-N+gED9y4/8pypaHjz/x0ah3CjoBr+N0hWWT+Gq4VXtMzyB+rUIdHni0ulzpD1j4H77iWy5Jg8PRMlVn6kjxo6g==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@vitest/browser-playwright/-/browser-playwright-5.0.5.tgz", + "integrity": "sha512-lcdThFUUcMV9mGGV1SUiZXPxfjgW4CssA7o3STxzh8WK0tT2r526kc12tZIBRZfoLMwkhxjLmMXkWXONzdsDQw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/browser": "5.0.0", - "@vitest/mocker": "5.0.0", - "tinyrainbow": "^3.1.1" + "@vitest/browser": "5.0.5", + "@vitest/mocker": "5.0.5", + "tinyrainbow": "^3.2.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "playwright": "*", - "vitest": "5.0.0" + "vitest": "5.0.5" }, "peerDependenciesMeta": { "playwright": { @@ -4593,22 +4593,22 @@ } }, "node_modules/@vitest/mocker": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-5.0.0.tgz", - "integrity": "sha512-66PGTMIiVJP3t4a5yxU9qPtf7MdTBs8jmToMvy+HVflB3Yy13WJZTtPePdvU+wjRV02SKK5doLbSA6o9pwOmiA==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-5.0.5.tgz", + "integrity": "sha512-xLL3lkDegJZw+MGoGaCCsFayDZthGgpAtr3Vziyfc4p7xH89K7KRPcRBBh/kEYm0Aqkt5DtTmkYpBtRV/FrHZg==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "0.3.31", - "@vitest/spy": "5.0.0", + "@vitest/spy": "5.0.5", "estree-walker": "^3.0.3", - "magic-string": "^1.2.3" + "magic-string": "^1.4.3" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "msw": "^2.4.9", + "msw": "^2.4.9 || ^3.0.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { @@ -4621,22 +4621,22 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-5.0.0.tgz", - "integrity": "sha512-PVRNuB3wpReb4SQEs4zTKM4KWFhQ5pw3spE8naoDJNB5T5aWRzGKHwXcLUllr0WeOTXpB6bSr3CJLo5+7XQSSQ==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-5.0.5.tgz", + "integrity": "sha512-24sSdIlMA9DVPXnYiB9siwU0bTd887Y9jX3+vabztCSsvHwo7ipvJ/a2L3Rljw8+2rK1f5fCj3h5U9I/Jsqgbw==", "dev": true, "license": "MIT", "dependencies": { - "tinyrainbow": "^3.1.1" + "tinyrainbow": "^3.2.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/spy": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-5.0.0.tgz", - "integrity": "sha512-uy+luWBAPw9XfthoHi5AkfHUnuPYEESjl0p/r+meoBnU8bxg5GDQ3Ey8MjcJ6sqahkL4PFyrvfMJJBw7LbU06g==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-5.0.5.tgz", + "integrity": "sha512-lwJRExuH417257Q5wv9QYugN9IMJkoxcrKrYxGPQkBzl7wlNpTUxD/5yNX4ESKVUIShKPgkGchYPFMWOOk0wzw==", "dev": true, "license": "MIT", "funding": { @@ -4644,36 +4644,36 @@ } }, "node_modules/@vitest/ui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-5.0.0.tgz", - "integrity": "sha512-h2FIFwggCY2GxUd2UdQoYNVQkOIqEQLPhNREcl3FUiRsdzQep7NWwYbSmhGEA9nFLPDq5pXzRMcBZQU8Py83sg==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-5.0.5.tgz", + "integrity": "sha512-dCoGUOdgmCaSB2g+WQ/spPCBkytAWdNUkFSXY4z+eYp2d8JEOY8v0uDRaJTG9qf/kTlTVZ4CuYMYMz/f1HS/qQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "5.0.0", + "@vitest/utils": "5.0.5", "fflate": "^0.8.3", "flatted": "^3.4.4", "pathe": "^2.0.3", "sirv": "^3.0.2", - "tinyrainbow": "^3.1.1" + "tinyrainbow": "^3.2.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "5.0.0" + "vitest": "5.0.5" } }, "node_modules/@vitest/utils": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-5.0.0.tgz", - "integrity": "sha512-dO++xL3vDfvhTAVimfkuQUA3k+JClIF1i1vAkPqpcGAthRmeWnXmHB7YPViPvgCwviX8u7Y5W1u2N//AaQr3fw==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-5.0.5.tgz", + "integrity": "sha512-/rBu7gzLDQI/SC79Tn98b5DwOgaHU/Gt4I9OVeP3YofzNaYtbImRCOJQmT1S6vOJg9gEIlWC+r3QxKkjuSa1nQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "5.0.0", + "@vitest/pretty-format": "5.0.5", "convert-source-map": "^2.0.0", - "tinyrainbow": "^3.1.1" + "tinyrainbow": "^3.2.0" }, "funding": { "url": "https://opencollective.com/vitest" @@ -4854,196 +4854,10 @@ "dev": true, "license": "Apache-2.0" }, - "node_modules/@yuku-codegen/binding-android-arm64": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-codegen/binding-android-arm64/-/binding-android-arm64-0.9.4.tgz", - "integrity": "sha512-6ViGFAr+N2Yjnc8wBx16wJZGB0pGmClILO+FUC3kzwEydfjXQovWEdcFyl98RVtWdj9ahS41XXe2zKFl+L3uWg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@yuku-codegen/binding-darwin-arm64": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-codegen/binding-darwin-arm64/-/binding-darwin-arm64-0.9.4.tgz", - "integrity": "sha512-0BTB70ha+wRsz6fI5HosevJpMmvgndmf+6ND1OneFKCrWhNzX/2xIQ36Z8rUgv5bpnWjKl6bRvzSFV3PU+WOlQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@yuku-codegen/binding-darwin-x64": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-codegen/binding-darwin-x64/-/binding-darwin-x64-0.9.4.tgz", - "integrity": "sha512-9QVVqq8LCD6v+Gl099u32YJ0999HBCoe09ecIeifKTi4Y1azX44DkF9q9pP2lxgwRUvR3GmWl5k1pLe3ojR2rg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@yuku-codegen/binding-freebsd-x64": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-codegen/binding-freebsd-x64/-/binding-freebsd-x64-0.9.4.tgz", - "integrity": "sha512-Qm3ky33Em9w1XVSryq+D/arLVapeqp0Bu1719UGV6olmfp4kTD+NfsLG9bRx5hOJSu1Zl3r9LbyTP1oTmcHAsg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@yuku-codegen/binding-linux-arm-gnu": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-codegen/binding-linux-arm-gnu/-/binding-linux-arm-gnu-0.9.4.tgz", - "integrity": "sha512-euKmS7pnkeJylEN6+9bfu0jHtGfbQRfFBIpmTe8YVnWzQ5Rjyrns13+1kao2RSS9DNkucX1RXIdiTvQoDUXF0w==", - "cpu": [ - "arm" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@yuku-codegen/binding-linux-arm-musl": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-codegen/binding-linux-arm-musl/-/binding-linux-arm-musl-0.9.4.tgz", - "integrity": "sha512-7JTizi2O+ks9/dLPDLYmVLsYQUC9Fxu0e6LNA+F6FFQ/sV2o7owBb1eTccMKkgauWGGUpJYQvlXrCKpGwguvhA==", - "cpu": [ - "arm" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@yuku-codegen/binding-linux-arm64-gnu": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-codegen/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.9.4.tgz", - "integrity": "sha512-f7eLYDwmcz56Jzvp8UmXUehFzTAn6hEHt64GDWNWGSqrphHRvWLEshQ+sQv8DfNpkXFaOQ49erl4gb2Wm0JM+A==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@yuku-codegen/binding-linux-arm64-musl": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-codegen/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.9.4.tgz", - "integrity": "sha512-bLdjCgo+u3dU3HH/t+WZ8FsAo2IgdOzruTHZ+XTFquj6j//QJjH9xfyRtu7h65lCT3CQVW9aGEe6/A/HPyA9KQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@yuku-codegen/binding-linux-x64-gnu": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-codegen/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.9.4.tgz", - "integrity": "sha512-hDMB71QCDx2AAxhlCBgakngMAa4KK6f6rcTt9v8nrzoXs681cmZultGeZk0tjONxli+N+VMhXQUoiVCSJuKiQg==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@yuku-codegen/binding-linux-x64-musl": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-codegen/binding-linux-x64-musl/-/binding-linux-x64-musl-0.9.4.tgz", - "integrity": "sha512-uk1hOZA79AqziAH9A/eSD05VchNRdnLb6zxFGHhCbLYeeGYL+KOEL0+kCIPtaKuQ7wdxDOooiKE1D0jpaWQ0aA==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@yuku-codegen/binding-win32-arm64": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-codegen/binding-win32-arm64/-/binding-win32-arm64-0.9.4.tgz", - "integrity": "sha512-IbZuNVrctjts5lAKUEd9ppnzvylaPdYBTv8AVDtY6EyQ5hpgUfsReqbqODJVGpn2/uIk1fa1jWP012orPoiK+A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@yuku-codegen/binding-win32-x64": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-codegen/binding-win32-x64/-/binding-win32-x64-0.9.4.tgz", - "integrity": "sha512-UqC4C0PlVAPEQ8fYr0AamuW2zKAkqQFiaaQ88Rl3YlzSNlshj+VmDoSbJRw4TFYL22+Vw53zDSJ95aXyjJN/aw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@yuku-parser/binding-android-arm64": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-parser/binding-android-arm64/-/binding-android-arm64-0.9.4.tgz", - "integrity": "sha512-x+dZef5ulszaYzgjHLUgnhDXAgJsGfodl30JuTinfLN5mEyB50burpUuyUqufGQp0fpI/sHLAN3V8fuJteFEQQ==", + "node_modules/@yuku-core/binding-android-arm64": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@yuku-core/binding-android-arm64/-/binding-android-arm64-0.19.0.tgz", + "integrity": "sha512-wdL2XmTiZixAOaHk9Z0JJZ8u9Qm8d333Zjpc6gaxXFX+UR5BlsfxZ7a2+2Rm71pamppsPYGUGFq2oVLbh6DISw==", "cpu": [ "arm64" ], @@ -5054,10 +4868,10 @@ "android" ] }, - "node_modules/@yuku-parser/binding-darwin-arm64": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.9.4.tgz", - "integrity": "sha512-bSpjVPP8zTTcMZi78gxPkZZhVNbg4Doqsb2CrxHR2g+vZxP7Ey4GVzgD5nVYSHgS1y8dGULGW8AhPrfRWFEF6w==", + "node_modules/@yuku-core/binding-darwin-arm64": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@yuku-core/binding-darwin-arm64/-/binding-darwin-arm64-0.19.0.tgz", + "integrity": "sha512-7sNJa6XJhyetnTy64jw3NEi4YgUcezHk1G5GH9FSvXAuC8wIlbaOwT9lgq5qo5sspjrZJQlBR1TWflP49uRpMw==", "cpu": [ "arm64" ], @@ -5068,10 +4882,10 @@ "darwin" ] }, - "node_modules/@yuku-parser/binding-darwin-x64": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-parser/binding-darwin-x64/-/binding-darwin-x64-0.9.4.tgz", - "integrity": "sha512-QNswJLBxsoDkghztrF0bUy+DEUoeX1lS4cL3dCM1IB4hfLoZ3Jf3jmCoggDnqN++sJ91F6w8oHiyQ4ZhUEr/bg==", + "node_modules/@yuku-core/binding-darwin-x64": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@yuku-core/binding-darwin-x64/-/binding-darwin-x64-0.19.0.tgz", + "integrity": "sha512-pTC7dYEc59isdyizc3nsuyFNBu2LU5wMYZ1be6UMr59PY/AJNtO1aBLWV0MgL/z7C1nv/2sX4TNjGgKLoeevJw==", "cpu": [ "x64" ], @@ -5082,10 +4896,10 @@ "darwin" ] }, - "node_modules/@yuku-parser/binding-freebsd-x64": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-parser/binding-freebsd-x64/-/binding-freebsd-x64-0.9.4.tgz", - "integrity": "sha512-D4rmGI0EOwxmKsv3+iGQDmtJ9/Oqr9wPxsQpONZ+QmxHqNbl+08XaJkhuC5wAg17bj6afcpdQfiIAoSMBY17Rw==", + "node_modules/@yuku-core/binding-freebsd-x64": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@yuku-core/binding-freebsd-x64/-/binding-freebsd-x64-0.19.0.tgz", + "integrity": "sha512-xrZjF6XOEwyLOiDIfrwDdRCS6ghxcJeirNC1KivQhVcUwlRonaU79S3/Uiyx3lBylPnT8qKJ3/aMT+H52nGTJQ==", "cpu": [ "x64" ], @@ -5096,10 +4910,10 @@ "freebsd" ] }, - "node_modules/@yuku-parser/binding-linux-arm-gnu": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-parser/binding-linux-arm-gnu/-/binding-linux-arm-gnu-0.9.4.tgz", - "integrity": "sha512-rZuqBxlaRnNY57nawRP1LPx4i+ieCrvIQkBsbGu/xjWkZGzFCrHPliy5YiMxp3Mw4v5KftAlDJx7c9jApNk2ww==", + "node_modules/@yuku-core/binding-linux-arm-gnu": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@yuku-core/binding-linux-arm-gnu/-/binding-linux-arm-gnu-0.19.0.tgz", + "integrity": "sha512-0OyIH53C0I1CbADHn9FSdCfX5qbpeLwJhmOVhonFJNYheybOnkSJ50qGMfTJIb8y5zrwqvLs7FVBvz6Fk8maZg==", "cpu": [ "arm" ], @@ -5113,10 +4927,10 @@ "linux" ] }, - "node_modules/@yuku-parser/binding-linux-arm-musl": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-parser/binding-linux-arm-musl/-/binding-linux-arm-musl-0.9.4.tgz", - "integrity": "sha512-0PRDvRZvh18Q1lADxs0RMtqYHTd3dD/o1WEnMO/K8o7V9Gmy/7nD3/HjGQCxFPxkHTp41toF+DsXgEandAc2Gw==", + "node_modules/@yuku-core/binding-linux-arm-musl": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@yuku-core/binding-linux-arm-musl/-/binding-linux-arm-musl-0.19.0.tgz", + "integrity": "sha512-z/iPfkCOCSXE34VXNt0uP1ORSW+4mEa9b5CiJcWZeqZH08g49bFU/jRM2T04f+Wpw5mJ6HIzNBiojxeAbrHjeg==", "cpu": [ "arm" ], @@ -5130,10 +4944,10 @@ "linux" ] }, - "node_modules/@yuku-parser/binding-linux-arm64-gnu": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-parser/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.9.4.tgz", - "integrity": "sha512-CT1I24KFA/Tv/Exi1f+CVxafUIjlKm3gc51HbWLW7yf7OvJKCvKSja+EB17sDtYsS5a2EB9BTr8I5fPuDJ8rFA==", + "node_modules/@yuku-core/binding-linux-arm64-gnu": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@yuku-core/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.19.0.tgz", + "integrity": "sha512-jLNTi+gzaRwBJ+gwhCJ+rDb5dmx/8hEBx93UWd7hjMSqPTL1D1wvVSvXVAldV5kALvju7b0/m51EHEhs4+I1fA==", "cpu": [ "arm64" ], @@ -5147,10 +4961,10 @@ "linux" ] }, - "node_modules/@yuku-parser/binding-linux-arm64-musl": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-parser/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.9.4.tgz", - "integrity": "sha512-DP193Z3nUXQ92AwmmkIAhVLxv2qj8rWAAAODownCwUk0wKrmnyH9km9Gd4NSmntBYG/Kv0P5btN6qcO1JXgEdw==", + "node_modules/@yuku-core/binding-linux-arm64-musl": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@yuku-core/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.19.0.tgz", + "integrity": "sha512-YwyPIdW/rN2Fmv0MTFWi47FaB3F9g+2b+sJISyAw83Yd60RWH4T3Nx6XkAHHVN+uKJNBAd6So7/BVihSiFYvuQ==", "cpu": [ "arm64" ], @@ -5164,10 +4978,10 @@ "linux" ] }, - "node_modules/@yuku-parser/binding-linux-x64-gnu": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-parser/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.9.4.tgz", - "integrity": "sha512-tjoxmuNz+xmSt/Or+US5aaKpRZcptQsWYaPtDp1/0QUvhyg8VS6mOrizKkzVBJKYVNZ7eDTleOBquYVm+Haz6w==", + "node_modules/@yuku-core/binding-linux-x64-gnu": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@yuku-core/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.19.0.tgz", + "integrity": "sha512-/vskaAXVX3ESR43FiTdfiYS7z1b9uoQJwVQ/0RgUHgN2sWoAyCZs+aX4CgU7eKGIHTVfp9VFwv+c+2XchYiEtQ==", "cpu": [ "x64" ], @@ -5181,10 +4995,10 @@ "linux" ] }, - "node_modules/@yuku-parser/binding-linux-x64-musl": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-parser/binding-linux-x64-musl/-/binding-linux-x64-musl-0.9.4.tgz", - "integrity": "sha512-kHXf72EM6oHN58Swwruf9plXlCVY4mOlgqIjpXenEAY87cVcH3VxMZdCQG7rIKa+k0Hf3E/WS/8ufqZSCER7Gw==", + "node_modules/@yuku-core/binding-linux-x64-musl": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@yuku-core/binding-linux-x64-musl/-/binding-linux-x64-musl-0.19.0.tgz", + "integrity": "sha512-FuXL5igeSKib9Rye02TdH+D6SQezTyGxIATMu1Qsn/QywrzwpGl35OLpS2C1x5vpGLeVE2XgiLd5mVPFHmIglQ==", "cpu": [ "x64" ], @@ -5198,10 +5012,10 @@ "linux" ] }, - "node_modules/@yuku-parser/binding-win32-arm64": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-parser/binding-win32-arm64/-/binding-win32-arm64-0.9.4.tgz", - "integrity": "sha512-Yj6+bbGDZrLbzp1Qr7hiaIjYagslUrRy6t3TIxfiXUeJWNH8ydx7birM0UJiIInqUld0mk9qBz1kei/T8gcKvw==", + "node_modules/@yuku-core/binding-win32-arm64": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@yuku-core/binding-win32-arm64/-/binding-win32-arm64-0.19.0.tgz", + "integrity": "sha512-YuJAe7zEKT1Xa7LuHlhGJpPnYQeVtvo0rZvNjJRqkH0hQGOw4C8QeP30Tg5VKGzZfo2x8CjhjEhKt4TmLwfmdg==", "cpu": [ "arm64" ], @@ -5212,10 +5026,10 @@ "win32" ] }, - "node_modules/@yuku-parser/binding-win32-x64": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-parser/binding-win32-x64/-/binding-win32-x64-0.9.4.tgz", - "integrity": "sha512-B9D+Z1/jVfoEd1SgbuaYTPH6onVlSsSaK151mW8Rb6Yv+OrTOocNnv2w3peBicS6MB3VI+mJG8YqxRI4ONd1OQ==", + "node_modules/@yuku-core/binding-win32-x64": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@yuku-core/binding-win32-x64/-/binding-win32-x64-0.19.0.tgz", + "integrity": "sha512-o8iY/mXwlRkedp0LNTr4+TEfXTPQwoNZmv6k+1WIAd1ZXEn8xJJTBCtB0osaVvdZo/x/cNmV16UrWrrGpM5Mvw==", "cpu": [ "x64" ], @@ -5227,9 +5041,9 @@ ] }, "node_modules/@yuku-toolchain/types": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@yuku-toolchain/types/-/types-0.9.4.tgz", - "integrity": "sha512-dqnMswJWE7YBbPEvGstgFlWFTRn20V/Hu82XTDjWxzaU18rGpxBqxhKlBlgyWrPARRvNLIqY2XA6S9edR+2AsA==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@yuku-toolchain/types/-/types-0.19.0.tgz", + "integrity": "sha512-tFkNbsP4WXX9UMUC5syJGdK9dPMLK0PPaIuXCcCYH75sZ8MrebfBZ2XvCILRTw8AgLivSSCfDa4R67iYBDa4Kg==", "dev": true, "license": "MIT" }, @@ -5271,9 +5085,9 @@ } }, "node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "dev": true, "license": "MIT", "dependencies": { @@ -5288,9 +5102,9 @@ } }, "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5581,9 +5395,9 @@ } }, "node_modules/cac": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cac/-/cac-7.0.0.tgz", - "integrity": "sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cac/-/cac-7.1.0.tgz", + "integrity": "sha512-LMDU/U2yA4IPIY8KT0NsNPWEYZvAMkbgyspxJ6btJaYV+WMDOHAZCmB0lsTObiHaRS1V/ztKAl7+TSkTqXyeoA==", "dev": true, "license": "MIT", "engines": { @@ -5643,9 +5457,9 @@ "license": "CC-BY-4.0" }, "node_modules/chai": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", - "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.3.0.tgz", + "integrity": "sha512-XWAtwJ6OHO+tj0EKCs0Y2UamnyOxseZWltU4x2U2wh8g4AigdjwvtUjvLP2tqkA/avxHEtzxNaqGq/YGNwckKg==", "dev": true, "license": "MIT", "engines": { @@ -6031,9 +5845,9 @@ "license": "ISC" }, "node_modules/empathic": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.1.tgz", - "integrity": "sha512-YGRs8knHhKHVShLkFET/rWAU8kmHbOV5LwN938RHI0pljAJ1Gf6SzXsSmRaEzcXTtOOmVqJ5+WtQPL5uigY50Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.1.0.tgz", + "integrity": "sha512-AnfC1ATldl49/cvZdLPDjBfrRNwbDO05aibiOtzQu3qtlbJtomNLhF30HEtn/7iBz50dlMECqATo3fG0LrdEgw==", "dev": true, "license": "MIT", "engines": { @@ -6051,9 +5865,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.24.5", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz", - "integrity": "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==", + "version": "5.26.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.26.0.tgz", + "integrity": "sha512-9vhedylFonb2YGogzUKX6+Ja72gOJbN1QHAqdrvqLwhdl/QWbKopzoUC9EbQNVsAns/bx/4uyqalrQAoy1IByw==", "dev": true, "license": "MIT", "dependencies": { @@ -6622,9 +6436,9 @@ "license": "ISC" }, "node_modules/happy-dom": { - "version": "20.14.0", - "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-20.14.0.tgz", - "integrity": "sha512-4bRh1KzRvKDnFNTlLhzT1RZTpkKhQbQDl9j+7GXszWsvuspYdo29k6OHRf4PwiM6oLb8r/pMWeYiJjkfod5AvQ==", + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-21.0.3.tgz", + "integrity": "sha512-PesNgu5BnIEmAwzKGewB3K1ORFeznFZJ4JrRz89ea1wkHnxskdpzX9sN/+zb4KO6k8oSMhyJSj/cwXAFrYBBNA==", "dev": true, "license": "MIT", "dependencies": { @@ -6677,9 +6491,9 @@ } }, "node_modules/hookable": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/hookable/-/hookable-6.1.1.tgz", - "integrity": "sha512-U9LYDy1CwhMCnprUfeAZWZGByVbhd54hwepegYTK7Pi5NvqEj63ifz5z+xukznehT7i6NIZRu89Ay1AZmRsLEQ==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-6.1.2.tgz", + "integrity": "sha512-+abwxtiEA52GCVIsQqut3S/uKTbUwYIp4Pe/vv+6py5XiXBCqMZHg6pA6Y5qhgLSEys0/cYuPbO0z1QFj5ZCmg==", "dev": true, "license": "MIT" }, @@ -6801,9 +6615,9 @@ } }, "node_modules/import-without-cache": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/import-without-cache/-/import-without-cache-0.4.0.tgz", - "integrity": "sha512-NkJQA7oZ4YHQhd2+H3BoRFKF3d/XNsiKpHZCQEMH9pDX27hQQLsTyOocyRgaIVtf8gHX3Nt3LPkR4e5EdtPAGQ==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/import-without-cache/-/import-without-cache-0.4.1.tgz", + "integrity": "sha512-vXoV9PjKHEednCUu01e98TkImxy67e3BJXbTIOmIq4Hyzw3IAwYRcuPkfeTzJzwyyts4kjuA73x+pWJLc4f86A==", "dev": true, "license": "MIT", "engines": { @@ -7089,9 +6903,9 @@ } }, "node_modules/lefthook": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/lefthook/-/lefthook-2.1.12.tgz", - "integrity": "sha512-2uOexfsrrRhCiTUWdGyDySxVHHhOFJ8MQejs27dM3hugrQB48/z1ZVlaNoxpZ1SnzQ1GaDIbO5rAvicwyiknYQ==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/lefthook/-/lefthook-2.2.2.tgz", + "integrity": "sha512-37fYHAhL12r1twaEV0PA5TwoIT491eTGGYjhhXxlYNMq3DSkiGZBQ++Jfk5maXj0vq52NRauLtMikBKtbNJs3Q==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -7099,22 +6913,37 @@ "lefthook": "bin/index.js" }, "optionalDependencies": { - "lefthook-darwin-arm64": "2.1.12", - "lefthook-darwin-x64": "2.1.12", - "lefthook-freebsd-arm64": "2.1.12", - "lefthook-freebsd-x64": "2.1.12", - "lefthook-linux-arm64": "2.1.12", - "lefthook-linux-x64": "2.1.12", - "lefthook-openbsd-arm64": "2.1.12", - "lefthook-openbsd-x64": "2.1.12", - "lefthook-windows-arm64": "2.1.12", - "lefthook-windows-x64": "2.1.12" - } + "lefthook-android-arm64": "2.2.2", + "lefthook-darwin-arm64": "2.2.2", + "lefthook-darwin-x64": "2.2.2", + "lefthook-freebsd-arm64": "2.2.2", + "lefthook-freebsd-x64": "2.2.2", + "lefthook-linux-arm64": "2.2.2", + "lefthook-linux-x64": "2.2.2", + "lefthook-openbsd-arm64": "2.2.2", + "lefthook-openbsd-x64": "2.2.2", + "lefthook-windows-arm64": "2.2.2", + "lefthook-windows-x64": "2.2.2" + } + }, + "node_modules/lefthook-android-arm64": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/lefthook-android-arm64/-/lefthook-android-arm64-2.2.2.tgz", + "integrity": "sha512-wb9rQQFLX7u1dJLxvMrq9VUfMYi5kxM7tJQ6Y4mWEOwaU+SmIm2wjoT/nromKq27Y8fh2Qd7FgCD3G1wfW8CnQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] }, "node_modules/lefthook-darwin-arm64": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/lefthook-darwin-arm64/-/lefthook-darwin-arm64-2.1.12.tgz", - "integrity": "sha512-GSUjqaCuxAYlPOovbjXEWE3HAIa/xOQkTTmZ937zieQldjPLTaC7+s5FHoxKywn+D9riBlofkDqG7Z4f5zzmPA==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/lefthook-darwin-arm64/-/lefthook-darwin-arm64-2.2.2.tgz", + "integrity": "sha512-6V8D3bLnD/60Xhqn0o2EQD6H3Fe/U9LGkt4WF1O/3eBHbux+5ZJqoH0hfrC+Bi9Dy1Ve1AWxiAY7U2asYl8qVA==", "cpu": [ "arm64" ], @@ -7126,9 +6955,9 @@ ] }, "node_modules/lefthook-darwin-x64": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/lefthook-darwin-x64/-/lefthook-darwin-x64-2.1.12.tgz", - "integrity": "sha512-qAUHSSw/7Afi5wxkoLkxORxSicCeTBXyVLnRgD6YZra6udviozpK3Aok9Z6FIWeKc5FBijRMSNDxGPTREhsjcQ==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/lefthook-darwin-x64/-/lefthook-darwin-x64-2.2.2.tgz", + "integrity": "sha512-fH/kArZ9ZZ65wCFtvBMgGcq25qwQpkQ5jp93ba+8wpjgxxzjczYGluwHvM/NQDJWLOFXuKXW0yFs76SramQkyQ==", "cpu": [ "x64" ], @@ -7140,9 +6969,9 @@ ] }, "node_modules/lefthook-freebsd-arm64": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/lefthook-freebsd-arm64/-/lefthook-freebsd-arm64-2.1.12.tgz", - "integrity": "sha512-FHZRfKliFNbyz54zsoGdVe9muq67cNjBTZ6jrPPUjI7xUuyCwSpzA+1OpiwJT00L9pP5ZGONBqnGZKnrpC+7Uw==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/lefthook-freebsd-arm64/-/lefthook-freebsd-arm64-2.2.2.tgz", + "integrity": "sha512-MCRsU01ju989QQffOfS3gCeFfyVDXs5B/FzR65fmrNvqcxb98fldvfzzoAbnK2q6SBJlRT3QT1tNEMCxddCwlA==", "cpu": [ "arm64" ], @@ -7154,9 +6983,9 @@ ] }, "node_modules/lefthook-freebsd-x64": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/lefthook-freebsd-x64/-/lefthook-freebsd-x64-2.1.12.tgz", - "integrity": "sha512-HYQZPGy2DDEx7dbuotusJpujY5q9igOLgx36qeeQcNQuvvdGHPj2ZGSIsGKhoJ0dw5Qa4knKJoPAHEZQWdV/og==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/lefthook-freebsd-x64/-/lefthook-freebsd-x64-2.2.2.tgz", + "integrity": "sha512-LkKuJU0S2oLimeoHwPTy1TLWB6GcN0t5lLxiXNlsBKUkr6R47QRcvPMZMoXmu3IetQtd+WliXMLE8qTwi2fqBg==", "cpu": [ "x64" ], @@ -7168,9 +6997,9 @@ ] }, "node_modules/lefthook-linux-arm64": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/lefthook-linux-arm64/-/lefthook-linux-arm64-2.1.12.tgz", - "integrity": "sha512-ipjOri2PB/sk4noPrHQuM5fcpNBjmlKo4qMtXyLnxeOxGYHWZzf0Xi0OtrXHQ//tOprcv40ADvhUuSdcGqigLw==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/lefthook-linux-arm64/-/lefthook-linux-arm64-2.2.2.tgz", + "integrity": "sha512-d+HFtS2DEKaOnD7vRU0tUz8pNgHwsUYmQ22+1dyXpOrXGyzNXR0AqX5KsIRF36JGhVvO5X5Anw5QYgR3mxVSuA==", "cpu": [ "arm64" ], @@ -7182,9 +7011,9 @@ ] }, "node_modules/lefthook-linux-x64": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/lefthook-linux-x64/-/lefthook-linux-x64-2.1.12.tgz", - "integrity": "sha512-DmU6xfvqVoFdW+STyc70YI4Ry8vkHGKHx+IJ1Js/Gacq5dv+fiwNzwle3bi28EkL6P8xY67B/CfQfRj4SRU4tg==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/lefthook-linux-x64/-/lefthook-linux-x64-2.2.2.tgz", + "integrity": "sha512-N/OlQyAhcU6RAXjrwFxLsh70sn96rBoi+XkuLJ8CVBkk9Ci3VDXQayDZTNz5B1xML8RwoMcV8Wblniy1xFOmSA==", "cpu": [ "x64" ], @@ -7196,9 +7025,9 @@ ] }, "node_modules/lefthook-openbsd-arm64": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/lefthook-openbsd-arm64/-/lefthook-openbsd-arm64-2.1.12.tgz", - "integrity": "sha512-vb0J7bElLvoaCWQmna3HntsvoNqMsGAhfjjC99ss1OdCteufZKM3RxCVoMBEbD50Itv2c1Ua2AFVToltVFTy1Q==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/lefthook-openbsd-arm64/-/lefthook-openbsd-arm64-2.2.2.tgz", + "integrity": "sha512-6G/gKXcpIwC+XcODg7ELZYP/hIrVIHQxhy2GoRdVyecmpGMFj+BZo3iqcUmeWusQMuL+UdNexbkrUaeJalIkNw==", "cpu": [ "arm64" ], @@ -7210,9 +7039,9 @@ ] }, "node_modules/lefthook-openbsd-x64": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/lefthook-openbsd-x64/-/lefthook-openbsd-x64-2.1.12.tgz", - "integrity": "sha512-QOmhDWqPPK4+99scanfEmbJjUR+JYC93qhr/0bp5Dj3LaR3kVFNWc6zOQUsOTPy/LC6PG759Lej/mr/BtjUL2Q==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/lefthook-openbsd-x64/-/lefthook-openbsd-x64-2.2.2.tgz", + "integrity": "sha512-eMJGi3/tqKEqu7XCZlqwQWRtK5JlL/9diaqqgRlEdlRD7GxwzHZN21z6awbITum9emea3lALvXFe6V8odQLGOA==", "cpu": [ "x64" ], @@ -7224,9 +7053,9 @@ ] }, "node_modules/lefthook-windows-arm64": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/lefthook-windows-arm64/-/lefthook-windows-arm64-2.1.12.tgz", - "integrity": "sha512-eErEyr9AHkRFj6TxpCQeKGd0s6IrtL/VEIZ/ssg8dNfG+ycR4jAW/IAlrJSw6/ZQXb3WtWLaQ6QA5c+TLh7vmg==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/lefthook-windows-arm64/-/lefthook-windows-arm64-2.2.2.tgz", + "integrity": "sha512-4P1EaQb5xG1zhYD1RLJ6TEGdFkmHkB+Slqx6yRDPKuBDNxMiD0+kTAAdUY2E8xPuRR35xHpVPR+b3/HtzPrjQQ==", "cpu": [ "arm64" ], @@ -7238,9 +7067,9 @@ ] }, "node_modules/lefthook-windows-x64": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/lefthook-windows-x64/-/lefthook-windows-x64-2.1.12.tgz", - "integrity": "sha512-0h+WmDVdDriTjloD/UbjPq/ZtqaaJlPAdGcVwMCEdAxfbF0FTgDbKX3igui9g2U/qG2y6QpVhtz1jeiRe7ctaw==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/lefthook-windows-x64/-/lefthook-windows-x64-2.2.2.tgz", + "integrity": "sha512-9Ck4zancQilBfXT3ZeRipm7Lcq4RQfxyMpy8SAVINw0t/BrbjsT25V46ZuziERcwdajnE4myfMzC33GoCBwr7g==", "cpu": [ "x64" ], @@ -7571,13 +7400,13 @@ } }, "node_modules/magic-string": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.2.3.tgz", - "integrity": "sha512-Bpb0W2TbLKOZ7vJnOUnVRGq3WL2p+ISV29M6hYPL1AFCpyKZpdr5ytiXoTSSxRVhg8YW7f65+6gbG8WG6PCa/g==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.3.tgz", + "integrity": "sha512-z12OxmaPGE0F4xlpGdjuAUckipLpQlTAuAmyGhNoD7ODpYUzvDfvtxUbjM/jwznyP178oju/KDdyi220wNJ0RQ==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" + "@jridgewell/sourcemap-codec": "^1.6.0" } }, "node_modules/math-intrinsics": { @@ -7711,9 +7540,9 @@ } }, "node_modules/minimizer-webpack-plugin": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/minimizer-webpack-plugin/-/minimizer-webpack-plugin-5.10.0.tgz", - "integrity": "sha512-2//60T4S0X1Ug/dqLDOgDaGlZsN1Lv8hf8oB0NOV/KIHSaXlPwXBBIbim79dE2Z7NEs52ES8YHoSv6Lmsk+XNg==", + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/minimizer-webpack-plugin/-/minimizer-webpack-plugin-5.13.0.tgz", + "integrity": "sha512-OO1NF2zHj6sf4CNv2AsUWYcS8WEwkVKQDXxxKzlOxx1Xl+WlqYtVC+oNlGNwGkLAOnpj277BSHypWwRtd9w4JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7873,9 +7702,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.18", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", - "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", + "version": "3.3.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.20.tgz", + "integrity": "sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==", "dev": true, "funding": [ { @@ -7901,13 +7730,6 @@ "node": ">= 0.6" } }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true, - "license": "MIT" - }, "node_modules/node-addon-api": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", @@ -7958,9 +7780,9 @@ } }, "node_modules/obug": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", - "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/obug/-/obug-3.0.0.tgz", + "integrity": "sha512-5vvB5+W7ePv+p3uqxi+RcW1XAzLW0/hxt3/4X4Lc4qHudzOhmBiBwOY6DRob4WnanAEGvNcLjF+KNOufrUoEQw==", "dev": true, "funding": [ "https://github.com/sponsors/sxzz", @@ -8033,13 +7855,13 @@ "license": "MIT" }, "node_modules/oxfmt": { - "version": "0.67.0", - "resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.67.0.tgz", - "integrity": "sha512-vV7sSiPsaO0mSxdoUdayipVDFPzW/UQ+hrezEHa20+Tx1dnMdZLSRHMT0PdS67FFbhd74M1n08asW21aLGeCrA==", + "version": "0.73.0", + "resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.73.0.tgz", + "integrity": "sha512-Ke4xbpuzqIBP4bkd48q815RhqWNJqOBzxVA9199M4qcF0y0LtpUv7UTg1dJ5ea6jw0RBUDZvX3qOUMNmmxfxbw==", "dev": true, "license": "MIT", "dependencies": { - "tinypool": "2.1.2" + "tinypool": "2.2.0" }, "bin": { "oxfmt": "bin/oxfmt" @@ -8051,31 +7873,35 @@ "url": "https://github.com/sponsors/oxc-project" }, "optionalDependencies": { - "@oxfmt/binding-android-arm-eabi": "0.67.0", - "@oxfmt/binding-android-arm64": "0.67.0", - "@oxfmt/binding-darwin-arm64": "0.67.0", - "@oxfmt/binding-darwin-x64": "0.67.0", - "@oxfmt/binding-freebsd-x64": "0.67.0", - "@oxfmt/binding-linux-arm-gnueabihf": "0.67.0", - "@oxfmt/binding-linux-arm-musleabihf": "0.67.0", - "@oxfmt/binding-linux-arm64-gnu": "0.67.0", - "@oxfmt/binding-linux-arm64-musl": "0.67.0", - "@oxfmt/binding-linux-ppc64-gnu": "0.67.0", - "@oxfmt/binding-linux-riscv64-gnu": "0.67.0", - "@oxfmt/binding-linux-riscv64-musl": "0.67.0", - "@oxfmt/binding-linux-s390x-gnu": "0.67.0", - "@oxfmt/binding-linux-x64-gnu": "0.67.0", - "@oxfmt/binding-linux-x64-musl": "0.67.0", - "@oxfmt/binding-openharmony-arm64": "0.67.0", - "@oxfmt/binding-win32-arm64-msvc": "0.67.0", - "@oxfmt/binding-win32-ia32-msvc": "0.67.0", - "@oxfmt/binding-win32-x64-msvc": "0.67.0" + "@oxfmt/binding-android-arm-eabi": "0.73.0", + "@oxfmt/binding-android-arm64": "0.73.0", + "@oxfmt/binding-darwin-arm64": "0.73.0", + "@oxfmt/binding-darwin-x64": "0.73.0", + "@oxfmt/binding-freebsd-x64": "0.73.0", + "@oxfmt/binding-linux-arm-gnueabihf": "0.73.0", + "@oxfmt/binding-linux-arm-musleabihf": "0.73.0", + "@oxfmt/binding-linux-arm64-gnu": "0.73.0", + "@oxfmt/binding-linux-arm64-musl": "0.73.0", + "@oxfmt/binding-linux-ppc64-gnu": "0.73.0", + "@oxfmt/binding-linux-riscv64-gnu": "0.73.0", + "@oxfmt/binding-linux-riscv64-musl": "0.73.0", + "@oxfmt/binding-linux-s390x-gnu": "0.73.0", + "@oxfmt/binding-linux-x64-gnu": "0.73.0", + "@oxfmt/binding-linux-x64-musl": "0.73.0", + "@oxfmt/binding-openharmony-arm64": "0.73.0", + "@oxfmt/binding-win32-arm64-msvc": "0.73.0", + "@oxfmt/binding-win32-ia32-msvc": "0.73.0", + "@oxfmt/binding-win32-x64-msvc": "0.73.0" }, "peerDependencies": { + "@astrojs/compiler-rs": "^0.4.0 || ^0.5.0", "svelte": "^5.0.0", "vite-plus": "*" }, "peerDependenciesMeta": { + "@astrojs/compiler-rs": { + "optional": true + }, "svelte": { "optional": true }, @@ -8287,13 +8113,13 @@ } }, "node_modules/playwright": { - "version": "1.63.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.63.0.tgz", - "integrity": "sha512-+7ziBLidS4NaNCdt57SUDT+wYmmd5fmiQejUic/kb+YsYSCPyOOE9sebzMjNmQrsnNpDJqd4WHvV/8lfKfUDUg==", + "version": "1.64.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.64.1.tgz", + "integrity": "sha512-HCrVhHr5QQuwYoswEUGTb7gGp522yflbv/ST8nF4sFWGuLjQCt17Q/EubpGGSNKYn1tsTCPZxqHhHCfVURu7UA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.63.0" + "playwright-core": "1.64.1" }, "bin": { "playwright": "cli.js" @@ -8303,9 +8129,9 @@ } }, "node_modules/playwright-core": { - "version": "1.63.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.63.0.tgz", - "integrity": "sha512-rYCsBF/M5HjUch52bbtVONEFjv6Xu8sm8h72dNlR5bzIE1fvC/bxgspzkjSfU+MweEMmPM8KJebG6nnyxo5mCg==", + "version": "1.64.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.64.1.tgz", + "integrity": "sha512-BC4s8y6SEVA6Q1rSxZTto8hI1KUI3xXlHGZgvGqP4IqPdI/a6FX9H29IDNz7vKo9l21b6LfYosScPL6M3xxyDQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -8326,9 +8152,9 @@ } }, "node_modules/postcss": { - "version": "8.5.28", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.28.tgz", - "integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==", + "version": "8.5.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.29.tgz", + "integrity": "sha512-49cGhUbXj8Qenv0iTMxA1cFBzxXoctpC9Ujd77t1WcbJIr6nF/eI7g/8MgxrYldFRuAXvja7xQRwavoW7kgrxQ==", "dev": true, "funding": [ { @@ -8346,9 +8172,9 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.18", + "nanoid": "^3.3.19", "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" + "source-map-js": "^1.2.2" }, "engines": { "node": "^10 || ^12 || >=14" @@ -8399,9 +8225,9 @@ } }, "node_modules/publint": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/publint/-/publint-0.3.24.tgz", - "integrity": "sha512-9zS56KrKBoqi5Qt8h92uMP8TTM9AYZSgnmCo4u2priMqkOZvQnTsziZ2p5LJ2ywbYkAjoCDp2jda9u4cgFefIw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/publint/-/publint-0.3.25.tgz", + "integrity": "sha512-WMMbn/d7JqRlfXQL/JUI4n5skC8cJ5WVr8/wT5mmiYWkUdENkZr1I5rgs2+dQPVRgoJd+JRYtB46MTsuDylw9g==", "dev": true, "license": "MIT", "dependencies": { @@ -8621,13 +8447,13 @@ } }, "node_modules/rolldown": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.7.tgz", - "integrity": "sha512-g0EtLvBjTUB7jhyV0S/TCup3v/XSVl45vUIGbOGU4QPiyjTenCe4mKuFvW9fEgYmS2Fo42AUssRmNuMziXdrig==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.13.tgz", + "integrity": "sha512-/5apOkwWxtACcQtZ5WlrAsKS4JwXVThQPJZ3RqIruRY9UG9M8e0VlXN068xum/JRKA4aIUoJ13ghe/kGCvidiQ==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.148.0", + "@oxc-project/types": "=0.153.0", "@rolldown/pluginutils": "^1.0.0" }, "bin": { @@ -8637,36 +8463,36 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm-eabi": "1.2.7", - "@rolldown/binding-android-arm64": "1.2.7", - "@rolldown/binding-darwin-arm64": "1.2.7", - "@rolldown/binding-darwin-x64": "1.2.7", - "@rolldown/binding-freebsd-x64": "1.2.7", - "@rolldown/binding-linux-arm-gnueabihf": "1.2.7", - "@rolldown/binding-linux-arm64-gnu": "1.2.7", - "@rolldown/binding-linux-arm64-musl": "1.2.7", - "@rolldown/binding-linux-ppc64-gnu": "1.2.7", - "@rolldown/binding-linux-s390x-gnu": "1.2.7", - "@rolldown/binding-linux-x64-gnu": "1.2.7", - "@rolldown/binding-linux-x64-musl": "1.2.7", - "@rolldown/binding-openharmony-arm64": "1.2.7", - "@rolldown/binding-win32-arm64-msvc": "1.2.7", - "@rolldown/binding-win32-x64-msvc": "1.2.7" + "@rolldown/binding-android-arm-eabi": "1.2.13", + "@rolldown/binding-android-arm64": "1.2.13", + "@rolldown/binding-darwin-arm64": "1.2.13", + "@rolldown/binding-darwin-x64": "1.2.13", + "@rolldown/binding-freebsd-x64": "1.2.13", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.13", + "@rolldown/binding-linux-arm64-gnu": "1.2.13", + "@rolldown/binding-linux-arm64-musl": "1.2.13", + "@rolldown/binding-linux-ppc64-gnu": "1.2.13", + "@rolldown/binding-linux-s390x-gnu": "1.2.13", + "@rolldown/binding-linux-x64-gnu": "1.2.13", + "@rolldown/binding-linux-x64-musl": "1.2.13", + "@rolldown/binding-openharmony-arm64": "1.2.13", + "@rolldown/binding-win32-arm64-msvc": "1.2.13", + "@rolldown/binding-win32-x64-msvc": "1.2.13" } }, "node_modules/rolldown-plugin-dts": { - "version": "0.28.5", - "resolved": "https://registry.npmjs.org/rolldown-plugin-dts/-/rolldown-plugin-dts-0.28.5.tgz", - "integrity": "sha512-yYd3C9CeJwqjOc9X23m0Tyxcqic491uLZlfg51szT287S8zCCqLR2uoySoElgqy2CLn7PdXcEo1dlkBs4n1WHg==", + "version": "0.28.8", + "resolved": "https://registry.npmjs.org/rolldown-plugin-dts/-/rolldown-plugin-dts-0.28.8.tgz", + "integrity": "sha512-FVhfqxorCWcc20BVT5eVRfRjzLLl6mgzjcMR4gSBf0K4oQMXT0qoHhhzfXy0L7y83fQy7Ug5ZDNk90xM3/LiCQ==", "dev": true, "license": "MIT", "dependencies": { "dts-resolver": "^3.0.0", "get-tsconfig": "5.0.0-beta.6", - "obug": "^2.1.4", - "yuku-ast": "^0.9.3", - "yuku-codegen": "^0.9.3", - "yuku-parser": "^0.9.3" + "obug": "^3.0.0", + "yuku-ast": "^0.19.0", + "yuku-codegen": "^0.19.0", + "yuku-parser": "^0.19.0" }, "engines": { "node": "^22.18.0 || ^24.11.0 || >=26.0.0" @@ -8677,6 +8503,7 @@ "peerDependencies": { "@typescript/native-preview": "*", "@volar/typescript": "~2.4.0", + "@vue/language-core": "~3.2.0 || ~3.3.0", "rolldown": "^1.2.0", "typescript": "^5.0.0 || ^6.0.0 || ~7.0.0", "vue-tsc": "~3.2.0 || ~3.3.0" @@ -8688,6 +8515,9 @@ "@volar/typescript": { "optional": true }, + "@vue/language-core": { + "optional": true + }, "typescript": { "optional": true }, @@ -8792,15 +8622,15 @@ "license": "MIT" }, "node_modules/schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.5.0.tgz", + "integrity": "sha512-zJlMCZ0cAR5p/Y4oVpRoqioDMJcGxaXRrQ/4rP4WyR84vc5z/DolXdbvXeDpTwbtocDFr2rhPqHPErDCUtz2kA==", "dev": true, "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", + "@types/json-schema": "^7.0.15", + "ajv": "^8.20.0", + "ajv-formats": "^3.0.1", "ajv-keywords": "^5.1.0" }, "engines": { @@ -9119,13 +8949,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true, - "license": "ISC" - }, "node_modules/sirv": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", @@ -9152,9 +8975,9 @@ } }, "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz", + "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -9172,13 +8995,6 @@ "source-map": "^0.6.0" } }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true, - "license": "MIT" - }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -9190,9 +9006,9 @@ } }, "node_modules/std-env": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz", - "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.3.0.tgz", + "integrity": "sha512-OtU/EgQ1kIm5KwqQpBC6ZEMXrZRui11w8zgfTWp8cdO9B8OaPsbA8bTHO2P+HNo1VlUTGMVBwPhydu6poeXiag==", "dev": true, "license": "MIT" }, @@ -9300,9 +9116,9 @@ "license": "MIT" }, "node_modules/tinybench": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-6.1.4.tgz", - "integrity": "sha512-9APumHG7r4yOk4X4WlkmE71aZcv1gvin1czO3OQ1U9iJcFA5Ja/ygyb0vPOVHTthFozUYs8CLoLUlM8grb2lTQ==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-6.2.2.tgz", + "integrity": "sha512-nIZ2N2dFpjBsg2hgitKu7mA+FvsIJuGJOwysRngmVRRmWgR/UyPjwJj8c/fT/dhm8EkHnF5EOogRf+0Z2qrimA==", "dev": true, "license": "MIT", "engines": { @@ -9337,9 +9153,9 @@ } }, "node_modules/tinypool": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-2.1.2.tgz", - "integrity": "sha512-9YodfrxS9g9IbFr/KOjE5bAeJ0p61n3bW6mqvy0jtoeKd1kTW1Cxm0oulm6KX2lyM9Gl6WIe8nEbY7LWv5ZJww==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-2.2.0.tgz", + "integrity": "sha512-jBrmx4lYmaC9k/mgPbylxs7kBUxHtD8256up+HjLaDFfXScKJQyil+SWXSvhAtT7XHo+yTVlpB81PGmHP8oLSQ==", "dev": true, "license": "MIT", "engines": { @@ -9347,9 +9163,9 @@ } }, "node_modules/tinyrainbow": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz", - "integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.2.0.tgz", + "integrity": "sha512-LgO3D9yZJjApUiuUfl9iFAwrtaX4+lok3wJIqttGoKCHlWUqHqbQpnxCf82L8FjgKsh4iGo78hqJwgL8F6To2A==", "dev": true, "license": "MIT", "engines": { @@ -9417,26 +9233,26 @@ } }, "node_modules/tsdown": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/tsdown/-/tsdown-0.23.0.tgz", - "integrity": "sha512-BaT+ep1xnj5hdyICLd5r5SYYE+TXnI1ATePLykv9vcKpHpFTWUWRH+x1AF/E2qcu3YB6+vI8IdyxIIIffEqw5Q==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/tsdown/-/tsdown-0.23.1.tgz", + "integrity": "sha512-MSC2WSOts3in95J334/VIS7KPfor3eCSvndJ6KdoVj9Aak9Kh1aNfz9ws5owhdukuTNSXRdfkPEzA/ihpDD6SA==", "dev": true, "license": "MIT", "dependencies": { - "cac": "^7.0.0", + "cac": "^7.0.1", "defu": "^6.1.7", - "empathic": "^2.0.1", - "hookable": "^6.1.1", - "import-without-cache": "^0.4.0", - "obug": "^2.1.4", + "empathic": "^2.1.0", + "hookable": "^6.1.2", + "import-without-cache": "^0.4.1", + "obug": "^3.0.0", "picomatch": "^4.0.7", - "rolldown": "~1.2.7", - "rolldown-plugin-dts": "^0.28.5", + "rolldown": "~1.2.13", + "rolldown-plugin-dts": "^0.28.7", "tinyexec": "^1.3.1", "tinyglobby": "^0.2.17", "tree-kill": "^1.2.2", "unconfig-core": "^7.5.0", - "verkit": "^0.4.0" + "verkit": "^0.5.0" }, "bin": { "tsdown": "dist/run.mjs" @@ -9449,8 +9265,8 @@ }, "peerDependencies": { "@arethetypeswrong/core": "^0.18.1", - "@tsdown/css": "0.23.0", - "@tsdown/exe": "0.23.0", + "@tsdown/css": "0.23.1", + "@tsdown/exe": "0.23.1", "@vitejs/devtools": "*", "publint": "^0.3.8", "tsx": "*", @@ -9696,9 +9512,9 @@ } }, "node_modules/verkit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/verkit/-/verkit-0.4.0.tgz", - "integrity": "sha512-sXMwN6DMHeouPfCxkxWkKAmxphWKEenHYY5H1nIBzU3PmDsmJp6kBXJdshjVdpMZuWCmL9SH7KFRx29AylpP6g==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/verkit/-/verkit-0.5.0.tgz", + "integrity": "sha512-u4J1hr6Y+C/hit34GwL3eIcUf3wngT8TlYUjK7tk0jxydKLAq3sYvifjdTDA6U3KCKRcQCQDGf/srjxfZF3l7g==", "dev": true, "license": "MIT", "engines": { @@ -9709,16 +9525,16 @@ } }, "node_modules/vite": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.2.tgz", - "integrity": "sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q==", + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.3.4.tgz", + "integrity": "sha512-IftLE8phJhdNRIGNEV4JCCvfNScoZQVfcXaN8TQropWGJtOHcu+iAB9pHcuGvmEb/kddw0LBe/jS8ztdC6xdiQ==", "dev": true, "license": "MIT", "dependencies": { "lightningcss": "^1.33.0", - "picomatch": "^4.0.5", - "postcss": "^8.5.26", - "rolldown": "~1.2.4", + "picomatch": "^4.0.7", + "postcss": "^8.5.29", + "rolldown": "~1.2.12", "tinyglobby": "^0.2.17" }, "bin": { @@ -9735,7 +9551,7 @@ }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.4.0 || ^0.5.0", + "@vitejs/devtools": "^0.7.1", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", @@ -9787,25 +9603,25 @@ } }, "node_modules/vitest": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-5.0.0.tgz", - "integrity": "sha512-gpsMNoRhMjMktVxPtstOH4/PJuPyovVaMDr4oDilXaGH1EcqM2OE96SoHT2VIQ6fTGtTjqmHDrEu2X9RQiXf8Q==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-5.0.5.tgz", + "integrity": "sha512-cPODOMF8YnkiiYtDdHo6n4wWmBrOBBbOIYH2d33M4l3CdNn72h+qMmO6uXffUN6A5AZFXNND/d+krS9mgkXRfg==", "dev": true, "license": "MIT", "dependencies": { "@types/chai": "^5.2.2", - "@vitest/mocker": "5.0.0", - "chai": "^6.2.2", + "@vitest/mocker": "5.0.5", + "chai": "^6.3.0", "es-module-lexer": "^2.3.2", "expect-type": "^1.4.0", - "magic-string": "^1.2.3", - "obug": "^2.1.4", + "magic-string": "^1.4.3", + "obug": "^3.0.0", "picomatch": "^4.0.7", - "std-env": "^4.2.0", - "tinybench": "6.1.4", - "tinyexec": "1.3.0", + "std-env": "^4.3.0", + "tinybench": "^6.2.2", + "tinyexec": "^1.3.1", "tinyglobby": "^0.2.17", - "why-is-node-running": "^2.3.0" + "why-is-node-running": "3.2.1" }, "bin": { "vitest": "vitest.mjs" @@ -9820,12 +9636,12 @@ "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "5.0.0", - "@vitest/browser-preview": "5.0.0", + "@vitest/browser-playwright": "5.0.5", + "@vitest/browser-preview": "5.0.5", "@vitest/browser-webdriverio": "^5.0.0-beta.5 || >=5.0.0", - "@vitest/coverage-istanbul": "5.0.0", - "@vitest/coverage-v8": "5.0.0", - "@vitest/ui": "5.0.0", + "@vitest/coverage-istanbul": "5.0.5", + "@vitest/coverage-v8": "5.0.5", + "@vitest/ui": "5.0.5", "happy-dom": "*", "jsdom": "*", "vite": "^6.4.0 || ^7.0.0 || ^8.0.0" @@ -9869,20 +9685,10 @@ } } }, - "node_modules/vitest/node_modules/tinyexec": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz", - "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, "node_modules/watchpack": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.2.tgz", - "integrity": "sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.6.1.tgz", + "integrity": "sha512-8mk/LnXpQAiM2xKZhTkxikwly5GhL2Z+DWiLTkMa/E1Nfv9zURhHgiFyWvM4BWqW+LjIgL2AIS7JntEUx6v3vQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9900,9 +9706,9 @@ "license": "MIT" }, "node_modules/webpack": { - "version": "5.110.3", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.110.3.tgz", - "integrity": "sha512-GuizBzRvo9YPpyoNMf3ag7AzxbaW85qrRSqTha345KyJbAFPt3/cMzBM0h+RWg7SK/7DdzRLINP3LvQ0hvr4hg==", + "version": "5.112.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.112.0.tgz", + "integrity": "sha512-NIBpsRuCll036haDDt/CfcTDfsWNR9Z782nMRMI9D377BsGcYzZDTNU5TyzhCJzPIcihAxMBaMAhq2WSaDrH8Q==", "dev": true, "license": "MIT", "dependencies": { @@ -9911,20 +9717,18 @@ "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.16.0", "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.24.4", + "enhanced-resolve": "^5.26.0", "es-module-lexer": "^2.1.0", "events": "^3.2.0", "graceful-fs": "^4.2.11", "mime-db": "^1.54.0", - "minimizer-webpack-plugin": "^5.7.0", - "neo-async": "^2.6.2", - "schema-utils": "^4.3.3", + "minimizer-webpack-plugin": "^5.13.0", + "schema-utils": "^4.5.0", "tapable": "^2.3.0", - "watchpack": "^2.5.2", - "webpack-sources": "^3.5.1" + "watchpack": "^2.6.1", + "webpack-sources": "^3.6.0" }, "bin": { "webpack": "bin/webpack.js" @@ -10121,9 +9925,9 @@ } }, "node_modules/webpack-sources": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.1.tgz", - "integrity": "sha512-jyuiGJdtvY434z5bUZrjz67v76/ePNvFZTp9Mdz29IlH4+GPsgyGjiv0fKI+M7BdkU6ADjulUcKAd3tUK3WlEw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.6.0.tgz", + "integrity": "sha512-EIMmPVvNI0CYXyRPp34F2Qk7W37/BZVZIofS6LAUnrNjCVahS+hO4mxwFJDjQjODTGZDtVzLYoN2+1dYkhk9qA==", "dev": true, "license": "MIT", "engines": { @@ -10157,20 +9961,16 @@ } }, "node_modules/why-is-node-running": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-3.2.1.tgz", + "integrity": "sha512-Tb2FUhB4vUsGQlfSquQLYkApkuPAFQXGFzxWKHHumVz2dK+X1RUm/HnID4+TfIGYJ1kTcwOaCk/buYCEJr6YjQ==", "dev": true, "license": "MIT", - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, "bin": { "why-is-node-running": "cli.js" }, "engines": { - "node": ">=8" + "node": ">=20.11" } }, "node_modules/wildcard": { @@ -10188,9 +9988,9 @@ "license": "ISC" }, "node_modules/ws": { - "version": "8.21.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", - "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.22.0.tgz", + "integrity": "sha512-Ydggc987+RO0AnWtZ/7Wq9FtNvcrL1b/RO0ud9mWjUPgDrsAAwQSF51sm2hm1XofbU/4jkpGEsLFsZZxU+1DOg==", "dev": true, "license": "MIT", "engines": { @@ -10227,62 +10027,70 @@ } }, "node_modules/yuku-ast": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/yuku-ast/-/yuku-ast-0.9.4.tgz", - "integrity": "sha512-AeeHDopMAy2mMafUMEIZxmQaCJOPEvBGDSSA23y5iKuzak3H2otfmgo4ObJubuzdHlJrv4eFY3KQ5XZOru5gpw==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/yuku-ast/-/yuku-ast-0.19.0.tgz", + "integrity": "sha512-PyCsiScaelhxBGzL8dyeJkLqvRZycoh78R31Vrt/WqYrm0hMFoKwIw/X7Dx5mBKLWAMlV9I9HEyBOHnj2gZVyw==", "dev": true, "license": "MIT", "dependencies": { - "@yuku-toolchain/types": "^0.9.4" + "@yuku-toolchain/types": "^0.19.0" + }, + "engines": { + "node": ">=14.18.0" } }, "node_modules/yuku-codegen": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/yuku-codegen/-/yuku-codegen-0.9.4.tgz", - "integrity": "sha512-pPr8xA8wBjrebER5VFeqS1XqATED1dQXU7JoAectAi1RBG4YFJz5yBirnmmmHZHldgnMKs/pMGkDtwGVQX+Efg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/yuku-codegen/-/yuku-codegen-0.19.0.tgz", + "integrity": "sha512-uymAKHjDuaP4BEpkXC/BSLz4DUEF5oArZ5AuD3888nb2miChjWSgpPdojEJxm3pjpXkgUaCRJQyNAbnMN33wHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@yuku-toolchain/types": "^0.19.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/yuku-core": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/yuku-core/-/yuku-core-0.19.0.tgz", + "integrity": "sha512-kYK9e1XdfirNhkipzW0wmMcSWcVF/CWnuugodfVYRCUwvoBefweL9HzB96OiKEhsx78V5WbUxbJqlizMX869Qg==", "dev": true, "license": "MIT", "dependencies": { - "@yuku-toolchain/types": "^0.9.4" + "@yuku-toolchain/types": "^0.19.0" + }, + "engines": { + "node": ">=14.18.0" }, "optionalDependencies": { - "@yuku-codegen/binding-android-arm64": "0.9.4", - "@yuku-codegen/binding-darwin-arm64": "0.9.4", - "@yuku-codegen/binding-darwin-x64": "0.9.4", - "@yuku-codegen/binding-freebsd-x64": "0.9.4", - "@yuku-codegen/binding-linux-arm-gnu": "0.9.4", - "@yuku-codegen/binding-linux-arm-musl": "0.9.4", - "@yuku-codegen/binding-linux-arm64-gnu": "0.9.4", - "@yuku-codegen/binding-linux-arm64-musl": "0.9.4", - "@yuku-codegen/binding-linux-x64-gnu": "0.9.4", - "@yuku-codegen/binding-linux-x64-musl": "0.9.4", - "@yuku-codegen/binding-win32-arm64": "0.9.4", - "@yuku-codegen/binding-win32-x64": "0.9.4" + "@yuku-core/binding-android-arm64": "0.19.0", + "@yuku-core/binding-darwin-arm64": "0.19.0", + "@yuku-core/binding-darwin-x64": "0.19.0", + "@yuku-core/binding-freebsd-x64": "0.19.0", + "@yuku-core/binding-linux-arm-gnu": "0.19.0", + "@yuku-core/binding-linux-arm-musl": "0.19.0", + "@yuku-core/binding-linux-arm64-gnu": "0.19.0", + "@yuku-core/binding-linux-arm64-musl": "0.19.0", + "@yuku-core/binding-linux-x64-gnu": "0.19.0", + "@yuku-core/binding-linux-x64-musl": "0.19.0", + "@yuku-core/binding-win32-arm64": "0.19.0", + "@yuku-core/binding-win32-x64": "0.19.0" } }, "node_modules/yuku-parser": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/yuku-parser/-/yuku-parser-0.9.4.tgz", - "integrity": "sha512-VWnoJzdB2g1JjsMEcB2MxSLoDbgISgOiNRsgiR0qrQKiUw2yyzEfYEYkNHSMNhdGkSo7gtmcN+2UOczzGDLAuw==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/yuku-parser/-/yuku-parser-0.19.0.tgz", + "integrity": "sha512-XrBh9ZiQK5mJVRxZBAvD6LwRyAYrK3MFtH3+onyuxFL5hFD44EC3QOmIC1FjTj6H2MMwq46/NAI+NZxLZPZgxg==", "dev": true, "license": "MIT", "dependencies": { - "@yuku-toolchain/types": "^0.9.4", - "yuku-ast": "^0.9.4" + "@yuku-toolchain/types": "^0.19.0", + "yuku-core": "0.19.0" }, - "optionalDependencies": { - "@yuku-parser/binding-android-arm64": "0.9.4", - "@yuku-parser/binding-darwin-arm64": "0.9.4", - "@yuku-parser/binding-darwin-x64": "0.9.4", - "@yuku-parser/binding-freebsd-x64": "0.9.4", - "@yuku-parser/binding-linux-arm-gnu": "0.9.4", - "@yuku-parser/binding-linux-arm-musl": "0.9.4", - "@yuku-parser/binding-linux-arm64-gnu": "0.9.4", - "@yuku-parser/binding-linux-arm64-musl": "0.9.4", - "@yuku-parser/binding-linux-x64-gnu": "0.9.4", - "@yuku-parser/binding-linux-x64-musl": "0.9.4", - "@yuku-parser/binding-win32-arm64": "0.9.4", - "@yuku-parser/binding-win32-x64": "0.9.4" + "engines": { + "node": ">=14.18.0" } } } diff --git a/package.json b/package.json index 8d0bfe4..cc2345b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@sqlite.org/sqlite-wasm", - "version": "3.53.4-build2", + "version": "3.54.1-build1", "description": "SQLite Wasm conveniently wrapped as an ES Module.", "type": "module", "repository": { @@ -75,17 +75,17 @@ "node": ">=22" }, "devDependencies": { - "@types/node": "^26.5.0", - "@vitest/browser": "^5.0.0", - "@vitest/browser-playwright": "^5.0.0", - "happy-dom": "20.14.0", - "lefthook": "2.1.12", - "oxfmt": "^0.67.0", - "playwright": "^1.63.0", - "publint": "^0.3.24", - "tsdown": "^0.23.0", + "@types/node": "^26.6.5", + "@vitest/browser": "^5.0.5", + "@vitest/browser-playwright": "^5.0.5", + "happy-dom": "21.0.3", + "lefthook": "2.2.2", + "oxfmt": "^0.73.0", + "playwright": "^1.64.1", + "publint": "^0.3.25", + "tsdown": "^0.23.1", "typescript": "7.0.2", - "vitest": "^5.0.0" + "vitest": "^5.0.5" }, "packageManager": "npm@12.0.1", "allowScripts": { diff --git a/src/bin/sqlite3-bundler-friendly.mjs b/src/bin/sqlite3-bundler-friendly.mjs index e026859..c55b1ed 100644 --- a/src/bin/sqlite3-bundler-friendly.mjs +++ b/src/bin/sqlite3-bundler-friendly.mjs @@ -27,9 +27,9 @@ /* @preserve ** This code was built from sqlite3 version... ** -** SQLITE_VERSION "3.53.4" -** SQLITE_VERSION_NUMBER 3053004 -** SQLITE_SOURCE_ID "2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc" +** SQLITE_VERSION "3.54.1" +** SQLITE_VERSION_NUMBER 3054001 +** SQLITE_SOURCE_ID "2026-10-16 14:45:20 555e07ef33f69a0957d24d8e555b702464a131d6f1607f4c3c1e4551e8e6ca76" ** ** Emscripten SDK: 5.0.5 */ @@ -92,7 +92,7 @@ var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIR /** This file was preprocessed using: - ./c-pp -o ./bld/pre-js.bundler.js -Dtarget:es6-module -Dtarget:es6-bundler-friendly -DModule.instantiateWasm api/pre-js.c-pp.js + ./c-pp -o ./bld/pre-js.bundler.js -Dtarget:es6-module -Dtarget:es6-bundler-friendly -Dsqlite3.wasm.base64=./jswasm/sqlite3.wasm -DModule.instantiateWasm api/pre-js.c-pp.js */ /* END FILE: api/pre-js.js. */ // end include: ./bld/pre-js.bundler.js @@ -4008,11 +4008,11 @@ var _sqlite3_status64, _sqlite3_db_status, _sqlite3_vfs_find, _sqlite3_initialize, - _sqlite3_malloc, - _sqlite3_free, _sqlite3_vfs_register, _sqlite3_vfs_unregister, + _sqlite3_malloc, _sqlite3_malloc64, + _sqlite3_free, _sqlite3_realloc, _sqlite3_realloc64, _sqlite3_value_text, @@ -4035,6 +4035,11 @@ var _sqlite3_status64, _sqlite3_column_type, _sqlite3_errmsg, _sqlite3_deserialize, + _sqlite3_backup_init, + _sqlite3_backup_step, + _sqlite3_backup_finish, + _sqlite3_backup_remaining, + _sqlite3_backup_pagecount, _sqlite3_clear_bindings, _sqlite3_value_blob, _sqlite3_value_bytes, @@ -4272,11 +4277,11 @@ function assignWasmExports(wasmExports) { _sqlite3_db_status = Module['_sqlite3_db_status'] = wasmExports['sqlite3_db_status']; _sqlite3_vfs_find = Module['_sqlite3_vfs_find'] = wasmExports['sqlite3_vfs_find']; _sqlite3_initialize = Module['_sqlite3_initialize'] = wasmExports['sqlite3_initialize']; - _sqlite3_malloc = Module['_sqlite3_malloc'] = wasmExports['sqlite3_malloc']; - _sqlite3_free = Module['_sqlite3_free'] = wasmExports['sqlite3_free']; _sqlite3_vfs_register = Module['_sqlite3_vfs_register'] = wasmExports['sqlite3_vfs_register']; _sqlite3_vfs_unregister = Module['_sqlite3_vfs_unregister'] = wasmExports['sqlite3_vfs_unregister']; + _sqlite3_malloc = Module['_sqlite3_malloc'] = wasmExports['sqlite3_malloc']; _sqlite3_malloc64 = Module['_sqlite3_malloc64'] = wasmExports['sqlite3_malloc64']; + _sqlite3_free = Module['_sqlite3_free'] = wasmExports['sqlite3_free']; _sqlite3_realloc = Module['_sqlite3_realloc'] = wasmExports['sqlite3_realloc']; _sqlite3_realloc64 = Module['_sqlite3_realloc64'] = wasmExports['sqlite3_realloc64']; _sqlite3_value_text = Module['_sqlite3_value_text'] = wasmExports['sqlite3_value_text']; @@ -4299,6 +4304,11 @@ function assignWasmExports(wasmExports) { _sqlite3_column_type = Module['_sqlite3_column_type'] = wasmExports['sqlite3_column_type']; _sqlite3_errmsg = Module['_sqlite3_errmsg'] = wasmExports['sqlite3_errmsg']; _sqlite3_deserialize = Module['_sqlite3_deserialize'] = wasmExports['sqlite3_deserialize']; + _sqlite3_backup_init = Module['_sqlite3_backup_init'] = wasmExports['sqlite3_backup_init']; + _sqlite3_backup_step = Module['_sqlite3_backup_step'] = wasmExports['sqlite3_backup_step']; + _sqlite3_backup_finish = Module['_sqlite3_backup_finish'] = wasmExports['sqlite3_backup_finish']; + _sqlite3_backup_remaining = Module['_sqlite3_backup_remaining'] = wasmExports['sqlite3_backup_remaining']; + _sqlite3_backup_pagecount = Module['_sqlite3_backup_pagecount'] = wasmExports['sqlite3_backup_pagecount']; _sqlite3_clear_bindings = Module['_sqlite3_clear_bindings'] = wasmExports['sqlite3_clear_bindings']; _sqlite3_value_blob = Module['_sqlite3_value_blob'] = wasmExports['sqlite3_value_blob']; _sqlite3_value_bytes = Module['_sqlite3_value_bytes'] = wasmExports['sqlite3_value_bytes']; @@ -4731,9 +4741,9 @@ Module.runSQLite3PostLoadInit = async function( /* @preserve ** This code was built from sqlite3 version... ** -** SQLITE_VERSION "3.53.4" -** SQLITE_VERSION_NUMBER 3053004 -** SQLITE_SOURCE_ID "2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc" +** SQLITE_VERSION "3.54.1" +** SQLITE_VERSION_NUMBER 3054001 +** SQLITE_SOURCE_ID "2026-10-16 14:45:20 555e07ef33f69a0957d24d8e555b702464a131d6f1607f4c3c1e4551e8e6ca76" ** ** Emscripten SDK: 5.0.5 */ @@ -5510,7 +5520,11 @@ globalThis.sqlite3ApiBootstrap = async function sqlite3ApiBootstrap( lead bytes of that buffer do not hold a SQLite3 database header, else it returns without side effects. - Added in 3.44. + Added in 3.44. As of 3.54 in SEE builds it performs only a + rudimentary length check and does not fail for invalid header + bytes, under the assumption that the input may be an encrypted + db. We cannot unambiguously distinguish an encrypted db from + garbage bytes. */ affirmDbHeader: function(bytes){ if(bytes instanceof ArrayBuffer) bytes = new Uint8Array(bytes); @@ -5530,7 +5544,8 @@ globalThis.sqlite3ApiBootstrap = async function sqlite3ApiBootstrap( database. It only examines the size and header, but further checks may be added in the future. - Added in 3.44. + Added in 3.44. See notes in affirmDbHeader() regarding SEE + builds. */ affirmIsDb: function(bytes){ if(bytes instanceof ArrayBuffer) bytes = new Uint8Array(bytes); @@ -6978,7 +6993,7 @@ globalThis.sqlite3ApiBootstrap.defaultConfig = Object.create(null); */ globalThis.sqlite3ApiBootstrap.sqlite3 = undefined; globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ - sqlite3.version = {"libVersion": "3.53.4", "libVersionNumber": 3053004, "sourceId": "2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc","downloadVersion": 3530400,"scm":{ "sha3-256": "bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc","branch": "branch-3.53","tags": "release version-3.53.4","datetime": "2026-07-24T19:02:57.525Z"}}; + sqlite3.version = {"libVersion": "3.54.1", "libVersionNumber": 3054001, "sourceId": "2026-10-16 14:45:20 555e07ef33f69a0957d24d8e555b702464a131d6f1607f4c3c1e4551e8e6ca76","downloadVersion": 3540100,"scm":{ "sha3-256": "555e07ef33f69a0957d24d8e555b702464a131d6f1607f4c3c1e4551e8e6ca76","branch": "branch-3.54","tags": "release version-3.54.1","datetime": "2026-10-16T14:45:20.546Z"}}; }); /** 2022-07-08 @@ -9550,7 +9565,7 @@ globalThis.WhWasmUtilInstaller ./c-pp -o js/jaccwabyt.js -@policy=error jaccwabyt/jaccwabyt.c-pp.js - by libcmpp 2.x 2fc4afc31f6505c27b9c34988973a2bd9b157d559247cdd26868ae75632c3a5e @ 2025-11-16 23:03:27.352 UTC + by libcmpp 2.0.x 4539e17f451054d2aeb6a5ffe3891af087fd8fa6cfae4e31d02e1fddfec69d46 @ 2026-09-30 09:12:44.230 UTC */ 'use strict'; globalThis.Jaccwabyt = @@ -9862,8 +9877,8 @@ function StructBinderFactory(config){ and unmaps obj from its native resources. */ const __freeStruct = function(ctor, obj, m){ const ii = getInstanceHandle(obj, false); - if( !ii ) return; - rmInstanceHandle(obj); + if( !ii || ii.isDisposing ) return; + ii.isDisposing = true; if( !m && !(m = ii.p) ){ console.warn("Cannot(?) happen: __freeStruct() found no instanceInfo"); return; @@ -9890,6 +9905,7 @@ function StructBinderFactory(config){ m,'threw. NOT propagating it.',e); } } + rmInstanceHandle(obj); delete obj.ondispose; if(ctor.debugFlags.__flags.dealloc){ log("debug.dealloc:",(ii.ownsPointer?"":"EXTERNAL"), @@ -10815,6 +10831,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ // Please keep these sorted by function name! ["sqlite3_aggregate_context","void*", "sqlite3_context*", "int"], /* sqlite3_auto_extension() has a hand-written binding. */ + ["sqlite3_backup_init", "sqlite3_backup*", "sqlite3*", "string", "sqlite3*", "string"], + ["sqlite3_backup_step", "int", "sqlite3_backup*", "int"], + ["sqlite3_backup_finish", "int", "sqlite3_backup*"], + ["sqlite3_backup_remaining", "int", "sqlite3_backup*"], + ["sqlite3_backup_pagecount", "int", "sqlite3_backup*"], /* sqlite3_bind_blob() and sqlite3_bind_text() have hand-written bindings to permit more flexible inputs. */ ["sqlite3_bind_double","int", "sqlite3_stmt*", "int", "f64"], @@ -11522,6 +11543,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ /*a class which no value can ever be an instance of*/ }; wasm.xWrap.argAdapter('sqlite3_filename', __xArgPtr) + ('sqlite3_backup*', __xArgPtr) ('sqlite3_context*', __xArgPtr) ('sqlite3_value*', __xArgPtr) ('void*', __xArgPtr) @@ -11573,6 +11595,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ */ const __xRcPtr = wasm.xWrap.resultAdapter('*'); wasm.xWrap.resultAdapter('sqlite3*', __xRcPtr) + ('sqlite3_backup*', __xRcPtr) ('sqlite3_context*', __xRcPtr) ('sqlite3_stmt*', __xRcPtr) ('sqlite3_value*', __xRcPtr) @@ -12726,8 +12749,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ */ const __doesNotOwnHandle = new Set(); /** - Map of DB instances to objects, each object being a map of Stmt - wasm pointers to Stmt objects. + Map of DB instances to objects, each object being a map of + sqlite3_stmt wasm pointers to Stmt objects. */ const __stmtMap = new WeakMap(); @@ -13209,7 +13232,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const stmt = db.prepare(sql); try { const rc = stmt.bind(bind).step() ? stmt.get(...getArgs) : undefined; - stmt.reset(/*for INSERT...RETURNING locking case*/); + stmt.reset(/*for INSERT...RETURNING locking case + https://sqlite.org/forum/forumpost/c411b3a9143d02dce */); return rc; }finally{ stmt.finalize(); @@ -13225,6 +13249,57 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ sql, bind, rowMode, returnValue: 'resultRows' }); + /** + Internal impl of DB.Stmt APIs which fetch a column. The caller is + required to have validated the ndx value before calling this (see + affirmColIndex()). The purpose of this impl is to speed up such + operations which loop, to avoid having to validate the index on + each iteration. The arguments are as documented for Stmt.get() + with the exception that ndx must be an in-range interger (that + function handles the other cases and proxies them to this one). + */ + const __stmtGetColumn = (stmt, ndx, asType)=>{ + switch(undefined===asType + ? capi.sqlite3_column_type(stmt.pointer, ndx) + : asType){ + case capi.SQLITE_NULL: return null; + case capi.SQLITE_INTEGER:{ + if(wasm.bigIntEnabled){ + const rc = capi.sqlite3_column_int64(stmt.pointer, ndx); + if(rc>=Number.MIN_SAFE_INTEGER && rc<=Number.MAX_SAFE_INTEGER){ + return Number(rc).valueOf(); + } + return rc; + }else{ + const rc = capi.sqlite3_column_double(stmt.pointer, ndx); + if(rc>Number.MAX_SAFE_INTEGER || rc{ - if(s && s.pointer){ + for(const s of Object.values(__stmtMap.get(this))){ + if(s?.pointer){ try{s.finalize()} - catch(e){/*ignore*/} + catch(ex){/*ignore*/} } - }); + } __ptrMap.delete(this); __stmtMap.delete(this); if( !__doesNotOwnHandle.delete(this) ){ capi.sqlite3_close_v2(pDb); } - if(this.onclose && (this.onclose.after instanceof Function)){ + if(this.onclose?.after instanceof Function){ try{this.onclose.after(this)} catch(e){/*ignore*/} } @@ -13884,8 +13959,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ selectValues: function(sql,bind,asType){ const stmt = this.prepare(sql), rc = []; try { + affirmColIndex(stmt, 0); stmt.bind(bind); - while(stmt.step()) rc.push(stmt.get(0,asType)); + while(stmt.step()) rc.push( + __stmtGetColumn(stmt, 0, asType) + ); stmt.reset(/*for INSERT...RETURNING locking case*/); }finally{ stmt.finalize(); @@ -14309,6 +14387,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ also called, otherwise any existing bindings, along with any memory allocated for them, are retained. + Clients must not use capi.sqlite3_reset() with this object + because this method does book-keeping specific to this class, + e.g. the pieces which ensure that the column-fetching methods + throw when called without a corresponding step(). + In versions 3.42.0 and earlier, this function did not throw if sqlite3_reset() returns non-0, but it was discovered that throwing (or significant extra client-side code) is necessary @@ -14325,6 +14408,32 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ checkSqlite3Rc(this.db, rc); return this; }, + + /** + Works like reset() except that it returns the underlying + C-level result code instead of throwing if that code represents + an error. + + Clients must not use capi.sqlite3_reset() for this purpose + because this method (like reset()) does book-keeping specific + to this class. + + Throws if an exec() is underway. + + The use case this addresses is when a step() fails due to, + e.g., a locking error: a following reset() will report that + locking error by throwing and that's sometimes inconvenient. + + Added in 3.54. + */ + resetNoThrow: function(alsoClearBinds){ + affirmNotLockedByExec(this,'reset()'); + if(alsoClearBinds) this.clearBindings(); + const rc = capi.sqlite3_reset(affirmStmtOpen(this).pointer); + __stmtMayGet.delete(this); + return rc; + }, + /** Binds one or more values to its bindable parameters. It accepts 1 or 2 arguments: @@ -14542,14 +14651,16 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ an exception is thrown. By default it will determine the data type of the result - automatically. If passed a second argument, it must be one - of the enumeration values for sqlite3 types, which are - defined as members of the sqlite3 module: SQLITE_INTEGER, - SQLITE_FLOAT, SQLITE_TEXT, SQLITE_BLOB. Any other value, - except for undefined, will trigger an exception. Passing - undefined is the same as not passing a value. It is legal - to, e.g., fetch an integer value as a string, in which case - sqlite3 will convert the value to a string. + automatically. If passed a second argument, it must be one of + the enumeration values for sqlite3 types, which are defined as + members of the sqlite3.capi namespace: SQLITE_INTEGER, + SQLITE_FLOAT, SQLITE_TEXT, SQLITE_BLOB. Any other value, except + for undefined, will trigger an exception. Passing undefined is + the same as not passing a value. It is legal to, e.g., fetch an + integer value as a string, in which case sqlite3 will convert + the value to a string. + + Blobs are returned as Uint8Array instances. If ndx is an array, this function behaves a differently: it assigns the indexes of the array, from 0 to the number of @@ -14561,7 +14672,27 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ the values of their corresponding result columns and returns that object. - Blobs are returned as Uint8Array instances. + Performance note: this class does not cache its column names + because a reprepare may change them and we have(?) no(?) way of + hooking into that to invalidate the cache. A side effect of + that is that this function, when ndx is an object, has to copy + those names from the WASM side on each call. When fetching many + objects, DB.exec() can do so more efficiently by caching those + names for the duration of the query. In large result sets the + runtime difference is human-perceivable. + + Behavior change notice: prior to 3.54, the asType argument was + ignored when ndx is an array or object, the justification being + that we're generally fetching rows of mixed data types. As of + 3.54, it still behaves that way when passed the undefined value + resp. is not passed a value, but will coerce each column to the + request type of it is not the undefined value. It is not + believed that this change adversely affects any existing + client-level code because this argument was ignored and + applications passing a non-undefined value were not necessarily + getting back what they had specified (or did so only because + all of the data was of that type, in which case the new + behavior is identical for those queries). Potential TODO: add type ID SQLITE_JSON, which fetches the result as a string and passes it (if it's not null) to @@ -14576,69 +14707,22 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ let i = 0; const n = this.columnCount; while(i=Number.MIN_SAFE_INTEGER && rc<=Number.MAX_SAFE_INTEGER){ - /* Coerce "normal" number ranges to normal number values, - and only return BigInt-type values for numbers out of this - range. */ - return Number(rc).valueOf(); - } - return rc; - }else{ - const rc = capi.sqlite3_column_double(this.pointer, ndx); - if(rc>Number.MAX_SAFE_INTEGER || rc cache.storagePool[store.jzClass] = @@ -16641,6 +16745,35 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ */ const pFileHandles = new Map(); + /** + Map of filename to lock objects with this structure: + + {.lockType: int, .nShared: int} + + Used by xLock(), xUnlock(), and xCheckReservedLock(). Modelled + after the "same-process, same-file, different-db-handle" locking + in os_unix.c. + */ + const mapPathToLocks = new Map(); + + /** + Main xUnlock() impl for kvvfs, also used by xClose(). Expects an + xOpen()-created file handle object and the second argument to + xUnlock(). It returns void. + */ + const unlockFile = function(fh, lockType){ + if(fh.lockType<=lockType) return; + const lk = mapPathToLocks.get(fh.jzClass); + if(fh.lockType>capi.SQLITE_LOCK_SHARED){ + lk.lockType = capi.SQLITE_LOCK_SHARED; + } + if(lockType===capi.SQLITE_LOCK_NONE && 0===--lk.nShared + /* Maintenance reminder: the && ordering is significant */){ + mapPathToLocks.delete(fh.jzClass); + } + fh.lockType = lockType; + }; + /** Original WASM functions for methods we partially override. */ @@ -16725,29 +16858,25 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ else if(1===nBuf){ wasm.poke(zBuf, 0); return nV; - } - if( nBuf+1 nV + 1 ){ + nBuf = nV + 1; } if( 0 ){ debug("xRcrdRead", nBuf, zClass, wasm.cstrToJs(zClass), wasm.cstrToJs(zKey), nV, jV, store); } - const zV = cache.memBuffer(0); - //if( !zV ) return -3 /*OOM*/; + const nCopy = nV0, }/*.vfs*/, @@ -16965,6 +17108,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ kvvfs?.log?.xClose && debug("xClose", pFile, h); if( h ){ pFileHandles.delete(pFile); + unlockFile(h, capi.SQLITE_LOCK_NONE); const s = h.store;//storageForZClass(h.jzClass); s.files = s.files.filter((v)=>v!==h.file); if( --s.refc<=0 && s.deleteAtRefc0 ){ @@ -17043,6 +17187,82 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ } }, + xLock: function(pFile, iLock){ + cache.popError(); + try{ + const h = pFileHandles.get(pFile); + if( capi.SQLITE_LOCK_NONE!==iLock ){ + /* Tells the impl to re-read its size. */ + originalMethods.ioDb.xLock(pFile, iLock); + } + /** + This impl is based off of the one in the opfs-sahpool VFS + impl which, in turn, is based off of the impl in + os_unix.c. + */ + if(h.lockType>=iLock) return 0; + let lk = mapPathToLocks.get(h.jzClass); + if(!lk){ + lk = Object.assign(Object.create(null),{ + nShared: 0, lockType: capi.SQLITE_LOCK_NONE + }); + mapPathToLocks.set(h.jzClass, lk); + } + if(h.lockType!==lk.lockType + && (lk.lockType>=capi.SQLITE_LOCK_PENDING + || iLock>capi.SQLITE_LOCK_SHARED)){ + return capi.SQLITE_BUSY; + } + if(iLock===capi.SQLITE_LOCK_SHARED){ + ++lk.nShared; + if(lk.lockType===capi.SQLITE_LOCK_NONE) lk.lockType = iLock; + }else if(iLock===capi.SQLITE_LOCK_EXCLUSIVE && lk.nShared>1){ + if(h.lockType===capi.SQLITE_LOCK_RESERVED){ + h.lockType = lk.lockType = capi.SQLITE_LOCK_PENDING; + } + return capi.SQLITE_BUSY; + }else{ + lk.lockType = iLock; + } + h.lockType = iLock; + return 0; + }catch(e){ + error("xLock", e); + return cache.setError(e); + } + }, + + xUnlock: function(pFile, iLock){ + cache.popError(); + try{ + if( capi.SQLITE_LOCK_NONE===iLock ){ + /* Tells the impl to re-read its size on the next op. */ + originalMethods.ioDb.xUnlock(pFile, iLock); + } + const h = pFileHandles.get(pFile); + unlockFile(h, iLock); + return 0; + }catch(e){ + error("xUnlock", e); + return cache.setError(e); + } + }, + + xCheckReservedLock: function(pFile, pOut){ + cache.popError(); + try{ + const h = pFileHandles.get(pFile); + const lk = mapPathToLocks.get(h.jzClass); + wasm.poke32(pOut, + (!!lk && lk.lockType>capi.SQLITE_LOCK_SHARED) + ? 1 : 0) + return 0; + }catch(e){ + error("xCheckReservedLock", e); + return cache.setError(e); + } + }, + }/*.ioDb*/, @@ -17051,6 +17271,9 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ are copied as-is from the ioDb objects. Others are specific to journal files. */ xClose: true, + xLock: true, + xUnlock: true, + xCheckReservedLock: true, }/*.ioJrnl*/ }/*methodOverrides*/; @@ -18280,11 +18503,15 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ called this way, the resolved value of the returned Promise is the number of bytes written to the target file. - It very specifically requires the input to be an SQLite3 - database and throws if that's not the case. It does so in - order to prevent this function from taking on a larger scope - than it is specifically intended to. i.e. we do not want it to - become a convenience for importing arbitrary files into OPFS. + It very specifically requires the input to be an SQLite3 database + and throws if that's not the case. It does so in order to + prevent this function from taking on a larger scope than it is + specifically intended to. i.e. we do not want it to become a + convenience for importing arbitrary files into OPFS. Caveat: as + of 3.54 in SEE builds, the "is this a db?" check is necessarily + lax to account for SEE-encrypted databases not having a legible + header. In such builds, only the db size is relevant for the + check. This routine rewrites the database header bytes in the output file (not the input array) to force disabling of WAL mode. @@ -18766,6 +18993,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ so would need to pass it to the async proxy. That would make it inordinately expensive considering that it's just a hint. + + See: forum:a2f573b00cda1372 */ wasm.poke(pOut, 0, 'i32'); return 0; @@ -19171,7 +19400,6 @@ const initS11n = function(){ const options = opfsUtil.options; const W = opfsVfs.worker = (()=>{ - /* _Sigh_... */ /* Discussion explaining this formulation: https://github.com/sqlite/sqlite-wasm/pull/159 */ const url = new URL('sqlite3-opfs-async-proxy.js', import.meta.url); @@ -19210,7 +19438,7 @@ const initS11n = function(){ //| capi.SQLITE_OPEN_DELETEONCLOSE | capi.SQLITE_OPEN_MAIN_DB; const pOut = wasm.scopedAlloc(8); - const dbFile = "/sanity/check/file"+randomFilename(8); + const dbFile = "/sanity/check/file"+opfsUtil.randomFilename(8); const zDbFile = wasm.scopedAllocCString(dbFile); let rc; state.s11n.serialize("This is รค string."); @@ -19299,7 +19527,7 @@ const initS11n = function(){ state.sabFileBufView = new Uint8Array(state.sabIO, 0, state.fileBufferSize); state.sabS11nView = new Uint8Array(state.sabIO, state.sabS11nOffset, state.sabS11nSize); opfsVfs.initS11n(); - delete opfsVfs.initS11n; + opfsVfs.initS11n = null; if(options.sanityChecks){ warn("Running sanity checks because of opfs-sanity-check URL arg..."); sanityCheck(); @@ -19565,6 +19793,9 @@ globalThis.sqlite3ApiBootstrap.initializersAsync.push(async (sqlite3)=>{ - Also because of that, it does not require the SharedArrayBuffer, so can function without the COOP/COEP HTTP response headers. + - Also because of that, this one is much faster and the performance + gap increases as the job sizes increase. + - It can hypothetically support Safari 16.4+, whereas the "opfs" VFS requires v17 due to a subworker/storage bug in 16.x which makes it incompatible with that VFS. @@ -19669,7 +19900,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ /* Logging verbosity 3+ == everything, 2 == warnings+errors, 1 == errors only. */ verbosity: 2, - forceReinitIfPreviouslyFailed: false + forceReinitIfPreviouslyFailed: false, + preserveOnInitFailure: false }); /** Logging routines, from most to least serious. */ @@ -19706,7 +19938,17 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const pool = getPoolForPFile(pFile); pool.log('xCheckReservedLock'); pool.storeErr(); - wasm.poke32(pOut, 1); + const file = pool.getOFileForS3File(pFile); + wasm.poke32( + pOut, + pool.hasReservedLock(file.path) ? 1 : 0 + /* As forum:b2fbb61642 elaborates on why we cannot simply + check file.lockType>=capi.SQLITE_LOCK_RESERVED + here. Summary: xOpen() has long allowed multiple handles to + the same filename and we need to check if any of them have + a lock to avoid a specific corruption case which that forum + thread demonstrates. */ + ); return 0; }, xClose: function(pFile){ @@ -19716,6 +19958,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ if(file) { try{ pool.log(`xClose ${file.path}`); + pool.unlockFile(file, capi.SQLITE_LOCK_NONE); pool.mapS3FileToOFile(pFile, false); file.sah.flush(); if(file.flags & capi.SQLITE_OPEN_DELETEONCLOSE){ @@ -19747,8 +19990,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ pool.log(`xLock ${lockType}`); pool.storeErr(); const file = pool.getOFileForS3File(pFile); - file.lockType = lockType; - return 0; + return pool.lockFile(file, lockType); }, xRead: function(pFile,pDest,n,offset64){ const pool = getPoolForPFile(pFile); @@ -19802,7 +20044,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const pool = getPoolForPFile(pFile); pool.log('xUnlock'); const file = pool.getOFileForS3File(pFile); - file.lockType = lockType; + pool.unlockFile(file, lockType); return 0; }, xWrite: function(pFile,pSrc,n,offset64){ @@ -19903,6 +20145,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ ? pool.getPath(zName) : getRandomName(); let sah = pool.getSAHForPath(path); + if(sah && (flags & capi.SQLITE_OPEN_CREATE) + && (flags & capi.SQLITE_OPEN_EXCLUSIVE)){ + toss('file already exists:', path); + } if(!sah && (flags & capi.SQLITE_OPEN_CREATE)) { // File not found so try to create it. if(pool.getFileCount() < pool.getCapacity()) { @@ -19969,7 +20215,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ /* Inherit certain VFS members from the default VFS, if available. */ opfsVfs.$xRandomness = dVfs.$xRandomness; - opfsVfs.$xSleep = dVfs.$xSleep; dVfs.dispose(); } if(!opfsVfs.$xRandomness && !vfsMethods.xRandomness){ @@ -19982,9 +20227,14 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ return i; }; } - if(!opfsVfs.$xSleep && !vfsMethods.xSleep){ - vfsMethods.xSleep = (pVfs,ms)=>0; - } + /** + This VFS's xSleep() must be a no-op. In this environment, + only db handles within the same thread can ever come into + contention, and that contention cannot be resolved if + one of the handles sleeps in that same thread. + See also: forum:3f0794c5d8 + */ + vfsMethods.xSleep = (pVfs,ms)=>0; sqlite3.vfs.installVfs({ vfs: {struct: opfsVfs, methods: vfsMethods} }); @@ -19992,8 +20242,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ }; /** - Class for managing OPFS-related state for the - OPFS SharedAccessHandle Pool sqlite3_vfs. + Class for managing OPFS-related state for the OPFS + SharedAccessHandle Pool sqlite3_vfs. This class is + internal-use-only, never exposed to the client. OpfsSAHPoolUtil + is the public-facing part. */ class OpfsSAHPool { /* OPFS dir in which VFS metadata is stored. */ @@ -20015,7 +20267,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ /* Set of currently-unused SAHs. */ #availableSAH = new Set(); /* Maps (sqlite3_file*) to xOpen's file objects. */ - #mapS3FileToOFile_ = new Map(); + #mapS3FileToOFile = new Map(); + /* Maps client-side file names to the lock state of the files + opened via this pool: {nShared, lockType}, modelled after + os_unix.c:unixInodeInfo. */ + #mapPathToLock = new Map(); /* Maps SAH to an abstract File Object which contains various metadata about that handle. */ @@ -20031,6 +20287,9 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ // Logging verbosity. See optionDefaults.verbosity. #verbosity; + /** + Options are documented in installOpfsSAHPoolVfs(). + */ constructor(options = Object.create(null)){ this.#verbosity = options.verbosity ?? optionDefaults.verbosity; this.vfsName = options.name || optionDefaults.name; @@ -20057,6 +20316,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ warn(...args){this.#logImpl(1, ...args)}; error(...args){this.#logImpl(0, ...args)}; + /* Design note: at the time this method was added, the developer + was unaware that getter syntax was an option: get vfs(){...} */ getVfs(){return this.#cVfs} /* Current pool capacity. */ @@ -20091,22 +20352,32 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ } /** - Reduce capacity by n, but can only reduce up to the limit - of currently-available SAHs. Returns a Promise which resolves - to the number of slots really removed. + Reduce capacity by n, but can only reduce up to the limit of + currently-available SAHs. Returns a Promise which resolves to + the number of slots really removed. Throws if removal of an + OPFS filesystem entry fails for any reason, in which case the + VFS itself is left in a well-defined state, possibly partially + reduced in capacity compared to before this call, but the file + which was unable to be removed is in an undefined state. It may + be orphaned and/or later recycled. + + As of 3.54, throws if n is an invalid value. Prior to that + an invalid value could cause it to remove all entries. */ async reduceCapacity(n){ + if(!Number.isSafeInteger(n) || n < 0){ + toss('Invalid capacity reduction:', n); + } let nRm = 0; for(const ah of Array.from(this.#availableSAH)){ if(nRm === n || this.getFileCount() === this.getCapacity()){ break; } const name = this.#mapSAHToName.get(ah); - //this.#unmapFileObject(ah); ah.close(); - await this.#dhOpaque.removeEntry(name); this.#mapSAHToName.delete(ah); this.#availableSAH.delete(ah); + await this.#dhOpaque.removeEntry(name); ++nRm; } return nRm; @@ -20122,6 +20393,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ this.#mapSAHToName.clear(); this.#mapFilenameToSAH.clear(); this.#availableSAH.clear(); + this.#mapS3FileToOFile.clear(); + this.#mapPathToLock.clear(); } /** @@ -20131,8 +20404,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ throws, this.$error will contain the corresponding Error object. - If it throws, it releases any SAHs which it may have - acquired before the exception was thrown, leaving the VFS in a + If it throws, it waits for every pending acquisition to settle, + then releases all SAHs it acquired, leaving the VFS in a well-defined but unusable state. If clearFiles is true, the client-stored state of each file is @@ -20146,27 +20419,31 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ files.push([name,h]); } } - return Promise.all(files.map(async([name,h])=>{ - try{ - const ah = await h.createSyncAccessHandle() - this.#mapSAHToName.set(ah, name); - if(clearFiles){ - ah.truncate(HEADER_OFFSET_DATA); - this.setAssociatedPath(ah, '', 0); + const results = await Promise.allSettled(files.map(async([name,h])=>{ + const ah = await h.createSyncAccessHandle() + this.#mapSAHToName.set(ah, name); + if(clearFiles){ + ah.truncate(HEADER_OFFSET_DATA); + this.setAssociatedPath(ah, '', 0); + }else{ + const path = this.getAssociatedPath(ah); + if(path){ + this.#mapFilenameToSAH.set(path, ah); }else{ - const path = this.getAssociatedPath(ah); - if(path){ - this.#mapFilenameToSAH.set(path, ah); - }else{ - this.#availableSAH.add(ah); - } + this.#availableSAH.add(ah); } - }catch(e){ - this.storeErr(e); - this.releaseAccessHandles(); - throw e; } })); + const failure = results.find((r)=>'rejected'===r.status) + /* If any failures are found then clean up and re-throw the + first one. We "could" record them all but we can only throw + one of them (or an exception wrapping all of them, which + seems unnecessary). */; + if( failure ){ + this.storeErr(failure.reason); + this.releaseAccessHandles(); + throw failure.reason; + } } /** @@ -20219,8 +20496,12 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ into the given SAH. If path is an empty string then the file is disassociated from the pool but its previous name is preserved in the metadata. + + If nameToRemove is truthy then it must be the "old" name when path + is falsy. This function removes the mapping of that name to an + SAH. */ - setAssociatedPath(sah, path, flags){ + setAssociatedPath(sah, path, flags, nameToRemove){ const enc = textEncoder.encodeInto(path, this.#apBody); if(HEADER_MAX_PATH_SIZE <= enc.written + 1/*NUL byte*/){ toss("Path too long:",path); @@ -20237,6 +20518,17 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const digest = this.computeDigest(this.#apBody, flags); //console.warn("setAssociatedPath(",path,") digest",digest); sah.write(this.#apBody, {at: 0}); + if(nameToRemove){ + /* The placement of this is very specific: between the above + write and the digest. If the above write fails, + nameToRemove remains in the mapping pool. If it succeeds, + nameToRemove is no longer available and needs to be removed + from the SAH mapping. If the write() _below_ fails, that + leaves us with a consistent world view. + + Discussion: bugs:432f260aa787a53 */ + this.#mapFilenameToSAH.delete(nameToRemove); + } sah.write(digest, {at: HEADER_OFFSET_DIGEST}); sah.flush(); @@ -20326,9 +20618,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ deletePath(path) { const sah = this.#mapFilenameToSAH.get(path); if(sah) { - // Un-associate the name from the SAH. - this.#mapFilenameToSAH.delete(path); - this.setAssociatedPath(sah, '', 0); + this.setAssociatedPath(sah, '', 0, path); } return !!sah; } @@ -20373,7 +20663,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ xOpen file object. */ getOFileForS3File(pFile){ - return this.#mapS3FileToOFile_.get(pFile); + return this.#mapS3FileToOFile.get(pFile); } /** Maps or unmaps (if file is falsy) the given (sqlite3_file*) @@ -20381,10 +20671,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ */ mapS3FileToOFile(pFile,file){ if(file){ - this.#mapS3FileToOFile_.set(pFile, file); + this.#mapS3FileToOFile.set(pFile, file); setPoolForPFile(pFile, this); }else{ - this.#mapS3FileToOFile_.delete(pFile); + this.#mapS3FileToOFile.delete(pFile); setPoolForPFile(pFile, false); } } @@ -20442,7 +20732,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ return true; } - /** "Pauses" this VFS by unregistering it from SQLite and relinquishing all open SAHs, leaving the associated files @@ -20464,7 +20753,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ @see unpauseVfs() */ pauseVfs(){ - if(this.#mapS3FileToOFile_.size>0){ + if(this.#mapS3FileToOFile.size>0){ sqlite3.SQLite3Error.toss( capi.SQLITE_MISUSE, "Cannot pause VFS", this.vfsName,"because it has opened files." @@ -20535,7 +20824,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ util.affirmDbHeader(chunk); checkedHeader = true; } - sah.write(chunk, {at: HEADER_OFFSET_DATA + nWrote}); + const n = sah.write(chunk, {at: HEADER_OFFSET_DATA + nWrote}); + if( n!==chunk.byteLength ){ + toss("Expected to write "+chunk.byteLength+ + "bytes but wrote"+n+"."); + } nWrote += chunk.byteLength; } if( nWrote < 512 || 0!==nWrote % 512 ){ @@ -20543,7 +20836,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ } if( !checkedHeader ){ const header = new Uint8Array(20); - sah.read( header, {at: 0} ); + sah.read( header, {at: HEADER_OFFSET_DATA} ); util.affirmDbHeader( header ); } sah.write(new Uint8Array([1,1]), { @@ -20561,24 +20854,19 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ importDb(name, bytes){ if( bytes instanceof ArrayBuffer ) bytes = new Uint8Array(bytes); else if( bytes instanceof Function ) return this.importDbChunked(name, bytes); + util.affirmIsDb(bytes); const sah = this.#mapFilenameToSAH.get(name) || this.nextAvailableSAH() || toss("No available handles to import to."); const n = bytes.byteLength; - if(n<512 || n%512!=0){ - toss("Byte array size is invalid for an SQLite db."); - } - const header = "SQLite format 3"; - for(let i = 0; i < header.length; ++i){ - if( header.charCodeAt(i) !== bytes[i] ){ - toss("Input does not contain an SQLite database header."); - } - } const nWrote = sah.write(bytes, {at: HEADER_OFFSET_DATA}); if(nWrote != n){ this.setAssociatedPath(sah, '', 0); toss("Expected to write "+n+" bytes but wrote "+nWrote+"."); }else{ + sah.truncate(HEADER_OFFSET_DATA + n + /* Ensure no trailing junk when overwriting an + existing file with a shorter one. */); sah.write(new Uint8Array([1,1]), {at: HEADER_OFFSET_DATA+18} /* force db out of WAL mode */); this.setAssociatedPath(sah, name, capi.SQLITE_OPEN_MAIN_DB); @@ -20586,8 +20874,72 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ return nWrote; } - }/*class OpfsSAHPool*/; + /** + Returns true if any (sqlite3_file*) currently opened by this + pool using the given client-provided file name (as distinct from + its opaque name) holds a RESERVED or greater lock, else false. + */ + hasReservedLock(filename){ + const lk = this.#mapPathToLock.get(filename); + return !!lk && lk.lockType>capi.SQLITE_LOCK_SHARED; + } + + /** + Implements xLock() for the given xOpen-generated file object. + This pool holds its SAHs exclusively, so its xOpen() represent + the only connections to a given file. The locks are held + separately from their file object in the same thread the same + way in which os_unix.c:unixLock() distinguishes multiple + connections of a single process which share an inode: a lock + which conflicts with another connection's lock fails with + SQLITE_BUSY, and a failed attempt to get from RESERVED to + EXCLUSIVE leaves a PENDING lock, which admits no new SHARED + locks. + */ + lockFile(file, lockType){ + if(file.lockType>=lockType) return 0; + let lk = this.#mapPathToLock.get(file.path); + if(!lk){ + lk = Object.assign(Object.create(null),{ + nShared: 0, lockType: capi.SQLITE_LOCK_NONE + }); + this.#mapPathToLock.set(file.path, lk); + } + if(file.lockType!==lk.lockType + && (lk.lockType>=capi.SQLITE_LOCK_PENDING + || lockType>capi.SQLITE_LOCK_SHARED)){ + return capi.SQLITE_BUSY; + } + if(lockType===capi.SQLITE_LOCK_SHARED){ + ++lk.nShared; + if(lk.lockType===capi.SQLITE_LOCK_NONE) lk.lockType = lockType; + }else if(lockType===capi.SQLITE_LOCK_EXCLUSIVE && lk.nShared>1){ + if(file.lockType===capi.SQLITE_LOCK_RESERVED){ + file.lockType = lk.lockType = capi.SQLITE_LOCK_PENDING; + } + return capi.SQLITE_BUSY; + }else{ + lk.lockType = lockType; + } + file.lockType = lockType; + return 0; + } + + /** Implements xUnlock() for the given xOpen file object. */ + unlockFile(file, lockType){ + if(file.lockType<=lockType) return; + const lk = this.#mapPathToLock.get(file.path); + if(file.lockType>capi.SQLITE_LOCK_SHARED){ + lk.lockType = capi.SQLITE_LOCK_SHARED; + } + if(lockType===capi.SQLITE_LOCK_NONE && 0===--lk.nShared + /* Maintenance reminder: the && ordering is significant */){ + this.#mapPathToLock.delete(file.path); + } + file.lockType = lockType; + } + }/*class OpfsSAHPool*/; /** A OpfsSAHPoolUtil instance is exposed to clients in order to @@ -20741,9 +21093,19 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ option is truthy _and_ the previous attempt to initialize this VFS with the same `name` failed, the VFS will attempt to initialize a second time instead of returning the cached - failure. See discussion at: + failure. See discussion at + - `preserveOnInitFailure`: (default=`false`) If truthy, + initialization failure unregisters and disposes of the VFS and + releases acquired handles without also deleting its storage. This + does not undo changes already made during initialization, + including `clearOnInit`. Otherwise, initialization failure + invokes this.removeVfs(), which attempts to delete the + pool. Retrying a cached initialization failure requires + `forceReinitIfPreviouslyFailed`. See discussion at + . + Peculiarities of this VFS vis a vis other SQLite VFSes: @@ -20780,16 +21142,17 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ - byteArray exportFile(name) - Synchronously reads the contents of the given file into a Uint8Array - and returns it. This will throw if the given name is not currently - in active use or on I/O error. Note that the given name is _not_ - visible directly in OPFS (or, if it is, it's not from this VFS). + Synchronously reads the contents of the given file into a + Uint8Array and returns it. This will throw if the given name is + not currently in active use or on I/O error. Because of how this + VFS maps names to storage, the given name is _not_ visible + directly in OPFS (or, if it is, it's not from this VFS). - number getCapacity() - Returns the number of files currently contained - in the SAH pool. The default capacity is only large enough for one - or two databases and their associated temp files. + Returns the number of files currently contained in the SAH + pool. The default capacity is only large enough for one or two + databases and their associated temp files. - number getFileCount() @@ -20806,11 +21169,14 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ Imports the contents of an SQLite database, provided as a byte array or ArrayBuffer, under the given name, overwriting any existing content. Throws if the pool has no available file slots, - on I/O error, or if the input does not appear to be a - database. In the latter case, only a cursory examination is made. + on I/O error, or if the input does not appear to be a database. + In the latter case, only a cursory examination is made to + determine whether the input is a db (and only in non-SEE builds, + as we cannot distinguish encrypted DBs from garbage input). + Results are undefined if the given db name refers to an opened - db. Note that this routine is _only_ for importing database - files, not arbitrary files, the reason being that this VFS will + db. This routine is _only_ for importing database files, not + arbitrary files, the reason being that this VFS will automatically clean up any non-database files so importing them is pointless. @@ -20825,7 +21191,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ called this way is the size of the resulting database. On success this routine rewrites the database header bytes in the - output file (not the input array) to force disabling of WAL mode. + output file (not the input array) to force disabling of WAL mode, + (A) for historical reasons and (B) getting WAL to work in this + build requires doing a (pragma locking_mode=exclusive) on the db + before using it. On a write error, the handle is removed from the pool and made available for re-use. @@ -20941,6 +21310,24 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ return (initPromises[vfsName] = Promise.reject(new Error("Missing required OPFS APIs."))); } + /** + An interal detail of OpfsSAHPool, called only by initPromises(). + + Unregisters and disposes of OpfsSAHPool thePool, releasing all + of its SAHs without deleting its files. Used when + initialization fails and the preserveOnInitFailure option is + set. This is a no-op if thePool.getVfs().pointer is falsy. Returns the + undefined value. + */ + const unregisterVfs = (thePool)=>{ + const cVfs = thePool.getVfs(); + if( cVfs?.pointer ){ + capi.sqlite3_vfs_unregister(cVfs.pointer); + cVfs.dispose(); + thePool.releaseAccessHandles(); + } + }; + /** Maintenance reminder: the order of ASYNC ops in this function is significant. We need to have them all chained at the very @@ -20978,7 +21365,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ thePool.log("VFS initialized."); return poolUtil; }).catch(async (e)=>{ - await thePool.removeVfs().catch(()=>{}); + if( options.preserveOnInitFailure ){ + unregisterVfs(thePool); + }else{ + await thePool.removeVfs().catch(()=>{}); + } throw e; }); }).catch((err)=>{ diff --git a/src/bin/sqlite3-node.mjs b/src/bin/sqlite3-node.mjs index fe47aaa..068e049 100644 --- a/src/bin/sqlite3-node.mjs +++ b/src/bin/sqlite3-node.mjs @@ -27,9 +27,9 @@ /* @preserve ** This code was built from sqlite3 version... ** -** SQLITE_VERSION "3.53.4" -** SQLITE_VERSION_NUMBER 3053004 -** SQLITE_SOURCE_ID "2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc" +** SQLITE_VERSION "3.54.1" +** SQLITE_VERSION_NUMBER 3054001 +** SQLITE_SOURCE_ID "2026-10-16 14:45:20 555e07ef33f69a0957d24d8e555b702464a131d6f1607f4c3c1e4551e8e6ca76" ** ** Emscripten SDK: 5.0.5 */ @@ -98,7 +98,7 @@ if (ENVIRONMENT_IS_NODE) { /** This file was preprocessed using: - ./c-pp -o ./bld/pre-js.node.js -Dtarget:node -Dtarget:es6-module -Dtarget:es6-bundler-friendly -Dunsupported-build -DModule.instantiateWasm api/pre-js.c-pp.js + ./c-pp -o ./bld/pre-js.node.js -Dtarget:node -Dtarget:es6-module -Dtarget:es6-bundler-friendly -Dunsupported-build -Dsqlite3.wasm.base64=./jswasm/sqlite3.wasm -DModule.instantiateWasm api/pre-js.c-pp.js */ /** UNSUPPORTED BUILD: @@ -4067,11 +4067,11 @@ var _sqlite3_status64, _sqlite3_db_status, _sqlite3_vfs_find, _sqlite3_initialize, - _sqlite3_malloc, - _sqlite3_free, _sqlite3_vfs_register, _sqlite3_vfs_unregister, + _sqlite3_malloc, _sqlite3_malloc64, + _sqlite3_free, _sqlite3_realloc, _sqlite3_realloc64, _sqlite3_value_text, @@ -4094,6 +4094,11 @@ var _sqlite3_status64, _sqlite3_column_type, _sqlite3_errmsg, _sqlite3_deserialize, + _sqlite3_backup_init, + _sqlite3_backup_step, + _sqlite3_backup_finish, + _sqlite3_backup_remaining, + _sqlite3_backup_pagecount, _sqlite3_clear_bindings, _sqlite3_value_blob, _sqlite3_value_bytes, @@ -4331,11 +4336,11 @@ function assignWasmExports(wasmExports) { _sqlite3_db_status = Module['_sqlite3_db_status'] = wasmExports['sqlite3_db_status']; _sqlite3_vfs_find = Module['_sqlite3_vfs_find'] = wasmExports['sqlite3_vfs_find']; _sqlite3_initialize = Module['_sqlite3_initialize'] = wasmExports['sqlite3_initialize']; - _sqlite3_malloc = Module['_sqlite3_malloc'] = wasmExports['sqlite3_malloc']; - _sqlite3_free = Module['_sqlite3_free'] = wasmExports['sqlite3_free']; _sqlite3_vfs_register = Module['_sqlite3_vfs_register'] = wasmExports['sqlite3_vfs_register']; _sqlite3_vfs_unregister = Module['_sqlite3_vfs_unregister'] = wasmExports['sqlite3_vfs_unregister']; + _sqlite3_malloc = Module['_sqlite3_malloc'] = wasmExports['sqlite3_malloc']; _sqlite3_malloc64 = Module['_sqlite3_malloc64'] = wasmExports['sqlite3_malloc64']; + _sqlite3_free = Module['_sqlite3_free'] = wasmExports['sqlite3_free']; _sqlite3_realloc = Module['_sqlite3_realloc'] = wasmExports['sqlite3_realloc']; _sqlite3_realloc64 = Module['_sqlite3_realloc64'] = wasmExports['sqlite3_realloc64']; _sqlite3_value_text = Module['_sqlite3_value_text'] = wasmExports['sqlite3_value_text']; @@ -4358,6 +4363,11 @@ function assignWasmExports(wasmExports) { _sqlite3_column_type = Module['_sqlite3_column_type'] = wasmExports['sqlite3_column_type']; _sqlite3_errmsg = Module['_sqlite3_errmsg'] = wasmExports['sqlite3_errmsg']; _sqlite3_deserialize = Module['_sqlite3_deserialize'] = wasmExports['sqlite3_deserialize']; + _sqlite3_backup_init = Module['_sqlite3_backup_init'] = wasmExports['sqlite3_backup_init']; + _sqlite3_backup_step = Module['_sqlite3_backup_step'] = wasmExports['sqlite3_backup_step']; + _sqlite3_backup_finish = Module['_sqlite3_backup_finish'] = wasmExports['sqlite3_backup_finish']; + _sqlite3_backup_remaining = Module['_sqlite3_backup_remaining'] = wasmExports['sqlite3_backup_remaining']; + _sqlite3_backup_pagecount = Module['_sqlite3_backup_pagecount'] = wasmExports['sqlite3_backup_pagecount']; _sqlite3_clear_bindings = Module['_sqlite3_clear_bindings'] = wasmExports['sqlite3_clear_bindings']; _sqlite3_value_blob = Module['_sqlite3_value_blob'] = wasmExports['sqlite3_value_blob']; _sqlite3_value_bytes = Module['_sqlite3_value_bytes'] = wasmExports['sqlite3_value_bytes']; @@ -4790,9 +4800,9 @@ Module.runSQLite3PostLoadInit = async function( /* @preserve ** This code was built from sqlite3 version... ** -** SQLITE_VERSION "3.53.4" -** SQLITE_VERSION_NUMBER 3053004 -** SQLITE_SOURCE_ID "2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc" +** SQLITE_VERSION "3.54.1" +** SQLITE_VERSION_NUMBER 3054001 +** SQLITE_SOURCE_ID "2026-10-16 14:45:20 555e07ef33f69a0957d24d8e555b702464a131d6f1607f4c3c1e4551e8e6ca76" ** ** Emscripten SDK: 5.0.5 */ @@ -5569,7 +5579,11 @@ globalThis.sqlite3ApiBootstrap = async function sqlite3ApiBootstrap( lead bytes of that buffer do not hold a SQLite3 database header, else it returns without side effects. - Added in 3.44. + Added in 3.44. As of 3.54 in SEE builds it performs only a + rudimentary length check and does not fail for invalid header + bytes, under the assumption that the input may be an encrypted + db. We cannot unambiguously distinguish an encrypted db from + garbage bytes. */ affirmDbHeader: function(bytes){ if(bytes instanceof ArrayBuffer) bytes = new Uint8Array(bytes); @@ -5589,7 +5603,8 @@ globalThis.sqlite3ApiBootstrap = async function sqlite3ApiBootstrap( database. It only examines the size and header, but further checks may be added in the future. - Added in 3.44. + Added in 3.44. See notes in affirmDbHeader() regarding SEE + builds. */ affirmIsDb: function(bytes){ if(bytes instanceof ArrayBuffer) bytes = new Uint8Array(bytes); @@ -7037,7 +7052,7 @@ globalThis.sqlite3ApiBootstrap.defaultConfig = Object.create(null); */ globalThis.sqlite3ApiBootstrap.sqlite3 = undefined; globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ - sqlite3.version = {"libVersion": "3.53.4", "libVersionNumber": 3053004, "sourceId": "2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc","downloadVersion": 3530400,"scm":{ "sha3-256": "bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc","branch": "branch-3.53","tags": "release version-3.53.4","datetime": "2026-07-24T19:02:57.525Z"}}; + sqlite3.version = {"libVersion": "3.54.1", "libVersionNumber": 3054001, "sourceId": "2026-10-16 14:45:20 555e07ef33f69a0957d24d8e555b702464a131d6f1607f4c3c1e4551e8e6ca76","downloadVersion": 3540100,"scm":{ "sha3-256": "555e07ef33f69a0957d24d8e555b702464a131d6f1607f4c3c1e4551e8e6ca76","branch": "branch-3.54","tags": "release version-3.54.1","datetime": "2026-10-16T14:45:20.546Z"}}; }); /** 2022-07-08 @@ -9609,7 +9624,7 @@ globalThis.WhWasmUtilInstaller ./c-pp -o js/jaccwabyt.js -@policy=error jaccwabyt/jaccwabyt.c-pp.js - by libcmpp 2.x 2fc4afc31f6505c27b9c34988973a2bd9b157d559247cdd26868ae75632c3a5e @ 2025-11-16 23:03:27.352 UTC + by libcmpp 2.0.x 4539e17f451054d2aeb6a5ffe3891af087fd8fa6cfae4e31d02e1fddfec69d46 @ 2026-09-30 09:12:44.230 UTC */ 'use strict'; globalThis.Jaccwabyt = @@ -9921,8 +9936,8 @@ function StructBinderFactory(config){ and unmaps obj from its native resources. */ const __freeStruct = function(ctor, obj, m){ const ii = getInstanceHandle(obj, false); - if( !ii ) return; - rmInstanceHandle(obj); + if( !ii || ii.isDisposing ) return; + ii.isDisposing = true; if( !m && !(m = ii.p) ){ console.warn("Cannot(?) happen: __freeStruct() found no instanceInfo"); return; @@ -9949,6 +9964,7 @@ function StructBinderFactory(config){ m,'threw. NOT propagating it.',e); } } + rmInstanceHandle(obj); delete obj.ondispose; if(ctor.debugFlags.__flags.dealloc){ log("debug.dealloc:",(ii.ownsPointer?"":"EXTERNAL"), @@ -10874,6 +10890,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ // Please keep these sorted by function name! ["sqlite3_aggregate_context","void*", "sqlite3_context*", "int"], /* sqlite3_auto_extension() has a hand-written binding. */ + ["sqlite3_backup_init", "sqlite3_backup*", "sqlite3*", "string", "sqlite3*", "string"], + ["sqlite3_backup_step", "int", "sqlite3_backup*", "int"], + ["sqlite3_backup_finish", "int", "sqlite3_backup*"], + ["sqlite3_backup_remaining", "int", "sqlite3_backup*"], + ["sqlite3_backup_pagecount", "int", "sqlite3_backup*"], /* sqlite3_bind_blob() and sqlite3_bind_text() have hand-written bindings to permit more flexible inputs. */ ["sqlite3_bind_double","int", "sqlite3_stmt*", "int", "f64"], @@ -11581,6 +11602,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ /*a class which no value can ever be an instance of*/ }; wasm.xWrap.argAdapter('sqlite3_filename', __xArgPtr) + ('sqlite3_backup*', __xArgPtr) ('sqlite3_context*', __xArgPtr) ('sqlite3_value*', __xArgPtr) ('void*', __xArgPtr) @@ -11632,6 +11654,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ */ const __xRcPtr = wasm.xWrap.resultAdapter('*'); wasm.xWrap.resultAdapter('sqlite3*', __xRcPtr) + ('sqlite3_backup*', __xRcPtr) ('sqlite3_context*', __xRcPtr) ('sqlite3_stmt*', __xRcPtr) ('sqlite3_value*', __xRcPtr) @@ -12785,8 +12808,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ */ const __doesNotOwnHandle = new Set(); /** - Map of DB instances to objects, each object being a map of Stmt - wasm pointers to Stmt objects. + Map of DB instances to objects, each object being a map of + sqlite3_stmt wasm pointers to Stmt objects. */ const __stmtMap = new WeakMap(); @@ -13268,7 +13291,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const stmt = db.prepare(sql); try { const rc = stmt.bind(bind).step() ? stmt.get(...getArgs) : undefined; - stmt.reset(/*for INSERT...RETURNING locking case*/); + stmt.reset(/*for INSERT...RETURNING locking case + https://sqlite.org/forum/forumpost/c411b3a9143d02dce */); return rc; }finally{ stmt.finalize(); @@ -13284,6 +13308,57 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ sql, bind, rowMode, returnValue: 'resultRows' }); + /** + Internal impl of DB.Stmt APIs which fetch a column. The caller is + required to have validated the ndx value before calling this (see + affirmColIndex()). The purpose of this impl is to speed up such + operations which loop, to avoid having to validate the index on + each iteration. The arguments are as documented for Stmt.get() + with the exception that ndx must be an in-range interger (that + function handles the other cases and proxies them to this one). + */ + const __stmtGetColumn = (stmt, ndx, asType)=>{ + switch(undefined===asType + ? capi.sqlite3_column_type(stmt.pointer, ndx) + : asType){ + case capi.SQLITE_NULL: return null; + case capi.SQLITE_INTEGER:{ + if(wasm.bigIntEnabled){ + const rc = capi.sqlite3_column_int64(stmt.pointer, ndx); + if(rc>=Number.MIN_SAFE_INTEGER && rc<=Number.MAX_SAFE_INTEGER){ + return Number(rc).valueOf(); + } + return rc; + }else{ + const rc = capi.sqlite3_column_double(stmt.pointer, ndx); + if(rc>Number.MAX_SAFE_INTEGER || rc{ - if(s && s.pointer){ + for(const s of Object.values(__stmtMap.get(this))){ + if(s?.pointer){ try{s.finalize()} - catch(e){/*ignore*/} + catch(ex){/*ignore*/} } - }); + } __ptrMap.delete(this); __stmtMap.delete(this); if( !__doesNotOwnHandle.delete(this) ){ capi.sqlite3_close_v2(pDb); } - if(this.onclose && (this.onclose.after instanceof Function)){ + if(this.onclose?.after instanceof Function){ try{this.onclose.after(this)} catch(e){/*ignore*/} } @@ -13943,8 +14018,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ selectValues: function(sql,bind,asType){ const stmt = this.prepare(sql), rc = []; try { + affirmColIndex(stmt, 0); stmt.bind(bind); - while(stmt.step()) rc.push(stmt.get(0,asType)); + while(stmt.step()) rc.push( + __stmtGetColumn(stmt, 0, asType) + ); stmt.reset(/*for INSERT...RETURNING locking case*/); }finally{ stmt.finalize(); @@ -14368,6 +14446,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ also called, otherwise any existing bindings, along with any memory allocated for them, are retained. + Clients must not use capi.sqlite3_reset() with this object + because this method does book-keeping specific to this class, + e.g. the pieces which ensure that the column-fetching methods + throw when called without a corresponding step(). + In versions 3.42.0 and earlier, this function did not throw if sqlite3_reset() returns non-0, but it was discovered that throwing (or significant extra client-side code) is necessary @@ -14384,6 +14467,32 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ checkSqlite3Rc(this.db, rc); return this; }, + + /** + Works like reset() except that it returns the underlying + C-level result code instead of throwing if that code represents + an error. + + Clients must not use capi.sqlite3_reset() for this purpose + because this method (like reset()) does book-keeping specific + to this class. + + Throws if an exec() is underway. + + The use case this addresses is when a step() fails due to, + e.g., a locking error: a following reset() will report that + locking error by throwing and that's sometimes inconvenient. + + Added in 3.54. + */ + resetNoThrow: function(alsoClearBinds){ + affirmNotLockedByExec(this,'reset()'); + if(alsoClearBinds) this.clearBindings(); + const rc = capi.sqlite3_reset(affirmStmtOpen(this).pointer); + __stmtMayGet.delete(this); + return rc; + }, + /** Binds one or more values to its bindable parameters. It accepts 1 or 2 arguments: @@ -14601,14 +14710,16 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ an exception is thrown. By default it will determine the data type of the result - automatically. If passed a second argument, it must be one - of the enumeration values for sqlite3 types, which are - defined as members of the sqlite3 module: SQLITE_INTEGER, - SQLITE_FLOAT, SQLITE_TEXT, SQLITE_BLOB. Any other value, - except for undefined, will trigger an exception. Passing - undefined is the same as not passing a value. It is legal - to, e.g., fetch an integer value as a string, in which case - sqlite3 will convert the value to a string. + automatically. If passed a second argument, it must be one of + the enumeration values for sqlite3 types, which are defined as + members of the sqlite3.capi namespace: SQLITE_INTEGER, + SQLITE_FLOAT, SQLITE_TEXT, SQLITE_BLOB. Any other value, except + for undefined, will trigger an exception. Passing undefined is + the same as not passing a value. It is legal to, e.g., fetch an + integer value as a string, in which case sqlite3 will convert + the value to a string. + + Blobs are returned as Uint8Array instances. If ndx is an array, this function behaves a differently: it assigns the indexes of the array, from 0 to the number of @@ -14620,7 +14731,27 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ the values of their corresponding result columns and returns that object. - Blobs are returned as Uint8Array instances. + Performance note: this class does not cache its column names + because a reprepare may change them and we have(?) no(?) way of + hooking into that to invalidate the cache. A side effect of + that is that this function, when ndx is an object, has to copy + those names from the WASM side on each call. When fetching many + objects, DB.exec() can do so more efficiently by caching those + names for the duration of the query. In large result sets the + runtime difference is human-perceivable. + + Behavior change notice: prior to 3.54, the asType argument was + ignored when ndx is an array or object, the justification being + that we're generally fetching rows of mixed data types. As of + 3.54, it still behaves that way when passed the undefined value + resp. is not passed a value, but will coerce each column to the + request type of it is not the undefined value. It is not + believed that this change adversely affects any existing + client-level code because this argument was ignored and + applications passing a non-undefined value were not necessarily + getting back what they had specified (or did so only because + all of the data was of that type, in which case the new + behavior is identical for those queries). Potential TODO: add type ID SQLITE_JSON, which fetches the result as a string and passes it (if it's not null) to @@ -14635,69 +14766,22 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ let i = 0; const n = this.columnCount; while(i=Number.MIN_SAFE_INTEGER && rc<=Number.MAX_SAFE_INTEGER){ - /* Coerce "normal" number ranges to normal number values, - and only return BigInt-type values for numbers out of this - range. */ - return Number(rc).valueOf(); - } - return rc; - }else{ - const rc = capi.sqlite3_column_double(this.pointer, ndx); - if(rc>Number.MAX_SAFE_INTEGER || rcObject.prototype.hasOwnProperty.call(o,k); - - const kvvfsMethods = new sqlite3_kvvfs_methods( - /* Wraps the static sqlite3_api_methods singleton */ - wasm.exports.sqlite3__wasm_kvvfs_methods() - ); - util.assert( 32<=kvvfsMethods.$nKeySize, "unexpected kvvfsMethods.$nKeySize: "+kvvfsMethods.$nKeySize); - - /** - Most of the VFS-internal state. - */ - const cache = Object.assign(Object.create(null),{ - /** Regex matching journal file names. */ - rxJournalSuffix: /-journal$/, - /** Frequently-used C-string. */ - zKeyJrnl: wasm.allocCString("jrnl"), - /** Frequently-used C-string. */ - zKeySz: wasm.allocCString("sz"), - /** - The maximum size of a kvvfs record key. It is historically only - 32, a limitation currently retained only because it's convenient to - do so (the underlying code has outgrown the need for the artifically - low limit). - - We cache this value here because the end of this init code will - dispose of kvvfsMethods, invalidating it. - */ - keySize: kvvfsMethods.$nKeySize, - /** - WASM heap memory buffers to optimize out some frequent - allocations. - */ - buffer: Object.assign(Object.create(null),{ - /** - The size of each buffer in this.pool. - - kvvfsMethods.$nBufferSize is slightly larger than the output - space needed for a kvvfs-encoded 64kb db page in a worse-cast - encoding (128kb). It is not suitable for arbitrary buffer - use, only page de/encoding. - */ - n: kvvfsMethods.$nBufferSize, - /** - Map of buffer ids to wasm.alloc()'d pointers of size - this.n. (Re)used by various internals. - - Buffer ids 0 and 1 are used in the API internals. Other - names are used in higher-level APIs. - - See memBuffer() and memBufferFree(). - */ - pool: Object.create(null) - }) - }); - - /** - Returns a (cached) wasm.alloc()'d buffer of cache.buffer.n size, - throwing on OOM. - - We leak this one-time alloc because we've no better option. - sqlite3_vfs does not have a finalizer, so we've no place to hook - in the cleanup. We "could" extend sqlite3_shutdown() to have a - cleanup list for stuff like this but that function is never - used in JS, so it's hardly worth it. - */ - cache.memBuffer = (id=0)=>cache.buffer.pool[id] ??= wasm.alloc(cache.buffer.n); - - /** Frees the buffer with the given id. */ - cache.memBufferFree = (id)=>{ - const b = cache.buffer.pool[id]; - if( b ){ - wasm.dealloc(b); - delete cache.buffer.pool[id]; - } - }; - - const noop = ()=>{}; - const debug = sqlite3.__isUnderTest - ? (...args)=>sqlite3.config.debug?.("kvvfs:", ...args) - : noop; - const warn = (...args)=>sqlite3.config.warn?.("kvvfs:", ...args); - const error = (...args)=>sqlite3.config.error?.("kvvfs:", ...args); - - /** - Implementation of JS's Storage interface for use as backing store - of the kvvfs. Storage is a native class and its constructor - cannot be legally called from JS, making it impossible to - directly subclass Storage. This class implements (only) the - Storage interface, to make it a drop-in replacement for - localStorage/sessionStorage. (Any behavioral discrepancies are to - be considered bugs.) - - This impl simply proxies a plain, prototype-less Object, suitable - for JSON-ing. - - Design note: Storage has a bit of an odd iteration-related - interface as does not (AFAIK) specify specific behavior regarding - modification during traversal. Because of that, this class does - some seemingly unnecessary things with its #keys member, deleting - and recreating it whenever a property index might be invalidated. - */ - class KVVfsStorage { - #map = Object.create(null); - #keys = null; - #size = 0; - - constructor(){ - this.clear(); - } - - #getKeys(){ - return this.#keys ??= Object.keys(this.#map); - } - - key(n){ - if(n < 0 || n >= this.#size) return null; - return this.#getKeys()[n]; - } - - getItem(k){ - return this.#map[k] ?? null; - } - - setItem(k,v){ - if( !(k in this.#map) ){ - ++this.#size; - this.#keys = null; - } - this.#map[k] = ''+v; - } - - removeItem(k){ - if( k in this.#map ){ - delete this.#map[k]; - --this.#size; - this.#keys = null; - } - } - - clear(){ - this.#map = Object.create(null); - this.#keys = null; - this.#size = 0; - } - - get length() { - return this.#size; - } - }/*KVVfsStorage*/; - - /** True if v is the name of one of the special persistant Storage - objects. */ - const kvvfsIsPersistentName = (v)=>'local'===v || 'session'===v; - - /** - Keys in kvvfs have a prefix of "kvvfs-NAME-", where NAME is the - db name. This key is redundant in JS but it's how kvvfs works (it - saves each key to a separate file, so needs a distinct namespace - per data source name). We retain this prefix in 'local' and - 'session' storage for backwards compatibility and so that they - can co-exist with client data in their storage, but we elide them - from "v2" storage, where they're superfluous. - */ - const kvvfsKeyPrefix = (v)=>kvvfsIsPersistentName(v) ? 'kvvfs-'+v+'-' : ''; - - /** - Throws if storage name n (JS string) is not valid for use as a - storage name. Much of this goes back to kvvfs having a fixed - buffer size for its keys, and the storage name needing to be - encoded in the keys for local/session storage. - - The second argument must only be true when called from xOpen() - - it makes names with a "-journal" suffix legal. - */ - const validateStorageName = function(n,mayBeJournal=false){ - if( kvvfsIsPersistentName(n) ) return; - const len = (new Blob([n])).size/*byte length*/; - if( !len ) toss3(capi.SQLITE_MISUSE, "Empty name is not permitted."); - let maxLen = cache.keySize - 1; - if( cache.rxJournalSuffix.test(n) ){ - if( !mayBeJournal ){ - toss3(capi.SQLITE_MISUSE, - "Storage names may not have a '-journal' suffix."); - } - }else if( ['-wal','-shm'].filter(v=>n.endsWith(v)).length ){ - toss3(capi.SQLITE_MISUSE, - "Storage names may not have a -wal or -shm suffix."); - }else{ - maxLen -= 8 /* so we have space for a matching "-journal" suffix */; - } - if( len > maxLen ){ - toss3(capi.SQLITE_RANGE, "Storage name is too long. Limit =", maxLen); - } - let i; - for( i = 0; i < len; ++i ){ - const ch = n.codePointAt(i); - if( ch<32 ){ - toss3(capi.SQLITE_RANGE, - "Illegal character ("+ch+"d) in storage name:",n); - } - } - }; - - /** - Create a new instance of the objects which go into - cache.storagePool, with a refcount of 1. If passed a Storage-like - object as its second argument, it is used for the storage, - otherwise it creates a new KVVfsStorage object. - */ - const newStorageObj = (name,storage=undefined)=>Object.assign(Object.create(null),{ - /** - JS string value of this KVVfsFile::$zClass. i.e. the storage's - name. - */ - jzClass: name, - /** - Refcount. This keeps dbs and journals pointing to the same - storage for the life of both and enables kvvfs to behave more - like a conventional filesystem (a stepping stone towards - downstream API goals). Managed by xOpen() and xClose(). - */ - refc: 1, - /** - If true, this storage will be removed by xClose() or - sqlite3_js_kvvfs_unlink() when refc reaches 0. The others will - persist when refc==0, to give the illusion of real back-end - storage. Managed by xOpen() and sqlite3_js_kvvfs_reserve(). By - default this is false but the delete-on-close=1 flag can be - used to set this to true. - */ - deleteAtRefc0: false, - /** - The backing store. Must implement the Storage interface. - */ - storage: storage || new KVVfsStorage, - /** - The storage prefix used for kvvfs keys. It is - "kvvfs-STORAGENAME-" for local/session storage and an empty - string for other storage. local/session storage must use the - long form (A) for backwards compatibility and (B) so that kvvfs - can coexist with non-db client data in those backends. Neither - (A) nor (B) are concerns for KVVfsStorage objects. - - This prefix mirrors the one generated by os_kv.c's - kvrecordMakeKey() and must stay in sync with that one. - */ - keyPrefix: kvvfsKeyPrefix(name), - /** - KVVfsFile instances currently using this storage. Managed by - xOpen() and xClose(). - */ - files: [], - /** - If set, it's an array of objects with various event - callbacks. See sqlite3_js_kvvfs_listen(). When there are no - listeners, this member is set to undefined (instead of an empty - array) to allow us to more easily optimize out calls to - notifyListeners() for the common case of no listeners. - */ - listeners: undefined - }); - - /** - Public interface for kvvfs v2. The capi.sqlite3_js_kvvfs_...() - routines remain in place for v1. Some members of this class proxy - to those functions but use different default argument values in - some cases. - */ - const kvvfs = sqlite3.kvvfs = Object.create(null); - if( sqlite3.__isUnderTest ){ - /* For inspection via the dev tools console. */ - kvvfs.log = Object.assign(Object.create(null),{ - xOpen: false, - xClose: false, - xWrite: false, - xRead: false, - xSync: false, - xAccess: false, - xFileControl: false, - xRcrdRead: false, - xRcrdWrite: false, - xRcrdDelete: false, - }); - } - - /** - Deletes the cache.storagePool entries for store (a - cache.storagePool entry) and its db/journal counterpart. - */ - const deleteStorage = function(store){ - const other = cache.rxJournalSuffix.test(store.jzClass) - ? store.jzClass.replace(cache.rxJournalSuffix,'') - : store.jzClass+'-journal'; - kvvfs?.log?.xClose - && debug("cleaning up storage handles [", store.jzClass, other,"]",store); - delete cache.storagePool[store.jzClass]; - delete cache.storagePool[other]; - if( !sqlite3.__isUnderTest ){ - /* In test runs, leave these for inspection. If we delete them here, - any prior dumps of them emitted via the console get cleared out - because the console shows live objects instead of call-time - static dumps. */ - delete store.storage; - delete store.refc; - } - }; - - /** - Add both store.jzClass and store.jzClass+"-journal" - to cache,storagePool. - */ - const installStorageAndJournal = (store)=> - cache.storagePool[store.jzClass] = - cache.storagePool[store.jzClass+'-journal'] = store; - - /** - The public name of the current thread's transient storage - object. A storage object with this name gets preinstalled. - */ - const nameOfThisThreadStorage = '.'; - - /** - Map of JS-stringified KVVfsFile::zClass names to - reference-counted Storage objects. These objects are created in - xOpen(). Their refcount is decremented in xClose(), and the - record is destroyed if the refcount reaches 0. We refcount so - that concurrent active xOpen()s on a given name, and within a - given thread, use the same storage object. - */ - cache.storagePool = Object.assign(Object.create(null),{ - /* Start off with mappings for well-known names. */ - [nameOfThisThreadStorage]: newStorageObj(nameOfThisThreadStorage) - }); - - if( globalThis.Storage ){ - /* If available, install local/session storage. */ - if( globalThis.localStorage instanceof globalThis.Storage ){ - cache.storagePool.local = newStorageObj('local', globalThis.localStorage); - } - if( globalThis.sessionStorage instanceof globalThis.Storage ){ - cache.storagePool.session = newStorageObj('session', globalThis.sessionStorage); - } - } - - cache.builtinStorageNames = Object.keys(cache.storagePool); - - const isBuiltinName = (n)=>cache.builtinStorageNames.indexOf(n)>-1; - - /* Add "-journal" twins for each cache.storagePool entry... */ - for(const k of Object.keys(cache.storagePool)){ - /* Journals in kvvfs are are stored as individual records within - their Storage-ish object, named "{storage.keyPrefix}jrnl". We - always map the db and its journal to the same Storage - object. */ - const orig = cache.storagePool[k]; - cache.storagePool[k+'-journal'] = orig; - } - - cache.setError = (e=undefined, dfltErrCode=capi.SQLITE_ERROR)=>{ - if( e ){ - cache.lastError = e; - return (e.resultCode | 0) || dfltErrCode; - } - delete cache.lastError; - return 0; - }; - - cache.popError = ()=>{ - const e = cache.lastError; - delete cache.lastError; - return e; - }; - - /** Exception handler for notifyListeners(). */ - const catchForNotify = (e)=>{ - warn("kvvfs.listener handler threw:",e); - }; - - const kvvfsDecode = wasm.exports.sqlite3__wasm_kvvfs_decode; - const kvvfsEncode = wasm.exports.sqlite3__wasm_kvvfs_encode; - - /** - Listener events and their argument(s) (via the callback(ev) - ev.data member): - - 'open': number of opened handles on this storage. - - 'close': number of opened handles on this storage. - - 'write': key, value - - 'delete': key - - 'sync': true if it's from xSync(), false if it's from - xFileControl(). - - For efficiency's sake, all calls to this function should - be in the form: - - store.listeners && notifyListeners(...); - - Failing to do so will trigger an exceptin in this function (which - will be ignored but may produce a console warning). - */ - const notifyListeners = async function(eventName,store,...args){ - try{ - //cache.rxPageNoSuffix ??= /(\d+)$/; - if( store.keyPrefix && args[0] ){ - args[0] = args[0].replace(store.keyPrefix,''); - } - let u8enc, z0, z1, wcache; - for(const ear of store.listeners){ - const ev = Object.create(null); - ev.storageName = store.jzClass; - ev.type = eventName; - const decodePages = ear.decodePages; - const f = ear.events[eventName]; - if( f ){ - if( !ear.includeJournal && args[0]==='jrnl' ){ - continue; - } - if( 'write'===eventName && ear.decodePages && +args[0]>0 ){ - /* Decode pages to Uint8Array, caching the result in - wcache in case we have more listeners. */ - ev.data = [args[0]]; - if( wcache?.[args[0]] ){ - ev.data[1] = wcache[args[0]]; - continue; - } - u8enc ??= new TextEncoder('utf-8'); - z0 ??= cache.memBuffer(10); - z1 ??= cache.memBuffer(11); - const u = u8enc.encode(args[1]); - const heap = wasm.heap8u(); - heap.set(u, Number(z0)); - heap[wasm.ptr.addn(z0, u.length)] = 0; - const rc = kvvfsDecode(z0, z1, cache.buffer.n); - if( rc>0 ){ - wcache ??= Object.create(null); - wcache[args[0]] - = ev.data[1] - = heap.slice(Number(z1), wasm.ptr.addn(z1,rc)); - }else{ - continue; - } - }else{ - ev.data = args.length - ? ((args.length===1) ? args[0] : args) - : undefined; - } - try{f(ev)?.catch?.(catchForNotify)} - catch(e){ - warn("notifyListeners [",store.jzClass,"]",eventName,e); - } - } - } - }catch(e){ - catchForNotify(e); - } - }/*notifyListeners()*/; - - /** - Returns the storage object mapped to the given string zClass - (C-string pointer or JS string). - */ - const storageForZClass = (zClass)=> - 'string'===typeof zClass - ? cache.storagePool[zClass] - : cache.storagePool[wasm.cstrToJs(zClass)]; - - - const kvvfsMakeKey = wasm.exports.sqlite3__wasm_kvvfsMakeKey; - /** - Returns a C string from kvvfsMakeKey() OR returns zKey. In the - former case the memory is static, so must be copied before a - second call. zKey MUST be a pointer passed to a VFS/file method, - to allow us to avoid an alloc and/or an snprintf(). It requires - C-string arguments for zClass and zKey. zClass may be NULL but - zKey may not. - */ - const zKeyForStorage = (store, zClass, zKey)=>{ - //debug("zKeyForStorage(",store, wasm.cstrToJs(zClass), wasm.cstrToJs(zKey)); - return (zClass && store.keyPrefix) ? kvvfsMakeKey(zClass, zKey) : zKey; - }; - - const jsKeyForStorage = (store,zClass,zKey)=> - wasm.cstrToJs(zKeyForStorage(store, zClass, zKey)); - - const storageGetDbSize = (store)=>+store.storage.getItem(store.keyPrefix + "sz"); - - /** - sqlite3_file pointers => objects, each of which has: - - .file = KVVfsFile instance - - .jzClass = JS-string form of f.$zClass - - .storage = Storage object. It is shared between a db and its - journal. - */ - const pFileHandles = new Map(); - - /** - Original WASM functions for methods we partially override. - */ - const originalMethods = { - vfs: Object.create(null), - ioDb: Object.create(null), - ioJrnl: Object.create(null) - }; - - /** Returns the appropriate originalMethods[X] instance for the - given a KVVfsFile instance. */ - const originalIoMethods = (kvvfsFile)=> - originalMethods[kvvfsFile.$isJournal ? 'ioJrnl' : 'ioDb']; - - const pVfs = new capi.sqlite3_vfs(kvvfsMethods.$pVfs); - const pIoDb = new capi.sqlite3_io_methods(kvvfsMethods.$pIoDb); - const pIoJrnl = new capi.sqlite3_io_methods(kvvfsMethods.$pIoJrnl); - const recordHandler = - Object.create(null)/** helper for some vfs - routines. Populated later. */; - const kvvfsInternal = Object.assign(Object.create(null),{ - pFileHandles, - cache, - storageForZClass, - KVVfsStorage, - /** - BUG: changing to a page size other than the default, - then vacuuming, corrupts the db. As a workaround, - until this is resolved, we forcibly disable - (pragma page_size=...) changes. - */ - disablePageSizeChange: true - }); - if( kvvfs.log ){ - // this is a test build - kvvfs.internal = kvvfsInternal; - } - - /** - Implementations for members of the object referred to by - sqlite3__wasm_kvvfs_methods(). We swap out some native - implementations with these so that we can use JS Storage for - their backing store. - */ - const methodOverrides = { - - /** - sqlite3_kvvfs_methods's member methods. These perform the - fetching, setting, and removal of storage keys on behalf of - kvvfs. In the native impl these write each db page to a - separate file. This impl stores each db page as a single - record in a Storage object which is mapped to zClass. - - A db's size is stored in a record named kvvfs[-storagename]-sz - and the journal is stored in kvvfs[-storagename]-jrnl. The - [-storagename] part is a remnant of the native impl (so that - it has unique filenames per db) and is only used for - localStorage and sessionStorage. We elide that part (to save - space) from other storage objects but retain it on those two - to avoid invalidating pre-version-2 session/localStorage dbs. - - The interface docs for these methods are in src/os_kv.c's - kvrecordRead(), kvrecordWrite(), and kvrecordDelete(). - */ - recordHandler: { - xRcrdRead: (zClass, zKey, zBuf, nBuf)=>{ - try{ - const jzClass = wasm.cstrToJs(zClass); - const store = storageForZClass(jzClass); - if( !store ) return -1; - const jXKey = jsKeyForStorage(store, zClass, zKey); - kvvfs?.log?.xRcrdRead && warn("xRcrdRead", jzClass, jXKey, nBuf, store ); - const jV = store.storage.getItem(jXKey); - if(null===jV) return -1; - const nV = jV.length /* We are relying 100% on v being - ** ASCII so that jV.length is equal - ** to the C-string's byte length. */; - if( 0 ){ - debug("xRcrdRead", jXKey, store, jV); - } - if(nBuf<=0) return nV; - else if(1===nBuf){ - wasm.poke(zBuf, 0); - return nV; - } - if( nBuf+1{ - try { - const store = storageForZClass(zClass); - const jxKey = jsKeyForStorage(store, zClass, zKey); - const jData = wasm.cstrToJs(zData); - kvvfs?.log?.xRcrdWrite && warn("xRcrdWrite",jxKey, store); - store.storage.setItem(jxKey, jData); - store.listeners && notifyListeners('write', store, jxKey, jData); - return 0; - }catch(e){ - error("kvrecordWrite()",e); - return cache.setError(e, capi.SQLITE_IOERR); - } - }, - - xRcrdDelete: (zClass, zKey)=>{ - try { - const store = storageForZClass(zClass); - const jxKey = jsKeyForStorage(store, zClass, zKey); - kvvfs?.log?.xRcrdDelete && warn("xRcrdDelete",jxKey, store); - store.storage.removeItem(jxKey); - store.listeners && notifyListeners('delete', store, jxKey); - return 0; - }catch(e){ - error("kvrecordDelete()",e); - return cache.setError(e, capi.SQLITE_IOERR); - } - } - }/*recordHandler*/, - - /** - Override certain operations of the underlying sqlite3_vfs and - the two sqlite3_io_methods instances so that we can tie - Storage objects to db names. - */ - vfs:{ - /* sqlite3_kvvfs_methods::pVfs's methods */ - xOpen: function(pProtoVfs,zName,pProtoFile,flags,pOutFlags){ - cache.popError(); - let zToFree /* alloc()'d memory for temp db name */; - try{ - if( !zName ){ - zToFree = wasm.allocCString(""+pProtoFile+"." - +(Math.random() * 100000 | 0)); - zName = zToFree; - } - const jzClass = wasm.cstrToJs(zName); - kvvfs?.log?.xOpen && debug("xOpen",jzClass,"flags =",flags); - validateStorageName(jzClass, true); - if( (flags & (capi.SQLITE_OPEN_MAIN_DB - | capi.SQLITE_OPEN_TEMP_DB - | capi.SQLITE_OPEN_TRANSIENT_DB)) - && cache.rxJournalSuffix.test(jzClass) ){ - toss3(capi.SQLITE_ERROR, - "DB files may not have a '-journal' suffix."); - } - let s = storageForZClass(jzClass); - if( !s && !(flags & capi.SQLITE_OPEN_CREATE) ){ - toss3(capi.SQLITE_ERROR, "Storage not found:", jzClass); - } - const rc = originalMethods.vfs.xOpen(pProtoVfs, zName, pProtoFile, - flags, pOutFlags); - if( rc ) return rc; - let deleteAt0 = !!(capi.SQLITE_OPEN_DELETEONCLOSE & flags); - if(wasm.isPtr(arguments[1]/*original zName*/)){ - if(capi.sqlite3_uri_boolean(zName, "delete-on-close", 0)){ - deleteAt0 = true; - } - } - const f = new KVVfsFile(pProtoFile); - util.assert(f.$zClass, "Missing f.$zClass"); - f.addOnDispose(zToFree); - zToFree = undefined; - //debug("xOpen", jzClass, s); - if( s ){ - ++s.refc; - //no if( true===deleteAt0 ) s.deleteAtRefc0 = true; - s.files.push(f); - wasm.poke32(pOutFlags, flags); - }else{ - wasm.poke32(pOutFlags, flags | capi.SQLITE_OPEN_CREATE); - util.assert( !f.$isJournal, "Opening a journal before its db? "+jzClass ); - /* Map both zName and zName-journal to the same storage. */ - const nm = jzClass.replace(cache.rxJournalSuffix,''); - s = newStorageObj(nm); - installStorageAndJournal(s); - s.files.push(f); - s.deleteAtRefc0 = deleteAt0; - kvvfs?.log?.xOpen - && debug("xOpen installed storage handle [",nm, nm+"-journal","]", s); - } - pFileHandles.set(pProtoFile, {store: s, file: f, jzClass}); - s.listeners && notifyListeners('open', s, s.files.length); - return 0; - }catch(e){ - warn("xOpen:",e); - return cache.setError(e); - }finally{ - zToFree && wasm.dealloc(zToFree); - } - }/*xOpen()*/, - - xDelete: function(pVfs, zName, iSyncFlag){ - cache.popError(); - try{ - const jzName = wasm.cstrToJs(zName); - if( cache.rxJournalSuffix.test(jzName) ){ - recordHandler.xRcrdDelete(zName, cache.zKeyJrnl); - }/* - else: historically not done, but maybe otherwise delete - all db pages from storageForZClass(zName)? - */ - return 0; - }catch(e){ - warn("xDelete",e); - return cache.setError(e); - } - }, - - xAccess: function(pProtoVfs, zPath, flags, pResOut){ - cache.popError(); - try{ - const s = storageForZClass(zPath); - const jzPath = s?.jzClass || wasm.cstrToJs(zPath); - if( kvvfs?.log?.xAccess ){ - debug("xAccess",jzPath,"flags =", - flags,"*pResOut =",wasm.peek32(pResOut), - "store =",s); - } - if( !s ){ - // From the API docs: - /** The xAccess method returns [SQLITE_OK] on success or some - ** non-zero error code if there is an I/O error or if the name of - ** the file given in the second argument is illegal. - */ - // However, returning non-0 from here is fatal, so we don't do that. - try{validateStorageName(jzPath)} - catch(e){ - //warn("xAccess is ignoring name validation failure:",e); - wasm.poke32(pResOut, 0); - return 0; - } - } - if( s ){ - const key = s.keyPrefix+ - (cache.rxJournalSuffix.test(jzPath) ? "jrnl" : "1"); - const res = s.storage.getItem(key) ? 0 : 1; - /* This res value looks completely backwards to me, and - is the opposite of the native kvvfs's impl, but it's - working, whereas reimplementing the native one - faithfully does not. Read the lib-level code of where - this is invoked, my expectation is that we set res to 0 - for not-exists. */ - //warn("access res",jzPath,res); - wasm.poke32(pResOut, res); - }else{ - wasm.poke32(pResOut, 0); - } - return 0; - }catch(e){ - error('xAccess',e); - return cache.setError(e); - } - }, - - xRandomness: function(pVfs, nOut, pOut){ - const heap = wasm.heap8u(); - let i = 0; - const npOut = Number(pOut); - for(; i < nOut; ++i) heap[npOut + i] = (Math.random()*255000) & 0xFF; - return nOut; - }, - - xGetLastError: function(pVfs,nOut,pOut){ - const e = cache.popError(); - debug('xGetLastError',e); - if(e){ - const scope = wasm.scopedAllocPush(); - try{ - const [cMsg, n] = wasm.scopedAllocCString(e.message, true); - wasm.cstrncpy(pOut, cMsg, nOut); - if(n > nOut) wasm.poke8(wasm.ptr.add(pOut,nOut,-1), 0); - debug("set xGetLastError",e.message); - return (e.resultCode | 0) || capi.SQLITE_IOERR; - }catch(e){ - return capi.SQLITE_NOMEM; - }finally{ - wasm.scopedAllocPop(scope); - } - } - return 0; - } - - }/*.vfs*/, - - /** - kvvfs has separate sqlite3_api_methods impls for some of the - methods depending on whether it's a db or journal file. Some - of the methods use shared impls but others are specific to - either db or journal files. - */ - ioDb:{ - /* sqlite3_kvvfs_methods::pIoDb's methods */ - xClose: function(pFile){ - cache.popError(); - try{ - const h = pFileHandles.get(pFile); - kvvfs?.log?.xClose && debug("xClose", pFile, h); - if( h ){ - pFileHandles.delete(pFile); - const s = h.store;//storageForZClass(h.jzClass); - s.files = s.files.filter((v)=>v!==h.file); - if( --s.refc<=0 && s.deleteAtRefc0 ){ - deleteStorage(s); - } - originalMethods.ioDb/*same for journals*/.xClose(pFile); - h.file.dispose(); - s.listeners && notifyListeners('close', s, s.files.length); - }else{ - /* Can happen if xOpen fails */ - } - return 0; - }catch(e){ - error("xClose",e); - return cache.setError(e); - } - }, - - xFileControl: function(pFile, opId, pArg){ - cache.popError(); - try{ - const h = pFileHandles.get(pFile); - util.assert(h, "Missing KVVfsFile handle"); - kvvfs?.log?.xFileControl && debug("xFileControl",h,'op =',opId); - if( opId===capi.SQLITE_FCNTL_PRAGMA - && kvvfsInternal.disablePageSizeChange ){ - /* pArg== length-3 (char**) */ - //const argv = wasm.cArgvToJs(3, pArg); // the easy way - const zName = wasm.peekPtr(wasm.ptr.add(pArg, wasm.ptr.size)); - if( "page_size"===wasm.cstrToJs(zName) ){ - kvvfs?.log?.xFileControl - && debug("xFileControl pragma",wasm.cstrToJs(zName)); - const zVal = wasm.peekPtr(wasm.ptr.add(pArg, 2*wasm.ptr.size)); - if( zVal ){ - /* Without this, pragma page_size=N; followed by a - vacuum breaks the db. With this, it continues - working but does not actually change the page - size. */ - kvvfs?.log?.xFileControl - && warn("xFileControl pragma", h, - "NOT setting page size to", wasm.cstrToJs(zVal)); - h.file.$szPage = -1; - return 0/*corrupts: capi.SQLITE_NOTFOUND*/; - }else if( h.file.$szPage>0 ){ - kvvfs?.log?.xFileControl && - warn("xFileControl", h, "getting page size",h.file.$szPage); - wasm.pokePtr(pArg, wasm.allocCString(""+h.file.$szPage) - /* memory now owned by the library */); - return 0;//capi.SQLITE_NOTFOUND; - } - } - } - const rc = originalMethods.ioDb.xFileControl(pFile, opId, pArg); - if( 0==rc && capi.SQLITE_FCNTL_SYNC===opId ){ - h.store.listeners && notifyListeners('sync', h.store, false); - } - return rc; - }catch(e){ - error("xFileControl",e); - return cache.setError(e); - } - }, - - xSync: function(pFile,flags){ - cache.popError(); - try{ - const h = pFileHandles.get(pFile); - kvvfs?.log?.xSync && debug("xSync", h); - util.assert(h, "Missing KVVfsFile handle"); - const rc = originalMethods.ioDb.xSync(pFile, flags); - if( 0==rc && h.store.listeners ) notifyListeners('sync', h.store, true); - return rc; - }catch(e){ - error("xSync",e); - return cache.setError(e); - } - }, - - - }/*.ioDb*/, - - ioJrnl:{ - /* sqlite3_kvvfs_methods::pIoJrnl's methods. Those set to true - are copied as-is from the ioDb objects. Others are specific - to journal files. */ - xClose: true, - }/*.ioJrnl*/ - }/*methodOverrides*/; - - - try { - util.assert( cache.buffer.n>1024*129, "Heap buffer is not large enough" - /* Native is SQLITE_KVOS_SZ is 133073 as of this writing */ ); - for(const e of Object.entries(methodOverrides.recordHandler)){ - // Overwrite kvvfsMethods's callbacks - const k = e[0], f = e[1]; - recordHandler[k] = f; - if( 0 ){ - // bug: this should work - kvvfsMethods.installMethod(k, f); - }else{ - kvvfsMethods[kvvfsMethods.memberKey(k)] = - wasm.installFunction(kvvfsMethods.memberSignature(k), f); - } - } - for(const e of Object.entries(methodOverrides.vfs)){ - // Overwrite some pVfs entries and stash the original impls - const k = e[0], f = e[1], km = pVfs.memberKey(k), - member = pVfs.structInfo.members[k] - || util.toss("Missing pVfs.structInfo[",k,"]"); - originalMethods.vfs[k] = wasm.functionEntry(pVfs[km]); - pVfs[km] = wasm.installFunction(member.signature, f); - } - for(const e of Object.entries(methodOverrides.ioDb)){ - // Similar treatment for pVfs.$pIoDb a.k.a. pIoDb... - const k = e[0], f = e[1], km = pIoDb.memberKey(k); - originalMethods.ioDb[k] = wasm.functionEntry(pIoDb[km]) - || util.toss("Missing native pIoDb[",km,"]"); - pIoDb[km] = wasm.installFunction(pIoDb.memberSignature(k), f); - } - for(const e of Object.entries(methodOverrides.ioJrnl)){ - // Similar treatment for pVfs.$pIoJrnl a.k.a. pIoJrnl... - const k = e[0], f = e[1], km = pIoJrnl.memberKey(k); - originalMethods.ioJrnl[k] = wasm.functionEntry(pIoJrnl[km]) - || util.toss("Missing native pIoJrnl[",km,"]"); - if( true===f ){ - /* use pIoDb's copy */ - pIoJrnl[km] = pIoDb[km] || util.toss("Missing copied pIoDb[",km,"]"); - }else{ - pIoJrnl[km] = wasm.installFunction(pIoJrnl.memberSignature(k), f); - } - } - }finally{ - kvvfsMethods.dispose(); - pVfs.dispose(); - pIoDb.dispose(); - pIoJrnl.dispose(); - } - - /* - That gets all of the low-level bits out of the way. What follows - are the public API additions. - */ - - /** - Clears all storage used by the kvvfs DB backend, deleting any - DB(s) stored there. - - Its argument must be the name of a kvvfs storage object: - - - 'session' - - 'local' - - '' - see below. - - A transient kvvfs storage object name. - - In the first two cases, only sessionStorage resp. localStorage is - cleared. An empty string resolves to both 'local' and 'session' - storage. - - Returns the number of entries cleared. - - As of kvvfs version 2: - - This API is available in Worker threads but does not have access - to localStorage or sessionStorage in them. Prior versions did not - include this API in Worker threads. - - Differences in this function in version 2: - - - It accepts an arbitrary storage name. In v1 this was a silent - no-op for any names other than ('local','session',''). - - - It throws if a db currently has the storage opened UNLESS the - storage object is localStorage or sessionStorage. That version 1 - did not throw for this case was due to an architectural - limitation which has since been overcome, but removal of - JsStorageDb.prototype.clearStorage() would be a backwards compatibility - break, so this function permits wiping the storage for those two - cases even if they are opened. Use with care. - */ - const sqlite3_js_kvvfs_clear = function callee(which){ - if( ''===which ){ - return callee('local') + callee('session'); - } - const store = storageForZClass(which); - if( !store ) return 0; - if( store.files.length ){ - if( globalThis.localStorage===store.storage - || globalThis.sessionStorage===store.storage ){ - /* backwards compatibility: allow these to be cleared - while opened. */ - }else{ - /* Interestingly, kvvfs recovers just fine when the storage is - wiped, so long as the db is not in use and its schema is - recreated before it's used, but client apps should not have - to be faced with that eventuality mid-query (where it - _will_ cause failures). Therefore we disallow it when - storage handles are opened. Kvvfs version 1 could not - detect this case - see the if() block above. - */ - toss3(capi.SQLITE_ACCESS, - "Cannot clear in-use database storage."); - } - } - const s = store.storage; - const toRm = [] /* keys to remove */; - let i, n = s.length; - //debug("kvvfs_clear",store,s); - for( i = 0; i < n; ++i ){ - const k = s.key(i); - //debug("kvvfs_clear ?",k); - if(!store.keyPrefix || k.startsWith(store.keyPrefix)) toRm.push(k); - } - toRm.forEach((kk)=>s.removeItem(kk)); - //alertFilesToReload(store); - return toRm.length; - }; - - /** - This routine estimates the approximate amount of - storage used by the given kvvfs back-end. - - Its arguments are as documented for sqlite3_js_kvvfs_clear(), - only the operation this performs is different. - - The returned value is twice the "length" value of every matching - key and value, noting that JavaScript stores each character in 2 - bytes. - - The returned size is not authoritative from the perspective of - how much data can fit into localStorage and sessionStorage, as - the precise algorithms for determining those limits are - unspecified and may include per-entry overhead invisible to - clients. - */ - const sqlite3_js_kvvfs_size = function callee(which){ - if( ''===which ){ - return callee('local') + callee('session'); - } - const store = storageForZClass(which); - if( !store ) return 0; - const s = store.storage; - let i, sz = 0; - for(i = 0; i < s.length; ++i){ - const k = s.key(i); - if(!store.keyPrefix || k.startsWith(store.keyPrefix)){ - sz += k.length; - sz += s.getItem(k).length; - } - } - return sz * 2 /* because JS uses 2-byte char encoding */; - }; - - /** - Exports a kvvfs storage object to an object, optionally - JSON-friendly. - - Usages: - - thisfunc(storageName); - thisfunc(options); - - In the latter case, the options object must be an object with - the following properties: - - - "name" (string) required. The storage to export. - - - "decodePages" (bool=false). If true, the .pages result property - holdes Uint8Array objects holding the raw binary-format db - pages. The default is to use kvvfs-encoded string pages - (JSON-friendly). - - - "includeJournal" (bool=false). If true and the db has a current - journal, it is exported as well. (Kvvfs journals are stored as a - single record within the db's storage object.) - - The returned object is structured as follows... - - - "name": the name of the storage. This is 'local' or 'session' - for localStorage resp. sessionStorage, and an arbitrary name for - transient storage. This propery may be changed before passing - this object to sqlite3_js_kvvfs_import() in order to - import into a different storage object. - - - "timestamp": the time this function was called, in Unix - epoch milliseconds. - - - "size": the unencoded db size. - - - "journal": if options.includeJournal is true and this db has a - journal, it is stored as a string here, otherwise this property - is not set. - - - "pages": An array holding the raw encoded db pages in their - proper order. - - Throws if this db is not opened. - - The encoding of the underlying database is not part of this - interface - it is simply passed on as-is. Interested parties are - directed to src/os_kv.c in the SQLite source tree, with the - caveat that that code also does not offer a public interface. - i.e. the encoding is a private implementation detail of kvvfs. - The format may be changed in the future but kvvfs will continue - to support the current form. - - Added in version 3.52.0. - */ - const sqlite3_js_kvvfs_export = function callee(...args){ - let opt; - if( 1===args.length && 'object'===typeof args[0] ){ - opt = args[0]; - }else if(args.length){ - opt = Object.assign(Object.create(null),{ - name: args[0], - //decodePages: true - }); - } - const store = opt ? storageForZClass(opt.name) : null; - if( !store ){ - toss3(capi.SQLITE_NOTFOUND, - "There is no kvvfs storage named",opt?.name); - } - //debug("store to export=",store); - const s = store.storage; - const rc = Object.assign(Object.create(null),{ - name: store.jzClass, - timestamp: Date.now(), - pages: [] - }); - const pages = Object.create(null); - let xpages; - const keyPrefix = store.keyPrefix; - const rxTail = keyPrefix - ? /^kvvfs-[^-]+-(\w+)/ /* X... part of kvvfs-NAME-X... */ - : undefined; - let i = 0, n = s.length; - for( ; i < n; ++i ){ - const k = s.key(i); - if( !keyPrefix || k.startsWith(keyPrefix) ){ - let kk = (keyPrefix ? rxTail.exec(k) : undefined)?.[1] ?? k; - switch( kk ){ - case 'jrnl': - if( opt.includeJournal ) rc.journal = s.getItem(k); - break; - case 'sz': - rc.size = +s.getItem(k); - break; - default: - kk = +kk /* coerce to number */; - if( !util.isInt32(kk) || kk<=0 ){ - toss3(capi.SQLITE_RANGE, "Malformed kvvfs key: "+k); - } - if( opt.decodePages ){ - const spg = s.getItem(k), - n = spg.length, - z = cache.memBuffer(0), - zDec = cache.memBuffer(1), - heap = wasm.heap8u()/* MUST be inited last*/; - let i = 0; - for( ; i < n; ++i ){ - heap[wasm.ptr.add(z, i)] = spg.codePointAt(i) & 0xff; - } - heap[wasm.ptr.add(z, i)] = 0; - //debug("Decoding",i,"page bytes"); - const nDec = kvvfsDecode( - z, zDec, cache.buffer.n - ); - //debug("Decoded",nDec,"page bytes"); - pages[kk] = heap.slice(Number(zDec), wasm.ptr.addn(zDec, nDec)); - }else{ - pages[kk] = s.getItem(k); - } - break; - } - } - } - if( opt.decodePages ) cache.memBufferFree(1); - /* Now sort the page numbers and move them into an array. In JS - property keys are always strings, so we have to coerce them to - numbers so we can get them sorted properly for the array. */ - Object.keys(pages).map((v)=>+v).sort().forEach( - (v)=>rc.pages.push(pages[v]) - ); - return rc; - }/* sqlite3_js_kvvfs_export */; - - /** - The counterpart of sqlite3_js_kvvfs_export(). Its - argument must be the result of that function() or - a compatible one. - - This either replaces the contents of an existing transient - storage object or installs one named exp.name, setting - the storage's db contents to that of the exp object. - - Throws on error. Error conditions include: - - - The given storage object is currently opened by any db. - Performing this page-by-page import would invoke undefined - behavior on them. - - - Malformed input object. - - If it throws after starting the import then it clears the storage - before returning, to avoid leaving the db in an undefined - state. It may throw for any of the above-listed conditions before - reaching that step, in which case the db is not modified. If - exp.name refers to a new storage name then if it throws, the name - does not get installed. - - Added in version 3.52.0. - */ - const sqlite3_js_kvvfs_import = function(exp, overwrite=false){ - if( !exp?.timestamp - || !exp.name - || undefined===exp.size - || !Array.isArray(exp.pages) ){ - toss3(capi.SQLITE_MISUSE, "Malformed export object."); - }else if( !exp.size - || (exp.size !== (exp.size | 0)) - //|| (exp.size % cache.fixedPageSize) - || exp.size>=0x7fffffff ){ - toss3(capi.SQLITE_RANGE, "Invalid db size: "+exp.size); - } - - validateStorageName(exp.name); - let store = storageForZClass(exp.name); - const isNew = !store; - if( store ){ - if( !overwrite ){ - //warn("Storage exists:",arguments,store); - toss3(capi.SQLITE_ACCESS, - "Storage '"+exp.name+"' already exists and", - "overwrite was not specified."); - }else if( !store.files || !store.jzClass ){ - toss3(capi.SQLITE_ERROR, - "Internal storage object", exp.name,"seems to be malformed."); - }else if( store.files.length ){ - toss3(capi.SQLITE_IOERR_ACCESS, - "Cannot import db storage while it is in use."); - } - sqlite3_js_kvvfs_clear(exp.name); - }else{ - store = newStorageObj(exp.name); - //warn("Installing new storage:",store); - } - //debug("Importing store",store.poolEntry.files.length, store); - //debug("object to import:",exp); - const keyPrefix = kvvfsKeyPrefix(exp.name); - let zEnc; - try{ - /* Force the native KVVfsFile instances to re-read the db - and page size. */; - const s = store.storage; - s.setItem(keyPrefix+'sz', exp.size); - if( exp.journal ) s.setItem(keyPrefix+'jrnl', exp.journal); - if( exp.pages[0] instanceof Uint8Array ){ - /* raw binary pages */ - //debug("pages",exp.pages); - exp.pages.forEach((u,ndx)=>{ - const n = u.length; - if( 0 && cache.fixedPageSize !== n ){ - util.toss3(capi.SQLITE_RANGE,"Unexpected page size:", n); - } - zEnc ??= cache.memBuffer(1); - const zBin = cache.memBuffer(0), - heap = wasm.heap8u()/*MUST be inited last*/; - /* Copy u to the heap and encode the heap copy via C. This - is _presumably_ faster than porting the encoding algo to - JS. */ - heap.set(u, Number(zBin)); - heap[wasm.ptr.addn(zBin,n)] = 0; - const rc = kvvfsEncode(zBin, n, zEnc); - util.assert( rc < cache.buffer.n, - "Impossibly long output - possibly smashed the heap" ); - util.assert( 0===wasm.peek8(wasm.ptr.add(zEnc,rc)), - "Expecting NUL-terminated encoded output" ); - const jenc = wasm.cstrToJs(zEnc); - //debug("(un)encoded page:",u,jenc); - s.setItem(keyPrefix+(ndx+1), jenc); - }); - }else if( exp.pages[0] ){ - /* kvvfs-encoded pages */ - exp.pages.forEach((v,ndx)=>s.setItem(keyPrefix+(ndx+1), v)); - } - if( isNew ) installStorageAndJournal(store); - }catch{ - if( !isNew ){ - try{sqlite3_js_kvvfs_clear(exp.name);}catch(ee){/*ignored*/} - } - }finally{ - if( zEnc ) cache.memBufferFree(1); - } - return this; - }; - - /** - If no kvvfs storage exists with the given name, one is - installed. If one exists, its reference count is increased so - that it won't be freed by the closing of a database or journal - file. - - Throws if the name is not valid for a new storage object. - - Added in version 3.52.0. - */ - const sqlite3_js_kvvfs_reserve = function(name){ - let store = storageForZClass(name); - if( store ){ - ++store.refc; - return; - } - validateStorageName(name); - installStorageAndJournal(newStorageObj(name)); - }; - - /** - Conditionally "unlinks" a kvvfs storage object, reducing its - reference count by 1. - - This is a no-op if name ends in "-journal" or refers to a - built-in storage object. - - It will not lower the refcount below the number of - currently-opened db/journal files for the storage (so that it - cannot delete it out from under them). - - If the refcount reaches 0 then the storage object is - removed. - - Returns true if it reduces the refcount, else false. A result of - true does not necessarily mean that the storage unit was removed, - just that its refcount was lowered. Similarly, a result of false - does not mean that the storage is removed - it may still have - opened handles. - - Added in version 3.52.0. - */ - const sqlite3_js_kvvfs_unlink = function(name){ - const store = storageForZClass(name); - if( !store - || kvvfsIsPersistentName(store.jzClass) - || isBuiltinName(store.jzClass) - || cache.rxJournalSuffix.test(name) ) return false; - if( store.refc > store.files.length || 0===store.files.length ){ - if( --store.refc<=0 ){ - /* Ignoring deleteAtRefc0 for an explicit unlink */ - deleteStorage(store); - } - return true; - } - return false; - }; - - /** - Adds an event listener to a kvvfs storage object. The idea is - that this can be used to asynchronously back up one kvvfs storage - object to another or another channel entirely. (The caveat in the - latter case is that kvvfs's format is not readily consumable by - downstream code.) - - Its argument must be an object with the following properties: - - - storage: the name of the kvvfs storage object. - - - reserve [=false]: if true, sqlite3_js_kvvfs_reserve() is used - to ensure that the storage exists if it does not already. - If this is false and the storage does not exist then an - exception is thrown. - - - events: an object which may have any of the following - callback function properties: open, close, write, delete. - - - decodePages [=false]: if true, write events will receive each - db page write in the form of a Uint8Array holding the raw binary - db page. The default is to emit the kvvfs-format page because it - requires no extra work, we already have it in hand, and it's - often smaller. It's not great for interchange, though. - - - includeJournal [=false]: if true, writes and deletes of - "jrnl" records are included. If false, no events are sent - for journal updates. - - Passing the same object to sqlite3_js_kvvfs_unlisten() will - remove the listener. - - Each one of the events callbacks will be called asynchronously - when the given storage performs those operations. They may be - asynchronous functions but are not required to be (the events are - fired async either way, but making the event callbacks async may - be advantageous when multiple listeners are involved). All - exceptions, including those via Promises, are ignored but may (or - may not) trigger warning output on the console. - - Each callback gets passed a single object with the following - properties: - - .type = the same as the name of the callback - - .storageName = the name of the storage object - - .data = callback-dependent: - - - 'open' and 'close' get an integer, the number of - currently-opened handles on the storage. - - - 'write' gets a length-two array holding the key and value which - were written. The key is always a string, even if it's a db page - number. For db-page records, the value's type depends on - opt.decodePages. All others, including the journal, are strings. - (The journal, being a kvvfs-specific format, is delivered in - that same JSON-friendly format.) More details below. - - - 'delete' gets the string-type key of the deleted record. - - - 'sync' gets a boolean value: true if it was triggered by db - file's xSync(), false if it was triggered by xFileControl(). The - latter triggers before the xSync() and also triggers if the DB - has PRAGMA SYNCHRONOUS=OFF (in which case xSync() is not - triggered). - - The key/value arguments to 'write', and key argument to 'delete', - are in one of the following forms: - - - 'sz' = the unencoded db size as a string. This specific key is - key is never deleted, so is only ever passed to 'write' events. - - - 'jrnl' = the current db journal as a kvvfs-encoded string. This - journal format is not useful anywhere except in the kvvfs - internals. These events are not fired if opt.includeJournal is - false. - - - '[1-9][0-9]*' (a db page number) = Its type depends on - opt.decodePages. These may be written and deleted in arbitrary - order. - - Design note: JS has StorageEvents but only in the main thread, - which is why the listeners are not based on that. - - Added in version 3.52.0. - */ - const sqlite3_js_kvvfs_listen = function(opt){ - if( !opt || 'object'!==typeof opt ){ - toss3(capi.SQLITE_MISUSE, "Expecting a listener object."); - } - let store = storageForZClass(opt.storage); - if( !store ){ - if( opt.storage && opt.reserve ){ - sqlite3_js_kvvfs_reserve(opt.storage); - store = storageForZClass(opt.storage); - util.assert(store, - "Unexpectedly cannot fetch reserved storage " - +opt.storage); - }else{ - toss3(capi.SQLITE_NOTFOUND,"No such storage:",opt.storage); - } - } - if( opt.events ){ - (store.listeners ??= []).push(opt); - } - }; - - /** - Removes the kvvfs event listeners for the given options - object. It must be passed the same object instance which was - passed to sqlite3_js_kvvfs_listen(). - - This has no side effects if opt is invalid or is not a match for - any listeners. - - Return true if it unregisters its argument, else false. - - Added in version 3.52.0. - */ - const sqlite3_js_kvvfs_unlisten = function(opt){ - const store = storageForZClass(opt?.storage); - if( store?.listeners && opt.events ){ - const n = store.listeners.length; - store.listeners = store.listeners.filter((v)=>v!==opt); - const rc = n>store.listeners.length; - if( !store.listeners.length ){ - // to speed up downstream checks for listeners - store.listeners = undefined; - } - return rc; - } - return false; - }; - - sqlite3.kvvfs.reserve = sqlite3_js_kvvfs_reserve; - sqlite3.kvvfs.import = sqlite3_js_kvvfs_import; - sqlite3.kvvfs.export = sqlite3_js_kvvfs_export; - sqlite3.kvvfs.unlink = sqlite3_js_kvvfs_unlink; - sqlite3.kvvfs.listen = sqlite3_js_kvvfs_listen; - sqlite3.kvvfs.unlisten = sqlite3_js_kvvfs_unlisten; - sqlite3.kvvfs.exists = (name)=>!!storageForZClass(name); - sqlite3.kvvfs.estimateSize = sqlite3_js_kvvfs_size; - sqlite3.kvvfs.clear = sqlite3_js_kvvfs_clear; - - - if( globalThis.Storage ){ - /** - Prior to version 2, kvvfs was only available in the main - thread. We retain that for the v1 APIs, exposing them only in - the main UI thread. As of version 2, kvvfs is available in all - threads but only via its v2 interface (sqlite3.kvvfs). - - These versions have a default argument value of "" which the v2 - versions lack. - */ - capi.sqlite3_js_kvvfs_size = (which="")=>sqlite3_js_kvvfs_size(which); - capi.sqlite3_js_kvvfs_clear = (which="")=>sqlite3_js_kvvfs_clear(which); - } - - if(sqlite3.oo1?.DB){ - /** - Functionally equivalent to DB(storageName,'c','kvvfs') except - that it throws if the given storage name is not one of 'local' - or 'session'. - - As of version 3.46, the argument may optionally be an options - object in the form: - - { - filename: 'session'|'local', - ... etc. (all options supported by the DB ctor) - } - - noting that the 'vfs' option supported by main DB - constructor is ignored here: the vfs is always 'kvvfs'. - */ - const DB = sqlite3.oo1.DB; - sqlite3.oo1.JsStorageDb = function( - storageName = sqlite3.oo1.JsStorageDb.defaultStorageName - ){ - const opt = DB.dbCtorHelper.normalizeArgs(...arguments); - opt.vfs = 'kvvfs'; - if( 0 ){ - // Current tests rely on these, but that's arguably a bug - if( opt.flags ) opt.flags = 'cw'+opt.flags; - else opt.flags = 'cw'; - } - switch( opt.filename ){ - /* sqlite3_open(), in these builds, recognizes the names - below and performs some magic which we want to bypass - here for sanity's sake. */ - case ":sessionStorage:": opt.filename = 'session'; break; - case ":localStorage:": opt.filename = 'local'; break; - } - const m = /(file:(\/\/)?)([^?]+)/.exec(opt.filename); - validateStorageName( m ? m[3] : opt.filename); - DB.dbCtorHelper.call(this, opt); - }; - sqlite3.oo1.JsStorageDb.defaultStorageName - = cache.storagePool.session ? 'session' : nameOfThisThreadStorage; - const jdb = sqlite3.oo1.JsStorageDb; - jdb.prototype = Object.create(DB.prototype); - jdb.clearStorage = sqlite3_js_kvvfs_clear; - /** - DEPRECATED: the inherited method of this name (as opposed to - the "static" class method) is deprecated with version 2 of - kvvfs. This function will, for backwards comaptibility, - continue to work with localStorage and sessionStorage, but will - throw for all other storage because they are opened. Version 1 - was not capable of recognizing that the storage was opened so - permitted wiping it out at any time, but that was arguably a - bug. - - Clears this database instance's storage or throws if this - instance has been closed. Returns the number of - database pages which were cleaned up. - */ - jdb.prototype.clearStorage = function(){ - return jdb.clearStorage(this.affirmOpen().dbFilename(), true); - }; - /** Equivalent to sqlite3_js_kvvfs_size(). */ - jdb.storageSize = sqlite3_js_kvvfs_size; - /** - Returns the _approximate_ number of bytes this database takes - up in its storage or throws if this instance has been closed. - */ - jdb.prototype.storageSize = function(){ - return jdb.storageSize(this.affirmOpen().dbFilename(), true); - }; - }/*sqlite3.oo1.JsStorageDb*/ - - if( sqlite3.__isUnderTest && sqlite3.vtab ){ - /** - An eponymous vtab for inspecting the kvvfs state. This is only - intended for use in testing and development, not part of the - public API. - */ - const cols = Object.assign(Object.create(null),{ - rowid: {type: 'INTEGER'}, - name: {type: 'TEXT'}, - nRef: {type: 'INTEGER'}, - nOpen: {type: 'INTEGER'}, - isTransient: {type: 'INTEGER'}, - dbSize: {type: 'INTEGER'} - }); - Object.keys(cols).forEach((v,i)=>cols[v].colId = i); - - const VT = sqlite3.vtab; - const ProtoCursor = Object.assign(Object.create(null),{ - row: function(){ - return cache.storagePool[this.names[this.rowid]]; - } - }); - Object.assign(Object.create(ProtoCursor),{ - rowid: 0, - names: Object.keys(cache.storagePool) - .filter(v=>!cache.rxJournalSuffix.test(v)) - }); - const cursorState = function(cursor, reset){ - const o = (cursor instanceof capi.sqlite3_vtab_cursor) - ? cursor - : VT.xCursor.get(cursor); - if( reset || !o.vTabState ){ - o.vTabState = Object.assign(Object.create(ProtoCursor),{ - rowid: 0, - names: Object.keys(cache.storagePool) - .filter(v=>!cache.rxJournalSuffix.test(v)) - }); - } - return o.vTabState; - }; - - const dbg = 1 ? ()=>{} : (...args)=>debug("vtab",...args); - - const theModule = function f(){ - return f.mod ??= new sqlite3.capi.sqlite3_module().setupModule({ - catchExceptions: true, - methods: { - xConnect: function(pDb, pAux, argc, argv, ppVtab, pzErr){ - dbg("xConnect"); - try{ - const xcol = []; - Object.keys(cols).forEach((k)=>{ - xcol.push(k+" "+cols[k].type); - }); - const rc = capi.sqlite3_declare_vtab( - pDb, "CREATE TABLE ignored("+xcol.join(',')+")" - ); - if(0===rc){ - const t = VT.xVtab.create(ppVtab); - util.assert( - (t === VT.xVtab.get(wasm.peekPtr(ppVtab))), - "output pointer check failed" - ); - } - return rc; - }catch(e){ - return VT.xError('xConnect', e, capi.SQLITE_ERROR); - } - }, - xCreate: wasm.ptr.null, // eponymous only - //xCreate: true, // copy xConnect, i.e. also eponymous only - xDisconnect: function(pVtab){ - dbg("xDisconnect",...arguments); - VT.xVtab.dispose(pVtab); - return 0; - }, - xOpen: function(pVtab, ppCursor){ - dbg("xOpen",...arguments); - VT.xCursor.create(ppCursor); - return 0; - }, - xClose: function(pCursor){ - dbg("xClose",...arguments); - const c = VT.xCursor.unget(pCursor); - delete c.vTabState; - c.dispose(); - return 0; - }, - xNext: function(pCursor){ - dbg("xNext",...arguments); - const c = VT.xCursor.get(pCursor); - ++cursorState(c).rowid; - return 0; - }, - xColumn: function(pCursor, pCtx, iCol){ - dbg("xColumn",...arguments); - //const c = VT.xCursor.get(pCursor); - const st = cursorState(pCursor); - const store = st.row(); - util.assert(store, "Unexpected xColumn call"); - switch(iCol){ - case cols.rowid.colId: - capi.sqlite3_result_int(pCtx, st.rowid); - break; - case cols.name.colId: - capi.sqlite3_result_text(pCtx, store.jzClass, -1, capi.SQLITE_TRANSIENT); - break; - case cols.nRef.colId: - capi.sqlite3_result_int(pCtx, store.refc); - break; - case cols.nOpen.colId: - capi.sqlite3_result_int(pCtx, store.files.length); - break; - case cols.isTransient.colId: - capi.sqlite3_result_int(pCtx, !!store.deleteAtRefc0); - break; - case cols.dbSize.colId: - capi.sqlite3_result_int(pCtx, storageGetDbSize(store)); - break; - default: - capi.sqlite3_result_error(pCtx, "Invalid column id: "+iCol); - return capi.SQLITE_RANGE; - } - return 0; - }, - xRowid: function(pCursor, ppRowid64){ - dbg("xRowid",...arguments); - const st = cursorState(pCursor); - VT.xRowid(ppRowid64, st.rowid); - return 0; - }, - xEof: function(pCursor){ - const st = cursorState(pCursor); - dbg("xEof?="+(!st.row()),...arguments); - return !st.row(); - }, - xFilter: function(pCursor, idxNum, idxCStr, - argc, argv/* [sqlite3_value* ...] */){ - dbg("xFilter",...arguments); - const st = cursorState(pCursor, true); - return 0; - }, - xBestIndex: function(pVtab, pIdxInfo){ - dbg("xBestIndex",...arguments); - //const t = VT.xVtab.get(pVtab); - const pii = new capi.sqlite3_index_info(pIdxInfo); - pii.$estimatedRows = cache.storagePool.size; - pii.$estimatedCost = 1.0; - pii.dispose(); - return 0; - } - } - })/*setupModule*/; - }/*theModule()*/; - - sqlite3.kvvfs.create_module = function(pDb, name="sqlite_kvvfs"){ - return capi.sqlite3_create_module(pDb, name, theModule(), - wasm.ptr.null); - }; - - }/* virtual table */ - - -})/*globalThis.sqlite3ApiBootstrap.initializers*/; + delete sqlite3.capi.sqlite3_kvvfs_methods; + delete sqlite3.capi.KVVfsFile; +}); /* The OPFS SAH Pool VFS parts are elided from builds targeting node.js. diff --git a/src/bin/sqlite3-opfs-async-proxy.js b/src/bin/sqlite3-opfs-async-proxy.js index e09bbbd..d136eab 100644 --- a/src/bin/sqlite3-opfs-async-proxy.js +++ b/src/bin/sqlite3-opfs-async-proxy.js @@ -62,7 +62,7 @@ if( !vfsName ){ VFS or both the "opfs" and "opfs-wl" VFSes. */ const workerId = (Math.random() * 10000000) | 0; -const isWebLocker = 'opfs-wl'===urlParams.get('vfs'); +const isWebLocker = 'opfs-wl'===vfsName; const wPost = (type,...args)=>postMessage({type, payload:args}); const installAsyncProxy = function(){ const toss = function(...args){throw new Error(args.join(' '))}; diff --git a/src/bin/sqlite3.mjs b/src/bin/sqlite3.mjs index 4f4fa6c..8936330 100644 --- a/src/bin/sqlite3.mjs +++ b/src/bin/sqlite3.mjs @@ -27,9 +27,9 @@ /* @preserve ** This code was built from sqlite3 version... ** -** SQLITE_VERSION "3.53.4" -** SQLITE_VERSION_NUMBER 3053004 -** SQLITE_SOURCE_ID "2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc" +** SQLITE_VERSION "3.54.1" +** SQLITE_VERSION_NUMBER 3054001 +** SQLITE_SOURCE_ID "2026-10-16 14:45:20 555e07ef33f69a0957d24d8e555b702464a131d6f1607f4c3c1e4551e8e6ca76" ** ** Emscripten SDK: 5.0.5 */ @@ -92,7 +92,7 @@ var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIR /** This file was preprocessed using: - ./c-pp -o ./bld/pre-js.esm.js -Dtarget:es6-module -DModule.instantiateWasm api/pre-js.c-pp.js + ./c-pp -o ./bld/pre-js.esm.js -Dtarget:es6-module -Dsqlite3.wasm.base64=./jswasm/sqlite3.wasm -DModule.instantiateWasm api/pre-js.c-pp.js */ (function(Module){ const sIMS = @@ -154,12 +154,17 @@ var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIR It's disabled in the (unsupported/untested) node builds because node does not do fetch(). */ - Module['instantiateWasm'] = function callee(imports,onSuccess){ + Module['instantiateWasm'] = function callee(imports, onSuccess){ if( this.emscriptenInstantiateWasm instanceof Function ){ /* See [tag:locateFile]. Same story here */ return this.emscriptenInstantiateWasm(imports, onSuccess); } const sims = this; + const finalThen = (arg)=>{ + arg.imports = imports; + sims.instantiateWasm = arg; /* used by sqlite3-api-prologue.c-pp.js */ + onSuccess(arg.instance, arg.module); + }; const uri = Module.locateFile( sims.wasmFilename, ( ('undefined'===typeof scriptDirectory/*var defined by Emscripten glue*/) @@ -167,11 +172,6 @@ var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIR ); 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 @@ -4099,11 +4099,11 @@ var _sqlite3_status64, _sqlite3_db_status, _sqlite3_vfs_find, _sqlite3_initialize, - _sqlite3_malloc, - _sqlite3_free, _sqlite3_vfs_register, _sqlite3_vfs_unregister, + _sqlite3_malloc, _sqlite3_malloc64, + _sqlite3_free, _sqlite3_realloc, _sqlite3_realloc64, _sqlite3_value_text, @@ -4126,6 +4126,11 @@ var _sqlite3_status64, _sqlite3_column_type, _sqlite3_errmsg, _sqlite3_deserialize, + _sqlite3_backup_init, + _sqlite3_backup_step, + _sqlite3_backup_finish, + _sqlite3_backup_remaining, + _sqlite3_backup_pagecount, _sqlite3_clear_bindings, _sqlite3_value_blob, _sqlite3_value_bytes, @@ -4363,11 +4368,11 @@ function assignWasmExports(wasmExports) { _sqlite3_db_status = Module['_sqlite3_db_status'] = wasmExports['sqlite3_db_status']; _sqlite3_vfs_find = Module['_sqlite3_vfs_find'] = wasmExports['sqlite3_vfs_find']; _sqlite3_initialize = Module['_sqlite3_initialize'] = wasmExports['sqlite3_initialize']; - _sqlite3_malloc = Module['_sqlite3_malloc'] = wasmExports['sqlite3_malloc']; - _sqlite3_free = Module['_sqlite3_free'] = wasmExports['sqlite3_free']; _sqlite3_vfs_register = Module['_sqlite3_vfs_register'] = wasmExports['sqlite3_vfs_register']; _sqlite3_vfs_unregister = Module['_sqlite3_vfs_unregister'] = wasmExports['sqlite3_vfs_unregister']; + _sqlite3_malloc = Module['_sqlite3_malloc'] = wasmExports['sqlite3_malloc']; _sqlite3_malloc64 = Module['_sqlite3_malloc64'] = wasmExports['sqlite3_malloc64']; + _sqlite3_free = Module['_sqlite3_free'] = wasmExports['sqlite3_free']; _sqlite3_realloc = Module['_sqlite3_realloc'] = wasmExports['sqlite3_realloc']; _sqlite3_realloc64 = Module['_sqlite3_realloc64'] = wasmExports['sqlite3_realloc64']; _sqlite3_value_text = Module['_sqlite3_value_text'] = wasmExports['sqlite3_value_text']; @@ -4390,6 +4395,11 @@ function assignWasmExports(wasmExports) { _sqlite3_column_type = Module['_sqlite3_column_type'] = wasmExports['sqlite3_column_type']; _sqlite3_errmsg = Module['_sqlite3_errmsg'] = wasmExports['sqlite3_errmsg']; _sqlite3_deserialize = Module['_sqlite3_deserialize'] = wasmExports['sqlite3_deserialize']; + _sqlite3_backup_init = Module['_sqlite3_backup_init'] = wasmExports['sqlite3_backup_init']; + _sqlite3_backup_step = Module['_sqlite3_backup_step'] = wasmExports['sqlite3_backup_step']; + _sqlite3_backup_finish = Module['_sqlite3_backup_finish'] = wasmExports['sqlite3_backup_finish']; + _sqlite3_backup_remaining = Module['_sqlite3_backup_remaining'] = wasmExports['sqlite3_backup_remaining']; + _sqlite3_backup_pagecount = Module['_sqlite3_backup_pagecount'] = wasmExports['sqlite3_backup_pagecount']; _sqlite3_clear_bindings = Module['_sqlite3_clear_bindings'] = wasmExports['sqlite3_clear_bindings']; _sqlite3_value_blob = Module['_sqlite3_value_blob'] = wasmExports['sqlite3_value_blob']; _sqlite3_value_bytes = Module['_sqlite3_value_bytes'] = wasmExports['sqlite3_value_bytes']; @@ -4822,9 +4832,9 @@ Module.runSQLite3PostLoadInit = async function( /* @preserve ** This code was built from sqlite3 version... ** -** SQLITE_VERSION "3.53.4" -** SQLITE_VERSION_NUMBER 3053004 -** SQLITE_SOURCE_ID "2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc" +** SQLITE_VERSION "3.54.1" +** SQLITE_VERSION_NUMBER 3054001 +** SQLITE_SOURCE_ID "2026-10-16 14:45:20 555e07ef33f69a0957d24d8e555b702464a131d6f1607f4c3c1e4551e8e6ca76" ** ** Emscripten SDK: 5.0.5 */ @@ -5601,7 +5611,11 @@ globalThis.sqlite3ApiBootstrap = async function sqlite3ApiBootstrap( lead bytes of that buffer do not hold a SQLite3 database header, else it returns without side effects. - Added in 3.44. + Added in 3.44. As of 3.54 in SEE builds it performs only a + rudimentary length check and does not fail for invalid header + bytes, under the assumption that the input may be an encrypted + db. We cannot unambiguously distinguish an encrypted db from + garbage bytes. */ affirmDbHeader: function(bytes){ if(bytes instanceof ArrayBuffer) bytes = new Uint8Array(bytes); @@ -5621,7 +5635,8 @@ globalThis.sqlite3ApiBootstrap = async function sqlite3ApiBootstrap( database. It only examines the size and header, but further checks may be added in the future. - Added in 3.44. + Added in 3.44. See notes in affirmDbHeader() regarding SEE + builds. */ affirmIsDb: function(bytes){ if(bytes instanceof ArrayBuffer) bytes = new Uint8Array(bytes); @@ -7069,7 +7084,7 @@ globalThis.sqlite3ApiBootstrap.defaultConfig = Object.create(null); */ globalThis.sqlite3ApiBootstrap.sqlite3 = undefined; globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ - sqlite3.version = {"libVersion": "3.53.4", "libVersionNumber": 3053004, "sourceId": "2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc","downloadVersion": 3530400,"scm":{ "sha3-256": "bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc","branch": "branch-3.53","tags": "release version-3.53.4","datetime": "2026-07-24T19:02:57.525Z"}}; + sqlite3.version = {"libVersion": "3.54.1", "libVersionNumber": 3054001, "sourceId": "2026-10-16 14:45:20 555e07ef33f69a0957d24d8e555b702464a131d6f1607f4c3c1e4551e8e6ca76","downloadVersion": 3540100,"scm":{ "sha3-256": "555e07ef33f69a0957d24d8e555b702464a131d6f1607f4c3c1e4551e8e6ca76","branch": "branch-3.54","tags": "release version-3.54.1","datetime": "2026-10-16T14:45:20.546Z"}}; }); /** 2022-07-08 @@ -9641,7 +9656,7 @@ globalThis.WhWasmUtilInstaller ./c-pp -o js/jaccwabyt.js -@policy=error jaccwabyt/jaccwabyt.c-pp.js - by libcmpp 2.x 2fc4afc31f6505c27b9c34988973a2bd9b157d559247cdd26868ae75632c3a5e @ 2025-11-16 23:03:27.352 UTC + by libcmpp 2.0.x 4539e17f451054d2aeb6a5ffe3891af087fd8fa6cfae4e31d02e1fddfec69d46 @ 2026-09-30 09:12:44.230 UTC */ 'use strict'; globalThis.Jaccwabyt = @@ -9953,8 +9968,8 @@ function StructBinderFactory(config){ and unmaps obj from its native resources. */ const __freeStruct = function(ctor, obj, m){ const ii = getInstanceHandle(obj, false); - if( !ii ) return; - rmInstanceHandle(obj); + if( !ii || ii.isDisposing ) return; + ii.isDisposing = true; if( !m && !(m = ii.p) ){ console.warn("Cannot(?) happen: __freeStruct() found no instanceInfo"); return; @@ -9981,6 +9996,7 @@ function StructBinderFactory(config){ m,'threw. NOT propagating it.',e); } } + rmInstanceHandle(obj); delete obj.ondispose; if(ctor.debugFlags.__flags.dealloc){ log("debug.dealloc:",(ii.ownsPointer?"":"EXTERNAL"), @@ -10906,6 +10922,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ // Please keep these sorted by function name! ["sqlite3_aggregate_context","void*", "sqlite3_context*", "int"], /* sqlite3_auto_extension() has a hand-written binding. */ + ["sqlite3_backup_init", "sqlite3_backup*", "sqlite3*", "string", "sqlite3*", "string"], + ["sqlite3_backup_step", "int", "sqlite3_backup*", "int"], + ["sqlite3_backup_finish", "int", "sqlite3_backup*"], + ["sqlite3_backup_remaining", "int", "sqlite3_backup*"], + ["sqlite3_backup_pagecount", "int", "sqlite3_backup*"], /* sqlite3_bind_blob() and sqlite3_bind_text() have hand-written bindings to permit more flexible inputs. */ ["sqlite3_bind_double","int", "sqlite3_stmt*", "int", "f64"], @@ -11613,6 +11634,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ /*a class which no value can ever be an instance of*/ }; wasm.xWrap.argAdapter('sqlite3_filename', __xArgPtr) + ('sqlite3_backup*', __xArgPtr) ('sqlite3_context*', __xArgPtr) ('sqlite3_value*', __xArgPtr) ('void*', __xArgPtr) @@ -11664,6 +11686,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ */ const __xRcPtr = wasm.xWrap.resultAdapter('*'); wasm.xWrap.resultAdapter('sqlite3*', __xRcPtr) + ('sqlite3_backup*', __xRcPtr) ('sqlite3_context*', __xRcPtr) ('sqlite3_stmt*', __xRcPtr) ('sqlite3_value*', __xRcPtr) @@ -12817,8 +12840,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ */ const __doesNotOwnHandle = new Set(); /** - Map of DB instances to objects, each object being a map of Stmt - wasm pointers to Stmt objects. + Map of DB instances to objects, each object being a map of + sqlite3_stmt wasm pointers to Stmt objects. */ const __stmtMap = new WeakMap(); @@ -13300,7 +13323,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const stmt = db.prepare(sql); try { const rc = stmt.bind(bind).step() ? stmt.get(...getArgs) : undefined; - stmt.reset(/*for INSERT...RETURNING locking case*/); + stmt.reset(/*for INSERT...RETURNING locking case + https://sqlite.org/forum/forumpost/c411b3a9143d02dce */); return rc; }finally{ stmt.finalize(); @@ -13316,6 +13340,57 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ sql, bind, rowMode, returnValue: 'resultRows' }); + /** + Internal impl of DB.Stmt APIs which fetch a column. The caller is + required to have validated the ndx value before calling this (see + affirmColIndex()). The purpose of this impl is to speed up such + operations which loop, to avoid having to validate the index on + each iteration. The arguments are as documented for Stmt.get() + with the exception that ndx must be an in-range interger (that + function handles the other cases and proxies them to this one). + */ + const __stmtGetColumn = (stmt, ndx, asType)=>{ + switch(undefined===asType + ? capi.sqlite3_column_type(stmt.pointer, ndx) + : asType){ + case capi.SQLITE_NULL: return null; + case capi.SQLITE_INTEGER:{ + if(wasm.bigIntEnabled){ + const rc = capi.sqlite3_column_int64(stmt.pointer, ndx); + if(rc>=Number.MIN_SAFE_INTEGER && rc<=Number.MAX_SAFE_INTEGER){ + return Number(rc).valueOf(); + } + return rc; + }else{ + const rc = capi.sqlite3_column_double(stmt.pointer, ndx); + if(rc>Number.MAX_SAFE_INTEGER || rc{ - if(s && s.pointer){ + for(const s of Object.values(__stmtMap.get(this))){ + if(s?.pointer){ try{s.finalize()} - catch(e){/*ignore*/} + catch(ex){/*ignore*/} } - }); + } __ptrMap.delete(this); __stmtMap.delete(this); if( !__doesNotOwnHandle.delete(this) ){ capi.sqlite3_close_v2(pDb); } - if(this.onclose && (this.onclose.after instanceof Function)){ + if(this.onclose?.after instanceof Function){ try{this.onclose.after(this)} catch(e){/*ignore*/} } @@ -13975,8 +14050,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ selectValues: function(sql,bind,asType){ const stmt = this.prepare(sql), rc = []; try { + affirmColIndex(stmt, 0); stmt.bind(bind); - while(stmt.step()) rc.push(stmt.get(0,asType)); + while(stmt.step()) rc.push( + __stmtGetColumn(stmt, 0, asType) + ); stmt.reset(/*for INSERT...RETURNING locking case*/); }finally{ stmt.finalize(); @@ -14400,6 +14478,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ also called, otherwise any existing bindings, along with any memory allocated for them, are retained. + Clients must not use capi.sqlite3_reset() with this object + because this method does book-keeping specific to this class, + e.g. the pieces which ensure that the column-fetching methods + throw when called without a corresponding step(). + In versions 3.42.0 and earlier, this function did not throw if sqlite3_reset() returns non-0, but it was discovered that throwing (or significant extra client-side code) is necessary @@ -14416,6 +14499,32 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ checkSqlite3Rc(this.db, rc); return this; }, + + /** + Works like reset() except that it returns the underlying + C-level result code instead of throwing if that code represents + an error. + + Clients must not use capi.sqlite3_reset() for this purpose + because this method (like reset()) does book-keeping specific + to this class. + + Throws if an exec() is underway. + + The use case this addresses is when a step() fails due to, + e.g., a locking error: a following reset() will report that + locking error by throwing and that's sometimes inconvenient. + + Added in 3.54. + */ + resetNoThrow: function(alsoClearBinds){ + affirmNotLockedByExec(this,'reset()'); + if(alsoClearBinds) this.clearBindings(); + const rc = capi.sqlite3_reset(affirmStmtOpen(this).pointer); + __stmtMayGet.delete(this); + return rc; + }, + /** Binds one or more values to its bindable parameters. It accepts 1 or 2 arguments: @@ -14633,14 +14742,16 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ an exception is thrown. By default it will determine the data type of the result - automatically. If passed a second argument, it must be one - of the enumeration values for sqlite3 types, which are - defined as members of the sqlite3 module: SQLITE_INTEGER, - SQLITE_FLOAT, SQLITE_TEXT, SQLITE_BLOB. Any other value, - except for undefined, will trigger an exception. Passing - undefined is the same as not passing a value. It is legal - to, e.g., fetch an integer value as a string, in which case - sqlite3 will convert the value to a string. + automatically. If passed a second argument, it must be one of + the enumeration values for sqlite3 types, which are defined as + members of the sqlite3.capi namespace: SQLITE_INTEGER, + SQLITE_FLOAT, SQLITE_TEXT, SQLITE_BLOB. Any other value, except + for undefined, will trigger an exception. Passing undefined is + the same as not passing a value. It is legal to, e.g., fetch an + integer value as a string, in which case sqlite3 will convert + the value to a string. + + Blobs are returned as Uint8Array instances. If ndx is an array, this function behaves a differently: it assigns the indexes of the array, from 0 to the number of @@ -14652,7 +14763,27 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ the values of their corresponding result columns and returns that object. - Blobs are returned as Uint8Array instances. + Performance note: this class does not cache its column names + because a reprepare may change them and we have(?) no(?) way of + hooking into that to invalidate the cache. A side effect of + that is that this function, when ndx is an object, has to copy + those names from the WASM side on each call. When fetching many + objects, DB.exec() can do so more efficiently by caching those + names for the duration of the query. In large result sets the + runtime difference is human-perceivable. + + Behavior change notice: prior to 3.54, the asType argument was + ignored when ndx is an array or object, the justification being + that we're generally fetching rows of mixed data types. As of + 3.54, it still behaves that way when passed the undefined value + resp. is not passed a value, but will coerce each column to the + request type of it is not the undefined value. It is not + believed that this change adversely affects any existing + client-level code because this argument was ignored and + applications passing a non-undefined value were not necessarily + getting back what they had specified (or did so only because + all of the data was of that type, in which case the new + behavior is identical for those queries). Potential TODO: add type ID SQLITE_JSON, which fetches the result as a string and passes it (if it's not null) to @@ -14667,69 +14798,22 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ let i = 0; const n = this.columnCount; while(i=Number.MIN_SAFE_INTEGER && rc<=Number.MAX_SAFE_INTEGER){ - /* Coerce "normal" number ranges to normal number values, - and only return BigInt-type values for numbers out of this - range. */ - return Number(rc).valueOf(); - } - return rc; - }else{ - const rc = capi.sqlite3_column_double(this.pointer, ndx); - if(rc>Number.MAX_SAFE_INTEGER || rc cache.storagePool[store.jzClass] = @@ -16732,6 +16836,35 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ */ const pFileHandles = new Map(); + /** + Map of filename to lock objects with this structure: + + {.lockType: int, .nShared: int} + + Used by xLock(), xUnlock(), and xCheckReservedLock(). Modelled + after the "same-process, same-file, different-db-handle" locking + in os_unix.c. + */ + const mapPathToLocks = new Map(); + + /** + Main xUnlock() impl for kvvfs, also used by xClose(). Expects an + xOpen()-created file handle object and the second argument to + xUnlock(). It returns void. + */ + const unlockFile = function(fh, lockType){ + if(fh.lockType<=lockType) return; + const lk = mapPathToLocks.get(fh.jzClass); + if(fh.lockType>capi.SQLITE_LOCK_SHARED){ + lk.lockType = capi.SQLITE_LOCK_SHARED; + } + if(lockType===capi.SQLITE_LOCK_NONE && 0===--lk.nShared + /* Maintenance reminder: the && ordering is significant */){ + mapPathToLocks.delete(fh.jzClass); + } + fh.lockType = lockType; + }; + /** Original WASM functions for methods we partially override. */ @@ -16816,29 +16949,25 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ else if(1===nBuf){ wasm.poke(zBuf, 0); return nV; - } - if( nBuf+1 nV + 1 ){ + nBuf = nV + 1; } if( 0 ){ debug("xRcrdRead", nBuf, zClass, wasm.cstrToJs(zClass), wasm.cstrToJs(zKey), nV, jV, store); } - const zV = cache.memBuffer(0); - //if( !zV ) return -3 /*OOM*/; + const nCopy = nV0, }/*.vfs*/, @@ -17056,6 +17199,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ kvvfs?.log?.xClose && debug("xClose", pFile, h); if( h ){ pFileHandles.delete(pFile); + unlockFile(h, capi.SQLITE_LOCK_NONE); const s = h.store;//storageForZClass(h.jzClass); s.files = s.files.filter((v)=>v!==h.file); if( --s.refc<=0 && s.deleteAtRefc0 ){ @@ -17134,6 +17278,82 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ } }, + xLock: function(pFile, iLock){ + cache.popError(); + try{ + const h = pFileHandles.get(pFile); + if( capi.SQLITE_LOCK_NONE!==iLock ){ + /* Tells the impl to re-read its size. */ + originalMethods.ioDb.xLock(pFile, iLock); + } + /** + This impl is based off of the one in the opfs-sahpool VFS + impl which, in turn, is based off of the impl in + os_unix.c. + */ + if(h.lockType>=iLock) return 0; + let lk = mapPathToLocks.get(h.jzClass); + if(!lk){ + lk = Object.assign(Object.create(null),{ + nShared: 0, lockType: capi.SQLITE_LOCK_NONE + }); + mapPathToLocks.set(h.jzClass, lk); + } + if(h.lockType!==lk.lockType + && (lk.lockType>=capi.SQLITE_LOCK_PENDING + || iLock>capi.SQLITE_LOCK_SHARED)){ + return capi.SQLITE_BUSY; + } + if(iLock===capi.SQLITE_LOCK_SHARED){ + ++lk.nShared; + if(lk.lockType===capi.SQLITE_LOCK_NONE) lk.lockType = iLock; + }else if(iLock===capi.SQLITE_LOCK_EXCLUSIVE && lk.nShared>1){ + if(h.lockType===capi.SQLITE_LOCK_RESERVED){ + h.lockType = lk.lockType = capi.SQLITE_LOCK_PENDING; + } + return capi.SQLITE_BUSY; + }else{ + lk.lockType = iLock; + } + h.lockType = iLock; + return 0; + }catch(e){ + error("xLock", e); + return cache.setError(e); + } + }, + + xUnlock: function(pFile, iLock){ + cache.popError(); + try{ + if( capi.SQLITE_LOCK_NONE===iLock ){ + /* Tells the impl to re-read its size on the next op. */ + originalMethods.ioDb.xUnlock(pFile, iLock); + } + const h = pFileHandles.get(pFile); + unlockFile(h, iLock); + return 0; + }catch(e){ + error("xUnlock", e); + return cache.setError(e); + } + }, + + xCheckReservedLock: function(pFile, pOut){ + cache.popError(); + try{ + const h = pFileHandles.get(pFile); + const lk = mapPathToLocks.get(h.jzClass); + wasm.poke32(pOut, + (!!lk && lk.lockType>capi.SQLITE_LOCK_SHARED) + ? 1 : 0) + return 0; + }catch(e){ + error("xCheckReservedLock", e); + return cache.setError(e); + } + }, + }/*.ioDb*/, @@ -17142,6 +17362,9 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ are copied as-is from the ioDb objects. Others are specific to journal files. */ xClose: true, + xLock: true, + xUnlock: true, + xCheckReservedLock: true, }/*.ioJrnl*/ }/*methodOverrides*/; @@ -18371,11 +18594,15 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ called this way, the resolved value of the returned Promise is the number of bytes written to the target file. - It very specifically requires the input to be an SQLite3 - database and throws if that's not the case. It does so in - order to prevent this function from taking on a larger scope - than it is specifically intended to. i.e. we do not want it to - become a convenience for importing arbitrary files into OPFS. + It very specifically requires the input to be an SQLite3 database + and throws if that's not the case. It does so in order to + prevent this function from taking on a larger scope than it is + specifically intended to. i.e. we do not want it to become a + convenience for importing arbitrary files into OPFS. Caveat: as + of 3.54 in SEE builds, the "is this a db?" check is necessarily + lax to account for SEE-encrypted databases not having a legible + header. In such builds, only the db size is relevant for the + check. This routine rewrites the database header bytes in the output file (not the input array) to force disabling of WAL mode. @@ -18857,6 +19084,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ so would need to pass it to the async proxy. That would make it inordinately expensive considering that it's just a hint. + + See: forum:a2f573b00cda1372 */ wasm.poke(pOut, 0, 'i32'); return 0; @@ -19298,7 +19527,7 @@ const initS11n = function(){ //| capi.SQLITE_OPEN_DELETEONCLOSE | capi.SQLITE_OPEN_MAIN_DB; const pOut = wasm.scopedAlloc(8); - const dbFile = "/sanity/check/file"+randomFilename(8); + const dbFile = "/sanity/check/file"+opfsUtil.randomFilename(8); const zDbFile = wasm.scopedAllocCString(dbFile); let rc; state.s11n.serialize("This is รค string."); @@ -19387,7 +19616,7 @@ const initS11n = function(){ state.sabFileBufView = new Uint8Array(state.sabIO, 0, state.fileBufferSize); state.sabS11nView = new Uint8Array(state.sabIO, state.sabS11nOffset, state.sabS11nSize); opfsVfs.initS11n(); - delete opfsVfs.initS11n; + opfsVfs.initS11n = null; if(options.sanityChecks){ warn("Running sanity checks because of opfs-sanity-check URL arg..."); sanityCheck(); @@ -19653,6 +19882,9 @@ globalThis.sqlite3ApiBootstrap.initializersAsync.push(async (sqlite3)=>{ - Also because of that, it does not require the SharedArrayBuffer, so can function without the COOP/COEP HTTP response headers. + - Also because of that, this one is much faster and the performance + gap increases as the job sizes increase. + - It can hypothetically support Safari 16.4+, whereas the "opfs" VFS requires v17 due to a subworker/storage bug in 16.x which makes it incompatible with that VFS. @@ -19757,7 +19989,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ /* Logging verbosity 3+ == everything, 2 == warnings+errors, 1 == errors only. */ verbosity: 2, - forceReinitIfPreviouslyFailed: false + forceReinitIfPreviouslyFailed: false, + preserveOnInitFailure: false }); /** Logging routines, from most to least serious. */ @@ -19794,7 +20027,17 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const pool = getPoolForPFile(pFile); pool.log('xCheckReservedLock'); pool.storeErr(); - wasm.poke32(pOut, 1); + const file = pool.getOFileForS3File(pFile); + wasm.poke32( + pOut, + pool.hasReservedLock(file.path) ? 1 : 0 + /* As forum:b2fbb61642 elaborates on why we cannot simply + check file.lockType>=capi.SQLITE_LOCK_RESERVED + here. Summary: xOpen() has long allowed multiple handles to + the same filename and we need to check if any of them have + a lock to avoid a specific corruption case which that forum + thread demonstrates. */ + ); return 0; }, xClose: function(pFile){ @@ -19804,6 +20047,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ if(file) { try{ pool.log(`xClose ${file.path}`); + pool.unlockFile(file, capi.SQLITE_LOCK_NONE); pool.mapS3FileToOFile(pFile, false); file.sah.flush(); if(file.flags & capi.SQLITE_OPEN_DELETEONCLOSE){ @@ -19835,8 +20079,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ pool.log(`xLock ${lockType}`); pool.storeErr(); const file = pool.getOFileForS3File(pFile); - file.lockType = lockType; - return 0; + return pool.lockFile(file, lockType); }, xRead: function(pFile,pDest,n,offset64){ const pool = getPoolForPFile(pFile); @@ -19890,7 +20133,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const pool = getPoolForPFile(pFile); pool.log('xUnlock'); const file = pool.getOFileForS3File(pFile); - file.lockType = lockType; + pool.unlockFile(file, lockType); return 0; }, xWrite: function(pFile,pSrc,n,offset64){ @@ -19991,6 +20234,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ ? pool.getPath(zName) : getRandomName(); let sah = pool.getSAHForPath(path); + if(sah && (flags & capi.SQLITE_OPEN_CREATE) + && (flags & capi.SQLITE_OPEN_EXCLUSIVE)){ + toss('file already exists:', path); + } if(!sah && (flags & capi.SQLITE_OPEN_CREATE)) { // File not found so try to create it. if(pool.getFileCount() < pool.getCapacity()) { @@ -20057,7 +20304,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ /* Inherit certain VFS members from the default VFS, if available. */ opfsVfs.$xRandomness = dVfs.$xRandomness; - opfsVfs.$xSleep = dVfs.$xSleep; dVfs.dispose(); } if(!opfsVfs.$xRandomness && !vfsMethods.xRandomness){ @@ -20070,9 +20316,14 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ return i; }; } - if(!opfsVfs.$xSleep && !vfsMethods.xSleep){ - vfsMethods.xSleep = (pVfs,ms)=>0; - } + /** + This VFS's xSleep() must be a no-op. In this environment, + only db handles within the same thread can ever come into + contention, and that contention cannot be resolved if + one of the handles sleeps in that same thread. + See also: forum:3f0794c5d8 + */ + vfsMethods.xSleep = (pVfs,ms)=>0; sqlite3.vfs.installVfs({ vfs: {struct: opfsVfs, methods: vfsMethods} }); @@ -20080,8 +20331,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ }; /** - Class for managing OPFS-related state for the - OPFS SharedAccessHandle Pool sqlite3_vfs. + Class for managing OPFS-related state for the OPFS + SharedAccessHandle Pool sqlite3_vfs. This class is + internal-use-only, never exposed to the client. OpfsSAHPoolUtil + is the public-facing part. */ class OpfsSAHPool { /* OPFS dir in which VFS metadata is stored. */ @@ -20103,7 +20356,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ /* Set of currently-unused SAHs. */ #availableSAH = new Set(); /* Maps (sqlite3_file*) to xOpen's file objects. */ - #mapS3FileToOFile_ = new Map(); + #mapS3FileToOFile = new Map(); + /* Maps client-side file names to the lock state of the files + opened via this pool: {nShared, lockType}, modelled after + os_unix.c:unixInodeInfo. */ + #mapPathToLock = new Map(); /* Maps SAH to an abstract File Object which contains various metadata about that handle. */ @@ -20119,6 +20376,9 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ // Logging verbosity. See optionDefaults.verbosity. #verbosity; + /** + Options are documented in installOpfsSAHPoolVfs(). + */ constructor(options = Object.create(null)){ this.#verbosity = options.verbosity ?? optionDefaults.verbosity; this.vfsName = options.name || optionDefaults.name; @@ -20145,6 +20405,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ warn(...args){this.#logImpl(1, ...args)}; error(...args){this.#logImpl(0, ...args)}; + /* Design note: at the time this method was added, the developer + was unaware that getter syntax was an option: get vfs(){...} */ getVfs(){return this.#cVfs} /* Current pool capacity. */ @@ -20179,22 +20441,32 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ } /** - Reduce capacity by n, but can only reduce up to the limit - of currently-available SAHs. Returns a Promise which resolves - to the number of slots really removed. + Reduce capacity by n, but can only reduce up to the limit of + currently-available SAHs. Returns a Promise which resolves to + the number of slots really removed. Throws if removal of an + OPFS filesystem entry fails for any reason, in which case the + VFS itself is left in a well-defined state, possibly partially + reduced in capacity compared to before this call, but the file + which was unable to be removed is in an undefined state. It may + be orphaned and/or later recycled. + + As of 3.54, throws if n is an invalid value. Prior to that + an invalid value could cause it to remove all entries. */ async reduceCapacity(n){ + if(!Number.isSafeInteger(n) || n < 0){ + toss('Invalid capacity reduction:', n); + } let nRm = 0; for(const ah of Array.from(this.#availableSAH)){ if(nRm === n || this.getFileCount() === this.getCapacity()){ break; } const name = this.#mapSAHToName.get(ah); - //this.#unmapFileObject(ah); ah.close(); - await this.#dhOpaque.removeEntry(name); this.#mapSAHToName.delete(ah); this.#availableSAH.delete(ah); + await this.#dhOpaque.removeEntry(name); ++nRm; } return nRm; @@ -20210,6 +20482,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ this.#mapSAHToName.clear(); this.#mapFilenameToSAH.clear(); this.#availableSAH.clear(); + this.#mapS3FileToOFile.clear(); + this.#mapPathToLock.clear(); } /** @@ -20219,8 +20493,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ throws, this.$error will contain the corresponding Error object. - If it throws, it releases any SAHs which it may have - acquired before the exception was thrown, leaving the VFS in a + If it throws, it waits for every pending acquisition to settle, + then releases all SAHs it acquired, leaving the VFS in a well-defined but unusable state. If clearFiles is true, the client-stored state of each file is @@ -20234,27 +20508,31 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ files.push([name,h]); } } - return Promise.all(files.map(async([name,h])=>{ - try{ - const ah = await h.createSyncAccessHandle() - this.#mapSAHToName.set(ah, name); - if(clearFiles){ - ah.truncate(HEADER_OFFSET_DATA); - this.setAssociatedPath(ah, '', 0); + const results = await Promise.allSettled(files.map(async([name,h])=>{ + const ah = await h.createSyncAccessHandle() + this.#mapSAHToName.set(ah, name); + if(clearFiles){ + ah.truncate(HEADER_OFFSET_DATA); + this.setAssociatedPath(ah, '', 0); + }else{ + const path = this.getAssociatedPath(ah); + if(path){ + this.#mapFilenameToSAH.set(path, ah); }else{ - const path = this.getAssociatedPath(ah); - if(path){ - this.#mapFilenameToSAH.set(path, ah); - }else{ - this.#availableSAH.add(ah); - } + this.#availableSAH.add(ah); } - }catch(e){ - this.storeErr(e); - this.releaseAccessHandles(); - throw e; } })); + const failure = results.find((r)=>'rejected'===r.status) + /* If any failures are found then clean up and re-throw the + first one. We "could" record them all but we can only throw + one of them (or an exception wrapping all of them, which + seems unnecessary). */; + if( failure ){ + this.storeErr(failure.reason); + this.releaseAccessHandles(); + throw failure.reason; + } } /** @@ -20307,8 +20585,12 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ into the given SAH. If path is an empty string then the file is disassociated from the pool but its previous name is preserved in the metadata. + + If nameToRemove is truthy then it must be the "old" name when path + is falsy. This function removes the mapping of that name to an + SAH. */ - setAssociatedPath(sah, path, flags){ + setAssociatedPath(sah, path, flags, nameToRemove){ const enc = textEncoder.encodeInto(path, this.#apBody); if(HEADER_MAX_PATH_SIZE <= enc.written + 1/*NUL byte*/){ toss("Path too long:",path); @@ -20325,6 +20607,17 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const digest = this.computeDigest(this.#apBody, flags); //console.warn("setAssociatedPath(",path,") digest",digest); sah.write(this.#apBody, {at: 0}); + if(nameToRemove){ + /* The placement of this is very specific: between the above + write and the digest. If the above write fails, + nameToRemove remains in the mapping pool. If it succeeds, + nameToRemove is no longer available and needs to be removed + from the SAH mapping. If the write() _below_ fails, that + leaves us with a consistent world view. + + Discussion: bugs:432f260aa787a53 */ + this.#mapFilenameToSAH.delete(nameToRemove); + } sah.write(digest, {at: HEADER_OFFSET_DIGEST}); sah.flush(); @@ -20414,9 +20707,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ deletePath(path) { const sah = this.#mapFilenameToSAH.get(path); if(sah) { - // Un-associate the name from the SAH. - this.#mapFilenameToSAH.delete(path); - this.setAssociatedPath(sah, '', 0); + this.setAssociatedPath(sah, '', 0, path); } return !!sah; } @@ -20461,7 +20752,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ xOpen file object. */ getOFileForS3File(pFile){ - return this.#mapS3FileToOFile_.get(pFile); + return this.#mapS3FileToOFile.get(pFile); } /** Maps or unmaps (if file is falsy) the given (sqlite3_file*) @@ -20469,10 +20760,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ */ mapS3FileToOFile(pFile,file){ if(file){ - this.#mapS3FileToOFile_.set(pFile, file); + this.#mapS3FileToOFile.set(pFile, file); setPoolForPFile(pFile, this); }else{ - this.#mapS3FileToOFile_.delete(pFile); + this.#mapS3FileToOFile.delete(pFile); setPoolForPFile(pFile, false); } } @@ -20530,7 +20821,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ return true; } - /** "Pauses" this VFS by unregistering it from SQLite and relinquishing all open SAHs, leaving the associated files @@ -20552,7 +20842,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ @see unpauseVfs() */ pauseVfs(){ - if(this.#mapS3FileToOFile_.size>0){ + if(this.#mapS3FileToOFile.size>0){ sqlite3.SQLite3Error.toss( capi.SQLITE_MISUSE, "Cannot pause VFS", this.vfsName,"because it has opened files." @@ -20623,7 +20913,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ util.affirmDbHeader(chunk); checkedHeader = true; } - sah.write(chunk, {at: HEADER_OFFSET_DATA + nWrote}); + const n = sah.write(chunk, {at: HEADER_OFFSET_DATA + nWrote}); + if( n!==chunk.byteLength ){ + toss("Expected to write "+chunk.byteLength+ + "bytes but wrote"+n+"."); + } nWrote += chunk.byteLength; } if( nWrote < 512 || 0!==nWrote % 512 ){ @@ -20631,7 +20925,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ } if( !checkedHeader ){ const header = new Uint8Array(20); - sah.read( header, {at: 0} ); + sah.read( header, {at: HEADER_OFFSET_DATA} ); util.affirmDbHeader( header ); } sah.write(new Uint8Array([1,1]), { @@ -20649,24 +20943,19 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ importDb(name, bytes){ if( bytes instanceof ArrayBuffer ) bytes = new Uint8Array(bytes); else if( bytes instanceof Function ) return this.importDbChunked(name, bytes); + util.affirmIsDb(bytes); const sah = this.#mapFilenameToSAH.get(name) || this.nextAvailableSAH() || toss("No available handles to import to."); const n = bytes.byteLength; - if(n<512 || n%512!=0){ - toss("Byte array size is invalid for an SQLite db."); - } - const header = "SQLite format 3"; - for(let i = 0; i < header.length; ++i){ - if( header.charCodeAt(i) !== bytes[i] ){ - toss("Input does not contain an SQLite database header."); - } - } const nWrote = sah.write(bytes, {at: HEADER_OFFSET_DATA}); if(nWrote != n){ this.setAssociatedPath(sah, '', 0); toss("Expected to write "+n+" bytes but wrote "+nWrote+"."); }else{ + sah.truncate(HEADER_OFFSET_DATA + n + /* Ensure no trailing junk when overwriting an + existing file with a shorter one. */); sah.write(new Uint8Array([1,1]), {at: HEADER_OFFSET_DATA+18} /* force db out of WAL mode */); this.setAssociatedPath(sah, name, capi.SQLITE_OPEN_MAIN_DB); @@ -20674,8 +20963,72 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ return nWrote; } - }/*class OpfsSAHPool*/; + /** + Returns true if any (sqlite3_file*) currently opened by this + pool using the given client-provided file name (as distinct from + its opaque name) holds a RESERVED or greater lock, else false. + */ + hasReservedLock(filename){ + const lk = this.#mapPathToLock.get(filename); + return !!lk && lk.lockType>capi.SQLITE_LOCK_SHARED; + } + + /** + Implements xLock() for the given xOpen-generated file object. + This pool holds its SAHs exclusively, so its xOpen() represent + the only connections to a given file. The locks are held + separately from their file object in the same thread the same + way in which os_unix.c:unixLock() distinguishes multiple + connections of a single process which share an inode: a lock + which conflicts with another connection's lock fails with + SQLITE_BUSY, and a failed attempt to get from RESERVED to + EXCLUSIVE leaves a PENDING lock, which admits no new SHARED + locks. + */ + lockFile(file, lockType){ + if(file.lockType>=lockType) return 0; + let lk = this.#mapPathToLock.get(file.path); + if(!lk){ + lk = Object.assign(Object.create(null),{ + nShared: 0, lockType: capi.SQLITE_LOCK_NONE + }); + this.#mapPathToLock.set(file.path, lk); + } + if(file.lockType!==lk.lockType + && (lk.lockType>=capi.SQLITE_LOCK_PENDING + || lockType>capi.SQLITE_LOCK_SHARED)){ + return capi.SQLITE_BUSY; + } + if(lockType===capi.SQLITE_LOCK_SHARED){ + ++lk.nShared; + if(lk.lockType===capi.SQLITE_LOCK_NONE) lk.lockType = lockType; + }else if(lockType===capi.SQLITE_LOCK_EXCLUSIVE && lk.nShared>1){ + if(file.lockType===capi.SQLITE_LOCK_RESERVED){ + file.lockType = lk.lockType = capi.SQLITE_LOCK_PENDING; + } + return capi.SQLITE_BUSY; + }else{ + lk.lockType = lockType; + } + file.lockType = lockType; + return 0; + } + /** Implements xUnlock() for the given xOpen file object. */ + unlockFile(file, lockType){ + if(file.lockType<=lockType) return; + const lk = this.#mapPathToLock.get(file.path); + if(file.lockType>capi.SQLITE_LOCK_SHARED){ + lk.lockType = capi.SQLITE_LOCK_SHARED; + } + if(lockType===capi.SQLITE_LOCK_NONE && 0===--lk.nShared + /* Maintenance reminder: the && ordering is significant */){ + this.#mapPathToLock.delete(file.path); + } + file.lockType = lockType; + } + + }/*class OpfsSAHPool*/; /** A OpfsSAHPoolUtil instance is exposed to clients in order to @@ -20829,9 +21182,19 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ option is truthy _and_ the previous attempt to initialize this VFS with the same `name` failed, the VFS will attempt to initialize a second time instead of returning the cached - failure. See discussion at: + failure. See discussion at + - `preserveOnInitFailure`: (default=`false`) If truthy, + initialization failure unregisters and disposes of the VFS and + releases acquired handles without also deleting its storage. This + does not undo changes already made during initialization, + including `clearOnInit`. Otherwise, initialization failure + invokes this.removeVfs(), which attempts to delete the + pool. Retrying a cached initialization failure requires + `forceReinitIfPreviouslyFailed`. See discussion at + . + Peculiarities of this VFS vis a vis other SQLite VFSes: @@ -20868,16 +21231,17 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ - byteArray exportFile(name) - Synchronously reads the contents of the given file into a Uint8Array - and returns it. This will throw if the given name is not currently - in active use or on I/O error. Note that the given name is _not_ - visible directly in OPFS (or, if it is, it's not from this VFS). + Synchronously reads the contents of the given file into a + Uint8Array and returns it. This will throw if the given name is + not currently in active use or on I/O error. Because of how this + VFS maps names to storage, the given name is _not_ visible + directly in OPFS (or, if it is, it's not from this VFS). - number getCapacity() - Returns the number of files currently contained - in the SAH pool. The default capacity is only large enough for one - or two databases and their associated temp files. + Returns the number of files currently contained in the SAH + pool. The default capacity is only large enough for one or two + databases and their associated temp files. - number getFileCount() @@ -20894,11 +21258,14 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ Imports the contents of an SQLite database, provided as a byte array or ArrayBuffer, under the given name, overwriting any existing content. Throws if the pool has no available file slots, - on I/O error, or if the input does not appear to be a - database. In the latter case, only a cursory examination is made. + on I/O error, or if the input does not appear to be a database. + In the latter case, only a cursory examination is made to + determine whether the input is a db (and only in non-SEE builds, + as we cannot distinguish encrypted DBs from garbage input). + Results are undefined if the given db name refers to an opened - db. Note that this routine is _only_ for importing database - files, not arbitrary files, the reason being that this VFS will + db. This routine is _only_ for importing database files, not + arbitrary files, the reason being that this VFS will automatically clean up any non-database files so importing them is pointless. @@ -20913,7 +21280,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ called this way is the size of the resulting database. On success this routine rewrites the database header bytes in the - output file (not the input array) to force disabling of WAL mode. + output file (not the input array) to force disabling of WAL mode, + (A) for historical reasons and (B) getting WAL to work in this + build requires doing a (pragma locking_mode=exclusive) on the db + before using it. On a write error, the handle is removed from the pool and made available for re-use. @@ -21029,6 +21399,24 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ return (initPromises[vfsName] = Promise.reject(new Error("Missing required OPFS APIs."))); } + /** + An interal detail of OpfsSAHPool, called only by initPromises(). + + Unregisters and disposes of OpfsSAHPool thePool, releasing all + of its SAHs without deleting its files. Used when + initialization fails and the preserveOnInitFailure option is + set. This is a no-op if thePool.getVfs().pointer is falsy. Returns the + undefined value. + */ + const unregisterVfs = (thePool)=>{ + const cVfs = thePool.getVfs(); + if( cVfs?.pointer ){ + capi.sqlite3_vfs_unregister(cVfs.pointer); + cVfs.dispose(); + thePool.releaseAccessHandles(); + } + }; + /** Maintenance reminder: the order of ASYNC ops in this function is significant. We need to have them all chained at the very @@ -21066,7 +21454,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ thePool.log("VFS initialized."); return poolUtil; }).catch(async (e)=>{ - await thePool.removeVfs().catch(()=>{}); + if( options.preserveOnInitFailure ){ + unregisterVfs(thePool); + }else{ + await thePool.removeVfs().catch(()=>{}); + } throw e; }); }).catch((err)=>{ diff --git a/src/bin/sqlite3.wasm b/src/bin/sqlite3.wasm index 2ea991b..2be0556 100644 Binary files a/src/bin/sqlite3.wasm and b/src/bin/sqlite3.wasm differ diff --git a/src/index.d.ts b/src/index.d.ts index f0ff34a..f2b03ec 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -353,6 +353,17 @@ export class PreparedStatement { */ reset(alsoClearBinds?: boolean): this; + /** + * Resets the statement and returns the SQLite result code instead of throwing + * for a SQLite error. Retains bindings unless `alsoClearBinds` is truthy. + * Still throws if finalized or locked by a Database.exec() callback. + * Preserves OO1 bookkeeping; use this instead of calling sqlite3_reset() + * directly on an OO1 statement. + * + * @since SQLite 3.54 + */ + resetNoThrow(alsoClearBinds?: boolean): Sqlite3Result; + /** * Steps the statement one time. If the result indicates that a row of data is * available, a truthy value is returned. If no row of data is available, a @@ -1539,6 +1550,8 @@ export class WasmAllocError extends Error { /** Exception class used primarily by the oo1 API. */ export class SQLite3Error extends Error { constructor(message: string); + /** Creates an error with the given SQLite result code and its error text. */ + constructor(resultCode: number); resultCode: number; } @@ -2232,6 +2245,16 @@ export type Sqlite3Static = { */ clearOnInit?: boolean; + /** + * Defaults to false. On initialization failure, unregister the VFS and + * release acquired handles without deleting the pool's storage. This does + * not undo changes already made, including clearOnInit. Retrying a cached + * failure also requires forceReinitIfPreviouslyFailed. + * + * @since SQLite 3.54 + */ + preserveOnInitFailure?: boolean; + /** * (default=6) Specifies the default capacity of the VFS. * @@ -3647,6 +3670,43 @@ export type CAPI = { sqlite3_module: typeof sqlite3_module; sqlite3_index_info: typeof sqlite3_index_info; + /** + * Starts copying a database between distinct connections. Schema names are + * usually "main". Returns 0 on failure; inspect the destination's error code + * and message. On success, call sqlite3_backup_finish() exactly once, even + * when stepping fails. Do not otherwise use the destination connection until + * the backup has been finished. + * + * See https://sqlite.org/c3ref/backup_finish.html + * @since SQLite Wasm 3.54 + */ + sqlite3_backup_init: ( + dest: DbPtr, + destName: string | WasmPointer, + source: DbPtr, + sourceName: string | WasmPointer, + ) => WasmPointer; + + /** + * Copies up to pageCount pages, or all remaining pages if negative. Returns + * SQLITE_DONE when complete, SQLITE_OK when more pages remain, or an error + * code. SQLITE_BUSY and SQLITE_LOCKED can be retried later. + */ + sqlite3_backup_step: (backup: WasmPointer, pageCount: number) => Sqlite3Result; + + /** + * Releases and invalidates a backup handle, rolling back an incomplete copy. + * Returns SQLITE_OK or a prior fatal backup error; SQLITE_OK alone does not + * indicate that all pages were copied. + */ + sqlite3_backup_finish: (backup: WasmPointer) => Sqlite3Result; + + /** Returns the pages remaining as of the most recent backup_step() call. */ + sqlite3_backup_remaining: (backup: WasmPointer) => number; + + /** Returns the total source pages as of the most recent backup_step() call. */ + sqlite3_backup_pagecount: (backup: WasmPointer) => number; + /** * Returns a string corresponding to the {@link CAPI#SQLITE_VERSION} macro. * This function is provided for use in DLLs. @@ -4414,9 +4474,13 @@ export type CAPI = { | CAPI['SQLITE_LIMIT_VARIABLE_NUMBER'] | CAPI['SQLITE_LIMIT_TRIGGER_DEPTH'] | CAPI['SQLITE_LIMIT_WORKER_THREADS'] - | CAPI['SQLITE_LIMIT_PARSER_DEPTH'], + | CAPI['SQLITE_LIMIT_PARSER_DEPTH'] + /** SQLITE_LIMIT_SCHEMA: maximum number of schema objects (since 3.54). */ + | 13 + /** SQLITE_LIMIT_TRIGGER_STEPS: maximum statements per trigger (since 3.54). */ + | 14, newVal: number, - ) => Sqlite3Result; + ) => number; /** * Compiles a prepared statement. @@ -4644,6 +4708,13 @@ export type CAPI = { */ sqlite3_bind_null: (stmt: StmtPtr, idx: number) => Sqlite3Result; + /** + * Binds a BLOB of n bytes filled with zeroes at the 1-based parameter index. + * A negative length produces an empty BLOB. + * See https://sqlite.org/c3ref/bind_blob.html + */ + sqlite3_bind_zeroblob: (stmt: StmtPtr, idx: number, n: number) => Sqlite3Result; + /** * Bind a `TEXT` value to a parameter in a prepared statement. * @@ -6407,6 +6478,22 @@ export type CAPI = { esc: number, ) => Sqlite3Result; + /** + * Configures a virtual table from its xCreate() or xConnect() callback. + * The Wasm binding always requires three arguments. Pass 0 for options that + * ignore the third argument; CONSTRAINT_SUPPORT uses it as an enable flag. + * See https://sqlite.org/c3ref/vtab_config.html + */ + sqlite3_vtab_config: ( + db: DbPtr, + op: + | CAPI['SQLITE_VTAB_CONSTRAINT_SUPPORT'] + | CAPI['SQLITE_VTAB_INNOCUOUS'] + | CAPI['SQLITE_VTAB_DIRECTONLY'] + | CAPI['SQLITE_VTAB_USES_ALL_SCHEMAS'], + value: number, + ) => Sqlite3Result; + /** * Determine The Virtual Table Conflict Policy * @@ -7927,6 +8014,34 @@ export type CAPI = { */ sqlite3_js_db_uses_vfs: (db: DbPtr, vfsName: string, dbName: string) => boolean; + /** + * Calls a synchronous callback up to maxTimes total attempts. Retries when + * it returns SQLITE_BUSY or throws SQLite3Error with that resultCode. + * Returns any other result, propagates other errors, and throws SQLite3Error + * when attempts are exhausted. beforeRetry receives the attempt number + * starting at 2; its return value is ignored. No sleeping is performed. + * Returns undefined if maxTimes permits no attempts. + * + * @since SQLite 3.53 + */ + sqlite3_js_retry_busy: ( + maxTimes: number, + callback: () => T, + beforeRetry?: (attempt: number) => void, + ) => T | undefined; + + /** + * Converts flexible SQL input to a JS string; unsupported inputs yield + * undefined. Arrays are joined without separators, byte buffers are decoded + * as UTF-8, and WASM pointers refer to NUL-terminated strings. + * + * Known upstream issue in 3.54.1: non-string inputs throw ReferenceError + * because the implementation references an undefined variable. + * + * @since SQLite 3.44 + */ + sqlite3_js_sql_to_string: (sql: FlexibleString) => string | undefined; + /** Returns an array of the names of all currently-registered sqlite3 VFSes. */ sqlite3_js_vfs_list: () => string[]; @@ -8413,6 +8528,12 @@ export type CAPI = { SQLITE_DETERMINISTIC: 2048; SQLITE_DIRECTONLY: 524_288; SQLITE_INNOCUOUS: 2_097_152; + /** The function inspects argument subtypes with sqlite3_value_subtype(). */ + SQLITE_SUBTYPE: 1_048_576; + /** The function sets its result subtype with sqlite3_result_subtype(). */ + SQLITE_RESULT_SUBTYPE: 16_777_216; + /** The aggregate internally orders its first argument. */ + SQLITE_SELFORDER1: 33_554_432; SQLITE_VERSION_NUMBER: number; SQLITE_VERSION: string; SQLITE_SOURCE_ID: string;