diff --git a/.github/workflows/tools.yml b/.github/workflows/tools.yml index 638a0fc2142118..59c9d4bcd466e7 100644 --- a/.github/workflows/tools.yml +++ b/.github/workflows/tools.yml @@ -311,7 +311,7 @@ jobs: # no-op if the base branch is already up-to-date. with: token: ${{ secrets.GH_USER_TOKEN }} - branch: actions/tools-update-${{ matrix.id }} # Custom branch *just* for this Action. + branch: actions/${{ github.ref_name == 'main' || format('{0}/', github.ref_name) }}tools-update-${{ matrix.id }} # Custom branch *just* for this Action. delete-branch: true commit-message: ${{ env.COMMIT_MSG }} labels: ${{ matrix.label }} diff --git a/.gitignore b/.gitignore index 221e4f4062486a..234bc0e262fb93 100644 --- a/.gitignore +++ b/.gitignore @@ -158,6 +158,10 @@ cmake_install.cmake install_manifest.txt *.cbp +# === Rules for AI assistants === +CLAUDE.md +AGENTS.md + # === Global Rules === # Keep last to avoid being excluded *.pyc diff --git a/BUILDING.md b/BUILDING.md index 23d047563a64a7..b54a167b0f8940 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -97,7 +97,7 @@ and libc version. The table below lists the support tier for each supported combination. A list of [supported compile toolchains](#supported-toolchains) is also supplied for tier 1 platforms. -**For production applications, run Node.js on supported platforms only.** +**For production applications, run Node.js on supported platforms only (Tier 1 or 2).** Node.js does not support a platform version if a vendor has expired support for it. In other words, Node.js does not support running on End-of-Life (EoL) @@ -214,12 +214,11 @@ If compiling without one of the above, use `configure` with the ### Previous versions of this document Supported platforms and toolchains change with each major version of Node.js. -This document is only valid for the current major version of Node.js. -Consult previous versions of this document for older versions of Node.js: +This document is only valid for the current version of Node.js, and is expected +to be valid for the entire lifetime of this release line. -* [Node.js 24](https://github.com/nodejs/node/blob/v24.x/BUILDING.md) -* [Node.js 22](https://github.com/nodejs/node/blob/v22.x/BUILDING.md) -* [Node.js 20](https://github.com/nodejs/node/blob/v20.x/BUILDING.md) +To consult the version of this document for another version, download its source +tarball and/or browse the git repository checked out at the relevant tag. ## Building Node.js on supported platforms @@ -666,7 +665,7 @@ Refs: To install it, select the following two optional components: * C++ Clang Compiler for Windows (Microsoft.VisualStudio.Component.VC.Llvm.Clang) * MSBuild support for LLVM (clang-cl) toolset (Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset) -* As an alternative to Visual Studio 2026, download Visual Studio 2022 Current channel Version 17.4 from the +* As an alternative to Visual Studio 2026, download Visual Studio 2022 Current channel Version 17.14 from the [Evergreen bootstrappers](https://learn.microsoft.com/en-us/visualstudio/releases/2022/release-history#evergreen-bootstrappers) table and install using the same workload and optional component selection as described above. * Basic Unix tools required for some tests, diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 54296234a304d8..e22f23543e5ccc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -46,6 +46,7 @@ dependencies, and tools contained in the `nodejs/node` repository. * [Setting up your local environment](./doc/contributing/pull-requests.md#setting-up-your-local-environment) * [The Process of Making Changes](./doc/contributing/pull-requests.md#the-process-of-making-changes) * [Reviewing Pull Requests](./doc/contributing/pull-requests.md#reviewing-pull-requests) +* [Large Pull Requests](./doc/contributing/large-pull-requests.md) * [Notes](./doc/contributing/pull-requests.md#notes) ## Automation and bots diff --git a/LICENSE b/LICENSE index 403ea3c5717087..2842efa1288eef 100644 --- a/LICENSE +++ b/LICENSE @@ -996,208 +996,208 @@ The externally maintained libraries used by Node.js are: - LIEF, located at deps/LIEF, is licensed as follows: """ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2017 - 2025 R. Thomas - Copyright 2017 - 2025 Quarkslab - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2017 - 2025 R. Thomas + Copyright 2017 - 2025 Quarkslab + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. """ - llhttp, located at deps/llhttp, is licensed as follows: diff --git a/Makefile b/Makefile index 1dbb9f95206aa6..61380c5b824ea0 100644 --- a/Makefile +++ b/Makefile @@ -570,7 +570,7 @@ test-all-suites: | clear-stalled test-build bench-addons-build doc-only ## Run a $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) test/* JS_SUITES ?= default -NATIVE_SUITES ?= addons js-native-api node-api embedding +NATIVE_SUITES ?= addons ffi js-native-api node-api embedding # CI_* variables should be kept synchronized with the ones in vcbuild.bat CI_NATIVE_SUITES ?= $(NATIVE_SUITES) benchmark CI_JS_SUITES ?= $(JS_SUITES) pummel @@ -1384,7 +1384,7 @@ else LINT_MD_NEWER = -newer tools/.mdlintstamp endif -LINT_MD_TARGETS = doc src lib benchmark test tools/doc tools/icu $(wildcard *.md) +LINT_MD_TARGETS = doc src lib benchmark test tools/doc tools/icu $(filter-out CLAUDE.md AGENTS.md,$(wildcard *.md)) LINT_MD_FILES = $(shell $(FIND) $(LINT_MD_TARGETS) -type f \ ! -path '*node_modules*' ! -path 'test/fixtures/*' -name '*.md' \ $(LINT_MD_NEWER)) diff --git a/README.md b/README.md index c137f44f4b7a4e..c2012523eb199a 100644 --- a/README.md +++ b/README.md @@ -317,8 +317,6 @@ For information about the governance of the Node.js project, see **Daeyeon Jeong** <> (he/him) * [dario-piotrowicz](https://github.com/dario-piotrowicz) - **Dario Piotrowicz** <> (he/him) -* [debadree25](https://github.com/debadree25) - - **Debadree Chatterjee** <> (he/him) * [deokjinkim](https://github.com/deokjinkim) - **Deokjin Kim** <> (he/him) * [edsadr](https://github.com/edsadr) - @@ -365,8 +363,6 @@ For information about the governance of the Node.js project, see **James M Snell** <> (he/him) * [jazelly](https://github.com/jazelly) - **Jason Zhang** <> (he/him) -* [JonasBa](https://github.com/JonasBa) - - **Jonas Badalic** <> (he/him) * [joyeecheung](https://github.com/joyeecheung) - **Joyee Cheung** <> (she/her) * [juanarbol](https://github.com/juanarbol) - @@ -453,8 +449,6 @@ For information about the governance of the Node.js project, see **Vladimir Morozov** <> (he/him) * [watilde](https://github.com/watilde) - **Daijiro Wachi** <> (he/him) -* [zcbenz](https://github.com/zcbenz) - - **Cheng Zhao** <> (he/him) * [ZYSzys](https://github.com/ZYSzys) - **Yongsheng Zhang** <> (he/him) @@ -509,6 +503,8 @@ For information about the governance of the Node.js project, see **David Cai** <> (he/him) * [davisjam](https://github.com/davisjam) - **Jamie Davis** <> (he/him) +* [debadree25](https://github.com/debadree25) - + **Debadree Chatterjee** <> (he/him) * [devnexen](https://github.com/devnexen) - **David Carlier** <> * [devsnek](https://github.com/devsnek) - @@ -573,6 +569,8 @@ For information about the governance of the Node.js project, see **João Reis** <> * [joesepi](https://github.com/joesepi) - **Joe Sepi** <> (he/him) +* [JonasBa](https://github.com/JonasBa) - + **Jonas Badalic** <> (he/him) * [joshgav](https://github.com/joshgav) - **Josh Gavant** <> * [julianduque](https://github.com/julianduque) - @@ -733,6 +731,8 @@ For information about the governance of the Node.js project, see **Yorkie Liu** <> * [yosuke-furukawa](https://github.com/yosuke-furukawa) - **Yosuke Furukawa** <> +* [zcbenz](https://github.com/zcbenz) - + **Cheng Zhao** <> (he/him) @@ -745,38 +745,24 @@ maintaining the Node.js project. * [1ilsang](https://github.com/1ilsang) - **Sangchul Lee** <<1ilsang.dev@gmail.com>> (he/him) -* [atlowChemi](https://github.com/atlowChemi) - - **Chemi Atlow** <> (he/him) * [bjohansebas](https://github.com/bjohansebas) - **Sebastian Beltran** <> * [bmuenzenmeyer](https://github.com/bmuenzenmeyer) - **Brian Muenzenmeyer** <> (he/him) -* [CanadaHonk](https://github.com/CanadaHonk) - - **Oliver Medhurst** <> (they/them) -* [daeyeon](https://github.com/daeyeon) - - **Daeyeon Jeong** <> (he/him) * [efekrskl](https://github.com/efekrskl) - **Efe Karasakal** <> (he/him) * [gireeshpunathil](https://github.com/gireeshpunathil) - **Gireesh Punathil** <> (he/him) -* [gurgunday](https://github.com/gurgunday) - - **Gürgün Dayıoğlu** <> * [haramj](https://github.com/haramj) - **Haram Jeong** <> * [HBSPS](https://github.com/HBSPS) - **Wiyeong Seo** <> * [iam-frankqiu](https://github.com/iam-frankqiu) - **Frank Qiu** <> (he/him) -* [KevinEady](https://github.com/KevinEady) - - **Kevin Eady** <> (he/him) -* [marsonya](https://github.com/marsonya) - - **Akhil Marsonya** <> (he/him) * [milesguicent](https://github.com/milesguicent) - **Miles Guicent** <> (he/him) * [preveen-stack](https://github.com/preveen-stack) - **Preveen Padmanabhan** <> (he/him) -* [RaisinTen](https://github.com/RaisinTen) - - **Darshan Sen** <> (he/him) Triagers follow the [Triage Guide](./doc/contributing/issues.md#triaging-a-bug-report) when responding to new issues. diff --git a/common.gypi b/common.gypi index 6dd4674aa3aeba..fbf739ae58173d 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.49', + 'v8_embedder_string': '-node.50', ##### V8 defaults for Node.js ##### diff --git a/deps/simdjson/simdjson.cpp b/deps/simdjson/simdjson.cpp index cbcd9f1e6bc017..6fa9693596be0c 100644 --- a/deps/simdjson/simdjson.cpp +++ b/deps/simdjson/simdjson.cpp @@ -1,4 +1,4 @@ -/* auto-generated on 2026-04-03 15:25:03 -0400. version 4.6.1 Do not edit! */ +/* auto-generated on 2026-05-06 17:28:39 -0400. version 4.6.4 Do not edit! */ /* including simdjson.cpp: */ /* begin file simdjson.cpp */ #define SIMDJSON_SRC_SIMDJSON_CPP diff --git a/deps/simdjson/simdjson.h b/deps/simdjson/simdjson.h index 0a021531346106..b9befc5b17ed3c 100644 --- a/deps/simdjson/simdjson.h +++ b/deps/simdjson/simdjson.h @@ -1,4 +1,4 @@ -/* auto-generated on 2026-04-03 15:25:03 -0400. version 4.6.1 Do not edit! */ +/* auto-generated on 2026-05-06 17:28:39 -0400. version 4.6.4 Do not edit! */ /* including simdjson.h: */ /* begin file simdjson.h */ #ifndef SIMDJSON_H @@ -2538,7 +2538,7 @@ namespace std { #define SIMDJSON_SIMDJSON_VERSION_H /** The version of simdjson being used (major.minor.revision) */ -#define SIMDJSON_VERSION "4.6.1" +#define SIMDJSON_VERSION "4.6.4" namespace simdjson { enum { @@ -2553,7 +2553,7 @@ enum { /** * The revision (major.minor.REVISION) of simdjson being used. */ - SIMDJSON_VERSION_REVISION = 1 + SIMDJSON_VERSION_REVISION = 4 }; } // namespace simdjson @@ -39794,6 +39794,7 @@ simdjson_warn_unused simdjson_result extract_fractured_json( /* begin file simdjson/generic/builder/json_string_builder-inl.h for arm64 */ #include #include +#include #include #ifndef SIMDJSON_GENERIC_STRING_BUILDER_INL_H @@ -40549,6 +40550,11 @@ simdjson_inline void string_builder::append(number_type v) noexcept { simdjson_inline void string_builder::escape_and_append(std::string_view input) noexcept { // escaping might turn a control character into \x00xx so 6 characters. + // Guard against size_t overflow in the multiplication below. + if (input.size() > (std::numeric_limits::max)() / 6) { + set_valid(false); + return; + } if (capacity_check(6 * input.size())) { position += write_string_escaped(input, buffer.get() + position); } @@ -40557,6 +40563,11 @@ string_builder::escape_and_append(std::string_view input) noexcept { simdjson_inline void string_builder::escape_and_append_with_quotes(std::string_view input) noexcept { // escaping might turn a control character into \x00xx so 6 characters. + // Guard against size_t overflow in the arithmetic below. + if (input.size() > ((std::numeric_limits::max)() - 2) / 6) { + set_valid(false); + return; + } if (capacity_check(2 + 6 * input.size())) { buffer.get()[position++] = '"'; position += write_string_escaped(input, buffer.get() + position); @@ -41878,6 +41889,7 @@ simdjson_warn_unused simdjson_result extract_fractured_json( /* begin file simdjson/generic/builder/json_string_builder-inl.h for fallback */ #include #include +#include #include #ifndef SIMDJSON_GENERIC_STRING_BUILDER_INL_H @@ -42633,6 +42645,11 @@ simdjson_inline void string_builder::append(number_type v) noexcept { simdjson_inline void string_builder::escape_and_append(std::string_view input) noexcept { // escaping might turn a control character into \x00xx so 6 characters. + // Guard against size_t overflow in the multiplication below. + if (input.size() > (std::numeric_limits::max)() / 6) { + set_valid(false); + return; + } if (capacity_check(6 * input.size())) { position += write_string_escaped(input, buffer.get() + position); } @@ -42641,6 +42658,11 @@ string_builder::escape_and_append(std::string_view input) noexcept { simdjson_inline void string_builder::escape_and_append_with_quotes(std::string_view input) noexcept { // escaping might turn a control character into \x00xx so 6 characters. + // Guard against size_t overflow in the arithmetic below. + if (input.size() > ((std::numeric_limits::max)() - 2) / 6) { + set_valid(false); + return; + } if (capacity_check(2 + 6 * input.size())) { buffer.get()[position++] = '"'; position += write_string_escaped(input, buffer.get() + position); @@ -44449,6 +44471,7 @@ simdjson_warn_unused simdjson_result extract_fractured_json( /* begin file simdjson/generic/builder/json_string_builder-inl.h for haswell */ #include #include +#include #include #ifndef SIMDJSON_GENERIC_STRING_BUILDER_INL_H @@ -45204,6 +45227,11 @@ simdjson_inline void string_builder::append(number_type v) noexcept { simdjson_inline void string_builder::escape_and_append(std::string_view input) noexcept { // escaping might turn a control character into \x00xx so 6 characters. + // Guard against size_t overflow in the multiplication below. + if (input.size() > (std::numeric_limits::max)() / 6) { + set_valid(false); + return; + } if (capacity_check(6 * input.size())) { position += write_string_escaped(input, buffer.get() + position); } @@ -45212,6 +45240,11 @@ string_builder::escape_and_append(std::string_view input) noexcept { simdjson_inline void string_builder::escape_and_append_with_quotes(std::string_view input) noexcept { // escaping might turn a control character into \x00xx so 6 characters. + // Guard against size_t overflow in the arithmetic below. + if (input.size() > ((std::numeric_limits::max)() - 2) / 6) { + set_valid(false); + return; + } if (capacity_check(2 + 6 * input.size())) { buffer.get()[position++] = '"'; position += write_string_escaped(input, buffer.get() + position); @@ -47020,6 +47053,7 @@ simdjson_warn_unused simdjson_result extract_fractured_json( /* begin file simdjson/generic/builder/json_string_builder-inl.h for icelake */ #include #include +#include #include #ifndef SIMDJSON_GENERIC_STRING_BUILDER_INL_H @@ -47775,6 +47809,11 @@ simdjson_inline void string_builder::append(number_type v) noexcept { simdjson_inline void string_builder::escape_and_append(std::string_view input) noexcept { // escaping might turn a control character into \x00xx so 6 characters. + // Guard against size_t overflow in the multiplication below. + if (input.size() > (std::numeric_limits::max)() / 6) { + set_valid(false); + return; + } if (capacity_check(6 * input.size())) { position += write_string_escaped(input, buffer.get() + position); } @@ -47783,6 +47822,11 @@ string_builder::escape_and_append(std::string_view input) noexcept { simdjson_inline void string_builder::escape_and_append_with_quotes(std::string_view input) noexcept { // escaping might turn a control character into \x00xx so 6 characters. + // Guard against size_t overflow in the arithmetic below. + if (input.size() > ((std::numeric_limits::max)() - 2) / 6) { + set_valid(false); + return; + } if (capacity_check(2 + 6 * input.size())) { buffer.get()[position++] = '"'; position += write_string_escaped(input, buffer.get() + position); @@ -49706,6 +49750,7 @@ simdjson_warn_unused simdjson_result extract_fractured_json( /* begin file simdjson/generic/builder/json_string_builder-inl.h for ppc64 */ #include #include +#include #include #ifndef SIMDJSON_GENERIC_STRING_BUILDER_INL_H @@ -50461,6 +50506,11 @@ simdjson_inline void string_builder::append(number_type v) noexcept { simdjson_inline void string_builder::escape_and_append(std::string_view input) noexcept { // escaping might turn a control character into \x00xx so 6 characters. + // Guard against size_t overflow in the multiplication below. + if (input.size() > (std::numeric_limits::max)() / 6) { + set_valid(false); + return; + } if (capacity_check(6 * input.size())) { position += write_string_escaped(input, buffer.get() + position); } @@ -50469,6 +50519,11 @@ string_builder::escape_and_append(std::string_view input) noexcept { simdjson_inline void string_builder::escape_and_append_with_quotes(std::string_view input) noexcept { // escaping might turn a control character into \x00xx so 6 characters. + // Guard against size_t overflow in the arithmetic below. + if (input.size() > ((std::numeric_limits::max)() - 2) / 6) { + set_valid(false); + return; + } if (capacity_check(2 + 6 * input.size())) { buffer.get()[position++] = '"'; position += write_string_escaped(input, buffer.get() + position); @@ -52709,6 +52764,7 @@ simdjson_warn_unused simdjson_result extract_fractured_json( /* begin file simdjson/generic/builder/json_string_builder-inl.h for westmere */ #include #include +#include #include #ifndef SIMDJSON_GENERIC_STRING_BUILDER_INL_H @@ -53464,6 +53520,11 @@ simdjson_inline void string_builder::append(number_type v) noexcept { simdjson_inline void string_builder::escape_and_append(std::string_view input) noexcept { // escaping might turn a control character into \x00xx so 6 characters. + // Guard against size_t overflow in the multiplication below. + if (input.size() > (std::numeric_limits::max)() / 6) { + set_valid(false); + return; + } if (capacity_check(6 * input.size())) { position += write_string_escaped(input, buffer.get() + position); } @@ -53472,6 +53533,11 @@ string_builder::escape_and_append(std::string_view input) noexcept { simdjson_inline void string_builder::escape_and_append_with_quotes(std::string_view input) noexcept { // escaping might turn a control character into \x00xx so 6 characters. + // Guard against size_t overflow in the arithmetic below. + if (input.size() > ((std::numeric_limits::max)() - 2) / 6) { + set_valid(false); + return; + } if (capacity_check(2 + 6 * input.size())) { buffer.get()[position++] = '"'; position += write_string_escaped(input, buffer.get() + position); @@ -55186,6 +55252,7 @@ simdjson_warn_unused simdjson_result extract_fractured_json( /* begin file simdjson/generic/builder/json_string_builder-inl.h for lsx */ #include #include +#include #include #ifndef SIMDJSON_GENERIC_STRING_BUILDER_INL_H @@ -55941,6 +56008,11 @@ simdjson_inline void string_builder::append(number_type v) noexcept { simdjson_inline void string_builder::escape_and_append(std::string_view input) noexcept { // escaping might turn a control character into \x00xx so 6 characters. + // Guard against size_t overflow in the multiplication below. + if (input.size() > (std::numeric_limits::max)() / 6) { + set_valid(false); + return; + } if (capacity_check(6 * input.size())) { position += write_string_escaped(input, buffer.get() + position); } @@ -55949,6 +56021,11 @@ string_builder::escape_and_append(std::string_view input) noexcept { simdjson_inline void string_builder::escape_and_append_with_quotes(std::string_view input) noexcept { // escaping might turn a control character into \x00xx so 6 characters. + // Guard against size_t overflow in the arithmetic below. + if (input.size() > ((std::numeric_limits::max)() - 2) / 6) { + set_valid(false); + return; + } if (capacity_check(2 + 6 * input.size())) { buffer.get()[position++] = '"'; position += write_string_escaped(input, buffer.get() + position); @@ -57686,6 +57763,7 @@ simdjson_warn_unused simdjson_result extract_fractured_json( /* begin file simdjson/generic/builder/json_string_builder-inl.h for lasx */ #include #include +#include #include #ifndef SIMDJSON_GENERIC_STRING_BUILDER_INL_H @@ -58441,6 +58519,11 @@ simdjson_inline void string_builder::append(number_type v) noexcept { simdjson_inline void string_builder::escape_and_append(std::string_view input) noexcept { // escaping might turn a control character into \x00xx so 6 characters. + // Guard against size_t overflow in the multiplication below. + if (input.size() > (std::numeric_limits::max)() / 6) { + set_valid(false); + return; + } if (capacity_check(6 * input.size())) { position += write_string_escaped(input, buffer.get() + position); } @@ -58449,6 +58532,11 @@ string_builder::escape_and_append(std::string_view input) noexcept { simdjson_inline void string_builder::escape_and_append_with_quotes(std::string_view input) noexcept { // escaping might turn a control character into \x00xx so 6 characters. + // Guard against size_t overflow in the arithmetic below. + if (input.size() > ((std::numeric_limits::max)() - 2) / 6) { + set_valid(false); + return; + } if (capacity_check(2 + 6 * input.size())) { buffer.get()[position++] = '"'; position += write_string_escaped(input, buffer.get() + position); @@ -60190,6 +60278,7 @@ simdjson_warn_unused simdjson_result extract_fractured_json( /* begin file simdjson/generic/builder/json_string_builder-inl.h for rvv_vls */ #include #include +#include #include #ifndef SIMDJSON_GENERIC_STRING_BUILDER_INL_H @@ -60945,6 +61034,11 @@ simdjson_inline void string_builder::append(number_type v) noexcept { simdjson_inline void string_builder::escape_and_append(std::string_view input) noexcept { // escaping might turn a control character into \x00xx so 6 characters. + // Guard against size_t overflow in the multiplication below. + if (input.size() > (std::numeric_limits::max)() / 6) { + set_valid(false); + return; + } if (capacity_check(6 * input.size())) { position += write_string_escaped(input, buffer.get() + position); } @@ -60953,6 +61047,11 @@ string_builder::escape_and_append(std::string_view input) noexcept { simdjson_inline void string_builder::escape_and_append_with_quotes(std::string_view input) noexcept { // escaping might turn a control character into \x00xx so 6 characters. + // Guard against size_t overflow in the arithmetic below. + if (input.size() > ((std::numeric_limits::max)() - 2) / 6) { + set_valid(false); + return; + } if (capacity_check(2 + 6 * input.size())) { buffer.get()[position++] = '"'; position += write_string_escaped(input, buffer.get() + position); @@ -63512,13 +63611,21 @@ class value { simdjson_inline simdjson_result at_path(std::string_view at_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard character (*) for arrays or ".*" for objects. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; protected: /** @@ -63711,9 +63818,23 @@ struct simdjson_result : public arm64::implementation_si simdjson_inline simdjson_result current_depth() const noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; }; +// Forward-declare explicit specializations so MSVC /permissive- sees them before +// any template instantiation that would resolve element.get(val) to the primary. +template<> simdjson_inline error_code +simdjson_result::get( + arm64::ondemand::value &out) noexcept; +template<> simdjson_inline simdjson_result +simdjson_result::get() noexcept; + } // namespace simdjson #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H @@ -65052,8 +65173,6 @@ class parser { static simdjson_inline bool release_parser(); private: - friend bool release_parser(); - friend ondemand::parser& get_parser(); /** Get the thread-local parser instance, allocates it if needed */ static simdjson_inline simdjson_warn_unused std::unique_ptr& get_parser_instance(); /** Get the thread-local parser instance, it might be null */ @@ -65216,13 +65335,21 @@ class array { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like "[*]" to match all array elements. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the array and returns a string_view instance corresponding to the @@ -65346,7 +65473,13 @@ struct simdjson_result : public arm64::implementation_si simdjson_inline simdjson_result at(size_t index) noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; simdjson_inline simdjson_result raw_json() noexcept; #if SIMDJSON_SUPPORTS_CONCEPTS // TODO: move this code into object-inl.h @@ -66246,21 +66379,24 @@ class document { simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * * Supports wildcard patterns like "$.array[*]" or "$.object.*" to match multiple elements. * - * This method materializes all matching values into a vector. * The document will be consumed after this call. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern, or: - * - INVALID_JSON_POINTER if the JSONPath cannot be parsed - * - NO_SUCH_FIELD if a field does not exist - * - INDEX_OUT_OF_BOUNDS if an array index is out of bounds - * - INCORRECT_TYPE if path traversal encounters wrong type + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the document and returns a string_view instance corresponding to the @@ -66481,7 +66617,13 @@ class document_reference { simdjson_inline simdjson_result raw_json_token() noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; private: document *doc{nullptr}; @@ -66567,7 +66709,13 @@ struct simdjson_result : public arm64::implementation simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -66652,7 +66800,13 @@ struct simdjson_result : public arm64::impl simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -67305,13 +67459,21 @@ class object { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like ".*" to match all object fields. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Reset the iterator so that we are pointing back at the @@ -67461,7 +67623,13 @@ struct simdjson_result : public arm64::implementation_s simdjson_inline simdjson_result operator[](std::string_view key) && noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; inline simdjson_result reset() noexcept; inline simdjson_result is_empty() noexcept; inline simdjson_result count_fields() & noexcept; @@ -68475,46 +68643,34 @@ inline simdjson_result array::at_path(std::string_view json_path) noexcep return at_pointer(json_pointer); } -inline simdjson_result> array::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code array::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; // Wildcard case - if(key=="*"){ - for(auto element: *this){ - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - // Use value_unsafe() because we've already checked for errors above. - // The 'element' is a simdjson_result wrapper, and we need to extract - // the underlying value. value_unsafe() is safe here because error() returned false. - result.push_back(std::move(element).value_unsafe()); - - }else{ - auto nested_result = element.at_path_with_wildcard(remaining_path); - - if(nested_result.error()){ - return nested_result.error(); - } - // Same logic as above. - std::vector nested_matches = std::move(nested_result).value_unsafe(); - - result.insert(result.end(), - std::make_move_iterator(nested_matches.begin()), - std::make_move_iterator(nested_matches.end())); + if (key=="*"){ + for(auto element: *this) { + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()) { + callback(val); + } else { + error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback); + if(err) { return err; } } } - return result; - }else{ + return SUCCESS; + } else { // Specific index case in which we access the element at the given index - size_t idx=0; + size_t idx = 0; - for(char c:key){ + for (char c : key) { if(c < '0' || c > '9'){ return INVALID_JSON_POINTER; } @@ -68522,16 +68678,13 @@ inline simdjson_result> array::at_path_with_wildcard(std::str } auto element = at(idx); - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - result.push_back(std::move(element).value_unsafe()); - return result; - }else{ - return element.at_path_with_wildcard(remaining_path); + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()){ + callback(val); + return SUCCESS; + } else { + return element.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -68594,9 +68747,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } @@ -69017,14 +69176,20 @@ simdjson_inline simdjson_result value::at_path(std::string_view json_path } } -inline simdjson_result> value::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code value::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -69288,12 +69453,18 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard( - std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code simdjson_result::for_each_at_path_with_wildcard( + std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } } // namespace simdjson @@ -69669,8 +69840,14 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p } } -simdjson_inline simdjson_result> document::at_path_with_wildcard(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_path_with_wildcard is called +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { + rewind(); // Rewind the document each time for_each_at_path_with_wildcard is called if (json_path.empty()) { return INVALID_JSON_POINTER; } @@ -69678,9 +69855,9 @@ simdjson_inline simdjson_result> document::at_path_with_wildc SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -70017,9 +70194,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION @@ -70130,7 +70313,13 @@ simdjson_inline simdjson_result document_reference::get_number() noexcep simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result> document_reference::at_path_with_wildcard(std::string_view json_path) noexcept { return doc->at_path_with_wildcard(json_path); } +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document_reference::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { return doc->for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} simdjson_inline document_reference::operator document&() const noexcept { return *doc; } #if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_STATIC_REFLECTION @@ -70395,11 +70584,17 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION template @@ -71977,9 +72172,13 @@ inline simdjson_result object::at_path(std::string_view json_path) noexce return at_pointer(json_pointer); } -inline simdjson_result> object::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code object::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; @@ -71989,34 +72188,22 @@ inline simdjson_result> object::at_path_with_wildcard(std::st for (auto field : *this) { value val; SIMDJSON_TRY(field.value().get(val)); - if (remaining_path.empty()) { - result.push_back(std::move(val)); + callback(val); } else { - auto nested_result = val.at_path_with_wildcard(remaining_path); - - if (nested_result.error()) { - return nested_result.error(); - } - // Extract and append all nested matches to our result - std::vector nested_vec; - SIMDJSON_TRY(std::move(nested_result).get(nested_vec)); - - result.insert(result.end(), - std::make_move_iterator(nested_vec.begin()), - std::make_move_iterator(nested_vec.end())); + SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback)); } } - return result; + return SUCCESS; } else { value val; SIMDJSON_TRY(find_field(key).get(val)); if (remaining_path.empty()) { - result.push_back(std::move(val)); - return result; + callback(val); + return SUCCESS; } else { - return val.at_path_with_wildcard(remaining_path); + return val.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -72147,9 +72334,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } inline simdjson_result simdjson_result::reset() noexcept { @@ -72530,7 +72723,7 @@ simdjson_inline simdjson_warn_unused ondemand::parser& parser::get_parser() { return *parser::get_parser_instance(); } -simdjson_inline bool release_parser() { +simdjson_inline bool parser::release_parser() { auto &parser_instance = parser::get_threadlocal_parser_if_exists(); if (parser_instance) { parser_instance.reset(); @@ -76788,13 +76981,21 @@ class value { simdjson_inline simdjson_result at_path(std::string_view at_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard character (*) for arrays or ".*" for objects. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; protected: /** @@ -76987,9 +77188,23 @@ struct simdjson_result : public fallback::implementat simdjson_inline simdjson_result current_depth() const noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; }; +// Forward-declare explicit specializations so MSVC /permissive- sees them before +// any template instantiation that would resolve element.get(val) to the primary. +template<> simdjson_inline error_code +simdjson_result::get( + fallback::ondemand::value &out) noexcept; +template<> simdjson_inline simdjson_result +simdjson_result::get() noexcept; + } // namespace simdjson #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H @@ -78328,8 +78543,6 @@ class parser { static simdjson_inline bool release_parser(); private: - friend bool release_parser(); - friend ondemand::parser& get_parser(); /** Get the thread-local parser instance, allocates it if needed */ static simdjson_inline simdjson_warn_unused std::unique_ptr& get_parser_instance(); /** Get the thread-local parser instance, it might be null */ @@ -78492,13 +78705,21 @@ class array { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like "[*]" to match all array elements. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the array and returns a string_view instance corresponding to the @@ -78622,7 +78843,13 @@ struct simdjson_result : public fallback::implementat simdjson_inline simdjson_result at(size_t index) noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; simdjson_inline simdjson_result raw_json() noexcept; #if SIMDJSON_SUPPORTS_CONCEPTS // TODO: move this code into object-inl.h @@ -79522,21 +79749,24 @@ class document { simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * * Supports wildcard patterns like "$.array[*]" or "$.object.*" to match multiple elements. * - * This method materializes all matching values into a vector. * The document will be consumed after this call. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern, or: - * - INVALID_JSON_POINTER if the JSONPath cannot be parsed - * - NO_SUCH_FIELD if a field does not exist - * - INDEX_OUT_OF_BOUNDS if an array index is out of bounds - * - INCORRECT_TYPE if path traversal encounters wrong type + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the document and returns a string_view instance corresponding to the @@ -79757,7 +79987,13 @@ class document_reference { simdjson_inline simdjson_result raw_json_token() noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; private: document *doc{nullptr}; @@ -79843,7 +80079,13 @@ struct simdjson_result : public fallback::implemen simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -79928,7 +80170,13 @@ struct simdjson_result : public fallback simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -80581,13 +80829,21 @@ class object { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like ".*" to match all object fields. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Reset the iterator so that we are pointing back at the @@ -80737,7 +80993,13 @@ struct simdjson_result : public fallback::implementa simdjson_inline simdjson_result operator[](std::string_view key) && noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; inline simdjson_result reset() noexcept; inline simdjson_result is_empty() noexcept; inline simdjson_result count_fields() & noexcept; @@ -81751,46 +82013,34 @@ inline simdjson_result array::at_path(std::string_view json_path) noexcep return at_pointer(json_pointer); } -inline simdjson_result> array::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code array::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; // Wildcard case - if(key=="*"){ - for(auto element: *this){ - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - // Use value_unsafe() because we've already checked for errors above. - // The 'element' is a simdjson_result wrapper, and we need to extract - // the underlying value. value_unsafe() is safe here because error() returned false. - result.push_back(std::move(element).value_unsafe()); - - }else{ - auto nested_result = element.at_path_with_wildcard(remaining_path); - - if(nested_result.error()){ - return nested_result.error(); - } - // Same logic as above. - std::vector nested_matches = std::move(nested_result).value_unsafe(); - - result.insert(result.end(), - std::make_move_iterator(nested_matches.begin()), - std::make_move_iterator(nested_matches.end())); + if (key=="*"){ + for(auto element: *this) { + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()) { + callback(val); + } else { + error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback); + if(err) { return err; } } } - return result; - }else{ + return SUCCESS; + } else { // Specific index case in which we access the element at the given index - size_t idx=0; + size_t idx = 0; - for(char c:key){ + for (char c : key) { if(c < '0' || c > '9'){ return INVALID_JSON_POINTER; } @@ -81798,16 +82048,13 @@ inline simdjson_result> array::at_path_with_wildcard(std::str } auto element = at(idx); - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - result.push_back(std::move(element).value_unsafe()); - return result; - }else{ - return element.at_path_with_wildcard(remaining_path); + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()){ + callback(val); + return SUCCESS; + } else { + return element.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -81870,9 +82117,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } @@ -82293,14 +82546,20 @@ simdjson_inline simdjson_result value::at_path(std::string_view json_path } } -inline simdjson_result> value::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code value::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -82564,12 +82823,18 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard( - std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code simdjson_result::for_each_at_path_with_wildcard( + std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } } // namespace simdjson @@ -82945,8 +83210,14 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p } } -simdjson_inline simdjson_result> document::at_path_with_wildcard(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_path_with_wildcard is called +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { + rewind(); // Rewind the document each time for_each_at_path_with_wildcard is called if (json_path.empty()) { return INVALID_JSON_POINTER; } @@ -82954,9 +83225,9 @@ simdjson_inline simdjson_result> document::at_path_with_wildc SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -83293,9 +83564,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION @@ -83406,7 +83683,13 @@ simdjson_inline simdjson_result document_reference::get_number() noexcep simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result> document_reference::at_path_with_wildcard(std::string_view json_path) noexcept { return doc->at_path_with_wildcard(json_path); } +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document_reference::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { return doc->for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} simdjson_inline document_reference::operator document&() const noexcept { return *doc; } #if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_STATIC_REFLECTION @@ -83671,11 +83954,17 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION template @@ -85253,9 +85542,13 @@ inline simdjson_result object::at_path(std::string_view json_path) noexce return at_pointer(json_pointer); } -inline simdjson_result> object::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code object::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; @@ -85265,34 +85558,22 @@ inline simdjson_result> object::at_path_with_wildcard(std::st for (auto field : *this) { value val; SIMDJSON_TRY(field.value().get(val)); - if (remaining_path.empty()) { - result.push_back(std::move(val)); + callback(val); } else { - auto nested_result = val.at_path_with_wildcard(remaining_path); - - if (nested_result.error()) { - return nested_result.error(); - } - // Extract and append all nested matches to our result - std::vector nested_vec; - SIMDJSON_TRY(std::move(nested_result).get(nested_vec)); - - result.insert(result.end(), - std::make_move_iterator(nested_vec.begin()), - std::make_move_iterator(nested_vec.end())); + SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback)); } } - return result; + return SUCCESS; } else { value val; SIMDJSON_TRY(find_field(key).get(val)); if (remaining_path.empty()) { - result.push_back(std::move(val)); - return result; + callback(val); + return SUCCESS; } else { - return val.at_path_with_wildcard(remaining_path); + return val.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -85423,9 +85704,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } inline simdjson_result simdjson_result::reset() noexcept { @@ -85806,7 +86093,7 @@ simdjson_inline simdjson_warn_unused ondemand::parser& parser::get_parser() { return *parser::get_parser_instance(); } -simdjson_inline bool release_parser() { +simdjson_inline bool parser::release_parser() { auto &parser_instance = parser::get_threadlocal_parser_if_exists(); if (parser_instance) { parser_instance.reset(); @@ -90551,13 +90838,21 @@ class value { simdjson_inline simdjson_result at_path(std::string_view at_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard character (*) for arrays or ".*" for objects. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; protected: /** @@ -90750,9 +91045,23 @@ struct simdjson_result : public haswell::implementatio simdjson_inline simdjson_result current_depth() const noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; }; +// Forward-declare explicit specializations so MSVC /permissive- sees them before +// any template instantiation that would resolve element.get(val) to the primary. +template<> simdjson_inline error_code +simdjson_result::get( + haswell::ondemand::value &out) noexcept; +template<> simdjson_inline simdjson_result +simdjson_result::get() noexcept; + } // namespace simdjson #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H @@ -92091,8 +92400,6 @@ class parser { static simdjson_inline bool release_parser(); private: - friend bool release_parser(); - friend ondemand::parser& get_parser(); /** Get the thread-local parser instance, allocates it if needed */ static simdjson_inline simdjson_warn_unused std::unique_ptr& get_parser_instance(); /** Get the thread-local parser instance, it might be null */ @@ -92255,13 +92562,21 @@ class array { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like "[*]" to match all array elements. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the array and returns a string_view instance corresponding to the @@ -92385,7 +92700,13 @@ struct simdjson_result : public haswell::implementatio simdjson_inline simdjson_result at(size_t index) noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; simdjson_inline simdjson_result raw_json() noexcept; #if SIMDJSON_SUPPORTS_CONCEPTS // TODO: move this code into object-inl.h @@ -93285,21 +93606,24 @@ class document { simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * * Supports wildcard patterns like "$.array[*]" or "$.object.*" to match multiple elements. * - * This method materializes all matching values into a vector. * The document will be consumed after this call. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern, or: - * - INVALID_JSON_POINTER if the JSONPath cannot be parsed - * - NO_SUCH_FIELD if a field does not exist - * - INDEX_OUT_OF_BOUNDS if an array index is out of bounds - * - INCORRECT_TYPE if path traversal encounters wrong type + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the document and returns a string_view instance corresponding to the @@ -93520,7 +93844,13 @@ class document_reference { simdjson_inline simdjson_result raw_json_token() noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; private: document *doc{nullptr}; @@ -93606,7 +93936,13 @@ struct simdjson_result : public haswell::implementa simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -93691,7 +94027,13 @@ struct simdjson_result : public haswell:: simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -94344,13 +94686,21 @@ class object { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like ".*" to match all object fields. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Reset the iterator so that we are pointing back at the @@ -94500,7 +94850,13 @@ struct simdjson_result : public haswell::implementati simdjson_inline simdjson_result operator[](std::string_view key) && noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; inline simdjson_result reset() noexcept; inline simdjson_result is_empty() noexcept; inline simdjson_result count_fields() & noexcept; @@ -95514,46 +95870,34 @@ inline simdjson_result array::at_path(std::string_view json_path) noexcep return at_pointer(json_pointer); } -inline simdjson_result> array::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code array::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; // Wildcard case - if(key=="*"){ - for(auto element: *this){ - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - // Use value_unsafe() because we've already checked for errors above. - // The 'element' is a simdjson_result wrapper, and we need to extract - // the underlying value. value_unsafe() is safe here because error() returned false. - result.push_back(std::move(element).value_unsafe()); - - }else{ - auto nested_result = element.at_path_with_wildcard(remaining_path); - - if(nested_result.error()){ - return nested_result.error(); - } - // Same logic as above. - std::vector nested_matches = std::move(nested_result).value_unsafe(); - - result.insert(result.end(), - std::make_move_iterator(nested_matches.begin()), - std::make_move_iterator(nested_matches.end())); + if (key=="*"){ + for(auto element: *this) { + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()) { + callback(val); + } else { + error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback); + if(err) { return err; } } } - return result; - }else{ + return SUCCESS; + } else { // Specific index case in which we access the element at the given index - size_t idx=0; + size_t idx = 0; - for(char c:key){ + for (char c : key) { if(c < '0' || c > '9'){ return INVALID_JSON_POINTER; } @@ -95561,16 +95905,13 @@ inline simdjson_result> array::at_path_with_wildcard(std::str } auto element = at(idx); - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - result.push_back(std::move(element).value_unsafe()); - return result; - }else{ - return element.at_path_with_wildcard(remaining_path); + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()){ + callback(val); + return SUCCESS; + } else { + return element.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -95633,9 +95974,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } @@ -96056,14 +96403,20 @@ simdjson_inline simdjson_result value::at_path(std::string_view json_path } } -inline simdjson_result> value::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code value::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -96327,12 +96680,18 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard( - std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code simdjson_result::for_each_at_path_with_wildcard( + std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } } // namespace simdjson @@ -96708,8 +97067,14 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p } } -simdjson_inline simdjson_result> document::at_path_with_wildcard(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_path_with_wildcard is called +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { + rewind(); // Rewind the document each time for_each_at_path_with_wildcard is called if (json_path.empty()) { return INVALID_JSON_POINTER; } @@ -96717,9 +97082,9 @@ simdjson_inline simdjson_result> document::at_path_with_wildc SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -97056,9 +97421,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION @@ -97169,7 +97540,13 @@ simdjson_inline simdjson_result document_reference::get_number() noexcep simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result> document_reference::at_path_with_wildcard(std::string_view json_path) noexcept { return doc->at_path_with_wildcard(json_path); } +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document_reference::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { return doc->for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} simdjson_inline document_reference::operator document&() const noexcept { return *doc; } #if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_STATIC_REFLECTION @@ -97434,11 +97811,17 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION template @@ -99016,9 +99399,13 @@ inline simdjson_result object::at_path(std::string_view json_path) noexce return at_pointer(json_pointer); } -inline simdjson_result> object::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code object::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; @@ -99028,34 +99415,22 @@ inline simdjson_result> object::at_path_with_wildcard(std::st for (auto field : *this) { value val; SIMDJSON_TRY(field.value().get(val)); - if (remaining_path.empty()) { - result.push_back(std::move(val)); + callback(val); } else { - auto nested_result = val.at_path_with_wildcard(remaining_path); - - if (nested_result.error()) { - return nested_result.error(); - } - // Extract and append all nested matches to our result - std::vector nested_vec; - SIMDJSON_TRY(std::move(nested_result).get(nested_vec)); - - result.insert(result.end(), - std::make_move_iterator(nested_vec.begin()), - std::make_move_iterator(nested_vec.end())); + SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback)); } } - return result; + return SUCCESS; } else { value val; SIMDJSON_TRY(find_field(key).get(val)); if (remaining_path.empty()) { - result.push_back(std::move(val)); - return result; + callback(val); + return SUCCESS; } else { - return val.at_path_with_wildcard(remaining_path); + return val.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -99186,9 +99561,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } inline simdjson_result simdjson_result::reset() noexcept { @@ -99569,7 +99950,7 @@ simdjson_inline simdjson_warn_unused ondemand::parser& parser::get_parser() { return *parser::get_parser_instance(); } -simdjson_inline bool release_parser() { +simdjson_inline bool parser::release_parser() { auto &parser_instance = parser::get_threadlocal_parser_if_exists(); if (parser_instance) { parser_instance.reset(); @@ -104314,13 +104695,21 @@ class value { simdjson_inline simdjson_result at_path(std::string_view at_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard character (*) for arrays or ".*" for objects. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; protected: /** @@ -104513,9 +104902,23 @@ struct simdjson_result : public icelake::implementatio simdjson_inline simdjson_result current_depth() const noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; }; +// Forward-declare explicit specializations so MSVC /permissive- sees them before +// any template instantiation that would resolve element.get(val) to the primary. +template<> simdjson_inline error_code +simdjson_result::get( + icelake::ondemand::value &out) noexcept; +template<> simdjson_inline simdjson_result +simdjson_result::get() noexcept; + } // namespace simdjson #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H @@ -105854,8 +106257,6 @@ class parser { static simdjson_inline bool release_parser(); private: - friend bool release_parser(); - friend ondemand::parser& get_parser(); /** Get the thread-local parser instance, allocates it if needed */ static simdjson_inline simdjson_warn_unused std::unique_ptr& get_parser_instance(); /** Get the thread-local parser instance, it might be null */ @@ -106018,13 +106419,21 @@ class array { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like "[*]" to match all array elements. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the array and returns a string_view instance corresponding to the @@ -106148,7 +106557,13 @@ struct simdjson_result : public icelake::implementatio simdjson_inline simdjson_result at(size_t index) noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; simdjson_inline simdjson_result raw_json() noexcept; #if SIMDJSON_SUPPORTS_CONCEPTS // TODO: move this code into object-inl.h @@ -107048,21 +107463,24 @@ class document { simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * * Supports wildcard patterns like "$.array[*]" or "$.object.*" to match multiple elements. * - * This method materializes all matching values into a vector. * The document will be consumed after this call. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern, or: - * - INVALID_JSON_POINTER if the JSONPath cannot be parsed - * - NO_SUCH_FIELD if a field does not exist - * - INDEX_OUT_OF_BOUNDS if an array index is out of bounds - * - INCORRECT_TYPE if path traversal encounters wrong type + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the document and returns a string_view instance corresponding to the @@ -107283,7 +107701,13 @@ class document_reference { simdjson_inline simdjson_result raw_json_token() noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; private: document *doc{nullptr}; @@ -107369,7 +107793,13 @@ struct simdjson_result : public icelake::implementa simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -107454,7 +107884,13 @@ struct simdjson_result : public icelake:: simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -108107,13 +108543,21 @@ class object { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like ".*" to match all object fields. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Reset the iterator so that we are pointing back at the @@ -108263,7 +108707,13 @@ struct simdjson_result : public icelake::implementati simdjson_inline simdjson_result operator[](std::string_view key) && noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; inline simdjson_result reset() noexcept; inline simdjson_result is_empty() noexcept; inline simdjson_result count_fields() & noexcept; @@ -109277,46 +109727,34 @@ inline simdjson_result array::at_path(std::string_view json_path) noexcep return at_pointer(json_pointer); } -inline simdjson_result> array::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code array::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; // Wildcard case - if(key=="*"){ - for(auto element: *this){ - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - // Use value_unsafe() because we've already checked for errors above. - // The 'element' is a simdjson_result wrapper, and we need to extract - // the underlying value. value_unsafe() is safe here because error() returned false. - result.push_back(std::move(element).value_unsafe()); - - }else{ - auto nested_result = element.at_path_with_wildcard(remaining_path); - - if(nested_result.error()){ - return nested_result.error(); - } - // Same logic as above. - std::vector nested_matches = std::move(nested_result).value_unsafe(); - - result.insert(result.end(), - std::make_move_iterator(nested_matches.begin()), - std::make_move_iterator(nested_matches.end())); + if (key=="*"){ + for(auto element: *this) { + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()) { + callback(val); + } else { + error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback); + if(err) { return err; } } } - return result; - }else{ + return SUCCESS; + } else { // Specific index case in which we access the element at the given index - size_t idx=0; + size_t idx = 0; - for(char c:key){ + for (char c : key) { if(c < '0' || c > '9'){ return INVALID_JSON_POINTER; } @@ -109324,16 +109762,13 @@ inline simdjson_result> array::at_path_with_wildcard(std::str } auto element = at(idx); - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - result.push_back(std::move(element).value_unsafe()); - return result; - }else{ - return element.at_path_with_wildcard(remaining_path); + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()){ + callback(val); + return SUCCESS; + } else { + return element.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -109396,9 +109831,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } @@ -109819,14 +110260,20 @@ simdjson_inline simdjson_result value::at_path(std::string_view json_path } } -inline simdjson_result> value::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code value::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -110090,12 +110537,18 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard( - std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code simdjson_result::for_each_at_path_with_wildcard( + std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } } // namespace simdjson @@ -110471,8 +110924,14 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p } } -simdjson_inline simdjson_result> document::at_path_with_wildcard(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_path_with_wildcard is called +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { + rewind(); // Rewind the document each time for_each_at_path_with_wildcard is called if (json_path.empty()) { return INVALID_JSON_POINTER; } @@ -110480,9 +110939,9 @@ simdjson_inline simdjson_result> document::at_path_with_wildc SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -110819,9 +111278,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION @@ -110932,7 +111397,13 @@ simdjson_inline simdjson_result document_reference::get_number() noexcep simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result> document_reference::at_path_with_wildcard(std::string_view json_path) noexcept { return doc->at_path_with_wildcard(json_path); } +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document_reference::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { return doc->for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} simdjson_inline document_reference::operator document&() const noexcept { return *doc; } #if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_STATIC_REFLECTION @@ -111197,11 +111668,17 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION template @@ -112779,9 +113256,13 @@ inline simdjson_result object::at_path(std::string_view json_path) noexce return at_pointer(json_pointer); } -inline simdjson_result> object::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code object::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; @@ -112791,34 +113272,22 @@ inline simdjson_result> object::at_path_with_wildcard(std::st for (auto field : *this) { value val; SIMDJSON_TRY(field.value().get(val)); - if (remaining_path.empty()) { - result.push_back(std::move(val)); + callback(val); } else { - auto nested_result = val.at_path_with_wildcard(remaining_path); - - if (nested_result.error()) { - return nested_result.error(); - } - // Extract and append all nested matches to our result - std::vector nested_vec; - SIMDJSON_TRY(std::move(nested_result).get(nested_vec)); - - result.insert(result.end(), - std::make_move_iterator(nested_vec.begin()), - std::make_move_iterator(nested_vec.end())); + SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback)); } } - return result; + return SUCCESS; } else { value val; SIMDJSON_TRY(find_field(key).get(val)); if (remaining_path.empty()) { - result.push_back(std::move(val)); - return result; + callback(val); + return SUCCESS; } else { - return val.at_path_with_wildcard(remaining_path); + return val.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -112949,9 +113418,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } inline simdjson_result simdjson_result::reset() noexcept { @@ -113332,7 +113807,7 @@ simdjson_inline simdjson_warn_unused ondemand::parser& parser::get_parser() { return *parser::get_parser_instance(); } -simdjson_inline bool release_parser() { +simdjson_inline bool parser::release_parser() { auto &parser_instance = parser::get_threadlocal_parser_if_exists(); if (parser_instance) { parser_instance.reset(); @@ -118192,13 +118667,21 @@ class value { simdjson_inline simdjson_result at_path(std::string_view at_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard character (*) for arrays or ".*" for objects. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; protected: /** @@ -118391,9 +118874,23 @@ struct simdjson_result : public ppc64::implementation_si simdjson_inline simdjson_result current_depth() const noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; }; +// Forward-declare explicit specializations so MSVC /permissive- sees them before +// any template instantiation that would resolve element.get(val) to the primary. +template<> simdjson_inline error_code +simdjson_result::get( + ppc64::ondemand::value &out) noexcept; +template<> simdjson_inline simdjson_result +simdjson_result::get() noexcept; + } // namespace simdjson #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H @@ -119732,8 +120229,6 @@ class parser { static simdjson_inline bool release_parser(); private: - friend bool release_parser(); - friend ondemand::parser& get_parser(); /** Get the thread-local parser instance, allocates it if needed */ static simdjson_inline simdjson_warn_unused std::unique_ptr& get_parser_instance(); /** Get the thread-local parser instance, it might be null */ @@ -119896,13 +120391,21 @@ class array { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like "[*]" to match all array elements. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the array and returns a string_view instance corresponding to the @@ -120026,7 +120529,13 @@ struct simdjson_result : public ppc64::implementation_si simdjson_inline simdjson_result at(size_t index) noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; simdjson_inline simdjson_result raw_json() noexcept; #if SIMDJSON_SUPPORTS_CONCEPTS // TODO: move this code into object-inl.h @@ -120926,21 +121435,24 @@ class document { simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * * Supports wildcard patterns like "$.array[*]" or "$.object.*" to match multiple elements. * - * This method materializes all matching values into a vector. * The document will be consumed after this call. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern, or: - * - INVALID_JSON_POINTER if the JSONPath cannot be parsed - * - NO_SUCH_FIELD if a field does not exist - * - INDEX_OUT_OF_BOUNDS if an array index is out of bounds - * - INCORRECT_TYPE if path traversal encounters wrong type + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the document and returns a string_view instance corresponding to the @@ -121161,7 +121673,13 @@ class document_reference { simdjson_inline simdjson_result raw_json_token() noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; private: document *doc{nullptr}; @@ -121247,7 +121765,13 @@ struct simdjson_result : public ppc64::implementation simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -121332,7 +121856,13 @@ struct simdjson_result : public ppc64::impl simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -121985,13 +122515,21 @@ class object { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like ".*" to match all object fields. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Reset the iterator so that we are pointing back at the @@ -122141,7 +122679,13 @@ struct simdjson_result : public ppc64::implementation_s simdjson_inline simdjson_result operator[](std::string_view key) && noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; inline simdjson_result reset() noexcept; inline simdjson_result is_empty() noexcept; inline simdjson_result count_fields() & noexcept; @@ -123155,46 +123699,34 @@ inline simdjson_result array::at_path(std::string_view json_path) noexcep return at_pointer(json_pointer); } -inline simdjson_result> array::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code array::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; // Wildcard case - if(key=="*"){ - for(auto element: *this){ - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - // Use value_unsafe() because we've already checked for errors above. - // The 'element' is a simdjson_result wrapper, and we need to extract - // the underlying value. value_unsafe() is safe here because error() returned false. - result.push_back(std::move(element).value_unsafe()); - - }else{ - auto nested_result = element.at_path_with_wildcard(remaining_path); - - if(nested_result.error()){ - return nested_result.error(); - } - // Same logic as above. - std::vector nested_matches = std::move(nested_result).value_unsafe(); - - result.insert(result.end(), - std::make_move_iterator(nested_matches.begin()), - std::make_move_iterator(nested_matches.end())); + if (key=="*"){ + for(auto element: *this) { + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()) { + callback(val); + } else { + error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback); + if(err) { return err; } } } - return result; - }else{ + return SUCCESS; + } else { // Specific index case in which we access the element at the given index - size_t idx=0; + size_t idx = 0; - for(char c:key){ + for (char c : key) { if(c < '0' || c > '9'){ return INVALID_JSON_POINTER; } @@ -123202,16 +123734,13 @@ inline simdjson_result> array::at_path_with_wildcard(std::str } auto element = at(idx); - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - result.push_back(std::move(element).value_unsafe()); - return result; - }else{ - return element.at_path_with_wildcard(remaining_path); + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()){ + callback(val); + return SUCCESS; + } else { + return element.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -123274,9 +123803,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } @@ -123697,14 +124232,20 @@ simdjson_inline simdjson_result value::at_path(std::string_view json_path } } -inline simdjson_result> value::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code value::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -123968,12 +124509,18 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard( - std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code simdjson_result::for_each_at_path_with_wildcard( + std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } } // namespace simdjson @@ -124349,8 +124896,14 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p } } -simdjson_inline simdjson_result> document::at_path_with_wildcard(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_path_with_wildcard is called +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { + rewind(); // Rewind the document each time for_each_at_path_with_wildcard is called if (json_path.empty()) { return INVALID_JSON_POINTER; } @@ -124358,9 +124911,9 @@ simdjson_inline simdjson_result> document::at_path_with_wildc SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -124697,9 +125250,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION @@ -124810,7 +125369,13 @@ simdjson_inline simdjson_result document_reference::get_number() noexcep simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result> document_reference::at_path_with_wildcard(std::string_view json_path) noexcept { return doc->at_path_with_wildcard(json_path); } +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document_reference::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { return doc->for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} simdjson_inline document_reference::operator document&() const noexcept { return *doc; } #if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_STATIC_REFLECTION @@ -125075,11 +125640,17 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION template @@ -126657,9 +127228,13 @@ inline simdjson_result object::at_path(std::string_view json_path) noexce return at_pointer(json_pointer); } -inline simdjson_result> object::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code object::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; @@ -126669,34 +127244,22 @@ inline simdjson_result> object::at_path_with_wildcard(std::st for (auto field : *this) { value val; SIMDJSON_TRY(field.value().get(val)); - if (remaining_path.empty()) { - result.push_back(std::move(val)); + callback(val); } else { - auto nested_result = val.at_path_with_wildcard(remaining_path); - - if (nested_result.error()) { - return nested_result.error(); - } - // Extract and append all nested matches to our result - std::vector nested_vec; - SIMDJSON_TRY(std::move(nested_result).get(nested_vec)); - - result.insert(result.end(), - std::make_move_iterator(nested_vec.begin()), - std::make_move_iterator(nested_vec.end())); + SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback)); } } - return result; + return SUCCESS; } else { value val; SIMDJSON_TRY(find_field(key).get(val)); if (remaining_path.empty()) { - result.push_back(std::move(val)); - return result; + callback(val); + return SUCCESS; } else { - return val.at_path_with_wildcard(remaining_path); + return val.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -126827,9 +127390,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } inline simdjson_result simdjson_result::reset() noexcept { @@ -127210,7 +127779,7 @@ simdjson_inline simdjson_warn_unused ondemand::parser& parser::get_parser() { return *parser::get_parser_instance(); } -simdjson_inline bool release_parser() { +simdjson_inline bool parser::release_parser() { auto &parser_instance = parser::get_threadlocal_parser_if_exists(); if (parser_instance) { parser_instance.reset(); @@ -132387,13 +132956,21 @@ class value { simdjson_inline simdjson_result at_path(std::string_view at_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard character (*) for arrays or ".*" for objects. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; protected: /** @@ -132586,9 +133163,23 @@ struct simdjson_result : public westmere::implementat simdjson_inline simdjson_result current_depth() const noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; }; +// Forward-declare explicit specializations so MSVC /permissive- sees them before +// any template instantiation that would resolve element.get(val) to the primary. +template<> simdjson_inline error_code +simdjson_result::get( + westmere::ondemand::value &out) noexcept; +template<> simdjson_inline simdjson_result +simdjson_result::get() noexcept; + } // namespace simdjson #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H @@ -133927,8 +134518,6 @@ class parser { static simdjson_inline bool release_parser(); private: - friend bool release_parser(); - friend ondemand::parser& get_parser(); /** Get the thread-local parser instance, allocates it if needed */ static simdjson_inline simdjson_warn_unused std::unique_ptr& get_parser_instance(); /** Get the thread-local parser instance, it might be null */ @@ -134091,13 +134680,21 @@ class array { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like "[*]" to match all array elements. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the array and returns a string_view instance corresponding to the @@ -134221,7 +134818,13 @@ struct simdjson_result : public westmere::implementat simdjson_inline simdjson_result at(size_t index) noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; simdjson_inline simdjson_result raw_json() noexcept; #if SIMDJSON_SUPPORTS_CONCEPTS // TODO: move this code into object-inl.h @@ -135121,21 +135724,24 @@ class document { simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * * Supports wildcard patterns like "$.array[*]" or "$.object.*" to match multiple elements. * - * This method materializes all matching values into a vector. * The document will be consumed after this call. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern, or: - * - INVALID_JSON_POINTER if the JSONPath cannot be parsed - * - NO_SUCH_FIELD if a field does not exist - * - INDEX_OUT_OF_BOUNDS if an array index is out of bounds - * - INCORRECT_TYPE if path traversal encounters wrong type + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the document and returns a string_view instance corresponding to the @@ -135356,7 +135962,13 @@ class document_reference { simdjson_inline simdjson_result raw_json_token() noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; private: document *doc{nullptr}; @@ -135442,7 +136054,13 @@ struct simdjson_result : public westmere::implemen simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -135527,7 +136145,13 @@ struct simdjson_result : public westmere simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -136180,13 +136804,21 @@ class object { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like ".*" to match all object fields. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Reset the iterator so that we are pointing back at the @@ -136336,7 +136968,13 @@ struct simdjson_result : public westmere::implementa simdjson_inline simdjson_result operator[](std::string_view key) && noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; inline simdjson_result reset() noexcept; inline simdjson_result is_empty() noexcept; inline simdjson_result count_fields() & noexcept; @@ -137350,46 +137988,34 @@ inline simdjson_result array::at_path(std::string_view json_path) noexcep return at_pointer(json_pointer); } -inline simdjson_result> array::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code array::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; // Wildcard case - if(key=="*"){ - for(auto element: *this){ - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - // Use value_unsafe() because we've already checked for errors above. - // The 'element' is a simdjson_result wrapper, and we need to extract - // the underlying value. value_unsafe() is safe here because error() returned false. - result.push_back(std::move(element).value_unsafe()); - - }else{ - auto nested_result = element.at_path_with_wildcard(remaining_path); - - if(nested_result.error()){ - return nested_result.error(); - } - // Same logic as above. - std::vector nested_matches = std::move(nested_result).value_unsafe(); - - result.insert(result.end(), - std::make_move_iterator(nested_matches.begin()), - std::make_move_iterator(nested_matches.end())); + if (key=="*"){ + for(auto element: *this) { + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()) { + callback(val); + } else { + error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback); + if(err) { return err; } } } - return result; - }else{ + return SUCCESS; + } else { // Specific index case in which we access the element at the given index - size_t idx=0; + size_t idx = 0; - for(char c:key){ + for (char c : key) { if(c < '0' || c > '9'){ return INVALID_JSON_POINTER; } @@ -137397,16 +138023,13 @@ inline simdjson_result> array::at_path_with_wildcard(std::str } auto element = at(idx); - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - result.push_back(std::move(element).value_unsafe()); - return result; - }else{ - return element.at_path_with_wildcard(remaining_path); + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()){ + callback(val); + return SUCCESS; + } else { + return element.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -137469,9 +138092,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } @@ -137892,14 +138521,20 @@ simdjson_inline simdjson_result value::at_path(std::string_view json_path } } -inline simdjson_result> value::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code value::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -138163,12 +138798,18 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard( - std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code simdjson_result::for_each_at_path_with_wildcard( + std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } } // namespace simdjson @@ -138544,8 +139185,14 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p } } -simdjson_inline simdjson_result> document::at_path_with_wildcard(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_path_with_wildcard is called +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { + rewind(); // Rewind the document each time for_each_at_path_with_wildcard is called if (json_path.empty()) { return INVALID_JSON_POINTER; } @@ -138553,9 +139200,9 @@ simdjson_inline simdjson_result> document::at_path_with_wildc SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -138892,9 +139539,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION @@ -139005,7 +139658,13 @@ simdjson_inline simdjson_result document_reference::get_number() noexcep simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result> document_reference::at_path_with_wildcard(std::string_view json_path) noexcept { return doc->at_path_with_wildcard(json_path); } +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document_reference::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { return doc->for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} simdjson_inline document_reference::operator document&() const noexcept { return *doc; } #if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_STATIC_REFLECTION @@ -139270,11 +139929,17 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION template @@ -140852,9 +141517,13 @@ inline simdjson_result object::at_path(std::string_view json_path) noexce return at_pointer(json_pointer); } -inline simdjson_result> object::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code object::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; @@ -140864,34 +141533,22 @@ inline simdjson_result> object::at_path_with_wildcard(std::st for (auto field : *this) { value val; SIMDJSON_TRY(field.value().get(val)); - if (remaining_path.empty()) { - result.push_back(std::move(val)); + callback(val); } else { - auto nested_result = val.at_path_with_wildcard(remaining_path); - - if (nested_result.error()) { - return nested_result.error(); - } - // Extract and append all nested matches to our result - std::vector nested_vec; - SIMDJSON_TRY(std::move(nested_result).get(nested_vec)); - - result.insert(result.end(), - std::make_move_iterator(nested_vec.begin()), - std::make_move_iterator(nested_vec.end())); + SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback)); } } - return result; + return SUCCESS; } else { value val; SIMDJSON_TRY(find_field(key).get(val)); if (remaining_path.empty()) { - result.push_back(std::move(val)); - return result; + callback(val); + return SUCCESS; } else { - return val.at_path_with_wildcard(remaining_path); + return val.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -141022,9 +141679,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } inline simdjson_result simdjson_result::reset() noexcept { @@ -141405,7 +142068,7 @@ simdjson_inline simdjson_warn_unused ondemand::parser& parser::get_parser() { return *parser::get_parser_instance(); } -simdjson_inline bool release_parser() { +simdjson_inline bool parser::release_parser() { auto &parser_instance = parser::get_threadlocal_parser_if_exists(); if (parser_instance) { parser_instance.reset(); @@ -146056,13 +146719,21 @@ class value { simdjson_inline simdjson_result at_path(std::string_view at_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard character (*) for arrays or ".*" for objects. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; protected: /** @@ -146255,9 +146926,23 @@ struct simdjson_result : public lsx::implementation_simdjs simdjson_inline simdjson_result current_depth() const noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; }; +// Forward-declare explicit specializations so MSVC /permissive- sees them before +// any template instantiation that would resolve element.get(val) to the primary. +template<> simdjson_inline error_code +simdjson_result::get( + lsx::ondemand::value &out) noexcept; +template<> simdjson_inline simdjson_result +simdjson_result::get() noexcept; + } // namespace simdjson #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H @@ -147596,8 +148281,6 @@ class parser { static simdjson_inline bool release_parser(); private: - friend bool release_parser(); - friend ondemand::parser& get_parser(); /** Get the thread-local parser instance, allocates it if needed */ static simdjson_inline simdjson_warn_unused std::unique_ptr& get_parser_instance(); /** Get the thread-local parser instance, it might be null */ @@ -147760,13 +148443,21 @@ class array { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like "[*]" to match all array elements. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the array and returns a string_view instance corresponding to the @@ -147890,7 +148581,13 @@ struct simdjson_result : public lsx::implementation_simdjs simdjson_inline simdjson_result at(size_t index) noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; simdjson_inline simdjson_result raw_json() noexcept; #if SIMDJSON_SUPPORTS_CONCEPTS // TODO: move this code into object-inl.h @@ -148790,21 +149487,24 @@ class document { simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * * Supports wildcard patterns like "$.array[*]" or "$.object.*" to match multiple elements. * - * This method materializes all matching values into a vector. * The document will be consumed after this call. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern, or: - * - INVALID_JSON_POINTER if the JSONPath cannot be parsed - * - NO_SUCH_FIELD if a field does not exist - * - INDEX_OUT_OF_BOUNDS if an array index is out of bounds - * - INCORRECT_TYPE if path traversal encounters wrong type + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the document and returns a string_view instance corresponding to the @@ -149025,7 +149725,13 @@ class document_reference { simdjson_inline simdjson_result raw_json_token() noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; private: document *doc{nullptr}; @@ -149111,7 +149817,13 @@ struct simdjson_result : public lsx::implementation_sim simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -149196,7 +149908,13 @@ struct simdjson_result : public lsx::implemen simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -149849,13 +150567,21 @@ class object { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like ".*" to match all object fields. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Reset the iterator so that we are pointing back at the @@ -150005,7 +150731,13 @@ struct simdjson_result : public lsx::implementation_simdj simdjson_inline simdjson_result operator[](std::string_view key) && noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; inline simdjson_result reset() noexcept; inline simdjson_result is_empty() noexcept; inline simdjson_result count_fields() & noexcept; @@ -151019,46 +151751,34 @@ inline simdjson_result array::at_path(std::string_view json_path) noexcep return at_pointer(json_pointer); } -inline simdjson_result> array::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code array::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; // Wildcard case - if(key=="*"){ - for(auto element: *this){ - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - // Use value_unsafe() because we've already checked for errors above. - // The 'element' is a simdjson_result wrapper, and we need to extract - // the underlying value. value_unsafe() is safe here because error() returned false. - result.push_back(std::move(element).value_unsafe()); - - }else{ - auto nested_result = element.at_path_with_wildcard(remaining_path); - - if(nested_result.error()){ - return nested_result.error(); - } - // Same logic as above. - std::vector nested_matches = std::move(nested_result).value_unsafe(); - - result.insert(result.end(), - std::make_move_iterator(nested_matches.begin()), - std::make_move_iterator(nested_matches.end())); + if (key=="*"){ + for(auto element: *this) { + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()) { + callback(val); + } else { + error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback); + if(err) { return err; } } } - return result; - }else{ + return SUCCESS; + } else { // Specific index case in which we access the element at the given index - size_t idx=0; + size_t idx = 0; - for(char c:key){ + for (char c : key) { if(c < '0' || c > '9'){ return INVALID_JSON_POINTER; } @@ -151066,16 +151786,13 @@ inline simdjson_result> array::at_path_with_wildcard(std::str } auto element = at(idx); - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - result.push_back(std::move(element).value_unsafe()); - return result; - }else{ - return element.at_path_with_wildcard(remaining_path); + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()){ + callback(val); + return SUCCESS; + } else { + return element.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -151138,9 +151855,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } @@ -151561,14 +152284,20 @@ simdjson_inline simdjson_result value::at_path(std::string_view json_path } } -inline simdjson_result> value::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code value::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -151832,12 +152561,18 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard( - std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code simdjson_result::for_each_at_path_with_wildcard( + std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } } // namespace simdjson @@ -152213,8 +152948,14 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p } } -simdjson_inline simdjson_result> document::at_path_with_wildcard(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_path_with_wildcard is called +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { + rewind(); // Rewind the document each time for_each_at_path_with_wildcard is called if (json_path.empty()) { return INVALID_JSON_POINTER; } @@ -152222,9 +152963,9 @@ simdjson_inline simdjson_result> document::at_path_with_wildc SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -152561,9 +153302,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION @@ -152674,7 +153421,13 @@ simdjson_inline simdjson_result document_reference::get_number() noexcep simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result> document_reference::at_path_with_wildcard(std::string_view json_path) noexcept { return doc->at_path_with_wildcard(json_path); } +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document_reference::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { return doc->for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} simdjson_inline document_reference::operator document&() const noexcept { return *doc; } #if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_STATIC_REFLECTION @@ -152939,11 +153692,17 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION template @@ -154521,9 +155280,13 @@ inline simdjson_result object::at_path(std::string_view json_path) noexce return at_pointer(json_pointer); } -inline simdjson_result> object::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code object::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; @@ -154533,34 +155296,22 @@ inline simdjson_result> object::at_path_with_wildcard(std::st for (auto field : *this) { value val; SIMDJSON_TRY(field.value().get(val)); - if (remaining_path.empty()) { - result.push_back(std::move(val)); + callback(val); } else { - auto nested_result = val.at_path_with_wildcard(remaining_path); - - if (nested_result.error()) { - return nested_result.error(); - } - // Extract and append all nested matches to our result - std::vector nested_vec; - SIMDJSON_TRY(std::move(nested_result).get(nested_vec)); - - result.insert(result.end(), - std::make_move_iterator(nested_vec.begin()), - std::make_move_iterator(nested_vec.end())); + SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback)); } } - return result; + return SUCCESS; } else { value val; SIMDJSON_TRY(find_field(key).get(val)); if (remaining_path.empty()) { - result.push_back(std::move(val)); - return result; + callback(val); + return SUCCESS; } else { - return val.at_path_with_wildcard(remaining_path); + return val.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -154691,9 +155442,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } inline simdjson_result simdjson_result::reset() noexcept { @@ -155074,7 +155831,7 @@ simdjson_inline simdjson_warn_unused ondemand::parser& parser::get_parser() { return *parser::get_parser_instance(); } -simdjson_inline bool release_parser() { +simdjson_inline bool parser::release_parser() { auto &parser_instance = parser::get_threadlocal_parser_if_exists(); if (parser_instance) { parser_instance.reset(); @@ -159748,13 +160505,21 @@ class value { simdjson_inline simdjson_result at_path(std::string_view at_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard character (*) for arrays or ".*" for objects. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; protected: /** @@ -159947,9 +160712,23 @@ struct simdjson_result : public lasx::implementation_simd simdjson_inline simdjson_result current_depth() const noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; }; +// Forward-declare explicit specializations so MSVC /permissive- sees them before +// any template instantiation that would resolve element.get(val) to the primary. +template<> simdjson_inline error_code +simdjson_result::get( + lasx::ondemand::value &out) noexcept; +template<> simdjson_inline simdjson_result +simdjson_result::get() noexcept; + } // namespace simdjson #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H @@ -161288,8 +162067,6 @@ class parser { static simdjson_inline bool release_parser(); private: - friend bool release_parser(); - friend ondemand::parser& get_parser(); /** Get the thread-local parser instance, allocates it if needed */ static simdjson_inline simdjson_warn_unused std::unique_ptr& get_parser_instance(); /** Get the thread-local parser instance, it might be null */ @@ -161452,13 +162229,21 @@ class array { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like "[*]" to match all array elements. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the array and returns a string_view instance corresponding to the @@ -161582,7 +162367,13 @@ struct simdjson_result : public lasx::implementation_simd simdjson_inline simdjson_result at(size_t index) noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; simdjson_inline simdjson_result raw_json() noexcept; #if SIMDJSON_SUPPORTS_CONCEPTS // TODO: move this code into object-inl.h @@ -162482,21 +163273,24 @@ class document { simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * * Supports wildcard patterns like "$.array[*]" or "$.object.*" to match multiple elements. * - * This method materializes all matching values into a vector. * The document will be consumed after this call. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern, or: - * - INVALID_JSON_POINTER if the JSONPath cannot be parsed - * - NO_SUCH_FIELD if a field does not exist - * - INDEX_OUT_OF_BOUNDS if an array index is out of bounds - * - INCORRECT_TYPE if path traversal encounters wrong type + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the document and returns a string_view instance corresponding to the @@ -162717,7 +163511,13 @@ class document_reference { simdjson_inline simdjson_result raw_json_token() noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; private: document *doc{nullptr}; @@ -162803,7 +163603,13 @@ struct simdjson_result : public lasx::implementation_s simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -162888,7 +163694,13 @@ struct simdjson_result : public lasx::implem simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -163541,13 +164353,21 @@ class object { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like ".*" to match all object fields. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Reset the iterator so that we are pointing back at the @@ -163697,7 +164517,13 @@ struct simdjson_result : public lasx::implementation_sim simdjson_inline simdjson_result operator[](std::string_view key) && noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; inline simdjson_result reset() noexcept; inline simdjson_result is_empty() noexcept; inline simdjson_result count_fields() & noexcept; @@ -164711,46 +165537,34 @@ inline simdjson_result array::at_path(std::string_view json_path) noexcep return at_pointer(json_pointer); } -inline simdjson_result> array::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code array::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; // Wildcard case - if(key=="*"){ - for(auto element: *this){ - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - // Use value_unsafe() because we've already checked for errors above. - // The 'element' is a simdjson_result wrapper, and we need to extract - // the underlying value. value_unsafe() is safe here because error() returned false. - result.push_back(std::move(element).value_unsafe()); - - }else{ - auto nested_result = element.at_path_with_wildcard(remaining_path); - - if(nested_result.error()){ - return nested_result.error(); - } - // Same logic as above. - std::vector nested_matches = std::move(nested_result).value_unsafe(); - - result.insert(result.end(), - std::make_move_iterator(nested_matches.begin()), - std::make_move_iterator(nested_matches.end())); + if (key=="*"){ + for(auto element: *this) { + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()) { + callback(val); + } else { + error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback); + if(err) { return err; } } } - return result; - }else{ + return SUCCESS; + } else { // Specific index case in which we access the element at the given index - size_t idx=0; + size_t idx = 0; - for(char c:key){ + for (char c : key) { if(c < '0' || c > '9'){ return INVALID_JSON_POINTER; } @@ -164758,16 +165572,13 @@ inline simdjson_result> array::at_path_with_wildcard(std::str } auto element = at(idx); - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - result.push_back(std::move(element).value_unsafe()); - return result; - }else{ - return element.at_path_with_wildcard(remaining_path); + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()){ + callback(val); + return SUCCESS; + } else { + return element.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -164830,9 +165641,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } @@ -165253,14 +166070,20 @@ simdjson_inline simdjson_result value::at_path(std::string_view json_path } } -inline simdjson_result> value::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code value::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -165524,12 +166347,18 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard( - std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code simdjson_result::for_each_at_path_with_wildcard( + std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } } // namespace simdjson @@ -165905,8 +166734,14 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p } } -simdjson_inline simdjson_result> document::at_path_with_wildcard(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_path_with_wildcard is called +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { + rewind(); // Rewind the document each time for_each_at_path_with_wildcard is called if (json_path.empty()) { return INVALID_JSON_POINTER; } @@ -165914,9 +166749,9 @@ simdjson_inline simdjson_result> document::at_path_with_wildc SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -166253,9 +167088,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION @@ -166366,7 +167207,13 @@ simdjson_inline simdjson_result document_reference::get_number() noexcep simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result> document_reference::at_path_with_wildcard(std::string_view json_path) noexcept { return doc->at_path_with_wildcard(json_path); } +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document_reference::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { return doc->for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} simdjson_inline document_reference::operator document&() const noexcept { return *doc; } #if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_STATIC_REFLECTION @@ -166631,11 +167478,17 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION template @@ -168213,9 +169066,13 @@ inline simdjson_result object::at_path(std::string_view json_path) noexce return at_pointer(json_pointer); } -inline simdjson_result> object::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code object::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; @@ -168225,34 +169082,22 @@ inline simdjson_result> object::at_path_with_wildcard(std::st for (auto field : *this) { value val; SIMDJSON_TRY(field.value().get(val)); - if (remaining_path.empty()) { - result.push_back(std::move(val)); + callback(val); } else { - auto nested_result = val.at_path_with_wildcard(remaining_path); - - if (nested_result.error()) { - return nested_result.error(); - } - // Extract and append all nested matches to our result - std::vector nested_vec; - SIMDJSON_TRY(std::move(nested_result).get(nested_vec)); - - result.insert(result.end(), - std::make_move_iterator(nested_vec.begin()), - std::make_move_iterator(nested_vec.end())); + SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback)); } } - return result; + return SUCCESS; } else { value val; SIMDJSON_TRY(find_field(key).get(val)); if (remaining_path.empty()) { - result.push_back(std::move(val)); - return result; + callback(val); + return SUCCESS; } else { - return val.at_path_with_wildcard(remaining_path); + return val.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -168383,9 +169228,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } inline simdjson_result simdjson_result::reset() noexcept { @@ -168766,7 +169617,7 @@ simdjson_inline simdjson_warn_unused ondemand::parser& parser::get_parser() { return *parser::get_parser_instance(); } -simdjson_inline bool release_parser() { +simdjson_inline bool parser::release_parser() { auto &parser_instance = parser::get_threadlocal_parser_if_exists(); if (parser_instance) { parser_instance.reset(); @@ -173444,13 +174295,21 @@ class value { simdjson_inline simdjson_result at_path(std::string_view at_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard character (*) for arrays or ".*" for objects. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; protected: /** @@ -173643,9 +174502,23 @@ struct simdjson_result : public rvv_vls::implementatio simdjson_inline simdjson_result current_depth() const noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; }; +// Forward-declare explicit specializations so MSVC /permissive- sees them before +// any template instantiation that would resolve element.get(val) to the primary. +template<> simdjson_inline error_code +simdjson_result::get( + rvv_vls::ondemand::value &out) noexcept; +template<> simdjson_inline simdjson_result +simdjson_result::get() noexcept; + } // namespace simdjson #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H @@ -174984,8 +175857,6 @@ class parser { static simdjson_inline bool release_parser(); private: - friend bool release_parser(); - friend ondemand::parser& get_parser(); /** Get the thread-local parser instance, allocates it if needed */ static simdjson_inline simdjson_warn_unused std::unique_ptr& get_parser_instance(); /** Get the thread-local parser instance, it might be null */ @@ -175148,13 +176019,21 @@ class array { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like "[*]" to match all array elements. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the array and returns a string_view instance corresponding to the @@ -175278,7 +176157,13 @@ struct simdjson_result : public rvv_vls::implementatio simdjson_inline simdjson_result at(size_t index) noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; simdjson_inline simdjson_result raw_json() noexcept; #if SIMDJSON_SUPPORTS_CONCEPTS // TODO: move this code into object-inl.h @@ -176178,21 +177063,24 @@ class document { simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * * Supports wildcard patterns like "$.array[*]" or "$.object.*" to match multiple elements. * - * This method materializes all matching values into a vector. * The document will be consumed after this call. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern, or: - * - INVALID_JSON_POINTER if the JSONPath cannot be parsed - * - NO_SUCH_FIELD if a field does not exist - * - INDEX_OUT_OF_BOUNDS if an array index is out of bounds - * - INCORRECT_TYPE if path traversal encounters wrong type + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the document and returns a string_view instance corresponding to the @@ -176413,7 +177301,13 @@ class document_reference { simdjson_inline simdjson_result raw_json_token() noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; private: document *doc{nullptr}; @@ -176499,7 +177393,13 @@ struct simdjson_result : public rvv_vls::implementa simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -176584,7 +177484,13 @@ struct simdjson_result : public rvv_vls:: simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -177237,13 +178143,21 @@ class object { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like ".*" to match all object fields. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Reset the iterator so that we are pointing back at the @@ -177393,7 +178307,13 @@ struct simdjson_result : public rvv_vls::implementati simdjson_inline simdjson_result operator[](std::string_view key) && noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; inline simdjson_result reset() noexcept; inline simdjson_result is_empty() noexcept; inline simdjson_result count_fields() & noexcept; @@ -178407,46 +179327,34 @@ inline simdjson_result array::at_path(std::string_view json_path) noexcep return at_pointer(json_pointer); } -inline simdjson_result> array::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code array::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; // Wildcard case - if(key=="*"){ - for(auto element: *this){ - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - // Use value_unsafe() because we've already checked for errors above. - // The 'element' is a simdjson_result wrapper, and we need to extract - // the underlying value. value_unsafe() is safe here because error() returned false. - result.push_back(std::move(element).value_unsafe()); - - }else{ - auto nested_result = element.at_path_with_wildcard(remaining_path); - - if(nested_result.error()){ - return nested_result.error(); - } - // Same logic as above. - std::vector nested_matches = std::move(nested_result).value_unsafe(); - - result.insert(result.end(), - std::make_move_iterator(nested_matches.begin()), - std::make_move_iterator(nested_matches.end())); + if (key=="*"){ + for(auto element: *this) { + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()) { + callback(val); + } else { + error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback); + if(err) { return err; } } } - return result; - }else{ + return SUCCESS; + } else { // Specific index case in which we access the element at the given index - size_t idx=0; + size_t idx = 0; - for(char c:key){ + for (char c : key) { if(c < '0' || c > '9'){ return INVALID_JSON_POINTER; } @@ -178454,16 +179362,13 @@ inline simdjson_result> array::at_path_with_wildcard(std::str } auto element = at(idx); - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - result.push_back(std::move(element).value_unsafe()); - return result; - }else{ - return element.at_path_with_wildcard(remaining_path); + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()){ + callback(val); + return SUCCESS; + } else { + return element.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -178526,9 +179431,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } @@ -178949,14 +179860,20 @@ simdjson_inline simdjson_result value::at_path(std::string_view json_path } } -inline simdjson_result> value::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code value::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -179220,12 +180137,18 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard( - std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code simdjson_result::for_each_at_path_with_wildcard( + std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } } // namespace simdjson @@ -179601,8 +180524,14 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p } } -simdjson_inline simdjson_result> document::at_path_with_wildcard(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_path_with_wildcard is called +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { + rewind(); // Rewind the document each time for_each_at_path_with_wildcard is called if (json_path.empty()) { return INVALID_JSON_POINTER; } @@ -179610,9 +180539,9 @@ simdjson_inline simdjson_result> document::at_path_with_wildc SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -179949,9 +180878,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION @@ -180062,7 +180997,13 @@ simdjson_inline simdjson_result document_reference::get_number() noexcep simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result> document_reference::at_path_with_wildcard(std::string_view json_path) noexcept { return doc->at_path_with_wildcard(json_path); } +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document_reference::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { return doc->for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} simdjson_inline document_reference::operator document&() const noexcept { return *doc; } #if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_STATIC_REFLECTION @@ -180327,11 +181268,17 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION template @@ -181909,9 +182856,13 @@ inline simdjson_result object::at_path(std::string_view json_path) noexce return at_pointer(json_pointer); } -inline simdjson_result> object::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code object::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; @@ -181921,34 +182872,22 @@ inline simdjson_result> object::at_path_with_wildcard(std::st for (auto field : *this) { value val; SIMDJSON_TRY(field.value().get(val)); - if (remaining_path.empty()) { - result.push_back(std::move(val)); + callback(val); } else { - auto nested_result = val.at_path_with_wildcard(remaining_path); - - if (nested_result.error()) { - return nested_result.error(); - } - // Extract and append all nested matches to our result - std::vector nested_vec; - SIMDJSON_TRY(std::move(nested_result).get(nested_vec)); - - result.insert(result.end(), - std::make_move_iterator(nested_vec.begin()), - std::make_move_iterator(nested_vec.end())); + SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback)); } } - return result; + return SUCCESS; } else { value val; SIMDJSON_TRY(find_field(key).get(val)); if (remaining_path.empty()) { - result.push_back(std::move(val)); - return result; + callback(val); + return SUCCESS; } else { - return val.at_path_with_wildcard(remaining_path); + return val.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -182079,9 +183018,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } inline simdjson_result simdjson_result::reset() noexcept { @@ -182462,7 +183407,7 @@ simdjson_inline simdjson_warn_unused ondemand::parser& parser::get_parser() { return *parser::get_parser_instance(); } -simdjson_inline bool release_parser() { +simdjson_inline bool parser::release_parser() { auto &parser_instance = parser::get_threadlocal_parser_if_exists(); if (parser_instance) { parser_instance.reset(); diff --git a/deps/sqlite/sqlite3.c b/deps/sqlite/sqlite3.c index 91db04a9ecdc54..dfd557adeda581 100644 --- a/deps/sqlite/sqlite3.c +++ b/deps/sqlite/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.53.0. By combining all the individual C code files into this +** version 3.53.1. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -18,7 +18,7 @@ ** separate file. This file contains only code for the core SQLite library. ** ** The content in this amalgamation comes from Fossil check-in -** 4525003a53a7fc63ca75c59b22c79608659c with changes in files: +** c88b22011a54b4f6fbd149e9f8e4de77658c with changes in files: ** ** */ @@ -467,12 +467,12 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.53.0" -#define SQLITE_VERSION_NUMBER 3053000 -#define SQLITE_SOURCE_ID "2026-04-09 11:41:38 4525003a53a7fc63ca75c59b22c79608659ca12f0131f52c18637f829977f20b" -#define SQLITE_SCM_BRANCH "trunk" -#define SQLITE_SCM_TAGS "release major-release version-3.53.0" -#define SQLITE_SCM_DATETIME "2026-04-09T11:41:38.498Z" +#define SQLITE_VERSION "3.53.1" +#define SQLITE_VERSION_NUMBER 3053001 +#define SQLITE_SOURCE_ID "2026-05-05 10:34:17 c88b22011a54b4f6fbd149e9f8e4de77658ce58143a1af0e3785e4e6475127e9" +#define SQLITE_SCM_BRANCH "branch-3.53" +#define SQLITE_SCM_TAGS "release version-3.53.1" +#define SQLITE_SCM_DATETIME "2026-05-05T10:34:17.344Z" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -32513,7 +32513,7 @@ static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){ sqlite3StrAccumSetError(pAccum, SQLITE_TOOBIG); return 0; } - z = sqlite3DbMallocRaw(pAccum->db, n); + z = sqlite3_malloc(n); if( z==0 ){ sqlite3StrAccumSetError(pAccum, SQLITE_NOMEM); } @@ -32971,11 +32971,27 @@ SQLITE_API void sqlite3_str_vappendf( szBufNeeded = MAX(e2,0)+(i64)precision+(i64)width+10; if( cThousand && e2>0 ) szBufNeeded += (e2+2)/3; - if( sqlite3StrAccumEnlargeIfNeeded(pAccum, szBufNeeded) ){ - width = length = 0; - break; + if( szBufNeeded + pAccum->nChar >= pAccum->nAlloc ){ + if( pAccum->mxAlloc==0 && pAccum->accError==0 ){ + /* Unable to allocate space in pAccum, perhaps because it + ** is coming from sqlite3_snprintf() or similar. We'll have + ** to render into temporary space and the memcpy() it over. */ + bufpt = sqlite3_malloc(szBufNeeded); + if( bufpt==0 ){ + sqlite3StrAccumSetError(pAccum, SQLITE_NOMEM); + return; + } + zExtra = bufpt; + }else if( sqlite3StrAccumEnlarge(pAccum, szBufNeeded)zText + pAccum->nChar; + } + }else{ + bufpt = pAccum->zText + pAccum->nChar; } - bufpt = zOut = pAccum->zText + pAccum->nChar; + zOut = bufpt; flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2; /* The sign in front of the number */ @@ -33076,14 +33092,22 @@ SQLITE_API void sqlite3_str_vappendf( } length = width; } - pAccum->nChar += length; - zOut[length] = 0; - /* Floating point conversions render directly into the output - ** buffer. Hence, don't just break out of the switch(). Bypass the - ** output buffer writing that occurs after the switch() by continuing - ** to the next character in the format string. */ - continue; + if( zExtra==0 ){ + /* The result is being rendered directory into pAccum. This + ** is the command and fast case */ + pAccum->nChar += length; + zOut[length] = 0; + continue; + }else{ + /* We were unable to render directly into pAccum because we + ** couldn't allocate sufficient memory. We need to memcpy() + ** the rendering (or some prefix thereof) into the output + ** buffer. */ + bufpt[0] = 0; + bufpt = zExtra; + break; + } } case etSIZE: if( !bArgList ){ @@ -33130,7 +33154,7 @@ SQLITE_API void sqlite3_str_vappendf( if( sqlite3StrAccumEnlargeIfNeeded(pAccum, nCopyBytes) ){ break; } - sqlite3_str_append(pAccum, + sqlite3_str_append(pAccum, &pAccum->zText[pAccum->nChar-nCopyBytes], nCopyBytes); precision -= nPrior; nPrior *= 2; @@ -33646,7 +33670,7 @@ SQLITE_API void sqlite3_str_reset(StrAccum *p){ ** of its content, all in one call. */ SQLITE_API void sqlite3_str_free(sqlite3_str *p){ - if( p ){ + if( p!=0 && p!=&sqlite3OomStr ){ sqlite3_str_reset(p); sqlite3_free(p); } @@ -36792,15 +36816,20 @@ SQLITE_PRIVATE u8 sqlite3StrIHash(const char *z){ return h; } +#if !defined(SQLITE_DISABLE_INTRINSIC) \ + && (defined(__GNUC__) || defined(__clang__)) \ + && (defined(__x86_64__) || defined(__aarch64__) || \ + (defined(__riscv) && defined(__riscv_xlen) && (__riscv_xlen>32))) +#define SQLITE_USE_UINT128 +#endif + /* ** Two inputs are multiplied to get a 128-bit result. Write the ** lower 64-bits of the result into *pLo, and return the high-order ** 64 bits. */ static u64 sqlite3Multiply128(u64 a, u64 b, u64 *pLo){ -#if (defined(__GNUC__) || defined(__clang__)) \ - && (defined(__x86_64__) || defined(__aarch64__) || defined(__riscv)) \ - && !defined(SQLITE_DISABLE_INTRINSIC) +#if defined(SQLITE_USE_UINT128) __uint128_t r = (__uint128_t)a * b; *pLo = (u64)r; return (u64)(r>>64); @@ -36834,9 +36863,7 @@ static u64 sqlite3Multiply128(u64 a, u64 b, u64 *pLo){ ** The lower 64 bits of A*B are discarded. */ static u64 sqlite3Multiply160(u64 a, u32 aLo, u64 b, u32 *pLo){ -#if (defined(__GNUC__) || defined(__clang__)) \ - && (defined(__x86_64__) || defined(__aarch64__) || defined(__riscv)) \ - && !defined(SQLITE_DISABLE_INTRINSIC) +#if defined(SQLITE_USE_UINT128) __uint128_t r = (__uint128_t)a * b; r += ((__uint128_t)aLo * b) >> 32; *pLo = (r>>32)&0xffffffff; @@ -36874,6 +36901,8 @@ static u64 sqlite3Multiply160(u64 a, u32 aLo, u64 b, u32 *pLo){ #endif } +#undef SQLITE_USE_UINT128 + /* ** Return a u64 with the N-th bit set. */ @@ -56108,10 +56137,10 @@ SQLITE_API int sqlite3_deserialize( if( rc ) goto end_deserialize; db->init.iDb = (u8)iDb; db->init.reopenMemdb = 1; - rc = sqlite3_step(pStmt); + sqlite3_step(pStmt); db->init.reopenMemdb = 0; - if( rc!=SQLITE_DONE ){ - rc = SQLITE_ERROR; + rc = sqlite3_finalize(pStmt); + if( rc!=SQLITE_OK ){ goto end_deserialize; } p = memdbFromDbSchema(db, zSchema); @@ -56132,7 +56161,6 @@ SQLITE_API int sqlite3_deserialize( } end_deserialize: - sqlite3_finalize(pStmt); if( pData && (mFlags & SQLITE_DESERIALIZE_FREEONCLOSE)!=0 ){ sqlite3_free(pData); } @@ -123122,7 +123150,9 @@ SQLITE_PRIVATE void sqlite3AlterDropConstraint( if( !pTab ) return; if( pCons ){ - zArg = sqlite3MPrintf(db, "%.*Q", pCons->n, pCons->z); + char *z = sqlite3NameFromToken(db, pCons); + zArg = sqlite3MPrintf(db, "%Q", z); + sqlite3DbFree(db, z); }else{ int iCol; if( alterFindCol(pParse, pTab, pCol, &iCol) ) return; @@ -125504,6 +125534,16 @@ static void attachFunc( ** from sqlite3_deserialize() to close database db->init.iDb and ** reopen it as a MemDB */ Btree *pNewBt = 0; + + pNew = &db->aDb[db->init.iDb]; + assert( pNew->pBt!=0 ); + if( sqlite3BtreeTxnState(pNew->pBt)!=SQLITE_TXN_NONE + || sqlite3BtreeIsInBackup(pNew->pBt) + ){ + rc = SQLITE_BUSY; + goto attach_error; + } + pVfs = sqlite3_vfs_find("memdb"); if( pVfs==0 ) return; rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNewBt, 0, SQLITE_OPEN_MAIN_DB); @@ -125513,8 +125553,7 @@ static void attachFunc( /* Both the Btree and the new Schema were allocated successfully. ** Close the old db and update the aDb[] slot with the new memdb ** values. */ - pNew = &db->aDb[db->init.iDb]; - if( ALWAYS(pNew->pBt) ) sqlite3BtreeClose(pNew->pBt); + sqlite3BtreeClose(pNew->pBt); pNew->pBt = pNewBt; pNew->pSchema = pNewSchema; }else{ @@ -156057,6 +156096,7 @@ static SQLITE_NOINLINE void existsToJoin( && !ExprHasProperty(pWhere, EP_OuterON|EP_InnerON) && ALWAYS(p->pSrc!=0) && p->pSrc->nSrcpLimit==0 || p->pLimit->pRight==0) ){ if( pWhere->op==TK_AND ){ Expr *pRight = pWhere->pRight; @@ -156104,7 +156144,6 @@ static SQLITE_NOINLINE void existsToJoin( sqlite3TreeViewSelect(0, p, 0); } #endif - existsToJoin(pParse, p, pSubWhere); } } } @@ -165946,7 +165985,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ** by this loop in the a[0] slot and all notReady tables in a[1..] slots. ** This becomes the SrcList in the recursive call to sqlite3WhereBegin(). */ - if( pWInfo->nLevel>1 ){ + if( pWInfo->nLevel>1 || pTabItem->fg.fromExists ){ int nNotReady; /* The number of notReady tables */ SrcItem *origSrc; /* Original list of tables */ nNotReady = pWInfo->nLevel - iLevel - 1; @@ -165959,6 +165998,13 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( for(k=1; k<=nNotReady; k++){ memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k])); } + + /* Clear the fromExists flag on the OR-optimized table entry so that + ** the calls to sqlite3WhereEnd() do not code early-exits after the + ** first row is visited. The early exit applies to this table's + ** overall loop - including the multiple OR branches and any WHERE + ** conditions not passed to the sub-loops - not to the sub-loops. */ + pOrTab->a[0].fg.fromExists = 0; }else{ pOrTab = pWInfo->pTabList; } @@ -166202,7 +166248,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( assert( pLevel->op==OP_Return ); pLevel->p2 = sqlite3VdbeCurrentAddr(v); - if( pWInfo->nLevel>1 ){ sqlite3DbFreeNN(db, pOrTab); } + if( pWInfo->pTabList!=pOrTab ){ sqlite3DbFreeNN(db, pOrTab); } if( !untestedTerms ) disableTerm(pLevel, pTerm); }else #endif /* SQLITE_OMIT_OR_OPTIMIZATION */ @@ -176127,27 +176173,11 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ } #endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */ } - if( pTabList->a[pLevel->iFrom].fg.fromExists - && (i==pWInfo->nLevel-1 - || pTabList->a[pWInfo->a[i+1].iFrom].fg.fromExists==0) - ){ - /* This is an EXISTS-to-JOIN optimization which is either the - ** inner-most loop, or the inner-most of a group of nested - ** EXISTS-to-JOIN optimization loops. If this loop sees a successful - ** row, it should break out of itself as well as other EXISTS-to-JOIN - ** loops in which is is directly nested. */ - int nOuter = 0; /* Nr of outer EXISTS that this one is nested within */ - while( nOutera[pLevel[-nOuter-1].iFrom].fg.fromExists ) break; - nOuter++; - } - testcase( nOuter>0 ); - sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel[-nOuter].addrBrk); - if( nOuter ){ - VdbeComment((v, "EXISTS break %d..%d", i-nOuter, i)); - }else{ - VdbeComment((v, "EXISTS break %d", i)); - } + if( pTabList->a[pLevel->iFrom].fg.fromExists ){ + /* This is an EXISTS-to-JOIN optimization loop. If this loop sees a + ** successful row, it should break out of itself. */ + sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk); + VdbeComment((v, "EXISTS break %d", i)); } sqlite3VdbeResolveLabel(v, pLevel->addrCont); if( pLevel->op!=OP_Noop ){ @@ -184334,6 +184364,7 @@ static YYACTIONTYPE yy_reduce( yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy454, 0); if( yymsp[-4].minor.yy454 ){ yymsp[-4].minor.yy454->x.pList = pList; + sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy454); }else{ sqlite3ExprListDelete(pParse->db, pList); } @@ -233951,10 +233982,11 @@ static int sessionSerialLen(const u8 *a){ int n; assert( a!=0 ); e = *a; - if( e==0 || e==0xFF ) return 1; - if( e==SQLITE_NULL ) return 1; if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9; - return sessionVarintGet(&a[1], &n) + 1 + n; + if( e==SQLITE_TEXT || e==SQLITE_BLOB ){ + return sessionVarintGet(&a[1], &n) + 1 + n; + } + return 1; } /* @@ -233977,17 +234009,17 @@ static unsigned int sessionChangeHash( u8 *a = aRecord; /* Used to iterate through change record */ for(i=0; inCol; i++){ - int eType = *a; int isPK = pTab->abPK[i]; if( bPkOnly && isPK==0 ) continue; - assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT - || eType==SQLITE_TEXT || eType==SQLITE_BLOB - || eType==SQLITE_NULL || eType==0 - ); - if( isPK ){ - a++; + int eType = *a++; + + assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT + || eType==SQLITE_TEXT || eType==SQLITE_BLOB + || eType==SQLITE_NULL || eType==0 + ); + h = sessionHashAppendType(h, eType); if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ h = sessionHashAppendI64(h, sessionGetI64(a)); @@ -237015,9 +237047,11 @@ static int sessionChangesetBufferRecord( rc = sessionInputBuffer(pIn, nByte); }else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ nByte += 8; + }else if( eType!=0 && eType!=SQLITE_NULL ){ + rc = SQLITE_CORRUPT_BKPT; } } - if( (pIn->iNext+nByte)>pIn->nData ){ + if( rc==SQLITE_OK && (pIn->iNext+nByte)>pIn->nData ){ rc = SQLITE_CORRUPT_BKPT; } } @@ -263222,7 +263256,7 @@ static void fts5SourceIdFunc( ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); - sqlite3_result_text(pCtx, "fts5: 2026-04-09 11:41:38 4525003a53a7fc63ca75c59b22c79608659ca12f0131f52c18637f829977f20b", -1, SQLITE_TRANSIENT); + sqlite3_result_text(pCtx, "fts5: 2026-05-05 10:34:17 c88b22011a54b4f6fbd149e9f8e4de77658ce58143a1af0e3785e4e6475127e9", -1, SQLITE_TRANSIENT); } /* diff --git a/deps/sqlite/sqlite3.h b/deps/sqlite/sqlite3.h index 5d7f82b659140b..8ee26c99d86e6e 100644 --- a/deps/sqlite/sqlite3.h +++ b/deps/sqlite/sqlite3.h @@ -146,12 +146,12 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.53.0" -#define SQLITE_VERSION_NUMBER 3053000 -#define SQLITE_SOURCE_ID "2026-04-09 11:41:38 4525003a53a7fc63ca75c59b22c79608659ca12f0131f52c18637f829977f20b" -#define SQLITE_SCM_BRANCH "trunk" -#define SQLITE_SCM_TAGS "release major-release version-3.53.0" -#define SQLITE_SCM_DATETIME "2026-04-09T11:41:38.498Z" +#define SQLITE_VERSION "3.53.1" +#define SQLITE_VERSION_NUMBER 3053001 +#define SQLITE_SOURCE_ID "2026-05-05 10:34:17 c88b22011a54b4f6fbd149e9f8e4de77658ce58143a1af0e3785e4e6475127e9" +#define SQLITE_SCM_BRANCH "branch-3.53" +#define SQLITE_SCM_TAGS "release version-3.53.1" +#define SQLITE_SCM_DATETIME "2026-05-05T10:34:17.344Z" /* ** CAPI3REF: Run-Time Library Version Numbers diff --git a/deps/undici/src/docs/docs/api/Client.md b/deps/undici/src/docs/docs/api/Client.md index 680375d1479e97..d3d115fdef6b15 100644 --- a/deps/undici/src/docs/docs/api/Client.md +++ b/deps/undici/src/docs/docs/api/Client.md @@ -24,6 +24,9 @@ Returns: `Client` * **keepAliveTimeoutThreshold** `number | null` (optional) - Default: `2e3` - A number of milliseconds subtracted from server *keep-alive* hints when overriding `keepAliveTimeout` to account for timing inaccuracies caused by e.g. transport latency. Defaults to 2 seconds. * **maxHeaderSize** `number | null` (optional) - Default: `--max-http-header-size` or `16384` - The maximum length of request headers in bytes. Defaults to Node.js' --max-http-header-size or 16KiB. * **maxResponseSize** `number | null` (optional) - Default: `-1` - The maximum length of response body in bytes. Set to `-1` to disable. +* **webSocket** `WebSocketOptions` (optional) - WebSocket-specific configuration options. + * **maxFragments** `number` (optional) - Default: `131072` - Maximum number of fragments in a message. Set to 0 to disable the limit. + * **maxPayloadSize** `number` (optional) - Default: `134217728` (128 MB) - Maximum allowed payload size in bytes for WebSocket messages. Applied to uncompressed messages, compressed frame payloads, and decompressed (permessage-deflate) messages. Set to 0 to disable the limit. * **pipelining** `number | null` (optional) - Default: `1` - The amount of concurrent requests to be sent over the single TCP/TLS connection according to [RFC7230](https://tools.ietf.org/html/rfc7230#section-6.3.2). Carefully consider your workload and environment before enabling concurrent requests as pipelining may reduce performance if used incorrectly. Pipelining is sensitive to network stack settings as well as head of line blocking caused by e.g. long running requests. Set to `0` to disable keep-alive connections. * **connect** `ConnectOptions | Function | null` (optional) - Default: `null`. * **strictContentLength** `Boolean` (optional) - Default: `true` - Whether to treat request content length mismatches as errors. If true, an error is thrown when the request content-length header doesn't match the length of the request body. **Security Warning:** Disabling this option can expose your application to HTTP Request Smuggling attacks, where mismatched content-length headers cause servers and proxies to interpret request boundaries differently. This can lead to cache poisoning, credential hijacking, and bypassing security controls. Only disable this in controlled environments where you fully trust the request source. diff --git a/deps/undici/src/docs/docs/api/Cookies.md b/deps/undici/src/docs/docs/api/Cookies.md index 0cad37914d6258..2368db43a79072 100644 --- a/deps/undici/src/docs/docs/api/Cookies.md +++ b/deps/undici/src/docs/docs/api/Cookies.md @@ -80,6 +80,33 @@ Arguments: Returns: `Cookie[]` +## `parseCookie(cookie)` + +Parses a single `Set-Cookie` header value into a `Cookie` object. + +```js +import { parseCookie } from 'undici' + +console.log(parseCookie('undici=getSetCookies; Secure; SameSite=Lax')) +// { +// name: 'undici', +// value: 'getSetCookies', +// secure: true, +// sameSite: 'Lax' +// } +``` + +Notes: + +* The cookie value is returned as it appears in the header. Percent-encoded sequences such as `%20` or `%0D%0A` are **not** decoded. +* `sameSite` is only set for exact case-insensitive matches of `Strict`, `Lax`, or `None`. + +Arguments: + +* **cookie** `string` + +Returns: `Cookie | null` + ## `setCookie(headers, cookie)` Appends a cookie to the `Set-Cookie` header. diff --git a/deps/undici/src/docs/docs/api/Socks5ProxyAgent.md b/deps/undici/src/docs/docs/api/Socks5ProxyAgent.md index ef6fc635a8f747..3ef0f852f27a97 100644 --- a/deps/undici/src/docs/docs/api/Socks5ProxyAgent.md +++ b/deps/undici/src/docs/docs/api/Socks5ProxyAgent.md @@ -22,6 +22,7 @@ Extends: [`PoolOptions`](/docs/docs/api/Pool.md#parameter-pooloptions) * **password** `string` (optional) - SOCKS5 proxy password for authentication. Can also be provided in the proxy URL. * **connect** `Function` (optional) - Custom connector function for the proxy connection. * **proxyTls** `BuildOptions` (optional) - TLS options for the proxy connection (when using SOCKS5 over TLS). +* **requestTls** `BuildOptions` (optional) - TLS options applied to the HTTPS connection to the target server through the SOCKS5 tunnel. Use this to configure `ca`, `cert`, `key`, `rejectUnauthorized`, `servername`, etc. for the target HTTPS endpoint. Examples: diff --git a/deps/undici/src/lib/api/api-request.js b/deps/undici/src/lib/api/api-request.js index f6d15f75b0ecaa..a6341af531b8af 100644 --- a/deps/undici/src/lib/api/api-request.js +++ b/deps/undici/src/lib/api/api-request.js @@ -21,7 +21,7 @@ class RequestHandler extends AsyncResource { throw new InvalidArgumentError('invalid callback') } - if (highWaterMark && (typeof highWaterMark !== 'number' || highWaterMark < 0)) { + if (highWaterMark != null && (!Number.isFinite(highWaterMark) || highWaterMark < 0)) { throw new InvalidArgumentError('invalid highWaterMark') } diff --git a/deps/undici/src/lib/cache/sqlite-cache-store.js b/deps/undici/src/lib/cache/sqlite-cache-store.js index 7cb4aa7e2466e3..7a5fc999f470d1 100644 --- a/deps/undici/src/lib/cache/sqlite-cache-store.js +++ b/deps/undici/src/lib/cache/sqlite-cache-store.js @@ -216,7 +216,7 @@ module.exports = class SqliteCacheStore { SELECT id FROM cacheInterceptorV${VERSION} - ORDER BY cachedAt DESC + ORDER BY cachedAt ASC LIMIT ? ) `) @@ -283,7 +283,6 @@ module.exports = class SqliteCacheStore { existingValue.id ) } else { - this.#prune() // New response, let's insert it this.#insertValueQuery.run( url, @@ -299,6 +298,7 @@ module.exports = class SqliteCacheStore { value.cachedAt, value.staleAt ) + this.#prune() } } @@ -409,7 +409,7 @@ module.exports = class SqliteCacheStore { const now = Date.now() for (const value of values) { if (now >= value.deleteAt && !canBeExpired) { - return undefined + continue } let matches = true diff --git a/deps/undici/src/lib/core/connect.js b/deps/undici/src/lib/core/connect.js index a49af91486e623..89a20c740a7550 100644 --- a/deps/undici/src/lib/core/connect.js +++ b/deps/undici/src/lib/core/connect.js @@ -38,6 +38,22 @@ const SessionCache = class WeakSessionCache { return } + if (this._sessionCache.has(sessionKey)) { + this._sessionCache.delete(sessionKey) + } else if (this._sessionCache.size >= this._maxCachedSessions) { + for (const [key, ref] of this._sessionCache) { + if (ref.deref() === undefined) { + this._sessionCache.delete(key) + return + } + } + + const oldest = this._sessionCache.keys().next() + if (!oldest.done) { + this._sessionCache.delete(oldest.value) + } + } + this._sessionCache.set(sessionKey, new WeakRef(session)) this._sessionRegistry.register(session, sessionKey) } diff --git a/deps/undici/src/lib/core/request.js b/deps/undici/src/lib/core/request.js index 829da6f8fc1d33..326d58fb43f8fd 100644 --- a/deps/undici/src/lib/core/request.js +++ b/deps/undici/src/lib/core/request.js @@ -27,6 +27,21 @@ const { headerNameLowerCasedRecord } = require('./constants') // Verifies that a given path is valid does not contain control chars \x00 to \x20 const invalidPathRegex = /[^\u0021-\u00ff]/ +function isValidContentLengthHeaderValue (val) { + if (typeof val !== 'string' || val.length === 0) { + return false + } + + for (let i = 0; i < val.length; i++) { + const charCode = val.charCodeAt(i) + if (charCode < 48 || charCode > 57) { + return false + } + } + + return true +} + const kHandler = Symbol('handler') class Request { @@ -402,10 +417,10 @@ function processHeader (request, key, val) { if (request.contentLength !== null) { throw new InvalidArgumentError('duplicate content-length header') } - request.contentLength = parseInt(val, 10) - if (!Number.isFinite(request.contentLength)) { + if (!isValidContentLengthHeaderValue(val)) { throw new InvalidArgumentError('invalid content-length header') } + request.contentLength = parseInt(val, 10) } else if (request.contentType === null && headerName === 'content-type') { request.contentType = val request.headers.push(key, val) diff --git a/deps/undici/src/lib/core/socks5-client.js b/deps/undici/src/lib/core/socks5-client.js index 5d175d70366ac5..90f6d0a680f419 100644 --- a/deps/undici/src/lib/core/socks5-client.js +++ b/deps/undici/src/lib/core/socks5-client.js @@ -7,6 +7,7 @@ const { debuglog } = require('node:util') const { parseAddress } = require('./socks5-utils') const debug = debuglog('undici:socks5') +const EMPTY_BUFFER = Buffer.alloc(0) // SOCKS5 constants const SOCKS_VERSION = 0x05 @@ -51,6 +52,7 @@ const STATES = { INITIAL: 'initial', HANDSHAKING: 'handshaking', AUTHENTICATING: 'authenticating', + AUTHENTICATED: 'authenticated', CONNECTING: 'connecting', CONNECTED: 'connected', ERROR: 'error', @@ -72,7 +74,10 @@ class Socks5Client extends EventEmitter { this.socket = socket this.options = options this.state = STATES.INITIAL - this.buffer = Buffer.alloc(0) + this.buffer = EMPTY_BUFFER + this.onSocketData = this.onData.bind(this) + this.onSocketError = this.onError.bind(this) + this.onSocketClose = this.onClose.bind(this) // Authentication settings this.authMethods = [] @@ -82,9 +87,9 @@ class Socks5Client extends EventEmitter { this.authMethods.push(AUTH_METHODS.NO_AUTH) // Socket event handlers - this.socket.on('data', this.onData.bind(this)) - this.socket.on('error', this.onError.bind(this)) - this.socket.on('close', this.onClose.bind(this)) + this.socket.on('data', this.onSocketData) + this.socket.on('error', this.onSocketError) + this.socket.on('close', this.onSocketClose) } /** @@ -139,6 +144,11 @@ class Socks5Client extends EventEmitter { } } + markAuthenticated () { + this.state = STATES.AUTHENTICATED + this.emit('authenticated') + } + /** * Start the SOCKS5 handshake */ @@ -189,7 +199,7 @@ class Socks5Client extends EventEmitter { debug('server selected auth method', method) if (method === AUTH_METHODS.NO_AUTH) { - this.emit('authenticated') + this.markAuthenticated() } else if (method === AUTH_METHODS.USERNAME_PASSWORD) { this.state = STATES.AUTHENTICATING this.sendAuthRequest() @@ -254,7 +264,7 @@ class Socks5Client extends EventEmitter { this.buffer = this.buffer.subarray(2) debug('authentication successful') - this.emit('authenticated') + this.markAuthenticated() } /** @@ -263,8 +273,12 @@ class Socks5Client extends EventEmitter { * @param {number} port - Target port */ connect (address, port) { - if (this.state === STATES.CONNECTED) { - throw new InvalidArgumentError('Already connected') + if (this.state === STATES.CONNECTING || this.state === STATES.CONNECTED) { + throw new InvalidArgumentError('Connection already in progress') + } + + if (this.state !== STATES.AUTHENTICATED) { + throw new InvalidArgumentError('Client must be authenticated before CONNECT') } debug('connecting to', address, port) @@ -363,8 +377,9 @@ class Socks5Client extends EventEmitter { const boundPort = this.buffer.readUInt16BE(offset) - this.buffer = this.buffer.subarray(responseLength) + this.buffer = EMPTY_BUFFER this.state = STATES.CONNECTED + this.socket.removeListener('data', this.onSocketData) debug('connected, bound address:', boundAddress, 'port:', boundPort) this.emit('connected', { address: boundAddress, port: boundPort }) diff --git a/deps/undici/src/lib/core/socks5-utils.js b/deps/undici/src/lib/core/socks5-utils.js index 2b5a3662bf560a..e6098bef05fc4c 100644 --- a/deps/undici/src/lib/core/socks5-utils.js +++ b/deps/undici/src/lib/core/socks5-utils.js @@ -46,34 +46,43 @@ function parseAddress (address) { */ function parseIPv6 (address) { const buffer = Buffer.alloc(16) - const parts = address.split(':') - let partIndex = 0 - let bufferIndex = 0 + let normalizedAddress = address + + // Expand an embedded IPv4 tail into the last two IPv6 groups. + if (address.includes('.')) { + const lastColonIndex = address.lastIndexOf(':') + const ipv4Part = address.slice(lastColonIndex + 1) + + if (net.isIPv4(ipv4Part)) { + const octets = ipv4Part.split('.').map(Number) + const high = ((octets[0] << 8) | octets[1]).toString(16) + const low = ((octets[2] << 8) | octets[3]).toString(16) + normalizedAddress = `${address.slice(0, lastColonIndex)}:${high}:${low}` + } + } // Handle compressed notation (::) - const doubleColonIndex = address.indexOf('::') + const doubleColonIndex = normalizedAddress.indexOf('::') if (doubleColonIndex !== -1) { - // Count non-empty parts - const nonEmptyParts = parts.filter(p => p.length > 0).length - const skipParts = 8 - nonEmptyParts - - for (let i = 0; i < parts.length; i++) { - if (parts[i] === '' && i === doubleColonIndex / 3) { - // Skip empty parts for :: - bufferIndex += skipParts * 2 - } else if (parts[i] !== '') { - const value = parseInt(parts[i], 16) - buffer.writeUInt16BE(value, bufferIndex) - bufferIndex += 2 - } + const before = normalizedAddress.slice(0, doubleColonIndex) + const after = normalizedAddress.slice(doubleColonIndex + 2) + const beforeParts = before === '' ? [] : before.split(':') + const afterParts = after === '' ? [] : after.split(':') + + let bufferIndex = 0 + for (const part of beforeParts) { + buffer.writeUInt16BE(parseInt(part, 16), bufferIndex) + bufferIndex += 2 + } + bufferIndex = 16 - afterParts.length * 2 + for (const part of afterParts) { + buffer.writeUInt16BE(parseInt(part, 16), bufferIndex) + bufferIndex += 2 } } else { - // No compression, parse normally - for (const part of parts) { - if (part === '') continue - const value = parseInt(part, 16) - buffer.writeUInt16BE(value, partIndex * 2) - partIndex++ + const parts = normalizedAddress.split(':') + for (let i = 0; i < parts.length; i++) { + buffer.writeUInt16BE(parseInt(parts[i], 16), i * 2) } } diff --git a/deps/undici/src/lib/dispatcher/agent.js b/deps/undici/src/lib/dispatcher/agent.js index 939b0ad55d3901..09fdd4be3d5ed9 100644 --- a/deps/undici/src/lib/dispatcher/agent.js +++ b/deps/undici/src/lib/dispatcher/agent.js @@ -35,7 +35,7 @@ class Agent extends DispatcherBase { throw new InvalidArgumentError('maxOrigins must be a number greater than 0') } - super() + super(options) if (connect && typeof connect !== 'function') { connect = { ...connect } diff --git a/deps/undici/src/lib/dispatcher/balanced-pool.js b/deps/undici/src/lib/dispatcher/balanced-pool.js index fa0fa97288ea3d..c21c081c45c45d 100644 --- a/deps/undici/src/lib/dispatcher/balanced-pool.js +++ b/deps/undici/src/lib/dispatcher/balanced-pool.js @@ -54,7 +54,7 @@ class BalancedPool extends PoolBase { throw new InvalidArgumentError('factory must be a function.') } - super() + super(opts) this[kOptions] = { ...util.deepClone(opts) } this[kOptions].interceptors = opts.interceptors diff --git a/deps/undici/src/lib/dispatcher/client-h1.js b/deps/undici/src/lib/dispatcher/client-h1.js index 939e0814bcd4b6..7d179967110a13 100644 --- a/deps/undici/src/lib/dispatcher/client-h1.js +++ b/deps/undici/src/lib/dispatcher/client-h1.js @@ -57,6 +57,9 @@ const constants = require('../llhttp/constants.js') const EMPTY_BUF = Buffer.alloc(0) const FastBuffer = Buffer[Symbol.species] const removeAllListeners = util.removeAllListeners +const kIdleSocketValidation = Symbol('kIdleSocketValidation') +const kIdleSocketValidationTimeout = Symbol('kIdleSocketValidationTimeout') +const kSocketUsed = Symbol('kSocketUsed') let extractBody @@ -69,9 +72,9 @@ function lazyllhttp () { let useWasmSIMD = process.arch !== 'ppc64' // The Env Variable UNDICI_NO_WASM_SIMD allows explicitly overriding the default behavior if (process.env.UNDICI_NO_WASM_SIMD === '1') { - useWasmSIMD = true - } else if (process.env.UNDICI_NO_WASM_SIMD === '0') { useWasmSIMD = false + } else if (process.env.UNDICI_NO_WASM_SIMD === '0') { + useWasmSIMD = true } if (useWasmSIMD) { @@ -216,6 +219,7 @@ class Parser { */ this.socket = socket this.timeout = null + this.timeoutWeakRef = new WeakRef(this) this.timeoutValue = null this.timeoutType = null this.statusCode = 0 @@ -253,9 +257,9 @@ class Parser { if (delay) { if (type & USE_FAST_TIMER) { - this.timeout = timers.setFastTimeout(onParserTimeout, delay, new WeakRef(this)) + this.timeout = timers.setFastTimeout(onParserTimeout, delay, this.timeoutWeakRef) } else { - this.timeout = setTimeout(onParserTimeout, delay, new WeakRef(this)) + this.timeout = setTimeout(onParserTimeout, delay, this.timeoutWeakRef) this.timeout?.unref() } } @@ -349,16 +353,7 @@ class Parser { this.paused = true socket.unshift(data) } else { - const ptr = llhttp.llhttp_get_error_reason(this.ptr) - let message = '' - if (ptr) { - const len = new Uint8Array(llhttp.memory.buffer, ptr).indexOf(0) - message = - 'Response does not match the HTTP/1.1 protocol (' + - Buffer.from(llhttp.memory.buffer, ptr, len).toString() + - ')' - } - throw new HTTPParserError(message, constants.ERROR[ret], data) + throw this.createError(ret, data) } } } catch (err) { @@ -366,6 +361,54 @@ class Parser { } } + finish () { + assert(currentParser === null) + assert(this.ptr != null) + assert(!this.paused) + + const { llhttp } = this + + let ret + + try { + currentParser = this + ret = llhttp.llhttp_finish(this.ptr) + } finally { + currentParser = null + } + + if (ret === constants.ERROR.OK) { + return null + } + + if (ret === constants.ERROR.PAUSED || ret === constants.ERROR.PAUSED_UPGRADE) { + this.paused = true + return null + } + + return this.createError(ret, EMPTY_BUF) + } + + createError (ret, data) { + const { llhttp, contentLength, bytesRead } = this + + if (contentLength && bytesRead !== parseInt(contentLength, 10)) { + return new ResponseContentLengthMismatchError() + } + + const ptr = llhttp.llhttp_get_error_reason(this.ptr) + let message = '' + if (ptr) { + const len = new Uint8Array(llhttp.memory.buffer, ptr).indexOf(0) + message = + 'Response does not match the HTTP/1.1 protocol (' + + Buffer.from(llhttp.memory.buffer, ptr, len).toString() + + ')' + } + + return new HTTPParserError(message, constants.ERROR[ret], data) + } + destroy () { assert(currentParser === null) assert(this.ptr != null) @@ -400,6 +443,11 @@ class Parser { return -1 } + if (client[kRunning] === 0) { + util.destroy(socket, new SocketError('bad response', util.getSocketInfo(socket))) + return -1 + } + const request = client[kQueue][client[kRunningIdx]] if (!request) { return -1 @@ -528,6 +576,11 @@ class Parser { return -1 } + if (client[kRunning] === 0) { + util.destroy(socket, new SocketError('bad response', util.getSocketInfo(socket))) + return -1 + } + const request = client[kQueue][client[kRunningIdx]] if (!request) { @@ -706,6 +759,7 @@ class Parser { request.onComplete(headers) client[kQueue][client[kRunningIdx]++] = null + socket[kSocketUsed] = client[kPending] === 0 if (socket[kWriting]) { assert(client[kRunning] === 0) @@ -782,6 +836,9 @@ function connectH1 (client, socket) { socket[kWriting] = false socket[kReset] = false socket[kBlocking] = false + socket[kIdleSocketValidation] = 0 + socket[kIdleSocketValidationTimeout] = null + socket[kSocketUsed] = false socket[kParser] = new Parser(client, socket, llhttpInstance) util.addListener(socket, 'error', onHttpSocketError) @@ -824,7 +881,7 @@ function connectH1 (client, socket) { * @returns {boolean} */ busy (request) { - if (socket[kWriting] || socket[kReset] || socket[kBlocking]) { + if (socket[kWriting] || socket[kReset] || socket[kBlocking] || socket[kIdleSocketValidation] === 1) { return true } @@ -870,8 +927,11 @@ function onHttpSocketError (err) { // On Mac OS, we get an ECONNRESET even if there is a full body to be forwarded // to the user. if (err.code === 'ECONNRESET' && parser.statusCode && !parser.shouldKeepAlive) { - // We treat all incoming data so for as a valid response. - parser.onMessageComplete() + const parserErr = parser.finish() + if (parserErr) { + this[kError] = parserErr + this[kClient][kOnError](parserErr) + } return } @@ -888,8 +948,10 @@ function onHttpSocketEnd () { const parser = this[kParser] if (parser.statusCode && !parser.shouldKeepAlive) { - // We treat all incoming data so far as a valid response. - parser.onMessageComplete() + const parserErr = parser.finish() + if (parserErr) { + util.destroy(this, parserErr) + } return } @@ -899,10 +961,11 @@ function onHttpSocketEnd () { function onHttpSocketClose () { const parser = this[kParser] + clearIdleSocketValidation(this) + if (parser) { if (!this[kError] && parser.statusCode && !parser.shouldKeepAlive) { - // We treat all incoming data so far as a valid response. - parser.onMessageComplete() + this[kError] = parser.finish() || this[kError] } this[kParser].destroy() @@ -946,6 +1009,28 @@ function onSocketClose () { this[kClosed] = true } +function clearIdleSocketValidation (socket) { + if (socket[kIdleSocketValidationTimeout]) { + clearTimeout(socket[kIdleSocketValidationTimeout]) + socket[kIdleSocketValidationTimeout] = null + } + + socket[kIdleSocketValidation] = 0 +} + +function scheduleIdleSocketValidation (client, socket) { + socket[kIdleSocketValidation] = 1 + socket[kIdleSocketValidationTimeout] = setTimeout(() => { + socket[kIdleSocketValidationTimeout] = null + socket[kIdleSocketValidation] = 2 + + if (client[kSocket] === socket && !socket.destroyed) { + client[kResume]() + } + }, 0) + socket[kIdleSocketValidationTimeout].unref?.() +} + /** * @param {import('./client.js')} client */ @@ -963,6 +1048,32 @@ function resumeH1 (client) { socket[kNoRef] = false } + if (client[kRunning] === 0 && client[kPending] > 0 && socket[kSocketUsed]) { + if (socket[kIdleSocketValidation] === 0) { + scheduleIdleSocketValidation(client, socket) + socket[kParser].readMore() + if (socket.destroyed) { + return + } + return + } + + if (socket[kIdleSocketValidation] === 1) { + socket[kParser].readMore() + if (socket.destroyed) { + return + } + return + } + } + + if (client[kRunning] === 0) { + socket[kParser].readMore() + if (socket.destroyed) { + return + } + } + if (client[kSize] === 0) { if (socket[kParser].timeoutType !== TIMEOUT_KEEP_ALIVE) { socket[kParser].setTimeout(client[kKeepAliveTimeoutValue], TIMEOUT_KEEP_ALIVE) @@ -1061,6 +1172,7 @@ function writeH1 (client, request) { } const socket = client[kSocket] + clearIdleSocketValidation(socket) /** * @param {Error} [err] diff --git a/deps/undici/src/lib/dispatcher/client.js b/deps/undici/src/lib/dispatcher/client.js index f4feff1bbe0aaa..6ef97ba0a369a9 100644 --- a/deps/undici/src/lib/dispatcher/client.js +++ b/deps/undici/src/lib/dispatcher/client.js @@ -114,7 +114,8 @@ class Client extends DispatcherBase { useH2c, initialWindowSize, connectionWindowSize, - pingInterval + pingInterval, + webSocket } = {}) { if (keepAlive !== undefined) { throw new InvalidArgumentError('unsupported keepAlive, use pipelining=0 instead') @@ -222,7 +223,7 @@ class Client extends DispatcherBase { throw new InvalidArgumentError('pingInterval must be a positive integer, greater or equal to 0') } - super() + super({ webSocket }) if (typeof connect !== 'function') { connect = buildConnector({ @@ -235,9 +236,13 @@ class Client extends DispatcherBase { ...(typeof autoSelectFamily === 'boolean' ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined), ...connect }) - } else if (socketPath != null) { + } else { const customConnect = connect - connect = (opts, callback) => customConnect({ ...opts, socketPath }, callback) + connect = (opts, callback) => customConnect({ + ...opts, + ...(socketPath != null ? { socketPath } : null), + ...(allowH2 != null ? { allowH2 } : null) + }, callback) } this[kUrl] = util.parseOrigin(url) diff --git a/deps/undici/src/lib/dispatcher/dispatcher-base.js b/deps/undici/src/lib/dispatcher/dispatcher-base.js index a6f471002571a4..feb2571abc2a3a 100644 --- a/deps/undici/src/lib/dispatcher/dispatcher-base.js +++ b/deps/undici/src/lib/dispatcher/dispatcher-base.js @@ -11,6 +11,7 @@ const { kDestroy, kClose, kClosed, kDestroyed, kDispatch } = require('../core/sy const kOnDestroyed = Symbol('onDestroyed') const kOnClosed = Symbol('onClosed') +const kWebSocketOptions = Symbol('webSocketOptions') class DispatcherBase extends Dispatcher { /** @type {boolean} */ @@ -25,6 +26,24 @@ class DispatcherBase extends Dispatcher { /** @type {Array|null} */ [kOnClosed] = null + /** + * @param {import('../../types/dispatcher').DispatcherOptions} [opts] + */ + constructor (opts) { + super() + this[kWebSocketOptions] = opts?.webSocket ?? {} + } + + /** + * @returns {import('../../types/dispatcher').WebSocketOptions} + */ + get webSocketOptions () { + return { + maxFragments: this[kWebSocketOptions].maxFragments ?? 131072, + maxPayloadSize: this[kWebSocketOptions].maxPayloadSize ?? 128 * 1024 * 1024 // 128 MB default + } + } + /** @returns {boolean} */ get destroyed () { return this[kDestroyed] diff --git a/deps/undici/src/lib/dispatcher/h2c-client.js b/deps/undici/src/lib/dispatcher/h2c-client.js index bd385225ea17e1..5fe7e778ba40e5 100644 --- a/deps/undici/src/lib/dispatcher/h2c-client.js +++ b/deps/undici/src/lib/dispatcher/h2c-client.js @@ -15,7 +15,7 @@ class H2CClient extends Client { ) } - const { connect, maxConcurrentStreams, pipelining, ...opts } = + const { maxConcurrentStreams, pipelining, ...opts } = clientOpts ?? {} let defaultMaxConcurrentStreams = 100 let defaultPipelining = 100 diff --git a/deps/undici/src/lib/dispatcher/pool.js b/deps/undici/src/lib/dispatcher/pool.js index 8419ac611e7907..0c5dbe44da779e 100644 --- a/deps/undici/src/lib/dispatcher/pool.js +++ b/deps/undici/src/lib/dispatcher/pool.js @@ -63,7 +63,7 @@ class Pool extends PoolBase { }) } - super() + super(options) this[kConnections] = connections || null this[kUrl] = util.parseOrigin(origin) diff --git a/deps/undici/src/lib/dispatcher/proxy-agent.js b/deps/undici/src/lib/dispatcher/proxy-agent.js index 1cf9cb51f4f812..d2a2f23cbff3b8 100644 --- a/deps/undici/src/lib/dispatcher/proxy-agent.js +++ b/deps/undici/src/lib/dispatcher/proxy-agent.js @@ -142,7 +142,8 @@ class ProxyAgent extends DispatcherBase { factory: agentFactory, username: opts.username || username, password: opts.password || password, - proxyTls: opts.proxyTls + proxyTls: opts.proxyTls, + requestTls: opts.requestTls }) } diff --git a/deps/undici/src/lib/dispatcher/socks5-proxy-agent.js b/deps/undici/src/lib/dispatcher/socks5-proxy-agent.js index a2dd2f428c7117..544d3025ea9e06 100644 --- a/deps/undici/src/lib/dispatcher/socks5-proxy-agent.js +++ b/deps/undici/src/lib/dispatcher/socks5-proxy-agent.js @@ -1,12 +1,11 @@ 'use strict' -const net = require('node:net') const { URL } = require('node:url') let tls // include tls conditionally since it is not always available const DispatcherBase = require('./dispatcher-base') const { InvalidArgumentError } = require('../core/errors') -const { Socks5Client } = require('../core/socks5-client') +const { Socks5Client, STATES } = require('../core/socks5-client') const { kDispatch, kClose, kDestroy } = require('../core/symbols') const Pool = require('./pool') const buildConnector = require('../core/connect') @@ -17,8 +16,10 @@ const debug = debuglog('undici:socks5-proxy') const kProxyUrl = Symbol('proxy url') const kProxyHeaders = Symbol('proxy headers') const kProxyAuth = Symbol('proxy auth') -const kPool = Symbol('pool') +const kProxyProtocol = Symbol('proxy protocol') +const kPools = Symbol('pools') const kConnector = Symbol('connector') +const kRequestTls = Symbol('request tls settings') // Static flag to ensure warning is only emitted once per process let experimentalWarningEmitted = false @@ -52,6 +53,8 @@ class Socks5ProxyAgent extends DispatcherBase { this[kProxyUrl] = url this[kProxyHeaders] = options.headers || {} + this[kProxyProtocol] = options.proxyTls ? 'https:' : 'http:' + this[kRequestTls] = options.requestTls // Extract auth from URL or options this[kProxyAuth] = { @@ -65,8 +68,8 @@ class Socks5ProxyAgent extends DispatcherBase { servername: options.proxyTls?.servername || url.hostname }) - // Pool for the actual HTTP connections (with SOCKS5 tunnel connect function) - this[kPool] = null + // Pools for the actual HTTP connections (with SOCKS5 tunnel connect function), keyed by origin + this[kPools] = new Map() } /** @@ -80,23 +83,18 @@ class Socks5ProxyAgent extends DispatcherBase { // Connect to the SOCKS5 proxy const socket = await new Promise((resolve, reject) => { - const onConnect = () => { - socket.removeListener('error', onError) - resolve(socket) - } - - const onError = (err) => { - socket.removeListener('connect', onConnect) - reject(err) - } - - const socket = net.connect({ + this[kConnector]({ + hostname: proxyHost, host: proxyHost, - port: proxyPort + port: proxyPort, + protocol: this[kProxyProtocol] + }, (err, socket) => { + if (err) { + reject(err) + } else { + resolve(socket) + } }) - - socket.once('connect', onConnect) - socket.once('error', onError) }) // Create SOCKS5 client @@ -130,7 +128,7 @@ class Socks5ProxyAgent extends DispatcherBase { } // Check if already authenticated (for NO_AUTH method) - if (socks5Client.state === 'authenticated') { + if (socks5Client.state === STATES.AUTHENTICATED) { clearTimeout(timeout) resolve() } else { @@ -171,15 +169,17 @@ class Socks5ProxyAgent extends DispatcherBase { /** * Dispatch a request through the SOCKS5 proxy */ - async [kDispatch] (opts, handler) { + [kDispatch] (opts, handler) { const { origin } = opts debug('dispatching request to', origin, 'via SOCKS5') try { - // Create Pool with custom connect function if we don't have one yet - if (!this[kPool] || this[kPool].destroyed || this[kPool].closed) { - this[kPool] = new Pool(origin, { + const originKey = String(origin) + let pool = this[kPools].get(originKey) + // Create a Pool per origin so requests are not routed to the wrong host + if (!pool || pool.destroyed || pool.closed) { + pool = new Pool(origin, { pipelining: opts.pipelining, connections: opts.connections, connect: async (connectOpts, callback) => { @@ -201,9 +201,9 @@ class Socks5ProxyAgent extends DispatcherBase { } debug('upgrading to TLS') finalSocket = tls.connect({ + ...this[kRequestTls], socket, - servername: targetHost, - ...connectOpts.tls || {} + servername: this[kRequestTls]?.servername || targetHost }) await new Promise((resolve, reject) => { @@ -219,14 +219,19 @@ class Socks5ProxyAgent extends DispatcherBase { } } }) + this[kPools].set(originKey, pool) } - // Dispatch the request through the pool - return this[kPool][kDispatch](opts, handler) + // Dispatch the request through the per-origin pool + return pool[kDispatch](opts, handler) } catch (err) { debug('dispatch error:', err) - if (typeof handler.onError === 'function') { + if (typeof handler.onResponseError === 'function') { + handler.onResponseError(null, err) + return false + } else if (typeof handler.onError === 'function') { handler.onError(err) + return false } else { throw err } @@ -234,15 +239,21 @@ class Socks5ProxyAgent extends DispatcherBase { } async [kClose] () { - if (this[kPool]) { - await this[kPool].close() + const closePromises = [] + for (const pool of this[kPools].values()) { + closePromises.push(pool.close()) } + this[kPools].clear() + await Promise.all(closePromises) } async [kDestroy] (err) { - if (this[kPool]) { - await this[kPool].destroy(err) + const destroyPromises = [] + for (const pool of this[kPools].values()) { + destroyPromises.push(pool.destroy(err)) } + this[kPools].clear() + await Promise.all(destroyPromises) } } diff --git a/deps/undici/src/lib/global.js b/deps/undici/src/lib/global.js index b61d779e498f06..565aceb4a03d09 100644 --- a/deps/undici/src/lib/global.js +++ b/deps/undici/src/lib/global.js @@ -2,7 +2,8 @@ // We include a version number for the Dispatcher API. In case of breaking changes, // this version number must be increased to avoid conflicts. -const globalDispatcher = Symbol.for('undici.globalDispatcher.1') +const globalDispatcher = Symbol.for('undici.globalDispatcher.2') +const legacyGlobalDispatcher = Symbol.for('undici.globalDispatcher.1') const { InvalidArgumentError } = require('./core/errors') const Agent = require('./dispatcher/agent') @@ -14,16 +15,24 @@ function setGlobalDispatcher (agent) { if (!agent || typeof agent.dispatch !== 'function') { throw new InvalidArgumentError('Argument agent must implement Agent') } + Object.defineProperty(globalThis, globalDispatcher, { value: agent, writable: true, enumerable: false, configurable: false }) + + Object.defineProperty(globalThis, legacyGlobalDispatcher, { + value: agent, + writable: true, + enumerable: false, + configurable: false + }) } function getGlobalDispatcher () { - return globalThis[globalDispatcher] + return globalThis[legacyGlobalDispatcher] } // These are the globals that can be installed by undici.install(). diff --git a/deps/undici/src/lib/handler/unwrap-handler.js b/deps/undici/src/lib/handler/unwrap-handler.js index e23b9666cf71fa..2949faea0fe9d0 100644 --- a/deps/undici/src/lib/handler/unwrap-handler.js +++ b/deps/undici/src/lib/handler/unwrap-handler.js @@ -13,6 +13,9 @@ class UnwrapController { [kResume] = null + rawHeaders = null + rawTrailers = null + constructor (abort) { this.#abort = abort } @@ -72,11 +75,13 @@ module.exports = class UnwrapHandler { } onUpgrade (statusCode, rawHeaders, socket) { + this.#controller.rawHeaders = rawHeaders this.#handler.onRequestUpgrade?.(this.#controller, statusCode, parseHeaders(rawHeaders), socket) } onHeaders (statusCode, rawHeaders, resume, statusMessage) { this.#controller[kResume] = resume + this.#controller.rawHeaders = rawHeaders this.#handler.onResponseStart?.(this.#controller, statusCode, parseHeaders(rawHeaders), statusMessage) return !this.#controller.paused } @@ -87,6 +92,7 @@ module.exports = class UnwrapHandler { } onComplete (rawTrailers) { + this.#controller.rawTrailers = rawTrailers this.#handler.onResponseEnd?.(this.#controller, parseHeaders(rawTrailers)) } diff --git a/deps/undici/src/lib/llhttp/wasm_build_env.txt b/deps/undici/src/lib/llhttp/wasm_build_env.txt index 3f5e2ae2859021..80834a2d8619a8 100644 --- a/deps/undici/src/lib/llhttp/wasm_build_env.txt +++ b/deps/undici/src/lib/llhttp/wasm_build_env.txt @@ -1,5 +1,5 @@ -> undici@7.25.0 build:wasm +> undici@7.28.0 build:wasm > node build/wasm.js --docker > docker run --rm --platform=linux/x86_64 --user 1001:1001 --mount type=bind,source=/home/runner/work/node/node/deps/undici/src/lib/llhttp,target=/home/node/build/lib/llhttp --mount type=bind,source=/home/runner/work/node/node/deps/undici/src/build,target=/home/node/build/build --mount type=bind,source=/home/runner/work/node/node/deps/undici/src/deps,target=/home/node/build/deps -t ghcr.io/nodejs/wasm-builder@sha256:975f391d907e42a75b8c72eb77c782181e941608687d4d8694c3e9df415a0970 node build/wasm.js diff --git a/deps/undici/src/lib/mock/mock-call-history.js b/deps/undici/src/lib/mock/mock-call-history.js index d4a92b2b24bc77..74de68247c7d2d 100644 --- a/deps/undici/src/lib/mock/mock-call-history.js +++ b/deps/undici/src/lib/mock/mock-call-history.js @@ -3,14 +3,14 @@ const { kMockCallHistoryAddLog } = require('./mock-symbols') const { InvalidArgumentError } = require('../core/errors') -function handleFilterCallsWithOptions (criteria, options, handler, store) { +function handleFilterCallsWithOptions (criteria, options, handler, store, allLogs) { switch (options.operator) { case 'OR': - store.push(...handler(criteria)) + store.push(...handler(criteria, allLogs)) return store case 'AND': - return handler.call({ logs: store }, criteria) + return handler(criteria, store) default: // guard -- should never happens because buildAndValidateFilterCallsOptions is called before throw new InvalidArgumentError('options.operator must to be a case insensitive string equal to \'OR\' or \'AND\'') @@ -35,14 +35,14 @@ function buildAndValidateFilterCallsOptions (options = {}) { } function makeFilterCalls (parameterName) { - return (parameterValue) => { + return (parameterValue, logs) => { if (typeof parameterValue === 'string' || parameterValue == null) { - return this.logs.filter((log) => { + return logs.filter((log) => { return log[parameterName] === parameterValue }) } if (parameterValue instanceof RegExp) { - return this.logs.filter((log) => { + return logs.filter((log) => { return parameterValue.test(log[parameterName]) }) } @@ -175,30 +175,30 @@ class MockCallHistory { const finalOptions = { operator: 'OR', ...buildAndValidateFilterCallsOptions(options) } - let maybeDuplicatedLogsFiltered = [] + let maybeDuplicatedLogsFiltered = finalOptions.operator === 'AND' ? this.logs : [] if ('protocol' in criteria) { - maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.protocol, finalOptions, this.filterCallsByProtocol, maybeDuplicatedLogsFiltered) + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.protocol, finalOptions, this.filterCallsByProtocol, maybeDuplicatedLogsFiltered, this.logs) } if ('host' in criteria) { - maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.host, finalOptions, this.filterCallsByHost, maybeDuplicatedLogsFiltered) + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.host, finalOptions, this.filterCallsByHost, maybeDuplicatedLogsFiltered, this.logs) } if ('port' in criteria) { - maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.port, finalOptions, this.filterCallsByPort, maybeDuplicatedLogsFiltered) + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.port, finalOptions, this.filterCallsByPort, maybeDuplicatedLogsFiltered, this.logs) } if ('origin' in criteria) { - maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.origin, finalOptions, this.filterCallsByOrigin, maybeDuplicatedLogsFiltered) + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.origin, finalOptions, this.filterCallsByOrigin, maybeDuplicatedLogsFiltered, this.logs) } if ('path' in criteria) { - maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.path, finalOptions, this.filterCallsByPath, maybeDuplicatedLogsFiltered) + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.path, finalOptions, this.filterCallsByPath, maybeDuplicatedLogsFiltered, this.logs) } if ('hash' in criteria) { - maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.hash, finalOptions, this.filterCallsByHash, maybeDuplicatedLogsFiltered) + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.hash, finalOptions, this.filterCallsByHash, maybeDuplicatedLogsFiltered, this.logs) } if ('fullUrl' in criteria) { - maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.fullUrl, finalOptions, this.filterCallsByFullUrl, maybeDuplicatedLogsFiltered) + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.fullUrl, finalOptions, this.filterCallsByFullUrl, maybeDuplicatedLogsFiltered, this.logs) } if ('method' in criteria) { - maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.method, finalOptions, this.filterCallsByMethod, maybeDuplicatedLogsFiltered) + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.method, finalOptions, this.filterCallsByMethod, maybeDuplicatedLogsFiltered, this.logs) } const uniqLogsFiltered = [...new Set(maybeDuplicatedLogsFiltered)] diff --git a/deps/undici/src/lib/util/cache.js b/deps/undici/src/lib/util/cache.js index 5968f4efe5f415..a8f112168e60fb 100644 --- a/deps/undici/src/lib/util/cache.js +++ b/deps/undici/src/lib/util/cache.js @@ -18,7 +18,7 @@ function makeCacheKey (opts) { let fullPath = opts.path || '/' - if (opts.query && !pathHasQueryOrFragment(opts.path)) { + if (opts.query && !pathHasQueryOrFragment(fullPath)) { fullPath = serializePathWithQuery(fullPath, opts.query) } @@ -228,6 +228,10 @@ function parseCacheControlHeader (header) { headers[headers.length - 1] = lastHeader } + for (let j = 0; j < headers.length; j++) { + headers[j] = headers[j].trim() + } + if (key in output) { output[key] = output[key].concat(headers) } else { @@ -236,10 +240,12 @@ function parseCacheControlHeader (header) { } } else { // Something like `no-cache="some-header"` + const fieldName = value.trim() + if (key in output) { - output[key] = output[key].concat(value) + output[key] = output[key].concat(fieldName) } else { - output[key] = [value] + output[key] = [fieldName] } } @@ -374,9 +380,11 @@ function assertCacheMethods (methods, name = 'CacheMethods') { * @returns {string} */ function makeDeduplicationKey (cacheKey, excludeHeaders) { - // Create a deterministic string key from the cache key - // Include origin, method, path, and sorted headers - let key = `${cacheKey.origin}:${cacheKey.method}:${cacheKey.path}` + // Use JSON.stringify to produce a collision-resistant key. + // Previous format used `:` and `=` delimiters without escaping, which + // allowed different header sets to produce identical keys (e.g. + // {a:"x:b=y"} vs {a:"x", b:"y"}). See: https://github.com/nodejs/undici/issues/5012 + const headers = {} if (cacheKey.headers) { const sortedHeaders = Object.keys(cacheKey.headers).sort() @@ -385,12 +393,11 @@ function makeDeduplicationKey (cacheKey, excludeHeaders) { if (excludeHeaders?.has(header.toLowerCase())) { continue } - const value = cacheKey.headers[header] - key += `:${header}=${Array.isArray(value) ? value.join(',') : value}` + headers[header] = cacheKey.headers[header] } } - return key + return JSON.stringify([cacheKey.origin, cacheKey.method, cacheKey.path, headers]) } module.exports = { diff --git a/deps/undici/src/lib/web/cookies/parse.js b/deps/undici/src/lib/web/cookies/parse.js index 74edf7ec6ac7fc..0e524908077c6d 100644 --- a/deps/undici/src/lib/web/cookies/parse.js +++ b/deps/undici/src/lib/web/cookies/parse.js @@ -4,7 +4,6 @@ const { collectASequenceOfCodePointsFast } = require('../infra') const { maxNameValuePairSize, maxAttributeValueSize } = require('./constants') const { isCTLExcludingHtab } = require('./util') const assert = require('node:assert') -const { unescape: qsUnescape } = require('node:querystring') /** * @description Parses the field-value attributes of a set-cookie header string. @@ -82,7 +81,7 @@ function parseSetCookie (header) { // store arbitrary data in a cookie-value SHOULD encode that data, for // example, using Base64 [RFC4648]. return { - name, value: qsUnescape(value), ...parseUnparsedAttributes(unparsedAttributes) + name, value, ...parseUnparsedAttributes(unparsedAttributes) } } @@ -280,32 +279,25 @@ function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {}) // If the attribute-name case-insensitively matches the string // "SameSite", the user agent MUST process the cookie-av as follows: - // 1. Let enforcement be "Default". - let enforcement = 'Default' - const attributeValueLowercase = attributeValue.toLowerCase() - // 2. If cookie-av's attribute-value is a case-insensitive match for - // "None", set enforcement to "None". - if (attributeValueLowercase.includes('none')) { - enforcement = 'None' - } - // 3. If cookie-av's attribute-value is a case-insensitive match for - // "Strict", set enforcement to "Strict". - if (attributeValueLowercase.includes('strict')) { - enforcement = 'Strict' + // 1. If cookie-av's attribute-value is a case-insensitive match for + // "None", append an attribute to the cookie-attribute-list with an + // attribute-name of "SameSite" and an attribute-value of "None". + if (attributeValueLowercase === 'none') { + cookieAttributeList.sameSite = 'None' + } else if (attributeValueLowercase === 'strict') { + // 2. If cookie-av's attribute-value is a case-insensitive match for + // "Strict", append an attribute to the cookie-attribute-list with + // an attribute-name of "SameSite" and an attribute-value of + // "Strict". + cookieAttributeList.sameSite = 'Strict' + } else if (attributeValueLowercase === 'lax') { + // 3. If cookie-av's attribute-value is a case-insensitive match for + // "Lax", append an attribute to the cookie-attribute-list with an + // attribute-name of "SameSite" and an attribute-value of "Lax". + cookieAttributeList.sameSite = 'Lax' } - - // 4. If cookie-av's attribute-value is a case-insensitive match for - // "Lax", set enforcement to "Lax". - if (attributeValueLowercase.includes('lax')) { - enforcement = 'Lax' - } - - // 5. Append an attribute to the cookie-attribute-list with an - // attribute-name of "SameSite" and an attribute-value of - // enforcement. - cookieAttributeList.sameSite = enforcement } else { cookieAttributeList.unparsed ??= [] diff --git a/deps/undici/src/lib/web/fetch/formdata-parser.js b/deps/undici/src/lib/web/fetch/formdata-parser.js index b65848998f7616..a4622ae10a356d 100644 --- a/deps/undici/src/lib/web/fetch/formdata-parser.js +++ b/deps/undici/src/lib/web/fetch/formdata-parser.js @@ -204,7 +204,7 @@ function multipartFormDataParser (input, mimeType) { * Parses content-disposition attributes (e.g., name="value" or filename*=utf-8''encoded) * @param {Buffer} input * @param {{ position: number }} position - * @returns {{ name: string, value: string }} + * @returns {{ name: string, value: string, extended: boolean } | null} */ function parseContentDispositionAttribute (input, position) { // Skip leading semicolon and whitespace @@ -304,7 +304,7 @@ function parseContentDispositionAttribute (input, position) { value = decoder.decode(tokenValue) } - return { name: attrNameStr, value } + return { name: attrNameStr, value, extended: isExtended } } /** @@ -368,6 +368,9 @@ function parseMultipartFormDataHeaders (input, position) { switch (bufferToLowerCasedHeaderName(headerName)) { case 'content-disposition': { name = filename = null + // Track whether filename was set from the extended (RFC 5987) form so + // a subsequent legacy `filename` attribute does not override it. + let filenameIsExtended = false // Collect the disposition type (should be "form-data") const dispositionType = collectASequenceOfBytes( @@ -383,8 +386,8 @@ function parseMultipartFormDataHeaders (input, position) { // Parse attributes recursively until CRLF while ( position.position < input.length && - input[position.position] !== 0x0d && - input[position.position + 1] !== 0x0a + (input[position.position] !== 0x0d || + input[position.position + 1] !== 0x0a) ) { const attribute = parseContentDispositionAttribute(input, position) @@ -395,7 +398,15 @@ function parseMultipartFormDataHeaders (input, position) { if (attribute.name === 'name') { name = attribute.value } else if (attribute.name === 'filename') { - filename = attribute.value + // Per RFC 5987 §4.1, when both legacy and extended forms of the + // same parameter are present, the extended (filename*) form takes + // precedence regardless of the order they appear in. + if (attribute.extended) { + filename = attribute.value + filenameIsExtended = true + } else if (!filenameIsExtended) { + filename = attribute.value + } } } @@ -448,7 +459,7 @@ function parseMultipartFormDataHeaders (input, position) { // 2.9. If position does not point to a sequence of bytes starting with 0x0D 0x0A // (CR LF), return failure. Otherwise, advance position by 2 (past the newline). - if (input[position.position] !== 0x0d && input[position.position + 1] !== 0x0a) { + if (input[position.position] !== 0x0d || input[position.position + 1] !== 0x0a) { throw parsingError('expected CRLF') } else { position.position += 2 diff --git a/deps/undici/src/lib/web/fetch/index.js b/deps/undici/src/lib/web/fetch/index.js index c48ed041cc6396..8aa86ff60ee283 100644 --- a/deps/undici/src/lib/web/fetch/index.js +++ b/deps/undici/src/lib/web/fetch/index.js @@ -1030,7 +1030,7 @@ function fetchFinale (fetchParams, response) { let responseStatus = 0 // 7. If fetchParams’s request’s mode is not "navigate" or response’s has-cross-origin-redirects is false: - if (fetchParams.request.mode !== 'navigator' || !response.hasCrossOriginRedirects) { + if (fetchParams.request.mode !== 'navigate' || !response.hasCrossOriginRedirects) { // 1. Set responseStatus to response’s status. responseStatus = response.status @@ -1433,7 +1433,10 @@ async function httpNetworkOrCacheFetch ( // 8. If contentLengthHeaderValue is non-null, then append // `Content-Length`/contentLengthHeaderValue to httpRequest’s header // list. - if (contentLengthHeaderValue != null) { + if ( + contentLengthHeaderValue != null && + !httpRequest.headersList.contains('content-length', true) + ) { httpRequest.headersList.append('content-length', contentLengthHeaderValue, true) } diff --git a/deps/undici/src/lib/web/webidl/index.js b/deps/undici/src/lib/web/webidl/index.js index 5518b4959062c3..58664859dc97f8 100644 --- a/deps/undici/src/lib/web/webidl/index.js +++ b/deps/undici/src/lib/web/webidl/index.js @@ -190,10 +190,10 @@ webidl.util.ConvertToInt = function (V, bitLength, signedness, flags) { } else { // 3. Otherwise: - // 1. Let lowerBound be -2^bitLength − 1. - lowerBound = Math.pow(-2, bitLength) - 1 + // 1. Let lowerBound be -2^(bitLength − 1). + lowerBound = -Math.pow(2, bitLength - 1) - // 2. Let upperBound be 2^bitLength − 1 − 1. + // 2. Let upperBound be 2^(bitLength − 1) − 1. upperBound = Math.pow(2, bitLength - 1) - 1 } @@ -272,9 +272,9 @@ webidl.util.ConvertToInt = function (V, bitLength, signedness, flags) { // 10. Set x to x modulo 2^bitLength. x = x % Math.pow(2, bitLength) - // 11. If signedness is "signed" and x ≥ 2^bitLength − 1, + // 11. If signedness is "signed" and x ≥ 2^(bitLength − 1), // then return x − 2^bitLength. - if (signedness === 'signed' && x >= Math.pow(2, bitLength) - 1) { + if (signedness === 'signed' && x >= Math.pow(2, bitLength - 1)) { return x - Math.pow(2, bitLength) } diff --git a/deps/undici/src/lib/web/websocket/permessage-deflate.js b/deps/undici/src/lib/web/websocket/permessage-deflate.js index 1f1a13038afb5f..6a6e43899c5a95 100644 --- a/deps/undici/src/lib/web/websocket/permessage-deflate.js +++ b/deps/undici/src/lib/web/websocket/permessage-deflate.js @@ -8,40 +8,35 @@ const tail = Buffer.from([0x00, 0x00, 0xff, 0xff]) const kBuffer = Symbol('kBuffer') const kLength = Symbol('kLength') -// Default maximum decompressed message size: 4 MB -const kDefaultMaxDecompressedSize = 4 * 1024 * 1024 - class PerMessageDeflate { /** @type {import('node:zlib').InflateRaw} */ #inflate #options = {} - /** @type {boolean} */ - #aborted = false - - /** @type {Function|null} */ - #currentCallback = null + #maxPayloadSize = 0 /** * @param {Map} extensions */ - constructor (extensions) { + constructor (extensions, options) { this.#options.serverNoContextTakeover = extensions.has('server_no_context_takeover') this.#options.serverMaxWindowBits = extensions.get('server_max_window_bits') + + this.#maxPayloadSize = options.maxPayloadSize } + /** + * Decompress a compressed payload. + * @param {Buffer} chunk Compressed data + * @param {boolean} fin Final fragment flag + * @param {Function} callback Callback function + */ decompress (chunk, fin, callback) { // An endpoint uses the following algorithm to decompress a message. // 1. Append 4 octets of 0x00 0x00 0xff 0xff to the tail end of the // payload of the message. // 2. Decompress the resulting data using DEFLATE. - - if (this.#aborted) { - callback(new MessageSizeExceededError()) - return - } - if (!this.#inflate) { let windowBits = Z_DEFAULT_WINDOWBITS @@ -64,23 +59,12 @@ class PerMessageDeflate { this.#inflate[kLength] = 0 this.#inflate.on('data', (data) => { - if (this.#aborted) { - return - } - this.#inflate[kLength] += data.length - if (this.#inflate[kLength] > kDefaultMaxDecompressedSize) { - this.#aborted = true + if (this.#maxPayloadSize > 0 && this.#inflate[kLength] > this.#maxPayloadSize) { + callback(new MessageSizeExceededError()) this.#inflate.removeAllListeners() - this.#inflate.destroy() this.#inflate = null - - if (this.#currentCallback) { - const cb = this.#currentCallback - this.#currentCallback = null - cb(new MessageSizeExceededError()) - } return } @@ -93,14 +77,13 @@ class PerMessageDeflate { }) } - this.#currentCallback = callback this.#inflate.write(chunk) if (fin) { this.#inflate.write(tail) } this.#inflate.flush(() => { - if (this.#aborted || !this.#inflate) { + if (!this.#inflate) { return } @@ -108,7 +91,6 @@ class PerMessageDeflate { this.#inflate[kBuffer].length = 0 this.#inflate[kLength] = 0 - this.#currentCallback = null callback(null, full) }) diff --git a/deps/undici/src/lib/web/websocket/receiver.js b/deps/undici/src/lib/web/websocket/receiver.js index 384808d1b7e8c3..a37bd22265a830 100644 --- a/deps/undici/src/lib/web/websocket/receiver.js +++ b/deps/undici/src/lib/web/websocket/receiver.js @@ -39,18 +39,27 @@ class ByteParser extends Writable { /** @type {import('./websocket').Handler} */ #handler + /** @type {number} */ + #maxFragments + + /** @type {number} */ + #maxPayloadSize + /** * @param {import('./websocket').Handler} handler * @param {Map|null} extensions + * @param {{ maxFragments?: number, maxPayloadSize?: number }} [options] */ - constructor (handler, extensions) { + constructor (handler, extensions, options = {}) { super() this.#handler = handler this.#extensions = extensions == null ? new Map() : extensions + this.#maxFragments = options.maxFragments ?? 0 + this.#maxPayloadSize = options.maxPayloadSize ?? 0 if (this.#extensions.has('permessage-deflate')) { - this.#extensions.set('permessage-deflate', new PerMessageDeflate(extensions)) + this.#extensions.set('permessage-deflate', new PerMessageDeflate(extensions, options)) } } @@ -66,6 +75,19 @@ class ByteParser extends Writable { this.run(callback) } + #validatePayloadLength () { + if ( + this.#maxPayloadSize > 0 && + !isControlFrame(this.#info.opcode) && + this.#info.payloadLength + this.#fragmentsBytes > this.#maxPayloadSize + ) { + failWebsocketConnection(this.#handler, 1009, 'Payload size exceeds maximum allowed size') + return false + } + + return true + } + /** * Runs whenever a new chunk is received. * Callback is called whenever there are no more chunks buffering, @@ -154,6 +176,10 @@ class ByteParser extends Writable { if (payloadLength <= 125) { this.#info.payloadLength = payloadLength this.#state = parserStates.READ_DATA + + if (!this.#validatePayloadLength()) { + return + } } else if (payloadLength === 126) { this.#state = parserStates.PAYLOADLENGTH_16 } else if (payloadLength === 127) { @@ -178,6 +204,10 @@ class ByteParser extends Writable { this.#info.payloadLength = buffer.readUInt16BE(0) this.#state = parserStates.READ_DATA + + if (!this.#validatePayloadLength()) { + return + } } else if (this.#state === parserStates.PAYLOADLENGTH_64) { if (this.#byteOffset < 8) { return callback() @@ -200,6 +230,10 @@ class ByteParser extends Writable { this.#info.payloadLength = lower this.#state = parserStates.READ_DATA + + if (!this.#validatePayloadLength()) { + return + } } else if (this.#state === parserStates.READ_DATA) { if (this.#byteOffset < this.#info.payloadLength) { return callback() @@ -212,7 +246,9 @@ class ByteParser extends Writable { this.#state = parserStates.INFO } else { if (!this.#info.compressed) { - this.writeFragments(body) + if (!this.writeFragments(body)) { + return + } // If the frame is not fragmented, a message has been received. // If the frame is fragmented, it will terminate with a fin bit set @@ -224,29 +260,41 @@ class ByteParser extends Writable { this.#state = parserStates.INFO } else { - this.#extensions.get('permessage-deflate').decompress(body, this.#info.fin, (error, data) => { - if (error) { - // Use 1009 (Message Too Big) for decompression size limit errors - const code = error instanceof MessageSizeExceededError ? 1009 : 1007 - failWebsocketConnection(this.#handler, code, error.message) - return - } - - this.writeFragments(data) + this.#extensions.get('permessage-deflate').decompress( + body, + this.#info.fin, + (error, data) => { + if (error) { + const code = error instanceof MessageSizeExceededError ? 1009 : 1007 + failWebsocketConnection(this.#handler, code, error.message) + return + } + + if (!this.writeFragments(data)) { + return + } + + // Check cumulative fragment size + if (this.#maxPayloadSize > 0 && this.#fragmentsBytes > this.#maxPayloadSize) { + failWebsocketConnection(this.#handler, 1009, new MessageSizeExceededError().message) + return + } + + if (!this.#info.fin) { + this.#state = parserStates.INFO + this.#loop = true + this.run(callback) + return + } + + websocketMessageReceived(this.#handler, this.#info.binaryType, this.consumeFragments()) - if (!this.#info.fin) { - this.#state = parserStates.INFO this.#loop = true + this.#state = parserStates.INFO this.run(callback) - return - } - - websocketMessageReceived(this.#handler, this.#info.binaryType, this.consumeFragments()) - - this.#loop = true - this.#state = parserStates.INFO - this.run(callback) - }) + }, + this.#fragmentsBytes + ) this.#loop = false break @@ -305,8 +353,17 @@ class ByteParser extends Writable { } writeFragments (fragment) { + if ( + this.#maxFragments > 0 && + this.#fragments.length === this.#maxFragments + ) { + failWebsocketConnection(this.#handler, 1008, 'Too many message fragments') + return false + } + this.#fragmentsBytes += fragment.length this.#fragments.push(fragment) + return true } consumeFragments () { diff --git a/deps/undici/src/lib/web/websocket/stream/websocketstream.js b/deps/undici/src/lib/web/websocket/stream/websocketstream.js index ce3be84fc3d034..1da0292b46502c 100644 --- a/deps/undici/src/lib/web/websocket/stream/websocketstream.js +++ b/deps/undici/src/lib/web/websocket/stream/websocketstream.js @@ -258,7 +258,14 @@ class WebSocketStream { #onConnectionEstablished (response, parsedExtensions) { this.#handler.socket = response.socket - const parser = new ByteParser(this.#handler, parsedExtensions) + // Get options from dispatcher options + const maxFragments = this.#handler.controller.dispatcher?.webSocketOptions?.maxFragments + const maxPayloadSize = this.#handler.controller.dispatcher?.webSocketOptions?.maxPayloadSize + + const parser = new ByteParser(this.#handler, parsedExtensions, { + maxFragments, + maxPayloadSize + }) parser.on('drain', () => this.#handler.onParserDrain()) parser.on('error', (err) => this.#handler.onParserError(err)) @@ -284,12 +291,6 @@ class WebSocketStream { start: (controller) => { this.#readableStreamController = controller }, - pull (controller) { - let chunk - while (controller.desiredSize > 0 && (chunk = response.socket.read()) !== null) { - controller.enqueue(chunk) - } - }, cancel: (reason) => this.#cancel(reason) }) @@ -338,7 +339,7 @@ class WebSocketStream { try { chunk = utf8Decode(data) } catch { - failWebsocketConnection(this.#handler, 'Received invalid UTF-8 in text frame.') + failWebsocketConnection(this.#handler, 1007, 'Received invalid UTF-8 in text frame.') return } } else if (type === opcodes.BINARY) { diff --git a/deps/undici/src/lib/web/websocket/websocket.js b/deps/undici/src/lib/web/websocket/websocket.js index da94ab5b352926..4f816ef17a7d91 100644 --- a/deps/undici/src/lib/web/websocket/websocket.js +++ b/deps/undici/src/lib/web/websocket/websocket.js @@ -468,7 +468,14 @@ class WebSocket extends EventTarget { // once this happens, the connection is open this.#handler.socket = response.socket - const parser = new ByteParser(this.#handler, parsedExtensions) + const webSocketOptions = this.#handler.controller.dispatcher?.webSocketOptions + const maxFragments = webSocketOptions?.maxFragments + const maxPayloadSize = webSocketOptions?.maxPayloadSize + + const parser = new ByteParser(this.#handler, parsedExtensions, { + maxFragments, + maxPayloadSize + }) parser.on('drain', () => this.#handler.onParserDrain()) parser.on('error', (err) => this.#handler.onParserError(err)) diff --git a/deps/undici/src/package-lock.json b/deps/undici/src/package-lock.json index e78bb21bf1b04c..81a8d5a4c447c9 100644 --- a/deps/undici/src/package-lock.json +++ b/deps/undici/src/package-lock.json @@ -1,12 +1,12 @@ { "name": "undici", - "version": "7.25.0", + "version": "7.28.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "undici", - "version": "7.25.0", + "version": "7.28.0", "license": "MIT", "devDependencies": { "@fastify/busboy": "3.2.0", @@ -76,13 +76,13 @@ "license": "MIT" }, "node_modules/@babel/code-frame": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", + "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -91,9 +91,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", - "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "dev": true, "license": "MIT", "engines": { @@ -101,21 +101,21 @@ } }, "node_modules/@babel/core": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", - "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.29.0", - "@babel/types": "^7.29.0", + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -132,14 +132,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.29.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", - "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.0", - "@babel/types": "^7.29.0", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -149,14 +149,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -166,9 +166,9 @@ } }, "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", "dev": true, "license": "MIT", "engines": { @@ -176,29 +176,29 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -208,9 +208,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", - "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", "dev": true, "license": "MIT", "engines": { @@ -218,9 +218,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "dev": true, "license": "MIT", "engines": { @@ -228,9 +228,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "dev": true, "license": "MIT", "engines": { @@ -238,9 +238,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", "dev": true, "license": "MIT", "engines": { @@ -248,27 +248,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", - "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", - "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.29.0" + "@babel/types": "^7.29.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -333,13 +333,13 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", - "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.29.7.tgz", + "integrity": "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -375,13 +375,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", - "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz", + "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -501,13 +501,13 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", - "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.29.7.tgz", + "integrity": "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -517,33 +517,33 @@ } }, "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", - "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0", + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", "debug": "^4.3.1" }, "engines": { @@ -551,14 +551,14 @@ } }, "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -1438,17 +1438,17 @@ } }, "node_modules/@jest/console": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.3.0.tgz", - "integrity": "sha512-PAwCvFJ4696XP2qZj+LAn1BWjZaJ6RjG6c7/lkMaUJnkyMS34ucuIsfqYvfskVNvUI27R/u4P1HMYFnlVXG/Ww==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.4.1.tgz", + "integrity": "sha512-v3bhyxUh9Hgmo5p6hAOXe14/R3ZxZDOsvHleh4B07z3m/x4/ngPUXEm9XwK4sF4u+f+P2ORb0Ge+MgpaqRMVDA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.3.0", + "@jest/types": "30.4.1", "@types/node": "*", "chalk": "^4.1.2", - "jest-message-util": "30.3.0", - "jest-util": "30.3.0", + "jest-message-util": "30.4.1", + "jest-util": "30.4.1", "slash": "^3.0.0" }, "engines": { @@ -1456,38 +1456,39 @@ } }, "node_modules/@jest/core": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.3.0.tgz", - "integrity": "sha512-U5mVPsBxLSO6xYbf+tgkymLx+iAhvZX43/xI1+ej2ZOPnPdkdO1CzDmFKh2mZBn2s4XZixszHeQnzp1gm/DIxw==", + "version": "30.4.2", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.4.2.tgz", + "integrity": "sha512-TZJA6cPJUFxoWhxaLo8t0VX/MZX2wPWr0uIDvLSHIvN4gu9h02vSzqI2kBADG1ExqQlC+cY09xKMSreivvrChQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "30.3.0", - "@jest/pattern": "30.0.1", - "@jest/reporters": "30.3.0", - "@jest/test-result": "30.3.0", - "@jest/transform": "30.3.0", - "@jest/types": "30.3.0", + "@jest/console": "30.4.1", + "@jest/pattern": "30.4.0", + "@jest/reporters": "30.4.1", + "@jest/test-result": "30.4.1", + "@jest/transform": "30.4.1", + "@jest/types": "30.4.1", "@types/node": "*", "ansi-escapes": "^4.3.2", "chalk": "^4.1.2", "ci-info": "^4.2.0", "exit-x": "^0.2.2", + "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.11", - "jest-changed-files": "30.3.0", - "jest-config": "30.3.0", - "jest-haste-map": "30.3.0", - "jest-message-util": "30.3.0", - "jest-regex-util": "30.0.1", - "jest-resolve": "30.3.0", - "jest-resolve-dependencies": "30.3.0", - "jest-runner": "30.3.0", - "jest-runtime": "30.3.0", - "jest-snapshot": "30.3.0", - "jest-util": "30.3.0", - "jest-validate": "30.3.0", - "jest-watcher": "30.3.0", - "pretty-format": "30.3.0", + "jest-changed-files": "30.4.1", + "jest-config": "30.4.2", + "jest-haste-map": "30.4.1", + "jest-message-util": "30.4.1", + "jest-regex-util": "30.4.0", + "jest-resolve": "30.4.1", + "jest-resolve-dependencies": "30.4.2", + "jest-runner": "30.4.2", + "jest-runtime": "30.4.2", + "jest-snapshot": "30.4.1", + "jest-util": "30.4.1", + "jest-validate": "30.4.1", + "jest-watcher": "30.4.1", + "pretty-format": "30.4.1", "slash": "^3.0.0" }, "engines": { @@ -1503,9 +1504,9 @@ } }, "node_modules/@jest/diff-sequences": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.3.0.tgz", - "integrity": "sha512-cG51MVnLq1ecVUaQ3fr6YuuAOitHK1S4WUJHnsPFE/quQr33ADUx1FfrTCpMCRxvy0Yr9BThKpDjSlcTi91tMA==", + "version": "30.4.0", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.4.0.tgz", + "integrity": "sha512-zOpzlfUs45l6u7jm39qr87JCHUDsaeCtvL+kQe/Vn9jSnRB4/5IPXISm0h9I1vZW/o00Kn4UTJ2MOlhnUGwv3g==", "dev": true, "license": "MIT", "engines": { @@ -1513,39 +1514,39 @@ } }, "node_modules/@jest/environment": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.3.0.tgz", - "integrity": "sha512-SlLSF4Be735yQXyh2+mctBOzNDx5s5uLv88/j8Qn1wH679PDcwy67+YdADn8NJnGjzlXtN62asGH/T4vWOkfaw==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.4.1.tgz", + "integrity": "sha512-AK9yNRqgKxiabqMoe4oW+3/TSSeV8vkdC7BGaxZdU0AFXfOpofTLqdru2GXKZghP3sdgwE9XXpnVwfZ8JnFV4w==", "dev": true, "license": "MIT", "dependencies": { - "@jest/fake-timers": "30.3.0", - "@jest/types": "30.3.0", + "@jest/fake-timers": "30.4.1", + "@jest/types": "30.4.1", "@types/node": "*", - "jest-mock": "30.3.0" + "jest-mock": "30.4.1" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/expect": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.3.0.tgz", - "integrity": "sha512-76Nlh4xJxk2D/9URCn3wFi98d2hb19uWE1idLsTt2ywhvdOldbw3S570hBgn25P4ICUZ/cBjybrBex2g17IDbg==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.4.1.tgz", + "integrity": "sha512-ginrj6TMgh2GshLUGCjO94Ptx9HhdZA/I6A9iUfyeLKFtdAjnKzHDgzgP9HYQgbxM1lbXScQ2eUBz2lGeVDPWA==", "dev": true, "license": "MIT", "dependencies": { - "expect": "30.3.0", - "jest-snapshot": "30.3.0" + "expect": "30.4.1", + "jest-snapshot": "30.4.1" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.3.0.tgz", - "integrity": "sha512-j0+W5iQQ8hBh7tHZkTQv3q2Fh/M7Je72cIsYqC4OaktgtO7v1So9UTjp6uPBHIaB6beoF/RRsCgMJKvti0wADA==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.4.1.tgz", + "integrity": "sha512-ZBn5CglH8fBsQsvs4VWNzD4aWfUYks+IdOOQU3MEK71ol/BcVm+P+rtb1KpiFBpSWSCE27uOahyyf1vfqOVbcQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1556,27 +1557,27 @@ } }, "node_modules/@jest/fake-timers": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.3.0.tgz", - "integrity": "sha512-WUQDs8SOP9URStX1DzhD425CqbN/HxUYCTwVrT8sTVBfMvFqYt/s61EK5T05qnHu0po6RitXIvP9otZxYDzTGQ==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.4.1.tgz", + "integrity": "sha512-iW5umdmfPeWzehrVhugFQZqCchSCud5S1l2YT0O9ZhjRR0ExclANDZkiSBwzqtnlOn0J1JXvO+HZ6rkuyOVOgQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.3.0", - "@sinonjs/fake-timers": "^15.0.0", + "@jest/types": "30.4.1", + "@sinonjs/fake-timers": "^15.4.0", "@types/node": "*", - "jest-message-util": "30.3.0", - "jest-mock": "30.3.0", - "jest-util": "30.3.0" + "jest-message-util": "30.4.1", + "jest-mock": "30.4.1", + "jest-util": "30.4.1" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/fake-timers/node_modules/@sinonjs/fake-timers": { - "version": "15.3.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-15.3.2.tgz", - "integrity": "sha512-mrn35Jl2pCpns+mE3HaZa1yPN5EYCRgiMI+135COjr2hr8Cls9DXqIZ57vZe2cz7y2XVSq92tcs6kGQcT1J8Rw==", + "version": "15.4.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-15.4.0.tgz", + "integrity": "sha512-DsG+8/LscQIQg68J6Ef3dv10u6nVyetYn923s3/sus5eaGfTo1of5WMZSLf0UJc9KDuKPilPH0UDJCjvNbDNCA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -1594,47 +1595,47 @@ } }, "node_modules/@jest/globals": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.3.0.tgz", - "integrity": "sha512-+owLCBBdfpgL3HU+BD5etr1SvbXpSitJK0is1kiYjJxAAJggYMRQz5hSdd5pq1sSggfxPbw2ld71pt4x5wwViA==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.4.1.tgz", + "integrity": "sha512-ZbuY4cmXC8DkxYjfvT2DbcHWL2T6vmsMhXCDcmTB2T0y0gaezBI77ufq5ZAIdcRkYZ7NEQEDg1xFeKbxUJ5v5Q==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.3.0", - "@jest/expect": "30.3.0", - "@jest/types": "30.3.0", - "jest-mock": "30.3.0" + "@jest/environment": "30.4.1", + "@jest/expect": "30.4.1", + "@jest/types": "30.4.1", + "jest-mock": "30.4.1" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/pattern": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", - "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", + "version": "30.4.0", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.4.0.tgz", + "integrity": "sha512-RAWn3+f9u8BsHijKJ71uHcFp6vmyEt6VvoWXkl6hKF3qVIuWNmudVjg12DlBPGup/frIl5UcUlH5HfEuvHpEXg==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", - "jest-regex-util": "30.0.1" + "jest-regex-util": "30.4.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/reporters": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.3.0.tgz", - "integrity": "sha512-a09z89S+PkQnL055bVj8+pe2Caed2PBOaczHcXCykW5ngxX9EWx/1uAwncxc/HiU0oZqfwseMjyhxgRjS49qPw==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.4.1.tgz", + "integrity": "sha512-/SnkPCzEQpUaBH81kjdEdDdo2WZl5hxw+BmLDGWjRkm8o7XlhjwsU36cqwe5PGBE5WYpBvDzRSdXx9rbGuJtNA==", "dev": true, "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "30.3.0", - "@jest/test-result": "30.3.0", - "@jest/transform": "30.3.0", - "@jest/types": "30.3.0", + "@jest/console": "30.4.1", + "@jest/test-result": "30.4.1", + "@jest/transform": "30.4.1", + "@jest/types": "30.4.1", "@jridgewell/trace-mapping": "^0.3.25", "@types/node": "*", "chalk": "^4.1.2", @@ -1647,9 +1648,9 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^5.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "30.3.0", - "jest-util": "30.3.0", - "jest-worker": "30.3.0", + "jest-message-util": "30.4.1", + "jest-util": "30.4.1", + "jest-worker": "30.4.1", "slash": "^3.0.0", "string-length": "^4.0.2", "v8-to-istanbul": "^9.0.1" @@ -1674,9 +1675,9 @@ "license": "MIT" }, "node_modules/@jest/schemas": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", - "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.4.1.tgz", + "integrity": "sha512-i6b4qw5qnP8c5FEeBJg/uZQ4ddrkN6Ca8qISJh0pr7a5hfn3h3v5x60BEbOC7OYAGZNMs1LfFLwnW2CuK8F57Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1687,13 +1688,13 @@ } }, "node_modules/@jest/snapshot-utils": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.3.0.tgz", - "integrity": "sha512-ORbRN9sf5PP82v3FXNSwmO1OTDR2vzR2YTaR+E3VkSBZ8zadQE6IqYdYEeFH1NIkeB2HIGdF02dapb6K0Mj05g==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.4.1.tgz", + "integrity": "sha512-ObY4ljvQ95mt6iwKtVLetR/4yXiAgl3H4nJxhztr0MTjrN97TwDYrnCp/kF60Ec9HdhkWTHSu+Hg05aXfngpOA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.3.0", + "@jest/types": "30.4.1", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", "natural-compare": "^1.4.0" @@ -1718,14 +1719,14 @@ } }, "node_modules/@jest/test-result": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.3.0.tgz", - "integrity": "sha512-e/52nJGuD74AKTSe0P4y5wFRlaXP0qmrS17rqOMHeSwm278VyNyXE3gFO/4DTGF9w+65ra3lo3VKj0LBrzmgdQ==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.4.1.tgz", + "integrity": "sha512-/ZG7pgEiOmmWkN9TplKbOu4id2N5lh7FHwRwlkgBVAzGdRH+OkkQ8wX/kIxg4zmd3ZQvAL1RwL2yWsvNYYECTw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "30.3.0", - "@jest/types": "30.3.0", + "@jest/console": "30.4.1", + "@jest/types": "30.4.1", "@types/istanbul-lib-coverage": "^2.0.6", "collect-v8-coverage": "^1.0.2" }, @@ -1734,15 +1735,15 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.3.0.tgz", - "integrity": "sha512-dgbWy9b8QDlQeRZcv7LNF+/jFiiYHTKho1xirauZ7kVwY7avjFF6uTT0RqlgudB5OuIPagFdVtfFMosjVbk1eA==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.4.1.tgz", + "integrity": "sha512-PeYE+4td5rKjoRPxztObrXU+H8hsjZfxKMXOcmrr34JerSyB/ROOxbbicz8B7A5j9R9VayDnVPvBmedqCsFCdw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/test-result": "30.3.0", + "@jest/test-result": "30.4.1", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.3.0", + "jest-haste-map": "30.4.1", "slash": "^3.0.0" }, "engines": { @@ -1750,23 +1751,23 @@ } }, "node_modules/@jest/transform": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.3.0.tgz", - "integrity": "sha512-TLKY33fSLVd/lKB2YI1pH69ijyUblO/BQvCj566YvnwuzoTNr648iE0j22vRvVNk2HsPwByPxATg3MleS3gf5A==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.4.1.tgz", + "integrity": "sha512-Wz0LyktlTvRefoymh+n64hQ84KNXsRGcwdoZ8CSa0Ea+fgYcHZlnk+hDP7v2MS7il2bQ5uTEIxf4/NNfhMN4KQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.27.4", - "@jest/types": "30.3.0", + "@jest/types": "30.4.1", "@jridgewell/trace-mapping": "^0.3.25", "babel-plugin-istanbul": "^7.0.1", "chalk": "^4.1.2", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.3.0", - "jest-regex-util": "30.0.1", - "jest-util": "30.3.0", + "jest-haste-map": "30.4.1", + "jest-regex-util": "30.4.0", + "jest-util": "30.4.1", "pirates": "^4.0.7", "slash": "^3.0.0", "write-file-atomic": "^5.0.1" @@ -1776,14 +1777,14 @@ } }, "node_modules/@jest/types": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.3.0.tgz", - "integrity": "sha512-JHm87k7bA33hpBngtU8h6UBub/fqqA9uXfw+21j5Hmk7ooPHlboRNxHq0JcMtC+n8VJGP1mcfnD3Mk+XKe1oSw==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.4.1.tgz", + "integrity": "sha512-f1x/vJXIfjOlEmejYpbkbgw1gOqpPECwMvMEtBqe47j7H2Hg8h8w3o3ikhSXq3MI15kg+oQ0exWO0uCtTNJLoQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/pattern": "30.0.1", - "@jest/schemas": "30.0.5", + "@jest/pattern": "30.4.0", + "@jest/schemas": "30.4.1", "@types/istanbul-lib-coverage": "^2.0.6", "@types/istanbul-reports": "^3.0.4", "@types/node": "*", @@ -1873,16 +1874,22 @@ } }, "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", - "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.5.tgz", + "integrity": "sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==", "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@tybys/wasm-util": "^0.10.0" + "@tybys/wasm-util": "^0.10.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" } }, "node_modules/@nodelib/fs.scandir": { @@ -1952,13 +1959,13 @@ } }, "node_modules/@pkgr/core": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", - "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.3.6.tgz", + "integrity": "sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==", "dev": true, "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + "node": "^14.18.0 || >=16.0.0" }, "funding": { "url": "https://opencollective.com/pkgr" @@ -2053,9 +2060,9 @@ } }, "node_modules/@tybys/wasm-util": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", - "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", + "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", "dev": true, "license": "MIT", "optional": true, @@ -2120,9 +2127,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "dev": true, "license": "MIT" }, @@ -2168,9 +2175,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.19.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.39.tgz", - "integrity": "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw==", + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", "dev": true, "license": "MIT", "dependencies": { @@ -2209,17 +2216,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.1.tgz", - "integrity": "sha512-BOziFIfE+6osHO9FoJG4zjoHUcvI7fTNBSpdAwrNH0/TLvzjsk2oo8XSSOT2HhqUyhZPfHv4UOffoJ9oEEQ7Ag==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.61.0.tgz", + "integrity": "sha512-bFNvl9ZczlVb+wR2Akszf3gHfKVj/8WanXaGJ3UstTA7brNKg0cNdk6X1Psu5V7MZ2oQtzZKOEzIUehaoxbDGw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.59.1", - "@typescript-eslint/type-utils": "8.59.1", - "@typescript-eslint/utils": "8.59.1", - "@typescript-eslint/visitor-keys": "8.59.1", + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/type-utils": "8.61.0", + "@typescript-eslint/utils": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -2232,7 +2239,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.59.1", + "@typescript-eslint/parser": "^8.61.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } @@ -2248,16 +2255,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.59.1.tgz", - "integrity": "sha512-HDQH9O/47Dxi1ceDhBXdaldtf/WV9yRYMjbjCuNk3qnaTD564qwv61Y7+gTxwxRKzSrgO5uhtw584igXVuuZkA==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.61.0.tgz", + "integrity": "sha512-5B7PfA2e1NQGCnDHd/0lW7W3gvp3d59Ryw54FYO8Uswxo9f6ikw3AZV+Xj/TvpImmpsiYyUqAfhC6kJID1jF6w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.59.1", - "@typescript-eslint/types": "8.59.1", - "@typescript-eslint/typescript-estree": "8.59.1", - "@typescript-eslint/visitor-keys": "8.59.1", + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", "debug": "^4.4.3" }, "engines": { @@ -2273,14 +2280,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.59.1.tgz", - "integrity": "sha512-+MuHQlHiEr00Of/IQbE/MmEoi44znZHbR/Pz7Opq4HryUOlRi+/44dro9Ycy8Fyo+/024IWtw8m4JUMCGTYxDg==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.61.0.tgz", + "integrity": "sha512-DV42F7MLJO6Rax7SK1yg43tcnEfGUrurSpSxKuVX+a3RCTzBlH3fuxprrOJXKCJGAaw82xXocikJ0uQaqwXgGA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.59.1", - "@typescript-eslint/types": "^8.59.1", + "@typescript-eslint/tsconfig-utils": "^8.61.0", + "@typescript-eslint/types": "^8.61.0", "debug": "^4.4.3" }, "engines": { @@ -2295,14 +2302,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.1.tgz", - "integrity": "sha512-LwuHQI4pDOYVKvmH2dkaJo6YZCSgouVgnS/z7yBPKBMvgtBvyLqiLy9Z6b7+m/TRcX1NFYUqZetI5Y+aT4GEfg==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.61.0.tgz", + "integrity": "sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.59.1", - "@typescript-eslint/visitor-keys": "8.59.1" + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2313,9 +2320,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.1.tgz", - "integrity": "sha512-/0nEyPbX7gRsk0Uwfe4ALwwgxuA66d/l2mhRDNlAvaj4U3juhUtJNq0DsY8M2AYwwb9rEq2hrC3IcIcEt++iJA==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.0.tgz", + "integrity": "sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ==", "dev": true, "license": "MIT", "engines": { @@ -2330,15 +2337,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.59.1.tgz", - "integrity": "sha512-klWPBR2ciQHS3f++ug/mVnWKPjBUo7icEL3FAO1lhAR1Z1i5NQYZ1EannMSRYcq5qCv5wNALlXr6fksRHyYl7w==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.61.0.tgz", + "integrity": "sha512-TuBiQYIkd97yBfInHCTKVYMbX4kvEmpOEuixIuzCU9p8BGT1SfyyO0d0IfDMbPIHcjn/hWnusUX5e8v5Xg+X8A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.59.1", - "@typescript-eslint/typescript-estree": "8.59.1", - "@typescript-eslint/utils": "8.59.1", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/utils": "8.61.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -2355,9 +2362,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.1.tgz", - "integrity": "sha512-ZDCjgccSdYPw5Bxh+my4Z0lJU96ZDN7jbBzvmEn0FZx3RtU1C7VWl6NbDx94bwY3V5YsgwRzJPOgeY2Q/nLG8A==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.61.0.tgz", + "integrity": "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg==", "dev": true, "license": "MIT", "engines": { @@ -2369,16 +2376,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.1.tgz", - "integrity": "sha512-OUd+vJS05sSkOip+BkZ/2NS8RMxrAAJemsC6vU3kmfLyeaJT0TftHkV9mcx2107MmsBVXXexhVu4F0TZXyMl4g==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.0.tgz", + "integrity": "sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.59.1", - "@typescript-eslint/tsconfig-utils": "8.59.1", - "@typescript-eslint/types": "8.59.1", - "@typescript-eslint/visitor-keys": "8.59.1", + "@typescript-eslint/project-service": "8.61.0", + "@typescript-eslint/tsconfig-utils": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -2407,9 +2414,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", - "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, "license": "MIT", "dependencies": { @@ -2436,9 +2443,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", "dev": true, "license": "ISC", "bin": { @@ -2449,16 +2456,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.1.tgz", - "integrity": "sha512-3pIeoXhCeYH9FSCBI8P3iNwJlGuzPlYKkTlen2O9T1DSeeg8UG8jstq6BLk+Mda0qup7mgk4z4XL4OzRaxZ8LA==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.61.0.tgz", + "integrity": "sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.59.1", - "@typescript-eslint/types": "8.59.1", - "@typescript-eslint/typescript-estree": "8.59.1" + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2473,13 +2480,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.1.tgz", - "integrity": "sha512-LdDNl6C5iJExcM0Yh0PwAIBb9PrSiCsWamF/JyEZawm3kFDnRoaq3LGE4bpyRao/fWeGKKyw7icx0YxrLFC5Cg==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.61.0.tgz", + "integrity": "sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/types": "8.61.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -2504,16 +2511,16 @@ } }, "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz", + "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==", "dev": true, "license": "ISC" }, "node_modules/@unrs/resolver-binding-android-arm-eabi": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", - "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz", + "integrity": "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==", "cpu": [ "arm" ], @@ -2525,9 +2532,9 @@ ] }, "node_modules/@unrs/resolver-binding-android-arm64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", - "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.12.2.tgz", + "integrity": "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==", "cpu": [ "arm64" ], @@ -2539,9 +2546,9 @@ ] }, "node_modules/@unrs/resolver-binding-darwin-arm64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", - "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.12.2.tgz", + "integrity": "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==", "cpu": [ "arm64" ], @@ -2553,9 +2560,9 @@ ] }, "node_modules/@unrs/resolver-binding-darwin-x64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", - "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.12.2.tgz", + "integrity": "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==", "cpu": [ "x64" ], @@ -2567,9 +2574,9 @@ ] }, "node_modules/@unrs/resolver-binding-freebsd-x64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", - "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.12.2.tgz", + "integrity": "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==", "cpu": [ "x64" ], @@ -2581,9 +2588,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", - "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.12.2.tgz", + "integrity": "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==", "cpu": [ "arm" ], @@ -2595,9 +2602,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", - "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.12.2.tgz", + "integrity": "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==", "cpu": [ "arm" ], @@ -2609,9 +2616,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", - "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.12.2.tgz", + "integrity": "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==", "cpu": [ "arm64" ], @@ -2626,9 +2633,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", - "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.12.2.tgz", + "integrity": "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==", "cpu": [ "arm64" ], @@ -2642,10 +2649,44 @@ "linux" ] }, + "node_modules/@unrs/resolver-binding-linux-loong64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.12.2.tgz", + "integrity": "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.12.2.tgz", + "integrity": "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", - "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.12.2.tgz", + "integrity": "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==", "cpu": [ "ppc64" ], @@ -2660,9 +2701,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", - "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.12.2.tgz", + "integrity": "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==", "cpu": [ "riscv64" ], @@ -2677,9 +2718,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", - "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.12.2.tgz", + "integrity": "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==", "cpu": [ "riscv64" ], @@ -2694,9 +2735,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", - "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.12.2.tgz", + "integrity": "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==", "cpu": [ "s390x" ], @@ -2711,9 +2752,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", - "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz", + "integrity": "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==", "cpu": [ "x64" ], @@ -2728,9 +2769,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", - "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.12.2.tgz", + "integrity": "sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==", "cpu": [ "x64" ], @@ -2744,10 +2785,24 @@ "linux" ] }, + "node_modules/@unrs/resolver-binding-openharmony-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.12.2.tgz", + "integrity": "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, "node_modules/@unrs/resolver-binding-wasm32-wasi": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", - "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.12.2.tgz", + "integrity": "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==", "cpu": [ "wasm32" ], @@ -2755,16 +2810,18 @@ "license": "MIT", "optional": true, "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.11" + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", - "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz", + "integrity": "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==", "cpu": [ "arm64" ], @@ -2776,9 +2833,9 @@ ] }, "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", - "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.12.2.tgz", + "integrity": "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==", "cpu": [ "ia32" ], @@ -2790,9 +2847,9 @@ ] }, "node_modules/@unrs/resolver-binding-win32-x64-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", - "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.12.2.tgz", + "integrity": "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==", "cpu": [ "x64" ], @@ -2817,9 +2874,9 @@ } }, "node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", "dev": true, "license": "MIT", "bin": { @@ -3234,16 +3291,16 @@ } }, "node_modules/babel-jest": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.3.0.tgz", - "integrity": "sha512-gRpauEU2KRrCox5Z296aeVHR4jQ98BCnu0IO332D/xpHNOsIH/bgSRk9k6GbKIbBw8vFeN6ctuu6tV8WOyVfYQ==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.4.1.tgz", + "integrity": "sha512-fATAbM8piYxkiXQp3RBXmZHxZVNJZAVXXfyeyCN2Tida3+qJ8ea9UxhiJ2y4fLO90ZImKt6k9FlcH2+rLkJGhw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/transform": "30.3.0", + "@jest/transform": "30.4.1", "@types/babel__core": "^7.20.5", "babel-plugin-istanbul": "^7.0.1", - "babel-preset-jest": "30.3.0", + "babel-preset-jest": "30.4.0", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", "slash": "^3.0.0" @@ -3313,9 +3370,9 @@ } }, "node_modules/babel-plugin-jest-hoist": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.3.0.tgz", - "integrity": "sha512-+TRkByhsws6sfPjVaitzadk1I0F5sPvOVUH5tyTSzhePpsGIVrdeunHSw/C36QeocS95OOk8lunc4rlu5Anwsg==", + "version": "30.4.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.4.0.tgz", + "integrity": "sha512-9EdtWM/sSfXLOGLwSn+GS6pIXyBnL07/8gyJlwFXjWy4DxMOyItqyUT29d4lQiS380EZwYlX7/At4PgBS+m2aA==", "dev": true, "license": "MIT", "dependencies": { @@ -3353,13 +3410,13 @@ } }, "node_modules/babel-preset-jest": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.3.0.tgz", - "integrity": "sha512-6ZcUbWHC+dMz2vfzdNwi87Z1gQsLNK2uLuK1Q89R11xdvejcivlYYwDlEv0FHX3VwEXpbBQ9uufB/MUNpZGfhQ==", + "version": "30.4.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.4.0.tgz", + "integrity": "sha512-lBY4jxsNmCnSiu7kquw8ZC9F4+XLMOKypT3RnNHPvU2Kpd4W0xaPuLr5ZkRyOsvLYAY4yaW1ZwTW4xB7NIiZzg==", "dev": true, "license": "MIT", "dependencies": { - "babel-plugin-jest-hoist": "30.3.0", + "babel-plugin-jest-hoist": "30.4.0", "babel-preset-current-node-syntax": "^1.2.0" }, "engines": { @@ -3377,9 +3434,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.10.23", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.23.tgz", - "integrity": "sha512-xwVXGqevyKPsiuQdLj+dZMVjidjJV508TBqexND5HrF89cGdCYCJFB3qhcxRHSeMctdCfbR1jrxBajhDy7o29g==", + "version": "2.10.37", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.37.tgz", + "integrity": "sha512-girxaJ7WZssDOFhzCGZTDKoTa1gk6A1TbflaYTpykLJ4UU9Fz9kx1aREM8JCuoVHbL8X8T/mJg7w2oYSq72Oig==", "dev": true, "license": "Apache-2.0", "bin": { @@ -3414,9 +3471,9 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", "dependencies": { @@ -3670,9 +3727,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001791", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001791.tgz", - "integrity": "sha512-yk0l/YSrOnFZk3UROpDLQD9+kC1l4meK/wed583AXrzoarMGJcbRi2Q4RaUYbKxYAsZ8sWmaSa/DsLmdBeI1vQ==", + "version": "1.0.30001799", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", + "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", "dev": true, "funding": [ { @@ -3857,9 +3914,9 @@ "license": "MIT" }, "node_modules/comment-parser": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.6.tgz", - "integrity": "sha512-ObxuY6vnbWTN6Od72xfwN9DbzC7Y2vv8u1Soi9ahRKL37gb6y1qk6/dgjs+3JWuXJHWvsg3BXIwzd/rkmAwavg==", + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.7.tgz", + "integrity": "sha512-0h+uSNtQGW3D98eQt3jJ8L06Fves8hncB4V/PKdw/Qb8Hnk19VaKuTr55UNRYiSoVa7WwrFls+rh3ux9agmkeQ==", "dev": true, "license": "MIT", "engines": { @@ -4172,9 +4229,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.344", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.344.tgz", - "integrity": "sha512-4MxfbmNDm+KPh066EZy+eUnkcDPcZ35wNmOWzFuh/ijvHsve6kbLTLURy88uCNK5FbpN+yk2nQY6BYh1GEt+wg==", + "version": "1.5.372", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.372.tgz", + "integrity": "sha512-M3yhbAlilnwqC8D21t28UCDGHyitShTmmLRU/H+b74P6Ski16Nb9HONYEaVpMj/pwC7BEo5B95FpjODLCWbtfA==", "dev": true, "license": "ISC" }, @@ -4199,9 +4256,9 @@ "license": "MIT" }, "node_modules/enhanced-resolve": { - "version": "5.21.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.0.tgz", - "integrity": "sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA==", + "version": "5.24.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.0.tgz", + "integrity": "sha512-SkE2t82KlkkxQRVMVLAGKxLfORGQfrkx5dkj+vlgXRVNEdPc4eZcR+J/Fvj8C+yKSFH5L0q3NFlyufOVQnCcYQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4312,9 +4369,9 @@ } }, "node_modules/es-iterator-helpers": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.2.tgz", - "integrity": "sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.3.tgz", + "integrity": "sha512-0PuBxFi+4uPanB97iDxCLWuHeYud2FALrw5HFZGtAF38UpJDbDC8frwp2cnDyae692CQ0dou60UwWfhgsa4U/g==", "dev": true, "license": "MIT", "dependencies": { @@ -4340,9 +4397,9 @@ } }, "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", "dev": true, "license": "MIT", "dependencies": { @@ -4541,9 +4598,9 @@ } }, "node_modules/eslint-compat-utils/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", "dev": true, "license": "ISC", "bin": { @@ -4752,9 +4809,9 @@ } }, "node_modules/eslint-plugin-import-x/node_modules/brace-expansion": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", - "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, "license": "MIT", "dependencies": { @@ -4781,9 +4838,9 @@ } }, "node_modules/eslint-plugin-import-x/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", "dev": true, "license": "ISC", "bin": { @@ -4834,9 +4891,9 @@ } }, "node_modules/eslint-plugin-n/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", "dev": true, "license": "ISC", "bin": { @@ -5120,27 +5177,27 @@ } }, "node_modules/expect": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-30.3.0.tgz", - "integrity": "sha512-1zQrciTiQfRdo7qJM1uG4navm8DayFa2TgCSRlzUyNkhcJ6XUZF3hjnpkyr3VhAqPH7i/9GkG7Tv5abz6fqz0Q==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.4.1.tgz", + "integrity": "sha512-PMARsyh/JtqC20HoGqlFcIlQAyqUtW4PlI1rup1uhYJtKuwAjbvWi3GQMAn+STdHum/dk8xrKfUM1+5SAwpolA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/expect-utils": "30.3.0", + "@jest/expect-utils": "30.4.1", "@jest/get-type": "30.1.0", - "jest-matcher-utils": "30.3.0", - "jest-message-util": "30.3.0", - "jest-mock": "30.3.0", - "jest-util": "30.3.0" + "jest-matcher-utils": "30.4.1", + "jest-message-util": "30.4.1", + "jest-mock": "30.4.1", + "jest-util": "30.4.1" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/fast-check": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-4.7.0.tgz", - "integrity": "sha512-NsZRtqvSSoCP0HbNjUD+r1JH8zqZalyp6gLY9e7OYs7NK9b6AHOs2baBFeBG7bVNsuoukh89x2Yg3rPsul8ziQ==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-4.8.0.tgz", + "integrity": "sha512-GOJ158CUMnN6cSahsv4+ExARvIDuzzinFjkp0E9WtiBa5zcVeLozVkWaE4IzFcc+Y48Wp1EDlUZsXRyAztQcSg==", "dev": true, "funding": [ { @@ -5396,18 +5453,21 @@ } }, "node_modules/function.prototype.name": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.2.0.tgz", + "integrity": "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", - "hasown": "^2.0.2", - "is-callable": "^1.2.7" + "has-property-descriptors": "^1.0.2", + "hasown": "^2.0.4", + "is-callable": "^1.2.7", + "is-document.all": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -5589,9 +5649,9 @@ } }, "node_modules/glob/node_modules/brace-expansion": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", - "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", "dev": true, "license": "MIT", "dependencies": { @@ -5784,9 +5844,9 @@ } }, "node_modules/hasown": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", - "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "dev": true, "license": "MIT", "dependencies": { @@ -6062,9 +6122,9 @@ } }, "node_modules/is-bun-module/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", "dev": true, "license": "ISC", "bin": { @@ -6088,13 +6148,13 @@ } }, "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", "dev": true, "license": "MIT", "dependencies": { - "hasown": "^2.0.2" + "hasown": "^2.0.3" }, "engines": { "node": ">= 0.4" @@ -6138,6 +6198,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-document.all": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-document.all/-/is-document.all-1.0.0.tgz", + "integrity": "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -6496,9 +6572,9 @@ } }, "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", "dev": true, "license": "ISC", "bin": { @@ -6587,16 +6663,16 @@ } }, "node_modules/jest": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-30.3.0.tgz", - "integrity": "sha512-AkXIIFcaazymvey2i/+F94XRnM6TsVLZDhBMLsd1Sf/W0wzsvvpjeyUrCZD6HGG4SDYPgDJDBKeiJTBb10WzMg==", + "version": "30.4.2", + "resolved": "https://registry.npmjs.org/jest/-/jest-30.4.2.tgz", + "integrity": "sha512-Yi1jqNC/Oq0N4hBgNH/YvBpP1P57QqundgytzYqy3yqAa7NZPNjSoi4SGbRAXDMdBzNE6xBCi5U7RgfrvMEUVQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/core": "30.3.0", - "@jest/types": "30.3.0", + "@jest/core": "30.4.2", + "@jest/types": "30.4.1", "import-local": "^3.2.0", - "jest-cli": "30.3.0" + "jest-cli": "30.4.2" }, "bin": { "jest": "bin/jest.js" @@ -6614,14 +6690,14 @@ } }, "node_modules/jest-changed-files": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.3.0.tgz", - "integrity": "sha512-B/7Cny6cV5At6M25EWDgf9S617lHivamL8vl6KEpJqkStauzcG4e+WPfDgMMF+H4FVH4A2PLRyvgDJan4441QA==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.4.1.tgz", + "integrity": "sha512-IuctmYrxi21iOSOaIXpJWalHyPAsVv0GeBHKDn8C1CA4W5htHn7INL+wdnL4Bo0+olEndvAFkmb++tIQJG+vvg==", "dev": true, "license": "MIT", "dependencies": { "execa": "^5.1.1", - "jest-util": "30.3.0", + "jest-util": "30.4.1", "p-limit": "^3.1.0" }, "engines": { @@ -6719,29 +6795,29 @@ } }, "node_modules/jest-circus": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.3.0.tgz", - "integrity": "sha512-PyXq5szeSfR/4f1lYqCmmQjh0vqDkURUYi9N6whnHjlRz4IUQfMcXkGLeEoiJtxtyPqgUaUUfyQlApXWBSN1RA==", + "version": "30.4.2", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.4.2.tgz", + "integrity": "sha512-rvHH7VlY6LgbJXJTQ87GW62g1FntOtbhh0zT+v04kC+pgL6aBKyYINXxWukCpj3dcIBMw5/XUbtDS9dU9JTXeQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.3.0", - "@jest/expect": "30.3.0", - "@jest/test-result": "30.3.0", - "@jest/types": "30.3.0", + "@jest/environment": "30.4.1", + "@jest/expect": "30.4.1", + "@jest/test-result": "30.4.1", + "@jest/types": "30.4.1", "@types/node": "*", "chalk": "^4.1.2", "co": "^4.6.0", "dedent": "^1.6.0", "is-generator-fn": "^2.1.0", - "jest-each": "30.3.0", - "jest-matcher-utils": "30.3.0", - "jest-message-util": "30.3.0", - "jest-runtime": "30.3.0", - "jest-snapshot": "30.3.0", - "jest-util": "30.3.0", + "jest-each": "30.4.1", + "jest-matcher-utils": "30.4.1", + "jest-message-util": "30.4.1", + "jest-runtime": "30.4.2", + "jest-snapshot": "30.4.1", + "jest-util": "30.4.1", "p-limit": "^3.1.0", - "pretty-format": "30.3.0", + "pretty-format": "30.4.1", "pure-rand": "^7.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" @@ -6768,21 +6844,21 @@ "license": "MIT" }, "node_modules/jest-cli": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.3.0.tgz", - "integrity": "sha512-l6Tqx+j1fDXJEW5bqYykDQQ7mQg+9mhWXtnj+tQZrTWYHyHoi6Be8HPumDSA+UiX2/2buEgjA58iJzdj146uCw==", + "version": "30.4.2", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.4.2.tgz", + "integrity": "sha512-jfA2ocvVHMXS2QijrJ0d31ektP+d/W0T5RpcTX2Pq+3sVqHlsXVCM2+FmwpL+bdY8OfHpIg9xMxLF17Zg0U49Q==", "dev": true, "license": "MIT", "dependencies": { - "@jest/core": "30.3.0", - "@jest/test-result": "30.3.0", - "@jest/types": "30.3.0", + "@jest/core": "30.4.2", + "@jest/test-result": "30.4.1", + "@jest/types": "30.4.1", "chalk": "^4.1.2", "exit-x": "^0.2.2", "import-local": "^3.2.0", - "jest-config": "30.3.0", - "jest-util": "30.3.0", - "jest-validate": "30.3.0", + "jest-config": "30.4.2", + "jest-util": "30.4.1", + "jest-validate": "30.4.1", "yargs": "^17.7.2" }, "bin": { @@ -6801,33 +6877,33 @@ } }, "node_modules/jest-config": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.3.0.tgz", - "integrity": "sha512-WPMAkMAtNDY9P/oKObtsRG/6KTrhtgPJoBTmk20uDn4Uy6/3EJnnaZJre/FMT1KVRx8cve1r7/FlMIOfRVWL4w==", + "version": "30.4.2", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.4.2.tgz", + "integrity": "sha512-rNHAShJQqQwFNoL0hbf3BphSBOWnpOUAKvidLS/AjNVLPfoj5mSf4jQMfW3cYOs6hXeZC7nF7mDHaBnbxELOzg==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.27.4", "@jest/get-type": "30.1.0", - "@jest/pattern": "30.0.1", - "@jest/test-sequencer": "30.3.0", - "@jest/types": "30.3.0", - "babel-jest": "30.3.0", + "@jest/pattern": "30.4.0", + "@jest/test-sequencer": "30.4.1", + "@jest/types": "30.4.1", + "babel-jest": "30.4.1", "chalk": "^4.1.2", "ci-info": "^4.2.0", "deepmerge": "^4.3.1", "glob": "^10.5.0", "graceful-fs": "^4.2.11", - "jest-circus": "30.3.0", - "jest-docblock": "30.2.0", - "jest-environment-node": "30.3.0", - "jest-regex-util": "30.0.1", - "jest-resolve": "30.3.0", - "jest-runner": "30.3.0", - "jest-util": "30.3.0", - "jest-validate": "30.3.0", + "jest-circus": "30.4.2", + "jest-docblock": "30.4.0", + "jest-environment-node": "30.4.1", + "jest-regex-util": "30.4.0", + "jest-resolve": "30.4.1", + "jest-runner": "30.4.2", + "jest-util": "30.4.1", + "jest-validate": "30.4.1", "parse-json": "^5.2.0", - "pretty-format": "30.3.0", + "pretty-format": "30.4.1", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -6852,25 +6928,25 @@ } }, "node_modules/jest-diff": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.3.0.tgz", - "integrity": "sha512-n3q4PDQjS4LrKxfWB3Z5KNk1XjXtZTBwQp71OP0Jo03Z6V60x++K5L8k6ZrW8MY8pOFylZvHM0zsjS1RqlHJZQ==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.4.1.tgz", + "integrity": "sha512-CRpFK0RtLriVDGcPPAnR6HMVI8bSR2jnUIgralhauzYQZIb4RH9AtEInTuQr65LmmGggGcRT6HIASxwqsVsmlA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/diff-sequences": "30.3.0", + "@jest/diff-sequences": "30.4.0", "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "pretty-format": "30.3.0" + "pretty-format": "30.4.1" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-docblock": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.2.0.tgz", - "integrity": "sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==", + "version": "30.4.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.4.0.tgz", + "integrity": "sha512-ZPMabUZCx5MpbZ2eBYSvZ0J8fvo3dR9oM+eeUpb3aKNQFuS2tu3Duw1TNlMoP8k3WQgKGJuhcMFvwcVuq6T7oA==", "dev": true, "license": "MIT", "dependencies": { @@ -6881,36 +6957,36 @@ } }, "node_modules/jest-each": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.3.0.tgz", - "integrity": "sha512-V8eMndg/aZ+3LnCJgSm13IxS5XSBM22QSZc9BtPK8Dek6pm+hfUNfwBdvsB3d342bo1q7wnSkC38zjX259qZNA==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.4.1.tgz", + "integrity": "sha512-/8MJbH6fuj48TstjrMf+u/pd06Qezz5xOXvZA6442heNOWr8bdeoGZX2d9fCn028CoMgYmroH9//zky5GfyYmA==", "dev": true, "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", - "@jest/types": "30.3.0", + "@jest/types": "30.4.1", "chalk": "^4.1.2", - "jest-util": "30.3.0", - "pretty-format": "30.3.0" + "jest-util": "30.4.1", + "pretty-format": "30.4.1" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-environment-node": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.3.0.tgz", - "integrity": "sha512-4i6HItw/JSiJVsC5q0hnKIe/hbYfZLVG9YJ/0pU9Hz2n/9qZe3Rhn5s5CUZA5ORZlcdT/vmAXRMyONXJwPrmYQ==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.4.1.tgz", + "integrity": "sha512-4FZYVOk85hz2AyT6BbarKy9u37g6DbrDyCdFhsnDdXqyrueYQvB+0zO4f/kqLCRD0BsPRXPMNJeQwihKZV8naw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.3.0", - "@jest/fake-timers": "30.3.0", - "@jest/types": "30.3.0", + "@jest/environment": "30.4.1", + "@jest/fake-timers": "30.4.1", + "@jest/types": "30.4.1", "@types/node": "*", - "jest-mock": "30.3.0", - "jest-util": "30.3.0", - "jest-validate": "30.3.0" + "jest-mock": "30.4.1", + "jest-util": "30.4.1", + "jest-validate": "30.4.1" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -6927,20 +7003,20 @@ } }, "node_modules/jest-haste-map": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.3.0.tgz", - "integrity": "sha512-mMi2oqG4KRU0R9QEtscl87JzMXfUhbKaFqOxmjb2CKcbHcUGFrJCBWHmnTiUqi6JcnzoBlO4rWfpdl2k/RfLCA==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.4.1.tgz", + "integrity": "sha512-rFrcONd8jeFsyw+Z9CrScJgglRf2+NFmNam8dKu7n+SoHqNYT47mn0DdEcVUZJpvh7Iz6/si7f7yUH7GJHVgnw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.3.0", + "@jest/types": "30.4.1", "@types/node": "*", "anymatch": "^3.1.3", "fb-watchman": "^2.0.2", "graceful-fs": "^4.2.11", - "jest-regex-util": "30.0.1", - "jest-util": "30.3.0", - "jest-worker": "30.3.0", + "jest-regex-util": "30.4.0", + "jest-util": "30.4.1", + "jest-worker": "30.4.1", "picomatch": "^4.0.3", "walker": "^1.0.8" }, @@ -6952,49 +7028,50 @@ } }, "node_modules/jest-leak-detector": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.3.0.tgz", - "integrity": "sha512-cuKmUUGIjfXZAiGJ7TbEMx0bcqNdPPI6P1V+7aF+m/FUJqFDxkFR4JqkTu8ZOiU5AaX/x0hZ20KaaIPXQzbMGQ==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.4.1.tgz", + "integrity": "sha512-IpmyiioeHxiWDhesHnUFmOxcTzwCwKpgACgWajtAP+nYQXiY7DakTxB6Bx9JFiRMljr0AX1PvnQdaU1KFoz6NQ==", "dev": true, "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", - "pretty-format": "30.3.0" + "pretty-format": "30.4.1" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.3.0.tgz", - "integrity": "sha512-HEtc9uFQgaUHkC7nLSlQL3Tph4Pjxt/yiPvkIrrDCt9jhoLIgxaubo1G+CFOnmHYMxHwwdaSN7mkIFs6ZK8OhA==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.4.1.tgz", + "integrity": "sha512-zvYfX5CaeEkFrrLS9suWe9rvJrm9J1Iv3ua8kIBv9GEPzcnsfBf0bob37la7s67fs0nlBC3EuvkOLnXQKxtx4A==", "dev": true, "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "jest-diff": "30.3.0", - "pretty-format": "30.3.0" + "jest-diff": "30.4.1", + "pretty-format": "30.4.1" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-message-util": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", - "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.4.1.tgz", + "integrity": "sha512-kwCKIvq0MCW1HzLoGola9Te6JUdzgV0loyKJ3Qghrkz9i5/RRIHsL95BMQc2HBBhlBKC4j22K9p11TGHH8RBpQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.3.0", + "@jest/types": "30.4.1", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", + "jest-util": "30.4.1", "picomatch": "^4.0.3", - "pretty-format": "30.3.0", + "pretty-format": "30.4.1", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -7003,15 +7080,15 @@ } }, "node_modules/jest-mock": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.3.0.tgz", - "integrity": "sha512-OTzICK8CpE+t4ndhKrwlIdbM6Pn8j00lvmSmq5ejiO+KxukbLjgOflKWMn3KE34EZdQm5RqTuKj+5RIEniYhog==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.4.1.tgz", + "integrity": "sha512-/i8SVb8/NSB7RfNi8gfqu8gxLV23KaL5EpAttyb9iz8qWRIqXRLflycz/32wXsYkOnaUlx8NAKnJYtpsmXUmfw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.3.0", + "@jest/types": "30.4.1", "@types/node": "*", - "jest-util": "30.3.0" + "jest-util": "30.4.1" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -7036,9 +7113,9 @@ } }, "node_modules/jest-regex-util": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", - "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "version": "30.4.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.4.0.tgz", + "integrity": "sha512-mWlvLviKIgIQ8VCuM1xRdD0TWp3zlzionlmDBjuXVBs+VkmXq6FgW9T4Emr7oGz/Rk6feDCGyiugolcQEyp3mg==", "dev": true, "license": "MIT", "engines": { @@ -7046,18 +7123,18 @@ } }, "node_modules/jest-resolve": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.3.0.tgz", - "integrity": "sha512-NRtTAHQlpd15F9rUR36jqwelbrDV/dY4vzNte3S2kxCKUJRYNd5/6nTSbYiak1VX5g8IoFF23Uj5TURkUW8O5g==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.4.1.tgz", + "integrity": "sha512-Zry8Yq/yJcNAZ7dJ5F2heic8AheXvbFZ7XI5V+h28nrYZ7Qoyy4dItq8OodjnYD270mvX+ZudmrNV9cysqhW5Q==", "dev": true, "license": "MIT", "dependencies": { "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.3.0", + "jest-haste-map": "30.4.1", "jest-pnp-resolver": "^1.2.3", - "jest-util": "30.3.0", - "jest-validate": "30.3.0", + "jest-util": "30.4.1", + "jest-validate": "30.4.1", "slash": "^3.0.0", "unrs-resolver": "^1.7.11" }, @@ -7066,46 +7143,46 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.3.0.tgz", - "integrity": "sha512-9ev8s3YN6Hsyz9LV75XUwkCVFlwPbaFn6Wp75qnI0wzAINYWY8Fb3+6y59Rwd3QaS3kKXffHXsZMziMavfz/nw==", + "version": "30.4.2", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.4.2.tgz", + "integrity": "sha512-gDiVh1I+GxYzz9oXlyw+1wv6VOYX1WYxMOfjsA3iGKePV2oxmbHhwxfkALxNxYy1ciw6APWwkW2zZONwP97aEQ==", "dev": true, "license": "MIT", "dependencies": { - "jest-regex-util": "30.0.1", - "jest-snapshot": "30.3.0" + "jest-regex-util": "30.4.0", + "jest-snapshot": "30.4.1" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-runner": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.3.0.tgz", - "integrity": "sha512-gDv6C9LGKWDPLia9TSzZwf4h3kMQCqyTpq+95PODnTRDO0g9os48XIYYkS6D236vjpBir2fF63YmJFtqkS5Duw==", + "version": "30.4.2", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.4.2.tgz", + "integrity": "sha512-2dw0PslVYXxffXGpLo+Ejad+KcI1Qkjn7f4X4619gf21oCUmL+SPfjqIa/losUem3yEOvfNZe/F1HWUcNpODcg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "30.3.0", - "@jest/environment": "30.3.0", - "@jest/test-result": "30.3.0", - "@jest/transform": "30.3.0", - "@jest/types": "30.3.0", + "@jest/console": "30.4.1", + "@jest/environment": "30.4.1", + "@jest/test-result": "30.4.1", + "@jest/transform": "30.4.1", + "@jest/types": "30.4.1", "@types/node": "*", "chalk": "^4.1.2", "emittery": "^0.13.1", "exit-x": "^0.2.2", "graceful-fs": "^4.2.11", - "jest-docblock": "30.2.0", - "jest-environment-node": "30.3.0", - "jest-haste-map": "30.3.0", - "jest-leak-detector": "30.3.0", - "jest-message-util": "30.3.0", - "jest-resolve": "30.3.0", - "jest-runtime": "30.3.0", - "jest-util": "30.3.0", - "jest-watcher": "30.3.0", - "jest-worker": "30.3.0", + "jest-docblock": "30.4.0", + "jest-environment-node": "30.4.1", + "jest-haste-map": "30.4.1", + "jest-leak-detector": "30.4.1", + "jest-message-util": "30.4.1", + "jest-resolve": "30.4.1", + "jest-runtime": "30.4.2", + "jest-util": "30.4.1", + "jest-watcher": "30.4.1", + "jest-worker": "30.4.1", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -7114,32 +7191,32 @@ } }, "node_modules/jest-runtime": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.3.0.tgz", - "integrity": "sha512-CgC+hIBJbuh78HEffkhNKcbXAytQViplcl8xupqeIWyKQF50kCQA8J7GeJCkjisC6hpnC9Muf8jV5RdtdFbGng==", + "version": "30.4.2", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.4.2.tgz", + "integrity": "sha512-3/5e8iPz2k/VLqlr8DgTftYyLUv8Su3FkCAO2/Od81UsUTpSxOrS6O5x5KkoQwyUjmpYyDJKeyAvg2T2nvpNkQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.3.0", - "@jest/fake-timers": "30.3.0", - "@jest/globals": "30.3.0", + "@jest/environment": "30.4.1", + "@jest/fake-timers": "30.4.1", + "@jest/globals": "30.4.1", "@jest/source-map": "30.0.1", - "@jest/test-result": "30.3.0", - "@jest/transform": "30.3.0", - "@jest/types": "30.3.0", + "@jest/test-result": "30.4.1", + "@jest/transform": "30.4.1", + "@jest/types": "30.4.1", "@types/node": "*", "chalk": "^4.1.2", "cjs-module-lexer": "^2.1.0", "collect-v8-coverage": "^1.0.2", "glob": "^10.5.0", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.3.0", - "jest-message-util": "30.3.0", - "jest-mock": "30.3.0", - "jest-regex-util": "30.0.1", - "jest-resolve": "30.3.0", - "jest-snapshot": "30.3.0", - "jest-util": "30.3.0", + "jest-haste-map": "30.4.1", + "jest-message-util": "30.4.1", + "jest-mock": "30.4.1", + "jest-regex-util": "30.4.0", + "jest-resolve": "30.4.1", + "jest-snapshot": "30.4.1", + "jest-util": "30.4.1", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -7148,9 +7225,9 @@ } }, "node_modules/jest-snapshot": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.3.0.tgz", - "integrity": "sha512-f14c7atpb4O2DeNhwcvS810Y63wEn8O1HqK/luJ4F6M4NjvxmAKQwBUWjbExUtMxWJQ0wVgmCKymeJK6NZMnfQ==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.4.1.tgz", + "integrity": "sha512-tEOkkfOMppUyeiHwjZswOQ3lcnoTnws/q5FnGIaeIh/jmoU0ZlgMYRR8sTlTj+nNGCoJ0RDq6SfxGxCsyMTPmw==", "dev": true, "license": "MIT", "dependencies": { @@ -7159,20 +7236,20 @@ "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/types": "^7.27.3", - "@jest/expect-utils": "30.3.0", + "@jest/expect-utils": "30.4.1", "@jest/get-type": "30.1.0", - "@jest/snapshot-utils": "30.3.0", - "@jest/transform": "30.3.0", - "@jest/types": "30.3.0", + "@jest/snapshot-utils": "30.4.1", + "@jest/transform": "30.4.1", + "@jest/types": "30.4.1", "babel-preset-current-node-syntax": "^1.2.0", "chalk": "^4.1.2", - "expect": "30.3.0", + "expect": "30.4.1", "graceful-fs": "^4.2.11", - "jest-diff": "30.3.0", - "jest-matcher-utils": "30.3.0", - "jest-message-util": "30.3.0", - "jest-util": "30.3.0", - "pretty-format": "30.3.0", + "jest-diff": "30.4.1", + "jest-matcher-utils": "30.4.1", + "jest-message-util": "30.4.1", + "jest-util": "30.4.1", + "pretty-format": "30.4.1", "semver": "^7.7.2", "synckit": "^0.11.8" }, @@ -7181,9 +7258,9 @@ } }, "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", "dev": true, "license": "ISC", "bin": { @@ -7194,13 +7271,13 @@ } }, "node_modules/jest-util": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", - "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.4.1.tgz", + "integrity": "sha512-vjQb1sACEiv13DKJMDToJpzVW0joCsIQrmbg0fi7CyOOt+g9jTuQl2A216pWRBYhOVt53XbL/2LbMKg1BECWOw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.3.0", + "@jest/types": "30.4.1", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", @@ -7212,18 +7289,18 @@ } }, "node_modules/jest-validate": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.3.0.tgz", - "integrity": "sha512-I/xzC8h5G+SHCb2P2gWkJYrNiTbeL47KvKeW5EzplkyxzBRBw1ssSHlI/jXec0ukH2q7x2zAWQm7015iusg62Q==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.4.1.tgz", + "integrity": "sha512-PDWi4SOwLnwqNDfHZjOcsEFyZ4fc/2W2gVL3DEoyqnB6jCQMLRtfBong8s6omIw3lI0HWOus12xfnFmQtjW3fw==", "dev": true, "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", - "@jest/types": "30.3.0", + "@jest/types": "30.4.1", "camelcase": "^6.3.0", "chalk": "^4.1.2", "leven": "^3.1.0", - "pretty-format": "30.3.0" + "pretty-format": "30.4.1" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -7243,19 +7320,19 @@ } }, "node_modules/jest-watcher": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.3.0.tgz", - "integrity": "sha512-PJ1d9ThtTR8aMiBWUdcownq9mDdLXsQzJayTk4kmaBRHKvwNQn+ANveuhEBUyNI2hR1TVhvQ8D5kHubbzBHR/w==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.4.1.tgz", + "integrity": "sha512-/l9UonmvCwjHH7d2h3iAwIloLc1H0S8mJZ/LNK3i86hqwPAz8otUJjP9MfYtz9Tt77Su5FD2xGjZn8d31IZHlw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/test-result": "30.3.0", - "@jest/types": "30.3.0", + "@jest/test-result": "30.4.1", + "@jest/types": "30.4.1", "@types/node": "*", "ansi-escapes": "^4.3.2", "chalk": "^4.1.2", "emittery": "^0.13.1", - "jest-util": "30.3.0", + "jest-util": "30.4.1", "string-length": "^4.0.2" }, "engines": { @@ -7263,15 +7340,15 @@ } }, "node_modules/jest-worker": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.3.0.tgz", - "integrity": "sha512-DrCKkaQwHexjRUFTmPzs7sHQe0TSj9nvDALKGdwmK5mW9v7j90BudWirKAJHt3QQ9Dhrg1F7DogPzhChppkJpQ==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.4.1.tgz", + "integrity": "sha512-SHynN/q/QD++iNyvMdy+WMmbCGk8jIsNcRxycXbWubSOhvo6T+j2afcfUSl+3hYsiBebOTo0cT7c2H7CXugu1g==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", "@ungap/structured-clone": "^1.3.0", - "jest-util": "30.3.0", + "jest-util": "30.4.1", "merge-stream": "^2.0.0", "supports-color": "^8.1.1" }, @@ -7303,10 +7380,20 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -7370,9 +7457,9 @@ } }, "node_modules/jsondiffpatch": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/jsondiffpatch/-/jsondiffpatch-0.7.3.tgz", - "integrity": "sha512-zd4dqFiXSYyant2WgSXAZ9+yYqilNVvragVNkNRn2IFZKgjyULNrKRznqN4Zon0MkLueCg+3QaPVCnDAVP20OQ==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/jsondiffpatch/-/jsondiffpatch-0.7.6.tgz", + "integrity": "sha512-zE9+AXFq+MkTolDor2Cw1nJzLC0aleqPkYf52Kb4Kn4mJcka/gFHpGI2JBVEJCfWOvBl0OoxZS+wuLdislQcqg==", "dev": true, "license": "MIT", "dependencies": { @@ -7545,9 +7632,9 @@ } }, "node_modules/make-dir/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", "dev": true, "license": "ISC", "bin": { @@ -7930,11 +8017,14 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.38", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz", - "integrity": "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==", + "version": "2.0.47", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.47.tgz", + "integrity": "sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/normalize-package-data": { "version": "3.0.3", @@ -7953,9 +8043,9 @@ } }, "node_modules/normalize-package-data/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", "dev": true, "license": "ISC", "bin": { @@ -8539,15 +8629,16 @@ } }, "node_modules/pretty-format": { - "version": "30.3.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", - "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.4.1.tgz", + "integrity": "sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/schemas": "30.0.5", + "@jest/schemas": "30.4.1", "ansi-styles": "^5.2.0", - "react-is": "^18.3.1" + "react-is-18": "npm:react-is@^18.3.1", + "react-is-19": "npm:react-is@^19.2.5" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -8594,13 +8685,6 @@ "react-is": "^16.13.1" } }, - "node_modules/prop-types/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true, - "license": "MIT" - }, "node_modules/proxy": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/proxy/-/proxy-2.2.0.tgz", @@ -8678,12 +8762,28 @@ } }, "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/react-is-18": { + "name": "react-is", "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, "license": "MIT" }, + "node_modules/react-is-19": { + "name": "react-is", + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.7.tgz", + "integrity": "sha512-kZFnouyVv7eP/Phmrlo9FK+zcAdriZJvzxXHF1Sl1P377WSGe2G/JxVolhTrB/jeV47lKImhNUsijjHAAbcl/A==", + "dev": true, + "license": "MIT" + }, "node_modules/read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", @@ -8925,14 +9025,14 @@ } }, "node_modules/resolve": { - "version": "2.0.0-next.6", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.6.tgz", - "integrity": "sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA==", + "version": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "is-core-module": "^2.16.1", + "is-core-module": "^2.16.2", "node-exports-info": "^1.6.0", "object-keys": "^1.1.1", "path-parse": "^1.0.7", @@ -9177,15 +9277,15 @@ } }, "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" }, @@ -9534,19 +9634,20 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", - "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.11.tgz", + "integrity": "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", "define-data-property": "^1.1.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-object-atoms": "^1.0.0", - "has-property-descriptors": "^1.0.2" + "es-abstract": "^1.24.2", + "es-object-atoms": "^1.1.2", + "has-property-descriptors": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -9556,16 +9657,16 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", - "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.10.tgz", + "integrity": "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "es-object-atoms": "^1.1.2" }, "engines": { "node": ">= 0.4" @@ -9722,13 +9823,13 @@ } }, "node_modules/synckit": { - "version": "0.11.12", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz", - "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.13.tgz", + "integrity": "sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg==", "dev": true, "license": "MIT", "dependencies": { - "@pkgr/core": "^0.2.9" + "@pkgr/core": "^0.3.6" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -9777,9 +9878,9 @@ } }, "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", - "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, "license": "MIT", "dependencies": { @@ -9806,9 +9907,9 @@ } }, "node_modules/tinyglobby": { - "version": "0.2.16", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", - "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "license": "MIT", "dependencies": { @@ -9984,6 +10085,13 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/tsd/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -10096,18 +10204,18 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", - "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.8.tgz", + "integrity": "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0", - "reflect.getprototypeof": "^1.0.6" + "call-bind": "^1.0.9", + "for-each": "^0.3.5", + "gopd": "^1.2.0", + "is-typed-array": "^1.1.15", + "possible-typed-array-names": "^1.1.0", + "reflect.getprototypeof": "^1.0.10" }, "engines": { "node": ">= 0.4" @@ -10131,16 +10239,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.59.1.tgz", - "integrity": "sha512-xqDcFVBmlrltH64lklOVp1wYxgJr6LVdg3NamBgH2OOQDLFdTKfIZXF5PfghrnXQKXZGTQs8tr1vL7fJvq8CTQ==", + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.61.0.tgz", + "integrity": "sha512-8y31Rd0eGTrDKqhy6vT0HtzhN+YLjQizwX3aA3hPXP/ynSfnrBXcQY5IzsP9/DM7+klX4IUncZZjkchP0z+rUw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.59.1", - "@typescript-eslint/parser": "8.59.1", - "@typescript-eslint/typescript-estree": "8.59.1", - "@typescript-eslint/utils": "8.59.1" + "@typescript-eslint/eslint-plugin": "8.61.0", + "@typescript-eslint/parser": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/utils": "8.61.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -10174,9 +10282,9 @@ } }, "node_modules/undici": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.25.0.tgz", - "integrity": "sha512-ZgpWDC5gmNiuY9CnLVXEH8rl50xhRCuLNA97fAUnKi8RRuV4E6KG31pDTsLVUKnohJE0I3XDrTeEydAXRw47xg==", + "version": "6.27.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.27.0.tgz", + "integrity": "sha512-YmfV3YnEDzXRC5lZ2jWtWWHKGUm1zIt8AhesR1tens+HTNv+YZlN/dp6G727LOvMJ8xjP9Be7Y2Sdr96LDm+pg==", "dev": true, "license": "MIT", "engines": { @@ -10204,38 +10312,41 @@ } }, "node_modules/unrs-resolver": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", - "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz", + "integrity": "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==", "dev": true, "hasInstallScript": true, "license": "MIT", "dependencies": { - "napi-postinstall": "^0.3.0" + "napi-postinstall": "^0.3.4" }, "funding": { "url": "https://opencollective.com/unrs-resolver" }, "optionalDependencies": { - "@unrs/resolver-binding-android-arm-eabi": "1.11.1", - "@unrs/resolver-binding-android-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-x64": "1.11.1", - "@unrs/resolver-binding-freebsd-x64": "1.11.1", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", - "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-musl": "1.11.1", - "@unrs/resolver-binding-wasm32-wasi": "1.11.1", - "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", - "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", - "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + "@unrs/resolver-binding-android-arm-eabi": "1.12.2", + "@unrs/resolver-binding-android-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-x64": "1.12.2", + "@unrs/resolver-binding-freebsd-x64": "1.12.2", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-arm64-musl": "1.12.2", + "@unrs/resolver-binding-linux-loong64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-loong64-musl": "1.12.2", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-musl": "1.12.2", + "@unrs/resolver-binding-linux-s390x-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-musl": "1.12.2", + "@unrs/resolver-binding-openharmony-arm64": "1.12.2", + "@unrs/resolver-binding-wasm32-wasi": "1.12.2", + "@unrs/resolver-binding-win32-arm64-msvc": "1.12.2", + "@unrs/resolver-binding-win32-ia32-msvc": "1.12.2", + "@unrs/resolver-binding-win32-x64-msvc": "1.12.2" } }, "node_modules/update-browserslist-db": { @@ -10399,14 +10510,14 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.20", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", - "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", + "version": "1.1.22", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz", + "integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==", "dev": true, "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", + "call-bind": "^1.0.9", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", @@ -10547,9 +10658,9 @@ } }, "node_modules/ws": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", - "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", "dev": true, "license": "MIT", "engines": { @@ -10586,9 +10697,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", - "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", "dev": true, "license": "ISC", "bin": { diff --git a/deps/undici/src/package.json b/deps/undici/src/package.json index 844cbc450fe3ba..25a191b25d17cb 100644 --- a/deps/undici/src/package.json +++ b/deps/undici/src/package.json @@ -1,6 +1,6 @@ { "name": "undici", - "version": "7.25.0", + "version": "7.28.0", "description": "An HTTP/1.1 client, written from scratch for Node.js", "homepage": "https://undici.nodejs.org", "bugs": { diff --git a/deps/undici/src/types/client.d.ts b/deps/undici/src/types/client.d.ts index a6e20221f68c40..6541b49ee4c395 100644 --- a/deps/undici/src/types/client.d.ts +++ b/deps/undici/src/types/client.d.ts @@ -107,6 +107,8 @@ export declare namespace Client { * @default 60000 */ pingInterval?: number; + /** WebSocket-specific configuration options. */ + webSocket?: WebSocketOptions; } export interface SocketInfo { localAddress?: string @@ -118,6 +120,20 @@ export declare namespace Client { bytesWritten?: number bytesRead?: number } + export interface WebSocketOptions { + /** + * Maximum number of fragments in a message. Set to 0 to disable the limit. + * @default 131072 + */ + maxFragments?: number; + /** + * Maximum allowed payload size in bytes for WebSocket messages. + * Applied to uncompressed messages, compressed frame payloads, and decompressed (permessage-deflate) messages. + * Set to 0 to disable the limit. + * @default 134217728 (128 MB) + */ + maxPayloadSize?: number; + } } export default Client diff --git a/deps/undici/src/types/dispatcher.d.ts b/deps/undici/src/types/dispatcher.d.ts index 33dc6051626c0b..3f2ec3d498bd72 100644 --- a/deps/undici/src/types/dispatcher.d.ts +++ b/deps/undici/src/types/dispatcher.d.ts @@ -212,6 +212,8 @@ declare namespace Dispatcher { get aborted(): boolean get paused(): boolean get reason(): Error | null + rawHeaders?: Buffer[] | string[] | IncomingHttpHeaders | null + rawTrailers?: Buffer[] | string[] | IncomingHttpHeaders | null abort(reason: Error): void pause(): void resume(): void diff --git a/deps/undici/undici.js b/deps/undici/undici.js index 903b1546d1c2b8..7527647408c777 100644 --- a/deps/undici/undici.js +++ b/deps/undici/undici.js @@ -2094,6 +2094,8 @@ var require_unwrap_handler = __commonJS({ #aborted = false; #abort; [kResume] = null; + rawHeaders = null; + rawTrailers = null; constructor(abort) { this.#abort = abort; } @@ -2143,10 +2145,12 @@ var require_unwrap_handler = __commonJS({ return this.#handler.onResponseStarted?.(); } onUpgrade(statusCode, rawHeaders, socket) { + this.#controller.rawHeaders = rawHeaders; this.#handler.onRequestUpgrade?.(this.#controller, statusCode, parseHeaders(rawHeaders), socket); } onHeaders(statusCode, rawHeaders, resume, statusMessage) { this.#controller[kResume] = resume; + this.#controller.rawHeaders = rawHeaders; this.#handler.onResponseStart?.(this.#controller, statusCode, parseHeaders(rawHeaders), statusMessage); return !this.#controller.paused; } @@ -2155,6 +2159,7 @@ var require_unwrap_handler = __commonJS({ return !this.#controller.paused; } onComplete(rawTrailers) { + this.#controller.rawTrailers = rawTrailers; this.#handler.onResponseEnd?.(this.#controller, parseHeaders(rawTrailers)); } onError(err) { @@ -2181,6 +2186,7 @@ var require_dispatcher_base = __commonJS({ var { kDestroy, kClose, kClosed, kDestroyed, kDispatch } = require_symbols(); var kOnDestroyed = /* @__PURE__ */ Symbol("onDestroyed"); var kOnClosed = /* @__PURE__ */ Symbol("onClosed"); + var kWebSocketOptions = /* @__PURE__ */ Symbol("webSocketOptions"); var DispatcherBase = class extends Dispatcher2 { static { __name(this, "DispatcherBase"); @@ -2193,6 +2199,23 @@ var require_dispatcher_base = __commonJS({ [kClosed] = false; /** @type {Array|null} */ [kOnClosed] = null; + /** + * @param {import('../../types/dispatcher').DispatcherOptions} [opts] + */ + constructor(opts) { + super(); + this[kWebSocketOptions] = opts?.webSocket ?? {}; + } + /** + * @returns {import('../../types/dispatcher').WebSocketOptions} + */ + get webSocketOptions() { + return { + maxFragments: this[kWebSocketOptions].maxFragments ?? 131072, + maxPayloadSize: this[kWebSocketOptions].maxPayloadSize ?? 128 * 1024 * 1024 + // 128 MB default + }; + } /** @returns {boolean} */ get destroyed() { return this[kDestroyed]; @@ -2848,6 +2871,19 @@ var require_request = __commonJS({ var { channels } = require_diagnostics(); var { headerNameLowerCasedRecord } = require_constants(); var invalidPathRegex = /[^\u0021-\u00ff]/; + function isValidContentLengthHeaderValue(val) { + if (typeof val !== "string" || val.length === 0) { + return false; + } + for (let i = 0; i < val.length; i++) { + const charCode = val.charCodeAt(i); + if (charCode < 48 || charCode > 57) { + return false; + } + } + return true; + } + __name(isValidContentLengthHeaderValue, "isValidContentLengthHeaderValue"); var kHandler = /* @__PURE__ */ Symbol("handler"); var Request = class { static { @@ -3150,10 +3186,10 @@ var require_request = __commonJS({ if (request.contentLength !== null) { throw new InvalidArgumentError("duplicate content-length header"); } - request.contentLength = parseInt(val, 10); - if (!Number.isFinite(request.contentLength)) { + if (!isValidContentLengthHeaderValue(val)) { throw new InvalidArgumentError("invalid content-length header"); } + request.contentLength = parseInt(val, 10); } else if (request.contentType === null && headerName === "content-type") { request.contentType = val; request.headers.push(key, val); @@ -3218,6 +3254,20 @@ var require_connect = __commonJS({ if (this._maxCachedSessions === 0) { return; } + if (this._sessionCache.has(sessionKey)) { + this._sessionCache.delete(sessionKey); + } else if (this._sessionCache.size >= this._maxCachedSessions) { + for (const [key, ref] of this._sessionCache) { + if (ref.deref() === void 0) { + this._sessionCache.delete(key); + return; + } + } + const oldest = this._sessionCache.keys().next(); + if (!oldest.done) { + this._sessionCache.delete(oldest.value); + } + } this._sessionCache.set(sessionKey, new WeakRef(session)); this._sessionRegistry.register(session, sessionKey); } @@ -4918,7 +4968,7 @@ var require_webidl = __commonJS({ lowerBound = 0; upperBound = Math.pow(2, bitLength) - 1; } else { - lowerBound = Math.pow(-2, bitLength) - 1; + lowerBound = -Math.pow(2, bitLength - 1); upperBound = Math.pow(2, bitLength - 1) - 1; } let x = Number(V); @@ -4955,7 +5005,7 @@ var require_webidl = __commonJS({ } x = webidl.util.IntegerPart(x); x = x % Math.pow(2, bitLength); - if (signedness === "signed" && x >= Math.pow(2, bitLength) - 1) { + if (signedness === "signed" && x >= Math.pow(2, bitLength - 1)) { return x - Math.pow(2, bitLength); } return x; @@ -6541,7 +6591,7 @@ var require_formdata_parser = __commonJS({ ); value = decoder.decode(tokenValue); } - return { name: attrNameStr, value }; + return { name: attrNameStr, value, extended: isExtended }; } __name(parseContentDispositionAttribute, "parseContentDispositionAttribute"); function parseMultipartFormDataHeaders(input, position) { @@ -6577,6 +6627,7 @@ var require_formdata_parser = __commonJS({ switch (bufferToLowerCasedHeaderName(headerName)) { case "content-disposition": { name = filename = null; + let filenameIsExtended = false; const dispositionType = collectASequenceOfBytes( (char) => isToken(char), input, @@ -6585,7 +6636,7 @@ var require_formdata_parser = __commonJS({ if (dispositionType.toString("ascii").toLowerCase() !== "form-data") { throw parsingError("expected form-data for content-disposition header"); } - while (position.position < input.length && input[position.position] !== 13 && input[position.position + 1] !== 10) { + while (position.position < input.length && (input[position.position] !== 13 || input[position.position + 1] !== 10)) { const attribute = parseContentDispositionAttribute(input, position); if (!attribute) { break; @@ -6593,7 +6644,12 @@ var require_formdata_parser = __commonJS({ if (attribute.name === "name") { name = attribute.value; } else if (attribute.name === "filename") { - filename = attribute.value; + if (attribute.extended) { + filename = attribute.value; + filenameIsExtended = true; + } else if (!filenameIsExtended) { + filename = attribute.value; + } } } if (name === null) { @@ -6629,7 +6685,7 @@ var require_formdata_parser = __commonJS({ ); } } - if (input[position.position] !== 13 && input[position.position + 1] !== 10) { + if (input[position.position] !== 13 || input[position.position + 1] !== 10) { throw parsingError("expected CRLF"); } else { position.position += 2; @@ -7078,15 +7134,18 @@ var require_client_h1 = __commonJS({ var EMPTY_BUF = Buffer.alloc(0); var FastBuffer = Buffer[Symbol.species]; var removeAllListeners = util.removeAllListeners; + var kIdleSocketValidation = /* @__PURE__ */ Symbol("kIdleSocketValidation"); + var kIdleSocketValidationTimeout = /* @__PURE__ */ Symbol("kIdleSocketValidationTimeout"); + var kSocketUsed = /* @__PURE__ */ Symbol("kSocketUsed"); var extractBody; function lazyllhttp() { const llhttpWasmData = process.env.JEST_WORKER_ID ? require_llhttp_wasm() : void 0; let mod; let useWasmSIMD = process.arch !== "ppc64"; if (process.env.UNDICI_NO_WASM_SIMD === "1") { - useWasmSIMD = true; - } else if (process.env.UNDICI_NO_WASM_SIMD === "0") { useWasmSIMD = false; + } else if (process.env.UNDICI_NO_WASM_SIMD === "0") { + useWasmSIMD = true; } if (useWasmSIMD) { try { @@ -7208,6 +7267,7 @@ var require_client_h1 = __commonJS({ this.client = client; this.socket = socket; this.timeout = null; + this.timeoutWeakRef = new WeakRef(this); this.timeoutValue = null; this.timeoutType = null; this.statusCode = 0; @@ -7233,9 +7293,9 @@ var require_client_h1 = __commonJS({ } if (delay) { if (type & USE_FAST_TIMER) { - this.timeout = timers.setFastTimeout(onParserTimeout, delay, new WeakRef(this)); + this.timeout = timers.setFastTimeout(onParserTimeout, delay, this.timeoutWeakRef); } else { - this.timeout = setTimeout(onParserTimeout, delay, new WeakRef(this)); + this.timeout = setTimeout(onParserTimeout, delay, this.timeoutWeakRef); this.timeout?.unref(); } } @@ -7307,19 +7367,47 @@ var require_client_h1 = __commonJS({ this.paused = true; socket.unshift(data); } else { - const ptr = llhttp.llhttp_get_error_reason(this.ptr); - let message = ""; - if (ptr) { - const len = new Uint8Array(llhttp.memory.buffer, ptr).indexOf(0); - message = "Response does not match the HTTP/1.1 protocol (" + Buffer.from(llhttp.memory.buffer, ptr, len).toString() + ")"; - } - throw new HTTPParserError(message, constants.ERROR[ret], data); + throw this.createError(ret, data); } } } catch (err) { util.destroy(socket, err); } } + finish() { + assert(currentParser === null); + assert(this.ptr != null); + assert(!this.paused); + const { llhttp } = this; + let ret; + try { + currentParser = this; + ret = llhttp.llhttp_finish(this.ptr); + } finally { + currentParser = null; + } + if (ret === constants.ERROR.OK) { + return null; + } + if (ret === constants.ERROR.PAUSED || ret === constants.ERROR.PAUSED_UPGRADE) { + this.paused = true; + return null; + } + return this.createError(ret, EMPTY_BUF); + } + createError(ret, data) { + const { llhttp, contentLength, bytesRead } = this; + if (contentLength && bytesRead !== parseInt(contentLength, 10)) { + return new ResponseContentLengthMismatchError(); + } + const ptr = llhttp.llhttp_get_error_reason(this.ptr); + let message = ""; + if (ptr) { + const len = new Uint8Array(llhttp.memory.buffer, ptr).indexOf(0); + message = "Response does not match the HTTP/1.1 protocol (" + Buffer.from(llhttp.memory.buffer, ptr, len).toString() + ")"; + } + return new HTTPParserError(message, constants.ERROR[ret], data); + } destroy() { assert(currentParser === null); assert(this.ptr != null); @@ -7347,6 +7435,10 @@ var require_client_h1 = __commonJS({ if (socket.destroyed) { return -1; } + if (client[kRunning] === 0) { + util.destroy(socket, new SocketError("bad response", util.getSocketInfo(socket))); + return -1; + } const request = client[kQueue][client[kRunningIdx]]; if (!request) { return -1; @@ -7449,6 +7541,10 @@ var require_client_h1 = __commonJS({ if (socket.destroyed) { return -1; } + if (client[kRunning] === 0) { + util.destroy(socket, new SocketError("bad response", util.getSocketInfo(socket))); + return -1; + } const request = client[kQueue][client[kRunningIdx]]; if (!request) { return -1; @@ -7582,6 +7678,7 @@ var require_client_h1 = __commonJS({ } request.onComplete(headers); client[kQueue][client[kRunningIdx]++] = null; + socket[kSocketUsed] = client[kPending] === 0; if (socket[kWriting]) { assert(client[kRunning] === 0); util.destroy(socket, new InformationalError("reset")); @@ -7636,6 +7733,9 @@ var require_client_h1 = __commonJS({ socket[kWriting] = false; socket[kReset] = false; socket[kBlocking] = false; + socket[kIdleSocketValidation] = 0; + socket[kIdleSocketValidationTimeout] = null; + socket[kSocketUsed] = false; socket[kParser] = new Parser(client, socket, llhttpInstance); util.addListener(socket, "error", onHttpSocketError); util.addListener(socket, "readable", onHttpSocketReadable); @@ -7675,7 +7775,7 @@ var require_client_h1 = __commonJS({ * @returns {boolean} */ busy(request) { - if (socket[kWriting] || socket[kReset] || socket[kBlocking]) { + if (socket[kWriting] || socket[kReset] || socket[kBlocking] || socket[kIdleSocketValidation] === 1) { return true; } if (request) { @@ -7698,7 +7798,11 @@ var require_client_h1 = __commonJS({ assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); const parser = this[kParser]; if (err.code === "ECONNRESET" && parser.statusCode && !parser.shouldKeepAlive) { - parser.onMessageComplete(); + const parserErr = parser.finish(); + if (parserErr) { + this[kError] = parserErr; + this[kClient][kOnError](parserErr); + } return; } this[kError] = err; @@ -7712,7 +7816,10 @@ var require_client_h1 = __commonJS({ function onHttpSocketEnd() { const parser = this[kParser]; if (parser.statusCode && !parser.shouldKeepAlive) { - parser.onMessageComplete(); + const parserErr = parser.finish(); + if (parserErr) { + util.destroy(this, parserErr); + } return; } util.destroy(this, new SocketError("other side closed", util.getSocketInfo(this))); @@ -7720,9 +7827,10 @@ var require_client_h1 = __commonJS({ __name(onHttpSocketEnd, "onHttpSocketEnd"); function onHttpSocketClose() { const parser = this[kParser]; + clearIdleSocketValidation(this); if (parser) { if (!this[kError] && parser.statusCode && !parser.shouldKeepAlive) { - parser.onMessageComplete(); + this[kError] = parser.finish() || this[kError]; } this[kParser].destroy(); this[kParser] = null; @@ -7753,6 +7861,26 @@ var require_client_h1 = __commonJS({ this[kClosed] = true; } __name(onSocketClose, "onSocketClose"); + function clearIdleSocketValidation(socket) { + if (socket[kIdleSocketValidationTimeout]) { + clearTimeout(socket[kIdleSocketValidationTimeout]); + socket[kIdleSocketValidationTimeout] = null; + } + socket[kIdleSocketValidation] = 0; + } + __name(clearIdleSocketValidation, "clearIdleSocketValidation"); + function scheduleIdleSocketValidation(client, socket) { + socket[kIdleSocketValidation] = 1; + socket[kIdleSocketValidationTimeout] = setTimeout(() => { + socket[kIdleSocketValidationTimeout] = null; + socket[kIdleSocketValidation] = 2; + if (client[kSocket] === socket && !socket.destroyed) { + client[kResume](); + } + }, 0); + socket[kIdleSocketValidationTimeout].unref?.(); + } + __name(scheduleIdleSocketValidation, "scheduleIdleSocketValidation"); function resumeH1(client) { const socket = client[kSocket]; if (socket && !socket.destroyed) { @@ -7765,6 +7893,29 @@ var require_client_h1 = __commonJS({ socket.ref(); socket[kNoRef] = false; } + if (client[kRunning] === 0 && client[kPending] > 0 && socket[kSocketUsed]) { + if (socket[kIdleSocketValidation] === 0) { + scheduleIdleSocketValidation(client, socket); + socket[kParser].readMore(); + if (socket.destroyed) { + return; + } + return; + } + if (socket[kIdleSocketValidation] === 1) { + socket[kParser].readMore(); + if (socket.destroyed) { + return; + } + return; + } + } + if (client[kRunning] === 0) { + socket[kParser].readMore(); + if (socket.destroyed) { + return; + } + } if (client[kSize] === 0) { if (socket[kParser].timeoutType !== TIMEOUT_KEEP_ALIVE) { socket[kParser].setTimeout(client[kKeepAliveTimeoutValue], TIMEOUT_KEEP_ALIVE); @@ -7819,6 +7970,7 @@ var require_client_h1 = __commonJS({ process.emitWarning(new RequestContentLengthMismatchError()); } const socket = client[kSocket]; + clearIdleSocketValidation(socket); const abort = /* @__PURE__ */ __name((err) => { if (request.aborted || request.completed) { return; @@ -9072,7 +9224,8 @@ var require_client = __commonJS({ useH2c, initialWindowSize, connectionWindowSize, - pingInterval + pingInterval, + webSocket } = {}) { if (keepAlive !== void 0) { throw new InvalidArgumentError("unsupported keepAlive, use pipelining=0 instead"); @@ -9150,7 +9303,7 @@ var require_client = __commonJS({ if (pingInterval != null && (typeof pingInterval !== "number" || !Number.isInteger(pingInterval) || pingInterval < 0)) { throw new InvalidArgumentError("pingInterval must be a positive integer, greater or equal to 0"); } - super(); + super({ webSocket }); if (typeof connect2 !== "function") { connect2 = buildConnector({ ...tls, @@ -9162,9 +9315,13 @@ var require_client = __commonJS({ ...typeof autoSelectFamily === "boolean" ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0, ...connect2 }); - } else if (socketPath != null) { + } else { const customConnect = connect2; - connect2 = /* @__PURE__ */ __name((opts, callback) => customConnect({ ...opts, socketPath }, callback), "connect"); + connect2 = /* @__PURE__ */ __name((opts, callback) => customConnect({ + ...opts, + ...socketPath != null ? { socketPath } : null, + ...allowH2 != null ? { allowH2 } : null + }, callback), "connect"); } this[kUrl] = util.parseOrigin(url); this[kConnector] = connect2; @@ -9556,7 +9713,7 @@ var require_pool = __commonJS({ ...connect }); } - super(); + super(options); this[kConnections] = connections || null; this[kUrl] = util.parseOrigin(origin); this[kOptions] = { ...util.deepClone(options), connect, allowH2, clientTtl, socketPath }; @@ -9633,7 +9790,7 @@ var require_agent = __commonJS({ if (typeof maxOrigins !== "number" || Number.isNaN(maxOrigins) || maxOrigins <= 0) { throw new InvalidArgumentError("maxOrigins must be a number greater than 0"); } - super(); + super(options); if (connect && typeof connect !== "function") { connect = { ...connect }; } @@ -9739,7 +9896,8 @@ var require_agent = __commonJS({ var require_global2 = __commonJS({ "lib/global.js"(exports2, module2) { "use strict"; - var globalDispatcher = /* @__PURE__ */ Symbol.for("undici.globalDispatcher.1"); + var globalDispatcher = /* @__PURE__ */ Symbol.for("undici.globalDispatcher.2"); + var legacyGlobalDispatcher = /* @__PURE__ */ Symbol.for("undici.globalDispatcher.1"); var { InvalidArgumentError } = require_errors(); var Agent = require_agent(); if (getGlobalDispatcher2() === void 0) { @@ -9755,10 +9913,16 @@ var require_global2 = __commonJS({ enumerable: false, configurable: false }); + Object.defineProperty(globalThis, legacyGlobalDispatcher, { + value: agent, + writable: true, + enumerable: false, + configurable: false + }); } __name(setGlobalDispatcher2, "setGlobalDispatcher"); function getGlobalDispatcher2() { - return globalThis[globalDispatcher]; + return globalThis[legacyGlobalDispatcher]; } __name(getGlobalDispatcher2, "getGlobalDispatcher"); var installedExports = ( @@ -9820,28 +9984,37 @@ var require_socks5_utils = __commonJS({ __name(parseAddress, "parseAddress"); function parseIPv6(address) { const buffer = Buffer2.alloc(16); - const parts = address.split(":"); - let partIndex = 0; - let bufferIndex = 0; - const doubleColonIndex = address.indexOf("::"); + let normalizedAddress = address; + if (address.includes(".")) { + const lastColonIndex = address.lastIndexOf(":"); + const ipv4Part = address.slice(lastColonIndex + 1); + if (net.isIPv4(ipv4Part)) { + const octets = ipv4Part.split(".").map(Number); + const high = (octets[0] << 8 | octets[1]).toString(16); + const low = (octets[2] << 8 | octets[3]).toString(16); + normalizedAddress = `${address.slice(0, lastColonIndex)}:${high}:${low}`; + } + } + const doubleColonIndex = normalizedAddress.indexOf("::"); if (doubleColonIndex !== -1) { - const nonEmptyParts = parts.filter((p) => p.length > 0).length; - const skipParts = 8 - nonEmptyParts; - for (let i = 0; i < parts.length; i++) { - if (parts[i] === "" && i === doubleColonIndex / 3) { - bufferIndex += skipParts * 2; - } else if (parts[i] !== "") { - const value = parseInt(parts[i], 16); - buffer.writeUInt16BE(value, bufferIndex); - bufferIndex += 2; - } + const before = normalizedAddress.slice(0, doubleColonIndex); + const after = normalizedAddress.slice(doubleColonIndex + 2); + const beforeParts = before === "" ? [] : before.split(":"); + const afterParts = after === "" ? [] : after.split(":"); + let bufferIndex = 0; + for (const part of beforeParts) { + buffer.writeUInt16BE(parseInt(part, 16), bufferIndex); + bufferIndex += 2; + } + bufferIndex = 16 - afterParts.length * 2; + for (const part of afterParts) { + buffer.writeUInt16BE(parseInt(part, 16), bufferIndex); + bufferIndex += 2; } } else { - for (const part of parts) { - if (part === "") continue; - const value = parseInt(part, 16); - buffer.writeUInt16BE(value, partIndex * 2); - partIndex++; + const parts = normalizedAddress.split(":"); + for (let i = 0; i < parts.length; i++) { + buffer.writeUInt16BE(parseInt(parts[i], 16), i * 2); } } return buffer; @@ -9951,6 +10124,7 @@ var require_socks5_client = __commonJS({ var { debuglog } = require("node:util"); var { parseAddress } = require_socks5_utils(); var debug = debuglog("undici:socks5"); + var EMPTY_BUFFER = Buffer2.alloc(0); var SOCKS_VERSION = 5; var AUTH_METHODS = { NO_AUTH: 0, @@ -9983,6 +10157,7 @@ var require_socks5_client = __commonJS({ INITIAL: "initial", HANDSHAKING: "handshaking", AUTHENTICATING: "authenticating", + AUTHENTICATED: "authenticated", CONNECTING: "connecting", CONNECTED: "connected", ERROR: "error", @@ -10000,15 +10175,18 @@ var require_socks5_client = __commonJS({ this.socket = socket; this.options = options; this.state = STATES.INITIAL; - this.buffer = Buffer2.alloc(0); + this.buffer = EMPTY_BUFFER; + this.onSocketData = this.onData.bind(this); + this.onSocketError = this.onError.bind(this); + this.onSocketClose = this.onClose.bind(this); this.authMethods = []; if (options.username && options.password) { this.authMethods.push(AUTH_METHODS.USERNAME_PASSWORD); } this.authMethods.push(AUTH_METHODS.NO_AUTH); - this.socket.on("data", this.onData.bind(this)); - this.socket.on("error", this.onError.bind(this)); - this.socket.on("close", this.onClose.bind(this)); + this.socket.on("data", this.onSocketData); + this.socket.on("error", this.onSocketError); + this.socket.on("close", this.onSocketClose); } /** * Handle incoming data from the socket @@ -10057,6 +10235,10 @@ var require_socks5_client = __commonJS({ this.socket.destroy(); } } + markAuthenticated() { + this.state = STATES.AUTHENTICATED; + this.emit("authenticated"); + } /** * Start the SOCKS5 handshake */ @@ -10092,7 +10274,7 @@ var require_socks5_client = __commonJS({ this.buffer = this.buffer.subarray(2); debug("server selected auth method", method); if (method === AUTH_METHODS.NO_AUTH) { - this.emit("authenticated"); + this.markAuthenticated(); } else if (method === AUTH_METHODS.USERNAME_PASSWORD) { this.state = STATES.AUTHENTICATING; this.sendAuthRequest(); @@ -10139,7 +10321,7 @@ var require_socks5_client = __commonJS({ } this.buffer = this.buffer.subarray(2); debug("authentication successful"); - this.emit("authenticated"); + this.markAuthenticated(); } /** * Send CONNECT command @@ -10147,8 +10329,11 @@ var require_socks5_client = __commonJS({ * @param {number} port - Target port */ connect(address, port) { - if (this.state === STATES.CONNECTED) { - throw new InvalidArgumentError("Already connected"); + if (this.state === STATES.CONNECTING || this.state === STATES.CONNECTED) { + throw new InvalidArgumentError("Connection already in progress"); + } + if (this.state !== STATES.AUTHENTICATED) { + throw new InvalidArgumentError("Client must be authenticated before CONNECT"); } debug("connecting to", address, port); this.state = STATES.CONNECTING; @@ -10222,8 +10407,9 @@ var require_socks5_client = __commonJS({ offset += 16; } const boundPort = this.buffer.readUInt16BE(offset); - this.buffer = this.buffer.subarray(responseLength); + this.buffer = EMPTY_BUFFER; this.state = STATES.CONNECTED; + this.socket.removeListener("data", this.onSocketData); debug("connected, bound address:", boundAddress, "port:", boundPort); this.emit("connected", { address: boundAddress, port: boundPort }); } @@ -10268,12 +10454,11 @@ var require_socks5_client = __commonJS({ var require_socks5_proxy_agent = __commonJS({ "lib/dispatcher/socks5-proxy-agent.js"(exports2, module2) { "use strict"; - var net = require("node:net"); var { URL: URL2 } = require("node:url"); var tls; var DispatcherBase = require_dispatcher_base(); var { InvalidArgumentError } = require_errors(); - var { Socks5Client } = require_socks5_client(); + var { Socks5Client, STATES } = require_socks5_client(); var { kDispatch, kClose, kDestroy } = require_symbols(); var Pool = require_pool(); var buildConnector = require_connect(); @@ -10282,8 +10467,10 @@ var require_socks5_proxy_agent = __commonJS({ var kProxyUrl = /* @__PURE__ */ Symbol("proxy url"); var kProxyHeaders = /* @__PURE__ */ Symbol("proxy headers"); var kProxyAuth = /* @__PURE__ */ Symbol("proxy auth"); - var kPool = /* @__PURE__ */ Symbol("pool"); + var kProxyProtocol = /* @__PURE__ */ Symbol("proxy protocol"); + var kPools = /* @__PURE__ */ Symbol("pools"); var kConnector = /* @__PURE__ */ Symbol("connector"); + var kRequestTls = /* @__PURE__ */ Symbol("request tls settings"); var experimentalWarningEmitted = false; var Socks5ProxyAgent = class extends DispatcherBase { static { @@ -10307,6 +10494,8 @@ var require_socks5_proxy_agent = __commonJS({ } this[kProxyUrl] = url; this[kProxyHeaders] = options.headers || {}; + this[kProxyProtocol] = options.proxyTls ? "https:" : "http:"; + this[kRequestTls] = options.requestTls; this[kProxyAuth] = { username: options.username || (url.username ? decodeURIComponent(url.username) : null), password: options.password || (url.password ? decodeURIComponent(url.password) : null) @@ -10315,7 +10504,7 @@ var require_socks5_proxy_agent = __commonJS({ ...options.proxyTls, servername: options.proxyTls?.servername || url.hostname }); - this[kPool] = null; + this[kPools] = /* @__PURE__ */ new Map(); } /** * Create a SOCKS5 connection to the proxy @@ -10325,20 +10514,18 @@ var require_socks5_proxy_agent = __commonJS({ const proxyPort = parseInt(this[kProxyUrl].port) || 1080; debug("creating SOCKS5 connection to", proxyHost, proxyPort); const socket = await new Promise((resolve, reject) => { - const onConnect = /* @__PURE__ */ __name(() => { - socket2.removeListener("error", onError); - resolve(socket2); - }, "onConnect"); - const onError = /* @__PURE__ */ __name((err) => { - socket2.removeListener("connect", onConnect); - reject(err); - }, "onError"); - const socket2 = net.connect({ + this[kConnector]({ + hostname: proxyHost, host: proxyHost, - port: proxyPort + port: proxyPort, + protocol: this[kProxyProtocol] + }, (err, socket2) => { + if (err) { + reject(err); + } else { + resolve(socket2); + } }); - socket2.once("connect", onConnect); - socket2.once("error", onError); }); const socks5Client = new Socks5Client(socket, this[kProxyAuth]); socks5Client.on("error", (err) => { @@ -10360,7 +10547,7 @@ var require_socks5_proxy_agent = __commonJS({ socks5Client.removeListener("authenticated", onAuthenticated); reject(err); }, "onError"); - if (socks5Client.state === "authenticated") { + if (socks5Client.state === STATES.AUTHENTICATED) { clearTimeout(timeout); resolve(); } else { @@ -10392,12 +10579,14 @@ var require_socks5_proxy_agent = __commonJS({ /** * Dispatch a request through the SOCKS5 proxy */ - async [kDispatch](opts, handler) { + [kDispatch](opts, handler) { const { origin } = opts; debug("dispatching request to", origin, "via SOCKS5"); try { - if (!this[kPool] || this[kPool].destroyed || this[kPool].closed) { - this[kPool] = new Pool(origin, { + const originKey = String(origin); + let pool = this[kPools].get(originKey); + if (!pool || pool.destroyed || pool.closed) { + pool = new Pool(origin, { pipelining: opts.pipelining, connections: opts.connections, connect: /* @__PURE__ */ __name(async (connectOpts, callback) => { @@ -10414,9 +10603,9 @@ var require_socks5_proxy_agent = __commonJS({ } debug("upgrading to TLS"); finalSocket = tls.connect({ + ...this[kRequestTls], socket, - servername: targetHost, - ...connectOpts.tls || {} + servername: this[kRequestTls]?.servername || targetHost }); await new Promise((resolve, reject) => { finalSocket.once("secureConnect", resolve); @@ -10430,26 +10619,37 @@ var require_socks5_proxy_agent = __commonJS({ } }, "connect") }); + this[kPools].set(originKey, pool); } - return this[kPool][kDispatch](opts, handler); + return pool[kDispatch](opts, handler); } catch (err) { debug("dispatch error:", err); - if (typeof handler.onError === "function") { + if (typeof handler.onResponseError === "function") { + handler.onResponseError(null, err); + return false; + } else if (typeof handler.onError === "function") { handler.onError(err); + return false; } else { throw err; } } } async [kClose]() { - if (this[kPool]) { - await this[kPool].close(); + const closePromises = []; + for (const pool of this[kPools].values()) { + closePromises.push(pool.close()); } + this[kPools].clear(); + await Promise.all(closePromises); } async [kDestroy](err) { - if (this[kPool]) { - await this[kPool].destroy(err); + const destroyPromises = []; + for (const pool of this[kPools].values()) { + destroyPromises.push(pool.destroy(err)); } + this[kPools].clear(); + await Promise.all(destroyPromises); } }; module2.exports = Socks5ProxyAgent; @@ -10583,7 +10783,8 @@ var require_proxy_agent = __commonJS({ factory: agentFactory, username: opts.username || username, password: opts.password || password, - proxyTls: opts.proxyTls + proxyTls: opts.proxyTls, + requestTls: opts.requestTls }); } if (!this[kTunnelProxy] && protocol2 === "http:" && this[kProxy].protocol === "http:") { @@ -13177,7 +13378,7 @@ var require_fetch = __commonJS({ cacheState = ""; } let responseStatus = 0; - if (fetchParams.request.mode !== "navigator" || !response.hasCrossOriginRedirects) { + if (fetchParams.request.mode !== "navigate" || !response.hasCrossOriginRedirects) { responseStatus = response.status; const mimeType = extractMimeType(response.headersList); if (mimeType !== "failure") { @@ -13344,7 +13545,7 @@ var require_fetch = __commonJS({ if (contentLength != null) { contentLengthHeaderValue = isomorphicEncode(`${contentLength}`); } - if (contentLengthHeaderValue != null) { + if (contentLengthHeaderValue != null && !httpRequest.headersList.contains("content-length", true)) { httpRequest.headersList.append("content-length", contentLengthHeaderValue, true); } if (contentLength != null && httpRequest.keepalive) { @@ -14629,7 +14830,6 @@ var require_permessage_deflate = __commonJS({ var tail = Buffer.from([0, 0, 255, 255]); var kBuffer = /* @__PURE__ */ Symbol("kBuffer"); var kLength = /* @__PURE__ */ Symbol("kLength"); - var kDefaultMaxDecompressedSize = 4 * 1024 * 1024; var PerMessageDeflate = class { static { __name(this, "PerMessageDeflate"); @@ -14637,22 +14837,22 @@ var require_permessage_deflate = __commonJS({ /** @type {import('node:zlib').InflateRaw} */ #inflate; #options = {}; - /** @type {boolean} */ - #aborted = false; - /** @type {Function|null} */ - #currentCallback = null; + #maxPayloadSize = 0; /** * @param {Map} extensions */ - constructor(extensions) { + constructor(extensions, options) { this.#options.serverNoContextTakeover = extensions.has("server_no_context_takeover"); this.#options.serverMaxWindowBits = extensions.get("server_max_window_bits"); + this.#maxPayloadSize = options.maxPayloadSize; } + /** + * Decompress a compressed payload. + * @param {Buffer} chunk Compressed data + * @param {boolean} fin Final fragment flag + * @param {Function} callback Callback function + */ decompress(chunk, fin, callback) { - if (this.#aborted) { - callback(new MessageSizeExceededError()); - return; - } if (!this.#inflate) { let windowBits = Z_DEFAULT_WINDOWBITS; if (this.#options.serverMaxWindowBits) { @@ -14671,20 +14871,11 @@ var require_permessage_deflate = __commonJS({ this.#inflate[kBuffer] = []; this.#inflate[kLength] = 0; this.#inflate.on("data", (data) => { - if (this.#aborted) { - return; - } this.#inflate[kLength] += data.length; - if (this.#inflate[kLength] > kDefaultMaxDecompressedSize) { - this.#aborted = true; + if (this.#maxPayloadSize > 0 && this.#inflate[kLength] > this.#maxPayloadSize) { + callback(new MessageSizeExceededError()); this.#inflate.removeAllListeners(); - this.#inflate.destroy(); this.#inflate = null; - if (this.#currentCallback) { - const cb = this.#currentCallback; - this.#currentCallback = null; - cb(new MessageSizeExceededError()); - } return; } this.#inflate[kBuffer].push(data); @@ -14694,19 +14885,17 @@ var require_permessage_deflate = __commonJS({ callback(err); }); } - this.#currentCallback = callback; this.#inflate.write(chunk); if (fin) { this.#inflate.write(tail); } this.#inflate.flush(() => { - if (this.#aborted || !this.#inflate) { + if (!this.#inflate) { return; } const full = Buffer.concat(this.#inflate[kBuffer], this.#inflate[kLength]); this.#inflate[kBuffer].length = 0; this.#inflate[kLength] = 0; - this.#currentCallback = null; callback(null, full); }); } @@ -14750,16 +14939,23 @@ var require_receiver = __commonJS({ #extensions; /** @type {import('./websocket').Handler} */ #handler; + /** @type {number} */ + #maxFragments; + /** @type {number} */ + #maxPayloadSize; /** * @param {import('./websocket').Handler} handler * @param {Map|null} extensions + * @param {{ maxFragments?: number, maxPayloadSize?: number }} [options] */ - constructor(handler, extensions) { + constructor(handler, extensions, options = {}) { super(); this.#handler = handler; this.#extensions = extensions == null ? /* @__PURE__ */ new Map() : extensions; + this.#maxFragments = options.maxFragments ?? 0; + this.#maxPayloadSize = options.maxPayloadSize ?? 0; if (this.#extensions.has("permessage-deflate")) { - this.#extensions.set("permessage-deflate", new PerMessageDeflate(extensions)); + this.#extensions.set("permessage-deflate", new PerMessageDeflate(extensions, options)); } } /** @@ -14772,6 +14968,13 @@ var require_receiver = __commonJS({ this.#loop = true; this.run(callback); } + #validatePayloadLength() { + if (this.#maxPayloadSize > 0 && !isControlFrame(this.#info.opcode) && this.#info.payloadLength + this.#fragmentsBytes > this.#maxPayloadSize) { + failWebsocketConnection(this.#handler, 1009, "Payload size exceeds maximum allowed size"); + return false; + } + return true; + } /** * Runs whenever a new chunk is received. * Callback is called whenever there are no more chunks buffering, @@ -14831,6 +15034,9 @@ var require_receiver = __commonJS({ if (payloadLength <= 125) { this.#info.payloadLength = payloadLength; this.#state = parserStates.READ_DATA; + if (!this.#validatePayloadLength()) { + return; + } } else if (payloadLength === 126) { this.#state = parserStates.PAYLOADLENGTH_16; } else if (payloadLength === 127) { @@ -14851,6 +15057,9 @@ var require_receiver = __commonJS({ const buffer = this.consume(2); this.#info.payloadLength = buffer.readUInt16BE(0); this.#state = parserStates.READ_DATA; + if (!this.#validatePayloadLength()) { + return; + } } else if (this.#state === parserStates.PAYLOADLENGTH_64) { if (this.#byteOffset < 8) { return callback(); @@ -14864,6 +15073,9 @@ var require_receiver = __commonJS({ } this.#info.payloadLength = lower; this.#state = parserStates.READ_DATA; + if (!this.#validatePayloadLength()) { + return; + } } else if (this.#state === parserStates.READ_DATA) { if (this.#byteOffset < this.#info.payloadLength) { return callback(); @@ -14874,30 +15086,43 @@ var require_receiver = __commonJS({ this.#state = parserStates.INFO; } else { if (!this.#info.compressed) { - this.writeFragments(body); + if (!this.writeFragments(body)) { + return; + } if (!this.#info.fragmented && this.#info.fin) { websocketMessageReceived(this.#handler, this.#info.binaryType, this.consumeFragments()); } this.#state = parserStates.INFO; } else { - this.#extensions.get("permessage-deflate").decompress(body, this.#info.fin, (error, data) => { - if (error) { - const code = error instanceof MessageSizeExceededError ? 1009 : 1007; - failWebsocketConnection(this.#handler, code, error.message); - return; - } - this.writeFragments(data); - if (!this.#info.fin) { - this.#state = parserStates.INFO; + this.#extensions.get("permessage-deflate").decompress( + body, + this.#info.fin, + (error, data) => { + if (error) { + const code = error instanceof MessageSizeExceededError ? 1009 : 1007; + failWebsocketConnection(this.#handler, code, error.message); + return; + } + if (!this.writeFragments(data)) { + return; + } + if (this.#maxPayloadSize > 0 && this.#fragmentsBytes > this.#maxPayloadSize) { + failWebsocketConnection(this.#handler, 1009, new MessageSizeExceededError().message); + return; + } + if (!this.#info.fin) { + this.#state = parserStates.INFO; + this.#loop = true; + this.run(callback); + return; + } + websocketMessageReceived(this.#handler, this.#info.binaryType, this.consumeFragments()); this.#loop = true; + this.#state = parserStates.INFO; this.run(callback); - return; - } - websocketMessageReceived(this.#handler, this.#info.binaryType, this.consumeFragments()); - this.#loop = true; - this.#state = parserStates.INFO; - this.run(callback); - }); + }, + this.#fragmentsBytes + ); this.#loop = false; break; } @@ -14945,8 +15170,13 @@ var require_receiver = __commonJS({ } } writeFragments(fragment) { + if (this.#maxFragments > 0 && this.#fragments.length === this.#maxFragments) { + failWebsocketConnection(this.#handler, 1008, "Too many message fragments"); + return false; + } this.#fragmentsBytes += fragment.length; this.#fragments.push(fragment); + return true; } consumeFragments() { const fragments = this.#fragments; @@ -15422,7 +15652,13 @@ var require_websocket = __commonJS({ */ #onConnectionEstablished(response, parsedExtensions) { this.#handler.socket = response.socket; - const parser = new ByteParser(this.#handler, parsedExtensions); + const webSocketOptions = this.#handler.controller.dispatcher?.webSocketOptions; + const maxFragments = webSocketOptions?.maxFragments; + const maxPayloadSize = webSocketOptions?.maxPayloadSize; + const parser = new ByteParser(this.#handler, parsedExtensions, { + maxFragments, + maxPayloadSize + }); parser.on("drain", () => this.#handler.onParserDrain()); parser.on("error", (err) => this.#handler.onParserError(err)); this.#parser = parser; @@ -16632,7 +16868,7 @@ var require_api_request = __commonJS({ if (typeof callback !== "function") { throw new InvalidArgumentError("invalid callback"); } - if (highWaterMark && (typeof highWaterMark !== "number" || highWaterMark < 0)) { + if (highWaterMark != null && (!Number.isFinite(highWaterMark) || highWaterMark < 0)) { throw new InvalidArgumentError("invalid highWaterMark"); } if (signal && typeof signal.on !== "function" && typeof signal.addEventListener !== "function") { diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index a26f2dc7fa4649..90cb40d98d47ab 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -460,27 +460,28 @@ static ssize_t uv__preadv_or_pwritev(int fd, off_t off, _Atomic uintptr_t* cache, int is_pread) { - ssize_t (*f)(int, const struct iovec*, uv__iovcnt, off_t); - void* p; + union { + ssize_t (*f)(int, const struct iovec*, uv__iovcnt, off_t); + void* p; + } u; - p = (void*) atomic_load_explicit(cache, memory_order_relaxed); - if (p == NULL) { + u.p = (void*) atomic_load_explicit(cache, memory_order_relaxed); + if (u.p == NULL) { #ifdef RTLD_DEFAULT /* Try _LARGEFILE_SOURCE version of preadv/pwritev first, * then fall back to the plain version, for libcs like musl. */ - p = dlsym(RTLD_DEFAULT, is_pread ? "preadv64" : "pwritev64"); - if (p == NULL) - p = dlsym(RTLD_DEFAULT, is_pread ? "preadv" : "pwritev"); + u.p = dlsym(RTLD_DEFAULT, is_pread ? "preadv64" : "pwritev64"); + if (u.p == NULL) + u.p = dlsym(RTLD_DEFAULT, is_pread ? "preadv" : "pwritev"); dlerror(); /* Clear errors. */ #endif /* RTLD_DEFAULT */ - if (p == NULL) - p = is_pread ? uv__preadv_emul : uv__pwritev_emul; - atomic_store_explicit(cache, (uintptr_t) p, memory_order_relaxed); + if (u.p == NULL) + u.f = is_pread ? uv__preadv_emul : uv__pwritev_emul; + atomic_store_explicit(cache, (uintptr_t) u.p, memory_order_relaxed); } - f = p; - return f(fd, bufs, nbufs, off); + return u.f(fd, bufs, nbufs, off); } diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index e5a7632909fc65..f1e8928d37ebf4 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -957,7 +957,7 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { int i; for (i = 0; i < count; i++) - uv__free(cpu_infos[i].model); + uv__free((char*) cpu_infos[i].model); uv__free(cpu_infos); #endif /* __linux__ */ diff --git a/deps/v8/src/codegen/external-reference.h b/deps/v8/src/codegen/external-reference.h index 702dcf5618bc95..8c6e511f532619 100644 --- a/deps/v8/src/codegen/external-reference.h +++ b/deps/v8/src/codegen/external-reference.h @@ -364,6 +364,8 @@ enum class IsolateFieldId : uint8_t; IF_WASM(V, wasm_WebAssemblyExceptionGetArg, \ "wasm::WebAssemblyExceptionGetArg") \ IF_WASM(V, wasm_WebAssemblyExceptionIs, "wasm::WebAssemblyExceptionIs") \ + IF_WASM(V, wasm_WebAssemblyExceptionGetStack, \ + "wasm::WebAssemblyExceptionGetStack") \ IF_WASM(V, wasm_WebAssemblyGlobal, "wasm::WebAssemblyGlobal") \ IF_WASM(V, wasm_WebAssemblyGlobalGetValue, \ "wasm::WebAssemblyGlobalGetValue") \ diff --git a/deps/v8/src/wasm/wasm-js.cc b/deps/v8/src/wasm/wasm-js.cc index ef83a43ddc66b8..74328efe56136b 100644 --- a/deps/v8/src/wasm/wasm-js.cc +++ b/deps/v8/src/wasm/wasm-js.cc @@ -3054,6 +3054,15 @@ void WebAssemblyExceptionIsImpl( info.GetReturnValue().Set(tag_object->tag() == *tag); } +void WebAssemblyExceptionGetStackImpl( + const v8::FunctionCallbackInfo& info) { + WasmJSApiScope js_api_scope{info, "WebAssembly.Exception.stack()"}; + auto [isolate, i_isolate, thrower] = js_api_scope.isolates_and_thrower(); + EXTRACT_THIS(exception, WasmExceptionPackage); + + info.GetReturnValue().Set(v8::Undefined(isolate)); +} + void WebAssemblyGlobalGetValueCommon(WasmJSApiScope& js_api_scope) { auto [isolate, i_isolate, thrower] = js_api_scope.isolates_and_thrower(); auto& info = js_api_scope.callback_info(); // Needed by EXTRACT_THIS. @@ -3494,6 +3503,7 @@ void WasmJs::PrepareForSnapshot(Isolate* isolate) { { DirectHandle exception_constructor = InstallConstructorFunc( isolate, webassembly, "Exception", wasm::WebAssemblyException); + exception_constructor->shared()->set_length(2); SetDummyInstanceTemplate(isolate, exception_constructor); DirectHandle exception_proto = SetupConstructor( isolate, exception_constructor, WASM_EXCEPTION_PACKAGE_TYPE, @@ -3503,6 +3513,8 @@ void WasmJs::PrepareForSnapshot(Isolate* isolate) { wasm::WebAssemblyExceptionGetArg, 2); InstallFunc(isolate, exception_proto, "is", wasm::WebAssemblyExceptionIs, 1); + InstallGetter(isolate, exception_proto, "stack", + wasm::WebAssemblyExceptionGetStack); native_context->set_wasm_exception_constructor(*exception_constructor); DirectHandle initial_map(exception_constructor->initial_map(), diff --git a/deps/v8/src/wasm/wasm-js.h b/deps/v8/src/wasm/wasm-js.h index 73134148b0870a..9d136a5484c84e 100644 --- a/deps/v8/src/wasm/wasm-js.h +++ b/deps/v8/src/wasm/wasm-js.h @@ -33,6 +33,7 @@ V8_EXPORT_PRIVATE std::unique_ptr StartStreamingForTesting( V(WebAssemblyCompile) \ V(WebAssemblyException) \ V(WebAssemblyExceptionGetArg) \ + V(WebAssemblyExceptionGetStack) \ V(WebAssemblyExceptionIs) \ V(WebAssemblyGlobal) \ V(WebAssemblyGlobalGetValue) \ diff --git a/deps/v8/test/mjsunit/wasm/exceptions-api.js b/deps/v8/test/mjsunit/wasm/exceptions-api.js index 25ba9c7e80ec27..9ceb2d506dfcbf 100644 --- a/deps/v8/test/mjsunit/wasm/exceptions-api.js +++ b/deps/v8/test/mjsunit/wasm/exceptions-api.js @@ -106,13 +106,19 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); print(arguments.callee.name); let tag = new WebAssembly.Tag({parameters: []}); let exn = new WebAssembly.Exception(tag, []); + assertTrue('stack' in exn); assertEquals(undefined, exn.stack); exn = new WebAssembly.Exception(tag, [], {traceStack: false}); + assertTrue('stack' in exn); assertEquals(undefined, exn.stack); exn = new WebAssembly.Exception(tag, [], {traceStack: true}); assertTrue(exn.stack.indexOf(arguments.callee.name) > 0); assertThrows(() => new WebAssembly.Exception(tag, [], 0), TypeError, /Argument 2 is not an object/); + // The stack getter may only be used with a receiver that is a + // WebAssembly.Exception. + let proto = WebAssembly.Exception.prototype; + assertThrows(() => proto.stack, TypeError); })(); (function TestCatchJSException() { @@ -319,3 +325,7 @@ function TestGetArgHelper(types_str, types, values) { // Don't catch with implicit wrapping. assertThrowsEquals(() => instance.exports.test(obj), obj); })(); + +(function TestExceptionConstructorLength() { + assertEquals(2, WebAssembly.Exception.length); +})(); diff --git a/doc/api/assert.md b/doc/api/assert.md index 463cd1ef8a7c3c..e0eed6098747d9 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -2036,7 +2036,7 @@ If no arguments are passed in at all `message` will be set to the string: Be aware that in the `repl` the error message will be different to the one thrown in a file! See below for further details. - + ```mjs import assert from 'node:assert/strict'; @@ -2073,7 +2073,7 @@ assert.ok(0); // assert.ok(0) ``` - + ```cjs const assert = require('node:assert/strict'); diff --git a/doc/api/cli.md b/doc/api/cli.md index ca5126bfd2c09c..6eeb360419df83 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -974,7 +974,8 @@ added: v23.10.0 If present, Node.js will look for a configuration file at the specified path. Node.js will read the configuration file and apply the settings. The configuration file should be a JSON file with the following structure. `vX.Y.Z` -in the `$schema` must be replaced with the version of Node.js you are using. +in the `$schema` must be replaced with the version of Node.js you are using or +`latest-vX.x` for the latest version of that major release line. ```json { diff --git a/doc/api/console.md b/doc/api/console.md index f0669558abe385..804778bd5fa681 100644 --- a/doc/api/console.md +++ b/doc/api/console.md @@ -240,9 +240,7 @@ added: v8.3.0 Maintains an internal counter specific to `label` and outputs to `stdout` the number of times `console.count()` has been called with the given `label`. - - -```js +```console > console.count() default: 1 undefined @@ -274,9 +272,7 @@ added: v8.3.0 Resets the internal counter specific to `label`. - - -```js +```console > console.count('abc'); abc: 1 undefined diff --git a/doc/api/crypto.md b/doc/api/crypto.md index 13ae03dc608740..a9b1bafa6749eb 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -53,8 +53,6 @@ try { } ``` - - When using the lexical ESM `import` keyword, the error can only be caught if a handler for `process.on('uncaughtException')` is registered _before_ any attempt to load the module is made (using, for instance, @@ -6092,7 +6090,7 @@ changes: * `algorithm` {string | null | undefined} -* `data` {ArrayBuffer|Buffer|TypedArray|DataView} +* `data` {ArrayBuffer|Buffer|SharedArrayBuffer|TypedArray|DataView|string} * `key` {Object|string|ArrayBuffer|Buffer|TypedArray|DataView|KeyObject|CryptoKey} * `callback` {Function} * `err` {Error} @@ -6224,9 +6222,9 @@ changes: * `algorithm` {string|null|undefined} -* `data` {ArrayBuffer| Buffer|TypedArray|DataView} +* `data` {ArrayBuffer|Buffer|SharedArrayBuffer|TypedArray|DataView|string} * `key` {Object|string|ArrayBuffer|Buffer|TypedArray|DataView|KeyObject|CryptoKey} -* `signature` {ArrayBuffer|Buffer|TypedArray|DataView} +* `signature` {ArrayBuffer|Buffer|SharedArrayBuffer|TypedArray|DataView} * `callback` {Function} * `err` {Error} * `result` {boolean} @@ -6617,7 +6615,7 @@ See the [list of SSL OP Flags][] for details. SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS - Instructs OpenSSL to disable a SSL 3.0/TLS 1.0 vulnerability + Instructs OpenSSL to disable an SSL 3.0/TLS 1.0 vulnerability workaround added in OpenSSL 0.9.6d. diff --git a/doc/api/debugger.md b/doc/api/debugger.md index 68fdf255a7ecd4..2fb579ca967d67 100644 --- a/doc/api/debugger.md +++ b/doc/api/debugger.md @@ -10,6 +10,14 @@ Node.js includes a command-line debugging utility. The Node.js debugger client is not a full-featured debugger, but simple stepping and inspection are possible. +The debugger supports two modes of operation: [interactive mode][] and [non-interactive probe mode][]. + +## Interactive mode + +```console +$ node inspect [--port=] [ ...] [