[
  {
    "path": ".cargo/config.toml",
    "content": "[alias]\n# Neon defines mutually exclusive feature flags which prevents using `cargo clippy --all-features`\n# The following aliases simplify linting the entire workspace\nneon-check = \" check  --all --all-targets --features napi-experimental,external-buffers,serde,tokio\"\nneon-clippy = \"clippy --all --all-targets --features napi-experimental,external-buffers,serde,tokio -- -A clippy::missing_safety_doc\"\nneon-test = \"  test   --all               --features=doc-dependencies,doc-comment,napi-experimental,external-buffers,serde,tokio\"\nneon-doc = \"   rustdoc -p neon            --features=doc-dependencies,napi-experimental,external-buffers,sys,serde,tokio -- --cfg docsrs\"\n"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nindent_style = space\nindent_size = 2\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[*.rs]\nindent_size = 4\n\n[*.toml]\nindent_size = 4\n\n[*.md]\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": ".github/workflows/bench.yml",
    "content": "name: Benchmarks\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n    branches:\n      - main\n\njobs:\n  bench:\n    name: regression\n    permissions:\n      checks: write\n      pull-requests: write\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: bencherdev/bencher@main\n      - name: Use Rust Stable\n        uses: dtolnay/rust-toolchain@stable\n      - name: Use Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20.x\n          cache: npm\n      - name: npm install\n        run: npm ci --prefer-offline --no-audit --no-fund\n      - name: Install Benchmark Dependencies\n        working-directory: ./bench\n        run: npm install\n      - name: Build Benchmark\n        working-directory: ./bench\n        run: npm run build\n      - name: Track base branch benchmarks with Bencher\n        if: github.ref_name == 'main'\n        run: bencher run\n          --project neon\n          --token '${{ secrets.BENCHER_API_TOKEN }}'\n          --branch main\n          --testbed ubuntu-latest\n          --adapter json\n          --github-actions '${{ secrets.GITHUB_TOKEN }}'\n          npm run --silent benchmark\n        working-directory: ./bench\n      - name: Track pull request benchmarks with Bencher\n        if: github.ref_name != 'main'\n        run: bencher run\n          --project neon\n          --token '${{ secrets.BENCHER_API_TOKEN }}'\n          --branch \"$GITHUB_HEAD_REF\"\n          --start-point \"$GITHUB_BASE_REF\"\n          --start-point-hash '${{ github.event.pull_request.base.sha }}'\n          --start-point-clone-thresholds\n          --start-point-reset\n          --testbed ubuntu-latest\n          --adapter json\n          --github-actions '${{ secrets.GITHUB_TOKEN }}'\n          npm run --silent benchmark\n        working-directory: ./bench\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non:\n  push:\n    # Prevent duplicate runs of this workflow on our own internal PRs.\n    branches:\n      - main\n      - next/*\n  pull_request:\n    types: [opened, synchronize, reopened, labeled]\n    branches:\n      - main\n      - next/*\n\nenv:\n  PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: \"true\"\n\njobs:\n  matrix:\n    runs-on: ubuntu-latest\n    outputs:\n      node_version: ${{ steps.set_matrix.outputs.node_version }}\n      rust_toolchain: ${{ steps.set_matrix.outputs.rust_toolchain }}\n    steps:\n      - name: Set Matrix\n        id: set_matrix\n        env:\n          FULL_NODE_VERSIONS: '[\"18.x\", \"20.x\"]'\n          FULL_RUST_TOOLCHAINS: '[\"stable\", \"nightly\"]'\n          PARTIAL_NODE_VERSIONS: '[\"20.x\"]'\n          PARTIAL_RUST_TOOLCHAINS: '[\"stable\"]'\n          HAS_FULL_MATRIX_LABEL: ${{ contains(github.event.pull_request.labels.*.name, 'full matrix') }}\n          IS_PUSHED: ${{ github.event_name == 'push' }}\n        run: |\n          if [[ \"$HAS_FULL_MATRIX_LABEL\" == \"true\" ]] || [[ \"$IS_PUSHED\" == \"true\" ]]; then\n            echo \"node_version=$FULL_NODE_VERSIONS\" >> $GITHUB_OUTPUT\n            echo \"rust_toolchain=$FULL_RUST_TOOLCHAINS\" >> $GITHUB_OUTPUT\n          else\n            echo \"node_version=$PARTIAL_NODE_VERSIONS\" >> $GITHUB_OUTPUT\n            echo \"rust_toolchain=$PARTIAL_RUST_TOOLCHAINS\" >> $GITHUB_OUTPUT\n          fi\n\n  build:\n    needs: matrix\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        os: [ubuntu-latest, windows-latest, macos-latest]\n        node-version: ${{fromJson(needs.matrix.outputs.node_version)}}\n        rust-toolchain: ${{fromJson(needs.matrix.outputs.rust_toolchain)}}\n\n    steps:\n      - name: Checkout Code\n        uses: actions/checkout@v4\n\n      - name: Use Rust ${{ matrix.rust-toolchain }}\n        uses: dtolnay/rust-toolchain@v1\n        with:\n          toolchain: ${{ matrix.rust-toolchain }}\n          components: clippy,rustfmt\n\n      - name: Rust Cache\n        uses: Swatinem/rust-cache@v2\n\n      - name: Use Node.js ${{ matrix.node-version }}\n        uses: actions/setup-node@v4\n        with:\n          node-version: ${{ matrix.node-version }}\n          cache: npm\n\n      - name: Cache Electron (Linux)\n        if: matrix.os == 'ubuntu-latest'\n        uses: actions/cache@v4\n        with:\n          key: ${{ runner.os }}-electron-${{ hashFiles('./package-lock.json') }}\n          path: ~/.cache/electron\n      - name: Cache Electron (Windows)\n        if: matrix.os == 'windows-latest'\n        uses: actions/cache@v4\n        with:\n          key: ${{ runner.os }}-electron-${{ hashFiles('./package-lock.json') }}\n          path: \"%LOCALAPPDATA%\\\\electron\\\\Cache\"\n      - name: Cache Electron (macOS)\n        if: matrix.os == 'macos-latest'\n        uses: actions/cache@v4\n        with:\n          key: ${{ runner.os }}-electron-${{ hashFiles('./package-lock.json') }}\n          path: ~/Library/Caches/electron\n\n      - name: Install cargo-llvm-cov\n        if: matrix.os == 'ubuntu-latest' && matrix.rust-toolchain == 'stable'\n        uses: taiki-e/install-action@cargo-llvm-cov\n\n      - name: Set coverage environment variables\n        if: matrix.os == 'ubuntu-latest' && matrix.rust-toolchain == 'stable'\n        run: cargo llvm-cov show-env | tr -d \"'\" >> $GITHUB_ENV\n\n      - name: npm install\n        run: npm ci --prefer-offline --no-audit --no-fund\n\n      - name: Allow unprivileged X server\n        if: matrix.os == 'ubuntu-latest'\n        run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0\n\n      - name: Test (Linux)\n        if: matrix.os == 'ubuntu-latest'\n        run: xvfb-run --auto-servernum npm test -- --nocapture\n      - name: Test\n        if: matrix.os != 'ubuntu-latest'\n        run: npm test\n\n      - name: Generate coverage report\n        if: matrix.os == 'ubuntu-latest' && matrix.rust-toolchain == 'stable'\n        run: cargo llvm-cov report --codecov --output-path target/codecov.json\n\n      - name: Upload coverage to Codecov\n        if: matrix.os == 'ubuntu-latest' && matrix.rust-toolchain == 'stable'\n        uses: codecov/codecov-action@v5\n        with:\n          token: ${{ secrets.CODECOV_TOKEN }}\n          slug: neon-bindings/neon\n          files: target/codecov.json\n"
  },
  {
    "path": ".github/workflows/lint.yml",
    "content": "name: Lints\n\non:\n  push:\n    # Prevent duplicate runs of this workflow on our own internal PRs.\n    branches:\n      - main\n      - next/*\n  pull_request:\n    branches:\n      - main\n      - next/*\n\nenv:\n  PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: \"true\"\n\njobs:\n  lint:\n    runs-on: ubuntu-latest\n\n    strategy:\n      matrix:\n        node-version: [20.x]\n        rust-toolchain: [nightly]\n\n    steps:\n      - name: Checkout Code\n        uses: actions/checkout@v4\n      - name: Use Rust ${{ matrix.rust-toolchain }}\n        uses: dtolnay/rust-toolchain@v1\n        with:\n          toolchain: ${{ matrix.rust-toolchain }}\n          components: clippy,rustfmt\n      - name: Rust Cache\n        uses: Swatinem/rust-cache@v2\n      - name: Use Node.js ${{ matrix.node-version }}\n        uses: actions/setup-node@v4\n        with:\n          node-version: ${{ matrix.node-version }}\n          cache: \"npm\"\n      - name: Cache Electron\n        uses: actions/cache@v4\n        with:\n          path: ~/.cache/electron\n          key: ${{ runner.os }}-electron-${{ hashFiles('./package-lock.json') }}\n      - name: npm install\n        run: npm ci --prefer-offline --no-audit --no-fund\n      - name: Prettier Formatting\n        run: npm run prettier:check\n      - name: Rust Formatting\n        run: cargo fmt --all -- --check\n      - name: Rust Clippy\n        run: cargo neon-clippy\n"
  },
  {
    "path": ".gitignore",
    "content": "# Rust\ntarget\nrls*.log\n\n# Created by `trybuild` ui tests\nwip\n**/*~\n\n# Node\n**/node_modules\nnpm-debug.log\n\n# JS build\n**/build\n**/dist\ncli/lib\ntest/cli/lib\n\n# Neon build\n**/index.node\n**/artifacts.json\npkgs/create-neon/create-neon-test-project\npkgs/create-neon/create-neon-manual-test-project\n\n# System\n**/.DS_Store\n"
  },
  {
    "path": ".prettierignore",
    "content": ".git/\ncli/lib/\ntest/cli/lib/\nnode_modules/\n**/dist/\ntarget/\nartifacts.json\n"
  },
  {
    "path": "AUTHORS.md",
    "content": "# Authors\n\nNeon owes its existence to the contributions of these fine people.\n\n* [Reza Akhavan](https://github.com/jedireza)\n* [andiliu-gh](https://github.com/andiliu-gh)\n* [Nerijus Arlauskas](https://github.com/Nercury)\n* [Igor Artamonov](https://github.com/splix)\n* [Peter Atashian](https://github.com/retep998)\n* [Alexander Azarov](https://github.com/alaz)\n* [David Baker](https://github.com/dbkr)\n* [Sean Billig](https://github.com/sbillig)\n* [Tim Blair](https://github.com/tblair)\n* [Max Brunsfeld](https://github.com/maxbrunsfeld)\n* [Dale Bustad](https://github.com/divmain)\n* [Eduard-Mihai Burtescu](https://github.com/eddyb)\n* [Gabriel Castro](https://github.com/GabrielCastro)\n* [Lin Clark](https://github.com/linclark)\n* [ComplexSpaces](https://github.com/complexspaces)\n* [Nathaniel Daniel](https://github.com/adumbidiot)\n* [John Darrington](https://github.com/DnOberon)\n* [erics118](https://github.com/erics118)\n* [Joey Ezechiëls](https://github.com/jjpe)\n* [Ryan Fitzgerald](https://github.com/rf-)\n* [Cory Forsyth](https://github.com/bantic)\n* [Olivier Goffart](https://github.com/ogoffart)\n* [Dave Herman](https://github.com/dherman)\n* [Himself65](https://github.com/Himself65)\n* [Maciej Hirsz](https://github.com/maciejhirsz)\n* [Amal Hussein](https://github.com/nomadtechie)\n* [Fedor Indutny](https://github.com/indutny)\n* [Usagi Ito](https://github.com/usagi)\n* [j1ngzoue](https://github.com/activeguild)\n* [Jeroen (jrd-rocks)](https://github.com/jrd-rocks)\n* [Keegan (mhsjlw)](https://github.com/mhsjlw)\n* [Florian Keller](https://github.com/ffflorian)\n* [Aleksey Kladov](https://github.com/matklad)\n* [Adam Kloboucnik](https://github.com/akloboucnik)\n* [Renée Kooi](https://github.com/goto-bus-stop)\n* [Laz](https://github.com/lazops)\n* [Anton Lazarev](https://github.com/antonok-edm)\n* [Simon Liang](https://github.com/lhr0909)\n* [Matthew Little](https://github.com/zone117x)\n* [Terence Lee](https://github.com/hone)\n* [Milan Loveless](https://github.com/MilanLoveless)\n* [Mikuroさいな](https://github.com/MikuroXina)\n* [MikaelUrankar](https://github.com/MikaelUrankar)\n* [Darin Morrison](https://github.com/freebroccolo)\n* [Martin Muñoz](https://github.com/mmun)\n* [Dominik Nakamura](https://github.com/dnaka91)\n* [Kayo Phoenix](https://github.com/katyo)\n* [Mike Piccolo](https://github.com/mfpiccolo)\n* [Jan Piotrowski](https://github.com/janpio)\n* [Robbie Pitts](https://github.com/robbiepitts)\n* [Thiago Pontes](https://github.com/thiagopnts)\n* [Sean Prashad](https://github.com/SeanPrashad)\n* [Jordan Rose](https://github.com/jrose-signal)\n* [Antonio Scandurra](https://github.com/as-cii)\n* [Edward Shaw](https://github.com/EdShaw)\n* [Nathan Sobo](https://github.com/nathansobo)\n* [sockmaster27](https://github.com/sockmaster27)\n* [André Staltz](https://github.com/staltz)\n* [Ingvar Stepanyan](https://github.com/RReverser)\n* [stoically](https://github.com/stoically)\n* [Andrew Stucki](https://github.com/andrewstucki)\n* [Martin Svanberg](https://github.com/msvbg)\n* [A2ZH (theJian)](https://github.com/theJian)\n* [Alex Touchet](https://github.com/atouchet)\n* [Corbin Uselton](https://github.com/corbinu)\n* [K.J. Valencik](https://github.com/kjvalencik)\n* [Velithris](https://github.com/Zireael-N)\n* [Roberto Vidal](https://github.com/jrvidal)\n* [Georg Vienna](https://github.com/geovie)\n* [Daijiro Wachi](https://github.com/watilde)\n* [Chi Wang](https://github.com/patr0nus)\n* [wangcong](https://github.com/king6cong)\n* [Amila Welihinda](https://github.com/amilajack)\n* [xyloflake](https://github.com/xyloflake)\n* [Felix Yan](https://github.com/felixonmars)\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, gender identity and expression, level of experience,\nnationality, personal appearance, race, religion, or sexual identity and\norientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\n  advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n  address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at david.herman@gmail.com. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to Neon\n\nNeon welcomes contribution from everyone. Here are some resources to help you join us!\n\n## Contributions\n\n### Issue reports\n\nWe welcome issues and aim to keep the barrier low. Just [file a GitHub issue](https://github.com/neon-bindings/neon/issues)\nlike normal---we don't require issue templates or have any particular process.\n\nThat said, the more information you can provide to help us reproduce your issue, the better!\n\n### Requests For Comments\n\nIf you would like to propose a design change or new feature for the Neon API or the `neon` command-line tool,\nwe encourage you to [submit an RFC](https://github.com/neon-bindings/rfcs)!\n\nThe [RFC process](https://github.com/neon-bindings/rfcs#the-process) has a little more overhead than\nfiling an issue, but it's for the goal of allowing the Neon community to have a chance to vet\ndesign ideas and reach consensus. And even at that, we've deliberately kept the [RFC template](https://github.com/neon-bindings/rfcs/blob/main/0000-template.md)\nsimple and open-ended.\n\n### Good first bugs\n\nSearch our issue tracker for anything labeled **[beginner friendly](https://github.com/neon-bindings/neon/issues?q=is%3Aissue+is%3Aopen+label%3A%22beginner+friendly%22)**.\n\n**We are here to help you!** Join our Slack and send an at-mention to **@dherman** and we'll happily arrange\nto help you get going and mentor you as much as you feel would be helpful.\n\n## Conduct\n\nWe follow the [Contributor Covenant Code of Conduct](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html).\nThe maintainers of Neon personally promise to work actively to uphold that code of conduct.\nWe aim to foster a community that is welcoming, inclusive, empathetic, and kind.\nIf you share those goals and want to have a ton of fun playing with Rust and JS, we hope you will come be a part of our community!\n\n## License\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as described in the [README](README.md), without any additional terms or conditions.\n\n## Communication\n\n* Slack: <https://rust-bindings.slack.com> -- get an invite from [the Slackin app](https://rust-bindings-slackin.herokuapp.com)\n"
  },
  {
    "path": "Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = [\n    \"crates/*\",\n    \"test/*\",\n    \"bench\",\n]\n\n[profile.release]\nlto = true\n"
  },
  {
    "path": "LICENSE-APACHE",
    "content": "                              Apache License\n                        Version 2.0, January 2004\n                     http://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n   \"License\" shall mean the terms and conditions for use, reproduction,\n   and distribution as defined by Sections 1 through 9 of this document.\n\n   \"Licensor\" shall mean the copyright owner or entity authorized by\n   the copyright owner that is granting the License.\n\n   \"Legal Entity\" shall mean the union of the acting entity and all\n   other entities that control, are controlled by, or are under common\n   control with that entity. For the purposes of this definition,\n   \"control\" means (i) the power, direct or indirect, to cause the\n   direction or management of such entity, whether by contract or\n   otherwise, or (ii) ownership of fifty percent (50%) or more of the\n   outstanding shares, or (iii) beneficial ownership of such entity.\n\n   \"You\" (or \"Your\") shall mean an individual or Legal Entity\n   exercising permissions granted by this License.\n\n   \"Source\" form shall mean the preferred form for making modifications,\n   including but not limited to software source code, documentation\n   source, and configuration files.\n\n   \"Object\" form shall mean any form resulting from mechanical\n   transformation or translation of a Source form, including but\n   not limited to compiled object code, generated documentation,\n   and conversions to other media types.\n\n   \"Work\" shall mean the work of authorship, whether in Source or\n   Object form, made available under the License, as indicated by a\n   copyright notice that is included in or attached to the work\n   (an example is provided in the Appendix below).\n\n   \"Derivative Works\" shall mean any work, whether in Source or Object\n   form, that is based on (or derived from) the Work and for which the\n   editorial revisions, annotations, elaborations, or other modifications\n   represent, as a whole, an original work of authorship. For the purposes\n   of this License, Derivative Works shall not include works that remain\n   separable from, or merely link (or bind by name) to the interfaces of,\n   the Work and Derivative Works thereof.\n\n   \"Contribution\" shall mean any work of authorship, including\n   the original version of the Work and any modifications or additions\n   to that Work or Derivative Works thereof, that is intentionally\n   submitted to Licensor for inclusion in the Work by the copyright owner\n   or by an individual or Legal Entity authorized to submit on behalf of\n   the copyright owner. For the purposes of this definition, \"submitted\"\n   means any form of electronic, verbal, or written communication sent\n   to the Licensor or its representatives, including but not limited to\n   communication on electronic mailing lists, source code control systems,\n   and issue tracking systems that are managed by, or on behalf of, the\n   Licensor for the purpose of discussing and improving the Work, but\n   excluding communication that is conspicuously marked or otherwise\n   designated in writing by the copyright owner as \"Not a Contribution.\"\n\n   \"Contributor\" shall mean Licensor and any individual or Legal Entity\n   on behalf of whom a Contribution has been received by Licensor and\n   subsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   copyright license to reproduce, prepare Derivative Works of,\n   publicly display, publicly perform, sublicense, and distribute the\n   Work and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   (except as stated in this section) patent license to make, have made,\n   use, offer to sell, sell, import, and otherwise transfer the Work,\n   where such license applies only to those patent claims licensable\n   by such Contributor that are necessarily infringed by their\n   Contribution(s) alone or by combination of their Contribution(s)\n   with the Work to which such Contribution(s) was submitted. If You\n   institute patent litigation against any entity (including a\n   cross-claim or counterclaim in a lawsuit) alleging that the Work\n   or a Contribution incorporated within the Work constitutes direct\n   or contributory patent infringement, then any patent licenses\n   granted to You under this License for that Work shall terminate\n   as of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\n   Work or Derivative Works thereof in any medium, with or without\n   modifications, and in Source or Object form, provided that You\n   meet the following conditions:\n\n   (a) You must give any other recipients of the Work or\n       Derivative Works a copy of this License; and\n\n   (b) You must cause any modified files to carry prominent notices\n       stating that You changed the files; and\n\n   (c) You must retain, in the Source form of any Derivative Works\n       that You distribute, all copyright, patent, trademark, and\n       attribution notices from the Source form of the Work,\n       excluding those notices that do not pertain to any part of\n       the Derivative Works; and\n\n   (d) If the Work includes a \"NOTICE\" text file as part of its\n       distribution, then any Derivative Works that You distribute must\n       include a readable copy of the attribution notices contained\n       within such NOTICE file, excluding those notices that do not\n       pertain to any part of the Derivative Works, in at least one\n       of the following places: within a NOTICE text file distributed\n       as part of the Derivative Works; within the Source form or\n       documentation, if provided along with the Derivative Works; or,\n       within a display generated by the Derivative Works, if and\n       wherever such third-party notices normally appear. The contents\n       of the NOTICE file are for informational purposes only and\n       do not modify the License. You may add Your own attribution\n       notices within Derivative Works that You distribute, alongside\n       or as an addendum to the NOTICE text from the Work, provided\n       that such additional attribution notices cannot be construed\n       as modifying the License.\n\n   You may add Your own copyright statement to Your modifications and\n   may provide additional or different license terms and conditions\n   for use, reproduction, or distribution of Your modifications, or\n   for any such Derivative Works as a whole, provided Your use,\n   reproduction, and distribution of the Work otherwise complies with\n   the conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\n   any Contribution intentionally submitted for inclusion in the Work\n   by You to the Licensor shall be under the terms and conditions of\n   this License, without any additional terms or conditions.\n   Notwithstanding the above, nothing herein shall supersede or modify\n   the terms of any separate license agreement you may have executed\n   with Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\n   names, trademarks, service marks, or product names of the Licensor,\n   except as required for reasonable and customary use in describing the\n   origin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\n   agreed to in writing, Licensor provides the Work (and each\n   Contributor provides its Contributions) on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n   implied, including, without limitation, any warranties or conditions\n   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n   PARTICULAR PURPOSE. You are solely responsible for determining the\n   appropriateness of using or redistributing the Work and assume any\n   risks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\n   whether in tort (including negligence), contract, or otherwise,\n   unless required by applicable law (such as deliberate and grossly\n   negligent acts) or agreed to in writing, shall any Contributor be\n   liable to You for damages, including any direct, indirect, special,\n   incidental, or consequential damages of any character arising as a\n   result of this License or out of the use or inability to use the\n   Work (including but not limited to damages for loss of goodwill,\n   work stoppage, computer failure or malfunction, or any and all\n   other commercial damages or losses), even if such Contributor\n   has been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\n   the Work or Derivative Works thereof, You may choose to offer,\n   and charge a fee for, acceptance of support, warranty, indemnity,\n   or other liability obligations and/or rights consistent with this\n   License. However, in accepting such obligations, You may act only\n   on Your own behalf and on Your sole responsibility, not on behalf\n   of any other Contributor, and only if You agree to indemnify,\n   defend, and hold each Contributor harmless for any liability\n   incurred by, or claims asserted against, such Contributor by reason\n   of your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work.\n\n   To apply the Apache License to your work, attach the following\n   boilerplate notice, with the fields enclosed by brackets \"[]\"\n   replaced with your own identifying information. (Don't include\n   the brackets!)  The text should be enclosed in the appropriate\n   comment syntax for the file format. We also recommend that a\n   file or class name and description of purpose be included on the\n   same \"printed page\" as the copyright notice for easier\n   identification within third-party archives.\n\nCopyright [yyyy] [name of copyright owner]\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n"
  },
  {
    "path": "LICENSE-MIT",
    "content": "Copyright (c) 2015 David Herman\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# <img src=\"https://raw.githubusercontent.com/neon-bindings/neon/refs/heads/main/doc/neon.png\" alt=\"neon\" width=\"100%\" />\n\n[![Cargo](https://img.shields.io/crates/v/neon.svg)](https://crates.io/crates/neon)\n[![Test Status](https://github.com/neon-bindings/neon/workflows/CI/badge.svg)](https://github.com/neon-bindings/neon/actions?query=workflow%3A%22CI%22)\n[![Lint Status](https://github.com/neon-bindings/neon/workflows/Lints/badge.svg)](https://github.com/neon-bindings/neon/actions?query=workflow%3A%22Lints%22)\n\nRust bindings for writing safe and fast Node.js native addons.\n\n## Getting started\n\nOnce you have the [platform dependencies](https://neon-bindings.com/docs/quick-start) installed, getting started is as\nsimple as:\n\n```\n$ npm init neon@latest my-project\n```\n\nThen see the [Hello World guide](https://neon-bindings.com/docs/hello-world/) for writing your first Hello World in\nNeon!\n\n## Docs\n\nSee our [Neon fundamentals docs](https://neon-bindings.com/docs/intro) and\nour [API docs](https://docs.rs/neon/latest/neon).\n\n## Neon 1.0.0 Migration Guide\n\nThe latest version of Neon, 1.0.0, includes several breaking changes in order to fix unsoundness, improve consistency, and add features.\n\n**Read the new [migration guide](doc/MIGRATION_GUIDE_1.0.0.md)** to learn how to port your \nNeon projects to 1.0.0!\n\n## Platform Support\n\n### Operating Systems\n\n| Linux  | macOS | Windows |\n| ------ | ----- | ------- |\n| ✓      | ✓     | ✓       |\n\n### Node.js\n\nNeon actively supports all current and [maintenance releases of Node](https://github.com/nodejs/LTS#release-schedule). If you're\nusing a different version of Node and believe it should be supported, let us know.\n\nOlder Node version support (minimum v10) may require lower Node-API versions. See the Node [version support matrix](https://nodejs.org/api/n-api.html#node-api-version-matrix) for more details.\n\n### Bun (experimental)\n\n[Bun](https://bun.sh/) is an alternate JavaScript runtime that targets Node compatibility. In many cases Neon modules will work in bun; however, at the time of this writing, some Node-API functions are [not implemented](https://github.com/oven-sh/bun/issues/158).\n\n### Rust\n\nNeon supports Rust stable version 1.65 and higher. We test on the latest stable, beta, and nightly versions of Rust.\n\n## A Taste...\n\n```rust\nfn make_an_array(mut cx: FunctionContext) -> JsResult<JsArray> {\n    // Create some values:\n    let n = cx.number(9000);\n    let s = cx.string(\"hello\");\n    let b = cx.boolean(true);\n\n    // Create a new array:\n    let array = cx.empty_array();\n\n    // Push the values into the array:\n    array.set(&mut cx, 0, n)?;\n    array.set(&mut cx, 1, s)?;\n    array.set(&mut cx, 2, b)?;\n\n    // Return the array:\n    Ok(array)\n}\n\n#[neon::main]\nfn main(mut cx: ModuleContext) -> NeonResult<()> {\n    cx.export_function(\"make_an_array\", make_an_array)?;\n    Ok(())\n}\n```\n\nFor more examples, see our [examples repo](https://github.com/neon-bindings/examples) and [integration tests](test).\n\n## Get Involved\n\nThe Neon community is just getting started and there's tons of fun to be had. Come play! :)\n\nThe [Neon Community Slack](https://rust-bindings.slack.com) is open to all;\nuse [this invite link](https://join.slack.com/t/rust-bindings/shared_invite/zt-1pl5s83xe-ZvXyrzL8vuUmijU~7yiEcg) to receive an invitation.\n\n### Testing Neon\n\nThe Neon project is both an [NPM workspace](https://docs.npmjs.com/cli/v8/using-npm/workspaces) and\na [Cargo workspace](https://doc.rust-lang.org/cargo/reference/workspaces.html). The full suite of tests may be executed\nby installing and testing the NPM workspace.\n\n```sh\nnpm install\nnpm test\n```\n\nIndividual JavaScript packages may be tested with an `npm` workspace command:\n\n```\nnpm --workspace=create-neon test\n```\n\nIndividual Rust crates may be tested with a `cargo` workspace command:\n\n```\ncargo test -p neon-build\n```\n\n## License\n\nLicensed under either of\n\n* Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)\n* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)\n\nat your option.\n"
  },
  {
    "path": "RELEASES.md",
    "content": "# `cargo-cp-artifact`\n\n`0.1.9` supports a [breaking change in `cargo`](https://github.com/rust-lang/cargo/issues/13867) that converts artifact names from `kebab-case` to `snake_case`.\n\n# Version 1.2.0-alpha.0\n\n### New Features\n\n* [Class macro](https://docs.rs/neon/1/neon/attr.class)\n* [impl TryFromJs for i32 and u32](https://github.com/neon-bindings/neon/pull/1107)\n* [impl TryIntoJs for LazyLock](https://github.com/neon-bindings/neon/pull/1111)\n* [`Deferred::settle()` and `Deferred::try_settle()`](https://github.com/neon-bindings/neon/pull/1120)\n\n# Version 1.1.0\n\n## Continued Commitment to Compatibility\n\nOur strong commitment to compatibility since the 1.0 release remains unchanged. New functionality\nthat has not yet stabilized is published under feature flags, so the only breaking changes that we\nexpect to publish are those that affect the unstable features, or, as always, safety bugfixes.\n\n## Version 1.1.1\n\nHotfix for Node-API versions lower than 5 (https://github.com/neon-bindings/neon/pull/1106).\n\n## Version 1.1.0\n\n### New Features\n\n* [Extractors API](https://docs.rs/neon/1/neon/types/extract/index.html)\n* [`#[export]` macro](https://docs.rs/neon/1/neon/attr.export.html)\n* [`npm init neon -- --lib`](https://www.npmjs.com/package/create-neon)\n* [`JsBox::deref()`](https://docs.rs/neon/1/neon/types/struct.JsBox.html#method.deref)\n* [`Handle<'_, JsBox>::as_inner()`](https://docs.rs/neon/1/neon/handle/struct.Handle.html#method.as_inner)\n\n### Bugfixes\n\n* Fix panic when borrowing empty buffer or typed array (https://github.com/neon-bindings/neon/pull/1058)\n* Fix build script behavior based on cargo diagnostics format change (https://github.com/neon-bindings/neon/pull/1039)\n\n## Version 1.1.0-alpha.2\n\n### Breaking Changes (unstable features only)\n\n* Convert snake_case to camelCase when exporting functions (https://github.com/neon-bindings/neon/pull/1084)\n* Remove `FromArgs` impl on `T: TryFromJs` and add `cx.{arg, arg_opt}` (https://github.com/neon-bindings/neon/pull/1096)\n\n### Other\n\n* Relax lifetime constraints on `With` (https://github.com/neon-bindings/neon/pull/1086)\n* Add `JsBox::{deref, as_inner}` to get long-lived reference to JsBox contents (https://github.com/neon-bindings/neon/pull/1087)\n* Add extractors for TypedArrays (https://github.com/neon-bindings/neon/pull/1089)\n* Add extractors for common container types (https://github.com/neon-bindings/neon/pull/1091)\n\n## Version 1.1.0-alpha.1\n\n### Breaking Changes (unstable features only)\n\n* `TryIntoJs` and `TryFromJs` take `Cx` instead of generic `Context` (https://github.com/neon-bindings/neon/pull/1062)\n\n### Bugfixes\n\n* Fix panic when borrowing empty buffer or typed array (https://github.com/neon-bindings/neon/pull/1058)\n\n### Other\n\n* More reliable checking for `Result` types in `#[export]` (https://github.com/neon-bindings/neon/pull/1057)\n* Allow users to take `Cx` instead of generic `Context` (https://github.com/neon-bindings/neon/pull/1048)\n* Introduce `With` for `TryIntoJs` (https://github.com/neon-bindings/neon/pull/1059)\n* Add tokio async runtime support to `#[export]` (https://github.com/neon-bindings/neon/pull/1055)\n* Add `TryIntoJs` and `TryFromJs` for common container types (https://github.com/neon-bindings/neon/pull/1066)\n* Allow `Cx` in exported functions (https://github.com/neon-bindings/neon/pull/1068)\n\n## Version 1.1.0-alpha.0\n\n### Bugfixes\n\n* Fix build script behavior based on cargo diagnostics format change (https://github.com/neon-bindings/neon/pull/1039)\n\n### Other\n\n* Added Extractors API (https://github.com/neon-bindings/neon/pull/1024)\n* Added `#[export]` macro (https://github.com/neon-bindings/neon/pull/1025)\n* Added `npm init neon --lib` (https://github.com/neon-bindings/neon/pull/1014 and https://github.com/neon-bindings/neon/pull/1041)\n\n\n# Version 1.0.0\n\n## Commitment to Compatibility\n\nThe release of Neon 1.0 marks our commitment to backwards-compatibility: starting with 1.0.0, Neon users can be confident that future **upgrades to Neon 1.x versions should never require code changes** (with the possible exception of safety bugfixes, which we expect to be rare). We also do not anticipate releasing new major versions often and do not have any plans to do so for now.\n\n## Breaking Changes\n\n* Remove the generic parameter from `JsFunction` (https://github.com/neon-bindings/neon/pull/989)\n* `JsArray::new` takes a `usize` instead of a `u32` (https://github.com/neon-bindings/neon/pull/988)\n* Made `Context::global` read a key and added `Context::global_object` (https://github.com/neon-bindings/neon/pull/987)\n* Deprecated feature flags were removed\n\n## Bug fixes\n\n* Fix `unhandledRejection` with `JsPromise::to_future` (https://github.com/neon-bindings/neon/pull/1008)\n* Typo in `cargo-cp-artifact` help (https://github.com/neon-bindings/neon/pull/998)\n* Typo in README (https://github.com/neon-bindings/neon/pull/1012)\n\n## Other\n\nhttps://github.com/neon-bindings/neon/pull/1010\n\n* Relaxed error behavior on missing Node-API symbols. Neon will panic on first use instead of aborting the process at module load time.\n* Bumped dependency versions\n* Changed to edition 2021\n* Updated support matrix to Node 18, 20, and 21\n\n# Version 1.0.0-alpha.4\n\nPatch to enable new features flags in docs.rs.\n\n# Version 1.0.0-alpha.3\n\n## Breaking Changes\n\n* Removed `Managed` trait\n\n## Improvements\n\n* Added `JsBigInt` (https://github.com/neon-bindings/neon/pull/963).\n* Added UTF-16 functions to `JsString` (https://github.com/neon-bindings/neon/pull/944).\n* Relaxed `Send` constraints (https://github.com/neon-bindings/neon/pull/979)\n* Lifecycle support for 32-bit (https://github.com/neon-bindings/neon/pull/977)\n* Added `sys` feature (https://github.com/neon-bindings/neon/pull/970)\n\n## Bug Fixes\n\n* Fix a scope leak in release builds (https://github.com/neon-bindings/neon/pull/952).\n\n## Docs\n\n* Examples added for many types ((https://github.com/neon-bindings/neon/pull/942)).\n\n### `cargo-cp-artifact`\n\n`0.1.8` fixes sending additional arguments on Windows (https://github.com/neon-bindings/neon/pull/972).\n\n# Version 1.0.0-alpha.2\n\n## Breaking Changes\n\n### `neon::object::This`\n\nhttps://github.com/neon-bindings/neon/pull/918\n\nTrait [`neon::object::This`](https://docs.rs/neon/latest/neon/object/trait.This.html) has been removed. `This` was primarily added for use with the `declare_types!` macro to generate classes. The macro was removed and `This` is no longer needed. Additionally, the `This` argument on `JsFunction` was found to be _invalid_ because it asserted at compile time a type for `this` that could change at runtime. (Note that this was _not_ unsound because the type would be checked by Node-API and result in a `panic`.)\n\n### `JsFunction::this`\n\nhttps://github.com/neon-bindings/neon/pull/918\n\n`JsFunction::this` was changed to perform a downcast and be _fallible_. This is in line with similar APIs (e.g., `Object::get`). Additionally, an infallible version, `JsValue::this_value` was added that does _not_ perform a downcast.\n\n### Added Feature flag for external buffers\n\nhttps://github.com/neon-bindings/neon/pull/937\n\nElectron began using [pointer compression](https://www.electronjs.org/blog/v8-memory-cage) on JavaScript values that is incompatible with external buffers. As a preventative measure, `JsArrayBuffer::external` and `JsBuffer::external` have been placed behind a feature flag that warns of Electron incompatibility.\n\n## Improvements\n\n* Lifetimes were relaxed on `execute_scoped` to allow valid code to compile. (https://github.com/neon-bindings/neon/pull/919)\n* Added a `from_slice` helper on `TypedArray` (https://github.com/neon-bindings/neon/pull/925)\n* `JsTypedArray` construction and type aliases (https://github.com/neon-bindings/neon/pull/909)\n\n## Bug Fixes\n\n* Fixed a panic on VM shutdown when using `Channel` (https://github.com/neon-bindings/neon/pull/934)\n* Type tags were added to `JsBox` to prevent undefined behavior when multiple native add-ons are used (https://github.com/neon-bindings/neon/pull/907)\n\n## Docs\n\n* Significantly improved documentation of `TypedArray` (https://github.com/neon-bindings/neon/pull/909)\n* Removed unused values in `Channel` docs (https://github.com/neon-bindings/neon/pull/925)\n\n### `cargo-cp-artifact`\n\n`0.1.7` includes a fix to unlink `.node` files before copying to address common code signing errors on macOS (https://github.com/neon-bindings/neon/pull/921).\n\n# Version 1.0.0-alpha.1\n\nPre-release of a major milestone for Neon. 1.0.\n\n## Breaking Changes\n\n### Major\n\n* Removed the legacy backend; only Node-API is supported going forward (https://github.com/neon-bindings/neon/pull/881)\n* Removed `neon::result::JsResultExt` in favor of more general `neon::result::ResultExt` (https://github.com/neon-bindings/neon/pull/904)\n\n### Minor\n\n* Length APIs (`argument`, `argument_ops`, `len`) use `usize` instead of `i32` (https://github.com/neon-bindings/neon/pull/889)\n* Deprecate feature flags for accepted RFCs (https://github.com/neon-bindings/neon/pull/872)\n* `neon::meta::version` returns `semver@1` version instead of `0.9` (https://github.com/neon-bindings/neon/pull/912)\n\n## Features\n\n* Add `Object.freeze` and `Object.seal` (https://github.com/neon-bindings/neon/pull/891)\n* Futures RFC (https://github.com/neon-bindings/neon/pull/872) Implementation (https://github.com/neon-bindings/neon/pull/874)\n  - Await `JoinHandle` from sending an event on a `Channel`\n  - Adapt `JsPromise` to `JsFuture`\n* API for thread-local data (i.e., instance data) (https://github.com/neon-bindings/neon/pull/902)\n* Add Object::call_with() convenience method to call a method on an object (https://github.com/neon-bindings/neon/pull/879)\n\n## Bug Fixes\n\n* Relax the lifetime constraints on `TypedArray` borrows (https://github.com/neon-bindings/neon/pull/877)\n* Allowing missing symbols at load time to support [bun](https://bun.sh) (https://github.com/neon-bindings/neon/pull/914)\n* Prevent a panic when an async event is called after the JavaScript runtime has stopped (https://github.com/neon-bindings/neon/pull/913)\n* Fix a soundness hole in `JsArrayBuffer::external` and `JsBuffer::external` (https://github.com/neon-bindings/neon/pull/897)\n\n## Docs\n\n* Fixed mistake in `Object::get` docs (https://github.com/neon-bindings/neon/pull/903)\n* Fixed link in README to migration guide (https://github.com/neon-bindings/neon/pull/895)\n\n## Internal\n\n* Moved `cargo-cp-artirfact` into the monorepo (https://github.com/neon-bindings/neon/pull/905)\n* Decreased the size of the Neon build matrix (https://github.com/neon-bindings/neon/pull/893)\n* Removed scope abstraction from legacy backend (https://github.com/neon-bindings/neon/pull/888)\n* Improved the monorepo structure of neon (https://github.com/neon-bindings/neon/pull/884)\n\n# Version 0.10.1\n\nFix a soundness hole in `JsArrayBuffer::external`\nand `JsBuffer::external` (https://github.com/neon-bindings/neon/pull/897).\n\nThanks to [@Cassy343](https://github.com/Cassy343) for finding the [issue](https://github.com/neon-bindings/neon/issues/896)!\n\nIn previous versions of Neon, it was possible to create a `JsArrayBuffer` or `JsBuffer` that references data without the `'static` lifetime.\n\n```rust\npub fn soundness_hole(mut cx: FunctionContext) -> JsResult<JsArrayBuffer> {\n    let mut data = vec![0u8, 1, 2, 3];\n\n    // Creating an external from `&mut [u8]` instead of `Vec<u8>` since there is a blanket impl\n    // of `AsMut<T> for &mut T`\n    let buf = JsArrayBuffer::external(&mut cx, data.as_mut_slice());\n\n    // `buf` is still holding a reference to `data`!\n    drop(data);\n\n    Ok(buf)\n}\n```\n\n# Version 0.10\n\nSee the [Neon 0.10 Migration Guide](docs/MIGRATION_GUIDE_0.10.md) for more details about new features and breaking changes.\n\n## Features\n\n* New [buffer borrowing API](https://github.com/neon-bindings/neon/pull/780)\n* Added [JoinHandle](https://github.com/neon-bindings/neon/pull/787) for `Channel::send`\n* [`JsPromise` and `TaskBuilder`](https://github.com/neon-bindings/neon/pull/789)\n* Handle [panics and exceptions](https://github.com/neon-bindings/neon/pull/808) in Channels and Tasks\n* [Function call / construct builders](https://github.com/neon-bindings/neon/pull/829)\n  and [simplify low level call](https://github.com/neon-bindings/neon/pull/825)\n* Create [functions from closures](https://github.com/neon-bindings/neon/pull/811)\n\n## Minor Improvements\n\n* [Performance improvements](https://github.com/neon-bindings/neon/pull/815)\n* [Rename N-API to Node-API](https://github.com/neon-bindings/neon/pull/753) in docs to match Node changes\n* Remove unused [cslice dependency](https://github.com/neon-bindings/neon/pull/794)\n* Switch to [`syn-mid`](https://github.com/neon-bindings/neon/pull/814) for faster compile times\n* Downcast in [`Object::get`](https://github.com/neon-bindings/neon/pull/839)\n* Added [migration guide](https://github.com/neon-bindings/neon/pull/859)\n* Added [`Object::get_opt` and `Object::get_value`](https://github.com/neon-bindings/neon/pull/867)\n\n## Fixes\n\n* [Safety] Make it harder to store and forge [Throw](https://github.com/neon-bindings/neon/pull/797)\n* [Soundness] [Make `JsValue` types `!Copy`](https://github.com/neon-bindings/neon/pull/832)\n* [Soundness] [Tag `Root`](https://github.com/neon-bindings/neon/pull/847) with instance id\n* `create-neon` no longer [leaves partial project on disk](https://github.com/neon-bindings/neon/pull/840)\n* Fix legacy backend on [Electron and Windows](https://github.com/neon-bindings/neon/pull/785)\n* [FreeBSD support](https://github.com/neon-bindings/neon/pull/856) on legacy backend\n\n## Internal Improvements\n\n* Replace Electron tests [with Playwright](https://github.com/neon-bindings/neon/pull/835)\n* Re-organize Neon into an [npm workspace](https://github.com/neon-bindings/neon/pull/852)\n* [Fix crates.io badge](https://github.com/neon-bindings/neon/pull/781)\n* [Doc test fixes](https://github.com/neon-bindings/neon/pull/800)\n* Fix [broken link](https://github.com/neon-bindings/neon/pull/804) in the README\n\n# Version 0.9.1\n\n* Expose the `Finalize` trait as `neon::types::Finalize` so that docs are visible\n* Improved docs and build scripts in `create-neon` to make release builds more\n  discoverable (https://github.com/neon-bindings/neon/pull/771)\n* Update `nan` to fix an Electron 13 incompatibility (https://github.com/neon-bindings/neon/pull/778)\n\n# Version 0.9.0\n\n## Performance\n\n`Channel`, formerly `EventQueue`, are now cloneable. Clones share a backing queue to take advantage of an [optimization](https://github.com/nodejs/node/pull/38506) in Node threadsafe functions. Additionally, when specifying Node API 6 or higher (`napi-6`), calling `cx.channel()` will return a shared queue (https://github.com/neon-bindings/neon/pull/739).\n\nThe change may cause a performance regression in some pathological use cases (https://github.com/neon-bindings/neon/issues/762).\n\n## Deprecation\n\n`EventQueue` and `EventQueueError` have been renamed to `Channel` and `ChannelError` respectively to clarify their function and similarity to Rust channels. The types are available as deprecated aliases (https://github.com/neon-bindings/neon/pull/752).\n\n## Docs\n\n* Document error causes for `Channel::try_send` docs (https://github.com/neon-bindings/neon/pull/767)\n* Document `neon::object` (https://github.com/neon-bindings/neon/pull/740)\n\n## Fixes\n\n* Fix usage of a removed API in legacy buffers (https://github.com/neon-bindings/neon/pull/769)\n\n# Version 0.8.3\n\n* Fix crash caused by non-thread safety in napi_threadsafefunction on early termination (https://github.com/neon-bindings/neon/pull/744)\n* Fix memory leak in `Root` (https://github.com/neon-bindings/neon/pull/750)\n\n# Version 0.8.2\n\n* More docs improvements\n* Added a deprecation warning to `neon new` (https://github.com/neon-bindings/neon/pull/722)\n\n# Version 0.8.1\n\n* Fix `legacy-backend` for Node 16 (https://github.com/neon-bindings/neon/pull/715)\n* Various docs improvements\n\n# Version 0.8.0\n\n## Fixes\n\n* `as_slice` and `as_mut_slice` properly handle a `null` pointer from an empty buffer (https://github.com/neon-bindings/neon/pull/681)\n* Global drop queue added to avoid panics on N-API 6+ when dropping a `Root` (https://github.com/neon-bindings/neon/pull/700)\n\n## Features\n\n* Added `neon::reflect::eval` (https://github.com/neon-bindings/neon/pull/692)\n* Added `create-neon` for creating an N-API project (https://github.com/neon-bindings/neon/pull/690)\n* Added details to the `README.md` generated by `create-neon` (https://github.com/neon-bindings/neon/pull/697)\n\n## Improvements\n\n* Switched N-API tests to `cargo-cp-artifact` (https://github.com/neon-bindings/neon/pull/687)\n* Added `impl<T: Finalize> Finalize for Option<T>` (https://github.com/neon-bindings/neon/pull/680)\n* Added a N-API migration guide (https://github.com/neon-bindings/neon/pull/685)\n\n## Housekeeping\n\n* Lint fixes (https://github.com/neon-bindings/neon/pull/609)\n* Lint CI enforcement and `cargo fmt` (https://github.com/neon-bindings/neon/pull/698)\n\n# Version 0.7.1\n\n### Features\n\n* Added `JsDate` to N-API backend (https://github.com/neon-bindings/neon/pull/639)\n* Implement `JsBuffer::unitialized` for N-API backend (https://github.com/neon-bindings/neon/pull/664)\n\n### Fixes\n\n* Do not panic if a `Root` is leaked after the event loop has stopped (https://github.com/neon-bindings/neon/pull/677)\n* Stubs for features that will not be implemented in the N-API backend are removed (https://github.com/neon-bindings/neon/pull/663)\n* Fix doc URL link (https://github.com/neon-bindings/neon/pull/663)\n\n# Version 0.7.0\n\n## N-API\n\n### Version Selection\n\nNeon supports a large number of different Node versions which may have different N-API requirements. Neon now supports selecting the minimum required N-API version required by a module. For example, for N-API Version 4:\n\n```toml\nneon = { version = \"0.7\", default-features = false, features = [\"napi-4\"] }\n```\n\nIf the Neon module is loaded in an older version of Node that does not support that N-API version, a `panic` message will inform the user.\n\n### Threadsafe Functions\n\nA prerelease version of `EventQueue` for calling into the main JavaScript thread from Rust threads can be enabled with the `event-queue-api` feature flag. The API is considered unstable and may change in the future until the [RFC](https://github.com/neon-bindings/rfcs/pull/32) is merged.\n\n# Version 0.6.0\n\nThe `cx.try_catch(..)` API has been updated to return `T: Sized` instead of `T: Value` (https://github.com/neon-bindings/neon/pull/631). This API is strictly more powerful and allows users to return both JavaScript and Rust values from `try_catch` closures.\n\n## N-API\n\n* N-API symbols are now loaded dynamically (https://github.com/neon-bindings/neon/pull/646)\n* Build process for N-API is greatly simplified by leveraging dynamic loading (https://github.com/neon-bindings/neon/pull/647)\n\n# Version 0.5.3\n\n## Bug Fixes\n\nUpgrade `node-gyp` (https://github.com/neon-bindings/neon/pull/623)\n* Fix Windows Node 15\n* Fix Apple M1\n\n## Features\n\nAdded `neon::main` macro as a replacement for `register_module!` (https://github.com/neon-bindings/neon/pull/636)\n\n## Known Issues\n\nBuilds occassionally fail with Windows, Node 15 and npm 7 (https://github.com/neon-bindings/neon/issues/642)\n\n# Version 0.5.2\n\n## CLI\n\nAdded support for [additional arguments](https://github.com/neon-bindings/neon/pull/633) passed to `cargo build`. Resolves https://github.com/neon-bindings/neon/issues/471.\n\n```sh\nneon build --release -- --features awesome\n```\n\n## N-API\n\n* Improved [arguments performance](https://github.com/neon-bindings/neon/pull/610)\n* Add [redirect and `NPM_CONFIG_DISTURL`](https://github.com/neon-bindings/neon/pull/620) support\n\n# Version 0.5.1\n\n## Performance\n\n* `smallvec` is used for collecting arguments and yields a small performance gain when calling `JsFunction`\n\n## Broader Support\n\nThanks to @staltz, neon now builds for both iOS and Android with [nodejs-mobile](https://github.com/JaneaSystems/nodejs-mobile).\n\n# Version 0.5.0\n\n_Re-publish_\n\nVersions `0.4.1` and `0.4.2` included a breaking change in `neon-runtime`. At the time, this was considered acceptable because `neon-runtime` is considered an internal crate and not part of the public API. However, it was discovered, after publishing, that `neon-serde`, a commonly used crate in the `neon` ecosystem, contained a direct dependency on `neon-runtime`. In order to best support users, versions `0.4.1` and `0.4.2` were \"yanked\" and re-published as `0.5.0`.\n\nAdditionally, the team is working with the authors of `neon-serde` to remove the dependency on `neon-runtime` to prevent future issues.\n\n## Bug Fixes\n\n* Fix stack overflow in `DowncastError` `Display` impl (https://github.com/neon-bindings/neon/pull/606)\n\n# Version 0.4.2\n\n_Unpublished / Yanked_\n\n## Bug Fixes\n\n* Fix memory leak and race condition in `EventHandler`\n\n# Version 0.4.1\n\n_Unpublished / Yanked_\n\n## Features\n\n### Try Catch\n\nAdded the `cx.try_catch` API of [RFC 29](https://github.com/neon-bindings/rfcs/pull/29). This feature is behind the `try-catch-api` feature flag.\n\n## Bug Fixes\n\n* Pass `async_context` to `node::MakeCallback` (https://github.com/neon-bindings/neon/pull/498)\n* Cache bust neon if node version changes (https://github.com/neon-bindings/neon/pull/388)\n* Fix debug builds in windows (https://github.com/neon-bindings/neon/pull/400)\n* Fix cross compiling architectures (https://github.com/neon-bindings/neon/pull/491)\n* Fix neon new hanging on Windows (https://github.com/neon-bindings/neon/pull/537)\n\n## CI Improvements\n\nThe Neon Project now uses Github Actions thanks to @lhr0909! As part of this change, CI now runs on all of our supported platforms (macOS, Windows, linux) and Node versions.\n\n# Version ✨0.4✨ 🎉\n\n## `EventHandler` API\n\nThe [`EventHandler` API](https://github.com/neon-bindings/rfcs/blob/main/text/0025-event-handler.md) is a new feature for scheduling work on the javascript main thread from other threads. Big thanks to @geovie for the RFC and implementation.\n\nThis feature is currently _unstable_ and gated by a `event-handler-api` feature flag.\n\n## Improvements\n\n* New project template updated for Rust 2018\n\n## Bug Fixes\n\n* Workaround for nodejs/node-gyp#1933\n* Docs build fixed\n* Temporarily disable static tests which keep breaking CI\n\n## N-API\n\n* Context/Isolate threading\n* Scopes\n* Strings\n* Primitive values (numbers, undefined, null, boolean)\n\n# Version 0.3.3\n\nHot fix for `neon build` in projects with many dependencies.\n\n# Version 0.3.2\n\n## Bug fixes and Small Features\n\n* Disable node module registration on test build, allowing `cargo test` to be used on neon modules\n* Added support for alternate `CARGO_TARGET_DIR` locations (e.g., workspaces)\n* Added macros to `neon::prelude` to improve ergonomics in Rust 2018\n* Link `win_delay_hook` when building with `electron-build-env`, fixing Windows Electron\n* Fixed missing `__cxa_pure_virtual` on Linux\n* Copy native files into `OUT_DIR` and build there to fix `cargo publish` and follow best practices\n* Eliminated `mem::uniitialized()` usage, reducing warnings and fixing an instance of undefined behavior\n\n## Potentially Breaking\n\nThe macOS link arguments were moved from `neon-cli` to `neon-build`. This is more idiomatic, but makes `neon-build` _required_ for macOS builds where it was unnecessary before.\n\nSince `neon-build` has been included in the project template since `0.1` this change was not deemed significant enough to warrant a major revision.\n\n## N-API\n\nNeon 0.3.2 lays the groundwork for the next major revision. Development of Neon against an ABI stable Node API (N-API) will occur on main.\n\n* Added `legacy-runtime` and `n-api` feature flags for toggling neon runtime\n* Moved the legacy runtime to `nodejs-sys` crate\n* Stubbed required `n-api` implementation\n* Added `feature` flag to `neon-cli` to help configuring `n-api` projects\n\n# Version 0.3.1\n\n* Build v0.3 project templates by default in the CLI\n\n# Version 0.3\n\n## Breaking Changes\n\n* [Removed support for Node 6](https://github.com/neon-bindings/neon/pull/420)\n\n## Bug Fixes\n\n* Correctly fail the build if [custom build command fails](https://github.com/neon-bindings/neon/pull/421)\n* Fix breaking changes with v8 [`GetFunction`](https://github.com/neon-bindings/neon/pull/410)\n* Moved `nan` from `devDependencies` to `dependencies` in [`neon-runtime`](https://github.com/neon-bindings/neon/pull/367)\n* Changed neon [crate type](https://github.com/neon-bindings/neon/pull/358) from `dylib` to `cdylib`\n* Ensure that neon module loading is [not optimized away](https://github.com/neon-bindings/neon/pull/392)\n\n## Improvements\n\n* Added support for [`CARGO_BUILD_TARGET` environment variable](https://github.com/neon-bindings/neon/pull/411)\n\n# Version ✨0.2✨ 🎉\n\nSee the [Neon 0.2 Migration Guide](https://github.com/neon-bindings/neon/wiki/Neon-0.2-Migration-Guide) for documentation on migrating your projects from the Neon 0.1.x series to Neon 0.2, and please [let us know](https://github.com/neon-bindings/neon#get-involved) if you need help!\n\n* Release automation (#318)\n* New `ArrayBuffer` views API -- see [RFC 5](https://github.com/neon-bindings/rfcs/blob/main/text/0005-array-buffer-views.md) (#306)\n* VM 2.0 -- see [RFC 14](https://github.com/neon-bindings/rfcs/blob/main/text/0014-vm-2.0.md) (#306)\n* New `JsString` constructor -- see [RFC 21](https://github.com/neon-bindings/rfcs/blob/main/text/0021-string-constructor.md) (#322)\n* Eliminated `JsInteger`, `JsVariant`, `callee()` -- see [RFC 22](https://github.com/neon-bindings/rfcs/blob/main/text/0022-zero-dot-two.md) (#323)\n* Renamed `Key` to `PropertyKey` and its method names -- see [RFC 22](https://github.com/neon-bindings/rfcs/blob/main/text/0022-zero-dot-two.md) (#323)\n* Module reorganization -- see [RFC 20](https://github.com/neon-bindings/rfcs/blob/main/text/0020-module-reorg.md) (#324)\n* New `JsError` API -- see [RFC 23](https://github.com/neon-bindings/rfcs/blob/main/text/0023-error-subtyping.md) (#325)\n* Eliminated `ToJsString` API -- see [RFC 22](https://github.com/neon-bindings/rfcs/blob/main/text/0022-zero-dot-two.md) (#326)\n* Eliminated `NEON_NODE_ABI` env var -- see [RFC 22](https://github.com/neon-bindings/rfcs/blob/main/text/0022-zero-dot-two.md) (#327)\n* Default to release builds -- see [RFC 22](https://github.com/neon-bindings/rfcs/blob/main/text/0022-zero-dot-two.md) (#328)\n* Made `Buffer` construction safe by default (#329, #331)\n* Made `Throw` not implement `std::error::Error` to avoid accidental suppression, thanks to [@kjvalencik](https://github.com/kjvalencik) (#334)\n* Fixed a bug causing unnecessary rebuilds, thanks to [@kjvalencik](https://github.com/kjvalencik) (#343)\n* Fixed a soundness bug in the `Task` API, thanks to [@kjvalencik](https://github.com/kjvalencik) (#335)\n\n# Version 0.1.23\n\n* Optimization in `Scope` structures, thanks to [@maciejhirsz](https://github.com/maciejhirsz) (#282)\n* Fixed a memory leak in the `Task` API, thanks to [@kjvalencik](https://github.com/kjvalencik) (#291)\n* Add support for Node 10, thanks to [@mhsjlw](https://github.com/mhsjlw) and [@nomadtechie](https://github.com/nomadtechie) (#314)\n\n# Version 0.1.22\n\n* Reinstate `JsInteger` (although it's deprecated) for now, to be removed in 0.2. (#279)\n\n# Version 0.1.21\n\n* Fix a bug that was causing annoying unnecessary rebuilds ([#242](https://github.com/neon-bindings/neon/issues/242)).\n* New [API for getting the global object](https://api.neon-bindings.com/neon/scope/trait.scope#method.global) ([#249](https://github.com/neon-bindings/neon/issues/249)).\n\n# Version 0.1.20\n\n* Background task API ([#214](https://github.com/neon-bindings/neon/pull/214)).\n* Fixes to Windows builds ([#221](https://github.com/neon-bindings/neon/pull/221), [#227](https://github.com/neon-bindings/neon/pull/227)), thanks to [@hone](https://github.com/hone)'s tenacious troubleshooting.\n\n# Version 0.1.19\n\n* TypeScript upgrade fixes ([neon-bindings/neon-cli#62](https://github.com/neon-bindings/neon-cli/pull/62), [neon-bindings/neon-cli#65](https://github.com/neon-bindings/neon-cli/pull/65)).\n\n# Version 0.1.18\n\n* CLI bugfix ([neon-bindings/neon-cli#59](https://github.com/neon-bindings/neon-cli/pull/59)).\n* JsArrayBuffer ([#210](https://github.com/neon-bindings/neon/pull/210)).\n\n# Version 0.1.17\n\n* CLI bugfix ([neon-bindings/neon-cli#57](https://github.com/neon-bindings/neon-cli/pull/57)).\n\n# Version 0.1.16\n\n* CLI bugfix ([neon-bindings/neon-cli#56](https://github.com/neon-bindings/neon-cli/pull/56)).\n\n# Version 0.1.15 (2017-05-21)\n\n* Better Electron support in CLI's build process.\n* Better support for Electron via the artifacts file ([neon-bindings/neon-cli#52](https://github.com/neon-bindings/neon-cli/pull/52)).\n\n# Version 0.1.14 (2017-04-02)\n\n* Ensure failing tests break the build ([#191](https://github.com/neon-bindings/neon/pull/191))\n* Catch Rust panics and convert them to JS exceptions ([#192](https://github.com/neon-bindings/neon/pull/192))\n* Implement `Error` for `Throw` ([#201](https://github.com/neon-bindings/neon/pull/191))\n* Clean up the CLI and allow `neon build` to optionally take module names ([neon-bindings/neon-cli#48](https://github.com/neon-bindings/neon-cli/pull/48)).\n\n# Version 0.1.13 (2017-02-17)\n\n* More robust build scripts for neon-runtime, fixing Homebrew node installations (see [#189](https://github.com/neon-bindings/neon/pull/189))\n\n# Version 0.1.12 (2017-02-16)\n\n* [Optimized rooting protocol](https://github.com/neon-bindings/neon/commit/cef41584d9978eda2d59866a077cfe7c7d3fa46e)\n* [Eliminate rustc warnings](https://github.com/neon-bindings/neon/pull/107)\n* Lots of internal API docs\n* Windows support! :tada:\n* [Renamed `neon-sys` to `neon-runtime`](https://github.com/neon-bindings/neon/issues/169)\n* Depend on `neon-build` as a build dependency (see [neon-bindings/neon-cli#46](https://github.com/neon-bindings/neon-cli/issues/46)).\n\n# Version 0.1.11 (2016-08-08)\n\n* [Exposed `This` trait](https://github.com/neon-bindings/neon/issues/101) to allow user-level abstractions involving `FunctionCall`\n* Bump version to match Neon so they can be kept in sync from now on.\n* Generate a `build.rs` to make Windows work (see [neon-bindings/neon-cli#42](https://github.com/neon-bindings/neon-cli/pull/42) and [neon-bindings/neon-cli#44](https://github.com/neon-bindings/neon-cli/issues/44)).\n\n# Version 0.1.10 (2016-05-11)\n\n* Added `JsError` API with support for throwing [all](https://github.com/neon-bindings/neon/issues/65) [standard](https://github.com/neon-bindings/neon/issues/66) [error](https://github.com/neon-bindings/neon/issues/67) [types](https://github.com/neon-bindings/neon/issues/74)\n* [Test harness and CI integration](https://github.com/neon-bindings/neon/issues/80)!! :tada: :tada: :tada:\n* API to [call JS functions from Rust](https://github.com/neon-bindings/neon/issues/60)\n* API to [new JS functions from Rust](https://github.com/neon-bindings/neon/issues/61)\n* Added [generalized `as_slice` and `as_mut_slice` methods](https://github.com/neon-bindings/neon/issues/64) to `CSlice` API.\n* Fixed a [soundness issue](https://github.com/neon-bindings/neon/issues/64) with Locks.\n\n## Incompatible Changes\n\n* The `JsTypeError` type is gone, and replaced by the more general `JsError` type.\n* `neon::js::error::JsTypeError::throw(msg)` is now `neon::js::error::JsError::throw(neon::js::error::kind::TypeError, msg)`\n"
  },
  {
    "path": "bench/.gitignore",
    "content": "index.node\nnpm-debug.log*\ncargo.log\ncross.log\n"
  },
  {
    "path": "bench/Cargo.toml",
    "content": "[package]\nname = \"bench\"\nversion = \"0.1.0\"\ndescription = \"Neon performance regression suite\"\nauthors = [\"David Herman <david.herman@gmail.com>\"]\nlicense = \"MIT\"\nedition = \"2021\"\nexclude = [\"index.node\"]\n\n[lib]\ncrate-type = [\"cdylib\"]\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\nneon = { path = \"../crates/neon\" }\n"
  },
  {
    "path": "bench/README.md",
    "content": "# bench: Neon performance regression suite\n\n## Building bench\n\nTo run the build, run:\n\n```sh\n$ npm run build\n```\n\n## Running the benchmarks\n\nTo run the benchmarks, run:\n\n```sh\n$ npm run benchmark\n```\n"
  },
  {
    "path": "bench/index.js",
    "content": "const { Suite, jsonReport } = require(\"bench-node\");\nconst addon = require(\"./index.node\");\n\nfunction median(values) {\n  const sorted = [...values].sort((a, b) => a - b);\n  const n = sorted.length;\n  return n % 2 === 0\n    ? (sorted[n / 2 - 1] + sorted[n / 2]) / 2\n    : sorted[Math.floor(n / 2)];\n}\n\n// A custom reporter for the bencher.dev benchmarking platform.\n// Format: https://bencher.dev/docs/reference/bencher-metric-format/\n//\n// The reporter provides two measures for each benchmark:\n// - \"throughput\": The number of operations per second.\n// - \"latency\": The time taken to perform an operation, in ns.\n//   * \"value\": The median value of all samples.\n//   * \"lower_value\": The minimum value of all samples.\n//   * \"upper_value\": The maximum value of all samples.\nfunction reportBencherDev(results) {\n  const bmf = Object.create(null);\n  for (const result of results) {\n    bmf[result.name] = {\n      throughput: {\n        value: result.opsSec,\n      },\n      latency: {\n        value: median(result.histogram.sampleData),\n        lower_value: result.histogram.min,\n        upper_value: result.histogram.max,\n      },\n    };\n  }\n  console.log(JSON.stringify(bmf, null, 2));\n}\n\nconst suite = new Suite({ reporter: reportBencherDev });\n\nsuite.add(\"hello-world\", () => {\n  addon.hello();\n});\n\nsuite.add(\"manually-exported-noop\", () => {\n  addon.manualNoop();\n});\n\nsuite.add(\"auto-exported-noop\", () => {\n  addon.exportNoop();\n});\n\nfunction triple(s, n, b) {\n  return [s, n, b];\n}\n\nsuite.add(\"JsFunction::call\", () => {\n  addon.callCallbackWithCall(triple);\n});\n\nsuite.add(\"JsFunction::call_with\", () => {\n  addon.callCallbackWithCallWith(triple);\n});\n\nsuite.add(\"JsFunction::bind\", () => {\n  addon.callCallbackWithBind(triple);\n});\n\nsuite.run();\n"
  },
  {
    "path": "bench/package.json",
    "content": "{\n  \"name\": \"bench\",\n  \"private\": true,\n  \"description\": \"Neon performance regression suite\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"benchmark\": \"node --allow-natives-syntax index.js\",\n    \"cargo-build\": \"cargo build --message-format=json-render-diagnostics > cargo.log\",\n    \"postcargo-build\": \"neon dist < cargo.log\",\n    \"build\": \"npm run cargo-build -- --release\"\n  },\n  \"author\": \"David Herman <david.herman@gmail.com>\",\n  \"devDependencies\": {\n    \"@neon-rs/cli\": \"0.1.82\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/neon-bindings/neon.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/neon-bindings/neon/issues\"\n  },\n  \"homepage\": \"https://github.com/neon-bindings/neon#readme\",\n  \"dependencies\": {\n    \"bench-node\": \"^0.5.4\"\n  }\n}\n"
  },
  {
    "path": "bench/src/lib.rs",
    "content": "use neon::prelude::*;\n\n#[neon::export]\nfn export_noop() {}\n\nfn manual_noop(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    Ok(cx.undefined())\n}\n\nfn hello(mut cx: FunctionContext) -> JsResult<JsString> {\n    Ok(cx.string(\"hello node\"))\n}\n\nfn call_callback_with_call(mut cx: FunctionContext) -> JsResult<JsValue> {\n    let f = cx.argument::<JsFunction>(0)?;\n    let s = cx.string(\"hello node\");\n    let n = cx.number(17.0);\n    let b = cx.boolean(true);\n    let this = cx.null();\n    let args = vec![s.upcast(), n.upcast(), b.upcast()];\n    f.call(&mut cx, this, args)\n}\n\nfn call_callback_with_call_with(mut cx: FunctionContext) -> JsResult<JsValue> {\n    let f = cx.argument::<JsFunction>(0)?;\n    f.call_with(&cx)\n        .this(cx.null())\n        .arg(cx.string(\"hello node\"))\n        .arg(cx.number(17.0))\n        .arg(cx.boolean(true))\n        .apply(&mut cx)\n}\n\nfn call_callback_with_bind(mut cx: FunctionContext) -> JsResult<JsValue> {\n    let f = cx.argument::<JsFunction>(0)?;\n    let this = cx.null();\n    f.bind(&mut cx)\n        .this(this)?\n        .arg(\"hello node\")?\n        .arg(17.0)?\n        .arg(true)?\n        .call()\n}\n\n#[neon::main]\nfn main(mut cx: ModuleContext) -> NeonResult<()> {\n    // Export all macro-registered exports\n    neon::registered().export(&mut cx)?;\n\n    cx.export_function(\"hello\", hello)?;\n    cx.export_function(\"manualNoop\", manual_noop)?;\n    cx.export_function(\"callCallbackWithCall\", call_callback_with_call)?;\n    cx.export_function(\"callCallbackWithCallWith\", call_callback_with_call_with)?;\n    cx.export_function(\"callCallbackWithBind\", call_callback_with_bind)?;\n\n    Ok(())\n}\n"
  },
  {
    "path": "codecov.yml",
    "content": "ignore:\n  - \"bench\"\n  - \"test\"\ncoverage:\n  status:\n    project: off\n    patch: off\n"
  },
  {
    "path": "crates/neon/Cargo.toml",
    "content": "[package]\nname = \"neon\"\nversion = \"1.1.1\"\nauthors = [\"Dave Herman <david.herman@gmail.com>\"]\ndescription = \"A safe abstraction layer for Node.js.\"\nreadme = \"../../README.md\"\nhomepage = \"https://www.neon-bindings.com\"\nrepository = \"https://github.com/neon-bindings/neon\"\nlicense = \"MIT/Apache-2.0\"\nexclude = [\"neon.jpg\", \"doc/**/*\"]\nedition = \"2021\"\n\n[dev-dependencies]\nitertools = \"0.10.5\"\nsemver = \"1.0.20\"\npsd = \"0.3.4\"        # used for a doc example\nanyhow = \"1.0.75\"    # used for a doc example\nwidestring = \"1.0.2\" # used for a doc example\nlinkify = \"0.10.0\"   # used for a doc example\neasy-cast = \"0.5.2\"  # used for a doc example\n\n[target.'cfg(not(target = \"windows\"))'.dev-dependencies]\n# Avoid `clang` as a dependency on windows\nnodejs-sys = \"0.15.0\"\n\n[dependencies]\neither = \"1.13.0\"\ngetrandom = { version = \"0.2.11\", optional = true }\nlibloading = \"0.8.1\"\nlinkme = \"0.3.33\"\nsemver = \"1.0.20\"\nsmallvec = \"1.11.2\"\nonce_cell = \"1.18.0\"\nneon-macros = { version = \"=1.1.1\", path = \"../neon-macros\" }\naquamarine = { version = \"0.3.2\", optional = true }\neasy-cast = { version = \"0.5.2\", optional = true }\ndoc-comment = { version = \"0.3.3\", optional = true }\nsend_wrapper = \"0.6.0\"\nserde = { version = \"1.0.197\", optional = true }\nserde_json = { version = \"1.0.114\", optional = true }\n\n[dependencies.tokio]\nversion = \"1.34.0\"\ndefault-features = false\nfeatures = [\"sync\"]\noptional = true\n\n[features]\ndefault = [\"napi-8\"]\n\n# Enable extracting values by serializing to JSON\nserde = [\"dep:serde\", \"dep:serde_json\"]\n\n# Enable the creation of external binary buffers. This is disabled by default\n# since these APIs fail at runtime in environments that enable the V8 memory\n# cage (such as Electron: https://www.electronjs.org/blog/v8-memory-cage).\nexternal-buffers = []\n\n# Experimental Rust Futures API\n# https://github.com/neon-bindings/rfcs/pull/46\nfutures = [\"dep:tokio\"]\n\n# Enable low-level system APIs. The `sys` API allows augmenting the Neon API\n# from external crates.\nsys = []\n\n# Enable async runtime\ntokio = [\"tokio-rt-multi-thread\"] # Shorter alias\ntokio-rt = [\"futures\", \"tokio/rt\"]\ntokio-rt-multi-thread = [\"tokio-rt\", \"tokio/rt-multi-thread\"]\n\n# Default N-API version. Prefer to select a minimum required version.\n# DEPRECATED: This is an alias that should be removed\nnapi-runtime = [\"napi-8\"]\n\n# Select the N-API version\n# Feature flags to enable the experimental N-API runtime. For now, this feature\n# is disabled by default.\n# The Node N-API documentation specifies N-API and Node version requirements\n# https://nodejs.org/api/n-api.html\nnapi-1 = []\nnapi-2 = [\"napi-1\"]\nnapi-3 = [\"napi-2\"]\nnapi-4 = [\"napi-3\"]\nnapi-5 = [\"napi-4\"]\nnapi-6 = [\"napi-5\"]\nnapi-7 = [\"napi-6\"]\nnapi-8 = [\"napi-7\", \"getrandom\"]\nnapi-latest = [\"napi-8\"]\nnapi-experimental = [\"napi-8\"]\n\n# Enables the optional dependencies that are only used for generating the API docs.\ndoc-dependencies = [\"doc-comment\", \"aquamarine\", \"easy-cast\"]\n\n[package.metadata.docs.rs]\nrustdoc-args = [\"--cfg\", \"docsrs\"]\nfeatures = [\n    \"external-buffers\",\n    \"futures\",\n    \"napi-experimental\",\n    \"doc-dependencies\",\n    \"sys\",\n]\n"
  },
  {
    "path": "crates/neon/src/context/internal.rs",
    "content": "use std::{cell::RefCell, ffi::c_void, mem::MaybeUninit};\n\nuse crate::{\n    context::{Cx, ModuleContext},\n    handle::Handle,\n    result::NeonResult,\n    sys::{self, raw},\n    types::{private::ValueInternal, JsObject},\n};\n\n#[repr(C)]\n#[derive(Clone, Copy)]\npub struct Env(raw::Env);\n\nimpl From<raw::Env> for Env {\n    fn from(env: raw::Env) -> Self {\n        Self(env)\n    }\n}\n\nthread_local! {\n    #[allow(unused)]\n    pub(crate) static IS_RUNNING: RefCell<bool> = const { RefCell::new(false) };\n}\n\nimpl Env {\n    pub(crate) fn to_raw(self) -> raw::Env {\n        let Self(ptr) = self;\n        ptr\n    }\n\n    pub(super) unsafe fn try_catch<T, F>(self, f: F) -> Result<T, raw::Local>\n    where\n        F: FnOnce() -> Result<T, crate::result::Throw>,\n    {\n        let result = f();\n        let mut local: MaybeUninit<raw::Local> = MaybeUninit::zeroed();\n\n        if sys::error::catch_error(self.to_raw(), local.as_mut_ptr()) {\n            Err(local.assume_init())\n        } else if let Ok(result) = result {\n            Ok(result)\n        } else {\n            panic!(\"try_catch: unexpected Err(Throw) when VM is not in a throwing state\");\n        }\n    }\n}\n\npub trait ContextInternal<'cx>: Sized {\n    fn cx(&self) -> &Cx<'cx>;\n    fn cx_mut(&mut self) -> &mut Cx<'cx>;\n    fn env(&self) -> Env {\n        self.cx().env\n    }\n}\n\nfn default_main(mut cx: ModuleContext) -> NeonResult<()> {\n    #[cfg(all(feature = \"napi-6\", feature = \"tokio-rt-multi-thread\"))]\n    crate::executor::tokio::init(&mut cx)?;\n    crate::registered().export(&mut cx)\n}\n\nfn init(cx: ModuleContext) -> NeonResult<()> {\n    if crate::macro_internal::MAIN.len() > 1 {\n        panic!(\"The `neon::main` macro must only be used once\");\n    }\n\n    if let Some(main) = crate::macro_internal::MAIN.first() {\n        main(cx)\n    } else {\n        default_main(cx)\n    }\n}\n\n#[no_mangle]\nunsafe extern \"C\" fn napi_register_module_v1(env: *mut c_void, m: *mut c_void) -> *mut c_void {\n    let env = env.cast();\n\n    sys::setup(env);\n\n    IS_RUNNING.with(|v| {\n        *v.borrow_mut() = true;\n    });\n\n    let env = Env(env);\n    let exports = Handle::new_internal(JsObject::from_local(env, m.cast()));\n    let _ = ModuleContext::with(env, exports, init);\n\n    m\n}\n"
  },
  {
    "path": "crates/neon/src/context/mod.rs",
    "content": "//! Provides runtime access to the JavaScript engine.\n//!\n//! An _execution context_ represents the current state of a thread of execution in the\n//! JavaScript engine. Internally, it tracks things like the set of pending function calls,\n//! whether the engine is currently throwing an exception or not, and whether the engine is\n//! in the process of shutting down. The context uses this internal state to manage what\n//! operations are safely available and when.\n//!\n//! The [`Context`] trait provides an abstract interface to the JavaScript\n//! execution context. All interaction with the JavaScript engine in Neon code is mediated\n//! through instances of this trait.\n//!\n//! One particularly useful context type is [`FunctionContext`], which is passed\n//! to all Neon functions as their initial execution context.\n//!\n//! ```\n//! # use neon::prelude::*;\n//! fn hello(mut cx: FunctionContext) -> JsResult<JsString> {\n//!     Ok(cx.string(\"hello Neon\"))\n//! }\n//! ```\n//!\n//! Another important context type is [`ModuleContext`], which is provided\n//! to a Neon module's [`main`](crate::main) function to enable sharing Neon functions back\n//! with JavaScript:\n//!\n//! ```\n//! # use neon::prelude::*;\n//! # fn hello(_: FunctionContext) -> JsResult<JsValue> { todo!() }\n//! #[neon::main]\n//! fn lib(mut cx: ModuleContext) -> NeonResult<()> {\n//!     cx.export_function(\"hello\", hello)?;\n//!     Ok(())\n//! }\n//! ```\n//!\n//! ## Writing Generic Helpers\n//!\n//! Depending on the entrypoint, a user may have a [`FunctionContext`], [`ModuleContext`], or\n//! generic [`Cx`]. While it is possible to write a helper that is generic over the [`Context`]\n//! trait, it is often simpler to accept a [`Cx`] argument. Due to deref coercion, other contexts\n//! may be passed into a function that accepts a reference to [`Cx`].\n//!\n//! ```\n//! # use neon::prelude::*;\n//! fn log(cx: &mut Cx, msg: &str) -> NeonResult<()> {\n//!     cx.global::<JsObject>(\"console\")?\n//!         .method(cx, \"log\")?\n//!         .arg(msg)?\n//!         .exec()?;\n//!     Ok(())\n//! }\n//!\n//! fn print(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n//!     let msg = cx.argument::<JsString>(0)?.value(&mut cx);\n//!     log(&mut cx, &msg)?;\n//!     Ok(cx.undefined())\n//! }\n//! ```\n//!\n//! ## Memory Management\n//!\n//! Because contexts represent the engine at a point in time, they are associated with a\n//! [_lifetime_][lifetime], which limits how long Rust code is allowed to access them. This\n//! is also used to determine the lifetime of [`Handle`]s, which\n//! provide safe references to JavaScript memory managed by the engine's garbage collector.\n//!\n//! For example, we can\n//! write a simple string scanner that counts whitespace in a JavaScript string and\n//! returns a [`JsNumber`]:\n//!\n//! ```\n//! # use neon::prelude::*;\n//! fn count_whitespace(mut cx: FunctionContext) -> JsResult<JsNumber> {\n//!     let s: Handle<JsString> = cx.argument(0)?;\n//!     let contents = s.value(&mut cx);\n//!     let count = contents\n//!         .chars()                       // iterate over the characters\n//!         .filter(|c| c.is_whitespace()) // select the whitespace chars\n//!         .count();                      // count the resulting chars\n//!     Ok(cx.number(count as f64))\n//! }\n//! ```\n//!\n//! In this example, `s` is assigned a handle to a string, which ensures that the string\n//! is _kept alive_ (i.e., prevented from having its storage reclaimed by the JavaScript\n//! engine's garbage collector) for the duration of the `count_whitespace` function. This\n//! is how Neon takes advantage of Rust's type system to allow your Rust code to safely\n//! interact with JavaScript values.\n//!\n//! ### Temporary Scopes\n//!\n//! Sometimes it can be useful to limit the scope of a handle's lifetime, to allow the\n//! engine to reclaim memory sooner. This can be important when, for example, an expensive inner loop generates\n//! temporary JavaScript values that are only needed inside the loop. In these cases,\n//! the [`execute_scoped`](Context::execute_scoped) and [`compute_scoped`](Context::compute_scoped)\n//! methods allow you to create temporary contexts in order to allocate temporary\n//! handles.\n//!\n//! For example, to extract the elements of a JavaScript [iterator][iterator] from Rust,\n//! a Neon function has to work with several temporary handles on each pass through\n//! the loop:\n//!\n//! ```\n//! # use neon::prelude::*;\n//! # fn iterate(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n//!     let iterator = cx.argument::<JsObject>(0)?;         // iterator object\n//!     let next: Handle<JsFunction> =                      // iterator's `next` method\n//!         iterator.prop(&mut cx, \"next\").get()?;\n//!     let mut numbers: Vec<f64> = vec![];                 // results vector\n//!     let mut done = false;                               // loop controller\n//!\n//!     while !done {\n//!         done = cx.execute_scoped(|mut cx| {                   // temporary scope\n//!             let obj: Handle<JsObject> = next                  // temporary object\n//!                 .bind(&mut cx)\n//!                 .this(iterator)?\n//!                 .call()?;\n//!             numbers.push(obj.prop(&mut cx, \"value\").get()?);  // temporary number\n//!             obj.prop(&mut cx, \"done\").get()                   // temporary boolean\n//!         })?;\n//!     }\n//! #   Ok(cx.undefined())\n//! # }\n//! ```\n//!\n//! The temporary scope ensures that the temporary values are only kept alive\n//! during a single pass through the loop, since the temporary context is\n//! discarded (and all of its handles released) on the inside of the loop.\n//!\n//! ## Throwing Exceptions\n//!\n//! When a Neon API causes a JavaScript exception to be thrown, it returns an\n//! [`Err`] result, indicating that the thread associated\n//! with the context is now throwing. This allows Rust code to perform any\n//! cleanup before returning, but with an important restriction:\n//!\n//! > **While a JavaScript thread is throwing, its context cannot be used.**\n//!\n//! Unless otherwise documented, any Neon API that uses a context (as `self` or as\n//! a parameter) immediately panics if called while the context's thread is throwing.\n//!\n//! Typically, Neon code can manage JavaScript exceptions correctly and conveniently\n//! by using Rust's [question mark (`?`)][question-mark] operator. This ensures that\n//! Rust code \"short-circuits\" when an exception is thrown and returns back to\n//! JavaScript without calling any throwing APIs.\n//!\n//! Alternatively, to invoke a Neon API and catch any JavaScript exceptions, use the\n//! [`Context::try_catch`] method, which catches any thrown\n//! exception and restores the context to non-throwing state.\n//!\n//! ## See also\n//!\n//! 1. Ecma International. [Execution contexts](https://tc39.es/ecma262/#sec-execution-contexts), _ECMAScript Language Specification_.\n//! 2. Madhavan Nagarajan. [What is the Execution Context and Stack in JavaScript?](https://medium.com/@itIsMadhavan/what-is-the-execution-context-stack-in-javascript-e169812e851a)\n//! 3. Rupesh Mishra. [Execution context, Scope chain and JavaScript internals](https://medium.com/@happymishra66/execution-context-in-javascript-319dd72e8e2c).\n//!\n//! [lifetime]: https://doc.rust-lang.org/book/ch10-00-generics.html\n//! [iterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators\n//! [question-mark]: https://doc.rust-lang.org/edition-guide/rust-2018/error-handling-and-panics/the-question-mark-operator-for-easier-error-handling.html\n\npub(crate) mod internal;\n\nuse std::{\n    convert::Into,\n    marker::PhantomData,\n    ops::{Deref, DerefMut},\n    panic::UnwindSafe,\n};\n\npub use crate::types::buffer::lock::Lock;\n\nuse crate::{\n    event::TaskBuilder,\n    handle::Handle,\n    object::Object,\n    result::{JsResult, NeonResult, Throw},\n    sys::{\n        self, raw,\n        scope::{EscapableHandleScope, HandleScope},\n    },\n    types::{\n        boxed::{Finalize, JsBox},\n        error::JsError,\n        extract::{FromArgs, TryFromJs},\n        private::ValueInternal,\n        Deferred, JsArray, JsArrayBuffer, JsBoolean, JsBuffer, JsFunction, JsNull, JsNumber,\n        JsObject, JsPromise, JsString, JsUndefined, JsValue, StringResult, Value,\n    },\n};\n\nuse self::internal::{ContextInternal, Env};\n\n#[cfg(feature = \"napi-4\")]\nuse crate::event::Channel;\n\n#[cfg(feature = \"napi-5\")]\nuse crate::types::date::{DateError, JsDate};\n\n#[cfg(feature = \"napi-6\")]\nuse crate::lifecycle::InstanceData;\n\n#[doc(hidden)]\n/// An execution context of a task completion callback.\npub type TaskContext<'cx> = Cx<'cx>;\n\n#[doc(hidden)]\n/// An execution context of a scope created by [`Context::execute_scoped()`](Context::execute_scoped).\npub type ExecuteContext<'cx> = Cx<'cx>;\n\n#[doc(hidden)]\n/// An execution context of a scope created by [`Context::compute_scoped()`](Context::compute_scoped).\npub type ComputeContext<'cx> = Cx<'cx>;\n\n#[doc(hidden)]\n/// A view of the JS engine in the context of a finalize method on garbage collection\npub type FinalizeContext<'cx> = Cx<'cx>;\n\n/// An execution context constructed from a raw [`Env`](crate::sys::bindings::Env).\n#[cfg(feature = \"sys\")]\n#[cfg_attr(docsrs, doc(cfg(feature = \"sys\")))]\n#[doc(hidden)]\npub type SysContext<'cx> = Cx<'cx>;\n\n/// Context representing access to the JavaScript runtime\npub struct Cx<'cx> {\n    env: Env,\n    _phantom_inner: PhantomData<&'cx ()>,\n}\n\nimpl<'cx> Cx<'cx> {\n    /// Creates a context from a raw `Env`.\n    ///\n    /// # Safety\n    ///\n    /// Once a [`Cx`] has been created, it is unsafe to use\n    /// the `Env`. The handle scope for the `Env` must be valid for\n    /// the lifetime `'cx`.\n    #[cfg(feature = \"sys\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"sys\")))]\n    pub unsafe fn from_raw(env: sys::Env) -> Self {\n        Self {\n            env: env.into(),\n            _phantom_inner: PhantomData,\n        }\n    }\n\n    fn new(env: Env) -> Self {\n        Self {\n            env,\n            _phantom_inner: PhantomData,\n        }\n    }\n\n    pub(crate) fn with_context<T, F: for<'b> FnOnce(Cx<'b>) -> T>(env: Env, f: F) -> T {\n        f(Self {\n            env,\n            _phantom_inner: PhantomData,\n        })\n    }\n}\n\nimpl<'cx> ContextInternal<'cx> for Cx<'cx> {\n    fn cx(&self) -> &Cx<'cx> {\n        self\n    }\n\n    fn cx_mut(&mut self) -> &mut Cx<'cx> {\n        self\n    }\n}\n\nimpl<'cx> Context<'cx> for Cx<'cx> {}\n\nimpl<'cx> From<FunctionContext<'cx>> for Cx<'cx> {\n    fn from(cx: FunctionContext<'cx>) -> Self {\n        cx.cx\n    }\n}\n\nimpl<'cx> From<ModuleContext<'cx>> for Cx<'cx> {\n    fn from(cx: ModuleContext<'cx>) -> Self {\n        cx.cx\n    }\n}\n\n#[repr(C)]\npub(crate) struct CallbackInfo<'cx> {\n    info: raw::FunctionCallbackInfo,\n    _lifetime: PhantomData<&'cx raw::FunctionCallbackInfo>,\n}\n\nimpl CallbackInfo<'_> {\n    pub unsafe fn new(info: raw::FunctionCallbackInfo) -> Self {\n        Self {\n            info,\n            _lifetime: PhantomData,\n        }\n    }\n\n    fn kind<'b, C: Context<'b>>(&self, cx: &C) -> CallKind {\n        if unsafe { sys::call::is_construct(cx.env().to_raw(), self.info) } {\n            CallKind::Construct\n        } else {\n            CallKind::Call\n        }\n    }\n\n    pub fn len<'b, C: Context<'b>>(&self, cx: &C) -> usize {\n        unsafe { sys::call::len(cx.env().to_raw(), self.info) }\n    }\n\n    pub fn argv<'b, C: Context<'b>>(&self, cx: &mut C) -> sys::call::Arguments {\n        unsafe { sys::call::argv(cx.env().to_raw(), self.info) }\n    }\n\n    pub fn this<'b, C: Context<'b>>(&self, cx: &mut C) -> raw::Local {\n        let env = cx.env();\n        unsafe {\n            let mut local: raw::Local = std::mem::zeroed();\n            sys::call::this(env.to_raw(), self.info, &mut local);\n            local\n        }\n    }\n\n    pub(crate) fn argv_exact<'b, C: Context<'b>, const N: usize>(\n        &self,\n        cx: &mut C,\n    ) -> [Handle<'b, JsValue>; N] {\n        use std::ptr;\n\n        let mut argv = [JsValue::new_internal(ptr::null_mut()); N];\n        let mut argc = argv.len();\n\n        // # Safety\n        // * Node-API fills empty slots with `undefined`\n        // * `Handle` and `JsValue` are transparent wrappers around a raw pointer\n        unsafe {\n            sys::get_cb_info(\n                cx.env().to_raw(),\n                self.info,\n                &mut argc,\n                argv.as_mut_ptr().cast(),\n                ptr::null_mut(),\n                ptr::null_mut(),\n            )\n            .unwrap();\n        }\n\n        // Empty values will be filled with `undefined`\n        argv\n    }\n}\n\n/// Indicates whether a function was called with `new`.\n#[derive(Clone, Copy, Debug)]\npub enum CallKind {\n    Construct,\n    Call,\n}\n\n/// An _execution context_, which represents the current state of a thread of execution in the JavaScript engine.\n///\n/// All interaction with the JavaScript engine in Neon code is mediated through instances of this trait.\n///\n/// A context has a lifetime `'a`, which ensures the safety of handles managed by the JS garbage collector. All handles created during the lifetime of a context are kept alive for that duration and cannot outlive the context.\npub trait Context<'a>: ContextInternal<'a> {\n    /// Lock the JavaScript engine, returning an RAII guard that keeps the lock active as long as the guard is alive.\n    ///\n    /// If this is not the currently active context (for example, if it was used to spawn a scoped context with `execute_scoped` or `compute_scoped`), this method will panic.\n    fn lock<'b>(&'b mut self) -> Lock<'b, Self>\n    where\n        'a: 'b,\n    {\n        Lock::new(self)\n    }\n\n    /// Executes a computation in a new memory management scope.\n    ///\n    /// Handles created in the new scope are kept alive only for the duration of the computation and cannot escape.\n    ///\n    /// This method can be useful for limiting the life of temporary values created during long-running computations, to prevent leaks.\n    fn execute_scoped<'b, T, F>(&mut self, f: F) -> T\n    where\n        'a: 'b,\n        F: FnOnce(Cx<'b>) -> T,\n    {\n        let env = self.env();\n        let scope = unsafe { HandleScope::new(env.to_raw()) };\n        let result = f(Cx::new(env));\n\n        drop(scope);\n\n        result\n    }\n\n    /// Executes a computation in a new memory management scope and computes a single result value that outlives the computation.\n    ///\n    /// Handles created in the new scope are kept alive only for the duration of the computation and cannot escape, with the exception of the result value, which is rooted in the outer context.\n    ///\n    /// This method can be useful for limiting the life of temporary values created during long-running computations, to prevent leaks.\n    fn compute_scoped<'b, V, F>(&mut self, f: F) -> JsResult<'a, V>\n    where\n        'a: 'b,\n        V: Value,\n        F: FnOnce(Cx<'b>) -> JsResult<'b, V>,\n    {\n        let env = self.env();\n        let scope = unsafe { EscapableHandleScope::new(env.to_raw()) };\n        let cx = Cx::new(env);\n\n        let escapee = unsafe { scope.escape(f(cx)?.to_local()) };\n\n        Ok(Handle::new_internal(unsafe {\n            V::from_local(self.env(), escapee)\n        }))\n    }\n\n    fn try_catch<T, F>(&mut self, f: F) -> Result<T, Handle<'a, JsValue>>\n    where\n        F: FnOnce(&mut Self) -> NeonResult<T>,\n    {\n        unsafe {\n            self.env()\n                .try_catch(move || f(self))\n                .map_err(JsValue::new_internal)\n        }\n    }\n\n    /// Convenience method for creating a `JsBoolean` value.\n    fn boolean(&mut self, b: bool) -> Handle<'a, JsBoolean> {\n        JsBoolean::new(self, b)\n    }\n\n    /// Convenience method for creating a `JsNumber` value.\n    fn number<T: Into<f64>>(&mut self, x: T) -> Handle<'a, JsNumber> {\n        JsNumber::new(self, x.into())\n    }\n\n    /// Convenience method for creating a `JsString` value.\n    ///\n    /// If the string exceeds the limits of the JS engine, this method panics.\n    fn string<S: AsRef<str>>(&mut self, s: S) -> Handle<'a, JsString> {\n        JsString::new(self, s)\n    }\n\n    /// Convenience method for creating a `JsString` value.\n    ///\n    /// If the string exceeds the limits of the JS engine, this method returns an `Err` value.\n    fn try_string<S: AsRef<str>>(&mut self, s: S) -> StringResult<'a> {\n        JsString::try_new(self, s)\n    }\n\n    /// Convenience method for creating a `JsNull` value.\n    fn null(&mut self) -> Handle<'a, JsNull> {\n        JsNull::new(self)\n    }\n\n    /// Convenience method for creating a `JsUndefined` value.\n    fn undefined(&mut self) -> Handle<'a, JsUndefined> {\n        JsUndefined::new(self)\n    }\n\n    /// Convenience method for creating an empty `JsObject` value.\n    fn empty_object(&mut self) -> Handle<'a, JsObject> {\n        JsObject::new(self)\n    }\n\n    /// Convenience method for creating an empty `JsArray` value.\n    fn empty_array(&mut self) -> Handle<'a, JsArray> {\n        JsArray::new(self, 0)\n    }\n\n    /// Convenience method for creating an empty `JsArrayBuffer` value.\n    fn array_buffer(&mut self, size: usize) -> JsResult<'a, JsArrayBuffer> {\n        JsArrayBuffer::new(self, size)\n    }\n\n    /// Convenience method for creating an empty `JsBuffer` value.\n    fn buffer(&mut self, size: usize) -> JsResult<'a, JsBuffer> {\n        JsBuffer::new(self, size)\n    }\n    /// Convenience method for creating a `JsDate` value.\n    #[cfg(feature = \"napi-5\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"napi-5\")))]\n    fn date(&mut self, value: impl Into<f64>) -> Result<Handle<'a, JsDate>, DateError> {\n        JsDate::new(self, value)\n    }\n\n    /// Convenience method for looking up a global property by name.\n    ///\n    /// Equivalent to:\n    ///\n    /// ```\n    /// # use neon::prelude::*;\n    /// # fn get_array_global<'cx>(cx: &mut Cx<'cx>) -> JsResult<'cx, JsFunction> {\n    /// #     let name = \"Array\";\n    /// #     let v: Handle<JsFunction> =\n    /// {\n    ///     let global = cx.global_object();\n    ///     global.prop(cx, name).get()\n    /// }\n    /// #     ?;\n    /// #     Ok(v)\n    /// # }\n    /// ```\n    fn global<T: Value>(&mut self, name: &str) -> JsResult<'a, T> {\n        let global = self.global_object();\n        global.get(self, name)\n    }\n\n    /// Produces a handle to the JavaScript global object.\n    fn global_object(&mut self) -> Handle<'a, JsObject> {\n        JsObject::build(|out| unsafe {\n            sys::scope::get_global(self.env().to_raw(), out);\n        })\n    }\n\n    /// Throws a JS value.\n    fn throw<T: Value, U>(&mut self, v: Handle<T>) -> NeonResult<U> {\n        unsafe {\n            sys::error::throw(self.env().to_raw(), v.to_local());\n            Err(Throw::new())\n        }\n    }\n\n    /// Creates a direct instance of the [`Error`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error) class.\n    fn error<S: AsRef<str>>(&mut self, msg: S) -> JsResult<'a, JsError> {\n        JsError::error(self, msg)\n    }\n\n    /// Creates an instance of the [`TypeError`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/TypeError) class.\n    fn type_error<S: AsRef<str>>(&mut self, msg: S) -> JsResult<'a, JsError> {\n        JsError::type_error(self, msg)\n    }\n\n    /// Creates an instance of the [`RangeError`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RangeError) class.\n    fn range_error<S: AsRef<str>>(&mut self, msg: S) -> JsResult<'a, JsError> {\n        JsError::range_error(self, msg)\n    }\n\n    /// Throws a direct instance of the [`Error`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error) class.\n    fn throw_error<S: AsRef<str>, T>(&mut self, msg: S) -> NeonResult<T> {\n        let err = JsError::error(self, msg)?;\n        self.throw(err)\n    }\n\n    /// Throws an instance of the [`TypeError`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/TypeError) class.\n    fn throw_type_error<S: AsRef<str>, T>(&mut self, msg: S) -> NeonResult<T> {\n        let err = JsError::type_error(self, msg)?;\n        self.throw(err)\n    }\n\n    /// Throws an instance of the [`RangeError`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RangeError) class.\n    fn throw_range_error<S: AsRef<str>, T>(&mut self, msg: S) -> NeonResult<T> {\n        let err = JsError::range_error(self, msg)?;\n        self.throw(err)\n    }\n\n    /// Convenience method for wrapping a value in a `JsBox`.\n    ///\n    /// # Example:\n    ///\n    /// ```rust\n    /// # use neon::prelude::*;\n    /// struct Point(usize, usize);\n    ///\n    /// impl Finalize for Point {}\n    ///\n    /// fn my_neon_function(mut cx: FunctionContext) -> JsResult<JsBox<Point>> {\n    ///     let point = cx.boxed(Point(0, 1));\n    ///\n    ///     Ok(point)\n    /// }\n    /// ```\n    fn boxed<U: Finalize + 'static>(&mut self, v: U) -> Handle<'a, JsBox<U>> {\n        JsBox::new(self, v)\n    }\n\n    #[cfg(feature = \"napi-4\")]\n    #[deprecated(since = \"0.9.0\", note = \"Please use the channel() method instead\")]\n    #[doc(hidden)]\n    fn queue(&mut self) -> Channel {\n        self.channel()\n    }\n\n    #[cfg(feature = \"napi-4\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"napi-4\")))]\n    /// Returns an unbounded channel for scheduling events to be executed on the JavaScript thread.\n    ///\n    /// When using N-API >= 6,the channel returned by this method is backed by a shared queue.\n    /// To create a channel backed by a _new_ queue see [`Channel`].\n    fn channel(&mut self) -> Channel {\n        #[cfg(feature = \"napi-6\")]\n        let channel = InstanceData::channel(self);\n\n        #[cfg(not(feature = \"napi-6\"))]\n        let channel = Channel::new(self);\n\n        channel\n    }\n\n    /// Creates a [`Deferred`] and [`JsPromise`] pair. The [`Deferred`] handle can be\n    /// used to resolve or reject the [`JsPromise`].\n    ///\n    /// ```\n    /// # use neon::prelude::*;\n    /// fn resolve_promise(mut cx: FunctionContext) -> JsResult<JsPromise> {\n    ///     let (deferred, promise) = cx.promise();\n    ///     let msg = cx.string(\"Hello, World!\");\n    ///\n    ///     deferred.resolve(&mut cx, msg);\n    ///\n    ///     Ok(promise)\n    /// }\n    /// ```\n    fn promise(&mut self) -> (Deferred, Handle<'a, JsPromise>) {\n        JsPromise::new(self)\n    }\n\n    /// Creates a [`TaskBuilder`] which can be used to schedule the `execute`\n    /// callback to asynchronously execute on the\n    /// [Node worker pool](https://nodejs.org/en/docs/guides/dont-block-the-event-loop/).\n    ///\n    /// ```\n    /// # use neon::prelude::*;\n    /// fn greet(mut cx: FunctionContext) -> JsResult<JsPromise> {\n    ///     let name = cx.argument::<JsString>(0)?.value(&mut cx);\n    ///\n    ///     let promise = cx\n    ///         .task(move || format!(\"Hello, {}!\", name))\n    ///         .promise(move |mut cx, greeting| Ok(cx.string(greeting)));\n    ///\n    ///     Ok(promise)\n    /// }\n    /// ```\n    fn task<'cx, O, E>(&'cx mut self, execute: E) -> TaskBuilder<'cx, Self, E>\n    where\n        'a: 'cx,\n        O: Send + 'static,\n        E: FnOnce() -> O + Send + 'static,\n    {\n        TaskBuilder::new(self, execute)\n    }\n\n    #[cfg(feature = \"sys\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"sys\")))]\n    /// Gets the raw `sys::Env` for usage with Node-API.\n    fn to_raw(&self) -> sys::Env {\n        self.env().to_raw()\n    }\n}\n\n/// An execution context of module initialization.\npub struct ModuleContext<'cx> {\n    cx: Cx<'cx>,\n    exports: Handle<'cx, JsObject>,\n}\n\nimpl<'cx> Deref for ModuleContext<'cx> {\n    type Target = Cx<'cx>;\n\n    fn deref(&self) -> &Self::Target {\n        self.cx()\n    }\n}\n\nimpl<'cx> DerefMut for ModuleContext<'cx> {\n    fn deref_mut(&mut self) -> &mut Self::Target {\n        self.cx_mut()\n    }\n}\n\nimpl<'cx> UnwindSafe for ModuleContext<'cx> {}\n\nimpl<'cx> ModuleContext<'cx> {\n    pub(crate) fn with<T, F: for<'b> FnOnce(ModuleContext<'b>) -> T>(\n        env: Env,\n        exports: Handle<'cx, JsObject>,\n        f: F,\n    ) -> T {\n        f(ModuleContext {\n            cx: Cx::new(env),\n            exports,\n        })\n    }\n\n    #[cfg(not(feature = \"napi-5\"))]\n    /// Convenience method for exporting a Neon function from a module.\n    pub fn export_function<T: Value>(\n        &mut self,\n        key: &str,\n        f: fn(FunctionContext) -> JsResult<T>,\n    ) -> NeonResult<()> {\n        let value = JsFunction::new(self, f)?.upcast::<JsValue>();\n        self.exports.clone().set(self, key, value)?;\n        Ok(())\n    }\n\n    #[cfg(feature = \"napi-5\")]\n    /// Convenience method for exporting a Neon function from a module.\n    pub fn export_function<F, V>(&mut self, key: &str, f: F) -> NeonResult<()>\n    where\n        F: Fn(FunctionContext) -> JsResult<V> + 'static,\n        V: Value,\n    {\n        let value = JsFunction::new(self, f)?.upcast::<JsValue>();\n        // Note: Cloning `exports` is necessary to avoid holding a shared reference to\n        // `self` while attempting to use it mutably in `set`.\n        self.exports.clone().set(self, key, value)?;\n        Ok(())\n    }\n\n    /// Exports a JavaScript value from a Neon module.\n    pub fn export_value<T: Value>(&mut self, key: &str, val: Handle<T>) -> NeonResult<()> {\n        self.exports.clone().set(self, key, val)?;\n        Ok(())\n    }\n\n    /// Produces a handle to a module's exports object.\n    pub fn exports_object(&mut self) -> JsResult<'cx, JsObject> {\n        Ok(self.exports)\n    }\n}\n\nimpl<'cx> ContextInternal<'cx> for ModuleContext<'cx> {\n    fn cx(&self) -> &Cx<'cx> {\n        &self.cx\n    }\n\n    fn cx_mut(&mut self) -> &mut Cx<'cx> {\n        &mut self.cx\n    }\n}\n\nimpl<'cx> Context<'cx> for ModuleContext<'cx> {}\n\n/// An execution context of a function call.\n///\n/// The type parameter `T` is the type of the `this`-binding.\npub struct FunctionContext<'cx> {\n    cx: Cx<'cx>,\n    info: &'cx CallbackInfo<'cx>,\n\n    arguments: Option<sys::call::Arguments>,\n}\n\nimpl<'cx> Deref for FunctionContext<'cx> {\n    type Target = Cx<'cx>;\n\n    fn deref(&self) -> &Self::Target {\n        &self.cx\n    }\n}\n\nimpl<'cx> DerefMut for FunctionContext<'cx> {\n    fn deref_mut(&mut self) -> &mut Self::Target {\n        &mut self.cx\n    }\n}\n\nimpl<'cx> UnwindSafe for FunctionContext<'cx> {}\n\nimpl<'cx> FunctionContext<'cx> {\n    /// Indicates whether the function was called with `new`.\n    pub fn kind(&self) -> CallKind {\n        self.info.kind(self)\n    }\n\n    pub(crate) fn with<U, F: for<'b> FnOnce(FunctionContext<'b>) -> U>(\n        env: Env,\n        info: &'cx CallbackInfo<'cx>,\n        f: F,\n    ) -> U {\n        f(FunctionContext {\n            cx: Cx::new(env),\n            info,\n            arguments: None,\n        })\n    }\n\n    /// Indicates the number of arguments that were passed to the function.\n    pub fn len(&self) -> usize {\n        self.info.len(self)\n    }\n\n    /// Indicates if no arguments were passed to the function.\n    pub fn is_empty(&self) -> bool {\n        self.len() == 0\n    }\n\n    /// Produces the `i`th argument, or `None` if `i` is greater than or equal to `self.len()`.\n    pub fn argument_opt(&mut self, i: usize) -> Option<Handle<'cx, JsValue>> {\n        let argv = if let Some(argv) = self.arguments.as_ref() {\n            argv\n        } else {\n            let argv = self.info.argv(self);\n            self.arguments.insert(argv)\n        };\n\n        argv.get(i)\n            .map(|v| Handle::new_internal(unsafe { JsValue::from_local(self.env(), v) }))\n    }\n\n    /// Produces the `i`th argument and casts it to the type `V`, or throws an exception if `i` is greater than or equal to `self.len()` or cannot be cast to `V`.\n    pub fn argument<V: Value>(&mut self, i: usize) -> JsResult<'cx, V> {\n        match self.argument_opt(i) {\n            Some(v) => v.downcast_or_throw(self),\n            None => self.throw_type_error(\"not enough arguments\"),\n        }\n    }\n\n    /// Produces a handle to the `this`-binding and attempts to downcast as a specific type.\n    /// Equivalent to calling `cx.this_value().downcast_or_throw(&mut cx)`.\n    ///\n    /// Throws an exception if the value is a different type.\n    pub fn this<T: Value>(&mut self) -> JsResult<'cx, T> {\n        self.this_value().downcast_or_throw(self)\n    }\n\n    /// Produces a handle to the function's [`this`-binding](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#function_context).\n    pub fn this_value(&mut self) -> Handle<'cx, JsValue> {\n        JsValue::new_internal(self.info.this(self))\n    }\n\n    /// Extract Rust data from the JavaScript arguments.\n    ///\n    /// This is frequently more efficient and ergonomic than getting arguments\n    /// individually. See the [`extract`](crate::types::extract) module documentation\n    /// for more examples.\n    ///\n    /// ```\n    /// # use neon::{prelude::*, types::extract::*};\n    /// fn add(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    ///     let (a, b): (f64, f64) = cx.args()?;\n    ///\n    ///     Ok(cx.number(a + b))\n    /// }\n    /// ```\n    pub fn args<T>(&mut self) -> NeonResult<T>\n    where\n        T: FromArgs<'cx>,\n    {\n        T::from_args(self)\n    }\n\n    /// Extract a single argument from a unary function. See [`Context::args`] for more details.\n    pub fn arg<T>(&mut self) -> NeonResult<T>\n    where\n        T: TryFromJs<'cx>,\n    {\n        self.args::<(T,)>().map(|(v,)| v)\n    }\n\n    /// Extract Rust data from the JavaScript arguments.\n    ///\n    /// Similar to [`FunctionContext::args`], but does not throw a JavaScript exception on errors. Useful\n    /// for function overloading.\n    ///\n    /// ```\n    /// # use neon::{prelude::*, types::extract::*};\n    /// fn combine(mut cx: FunctionContext) -> JsResult<JsValue> {\n    ///     if let Some((a, b)) = cx.args_opt::<(f64, f64)>()? {\n    ///         return Ok(cx.number(a + b).upcast());\n    ///     }\n    ///\n    ///     let (a, b): (String, String) = cx.args()?;\n    ///\n    ///     Ok(cx.string(a + &b).upcast())\n    /// }\n    /// ```\n    pub fn args_opt<T>(&mut self) -> NeonResult<Option<T>>\n    where\n        T: FromArgs<'cx>,\n    {\n        T::from_args_opt(self)\n    }\n\n    /// Extract a single optional argument from a unary function. See [`Context::args_opt`] for more details.\n    pub fn arg_opt<T>(&mut self) -> NeonResult<Option<T>>\n    where\n        T: TryFromJs<'cx>,\n    {\n        self.args_opt::<(T,)>().map(|v| v.map(|(v,)| v))\n    }\n\n    pub(crate) fn argv<const N: usize>(&mut self) -> [Handle<'cx, JsValue>; N] {\n        self.info.argv_exact(self)\n    }\n}\n\nimpl<'cx> ContextInternal<'cx> for FunctionContext<'cx> {\n    fn cx(&self) -> &Cx<'cx> {\n        &self.cx\n    }\n\n    fn cx_mut(&mut self) -> &mut Cx<'cx> {\n        &mut self.cx\n    }\n}\n\nimpl<'cx> Context<'cx> for FunctionContext<'cx> {}\n"
  },
  {
    "path": "crates/neon/src/event/channel.rs",
    "content": "use std::{\n    error, fmt,\n    sync::{\n        atomic::{AtomicUsize, Ordering},\n        Arc,\n    },\n};\n\nuse crate::{\n    context::{internal::Env, Context, Cx},\n    result::{NeonResult, ResultExt, Throw},\n    sys::{self, tsfn::ThreadsafeFunction},\n};\n\n#[cfg(feature = \"futures\")]\nuse {\n    std::future::Future,\n    std::pin::Pin,\n    std::task::{self, Poll},\n    tokio::sync::oneshot,\n};\n\n#[cfg(not(feature = \"futures\"))]\n// Synchronous oneshot channel API compatible with `tokio::sync::oneshot`\nmod oneshot {\n    use std::sync::mpsc;\n\n    pub(super) mod error {\n        pub use super::mpsc::RecvError;\n    }\n\n    pub(super) struct Receiver<T>(mpsc::Receiver<T>);\n\n    impl<T> Receiver<T> {\n        pub(super) fn blocking_recv(self) -> Result<T, mpsc::RecvError> {\n            self.0.recv()\n        }\n    }\n\n    pub(super) fn channel<T>() -> (mpsc::SyncSender<T>, Receiver<T>) {\n        let (tx, rx) = mpsc::sync_channel(1);\n\n        (tx, Receiver(rx))\n    }\n}\n\ntype Callback = Box<dyn FnOnce(sys::Env) + Send + 'static>;\n\n/// Channel for scheduling Rust closures to execute on the JavaScript main thread.\n///\n/// Cloning a `Channel` will create a new channel that shares a backing queue for\n/// events.\n///\n/// # Example\n///\n/// The following example spawns a standard Rust thread to complete a computation\n/// and calls back to a JavaScript function asynchronously with the result.\n///\n/// ```\n/// # use neon::prelude::*;\n/// # fn fibonacci(_: f64) -> f64 { todo!() }\n/// fn async_fibonacci(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n///     // These types (`f64`, `Root<JsFunction>`, `Channel`) may all be sent\n///     // across threads.\n///     let n = cx.argument::<JsNumber>(0)?.value(&mut cx);\n///     let callback = cx.argument::<JsFunction>(1)?.root(&mut cx);\n///     let channel = cx.channel();\n///\n///     // Spawn a thread to complete the execution. This will _not_ block the\n///     // JavaScript event loop.\n///     std::thread::spawn(move || {\n///         let result = fibonacci(n);\n///\n///         // Send a closure as a task to be executed by the JavaScript event\n///         // loop. This _will_ block the event loop while executing.\n///         channel.send(move |mut cx| {\n///             let callback = callback.into_inner(&mut cx);\n///\n///             callback\n///                 .bind(&mut cx)\n///                 .args(((), result))?\n///                 .exec()?;\n///\n///             Ok(())\n///         });\n///     });\n///\n///     Ok(cx.undefined())\n/// }\n/// ```\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-4\")))]\npub struct Channel {\n    state: Arc<ChannelState>,\n    has_ref: bool,\n}\n\nimpl fmt::Debug for Channel {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        f.write_str(\"Channel\")\n    }\n}\n\nimpl Channel {\n    /// Creates an unbounded channel for scheduling closures on the JavaScript\n    /// main thread\n    pub fn new<'a, C: Context<'a>>(cx: &mut C) -> Self {\n        Self {\n            state: Arc::new(ChannelState::new(cx)),\n            has_ref: true,\n        }\n    }\n\n    /// Allow the Node event loop to exit while this `Channel` exists.\n    /// _Idempotent_\n    pub fn unref<'a, C: Context<'a>>(&mut self, cx: &mut C) -> &mut Self {\n        // Already unreferenced\n        if !self.has_ref {\n            return self;\n        }\n\n        self.has_ref = false;\n        self.state.unref(cx);\n        self\n    }\n\n    /// Prevent the Node event loop from exiting while this `Channel` exists. (Default)\n    /// _Idempotent_\n    pub fn reference<'a, C: Context<'a>>(&mut self, cx: &mut C) -> &mut Self {\n        // Already referenced\n        if self.has_ref {\n            return self;\n        }\n\n        self.has_ref = true;\n        self.state.reference(cx);\n        self\n    }\n\n    /// Schedules a closure to execute on the JavaScript thread that created this Channel\n    /// Panics if there is a libuv error\n    pub fn send<T, F>(&self, f: F) -> JoinHandle<T>\n    where\n        T: Send + 'static,\n        F: FnOnce(Cx) -> NeonResult<T> + Send + 'static,\n    {\n        self.try_send(f).unwrap()\n    }\n\n    /// Schedules a closure to execute on the JavaScript thread that created this Channel\n    /// Returns an `Error` if the task could not be scheduled.\n    ///\n    /// See [`SendError`] for additional details on failure causes.\n    pub fn try_send<T, F>(&self, f: F) -> Result<JoinHandle<T>, SendError>\n    where\n        T: Send + 'static,\n        F: FnOnce(Cx) -> NeonResult<T> + Send + 'static,\n    {\n        let (tx, rx) = oneshot::channel();\n        let callback = Box::new(move |env| {\n            let env = Env::from(env);\n\n            // Note: It is sufficient to use `Cx` because\n            // N-API creates a `HandleScope` before calling the callback.\n            Cx::with_context(env, move |cx| {\n                // Error can be ignored; it only means the user didn't join\n                let _ = tx.send(f(cx).map_err(Into::into));\n            });\n        });\n\n        self.state\n            .tsfn\n            .call(callback, None)\n            .map_err(|_| SendError)?;\n\n        Ok(JoinHandle { rx })\n    }\n\n    /// Returns a boolean indicating if this `Channel` will prevent the Node event\n    /// loop from exiting.\n    pub fn has_ref(&self) -> bool {\n        self.has_ref\n    }\n}\n\nimpl Clone for Channel {\n    /// Returns a clone of the Channel instance that shares the internal\n    /// unbounded queue with the original channel. Scheduling callbacks on the\n    /// same queue is faster than using separate channels, but might lead to\n    /// starvation if one of the threads posts significantly more callbacks on\n    /// the channel than the other one.\n    ///\n    /// Cloned and referenced Channel instances might trigger additional\n    /// event-loop tick when dropped. Channel can be wrapped into an Arc and\n    /// shared between different threads/callers to avoid this.\n    fn clone(&self) -> Self {\n        // Not referenced, we can simply clone the fields\n        if !self.has_ref {\n            return Self {\n                state: self.state.clone(),\n                has_ref: false,\n            };\n        }\n\n        let state = Arc::clone(&self.state);\n\n        // Only need to increase the ref count since the tsfn is already referenced\n        state.ref_count.fetch_add(1, Ordering::Relaxed);\n\n        Self {\n            state,\n            has_ref: true,\n        }\n    }\n}\n\nimpl Drop for Channel {\n    fn drop(&mut self) {\n        // Not a referenced event queue\n        if !self.has_ref {\n            return;\n        }\n\n        // It was only us who kept the `ChannelState` alive. No need to unref\n        // the `tsfn`, because it is going to be dropped once this function\n        // returns.\n        if Arc::strong_count(&self.state) == 1 {\n            return;\n        }\n\n        // The ChannelState is dropped on a worker thread. We have to `unref`\n        // the tsfn on the UV thread after all pending closures. Note that in\n        // the most of scenarios the optimization in N-API layer would coalesce\n        // `send()` with a user-supplied closure and the unref send here into a\n        // single UV tick.\n        //\n        // If this ever has to be optimized a second `Arc` could be used to wrap\n        // the `state` and it could be cloned in `try_send` and unref'ed on the\n        // UV thread if strong reference count goes to 0.\n        let state = Arc::clone(&self.state);\n\n        // `Channel::try_send` will only fail if the environment has shutdown.\n        // In that case, the teardown will perform clean-up.\n        let _ = self.try_send(move |mut cx| {\n            state.unref(&mut cx);\n            Ok(())\n        });\n    }\n}\n\n/// An owned permission to join on the result of a closure sent to the JavaScript main\n/// thread with [`Channel::send`].\npub struct JoinHandle<T> {\n    // `Err` is always `Throw`, but `Throw` cannot be sent across threads\n    rx: oneshot::Receiver<Result<T, SendThrow>>,\n}\n\nimpl<T> JoinHandle<T> {\n    /// Waits for the associated closure to finish executing\n    ///\n    /// If the closure panics or throws an exception, `Err` is returned\n    ///\n    /// # Panics\n    ///\n    /// This function panics if called within an asynchronous execution context.\n    pub fn join(self) -> Result<T, JoinError> {\n        Ok(self.rx.blocking_recv()??)\n    }\n}\n\n#[cfg(feature = \"futures\")]\n#[cfg_attr(docsrs, doc(cfg(feature = \"futures\")))]\nimpl<T> Future for JoinHandle<T> {\n    type Output = Result<T, JoinError>;\n\n    fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context) -> Poll<Self::Output> {\n        match Pin::new(&mut self.rx).poll(cx) {\n            Poll::Ready(result) => {\n                // Flatten `Result<Result<T, SendThrow>, RecvError>` by mapping to\n                // `Result<T, JoinError>`. This can be simplified by replacing the\n                // closure with a try-block after stabilization.\n                // https://doc.rust-lang.org/beta/unstable-book/language-features/try-blocks.html\n                let get_result = move || Ok(result??);\n\n                Poll::Ready(get_result())\n            }\n            Poll::Pending => Poll::Pending,\n        }\n    }\n}\n\n#[derive(Debug)]\n/// Error returned by [`JoinHandle::join`] indicating the associated closure panicked\n/// or threw an exception.\npub struct JoinError(JoinErrorType);\n\n#[derive(Debug)]\nenum JoinErrorType {\n    Panic,\n    Throw,\n}\n\nimpl JoinError {\n    fn as_str(&self) -> &str {\n        match &self.0 {\n            JoinErrorType::Panic => \"Closure panicked before returning\",\n            JoinErrorType::Throw => \"Closure threw an exception\",\n        }\n    }\n}\n\nimpl fmt::Display for JoinError {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        f.write_str(self.as_str())\n    }\n}\n\nimpl error::Error for JoinError {}\n\nimpl From<oneshot::error::RecvError> for JoinError {\n    fn from(_: oneshot::error::RecvError) -> Self {\n        JoinError(JoinErrorType::Panic)\n    }\n}\n\n// Marker that a `Throw` occurred that can be sent across threads for use in `JoinError`\npub(crate) struct SendThrow(());\n\nimpl From<SendThrow> for JoinError {\n    fn from(_: SendThrow) -> Self {\n        JoinError(JoinErrorType::Throw)\n    }\n}\n\nimpl From<Throw> for SendThrow {\n    fn from(_: Throw) -> SendThrow {\n        SendThrow(())\n    }\n}\n\nimpl<T> ResultExt<T> for Result<T, JoinError> {\n    fn or_throw<'a, C: Context<'a>>(self, cx: &mut C) -> NeonResult<T> {\n        self.or_else(|err| cx.throw_error(err.as_str()))\n    }\n}\n\n/// Error indicating that a closure was unable to be scheduled to execute on the event loop.\n///\n/// The most likely cause of a failure is that Node is shutting down. This may occur if the\n/// process is forcefully exiting even if the channel is referenced. For example, by calling\n/// `process.exit()`.\n//\n// NOTE: These docs will need to be updated to include `QueueFull` if bounded queues are\n// implemented.\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-4\")))]\npub struct SendError;\n\nimpl fmt::Display for SendError {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(f, \"SendError\")\n    }\n}\n\nimpl fmt::Debug for SendError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        fmt::Display::fmt(self, f)\n    }\n}\n\nimpl error::Error for SendError {}\n\nstruct ChannelState {\n    tsfn: ThreadsafeFunction<Callback>,\n    ref_count: AtomicUsize,\n}\n\nimpl ChannelState {\n    fn new<'a, C: Context<'a>>(cx: &mut C) -> Self {\n        let tsfn = unsafe { ThreadsafeFunction::new(cx.env().to_raw(), Self::callback) };\n        Self {\n            tsfn,\n            ref_count: AtomicUsize::new(1),\n        }\n    }\n\n    fn reference<'a, C: Context<'a>>(&self, cx: &mut C) {\n        // We can use relaxed ordering because `reference()` can only be called\n        // on the Event-Loop thread.\n        if self.ref_count.fetch_add(1, Ordering::Relaxed) != 0 {\n            return;\n        }\n\n        unsafe {\n            self.tsfn.reference(cx.env().to_raw());\n        }\n    }\n\n    fn unref<'a, C: Context<'a>>(&self, cx: &mut C) {\n        // We can use relaxed ordering because `unref()` can only be called\n        // on the Event-Loop thread.\n        if self.ref_count.fetch_sub(1, Ordering::Relaxed) != 1 {\n            return;\n        }\n\n        unsafe {\n            self.tsfn.unref(cx.env().to_raw());\n        }\n    }\n\n    // Monomorphized trampoline funciton for calling the user provided closure\n    fn callback(env: Option<sys::Env>, callback: Callback) {\n        if let Some(env) = env {\n            callback(env);\n        } else {\n            crate::context::internal::IS_RUNNING.with(|v| {\n                *v.borrow_mut() = false;\n            });\n        }\n    }\n}\n"
  },
  {
    "path": "crates/neon/src/event/mod.rs",
    "content": "//! Exposes the JavaScript event loop for scheduling asynchronous events.\n//!\n//! ## The Event Loop\n//!\n//! The [_event loop_][event-loop] is how Node.js provides JavaScript programs\n//! access to concurrent events such as completion of [file][fs] or\n//! [network][net] operations, notification of scheduled [timers][timer], or\n//! receiving of messages from other [processes][process].\n//!\n//! When an asynchronous operation is started from JavaScript, it registers\n//! a JavaScript callback function to wait for the operation to complete. When\n//! the operation completes, the callback and the result data are added to an\n//! internal _event queue_ in the Node.js runtime so that the event can be\n//! processed in order.\n//!\n//! The event loop processes completed events one at a time in the JavaScript\n//! execution thread by calling the registered callback function with its result\n//! value as an argument.\n//!\n//! ## Creating Custom Events\n//!\n//! This module allows Neon programs to create new types of concurrent events\n//! in Rust and expose them to JavaScript as asynchronous functions.\n//!\n//! A common use for custom events is to run expensive or long-lived\n//! computations in a background thread without blocking the JavaScript\n//! thread. For example, using the [`psd` crate][psd-crate], a Neon program could\n//! asynchronously parse (potentially large) [PSD files][psd-file] in a\n//! background thread:\n//!\n//! ```\n//! # use neon::prelude::*;\n//! # #[cfg(not(feature = \"napi-6\"))]\n//! # type Channel = ();\n//! # fn parse(filename: String, callback: Root<JsFunction>, channel: Channel) { }\n//! # #[cfg(feature = \"napi-6\")]\n//! fn parse_async(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n//!     // The types `String`, `Root<JsFunction>`, and `Channel` can all be\n//!     // sent across threads.\n//!     let filename = cx.argument::<JsString>(0)?.value(&mut cx);\n//!     let callback = cx.argument::<JsFunction>(1)?.root(&mut cx);\n//!     let channel = cx.channel();\n//!\n//!     // Spawn a background thread to complete the execution. The background\n//!     // execution will _not_ block the JavaScript event loop.\n//!     std::thread::spawn(move || {\n//!         // Do the heavy lifting inside the background thread.\n//!         parse(filename, callback, channel);\n//!     });\n//!\n//!     Ok(cx.undefined())\n//! }\n//! ```\n//!\n//! (Note that this usage of [`spawn`](std::thread::spawn) makes use of Rust's\n//! [`move`][move] syntax to transfer ownership of data to the background\n//! thread.)\n//!\n//! Upon completion of its task, the background thread can use the JavaScript\n//! callback and the channel to notify the main thread of the result:\n//!\n//! ```\n//! # use neon::prelude::*;\n//! # #[cfg(not(feature = \"napi-6\"))]\n//! # type Channel = ();\n//! # use psd::Psd;\n//! # use anyhow::{Context as _, Result};\n//! #\n//! fn psd_from_filename(filename: String) -> Result<Psd> {\n//!     Psd::from_bytes(&std::fs::read(&filename)?).context(\"invalid psd file\")\n//! }\n//!\n//! # #[cfg(feature = \"napi-6\")]\n//! fn parse(filename: String, callback: Root<JsFunction>, channel: Channel) {\n//!     let result = psd_from_filename(filename);\n//!\n//!     // Send a closure as a task to be executed by the JavaScript event\n//!     // loop. This _will_ block the event loop while executing.\n//!     channel.send(move |mut cx| {\n//!         let callback = callback.into_inner(&mut cx);\n//!\n//!         match result {\n//!             Ok(psd) => {\n//!                 // Extract data from the parsed file.\n//!                 let obj = cx.empty_object()\n//!                     .prop(&mut cx, \"width\").set(psd.width())?\n//!                     .prop(\"height\").set(psd.height())?\n//!                     .this();\n//!\n//!                 callback\n//!                     .bind(&mut cx)\n//!                     .args(((), obj))?\n//!                     .exec()?;\n//!             }\n//!             Err(err) => {\n//!                 use neon::types::extract::Error;\n//!                 callback\n//!                     .bind(&mut cx)\n//!                     .arg(Error::from(err))?\n//!                     .exec()?;\n//!             }\n//!         }\n//!\n//!         Ok(())\n//!     });\n//! }\n//! ```\n//!\n//! ## See also\n//!\n//! 1. Panu Pitkamaki. [Event loop from 10,000ft][event-loop].\n//!\n//! [event-loop]: https://bytearcher.com/articles/event-loop-10-000ft/\n//! [fs]: https://nodejs.org/dist/latest/docs/api/fs.html\n//! [net]: https://nodejs.org/dist/latest/docs/api/net.html\n//! [process]: https://nodejs.org/dist/latest/docs/api/process.html\n//! [timer]: https://nodejs.org/dist/latest/docs/api/timers.html\n//! [move]: https://doc.rust-lang.org/std/keyword.move.html\n//! [psd-crate]: https://crates.io/crates/psd\n//! [psd-file]: https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/\n\n#[cfg(feature = \"napi-4\")]\nmod channel;\n\nmod task;\n\npub use self::task::TaskBuilder;\n\n#[cfg(all(feature = \"napi-5\", feature = \"futures\"))]\npub(crate) use self::channel::SendThrow;\n#[cfg(feature = \"napi-4\")]\npub use self::channel::{Channel, JoinError, JoinHandle, SendError};\n\n#[cfg(feature = \"napi-4\")]\n#[deprecated(since = \"0.9.0\", note = \"Please use the Channel type instead\")]\n#[doc(hidden)]\npub type EventQueue = self::channel::Channel;\n\n#[cfg(feature = \"napi-4\")]\n#[deprecated(since = \"0.9.0\", note = \"Please use the SendError type instead\")]\n#[doc(hidden)]\npub type EventQueueError = self::channel::SendError;\n"
  },
  {
    "path": "crates/neon/src/event/task.rs",
    "content": "use std::{panic::resume_unwind, thread};\n\nuse crate::{\n    context::{internal::Env, Context, Cx},\n    handle::Handle,\n    result::{JsResult, NeonResult},\n    sys::{async_work, raw},\n    types::{Deferred, JsPromise, Value},\n};\n\n/// Node asynchronous task builder\n///\n/// ```\n/// # use neon::prelude::*;\n/// fn greet(mut cx: FunctionContext) -> JsResult<JsPromise> {\n///     let name = cx.argument::<JsString>(0)?.value(&mut cx);\n///\n///     let promise = cx\n///         .task(move || format!(\"Hello, {}!\", name))\n///         .promise(move |mut cx, greeting| Ok(cx.string(greeting)));\n///\n///     Ok(promise)\n/// }\n/// ```\npub struct TaskBuilder<'cx, C, E> {\n    cx: &'cx mut C,\n    execute: E,\n}\n\nimpl<'a: 'cx, 'cx, C, O, E> TaskBuilder<'cx, C, E>\nwhere\n    C: Context<'a>,\n    O: Send + 'static,\n    E: FnOnce() -> O + Send + 'static,\n{\n    /// Construct a new task builder from an `execute` callback that can be\n    /// scheduled to execute on the Node worker pool\n    pub fn new(cx: &'cx mut C, execute: E) -> Self {\n        Self { cx, execute }\n    }\n\n    /// Schedules a task to execute on the Node worker pool, executing the\n    /// `complete` callback on the JavaScript main thread with the result\n    /// of the `execute` callback\n    pub fn and_then<F>(self, complete: F)\n    where\n        F: FnOnce(Cx, O) -> NeonResult<()> + 'static,\n    {\n        let env = self.cx.env();\n        let execute = self.execute;\n\n        schedule(env, execute, complete);\n    }\n\n    /// Schedules a task to execute on the Node worker pool and returns a\n    /// promise that is resolved with the value from the `complete` callback.\n    ///\n    /// The `complete` callback will execute on the JavaScript main thread and\n    /// is passed the return value from `execute`. If the `complete` callback\n    /// throws, the promise will be rejected with the exception\n    pub fn promise<V, F>(self, complete: F) -> Handle<'a, JsPromise>\n    where\n        V: Value,\n        F: FnOnce(Cx, O) -> JsResult<V> + 'static,\n    {\n        let env = self.cx.env();\n        let (deferred, promise) = JsPromise::new(self.cx);\n        let execute = self.execute;\n\n        schedule_promise(env, execute, complete, deferred);\n\n        promise\n    }\n}\n\n// Schedule a task to execute on the Node worker pool\nfn schedule<I, O, D>(env: Env, input: I, data: D)\nwhere\n    I: FnOnce() -> O + Send + 'static,\n    O: Send + 'static,\n    D: FnOnce(Cx, O) -> NeonResult<()> + 'static,\n{\n    unsafe {\n        async_work::schedule(env.to_raw(), input, execute::<I, O>, complete::<O, D>, data);\n    }\n}\n\nfn execute<I, O>(input: I) -> O\nwhere\n    I: FnOnce() -> O + Send + 'static,\n    O: Send + 'static,\n{\n    input()\n}\n\nfn complete<O, D>(env: raw::Env, output: thread::Result<O>, callback: D)\nwhere\n    O: Send + 'static,\n    D: FnOnce(Cx, O) -> NeonResult<()> + 'static,\n{\n    let output = output.unwrap_or_else(|panic| {\n        // If a panic was caught while executing the task on the Node Worker\n        // pool, resume panicking on the main JavaScript thread\n        resume_unwind(panic)\n    });\n\n    Cx::with_context(env.into(), move |cx| {\n        let _ = callback(cx, output);\n    });\n}\n\n// Schedule a task to execute on the Node worker pool and settle a `Promise` with the result\nfn schedule_promise<I, O, D, V>(env: Env, input: I, complete: D, deferred: Deferred)\nwhere\n    I: FnOnce() -> O + Send + 'static,\n    O: Send + 'static,\n    D: FnOnce(Cx, O) -> JsResult<V> + 'static,\n    V: Value,\n{\n    unsafe {\n        async_work::schedule(\n            env.to_raw(),\n            input,\n            execute::<I, O>,\n            complete_promise::<O, D, V>,\n            (complete, deferred),\n        );\n    }\n}\n\nfn complete_promise<O, D, V>(\n    env: raw::Env,\n    output: thread::Result<O>,\n    (complete, deferred): (D, Deferred),\n) where\n    O: Send + 'static,\n    D: FnOnce(Cx, O) -> JsResult<V> + 'static,\n    V: Value,\n{\n    let env = env.into();\n\n    Cx::with_context(env, move |cx| {\n        deferred.try_catch_settle(cx, move |cx| {\n            let output = output.unwrap_or_else(|panic| resume_unwind(panic));\n\n            complete(cx, output)\n        })\n    });\n}\n"
  },
  {
    "path": "crates/neon/src/executor/mod.rs",
    "content": "use std::{future::Future, pin::Pin};\n\nuse crate::{context::Cx, thread::LocalKey};\n\n#[cfg(feature = \"tokio-rt\")]\npub(crate) mod tokio;\n\ntype BoxFuture = Pin<Box<dyn Future<Output = ()> + Send + 'static>>;\n\npub(crate) static RUNTIME: LocalKey<Box<dyn Runtime>> = LocalKey::new();\n\npub trait Runtime: Send + Sync + 'static {\n    fn spawn(&self, fut: BoxFuture);\n}\n\n/// Register a [`Future`] executor runtime globally to the addon.\n///\n/// Returns `Ok(())` if a global executor has not been set and `Err(runtime)` if it has.\n///\n/// If the `tokio` feature flag is enabled and the addon does not provide a\n/// [`#[neon::main]`](crate::main) function, a multithreaded tokio runtime will be\n/// automatically registered.\n///\n/// **Note**: Each instance of the addon will have its own runtime. It is recommended\n/// to initialize the async runtime once in a process global and share it across instances.\n///\n/// ```\n/// # fn main() {\n/// # #[cfg(feature = \"tokio-rt-multi-thread\")]\n/// # fn example() {\n/// # use neon::prelude::*;\n/// use once_cell::sync::OnceCell;\n/// use tokio::runtime::Runtime;\n///\n/// static RUNTIME: OnceCell<Runtime> = OnceCell::new();\n///\n/// #[neon::main]\n/// fn main(mut cx: ModuleContext) -> NeonResult<()> {\n///     let runtime = RUNTIME\n///         .get_or_try_init(Runtime::new)\n///         .or_else(|err| cx.throw_error(err.to_string()))?;\n///\n///     let _ = neon::set_global_executor(&mut cx, runtime);\n///\n///     Ok(())\n/// }\n/// # }\n/// # }\n/// ```\npub fn set_global_executor<R>(cx: &mut Cx, runtime: R) -> Result<(), R>\nwhere\n    R: Runtime,\n{\n    if RUNTIME.get(cx).is_some() {\n        return Err(runtime);\n    }\n\n    RUNTIME.get_or_init(cx, || Box::new(runtime));\n\n    Ok(())\n}\n"
  },
  {
    "path": "crates/neon/src/executor/tokio.rs",
    "content": "use std::sync::Arc;\n\nuse super::{BoxFuture, Runtime};\n\nimpl Runtime for tokio::runtime::Runtime {\n    fn spawn(&self, fut: BoxFuture) {\n        spawn(self.handle(), fut);\n    }\n}\n\nimpl Runtime for Arc<tokio::runtime::Runtime> {\n    fn spawn(&self, fut: BoxFuture) {\n        spawn(self.handle(), fut);\n    }\n}\n\nimpl Runtime for &'static tokio::runtime::Runtime {\n    fn spawn(&self, fut: BoxFuture) {\n        spawn(self.handle(), fut);\n    }\n}\n\nimpl Runtime for tokio::runtime::Handle {\n    fn spawn(&self, fut: BoxFuture) {\n        spawn(self, fut);\n    }\n}\n\nimpl Runtime for &'static tokio::runtime::Handle {\n    fn spawn(&self, fut: BoxFuture) {\n        spawn(self, fut);\n    }\n}\n\nfn spawn(handle: &tokio::runtime::Handle, fut: BoxFuture) {\n    #[allow(clippy::let_underscore_future)]\n    let _ = handle.spawn(fut);\n}\n\n#[cfg(feature = \"tokio-rt-multi-thread\")]\npub(crate) fn init(cx: &mut crate::context::ModuleContext) -> crate::result::NeonResult<()> {\n    use once_cell::sync::OnceCell;\n    use tokio::runtime::{Builder, Runtime};\n\n    use crate::context::Context;\n\n    static RUNTIME: OnceCell<Runtime> = OnceCell::new();\n\n    super::RUNTIME.get_or_try_init(cx, |cx| {\n        let runtime = RUNTIME\n            .get_or_try_init(|| {\n                #[cfg(feature = \"tokio-rt-multi-thread\")]\n                let mut builder = Builder::new_multi_thread();\n\n                #[cfg(not(feature = \"tokio-rt-multi-thread\"))]\n                let mut builder = Builder::new_current_thread();\n\n                builder.enable_all().build()\n            })\n            .or_else(|err| cx.throw_error(err.to_string()))?;\n\n        Ok(Box::new(runtime))\n    })?;\n\n    Ok(())\n}\n"
  },
  {
    "path": "crates/neon/src/handle/internal.rs",
    "content": "use std::{fmt::Debug, mem};\n\nuse crate::types::Value;\n\npub trait SuperType<T: Value> {\n    fn upcast_internal(v: &T) -> Self;\n}\n\n#[doc(hidden)]\n/// Trait asserting that `Self` is a transparent wrapper around `Self::Inner`\n/// with identical representation and may be safely transmuted.\n///\n/// # Safety\n/// `Self` must be `#[repr(transparent)]` with a field `Self::Inner`\npub unsafe trait TransparentNoCopyWrapper: Sized {\n    type Inner: Debug + Copy;\n\n    // A default implementation cannot be provided because it would create\n    // dependently sized types. This may be supported in a future Rust version.\n    fn into_inner(self) -> Self::Inner;\n\n    fn wrap_ref(s: &Self::Inner) -> &Self {\n        unsafe { mem::transmute(s) }\n    }\n\n    fn wrap_mut(s: &mut Self::Inner) -> &mut Self {\n        unsafe { mem::transmute(s) }\n    }\n}\n"
  },
  {
    "path": "crates/neon/src/handle/mod.rs",
    "content": "//! References to garbage-collected JavaScript values.\n//!\n//! A _handle_ is a safe reference to a JavaScript value that is owned and managed\n//! by the JavaScript engine's memory management system (the garbage collector).\n//!\n//! Neon APIs that accept and return JavaScript values never use raw pointer types\n//! ([`*T`](pointer)) or reference types ([`&T`](reference)). Instead they use the\n//! special Neon type [`Handle`], which encapsulates a JavaScript\n//! [`Value`] and ensures that Rust only maintains access to\n//! the value while it is guaranteed to be valid.\n//!\n//! ## Working with Handles\n//!\n//! The `Handle<T>` type automatically dereferences to `T` (via the standard\n//! [`Deref`] trait), so you can call `T`'s methods on a value of\n//! type `Handle<T>`. For example, we can call\n//! [`JsNumber::value()`](crate::types::JsNumber::value) on a `Handle<JsNumber>`:\n//!\n//! ```\n//! # use neon::prelude::*;\n//! # fn run(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n//! let n: Handle<JsNumber> = cx.argument(0)?;\n//! let v = n.value(&mut cx); // JsNumber::value()\n//! # Ok(cx.undefined())\n//! # }\n//! ```\n//!\n//! ## Example\n//!\n//! This Neon function takes an object as its argument, extracts an object property,\n//! `homeAddress`, and then extracts a string property, `zipCode` from that second\n//! object. Each JavaScript value in the calculation is stored locally in a `Handle`.\n//!\n//! ```\n//! # use neon::prelude::*;\n//! # use neon::export;\n//! #[export]\n//! fn customer_zip_code<'cx>(cx: &mut FunctionContext<'cx>, customer: Handle<'cx, JsObject>) -> JsResult<'cx, JsString> {\n//!     let home_address: Handle<JsObject> = customer.prop(cx, \"homeAddress\").get()?;\n//!     let zip_code: Handle<JsString> = home_address.prop(cx, \"zipCode\").get()?;\n//!     Ok(zip_code)\n//! }\n//! ```\n\npub(crate) mod internal;\n\npub(crate) mod root;\n\nuse std::{\n    error::Error,\n    fmt::{self, Debug, Display},\n    marker::PhantomData,\n    mem,\n    ops::{Deref, DerefMut},\n};\n\npub use self::root::Root;\n\nuse crate::{\n    context::Context,\n    handle::internal::{SuperType, TransparentNoCopyWrapper},\n    result::{JsResult, ResultExt},\n    sys,\n    types::Value,\n};\n\n/// A handle to a JavaScript value that is owned by the JavaScript engine.\n#[derive(Debug)]\n#[repr(transparent)]\npub struct Handle<'a, V: Value + 'a> {\n    // Contains the actual `Copy` JavaScript value data. It will be wrapped in\n    // in a `!Copy` type when dereferencing. Only `V` should be visible to the user.\n    value: <V as TransparentNoCopyWrapper>::Inner,\n    phantom: PhantomData<&'a V>,\n}\n\nimpl<'a, V: Value> Clone for Handle<'a, V> {\n    fn clone(&self) -> Self {\n        *self\n    }\n}\n\nimpl<'a, V: Value> Copy for Handle<'a, V> {}\n\nimpl<'a, V: Value + 'a> Handle<'a, V> {\n    pub(crate) fn new_internal(value: V) -> Handle<'a, V> {\n        Handle {\n            value: value.into_inner(),\n            phantom: PhantomData,\n        }\n    }\n}\n\n/// An error representing a failed downcast.\n#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]\npub struct DowncastError<F: Value, T: Value> {\n    phantom_from: PhantomData<F>,\n    phantom_to: PhantomData<T>,\n}\n\nimpl<F: Value, T: Value> Debug for DowncastError<F, T> {\n    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {\n        write!(f, \"DowncastError\")\n    }\n}\n\nimpl<F: Value, T: Value> DowncastError<F, T> {\n    fn new() -> Self {\n        DowncastError {\n            phantom_from: PhantomData,\n            phantom_to: PhantomData,\n        }\n    }\n}\n\nimpl<F: Value, T: Value> Display for DowncastError<F, T> {\n    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {\n        write!(f, \"failed to downcast {} to {}\", F::name(), T::name())\n    }\n}\n\nimpl<F: Value, T: Value> Error for DowncastError<F, T> {}\n\n/// The result of a call to [`Handle::downcast()`](Handle::downcast).\npub type DowncastResult<'a, F, T> = Result<Handle<'a, T>, DowncastError<F, T>>;\n\nimpl<'a, F: Value, T: Value> ResultExt<Handle<'a, T>> for DowncastResult<'a, F, T> {\n    fn or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> JsResult<'a, T> {\n        match self {\n            Ok(v) => Ok(v),\n            Err(e) => cx.throw_type_error(e.to_string()),\n        }\n    }\n}\n\nimpl<'a, T: Value> Handle<'a, T> {\n    /// Safely upcast a handle to a supertype.\n    ///\n    /// This method does not require an execution context because it only copies a handle.\n    pub fn upcast<U: Value + SuperType<T>>(&self) -> Handle<'a, U> {\n        Handle::new_internal(SuperType::upcast_internal(self.deref()))\n    }\n\n    /// Tests whether this value is an instance of the given type.\n    ///\n    /// # Example:\n    ///\n    /// ```no_run\n    /// # use neon::prelude::*;\n    /// # fn my_neon_function(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    /// let v: Handle<JsValue> = cx.number(17).upcast();\n    /// v.is_a::<JsString, _>(&mut cx); // false\n    /// v.is_a::<JsNumber, _>(&mut cx); // true\n    /// v.is_a::<JsValue, _>(&mut cx);  // true\n    /// # Ok(cx.undefined())\n    /// # }\n    /// ```\n    pub fn is_a<'b, U: Value, C: Context<'b>>(&self, cx: &mut C) -> bool {\n        U::is_typeof(cx.cx_mut(), self.deref())\n    }\n\n    /// Attempts to downcast a handle to another type, which may fail. A failure\n    /// to downcast **does not** throw a JavaScript exception, so it's OK to\n    /// continue interacting with the JS engine if this method produces an `Err`\n    /// result.\n    pub fn downcast<'b, U: Value, C: Context<'b>>(&self, cx: &mut C) -> DowncastResult<'a, T, U> {\n        match U::downcast(cx.cx_mut(), self.deref()) {\n            Some(v) => Ok(Handle::new_internal(v)),\n            None => Err(DowncastError::new()),\n        }\n    }\n\n    /// Attempts to downcast a handle to another type, raising a JavaScript `TypeError`\n    /// exception on failure. This method is a convenient shorthand, equivalent to\n    /// `self.downcast::<U>().or_throw::<C>(cx)`.\n    pub fn downcast_or_throw<'b, U: Value, C: Context<'b>>(&self, cx: &mut C) -> JsResult<'a, U> {\n        self.downcast(cx).or_throw(cx)\n    }\n\n    pub fn strict_equals<'b, U: Value, C: Context<'b>>(\n        &self,\n        cx: &mut C,\n        other: Handle<'b, U>,\n    ) -> bool {\n        unsafe { sys::mem::strict_equals(cx.env().to_raw(), self.to_local(), other.to_local()) }\n    }\n}\n\nimpl<'a, V: Value> Deref for Handle<'a, V> {\n    type Target = V;\n    fn deref(&self) -> &V {\n        unsafe { mem::transmute(&self.value) }\n    }\n}\n\nimpl<'a, V: Value> DerefMut for Handle<'a, V> {\n    fn deref_mut(&mut self) -> &mut V {\n        unsafe { mem::transmute(&mut self.value) }\n    }\n}\n"
  },
  {
    "path": "crates/neon/src/handle/root.rs",
    "content": "use std::{ffi::c_void, marker::PhantomData};\n\nuse crate::{\n    context::Context,\n    handle::Handle,\n    object::Object,\n    sys::{raw, reference},\n    types::boxed::Finalize,\n};\n\n#[cfg(feature = \"napi-6\")]\nuse {\n    crate::{\n        lifecycle::{DropData, InstanceData, InstanceId},\n        sys::tsfn::ThreadsafeFunction,\n    },\n    std::sync::Arc,\n};\n\n#[cfg(not(feature = \"napi-6\"))]\nuse std::thread::{self, ThreadId};\n\n#[cfg(not(feature = \"napi-6\"))]\ntype InstanceId = ThreadId;\n\n#[repr(transparent)]\n#[derive(Clone)]\npub(crate) struct NapiRef(*mut c_void);\n\nimpl NapiRef {\n    /// # Safety\n    /// Must only be used from the same module context that created the reference\n    pub(crate) unsafe fn unref(self, env: raw::Env) {\n        reference::unreference(env, self.0.cast());\n    }\n}\n\n// # Safety\n// `NapiRef` are reference counted types that allow references to JavaScript objects\n// to outlive a `Context` (`napi_env`). Since access is serialized by obtaining a\n// `Context`, they are both `Send` and `Sync`.\n// https://nodejs.org/api/n-api.html#n_api_references_to_objects_with_a_lifespan_longer_than_that_of_the_native_method\nunsafe impl Send for NapiRef {}\n\nunsafe impl Sync for NapiRef {}\n\n/// A thread-safe handle that holds a reference to a JavaScript object and\n/// prevents it from being garbage collected.\n///\n/// A `Root<T>` may be sent across threads, but the referenced object may\n/// only be accessed on the JavaScript thread that created it.\npub struct Root<T> {\n    // `Option` is used to skip `Drop` when `Root::drop` or `Root::into_inner` is used.\n    // It will *always* be `Some` when a user is interacting with `Root`.\n    internal: Option<NapiRef>,\n    instance_id: InstanceId,\n    #[cfg(feature = \"napi-6\")]\n    drop_queue: Arc<ThreadsafeFunction<DropData>>,\n    _phantom: PhantomData<T>,\n}\n\nimpl<T> std::fmt::Debug for Root<T> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"Root<{}>\", std::any::type_name::<T>())\n    }\n}\n\n// `Root` are intended to be `Send` and `Sync`\n// Safety: `Root` contains two types. A `NapiRef` which is `Send` and `Sync` and a\n// `PhantomData` that does not impact the safety.\nunsafe impl<T> Send for Root<T> {}\n\nunsafe impl<T> Sync for Root<T> {}\n\n#[cfg(feature = \"napi-6\")]\nfn instance_id<'a, C: Context<'a>>(cx: &mut C) -> InstanceId {\n    InstanceData::id(cx)\n}\n\n#[cfg(not(feature = \"napi-6\"))]\nfn instance_id<'a, C: Context<'a>>(_: &mut C) -> InstanceId {\n    thread::current().id()\n}\n\nimpl<T: Object> Root<T> {\n    /// Create a reference to a JavaScript object. The object will not be\n    /// garbage collected until the `Root` is dropped. A `Root<T>` may only\n    /// be dropped on the JavaScript thread that created it.\n    ///\n    /// The caller _should_ ensure `Root::into_inner` or `Root::drop` is called\n    /// to properly dispose of the `Root<T>`. If the value is dropped without\n    /// calling one of these methods:\n    /// * N-API < 6, Neon will `panic` to notify of the leak\n    /// * N-API >= 6, Neon will drop from a global queue at a runtime cost\n    pub fn new<'a, C: Context<'a>>(cx: &mut C, value: &T) -> Self {\n        let env = cx.env().to_raw();\n        let internal = unsafe { reference::new(env, value.to_local()) };\n\n        Self {\n            internal: Some(NapiRef(internal as *mut _)),\n            instance_id: instance_id(cx),\n            #[cfg(feature = \"napi-6\")]\n            drop_queue: InstanceData::drop_queue(cx),\n            _phantom: PhantomData,\n        }\n    }\n\n    /// Clone a reference to the contained JavaScript object. This method can\n    /// be considered identical to the following:\n    /// ```\n    /// # use neon::prelude::*;\n    /// # fn my_neon_function(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    /// # let root = cx.argument::<JsObject>(0)?.root(&mut cx);\n    /// let inner = root.into_inner(&mut cx);\n    /// let cloned = inner.root(&mut cx);\n    /// let root = inner.root(&mut cx);\n    /// # Ok(cx.undefined())\n    /// # }\n    /// ```\n    pub fn clone<'a, C: Context<'a>>(&self, cx: &mut C) -> Self {\n        let env = cx.env();\n        let internal = self.as_napi_ref(cx).0 as *mut _;\n\n        unsafe {\n            reference::reference(env.to_raw(), internal);\n        };\n\n        Self {\n            internal: self.internal.clone(),\n            instance_id: instance_id(cx),\n            #[cfg(feature = \"napi-6\")]\n            drop_queue: Arc::clone(&self.drop_queue),\n            _phantom: PhantomData,\n        }\n    }\n\n    /// Safely drop a `Root<T>` without returning the referenced JavaScript\n    /// object.\n    pub fn drop<'a, C: Context<'a>>(self, cx: &mut C) {\n        let env = cx.env().to_raw();\n\n        unsafe {\n            self.into_napi_ref(cx).unref(env);\n        }\n    }\n\n    /// Return the referenced JavaScript object and allow it to be garbage collected.\n    ///\n    /// # Panics\n    ///\n    /// This method panics if it is called from a different JavaScript thread than the\n    /// one in which the handle was created.\n    pub fn into_inner<'a, C: Context<'a>>(self, cx: &mut C) -> Handle<'a, T> {\n        let env = cx.env();\n        let internal = self.into_napi_ref(cx);\n        let local = unsafe { reference::get(env.to_raw(), internal.0.cast()) };\n\n        unsafe {\n            internal.unref(env.to_raw());\n        }\n\n        Handle::new_internal(unsafe { T::from_local(env, local) })\n    }\n\n    /// Access the inner JavaScript object without consuming the `Root`\n    /// This method aliases the reference without changing the reference count. It\n    /// can be used in place of a clone immediately followed by a call to `into_inner`.\n    ///\n    /// # Panics\n    ///\n    /// This method panics if it is called from a different JavaScript thread than the\n    /// one in which the handle was created.\n    pub fn to_inner<'a, C: Context<'a>>(&self, cx: &mut C) -> Handle<'a, T> {\n        let env = cx.env();\n        let local = unsafe { reference::get(env.to_raw(), self.as_napi_ref(cx).0 as *mut _) };\n\n        Handle::new_internal(unsafe { T::from_local(env, local) })\n    }\n\n    fn as_napi_ref<'a, C: Context<'a>>(&self, cx: &mut C) -> &NapiRef {\n        if self.instance_id != instance_id(cx) {\n            panic!(\"Attempted to dereference a `neon::handle::Root` from the wrong module \");\n        }\n\n        self.internal\n            .as_ref()\n            // `unwrap` will not `panic` because `internal` will always be `Some`\n            // until the `Root` is consumed.\n            .unwrap()\n    }\n\n    fn into_napi_ref<'a, C: Context<'a>>(mut self, cx: &mut C) -> NapiRef {\n        let reference = self.as_napi_ref(cx).clone();\n        // This uses `as_napi_ref` instead of `Option::take` for the instance id safety check\n        self.internal = None;\n        reference\n    }\n}\n\n// Allows putting `Root<T>` directly in a container that implements `Finalize`\n// For example, `Vec<Root<T>>` or `JsBox`.\nimpl<T: Object> Finalize for Root<T> {\n    fn finalize<'a, C: Context<'a>>(self, cx: &mut C) {\n        self.drop(cx);\n    }\n}\n\nimpl<T> Drop for Root<T> {\n    #[cfg(not(feature = \"napi-6\"))]\n    fn drop(&mut self) {\n        // If `None`, the `NapiRef` has already been manually dropped\n        if self.internal.is_none() {\n            return;\n        }\n\n        // Destructors are called during stack unwinding, prevent a double\n        // panic and instead prefer to leak.\n        if std::thread::panicking() {\n            eprintln!(\"Warning: neon::handle::Root leaked during a panic\");\n            return;\n        }\n\n        // Only panic if the event loop is still running\n        if let Ok(true) = crate::context::internal::IS_RUNNING.try_with(|v| *v.borrow()) {\n            panic!(\"Must call `into_inner` or `drop` on `neon::handle::Root`\");\n        }\n    }\n\n    #[cfg(feature = \"napi-6\")]\n    fn drop(&mut self) {\n        // If `None`, the `NapiRef` has already been manually dropped\n        if let Some(internal) = self.internal.take() {\n            let _ = self.drop_queue.call(DropData::Ref(internal), None);\n        }\n    }\n}\n"
  },
  {
    "path": "crates/neon/src/lib.rs",
    "content": "//! The [Neon][neon] crate provides bindings for writing [Node.js addons][addons]\n//! (i.e., dynamically-loaded binary modules) with a safe and fast Rust API.\n//!\n//! ## Getting Started\n//!\n//! You can conveniently bootstrap a new Neon project with the Neon project\n//! generator. You don't need to install anything special on your machine as\n//! long as you have a [supported version of Node and Rust][supported] on\n//! your system.\n//!\n//! To start a new project, open a terminal in the directory where you would\n//! like to place the project, and run at the command prompt:\n//!\n//! ```text\n//! % npm init neon my-project\n//! ... answer the user prompts ...\n//! ✨ Created Neon project `my-project`. Happy 🦀 hacking! ✨\n//! ```\n//!\n//! where `my-project` can be any name you like for the project. This will\n//! run the Neon project generator, prompting you with a few questions and\n//! placing a simple but working Neon project in a subdirectory called\n//! `my-project` (or whatever name you chose).\n//!\n//! You can then install and build the project by changing into the project\n//! directory and running the standard Node installation command:\n//!\n//! ```text\n//! % cd my-project\n//! % npm install\n//! % node\n//! > require(\".\").hello()\n//! 'hello node'\n//! ```\n//!\n//! You can look in the project's generated `README.md` for more details on\n//! the project structure.\n//!\n//! ## Example\n//!\n//! The generated `src/lib.rs` contains a function annotated with the\n//! [`#[neon::main]`](main) attribute, marking it as the module's main entry\n//! point to be executed when the module is loaded. This function can have\n//! any name but is conventionally called `main`:\n//!\n//! ```no_run\n//! # mod example {\n//! # use neon::prelude::*;\n//! # fn hello(mut cx: FunctionContext) -> JsResult<JsString> {\n//! #    Ok(cx.string(\"hello node\"))\n//! # }\n//! #[neon::main]\n//! fn main(mut cx: ModuleContext) -> NeonResult<()> {\n//!     cx.export_function(\"hello\", hello)?;\n//!     Ok(())\n//! }\n//! # }\n//! ```\n//!\n//! The example code generated by `npm init neon` exports a single\n//! function via [`ModuleContext::export_function`](context::ModuleContext::export_function).\n//! The `hello` function is defined just above `main` in `src/lib.rs`:\n//!\n//! ```\n//! # use neon::prelude::*;\n//! #\n//! fn hello(mut cx: FunctionContext) -> JsResult<JsString> {\n//!     Ok(cx.string(\"hello node\"))\n//! }\n//! ```\n//!\n//! The `hello` function takes a [`FunctionContext`](context::FunctionContext) and\n//! returns a JavaScript string. Because all Neon functions can potentially throw a\n//! JavaScript exception, the return type is wrapped in a [`JsResult`](result::JsResult).\n//!\n//! [neon]: https://www.neon-bindings.com/\n//! [addons]: https://nodejs.org/api/addons.html\n//! [supported]: https://github.com/neon-bindings/neon#platform-support\n#![cfg_attr(docsrs, feature(doc_cfg))]\n\npub mod context;\npub mod event;\npub mod handle;\nmod macros;\npub mod meta;\npub mod object;\npub mod prelude;\npub mod reflect;\npub mod result;\n#[cfg(not(feature = \"sys\"))]\nmod sys;\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-6\")))]\n#[cfg(feature = \"napi-6\")]\npub mod thread;\n// To use the #[aquamarine] attribute on the top-level neon::types module docs, we have to\n// use this hack so we can keep the module docs in a separate file.\n// See: https://github.com/mersinvald/aquamarine/issues/5#issuecomment-1168816499\nmod types_docs;\nmod types_impl;\n\n#[cfg(feature = \"sys\")]\n#[cfg_attr(docsrs, doc(cfg(feature = \"sys\")))]\npub mod sys;\n\n#[cfg(all(feature = \"napi-6\", feature = \"futures\"))]\n#[cfg_attr(docsrs, doc(cfg(all(feature = \"napi-6\", feature = \"futures\"))))]\npub use executor::set_global_executor;\npub use types_docs::exports as types;\n\n#[doc(hidden)]\npub mod macro_internal;\n\npub use crate::macros::*;\n\nuse crate::{context::ModuleContext, handle::Handle, result::NeonResult, types::JsValue};\n\n#[cfg(feature = \"napi-6\")]\nmod lifecycle;\n\n#[cfg(all(feature = \"napi-6\", feature = \"futures\"))]\nmod executor;\n\n#[cfg(feature = \"napi-8\")]\nstatic MODULE_TAG: once_cell::sync::Lazy<crate::sys::TypeTag> = once_cell::sync::Lazy::new(|| {\n    let mut lower = [0; std::mem::size_of::<u64>()];\n\n    // Generating a random module tag at runtime allows Neon builds to be reproducible. A few\n    //  alternatives considered:\n    // * Generating a random value at build time; this reduces runtime dependencies but, breaks\n    //   reproducible builds\n    // * A static random value; this solves the previous issues, but does not protect against ABI\n    //   differences across Neon and Rust versions\n    // * Calculating a variable from the environment (e.g. Rust version); this theoretically works\n    //   but, is complicated and error prone. This could be a future optimization.\n    getrandom::getrandom(&mut lower).expect(\"Failed to generate a Neon module type tag\");\n\n    // We only use 64-bits of the available 128-bits. The rest is reserved for future versioning and\n    // expansion of implementation.\n    let lower = u64::from_ne_bytes(lower);\n\n    // Note: `upper` must be non-zero or `napi_check_object_type_tag` will always return false\n    // https://github.com/nodejs/node/blob/5fad0b93667ffc6e4def52996b9529ac99b26319/src/js_native_api_v8.cc#L2455\n    crate::sys::TypeTag { lower, upper: 1 }\n});\n\n/// Values exported with [`neon::export`](export)\npub struct Exports(());\n\nimpl Exports {\n    /// Export all values exported with [`neon::export`](export)\n    ///\n    /// ```\n    /// # fn main() {\n    /// # use neon::prelude::*;\n    /// #[neon::main]\n    /// fn main(mut cx: ModuleContext) -> NeonResult<()> {\n    ///     neon::registered().export(&mut cx)?;\n    ///     Ok(())\n    /// }\n    /// # }\n    /// ```\n    ///\n    /// For more control, iterate over exports.\n    ///\n    /// ```\n    /// # fn main() {\n    /// # use neon::prelude::*;\n    /// #[neon::main]\n    /// fn main(mut cx: ModuleContext) -> NeonResult<()> {\n    ///     for create in neon::registered() {\n    ///         let (name, value) = create(&mut cx)?;\n    ///\n    ///         cx.export_value(name, value)?;\n    ///     }\n    ///\n    ///     Ok(())\n    /// }\n    /// # }\n    /// ```\n    pub fn export(self, cx: &mut ModuleContext) -> NeonResult<()> {\n        for create in self {\n            let (name, value) = create(cx)?;\n\n            cx.export_value(name, value)?;\n        }\n\n        Ok(())\n    }\n}\n\nimpl IntoIterator for Exports {\n    type Item = <<Self as IntoIterator>::IntoIter as IntoIterator>::Item;\n    type IntoIter = std::slice::Iter<\n        'static,\n        for<'cx> fn(&mut ModuleContext<'cx>) -> NeonResult<(&'static str, Handle<'cx, JsValue>)>,\n    >;\n\n    fn into_iter(self) -> Self::IntoIter {\n        crate::macro_internal::EXPORTS.into_iter()\n    }\n}\n\n/// Access values exported with [`neon::export`](export)\npub fn registered() -> Exports {\n    Exports(())\n}\n\n#[test]\nfn feature_matrix() {\n    use std::{env, process::Command};\n\n    // N.B.: Only versions that are used are included in order to keep the set\n    // of permutations as small as possible.\n    const NODE_API_VERSIONS: &[&str] = &[\"napi-1\", \"napi-4\", \"napi-5\", \"napi-6\", \"napi-8\"];\n\n    const FEATURES: &[&str] = &[\"external-buffers\", \"futures\", \"serde\", \"tokio\", \"tokio-rt\"];\n\n    let cargo = env::var_os(\"CARGO\").unwrap_or_else(|| \"cargo\".into());\n\n    for features in itertools::Itertools::powerset(FEATURES.iter()) {\n        for version in NODE_API_VERSIONS.iter().map(|f| f.to_string()) {\n            let features = features.iter().fold(version, |f, s| f + \",\" + s);\n            let status = Command::new(&cargo)\n                .args([\"check\", \"-p\", \"neon\", \"--no-default-features\", \"--features\"])\n                .arg(features)\n                .spawn()\n                .unwrap()\n                .wait()\n                .unwrap();\n\n            assert!(status.success());\n        }\n    }\n}\n"
  },
  {
    "path": "crates/neon/src/lifecycle.rs",
    "content": "//! # Environment life cycle APIs\n//!\n//! These APIs map to the life cycle of a specific \"Agent\" or self-contained\n//! environment. If a Neon module is loaded multiple times (Web Workers, worker\n//! threads), these API will be handle data associated with a specific instance.\n//!\n//! See the [N-API Lifecycle][npai-docs] documentation for more details.\n//!\n//! [napi-docs]: https://nodejs.org/api/n-api.html#n_api_environment_life_cycle_apis\n\nuse std::{\n    any::Any,\n    marker::PhantomData,\n    sync::{\n        atomic::{AtomicU32, Ordering},\n        Arc,\n    },\n};\n\nuse crate::{\n    context::Context,\n    event::Channel,\n    handle::root::NapiRef,\n    sys::{lifecycle, raw::Env, tsfn::ThreadsafeFunction},\n    types::promise::NodeApiDeferred,\n};\n\n#[derive(Copy, Clone, Debug, Eq, PartialEq)]\n#[repr(transparent)]\n/// Uniquely identifies an instance of the module\n///\n/// _Note_: Since `InstanceData` is created lazily, the order of `id` may not\n/// reflect the order that instances were created.\npub(crate) struct InstanceId(u32);\n\nimpl InstanceId {\n    fn next() -> Self {\n        static NEXT_ID: AtomicU32 = AtomicU32::new(0);\n\n        let next = NEXT_ID.fetch_add(1, Ordering::SeqCst).checked_add(1);\n        match next {\n            Some(id) => Self(id),\n            None => panic!(\"u32 overflow ocurred in Lifecycle InstanceId\"),\n        }\n    }\n}\n\n/// `InstanceData` holds Neon data associated with a particular instance of a\n/// native module. If a module is loaded multiple times (e.g., worker threads), this\n/// data will be unique per instance.\npub(crate) struct InstanceData {\n    id: InstanceId,\n\n    /// Used to free `Root` in the same JavaScript environment that created it\n    ///\n    /// _Design Note_: An `Arc` ensures the `ThreadsafeFunction` outlives the unloading\n    /// of a module. Since it is unlikely that modules will be re-loaded frequently, this\n    /// could be replaced with a leaked `&'static ThreadsafeFunction<NapiRef>`. However,\n    /// given the cost of FFI, this optimization is omitted until the cost of an\n    /// `Arc` is demonstrated as significant.\n    drop_queue: Arc<ThreadsafeFunction<DropData>>,\n\n    /// Shared `Channel` that is cloned to be returned by the `cx.channel()` method\n    shared_channel: Channel,\n\n    /// Table of user-defined instance-local cells.\n    locals: LocalTable,\n}\n\n#[derive(Default)]\npub(crate) struct LocalTable {\n    cells: Vec<LocalCell>,\n}\n\npub(crate) type LocalCellValue = Box<dyn Any + Send + 'static>;\n\n#[derive(Default)]\npub(crate) enum LocalCell {\n    #[default]\n    /// Uninitialized state.\n    Uninit,\n    /// Intermediate \"dirty\" state representing the middle of a `get_or_try_init` transaction.\n    Trying,\n    /// Fully initialized state.\n    Init(LocalCellValue),\n}\n\nimpl LocalCell {\n    /// Establish the initial state at the beginning of the initialization protocol.\n    /// This method ensures that re-entrant initialization always panics (i.e. when\n    /// an existing `get_or_try_init` is in progress).\n    fn pre_init<F>(&mut self, f: F)\n    where\n        F: FnOnce() -> LocalCell,\n    {\n        match self {\n            LocalCell::Uninit => {\n                *self = f();\n            }\n            LocalCell::Trying => panic!(\"attempt to reinitialize Local during initialization\"),\n            LocalCell::Init(_) => {}\n        }\n    }\n\n    pub(crate) fn get<'cx, 'a, C>(cx: &'a mut C, id: usize) -> Option<&'a mut LocalCellValue>\n    where\n        C: Context<'cx>,\n    {\n        let cell = InstanceData::locals(cx).get(id);\n        match cell {\n            LocalCell::Init(ref mut b) => Some(b),\n            _ => None,\n        }\n    }\n\n    pub(crate) fn get_or_init<'cx, 'a, C, F>(\n        cx: &'a mut C,\n        id: usize,\n        f: F,\n    ) -> &'a mut LocalCellValue\n    where\n        C: Context<'cx>,\n        F: FnOnce() -> LocalCellValue,\n    {\n        InstanceData::locals(cx)\n            .get(id)\n            .pre_init(|| LocalCell::Init(f()));\n\n        LocalCell::get(cx, id).unwrap()\n    }\n\n    pub(crate) fn get_or_try_init<'cx, 'a, C, E, F>(\n        cx: &'a mut C,\n        id: usize,\n        f: F,\n    ) -> Result<&'a mut LocalCellValue, E>\n    where\n        C: Context<'cx>,\n        F: FnOnce(&mut C) -> Result<LocalCellValue, E>,\n    {\n        // Kick off a new transaction and drop it before getting the result.\n        {\n            let mut tx = TryInitTransaction::new(cx, id);\n            tx.run(|cx| f(cx))?;\n        }\n\n        // If we're here, the transaction has succeeded, so get the result.\n        Ok(LocalCell::get(cx, id).unwrap())\n    }\n}\n\nimpl LocalTable {\n    pub(crate) fn get(&mut self, index: usize) -> &mut LocalCell {\n        if index >= self.cells.len() {\n            self.cells.resize_with(index + 1, Default::default);\n        }\n        &mut self.cells[index]\n    }\n}\n\n/// An RAII implementation of `LocalCell::get_or_try_init`, which ensures that\n/// the state of a cell is properly managed through all possible control paths.\n/// As soon as the transaction begins, the cell is labelled as being in a dirty\n/// state (`LocalCell::Trying`), so that any additional re-entrant attempts to\n/// initialize the cell will fail fast. The `Drop` implementation ensures that\n/// after the transaction, the cell goes back to a clean state of either\n/// `LocalCell::Uninit` if it fails or `LocalCell::Init` if it succeeds.\nstruct TryInitTransaction<'cx, 'a, C: Context<'cx>> {\n    cx: &'a mut C,\n    id: usize,\n    _lifetime: PhantomData<&'cx ()>,\n}\n\nimpl<'cx, 'a, C: Context<'cx>> TryInitTransaction<'cx, 'a, C> {\n    fn new(cx: &'a mut C, id: usize) -> Self {\n        let mut tx = Self {\n            cx,\n            id,\n            _lifetime: PhantomData,\n        };\n        tx.cell().pre_init(|| LocalCell::Trying);\n        tx\n    }\n\n    /// _Post-condition:_ If this method returns an `Ok` result, the cell is in the\n    /// `LocalCell::Init` state.\n    fn run<E, F>(&mut self, f: F) -> Result<(), E>\n    where\n        F: FnOnce(&mut C) -> Result<LocalCellValue, E>,\n    {\n        if self.is_trying() {\n            let value = f(self.cx)?;\n            *self.cell() = LocalCell::Init(value);\n        }\n        Ok(())\n    }\n\n    fn cell(&mut self) -> &mut LocalCell {\n        InstanceData::locals(self.cx).get(self.id)\n    }\n\n    #[allow(clippy::wrong_self_convention)]\n    fn is_trying(&mut self) -> bool {\n        matches!(self.cell(), LocalCell::Trying)\n    }\n}\n\nimpl<'cx, 'a, C: Context<'cx>> Drop for TryInitTransaction<'cx, 'a, C> {\n    fn drop(&mut self) {\n        if self.is_trying() {\n            *self.cell() = LocalCell::Uninit;\n        }\n    }\n}\n\n/// Wrapper for raw Node-API values to be dropped on the main thread\npub(crate) enum DropData {\n    Deferred(NodeApiDeferred),\n    Ref(NapiRef),\n}\n\nimpl DropData {\n    /// Drop a value on the main thread\n    fn drop(env: Option<Env>, data: Self) {\n        if let Some(env) = env {\n            unsafe {\n                match data {\n                    DropData::Deferred(data) => data.leaked(env),\n                    DropData::Ref(data) => data.unref(env),\n                }\n            }\n        }\n    }\n}\n\nimpl InstanceData {\n    /// Return the data associated with this module instance, lazily initializing if\n    /// necessary.\n    ///\n    /// # Safety\n    /// No additional locking (e.g., `Mutex`) is necessary because holding a\n    /// `Context` reference ensures serialized access.\n    pub(crate) fn get<'cx, C: Context<'cx>>(cx: &mut C) -> &mut InstanceData {\n        let env = cx.env().to_raw();\n        let data = unsafe { lifecycle::get_instance_data::<InstanceData>(env).as_mut() };\n\n        if let Some(data) = data {\n            return data;\n        }\n\n        let drop_queue = unsafe {\n            let queue = ThreadsafeFunction::new(env, DropData::drop);\n            queue.unref(env);\n            queue\n        };\n\n        let shared_channel = {\n            let mut channel = Channel::new(cx);\n            channel.unref(cx);\n            channel\n        };\n\n        let data = InstanceData {\n            id: InstanceId::next(),\n            drop_queue: Arc::new(drop_queue),\n            shared_channel,\n            locals: LocalTable::default(),\n        };\n\n        unsafe { &mut *lifecycle::set_instance_data(env, data) }\n    }\n\n    /// Helper to return a reference to the `drop_queue` field of `InstanceData`\n    pub(crate) fn drop_queue<'cx, C: Context<'cx>>(\n        cx: &mut C,\n    ) -> Arc<ThreadsafeFunction<DropData>> {\n        Arc::clone(&InstanceData::get(cx).drop_queue)\n    }\n\n    /// Clones the shared channel and references it since new channels should start\n    /// referenced, but the shared channel is unreferenced.\n    pub(crate) fn channel<'cx, C: Context<'cx>>(cx: &mut C) -> Channel {\n        let mut channel = InstanceData::get(cx).shared_channel.clone();\n        channel.reference(cx);\n        channel\n    }\n\n    /// Unique identifier for this instance of the module\n    pub(crate) fn id<'cx, C: Context<'cx>>(cx: &mut C) -> InstanceId {\n        InstanceData::get(cx).id\n    }\n\n    /// Helper to return a reference to the `locals` field of `InstanceData`.\n    pub(crate) fn locals<'cx, C: Context<'cx>>(cx: &mut C) -> &mut LocalTable {\n        &mut InstanceData::get(cx).locals\n    }\n}\n"
  },
  {
    "path": "crates/neon/src/macro_internal/futures.rs",
    "content": "use std::future::Future;\n\nuse crate::{\n    context::{Context, Cx, TaskContext},\n    result::JsResult,\n    types::JsValue,\n};\n\npub fn spawn<'cx, F, S>(cx: &mut Cx<'cx>, fut: F, settle: S) -> JsResult<'cx, JsValue>\nwhere\n    F: Future + Send + 'static,\n    F::Output: Send,\n    S: FnOnce(TaskContext, F::Output) -> JsResult<JsValue> + Send + 'static,\n{\n    let rt = match crate::executor::RUNTIME.get(cx) {\n        Some(rt) => rt,\n        None => return cx.throw_error(\"must initialize with neon::set_global_executor\"),\n    };\n\n    let ch = cx.channel();\n    let (d, promise) = cx.promise();\n\n    rt.spawn(Box::pin(async move {\n        let res = fut.await;\n        let _ = d.try_settle_with(&ch, move |cx| settle(cx, res));\n    }));\n\n    Ok(promise.upcast())\n}\n"
  },
  {
    "path": "crates/neon/src/macro_internal/mod.rs",
    "content": "//! Internals needed by macros. These have to be exported for the macros to work\n\nuse std::marker::PhantomData;\n\npub use linkme;\n\nuse crate::{\n    context::{Context, Cx, ModuleContext},\n    handle::Handle,\n    result::{JsResult, NeonResult},\n    types::{extract::TryIntoJs, JsValue},\n};\n\n#[cfg(feature = \"serde\")]\nuse crate::types::extract::Json;\n\n#[cfg(all(feature = \"napi-6\", feature = \"futures\"))]\npub use self::futures::*;\n\npub mod object {\n    pub use crate::object::wrap::{unwrap, wrap};\n}\n\n#[cfg(all(feature = \"napi-6\", feature = \"futures\"))]\nmod futures;\n\ntype Export<'cx> = (&'static str, Handle<'cx, JsValue>);\n\n#[linkme::distributed_slice]\npub static EXPORTS: [for<'cx> fn(&mut ModuleContext<'cx>) -> NeonResult<Export<'cx>>];\n\n#[linkme::distributed_slice]\npub static MAIN: [for<'cx> fn(ModuleContext<'cx>) -> NeonResult<()>];\n\n// Wrapper for the value type and return type tags\npub struct NeonMarker<Tag, Return>(PhantomData<Tag>, PhantomData<Return>);\n\n// Markers to determine the type of a value\n#[cfg(feature = \"serde\")]\npub struct NeonJsonTag;\npub struct NeonValueTag;\npub struct NeonResultTag;\n\npub trait ToNeonMarker {\n    type Return;\n\n    fn to_neon_marker<Tag>(&self) -> NeonMarker<Tag, Self::Return>;\n}\n\n// Specialized implementation for `Result`\nimpl<T, E> ToNeonMarker for Result<T, E> {\n    type Return = NeonResultTag;\n\n    fn to_neon_marker<Tag>(&self) -> NeonMarker<Tag, Self::Return> {\n        NeonMarker(PhantomData, PhantomData)\n    }\n}\n\n// Default implementation that takes lower precedence due to autoref\nimpl<T> ToNeonMarker for &T {\n    type Return = NeonValueTag;\n\n    fn to_neon_marker<Tag>(&self) -> NeonMarker<Tag, Self::Return> {\n        NeonMarker(PhantomData, PhantomData)\n    }\n}\n\nimpl<Return> NeonMarker<NeonValueTag, Return> {\n    pub fn neon_into_js<'cx, T>(self, cx: &mut Cx<'cx>, v: T) -> JsResult<'cx, JsValue>\n    where\n        T: TryIntoJs<'cx>,\n    {\n        v.try_into_js(cx).map(|v| v.upcast())\n    }\n}\n\n#[cfg(feature = \"serde\")]\nimpl NeonMarker<NeonJsonTag, NeonValueTag> {\n    pub fn neon_into_js<'cx, T>(self, cx: &mut Cx<'cx>, v: T) -> JsResult<'cx, JsValue>\n    where\n        Json<T>: TryIntoJs<'cx>,\n    {\n        Json(v).try_into_js(cx).map(|v| v.upcast())\n    }\n}\n\n#[cfg(feature = \"serde\")]\nimpl NeonMarker<NeonJsonTag, NeonResultTag> {\n    pub fn neon_into_js<'cx, T, E>(\n        self,\n        cx: &mut Cx<'cx>,\n        res: Result<T, E>,\n    ) -> JsResult<'cx, JsValue>\n    where\n        Result<Json<T>, E>: TryIntoJs<'cx>,\n    {\n        res.map(Json).try_into_js(cx).map(|v| v.upcast())\n    }\n}\n\nimpl<Tag> NeonMarker<Tag, NeonValueTag> {\n    pub fn into_neon_result<T>(self, _cx: &mut Cx, v: T) -> NeonResult<T> {\n        Ok(v)\n    }\n}\n\nimpl<Tag> NeonMarker<Tag, NeonResultTag> {\n    pub fn into_neon_result<'cx, T, E>(self, cx: &mut Cx<'cx>, res: Result<T, E>) -> NeonResult<T>\n    where\n        E: TryIntoJs<'cx>,\n    {\n        match res {\n            Ok(v) => Ok(v),\n            Err(err) => err.try_into_js(cx).and_then(|err| cx.throw(err)),\n        }\n    }\n}\n\n#[cfg(feature = \"napi-6\")]\npub use crate::object::class::new_class_metadata;\n\n#[cfg(feature = \"napi-6\")]\npub use crate::types_impl::extract::private::Sealed;\n\n#[cfg(feature = \"napi-6\")]\npub use crate::object::wrap::WrapError;\n\n#[cfg(feature = \"napi-6\")]\npub use crate::object::class::ClassInternal;\n\n#[cfg(feature = \"napi-6\")]\npub use crate::object::class::{ClassMetadata, RootClassMetadata};\n\n#[cfg(feature = \"napi-6\")]\npub fn internal_constructor<'cx, T: crate::object::Class>(\n    cx: &mut Cx<'cx>,\n) -> NeonResult<Handle<'cx, crate::types::JsFunction>> {\n    let class_instance = T::local(cx)?;\n    Ok(class_instance.internal_constructor())\n}\n"
  },
  {
    "path": "crates/neon/src/macros.rs",
    "content": "//! Helper module to add documentation to macros prior to re-exporting.\n\n#[cfg(feature = \"napi-6\")]\n/// Create a Neon class from a Rust datatype\n///\n/// The `#[neon::class]` attribute can be applied to an `impl` block to create a JavaScript\n/// class that wraps a Rust struct (or enum). The `impl` block specifies a constructor method named\n/// `new` to create instances of the struct, which Neon automatically attaches to instances of the\n/// JavaScript class during object construction.\n///\n/// Typically, Neon classes are exported from their addon, which can be done with the\n/// [`#[neon::export(class)]`](crate::export) attribute.\n///\n/// ## Example\n///\n/// ```\n/// # use neon::prelude::*;\n/// # use neon::{context::Context, types::Finalize};\n/// #[derive(Clone)]\n/// pub struct User {\n///     username: String,\n///     first_name: String,\n///     last_name: String,\n/// }\n///\n/// #[neon::export(class)]\n/// impl User {\n///     pub fn new(username: String, first_name: String, last_name: String) -> Self {\n///         Self { username, first_name, last_name }\n///     }\n///\n///     pub fn to_string(&self) -> String {\n///         format!(\"[object User:{}]\", self.username)\n///     }\n/// }\n/// ```\n///\n/// ## Constructor\n///\n/// Classes must have exactly one constructor method named `new`. The constructor takes\n/// the class parameters and returns `Self`. Constructor arguments can be any type that\n/// implements [`TryFromJs`](crate::types::extract::TryFromJs).\n///\n/// ```\n/// # use neon::prelude::*;\n/// # use neon::types::Finalize;\n/// pub struct Person {\n///     name: String,\n///     age: u32,\n/// }\n///\n/// #[neon::class]\n/// impl Person {\n///     pub fn new(name: String, age: u32) -> Self {\n///         Self { name, age }\n///     }\n/// }\n/// ```\n///\n/// ## Methods\n///\n/// Class methods can have either `&self` or `&mut self` as their first parameter.\n/// Methods can take any type that implements [`TryFromJs`](crate::types::extract::TryFromJs)\n/// and return any type that implements [`TryIntoJs`](crate::types::extract::TryIntoJs).\n///\n/// ```\n/// # use neon::prelude::*;\n/// # use neon::types::Finalize;\n/// pub struct Counter {\n///     value: i32,\n/// }\n///\n/// #[neon::class]\n/// impl Counter {\n///     pub fn new(initial: i32) -> Self {\n///         Self { value: initial }\n///     }\n///\n///     pub fn increment(&mut self) -> i32 {\n///         self.value += 1;\n///         self.value\n///     }\n///\n///     pub fn get(&self) -> i32 {\n///         self.value\n///     }\n/// }\n/// ```\n///\n/// ### Reference Parameters\n///\n/// Methods can accept class instances by reference (`&T`) or mutable reference (`&mut T`)\n/// to avoid cloning when passing instances between methods. The type must implement\n/// [`TryFromJsRef`](crate::types::extract::TryFromJsRef) for immutable references or\n/// [`TryFromJsRefMut`](crate::types::extract::TryFromJsRefMut) for mutable references.\n/// The `#[neon::class]` macro automatically implements these traits for all class types.\n///\n/// ```\n/// # use neon::prelude::*;\n/// # use neon::types::Finalize;\n/// #[derive(Clone)]\n/// pub struct Point {\n///     x: f64,\n///     y: f64,\n/// }\n///\n/// #[neon::class]\n/// impl Point {\n///     pub fn new(x: f64, y: f64) -> Self {\n///         Self { x, y }\n///     }\n///\n///     // Accept another Point by immutable reference (no clone)\n///     pub fn distance(&self, other: &Self) -> f64 {\n///         let dx = self.x - other.x;\n///         let dy = self.y - other.y;\n///         (dx * dx + dy * dy).sqrt()\n///     }\n///\n///     // Accept another Point by mutable reference (no clone)\n///     pub fn swap_coordinates(&mut self, other: &mut Self) {\n///         std::mem::swap(&mut self.x, &mut other.x);\n///         std::mem::swap(&mut self.y, &mut other.y);\n///     }\n///\n///     // Accept another Point by value (clones the instance)\n///     pub fn midpoint(&self, other: Self) -> Self {\n///         Self {\n///             x: (self.x + other.x) / 2.0,\n///             y: (self.y + other.y) / 2.0,\n///         }\n///     }\n/// }\n/// ```\n///\n/// From JavaScript:\n/// ```js\n/// const p1 = new Point(0, 0);\n/// const p2 = new Point(3, 4);\n///\n/// console.log(p1.distance(p2));    // 5 (no cloning)\n///\n/// p1.swapCoordinates(p2);          // Mutates both points\n/// console.log(p1.x);               // 3\n/// console.log(p2.x);               // 0\n///\n/// const mid = p1.midpoint(p2);     // Clones p2\n/// ```\n///\n/// **When to use references:**\n/// - Use `&T` when you only need to read from the instance\n/// - Use `&mut T` when you need to mutate the instance\n/// - Use `T` (by value) when the semantics require taking ownership\n///\n/// Note that reference parameters still use [`RefCell`](std::cell::RefCell) internally,\n/// so runtime borrow checking applies. Attempting to borrow the same instance both mutably\n/// and immutably (or multiple times mutably) will panic.\n///\n/// ## Finalizer\n///\n/// Classes can implement a `finalize` method to perform cleanup when the\n/// JavaScript object is garbage collected. The `finalize` method takes\n/// ownership of the class instance and is called when the object is no longer\n/// reachable from JavaScript.\n///\n/// ```\n/// # use neon::prelude::*;\n/// pub struct Logger {\n///     name: String,\n/// }\n///\n/// #[neon::class]\n/// impl Logger {\n///     pub fn new(name: String) -> Self {\n///         Self { name }\n///     }\n///\n///     pub fn finalize<'cx, C: Context<'cx>>(self, _cx: &mut C) {\n///         println!(\"Logger {} is being finalized\", self.name);\n///     }\n/// }\n/// ```\n///\n/// ## Mutability and Borrow Checking\n///\n/// Neon classes use [`RefCell`](std::cell::RefCell) internally to allow mutation through\n/// `&mut self` methods while maintaining JavaScript's shared ownership semantics. This means\n/// that borrow checking happens at runtime, not compile time, and violating Rust's borrowing\n/// rules will cause a panic.\n///\n/// **Important:** You cannot call a method that requires `&mut self` while another method\n/// is borrowing the instance (even with `&self`). This includes:\n/// - Reentrancy from JavaScript callbacks\n/// - Nested method calls on the same instance\n///\n/// For complex scenarios involving callbacks or shared mutable state across threads,\n/// consider using additional interior mutability types like\n/// [`Arc<Mutex<T>>`](std::sync::Arc) for the specific fields that need it.\n///\n/// ### Method Attributes\n///\n/// Methods support the same attributes as [`#[neon::export]`](crate::export) functions, including\n/// `json`, `task`, `async`, `context`, `this`, and `name`, and may be fallible by returning\n/// `Result` types.\n///\n/// #### JSON Methods\n///\n/// ```\n/// # use neon::prelude::*;\n/// # use neon::types::Finalize;\n/// pub struct DataProcessor;\n///\n/// #[neon::class]\n/// impl DataProcessor {\n///     pub fn new() -> Self {\n///         Self\n///     }\n///\n///     #[neon(json)]\n///     pub fn process_data(&self, items: Vec<String>) -> Vec<String> {\n///         items.into_iter().map(|s| s.to_uppercase()).collect()\n///     }\n/// }\n/// ```\n///\n/// #### Async Methods\n///\n/// Methods declared with `async fn` are automatically detected and exported as async. The\n/// macro automatically clones the instance before calling the method. Because Rust's `async fn`\n/// captures `self` into the Future (which must be `'static`), the method must take `self` by\n/// value (not `&self` or `&mut self`) and the struct must implement `Clone`. Any shared mutable\n/// state should use types like [`Arc<Mutex<T>>`](std::sync::Arc) for thread-safe interior\n/// mutability.\n///\n/// ```\n/// # #[cfg(all(feature = \"napi-6\", feature = \"futures\"))]\n/// # {\n/// # use neon::prelude::*;\n/// # use neon::types::Finalize;\n/// # use std::sync::{Arc, Mutex};\n/// # #[derive(Clone)]\n/// # pub struct AsyncWorker {\n/// #     counter: Arc<Mutex<i32>>,\n/// # }\n/// #[neon::class]\n/// impl AsyncWorker {\n///     pub fn new() -> Self {\n///         Self {\n///             counter: Arc::new(Mutex::new(0)),\n///         }\n///     }\n///\n///     // Must take `self` by value; the macro clones the instance automatically\n///     pub async fn fetch_data(self, url: String) -> String {\n///         // Simulate async work\n///         let mut count = self.counter.lock().unwrap();\n///         *count += 1;\n///         format!(\"Data from {} (request #{})\", url, count)\n///     }\n/// }\n/// # }\n/// ```\n///\n/// ##### Synchronous Setup\n///\n/// For more control over async behavior, use `#[neon(async)]` with a method that\n/// returns a [`Future`](std::future::Future). This allows synchronous setup on\n/// the JavaScript main thread. With this approach, the method takes `&self` and you\n/// are responsible for cloning any data needed to make the returned Future `'static`.\n///\n/// ```\n/// # #[cfg(all(feature = \"napi-6\", feature = \"futures\"))]\n/// # {\n/// # use neon::prelude::*;\n/// # use neon::types::Finalize;\n/// # use std::future::Future;\n/// # #[derive(Clone)]\n/// # pub struct AsyncWorker {\n/// #     value: String,\n/// # }\n/// #[neon::class]\n/// impl AsyncWorker {\n/// #   pub fn new() -> Self { Self { value: String::new() } }\n///     #[neon(async)]\n///     pub fn process_data(&self, data: String) -> impl Future<Output = String> + 'static {\n///         println!(\"Setup on main thread\");\n///         // Clone any instance data you need for the Future\n///         let value = self.value.clone();\n///         async move {\n///             format!(\"{}: {}\", value, data.to_uppercase())\n///         }\n///     }\n/// }\n/// # }\n/// ```\n///\n/// #### Task Methods\n///\n/// Methods can be executed on Node's worker pool using the `task` attribute. The macro\n/// automatically clones the instance before moving it to the worker thread, so the struct\n/// must implement `Clone`. Like `async fn` methods, task methods must take `self` by value\n/// (not `&self` or `&mut self`) to make it clear that they operate on a clone.\n///\n/// ```\n/// # use neon::prelude::*;\n/// # use neon::types::Finalize;\n/// #[derive(Clone)]\n/// pub struct CpuWorker {\n///     multiplier: u32,\n/// }\n///\n/// #[neon::class]\n/// impl CpuWorker {\n///     pub fn new(multiplier: u32) -> Self {\n///         Self { multiplier }\n///     }\n///\n///     // Must take `self` by value; the macro clones the instance automatically\n///     #[neon(task)]\n///     pub fn heavy_computation(self, iterations: u32) -> u32 {\n///         (0..iterations).map(|i| i * self.multiplier).sum()\n///     }\n/// }\n/// ```\n///\n/// #### Method Naming\n///\n/// Like [`#[neon::export]`](crate::export) functions, method names are converted from `snake_case`\n/// to `camelCase`. Custom names can be specified with the `name` attribute:\n///\n/// ```\n/// # use neon::prelude::*;\n/// # use neon::types::Finalize;\n/// pub struct Label {\n///     data: String,\n/// }\n///\n/// #[neon::class]\n/// impl Label {\n///     pub fn new() -> Self {\n///         Self { data: String::new() }\n///     }\n///\n///     #[neon(name = \"trimStart\")]\n///     pub fn trim_leading(&self) -> String {\n///         self.data.trim_start().to_string()\n///     }\n/// }\n/// ```\n///\n/// #### Fallible Methods\n///\n/// Methods can return `Result` types to throw JavaScript exceptions, just like\n/// `#[neon::export]` functions.\n///\n/// ```\n/// # use neon::prelude::*;\n/// pub struct User {\n///     name: String,\n/// }\n///\n/// #[neon::class]\n/// impl User {\n///     pub fn new(name: String) -> Self {\n///         Self { name }\n///     }\n///\n///     pub fn get_name(&self) -> String {\n///         self.name.clone()\n///     }\n///\n///     pub fn set_name(&mut self, name: String) -> Result<(), &'static str> {\n///         if name.is_empty() {\n///             return Err(\"Name cannot be empty\");\n///         }\n///\n///         self.name = name;\n///\n///         Ok(())\n///     }\n/// }\n/// ```\n///\n/// ### Constructor Attributes\n///\n/// Constructor methods support the `json` and `context` attributes and may be fallible as well.\n///\n/// ```\n/// # use neon::prelude::*;\n/// # use neon::types::extract::Json;\n/// pub struct Argv {\n///     pub args: Vec<String>,\n/// }\n///\n/// #[neon::class]\n/// impl Argv {\n///     // context attribute is inferred automatically\n///     #[neon(json)]\n///     pub fn new(cx: &mut Cx, args: Option<Vec<String>>) -> NeonResult<Self> {\n///         let args = if let Some(args) = args { args } else {\n///             let Json(args): Json<Vec<String>> = cx\n///                 .global::<JsObject>(\"process\")?\n///                 .prop(cx, \"argv\")\n///                 .get()?;\n///             args\n///         };\n///         Ok(Self { args } )\n///     }\n///\n///     pub fn len(&self) -> u32 {\n///         self.args.len() as u32\n///     }\n///\n///     pub fn get(&self, index: u32) -> Option<String> {\n///         self.args.get(index as usize).cloned()\n///     }\n/// }\n/// ```\n///\n/// ## Const Properties\n///\n/// Classes can expose Rust constants as static, immutable properties on the JavaScript class:\n///\n/// ```\n/// # use neon::prelude::*;\n/// # use neon::types::Finalize;\n/// pub struct MathConstants;\n///\n/// #[neon::class]\n/// impl MathConstants {\n///     const PI: f64 = 3.14159;\n///     const VERSION: u32 = 1;\n///\n///     #[neon(name = \"maxValue\")]\n///     const MAX_VALUE: f64 = f64::MAX;\n///\n///     #[neon(json)]\n///     const DEFAULT_SETTINGS: &'static [&'static str] = &[\"feature1\", \"feature2\"];\n///\n///     pub fn new() -> Self {\n///         Self\n///     }\n/// }\n/// ```\n///\n/// From JavaScript:\n/// ```js\n/// console.log(MathConstants.PI);               // 3.14159\n/// console.log(MathConstants.maxValue);         // 1.7976931348623157e+308\n/// console.log(MathConstants.DEFAULT_SETTINGS); // [\"feature1\", \"feature2\"]\n/// ```\n///\n/// Const properties support the same attributes as globals: `name` for custom naming\n/// and `json` for automatic JSON serialization. Properties are immutable from JavaScript.\n///\n/// ## Context and This Parameters\n///\n/// Methods can access the JavaScript runtime context and the JavaScript object wrapper:\n///\n/// ```\n/// # use neon::prelude::*;\n/// # use neon::types::Finalize;\n/// pub struct Interactive {\n///     data: String,\n/// }\n///\n/// #[neon::class]\n/// impl Interactive {\n///     pub fn new(data: String) -> Self {\n///         Self { data }\n///     }\n///\n///     // Method with context parameter\n///     pub fn create_object<'cx>(\n///         &self,\n///         cx: &mut FunctionContext<'cx>,\n///     ) -> JsResult<'cx, JsObject> {\n///         let obj = cx.empty_object();\n///         let value = cx.string(&self.data);\n///         obj.set(cx, \"data\", value)?;\n///         Ok(obj)\n///     }\n///\n///     // Method with this parameter (access to JS object)\n///     pub fn inspect_this(&self, this: Handle<JsObject>) -> String {\n///         format!(\"JS object available: {}\", self.data)\n///     }\n/// }\n/// ```\n///\n/// ## Working with Class Instances\n///\n/// Methods can accept and return instances of the same class directly. When a class instance\n/// is passed as a parameter or returned from a method, it is automatically cloned from (or into)\n/// the internal [`RefCell`](std::cell::RefCell) storage, so the struct must implement `Clone`.\n///\n/// ```\n/// # use neon::prelude::*;\n/// # use neon::types::Finalize;\n/// #[derive(Clone)]\n/// pub struct Point {\n///     x: f64,\n///     y: f64,\n/// }\n///\n/// #[neon::class]\n/// impl Point {\n///     pub fn new(x: f64, y: f64) -> Self {\n///         Self { x, y }\n///     }\n///\n///     pub fn distance(&self, other: Self) -> f64 {\n///         let dx = self.x - other.x;\n///         let dy = self.y - other.y;\n///         (dx * dx + dy * dy).sqrt()\n///     }\n///\n///     pub fn midpoint(&self, other: Self) -> Self {\n///         Self {\n///             x: (self.x + other.x) / 2.0,\n///             y: (self.y + other.y) / 2.0,\n///         }\n///     }\n/// }\n/// ```\n///\n/// From JavaScript, you can call these methods with other instances of the same class:\n/// ```js\n/// const p1 = new Point(0, 0);\n/// const p2 = new Point(3, 4);\n/// console.log(p1.distance(p2)); // 5\n/// const midpoint = p1.midpoint(p2); // Point { x: 1.5, y: 2 }\n/// ```\n///\n/// ## Export Shorthand\n///\n/// Use [`#[neon::export(class)]`](crate::export) to combine class definition with\n/// automatic module export:\n///\n/// ```\n/// # use neon::prelude::*;\n/// # use neon::types::Finalize;\n/// pub struct AutoExported {\n///     value: u32,\n/// }\n///\n/// // Combines #[neon::class] with automatic export\n/// #[neon::export(class)]\n/// impl AutoExported {\n///     pub fn new(value: u32) -> Self {\n///         Self { value }\n///     }\n/// }\n/// ```\n///\n/// Like other exports, classes can be exported with custom names:\n///\n/// ```\n/// # use neon::prelude::*;\n/// # use neon::types::Finalize;\n/// pub struct InternalPoint {\n///     x: f64,\n///     y: f64,\n/// }\n///\n/// // Export as \"Point\" instead of \"InternalPoint\"\n/// #[neon::export(class(name = \"Point\"))]\n/// impl InternalPoint {\n///     pub fn new(x: f64, y: f64) -> Self {\n///         Self { x, y }\n///     }\n///\n///     pub fn distance_from_origin(&self) -> f64 {\n///         (self.x * self.x + self.y * self.y).sqrt()\n///     }\n/// }\n/// ```\n///\n/// It's also possible to distinguish between the class name and export name:\n///\n/// ```\n/// # use neon::prelude::*;\n/// pub struct RustPoint {\n///     x: f64,\n///     y: f64,\n/// }\n///\n/// // Export as \"Point\" but with Point.name === \"NeonPoint\"\n/// #[neon::export(class(name = \"NeonPoint\"), name = \"Point\")]\n/// impl RustPoint {\n///     pub fn new(x: f64, y: f64) -> Self {\n///         Self { x, y }\n///     }\n/// }\n/// ```\n///\n/// ## Error Handling\n///\n/// Methods can return [`Result`] types to throw JavaScript exceptions, just like\n/// [`#[neon::export]`](crate::export) functions:\n///\n/// ```\n/// # use neon::prelude::*;\n/// # use neon::types::{Finalize, extract::Error};\n/// pub struct FileReader;\n///\n/// #[neon::class]\n/// impl FileReader {\n///     pub fn new() -> Self {\n///         Self\n///     }\n///\n///     pub fn read_file(&self, path: String) -> Result<String, Error> {\n///         std::fs::read_to_string(path).map_err(Error::from)\n///     }\n/// }\n/// ```\n///\n/// ## `Class` Trait\n///\n/// The `#[neon::class]` macro automatically implements the [`Class`](crate::object::Class)\n/// trait for the struct. This trait can be used to access the constructor function at runtime.\n///\n/// ```\n/// # use neon::prelude::*;\n/// # use neon::types::Finalize;\n/// use neon::object::Class;\n/// # #[derive(Clone)]\n/// # pub struct Point {\n/// #     x: f64,\n/// #     y: f64,\n/// # }\n/// #\n/// # #[neon::class]\n/// # impl Point {\n/// #     pub fn new(x: f64, y: f64) -> Self {\n/// #         Self { x, y }\n/// #     }\n/// # }\n///\n/// # fn init_statics<'cx>(cx: &mut FunctionContext<'cx>) -> JsResult<'cx, JsUndefined> {\n/// let constructor = Point::constructor(cx)?;\n/// constructor\n///     .prop(cx, \"ORIGIN\")\n///     .set(Point::new(0.0, 0.0))?;\n/// # Ok(cx.undefined())\n/// # }\n/// ```\npub use neon_macros::class;\n\n/// Marks a function as the main entry point for initialization in\n/// a Neon module.\n///\n/// This attribute should only be used _once_ in a module and will\n/// be called each time the module is initialized in a context.\n///\n/// If a `main` function is not provided, all registered exports will be exported. If\n/// the `tokio` feature flag is enabled, a multithreaded tokio runtime will also be\n/// registered globally.\n///\n/// ```\n/// # use neon::prelude::*;\n/// # fn main() {\n/// #[neon::main]\n/// fn main(mut cx: ModuleContext) -> NeonResult<()> {\n///     // Export all registered exports\n///     neon::registered().export(&mut cx)?;\n///\n///     let version = cx.string(\"1.0.0\");\n///\n///     cx.export_value(\"version\", version)?;\n///\n///     Ok(())\n/// }\n/// # }\n/// ```\npub use neon_macros::main;\n\n/// Register an item to be exported by the Neon addon\n///\n/// ## Exporting constants and statics\n///\n/// ```\n/// #[neon::export]\n/// static GREETING: &str = \"Hello, Neon!\";\n///\n/// #[neon::export]\n/// const ANSWER: u8 = 42;\n/// ```\n///\n/// ### Renaming an export\n///\n/// By default, items will be exported with their Rust name. Exports may\n/// be renamed by providing the `name` attribute.\n///\n/// ```\n/// #[neon::export(name = \"myGreeting\")]\n/// static GREETING: &str = \"Hello, Neon!\";\n/// ```\n///\n/// ### JSON exports\n///\n/// Complex values may be exported by automatically serializing to JSON and\n/// parsing in JavaScript. Any type that implements `serde::Serialize` may be used.\n///\n/// ```\n/// #[neon::export(json)]\n/// static MESSAGES: &[&str] = &[\"hello\", \"goodbye\"];\n/// ```\n///\n/// ## Exporting functions\n///\n/// Functions may take any type that implements [`TryFromJs`](crate::types::extract::TryFromJs) as\n/// an argument and return any type that implements [`TryIntoJs`](crate::types::extract::TryIntoJs).\n///\n/// ```\n/// #[neon::export]\n/// fn add(a: f64, b: f64) -> f64 {\n///     a + b\n/// }\n/// ```\n///\n/// ### Naming exported functions\n///\n/// Conventionally, Rust uses `snake_case` for function identifiers and JavaScript uses `camelCase`.\n/// By default, Neon will attempt to convert function names to camel case. For example:\n///\n/// ```rust\n/// #[neon::export]\n/// fn add_one(n: f64) -> f64 {\n///     n + 1.0\n/// }\n/// ```\n///\n/// The `add_one` function will be exported as `addOne` in JavaScript.\n///\n/// ```js\n/// import { addOne } from \".\";\n/// ```\n///\n/// [Similar to globals](#renaming-an-export), exported functions can be overridden with the `name`\n/// attribute.\n///\n/// ```rust\n/// #[neon::export(name = \"addOneSync\")]\n/// fn add_one(n: f64) -> f64 {\n///     n + 1.0\n/// }\n/// ```\n/// Neon uses the following rules when converting `snake_case` to `camelCase`:\n///\n/// * All _leading_ and _trailing_ underscores (`_`) are preserved\n/// * Characters _immediately_ following a _non-leading_ underscore are converted to uppercase\n/// * If the identifier contains an _unexpected_ character, **no** conversion is performed and\n///   the identifier is used _unchanged_. Unexpected characters include:\n///   - Uppercase characters\n///   - Duplicate _interior_ (non-leading, non-trailing underscores)\n///\n/// ### Exporting a function that uses JSON\n///\n/// The [`Json`](crate::types::extract::Json) wrapper allows ergonomically handling complex\n/// types that implement `serde::Deserialize` and `serde::Serialize`.\n///\n/// ```\n/// # use neon::types::extract::Json;\n/// #[neon::export]\n/// fn sort(Json(mut items): Json<Vec<String>>) -> Json<Vec<String>> {\n///     items.sort();\n///     Json(items)\n/// }\n/// ```\n///\n/// As a convenience, macro uses may add the `json` attribute to automatically\n/// wrap arguments and return values with `Json`.\n///\n/// ```\n/// #[neon::export(json)]\n/// fn sort(mut items: Vec<String>) -> Vec<String> {\n///     items.sort();\n///     items\n/// }\n/// ```\n///\n/// ### Tasks\n///\n/// Neon provides an API for spawning tasks to execute asynchronously on Node's worker\n/// pool. JavaScript may await a promise for completion of the task.\n///\n/// ```\n/// # use neon::prelude::*;\n/// #[neon::export]\n/// fn add<'cx>(cx: &mut FunctionContext<'cx>, a: f64, b: f64) -> JsResult<'cx, JsPromise> {\n///     let promise = cx\n///         .task(move || a + b)\n///         .promise(|mut cx, res| Ok(cx.number(res)));\n///\n///     Ok(promise)\n/// }\n/// ```\n///\n/// As a convenience, macro users may indicate that a function should be executed\n/// asynchronously on the worker pool by adding the `task` attribute.\n///\n/// ```\n/// #[neon::export(task)]\n/// fn add(a: f64, b: f64) -> f64 {\n///     a + b\n/// }\n/// ```\n///\n/// ### Async Functions\n///\n/// The [`export`] macro can export `async fn`, converting to a JavaScript `Promise`, if a global\n/// future executor is registered. See [`neon::set_global_executor`](crate::set_global_executor) for\n/// more details.\n///\n/// ```\n/// # #[cfg(all(feature = \"napi-6\", feature = \"futures\"))]\n/// # {\n/// #[neon::export]\n/// async fn add(a: f64, b: f64) -> f64 {\n///     a + b\n/// }\n/// # }\n/// ```\n///\n/// #### Synchronous Setup\n///\n/// To implement a function that appears asynchronous to JavaScript, but needs to perform\n/// some synchronous setup on the JavaScript main thread, a normal (i.e., non-`async`) Rust\n/// function that returns a [`Future`](std::future::Future) can be annotated with\n/// `#[neon::export(async)]`.\n///\n/// ```\n/// # #[cfg(all(feature = \"napi-6\", feature = \"futures\"))]\n/// # {\n/// # use std::future::Future;\n/// # use neon::prelude::*;\n/// #[neon::export(async)]\n/// fn add(a: f64, b: f64) -> impl Future<Output = f64> {\n///     println!(\"Hello from the JavaScript main thread!\");\n///\n///     async move {\n///         a + b\n///     }\n/// }\n/// # }\n/// ```\n///\n/// If work needs to be performed on the JavaScript main thread _after_ the asynchronous operation,\n/// the [`With`](crate::types::extract::With) extractor can be used to execute a closure before returning.\n///\n/// ```\n/// # #[cfg(all(feature = \"napi-6\", feature = \"futures\"))]\n/// # {\n/// # use neon::types::extract::{self, TryIntoJs};\n/// #[neon::export]\n/// async fn add(a: f64, b: f64) -> impl for<'cx> TryIntoJs<'cx> {\n///     let sum = a + b;\n///\n///     extract::with(move |cx| {\n///         println!(\"Hello from the JavaScript main thread!\");\n///\n///         sum.try_into_js(cx)\n///     })\n/// }\n/// # }\n/// ```\n///\n/// ### Error Handling\n///\n/// If an exported function returns a [`Result`], a JavaScript exception will be thrown\n/// with the [`Err`]. Any error type that implements [`TryIntoJs`](crate::types::extract::TryIntoJs)\n/// may be used.\n///\n/// ```\n/// #[neon::export]\n/// fn throw(msg: String) -> Result<(), String> {\n///     Err(msg)\n/// }\n/// ```\n///\n/// The [`Error`](crate::types::extract::Error) type is provided for ergonomic error conversions\n/// from most error types using the `?` operator.\n///\n/// ```\n/// use neon::types::extract::Error;\n///\n/// #[neon::export]\n/// fn read_file(path: String) -> Result<String, Error> {\n///     let contents = std::fs::read_to_string(path)?;\n///     Ok(contents)\n/// }\n/// ```\n///\n/// ### Interact with the JavaScript runtime\n///\n/// More complex functions may need to interact directly with the JavaScript runtime,\n/// for example with [`Context`](crate::context::Context) or handles to JavaScript values.\n///\n/// Functions may optionally include a [`Cx`](crate::context::Cx) or\n/// [`FunctionContext`](crate::context::FunctionContext) argument. Note that unlike functions\n/// created with [`JsFunction::new`](crate::types::JsFunction), exported function receive a borrowed\n/// context and may require explicit lifetimes.\n///\n/// ```\n/// # use neon::prelude::*;\n/// #[neon::export]\n/// fn add<'cx>(\n///     cx: &mut Cx<'cx>,\n///     a: Handle<JsNumber>,\n///     b: Handle<JsNumber>,\n/// ) -> JsResult<'cx, JsNumber> {\n///     let a = a.value(cx);\n///     let b = b.value(cx);\n///\n///     Ok(cx.number(a + b))\n/// }\n/// ```\n///\n/// ### Classes\n///\n/// The `#[neon::export(class)]` attribute may be used on an `impl` block to\n/// combine class definition with automatic export. See the documentation for\n/// [`#[neon::class]`](crate::class) for more details.\n///\n/// ### Advanced\n///\n/// The following attributes are for advanced configuration and may not be\n/// necessary for most users.\n///\n/// #### `context`\n///\n/// The `#[neon::export]` uses a heuristic to determine if the first argument\n/// to a function is a _context_ argument.\n///\n/// * In a function executed on the JavaScript main thread, it looks for `&mut Cx`\n///   or `&mut FunctionContext` to determine if the [`Context`](crate::context::Context)\n///   should be passed.\n/// * In a function executed on another thread, it looks for [`Channel`](crate::event::Channel).\n///\n/// If the type has been renamed when importing, the `context` attribute can be\n/// added to force it to be passed.\n///\n/// ```\n/// use neon::event::Channel as Ch;\n/// use neon::context::FunctionContext as FnCtx;\n///\n/// #[neon::export(context)]\n/// fn add(_cx: &mut FnCtx, a: f64, b: f64) -> f64 {\n///     a + b\n/// }\n///\n/// #[neon::export(context)]\n/// async fn div(_ch: Ch, a: f64, b: f64) -> f64 {\n///     a / b\n/// }\n/// ```\n///\n/// #### `this`\n///\n/// The `#[neon::export]` uses a heuristic to determine if an argument to this function is\n/// referring to [`this`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this).\n///\n/// 1. If the first argument is a [context](#context), use the 0th argument, otherwise use the 1st.\n/// 2. If the argument binding is named `this`\n/// 3. Or if it is a tuple struct pattern with an element named `this`\n///\n/// ```\n/// use neon::types::extract::Boxed;\n///\n/// #[neon::export]\n/// fn buffer_clone(this: Vec<u8>) -> Vec<u8> {\n///     this\n/// }\n///\n/// #[neon::export]\n/// fn box_to_string(Boxed(this): Boxed<String>) -> String {\n///     this\n/// }\n/// ```\n///\n/// If the function uses a variable name other than `this`, the `this` attribute may\n/// be added.\n///\n/// ```\n/// #[neon::export(this)]\n/// fn buffer_clone(me: Vec<u8>) -> Vec<u8> {\n///     me\n/// }\n/// ```\npub use neon_macros::export;\n"
  },
  {
    "path": "crates/neon/src/meta.rs",
    "content": "//! Metadata about the Neon version and build.\n\nuse semver::Version;\n\n/// The Neon version.\npub const VERSION: &str = env!(\"CARGO_PKG_VERSION\");\n\n/// The Neon major version.\npub const MAJOR: &str = env!(\"CARGO_PKG_VERSION_MAJOR\");\n\n/// The Neon minor version.\npub const MINOR: &str = env!(\"CARGO_PKG_VERSION_MINOR\");\n\n/// The Neon patch version.\npub const PATCH: &str = env!(\"CARGO_PKG_VERSION_PATCH\");\n\n/// Produces a `semver::Version` data structure representing the Neon version.\npub fn version() -> Version {\n    Version {\n        major: MAJOR.parse().unwrap(),\n        minor: MINOR.parse().unwrap(),\n        patch: PATCH.parse().unwrap(),\n        pre: Default::default(),\n        build: Default::default(),\n    }\n}\n"
  },
  {
    "path": "crates/neon/src/object/class.rs",
    "content": "use crate::{\n    context::Cx,\n    handle::{Handle, Root},\n    object::Object,\n    result::{JsResult, NeonResult},\n    types::JsFunction,\n};\n\n#[doc(hidden)]\npub trait ClassInternal {\n    fn local<'cx>(cx: &mut Cx<'cx>) -> NeonResult<ClassMetadata<'cx>>;\n    fn create<'cx>(cx: &mut Cx<'cx>) -> NeonResult<ClassMetadata<'cx>>;\n}\n\n/// A trait defining a Neon class.\n///\n/// **This should not be implemented directly.** Instead, use the [`#[neon::class]`](crate::class)\n/// attribute macro to define a class, which will automatically implement this trait.\npub trait Class: ClassInternal {\n    /// The class name.\n    fn name() -> String;\n\n    /// The constructor function for the class.\n    fn constructor<'cx>(cx: &mut Cx<'cx>) -> JsResult<'cx, JsFunction>;\n}\n\n#[doc(hidden)]\npub struct ClassMetadata<'cx> {\n    external_constructor: Handle<'cx, JsFunction>,\n    internal_constructor: Handle<'cx, JsFunction>,\n}\n\npub fn new_class_metadata<'cx>(\n    external: Handle<'cx, JsFunction>,\n    internal: Handle<'cx, JsFunction>,\n) -> ClassMetadata<'cx> {\n    ClassMetadata {\n        external_constructor: external,\n        internal_constructor: internal,\n    }\n}\n\nimpl<'cx> ClassMetadata<'cx> {\n    pub fn constructor(&self) -> Handle<'cx, JsFunction> {\n        self.external_constructor\n    }\n\n    pub(crate) fn internal_constructor(&self) -> Handle<'cx, JsFunction> {\n        self.internal_constructor\n    }\n\n    #[doc(hidden)]\n    pub fn root<'cx2>(&self, cx: &mut Cx<'cx2>) -> RootClassMetadata {\n        RootClassMetadata {\n            external_constructor: self.external_constructor.root(cx),\n            internal_constructor: self.internal_constructor.root(cx),\n        }\n    }\n}\n\n#[doc(hidden)]\npub struct RootClassMetadata {\n    pub external_constructor: Root<JsFunction>,\n    pub internal_constructor: Root<JsFunction>,\n}\n\n// Since it's just a pair of Root which are both Send, we can mark it as such.\nunsafe impl Send for RootClassMetadata {}\n\nimpl RootClassMetadata {\n    pub fn to_inner<'a, 'cx: 'a>(&'a self, cx: &'a mut Cx<'cx>) -> ClassMetadata<'cx> {\n        ClassMetadata {\n            external_constructor: self.external_constructor.to_inner(cx),\n            internal_constructor: self.internal_constructor.to_inner(cx),\n        }\n    }\n}\n"
  },
  {
    "path": "crates/neon/src/object/mod.rs",
    "content": "//! Traits for working with JavaScript objects.\n//!\n//! This module defines the [`Object`] trait, which is implemented\n//! by all object types in the [JavaScript type hierarchy][hierarchy]. This\n//! trait provides key operations in the semantics of JavaScript objects,\n//! such as getting and setting an object's properties.\n//!\n//! ## Property Keys\n//!\n//! Object properties are accessed by a _property key_, which in JavaScript\n//! can be a string or [symbol][symbol]. (Neon does not yet have support for\n//! symbols.) For convenience, the [`PropertyKey`] trait allows\n//! Neon programs to use various Rust string types, as well as numeric types,\n//! as keys when accessing object properties, converting the keys to strings\n//! as necessary:\n//!\n//! ```\n//! # use neon::prelude::*;\n//! fn set_and_check<'cx>(\n//!     cx: &mut Cx<'cx>,\n//!     obj: Handle<'cx, JsObject>\n//! ) -> JsResult<'cx, JsValue> {\n//!     // set property \"17\" with integer shorthand\n//!     obj.prop(cx, 17).set(\"hello\")?;\n//!     // get property \"17\" with string shorthand\n//!     // returns the same value (\"hello!\")\n//!     obj.prop(cx, \"17\").get()\n//! }\n//! ```\n//!\n//! [hierarchy]: crate::types#the-javascript-type-hierarchy\n//! [symbol]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol\n\nuse smallvec::smallvec;\n\nuse crate::{\n    context::{internal::ContextInternal, Context, Cx},\n    handle::{Handle, Root},\n    result::{NeonResult, Throw},\n    sys::{self, raw},\n    types::{\n        build,\n        extract::{TryFromJs, TryIntoJs},\n        function::{BindOptions, CallOptions},\n        private::ValueInternal,\n        utf8::Utf8,\n        JsFunction, JsUndefined, JsValue, Value,\n    },\n};\n\n#[cfg(feature = \"napi-6\")]\nuse crate::{result::JsResult, types::JsArray};\n\n#[cfg(feature = \"napi-6\")]\npub use self::class::Class;\n\n#[doc(hidden)]\npub use self::wrap::{unwrap, wrap};\n\n#[cfg(feature = \"napi-6\")]\npub(crate) mod class;\npub(crate) mod wrap;\n\n/// A property key in a JavaScript object.\npub trait PropertyKey: Copy {\n    unsafe fn get_from<'c, C: Context<'c>>(\n        self,\n        cx: &mut C,\n        out: &mut raw::Local,\n        obj: raw::Local,\n    ) -> bool;\n\n    unsafe fn set_from<'c, C: Context<'c>>(\n        self,\n        cx: &mut C,\n        out: &mut bool,\n        obj: raw::Local,\n        val: raw::Local,\n    ) -> bool;\n}\n\nimpl PropertyKey for u32 {\n    unsafe fn get_from<'c, C: Context<'c>>(\n        self,\n        cx: &mut C,\n        out: &mut raw::Local,\n        obj: raw::Local,\n    ) -> bool {\n        sys::object::get_index(out, cx.env().to_raw(), obj, self)\n    }\n\n    unsafe fn set_from<'c, C: Context<'c>>(\n        self,\n        cx: &mut C,\n        out: &mut bool,\n        obj: raw::Local,\n        val: raw::Local,\n    ) -> bool {\n        sys::object::set_index(out, cx.env().to_raw(), obj, self, val)\n    }\n}\n\nimpl<'a, K: Value> PropertyKey for Handle<'a, K> {\n    unsafe fn get_from<'c, C: Context<'c>>(\n        self,\n        cx: &mut C,\n        out: &mut raw::Local,\n        obj: raw::Local,\n    ) -> bool {\n        let env = cx.env().to_raw();\n\n        sys::object::get(out, env, obj, self.to_local())\n    }\n\n    unsafe fn set_from<'c, C: Context<'c>>(\n        self,\n        cx: &mut C,\n        out: &mut bool,\n        obj: raw::Local,\n        val: raw::Local,\n    ) -> bool {\n        let env = cx.env().to_raw();\n\n        sys::object::set(out, env, obj, self.to_local(), val)\n    }\n}\n\nimpl PropertyKey for &str {\n    unsafe fn get_from<'c, C: Context<'c>>(\n        self,\n        cx: &mut C,\n        out: &mut raw::Local,\n        obj: raw::Local,\n    ) -> bool {\n        let (ptr, len) = Utf8::from(self).into_small_unwrap().lower();\n        let env = cx.env().to_raw();\n\n        sys::object::get_string(env, out, obj, ptr, len)\n    }\n\n    unsafe fn set_from<'c, C: Context<'c>>(\n        self,\n        cx: &mut C,\n        out: &mut bool,\n        obj: raw::Local,\n        val: raw::Local,\n    ) -> bool {\n        let (ptr, len) = Utf8::from(self).into_small_unwrap().lower();\n        let env = cx.env().to_raw();\n\n        sys::object::set_string(env, out, obj, ptr, len, val)\n    }\n}\n\n/// A builder for accessing an object property.\n///\n/// The builder methods make it convenient to get and set properties\n/// as well as to bind and call methods.\n/// ```\n/// # use neon::prelude::*;\n/// # fn foo(mut cx: FunctionContext) -> JsResult<JsString> {\n/// # let obj: Handle<JsObject> = cx.argument(0)?;\n/// let x: f64 = obj\n///     .prop(&mut cx, \"x\")\n///     .get()?;\n///\n/// obj.prop(&mut cx, \"y\")\n///     .set(x)?;\n///\n/// let s: String = obj.method(&mut cx, \"toString\")?.call()?;\n/// # Ok(cx.string(s))\n/// # }\n/// ```\npub struct PropOptions<'a, 'cx, O, K>\nwhere\n    'cx: 'a,\n    O: Object,\n    K: PropertyKey,\n{\n    pub(crate) cx: &'a mut Cx<'cx>,\n    pub(crate) this: Handle<'cx, O>,\n    pub(crate) key: K,\n}\n\nimpl<'a, 'cx, O, K> PropOptions<'a, 'cx, O, K>\nwhere\n    'cx: 'a,\n    O: Object,\n    K: PropertyKey,\n{\n    /// Returns the original object from which the property was accessed.\n    pub fn this(&self) -> Handle<'cx, O> {\n        self.this\n    }\n\n    /// Updates the property key.\n    ///\n    /// This method is useful for chaining multiple property assignments:\n    ///\n    /// ```\n    /// # use neon::prelude::*;\n    /// # fn foo(mut cx: FunctionContext) -> JsResult<JsObject> {\n    /// let obj = cx.empty_object()\n    ///     .prop(&mut cx, \"x\")\n    ///     .set(1)?\n    ///     .prop(\"y\")\n    ///     .set(2)?\n    ///     .prop(\"color\")\n    ///     .set(\"blue\")?\n    ///     .this();\n    /// # Ok(obj)\n    /// # }\n    /// ```\n    pub fn prop(&mut self, key: K) -> &mut Self {\n        self.key = key;\n        self\n    }\n\n    /// Gets the property from the object and attempts to convert it to a Rust value.\n    ///\n    /// May throw an exception either during accessing the property or converting the\n    /// result type.\n    pub fn get<R: TryFromJs<'cx>>(&mut self) -> NeonResult<R> {\n        let v = self.this.get_value(self.cx, self.key)?;\n        R::from_js(self.cx, v)\n    }\n\n    /// Sets the property on the object to a value converted from Rust.\n    ///\n    /// May throw an exception either during converting the value or setting the property.\n    pub fn set<V: TryIntoJs<'cx>>(&mut self, v: V) -> NeonResult<&mut Self> {\n        let v = v.try_into_js(self.cx)?;\n        self.this.set(self.cx, self.key, v)?;\n        Ok(self)\n    }\n\n    /// Sets the property on the object to a value computed from a closure.\n    ///\n    /// May throw an exception either during converting the value or setting the property.\n    pub fn set_with<R, F>(&mut self, f: F) -> NeonResult<&mut Self>\n    where\n        R: TryIntoJs<'cx>,\n        F: FnOnce(&mut Cx<'cx>) -> R,\n    {\n        let v = f(self.cx).try_into_js(self.cx)?;\n        self.this.set(self.cx, self.key, v)?;\n        Ok(self)\n    }\n\n    /// Gets the property from the object as a method and binds `this` to the object.\n    ///\n    /// May throw an exception when accessing the property.\n    ///\n    /// Defers checking that the method is callable until call time.\n    pub fn bind(&'a mut self) -> NeonResult<BindOptions<'a, 'cx>> {\n        let callee: Handle<JsValue> = self.this.get(self.cx, self.key)?;\n        let this = Some(self.this.upcast());\n        Ok(BindOptions {\n            cx: self.cx,\n            callee,\n            this,\n            args: smallvec![],\n        })\n    }\n}\n\n/// The trait of all object types.\npub trait Object: Value {\n    /// Create a [`PropOptions`] for accessing a property.\n    ///\n    /// # Safety\n    ///\n    /// Because `cx` is a mutable reference, Neon guarantees it\n    /// is the context with the shortest possible lifetime, so\n    /// replacing the lifetime `'self` with `'cx` cannot extend\n    /// the lifetime of the property beyond the lifetime of the\n    /// object.\n    fn prop<'a, 'cx: 'a, K: PropertyKey>(\n        &self,\n        cx: &'a mut Cx<'cx>,\n        key: K,\n    ) -> PropOptions<'a, 'cx, Self, K> {\n        let this: Handle<'_, Self> =\n            Handle::new_internal(unsafe { ValueInternal::from_local(cx.env(), self.to_local()) });\n        PropOptions { cx, this, key }\n    }\n\n    /// Gets a property from the object as a method and binds `this` to the object.\n    ///\n    /// May throw an exception either from accessing the property.\n    ///\n    /// Defers checking that the method is callable until call time.\n    fn method<'a, 'cx: 'a, K: PropertyKey>(\n        &self,\n        cx: &'a mut Cx<'cx>,\n        key: K,\n    ) -> NeonResult<BindOptions<'a, 'cx>> {\n        let callee: Handle<JsValue> = self.prop(cx, key).get()?;\n        let this = Some(self.as_value(cx));\n        Ok(BindOptions {\n            cx,\n            callee,\n            this,\n            args: smallvec![],\n        })\n    }\n\n    #[deprecated(since = \"TBD\", note = \"use `Object::prop()` instead\")]\n    fn get_opt<'a, V: Value, C: Context<'a>, K: PropertyKey>(\n        &self,\n        cx: &mut C,\n        key: K,\n    ) -> NeonResult<Option<Handle<'a, V>>> {\n        let v = self.get_value(cx, key)?;\n\n        if v.is_a::<JsUndefined, _>(cx) {\n            return Ok(None);\n        }\n\n        v.downcast_or_throw(cx).map(Some)\n    }\n\n    #[deprecated(since = \"TBD\", note = \"use `Object::prop()` instead\")]\n    fn get_value<'a, C: Context<'a>, K: PropertyKey>(\n        &self,\n        cx: &mut C,\n        key: K,\n    ) -> NeonResult<Handle<'a, JsValue>> {\n        build(cx.env(), |out| unsafe {\n            key.get_from(cx, out, self.to_local())\n        })\n    }\n\n    #[deprecated(since = \"TBD\", note = \"use `Object::prop()` instead\")]\n    fn get<'a, V: Value, C: Context<'a>, K: PropertyKey>(\n        &self,\n        cx: &mut C,\n        key: K,\n    ) -> NeonResult<Handle<'a, V>> {\n        self.get_value(cx, key)?.downcast_or_throw(cx)\n    }\n\n    #[cfg(feature = \"napi-6\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"napi-6\")))]\n    fn get_own_property_names<'a, C: Context<'a>>(&self, cx: &mut C) -> JsResult<'a, JsArray> {\n        let env = cx.env();\n\n        build(cx.env(), |out| unsafe {\n            sys::object::get_own_property_names(out, env.to_raw(), self.to_local())\n        })\n    }\n\n    #[cfg(feature = \"napi-8\")]\n    fn freeze<'a, C: Context<'a>>(&self, cx: &mut C) -> NeonResult<&Self> {\n        let env = cx.env().to_raw();\n        let obj = self.to_local();\n        unsafe {\n            match sys::object::freeze(env, obj) {\n                Ok(()) => Ok(self),\n                Err(sys::Status::PendingException) => Err(Throw::new()),\n                _ => cx.throw_type_error(\"object cannot be frozen\"),\n            }\n        }\n    }\n\n    #[cfg(feature = \"napi-8\")]\n    fn seal<'a, C: Context<'a>>(&self, cx: &mut C) -> NeonResult<&Self> {\n        let env = cx.env().to_raw();\n        let obj = self.to_local();\n        unsafe {\n            match sys::object::seal(env, obj) {\n                Ok(()) => Ok(self),\n                Err(sys::Status::PendingException) => Err(Throw::new()),\n                _ => cx.throw_type_error(\"object cannot be sealed\"),\n            }\n        }\n    }\n\n    #[deprecated(since = \"TBD\", note = \"use `Object::prop()` instead\")]\n    fn set<'a, C: Context<'a>, K: PropertyKey, W: Value>(\n        &self,\n        cx: &mut C,\n        key: K,\n        val: Handle<W>,\n    ) -> NeonResult<bool> {\n        let mut result = false;\n        unsafe {\n            if key.set_from(cx, &mut result, self.to_local(), val.to_local()) {\n                Ok(result)\n            } else {\n                Err(Throw::new())\n            }\n        }\n    }\n\n    fn root<'a, C: Context<'a>>(&self, cx: &mut C) -> Root<Self> {\n        Root::new(cx, self)\n    }\n\n    #[deprecated(since = \"TBD\", note = \"use `Object::method()` instead\")]\n    fn call_method_with<'a, C, K>(&self, cx: &mut C, method: K) -> NeonResult<CallOptions<'a>>\n    where\n        C: Context<'a>,\n        K: PropertyKey,\n    {\n        let mut options = self.get::<JsFunction, _, _>(cx, method)?.call_with(cx);\n        options.this(JsValue::new_internal(self.to_local()));\n        Ok(options)\n    }\n}\n"
  },
  {
    "path": "crates/neon/src/object/wrap.rs",
    "content": "use std::{any::Any, error, ffi::c_void, fmt, mem::MaybeUninit, ptr};\n\nuse crate::{\n    context::{\n        internal::{ContextInternal, Env},\n        Context, Cx,\n    },\n    handle::Handle,\n    object::Object,\n    result::{JsResult, NeonResult, ResultExt, Throw},\n    sys,\n    types::{extract::TryIntoJs, Finalize, Value},\n};\n\ntype BoxAny = Box<dyn Any + 'static>;\n\n#[derive(Debug)]\npub struct WrapError(WrapErrorType);\n\nimpl WrapError {\n    fn object_expected() -> Self {\n        Self(WrapErrorType::ObjectExpected)\n    }\n\n    fn already_wrapped() -> Self {\n        Self(WrapErrorType::AlreadyWrapped)\n    }\n\n    #[cfg(feature = \"napi-8\")]\n    fn not_wrapped() -> Self {\n        Self(WrapErrorType::NotWrapped)\n    }\n\n    fn wrong_type(expected: &'static str) -> Self {\n        Self(WrapErrorType::WrongType(expected))\n    }\n\n    #[cfg(feature = \"napi-8\")]\n    fn foreign_type() -> Self {\n        Self(WrapErrorType::ForeignType)\n    }\n}\n\nimpl fmt::Display for WrapError {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(f, \"{}\", self.0)\n    }\n}\n\nimpl error::Error for WrapError {}\n\nimpl crate::types::extract::private::Sealed for WrapError {}\n\nimpl<'cx> TryIntoJs<'cx> for WrapError {\n    type Value = crate::types::JsError;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        match self.0 {\n            WrapErrorType::ObjectExpected => cx.type_error(\"object expected\"),\n            _ => cx.type_error(self.to_string()),\n        }\n    }\n}\n\nimpl<T> ResultExt<T> for Result<T, WrapError> {\n    fn or_throw<'cx, C>(self, cx: &mut C) -> NeonResult<T>\n    where\n        C: Context<'cx>,\n    {\n        match self {\n            Ok(v) => Ok(v),\n            Err(WrapError(WrapErrorType::ObjectExpected)) => cx.throw_type_error(\"object expected\"),\n            Err(err) => cx.throw_type_error(err.to_string()),\n        }\n    }\n}\n\n#[derive(Debug)]\nenum WrapErrorType {\n    ObjectExpected,\n    AlreadyWrapped,\n    #[cfg(feature = \"napi-8\")]\n    NotWrapped,\n    WrongType(&'static str),\n    #[cfg(feature = \"napi-8\")]\n    ForeignType,\n}\n\nfn ref_cell_target_type_name(s: &str) -> Option<String> {\n    if let Some(start) = s.find('<') {\n        let s = &s[start + 1..];\n        if let Some(end) = s.find('>') {\n            return Some(s[0..end].to_string());\n        }\n    }\n    None\n}\n\nimpl fmt::Display for WrapErrorType {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        match self {\n            Self::ObjectExpected => write!(f, \"object expected\"),\n            Self::AlreadyWrapped => write!(f, \"non-class instance expected\"),\n            #[cfg(feature = \"napi-8\")]\n            Self::NotWrapped => write!(f, \"class instance expected\"),\n            Self::WrongType(expected) => {\n                let target_type_name =\n                    ref_cell_target_type_name(expected).unwrap_or(expected.to_string());\n                write!(f, \"expected instance of {}\", target_type_name)\n            }\n            #[cfg(feature = \"napi-8\")]\n            Self::ForeignType => write!(f, \"Neon object expected\"),\n        }\n    }\n}\n\npub fn wrap<T, V>(cx: &mut Cx, o: Handle<V>, v: T) -> NeonResult<Result<(), WrapError>>\nwhere\n    T: Finalize + 'static,\n    V: Object,\n{\n    let env = cx.env().to_raw();\n    let o = o.to_local();\n    let v = Box::into_raw(Box::new(Box::new(v) as BoxAny));\n\n    // # Safety\n    // The `finalize` function will be called when the JavaScript object is garbage\n    // collected. The `data` pointer is guaranteed to be the same pointer passed when\n    // wrapping.\n    unsafe extern \"C\" fn finalize<T>(env: sys::Env, data: *mut c_void, _hint: *mut c_void)\n    where\n        T: Finalize + 'static,\n    {\n        let data = Box::from_raw(data.cast::<BoxAny>());\n        let data = *data.downcast::<T>().unwrap();\n        let env = Env::from(env);\n\n        Cx::with_context(env, move |mut cx| data.finalize(&mut cx));\n    }\n\n    // # Safety\n    // The `env` value was obtained from a valid `Cx` and the `o` handle has\n    // already been verified to be an object.\n    unsafe {\n        match sys::wrap(\n            env,\n            o,\n            v.cast(),\n            Some(finalize::<T>),\n            ptr::null_mut(),\n            ptr::null_mut(),\n        ) {\n            Err(sys::Status::InvalidArg) => {\n                // Wrap failed, we can safely free the value\n                let _ = Box::from_raw(v);\n\n                return Ok(Err(WrapError::already_wrapped()));\n            }\n            Err(sys::Status::PendingException) => {\n                // Wrap failed, we can safely free the value\n                let _ = Box::from_raw(v);\n\n                return Err(Throw::new());\n            }\n            // If an unexpected error occurs, we cannot safely free the value\n            // because `finalize` may be called later.\n            res => res.unwrap(),\n        }\n\n        #[cfg(feature = \"napi-8\")]\n        match sys::type_tag_object(env, o, &*crate::MODULE_TAG) {\n            Err(sys::Status::InvalidArg) => {\n                sys::remove_wrap(env, o, ptr::null_mut()).unwrap();\n\n                // Unwrap succeeded, we can safely free the value\n                let _ = Box::from_raw(v);\n\n                return Ok(Err(WrapError::foreign_type()));\n            }\n            res => res.unwrap(),\n        }\n    }\n\n    Ok(Ok(()))\n}\n\npub fn unwrap<'cx, T, V>(cx: &mut Cx, o: Handle<'cx, V>) -> NeonResult<Result<&'cx T, WrapError>>\nwhere\n    T: Finalize + 'static,\n    V: Value,\n{\n    let env = cx.env().to_raw();\n    let o = o.to_local();\n\n    #[cfg(feature = \"napi-8\")]\n    // # Safety\n    // The `env` value was obtained from a valid `Cx`.\n    unsafe {\n        let mut is_tagged = false;\n\n        match sys::check_object_type_tag(env, o, &*crate::MODULE_TAG, &mut is_tagged) {\n            Err(sys::Status::PendingException) => return Err(Throw::new()),\n            Err(sys::Status::ObjectExpected) => return Ok(Err(WrapError::object_expected())),\n            res => res.unwrap(),\n        }\n\n        if !is_tagged {\n            return Ok(Err(WrapError::not_wrapped()));\n        }\n    }\n\n    // # Safety\n    // The `env` value was obtained from a valid `Cx`.\n    let data = unsafe {\n        let mut data = MaybeUninit::<*mut BoxAny>::uninit();\n\n        match sys::unwrap(env, o, data.as_mut_ptr().cast()) {\n            Err(sys::Status::PendingException) => return Err(Throw::new()),\n            Err(sys::Status::ObjectExpected) => return Ok(Err(WrapError::object_expected())),\n            res => res.unwrap(),\n        }\n\n        // # Safety\n        // Since `unwrap` was successful, we know this is a valid pointer. On Node-API\n        // versions 8 and higher, we are also guaranteed it is a `BoxAny`.\n        &*data.assume_init()\n    };\n\n    match data.downcast_ref() {\n        Some(result) => Ok(Ok(result)),\n        None => Ok(Err(WrapError::wrong_type(std::any::type_name::<T>()))),\n    }\n}\n"
  },
  {
    "path": "crates/neon/src/prelude.rs",
    "content": "//! Convenience module for the most common Neon imports.\n\n#[doc(no_inline)]\npub use crate::{\n    context::{CallKind, Context, Cx, FunctionContext, ModuleContext},\n    handle::{Handle, Root},\n    object::Object,\n    result::{JsResult, NeonResult, ResultExt as NeonResultExt},\n    types::{\n        boxed::{Finalize, JsBox},\n        JsArray, JsArrayBuffer, JsBigInt64Array, JsBigUint64Array, JsBoolean, JsBuffer, JsError,\n        JsFloat32Array, JsFloat64Array, JsFunction, JsInt16Array, JsInt32Array, JsInt8Array,\n        JsNull, JsNumber, JsObject, JsPromise, JsString, JsTypedArray, JsUint16Array,\n        JsUint32Array, JsUint8Array, JsUndefined, JsValue, Value,\n    },\n};\n\n#[doc(hidden)]\npub use crate::context::{ComputeContext, ExecuteContext, TaskContext};\n\n#[cfg(feature = \"napi-4\")]\n#[doc(no_inline)]\npub use crate::event::{Channel, SendError};\n\n#[cfg(feature = \"napi-4\")]\n#[doc(no_inline)]\n#[allow(deprecated)]\npub use crate::event::{EventQueue, EventQueueError};\n"
  },
  {
    "path": "crates/neon/src/reflect.rs",
    "content": "//! Exposes JavaScript's reflection API to Rust.\n\nuse crate::{\n    context::Context,\n    handle::Handle,\n    result::JsResult,\n    types::{build, private::ValueInternal, JsString, JsValue},\n};\n\npub fn eval<'a, 'b, C: Context<'a>>(\n    cx: &mut C,\n    script: Handle<'b, JsString>,\n) -> JsResult<'a, JsValue> {\n    let env = cx.env().to_raw();\n    build(cx.env(), |out| unsafe {\n        crate::sys::string::run_script(out, env, script.to_local())\n    })\n}\n"
  },
  {
    "path": "crates/neon/src/result/mod.rs",
    "content": "//! Represents JavaScript exceptions as a Rust [`Result`](std::result) type.\n//!\n//! Most interactions with the JavaScript engine can throw a JavaScript exception. Neon APIs\n//! that can throw an exception are called _throwing APIs_ and return the type\n//! [`NeonResult`] (or its shorthand [`JsResult`]).\n//!\n//! When a throwing API triggers a JavaScript exception, it returns an [Err]\n//! result. This indicates that the thread associated with the [`Context`]\n//! is now throwing, and allows Rust code to perform any cleanup. See the\n//! [`neon::context`](crate::context) module documentation for more about\n//! [contexts and exceptions](crate::context#throwing-exceptions).\n//!\n//! Typically, Neon code can manage JavaScript exceptions correctly and conveniently by\n//! using Rust's [question mark (`?`)][question-mark] operator. This ensures that Rust code\n//! \"short-circuits\" when an exception is thrown and returns back to JavaScript without\n//! calling any throwing APIs.\n//!\n//! ## Example\n//!\n//! Neon functions typically use [`JsResult`] for their return type. This\n//! example defines a function that extracts a property called `\"message\"` from an object,\n//! throwing an exception if the argument is not of the right type or extracting the property\n//! fails:\n//!\n//! ```\n//! # use neon::prelude::*;\n//! fn get_message(mut cx: FunctionContext) -> JsResult<JsValue> {\n//!     let obj: Handle<JsObject> = cx.argument(0)?;\n//!     obj.prop(&mut cx, \"message\").get()\n//! }\n//! ```\n//!\n//! [question-mark]: https://doc.rust-lang.org/edition-guide/rust-2018/error-handling-and-panics/the-question-mark-operator-for-easier-error-handling.html\n\nuse std::{\n    fmt::{Display, Formatter, Result as FmtResult},\n    marker::PhantomData,\n};\n\nuse crate::{context::Context, handle::Handle, types::Value};\n\n/// A [unit type][unit] indicating that the JavaScript thread is throwing an exception.\n///\n/// `Throw` deliberately does not implement [`std::error::Error`]. It's\n/// not recommended to chain JavaScript exceptions with other kinds of Rust errors,\n/// since throwing means that the JavaScript thread is unavailable until the exception\n/// is handled.\n///\n/// [unit]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#unit-like-structs-without-any-fields\n#[derive(Debug)]\npub struct Throw(PhantomData<*mut ()>); // *mut is !Send + !Sync, making it harder to accidentally store\n\nimpl Throw {\n    #[cfg(feature = \"sys\")]\n    /// Creates a `Throw` struct representing a JavaScript exception\n    /// state.\n    ///\n    /// # Safety\n    ///\n    /// `Throw` should *only* be constructed when the JavaScript VM is in a\n    /// throwing state. I.e., when [`Status::PendingException`](crate::sys::bindings::Status::PendingException)\n    /// is returned.\n    pub unsafe fn new() -> Self {\n        Self(PhantomData)\n    }\n\n    #[cfg(not(feature = \"sys\"))]\n    pub(crate) unsafe fn new() -> Self {\n        Self(PhantomData)\n    }\n}\n\nimpl Display for Throw {\n    fn fmt(&self, fmt: &mut Formatter) -> FmtResult {\n        fmt.write_str(\"JavaScript Error\")\n    }\n}\n\n/// The result type for throwing APIs.\npub type NeonResult<T> = Result<T, Throw>;\n\n/// Shorthand for a [`NeonResult`] that produces JavaScript values.\npub type JsResult<'b, T> = NeonResult<Handle<'b, T>>;\n\n/// Extension trait for converting Rust [`Result`] values\n/// into [`NeonResult`] values by throwing JavaScript exceptions.\npub trait ResultExt<T> {\n    fn or_throw<'a, C: Context<'a>>(self, cx: &mut C) -> NeonResult<T>;\n}\n\nimpl<'a, 'b, T, E> ResultExt<Handle<'a, T>> for Result<Handle<'a, T>, Handle<'b, E>>\nwhere\n    T: Value,\n    E: Value,\n{\n    fn or_throw<'cx, C: Context<'cx>>(self, cx: &mut C) -> JsResult<'a, T> {\n        self.or_else(|err| cx.throw(err))\n    }\n}\n"
  },
  {
    "path": "crates/neon/src/sys/array.rs",
    "content": "//! Facilities for working with Array `napi_value`s.\n\nuse super::{\n    bindings as napi,\n    raw::{Env, Local},\n};\n\npub unsafe fn new(out: &mut Local, env: Env, length: usize) {\n    napi::create_array_with_length(env, length, out as *mut _).unwrap();\n}\n\n/// Gets the length of a `napi_value` containing a JavaScript Array.\n///\n/// # Panics\n/// This function panics if `array` is not an Array, or if a previous n-api call caused a pending\n/// exception.\npub unsafe fn len(env: Env, array: Local) -> u32 {\n    let mut len = 0;\n    napi::get_array_length(env, array, &mut len as *mut _).unwrap();\n    len\n}\n"
  },
  {
    "path": "crates/neon/src/sys/arraybuffer.rs",
    "content": "#[cfg(feature = \"external-buffers\")]\nuse std::os::raw::c_void;\nuse std::{mem::MaybeUninit, ptr::null_mut, slice};\n\nuse super::{\n    bindings as napi,\n    raw::{Env, Local},\n};\n\npub unsafe fn new(env: Env, len: usize) -> Result<Local, napi::Status> {\n    let mut buf = MaybeUninit::uninit();\n    let status = napi::create_arraybuffer(env, len, null_mut(), buf.as_mut_ptr());\n\n    match status {\n        Err(err @ napi::Status::PendingException) => return Err(err),\n        status => status.unwrap(),\n    };\n\n    Ok(buf.assume_init())\n}\n\n#[cfg(feature = \"external-buffers\")]\npub unsafe fn new_external<T>(env: Env, data: T) -> Local\nwhere\n    T: AsMut<[u8]> + Send,\n{\n    // Safety: Boxing could move the data; must box before grabbing a raw pointer\n    let mut data = Box::new(data);\n    let buf = data.as_mut().as_mut();\n    let length = buf.len();\n    let mut result = MaybeUninit::uninit();\n\n    napi::create_external_arraybuffer(\n        env,\n        buf.as_mut_ptr() as *mut _,\n        length,\n        Some(drop_external::<T>),\n        Box::into_raw(data) as *mut _,\n        result.as_mut_ptr(),\n    )\n    .unwrap();\n\n    result.assume_init()\n}\n\n#[cfg(feature = \"external-buffers\")]\nunsafe extern \"C\" fn drop_external<T>(_env: Env, _data: *mut c_void, hint: *mut c_void) {\n    drop(Box::<T>::from_raw(hint as *mut _));\n}\n\n/// # Safety\n/// * Caller must ensure `env` and `buf` are valid\n/// * The lifetime `'a` does not exceed the lifetime of `Env` or `buf`\npub unsafe fn as_mut_slice<'a>(env: Env, buf: Local) -> &'a mut [u8] {\n    let mut data = MaybeUninit::uninit();\n    let mut size = 0usize;\n\n    napi::get_arraybuffer_info(env, buf, data.as_mut_ptr(), &mut size as *mut _).unwrap();\n\n    if size == 0 {\n        return &mut [];\n    }\n\n    slice::from_raw_parts_mut(data.assume_init().cast(), size)\n}\n\n/// # Safety\n/// * Caller must ensure `env` and `buf` are valid\npub unsafe fn size(env: Env, buf: Local) -> usize {\n    let mut data = MaybeUninit::uninit();\n    let mut size = 0usize;\n\n    napi::get_arraybuffer_info(env, buf, data.as_mut_ptr(), &mut size as *mut _).unwrap();\n\n    size\n}\n"
  },
  {
    "path": "crates/neon/src/sys/async_work.rs",
    "content": "//! Rust wrappers for Node-API simple asynchronous operations\n//!\n//! Unlike `napi_async_work` which threads a single mutable pointer to a data\n//! struct to both the `execute` and `complete` callbacks, the wrapper follows\n//! a more idiomatic Rust ownership pattern by passing the output of `execute`\n//! into the input of `complete`.\n//!\n//! See: [Async operations in Node-API](https://nodejs.org/api/n-api.html#n_api_simple_asynchronous_operations)\n\nuse std::{\n    ffi::c_void,\n    mem,\n    panic::{catch_unwind, resume_unwind, AssertUnwindSafe},\n    ptr, thread,\n};\n\nuse super::{\n    bindings as napi, debug_send_wrapper::DebugSendWrapper, no_panic::FailureBoundary, raw::Env,\n};\n\nconst BOUNDARY: FailureBoundary = FailureBoundary {\n    both: \"A panic and exception occurred while executing a `neon::event::TaskBuilder` task\",\n    exception: \"An exception occurred while executing a `neon::event::TaskBuilder` task\",\n    panic: \"A panic occurred while executing a `neon::event::TaskBuilder` task\",\n};\n\ntype Execute<I, O> = fn(input: I) -> O;\ntype Complete<O, D> = fn(env: Env, output: thread::Result<O>, data: D);\n\n/// Schedule work to execute on the libuv thread pool\n///\n/// # Safety\n/// * `env` must be a valid `napi_env` for the current thread\n/// * The `thread::Result::Err` must only be used for resuming unwind if\n///   `execute` is not unwind safe\npub unsafe fn schedule<I, O, D>(\n    env: Env,\n    input: I,\n    execute: Execute<I, O>,\n    complete: Complete<O, D>,\n    data: D,\n) where\n    I: Send + 'static,\n    O: Send + 'static,\n    D: 'static,\n{\n    let mut data = Box::new(Data {\n        state: State::Input(input),\n        execute,\n        complete,\n        data: DebugSendWrapper::new(data),\n        // Work is initialized as a null pointer, but set by `create_async_work`\n        // `data` must not be used until this value has been set.\n        work: ptr::null_mut(),\n    });\n\n    // Store a pointer to `work` before ownership is transferred to `Box::into_raw`\n    let work = &mut data.work as *mut _;\n\n    // Create the `async_work`\n    napi::create_async_work(\n        env,\n        ptr::null_mut(),\n        super::string(env, \"neon_async_work\"),\n        Some(call_execute::<I, O, D>),\n        Some(call_complete::<I, O, D>),\n        Box::into_raw(data).cast(),\n        work,\n    )\n    .unwrap();\n\n    // Queue the work\n    match napi::queue_async_work(env, *work) {\n        Ok(()) => {}\n        status => {\n            // If queueing failed, delete the work to prevent a leak\n            let _ = napi::delete_async_work(env, *work);\n            status.unwrap()\n        }\n    }\n}\n\n/// A pointer to data is passed to the `execute` and `complete` callbacks\nstruct Data<I, O, D> {\n    state: State<I, O>,\n    execute: Execute<I, O>,\n    complete: Complete<O, D>,\n    data: DebugSendWrapper<D>,\n    work: napi::AsyncWork,\n}\n\n/// State of the task that is transitioned by `execute` and `complete`\nenum State<I, O> {\n    /// Initial data input passed to `execute`\n    Input(I),\n    /// Transient state while `execute` is running\n    Executing,\n    /// Return data of `execute` passed to `complete`\n    Output(thread::Result<O>),\n}\n\nimpl<I, O> State<I, O> {\n    /// Return the input if `State::Input`, replacing with `State::Executing`\n    fn take_execute_input(&mut self) -> Option<I> {\n        match mem::replace(self, Self::Executing) {\n            Self::Input(input) => Some(input),\n            _ => None,\n        }\n    }\n\n    /// Return the output if `State::Output`, replacing with `State::Executing`\n    fn into_output(self) -> Option<thread::Result<O>> {\n        match self {\n            Self::Output(output) => Some(output),\n            _ => None,\n        }\n    }\n}\n\n/// Callback executed on the libuv thread pool\n///\n/// # Safety\n/// * `Env` should not be used because it could attempt to call JavaScript\n/// * `data` is expected to be a pointer to `Data<I, O, D>`\nunsafe extern \"C\" fn call_execute<I, O, D>(_: Env, data: *mut c_void) {\n    let data = &mut *data.cast::<Data<I, O, D>>();\n\n    // This is unwind safe because unwinding will resume on the other side\n    let output = catch_unwind(AssertUnwindSafe(|| {\n        // `unwrap` is ok because `call_execute` should be called exactly once\n        // after initialization\n        let input = data.state.take_execute_input().unwrap();\n\n        (data.execute)(input)\n    }));\n\n    data.state = State::Output(output);\n}\n\n/// Callback executed on the JavaScript main thread\n///\n/// # Safety\n/// * `data` is expected to be a pointer to `Data<I, O, D>`\nunsafe extern \"C\" fn call_complete<I, O, D>(env: Env, status: napi::Status, data: *mut c_void) {\n    let Data {\n        state,\n        complete,\n        data,\n        work,\n        ..\n    } = *Box::<Data<I, O, D>>::from_raw(data.cast());\n\n    debug_assert_eq!(napi::delete_async_work(env, work), Ok(()));\n\n    BOUNDARY.catch_failure(env, None, move |env| {\n        // `unwrap` is okay because `call_complete` should be called exactly once\n        // if and only if `call_execute` has completed successfully\n        let output = state.into_output().unwrap();\n\n        // The event looped has stopped if we do not have an Env\n        let env = if let Some(env) = env {\n            env\n        } else {\n            // Resume panicking if necessary\n            if let Err(panic) = output {\n                resume_unwind(panic);\n            }\n\n            return ptr::null_mut();\n        };\n\n        match status {\n            napi::Status::Ok => complete(env, output, data.take()),\n            napi::Status::Cancelled => {}\n            _ => assert_eq!(status, napi::Status::Ok),\n        }\n\n        ptr::null_mut()\n    });\n}\n"
  },
  {
    "path": "crates/neon/src/sys/bindings/functions.rs",
    "content": "#![allow(clippy::too_many_arguments)]\n\nmod napi1 {\n    use super::super::types::*;\n    use std::os::raw::{c_char, c_void};\n\n    generate!(\n        #[cfg_attr(docsrs, doc(cfg(feature = \"napi-1\")))]\n        extern \"C\" {\n            fn get_undefined(env: Env, result: *mut Value) -> Status;\n\n            fn get_null(env: Env, result: *mut Value) -> Status;\n\n            fn get_global(env: Env, result: *mut Value) -> Status;\n\n            fn get_boolean(env: Env, value: bool, result: *mut Value) -> Status;\n\n            fn create_double(env: Env, value: f64, result: *mut Value) -> Status;\n\n            fn create_object(env: Env, result: *mut Value) -> Status;\n\n            fn get_value_bool(env: Env, value: Value, result: *mut bool) -> Status;\n\n            fn get_value_double(env: Env, value: Value, result: *mut f64) -> Status;\n\n            fn get_value_uint32(env: Env, value: Value, result: *mut u32) -> Status;\n\n            fn get_value_int32(env: Env, value: Value, result: *mut i32) -> Status;\n\n            fn create_array_with_length(env: Env, length: usize, result: *mut Value) -> Status;\n\n            fn get_array_length(env: Env, value: Value, result: *mut u32) -> Status;\n\n            fn get_new_target(env: Env, cbinfo: CallbackInfo, result: *mut Value) -> Status;\n\n            fn coerce_to_string(env: Env, value: Value, result: *mut Value) -> Status;\n\n            fn throw(env: Env, error: Value) -> Status;\n\n            fn create_error(env: Env, code: Value, msg: Value, result: *mut Value) -> Status;\n\n            fn get_and_clear_last_exception(env: Env, result: *mut Value) -> Status;\n\n            fn is_exception_pending(env: Env, result: *mut bool) -> Status;\n\n            fn get_value_external(env: Env, value: Value, result: *mut *mut c_void) -> Status;\n\n            fn typeof_value(env: Env, value: Value, result: *mut ValueType) -> Status;\n\n            fn close_escapable_handle_scope(env: Env, scope: EscapableHandleScope) -> Status;\n\n            fn open_escapable_handle_scope(env: Env, result: *mut EscapableHandleScope) -> Status;\n\n            fn open_handle_scope(env: Env, result: *mut HandleScope) -> Status;\n\n            fn close_handle_scope(env: Env, scope: HandleScope) -> Status;\n\n            fn is_arraybuffer(env: Env, value: Value, result: *mut bool) -> Status;\n            fn is_typedarray(env: Env, value: Value, result: *mut bool) -> Status;\n            fn is_buffer(env: Env, value: Value, result: *mut bool) -> Status;\n            fn is_error(env: Env, value: Value, result: *mut bool) -> Status;\n            fn is_array(env: Env, value: Value, result: *mut bool) -> Status;\n            fn is_promise(env: Env, value: Value, result: *mut bool) -> Status;\n\n            fn get_value_string_utf8(\n                env: Env,\n                value: Value,\n                buf: *mut c_char,\n                bufsize: usize,\n                result: *mut usize,\n            ) -> Status;\n\n            // The `buf` argument is defined as a `char16_t` which _should_ be a `u16` on most\n            // platforms. When generating bindings with `rust-bindgen` it unconditionally defines\n            // it as `u16` as well.\n            fn get_value_string_utf16(\n                env: Env,\n                value: Value,\n                buf: *mut u16,\n                bufsize: usize,\n                result: *mut usize,\n            ) -> Status;\n\n            fn create_type_error(env: Env, code: Value, msg: Value, result: *mut Value) -> Status;\n\n            fn create_range_error(env: Env, code: Value, msg: Value, result: *mut Value) -> Status;\n\n            fn create_string_utf8(\n                env: Env,\n                str: *const c_char,\n                length: usize,\n                result: *mut Value,\n            ) -> Status;\n\n            fn create_arraybuffer(\n                env: Env,\n                byte_length: usize,\n                data: *mut *mut c_void,\n                result: *mut Value,\n            ) -> Status;\n\n            fn get_arraybuffer_info(\n                env: Env,\n                arraybuffer: Value,\n                data: *mut *mut c_void,\n                byte_length: *mut usize,\n            ) -> Status;\n\n            fn create_typedarray(\n                env: Env,\n                type_: TypedArrayType,\n                length: usize,\n                arraybuffer: Value,\n                byte_offset: usize,\n                result: *mut Value,\n            ) -> Status;\n\n            fn get_typedarray_info(\n                env: Env,\n                typedarray: Value,\n                typ: *mut TypedArrayType,\n                length: *mut usize,\n                data: *mut *mut c_void,\n                buf: *mut Value,\n                offset: *mut usize,\n            ) -> Status;\n\n            fn create_buffer(\n                env: Env,\n                length: usize,\n                data: *mut *mut c_void,\n                result: *mut Value,\n            ) -> Status;\n\n            fn get_buffer_info(\n                env: Env,\n                value: Value,\n                data: *mut *mut c_void,\n                length: *mut usize,\n            ) -> Status;\n\n            fn get_cb_info(\n                env: Env,\n                cbinfo: CallbackInfo,\n                argc: *mut usize,\n                argv: *mut Value,\n                this_arg: *mut Value,\n                data: *mut *mut c_void,\n            ) -> Status;\n\n            fn create_external(\n                env: Env,\n                data: *mut c_void,\n                finalize_cb: Finalize,\n                finalize_hint: *mut c_void,\n                result: *mut Value,\n            ) -> Status;\n\n            fn new_instance(\n                env: Env,\n                constructor: Value,\n                argc: usize,\n                argv: *const Value,\n                result: *mut Value,\n            ) -> Status;\n\n            fn call_function(\n                env: Env,\n                recv: Value,\n                func: Value,\n                argc: usize,\n                argv: *const Value,\n                result: *mut Value,\n            ) -> Status;\n\n            fn create_function(\n                env: Env,\n                utf8name: *const c_char,\n                length: usize,\n                cb: Callback,\n                data: *mut c_void,\n                result: *mut Value,\n            ) -> Status;\n\n            fn set_property(env: Env, object: Value, key: Value, value: Value) -> Status;\n\n            fn get_property(env: Env, object: Value, key: Value, result: *mut Value) -> Status;\n\n            fn set_element(env: Env, object: Value, index: u32, value: Value) -> Status;\n\n            fn get_element(env: Env, object: Value, index: u32, result: *mut Value) -> Status;\n\n            fn escape_handle(\n                env: Env,\n                scope: EscapableHandleScope,\n                escapee: Value,\n                result: *mut Value,\n            ) -> Status;\n\n            fn create_reference(\n                env: Env,\n                value: Value,\n                initial_ref_count: u32,\n                result: *mut Ref,\n            ) -> Status;\n\n            fn reference_ref(env: Env, reference: Ref, result: *mut u32) -> Status;\n\n            fn reference_unref(env: Env, reference: Ref, result: *mut u32) -> Status;\n\n            fn delete_reference(env: Env, reference: Ref) -> Status;\n\n            fn get_reference_value(env: Env, reference: Ref, result: *mut Value) -> Status;\n\n            fn strict_equals(env: Env, lhs: Value, rhs: Value, result: *mut bool) -> Status;\n\n            #[cfg(any(feature = \"sys\", feature = \"external-buffers\"))]\n            fn create_external_arraybuffer(\n                env: Env,\n                data: *mut c_void,\n                length: usize,\n                finalize_cb: Finalize,\n                finalize_hint: *mut c_void,\n                result: *mut Value,\n            ) -> Status;\n\n            #[cfg(any(feature = \"sys\", feature = \"external-buffers\"))]\n            fn create_external_buffer(\n                env: Env,\n                length: usize,\n                data: *mut c_void,\n                finalize_cb: Finalize,\n                finalize_hint: *mut c_void,\n                result: *mut Value,\n            ) -> Status;\n\n            fn run_script(env: Env, script: Value, result: *mut Value) -> Status;\n\n            fn create_async_work(\n                env: Env,\n                async_resource: Value,\n                async_resource_name: Value,\n                execute: AsyncExecuteCallback,\n                complete: AsyncCompleteCallback,\n                data: *mut c_void,\n                result: *mut AsyncWork,\n            ) -> Status;\n\n            fn delete_async_work(env: Env, work: AsyncWork) -> Status;\n            fn queue_async_work(env: Env, work: AsyncWork) -> Status;\n            fn create_promise(env: Env, deferred: *mut Deferred, promise: *mut Value) -> Status;\n            fn resolve_deferred(env: Env, deferred: Deferred, resolution: Value) -> Status;\n            fn reject_deferred(env: Env, deferred: Deferred, rejection: Value) -> Status;\n\n            fn fatal_error(\n                location: *const c_char,\n                location_len: usize,\n                message: *const c_char,\n                message_len: usize,\n            );\n\n            fn wrap(\n                env: Env,\n                js_object: Value,\n                native_object: *mut c_void,\n                finalize_cb: Finalize,\n                finalize_hint: *mut c_void,\n                result: *mut Ref,\n            ) -> Status;\n\n            fn unwrap(env: Env, js_object: Value, result: *mut *mut c_void) -> Status;\n\n            #[cfg(feature = \"napi-8\")]\n            fn remove_wrap(env: Env, js_object: Value, result: *mut *mut c_void) -> Status;\n        }\n    );\n}\n\n#[cfg(feature = \"napi-4\")]\nmod napi4 {\n    use super::super::types::*;\n    use std::os::raw::c_void;\n\n    generate!(\n        #[cfg_attr(docsrs, doc(cfg(feature = \"napi-4\")))]\n        extern \"C\" {\n            fn create_threadsafe_function(\n                env: Env,\n                func: Value,\n                async_resource: Value,\n                async_resource_name: Value,\n                max_queue_size: usize,\n                initial_thread_count: usize,\n                thread_finalize_data: *mut c_void,\n                thread_finalize_cb: Finalize,\n                context: *mut c_void,\n                call_js_cb: ThreadsafeFunctionCallJs,\n                result: *mut ThreadsafeFunction,\n            ) -> Status;\n\n            fn call_threadsafe_function(\n                func: ThreadsafeFunction,\n                data: *mut c_void,\n                is_blocking: ThreadsafeFunctionCallMode,\n            ) -> Status;\n\n            fn release_threadsafe_function(\n                func: ThreadsafeFunction,\n                mode: ThreadsafeFunctionReleaseMode,\n            ) -> Status;\n\n            fn ref_threadsafe_function(env: Env, func: ThreadsafeFunction) -> Status;\n\n            fn unref_threadsafe_function(env: Env, func: ThreadsafeFunction) -> Status;\n        }\n    );\n}\n\n#[cfg(feature = \"napi-5\")]\nmod napi5 {\n    use super::super::types::*;\n    use std::ffi::c_void;\n\n    generate!(\n        #[cfg_attr(docsrs, doc(cfg(feature = \"napi-5\")))]\n        extern \"C\" {\n            fn create_date(env: Env, value: f64, result: *mut Value) -> Status;\n\n            fn get_date_value(env: Env, value: Value, result: *mut f64) -> Status;\n\n            fn is_date(env: Env, value: Value, result: *mut bool) -> Status;\n\n            fn add_finalizer(\n                env: Env,\n                js_object: Value,\n                native_object: *mut c_void,\n                finalize_cb: Finalize,\n                finalize_hint: *mut c_void,\n                result: Ref,\n            ) -> Status;\n        }\n    );\n}\n\n#[cfg(feature = \"napi-6\")]\nmod napi6 {\n    use super::super::types::*;\n    use std::os::raw::c_void;\n\n    generate!(\n        #[cfg_attr(docsrs, doc(cfg(feature = \"napi-6\")))]\n        extern \"C\" {\n            fn get_all_property_names(\n                env: Env,\n                object: Value,\n                key_mode: KeyCollectionMode,\n                key_filter: KeyFilter,\n                key_conversion: KeyConversion,\n                result: *mut Value,\n            ) -> Status;\n\n            fn set_instance_data(\n                env: Env,\n                data: *mut c_void,\n                finalize_cb: Finalize,\n                finalize_hint: *mut c_void,\n            ) -> Status;\n\n            fn get_instance_data(env: Env, data: *mut *mut c_void) -> Status;\n\n            fn create_bigint_int64(env: Env, value: i64, result: *mut Value) -> Status;\n\n            fn create_bigint_uint64(env: Env, value: u64, result: *mut Value) -> Status;\n\n            fn create_bigint_words(\n                env: Env,\n                sign_bit: i32,\n                word_count: usize,\n                words: *const u64,\n                result: *mut Value,\n            ) -> Status;\n\n            fn get_value_bigint_int64(\n                env: Env,\n                value: Value,\n                result: *mut i64,\n                lossless: *mut bool,\n            ) -> Status;\n\n            fn get_value_bigint_uint64(\n                env: Env,\n                value: Value,\n                result: *mut u64,\n                lossless: *mut bool,\n            ) -> Status;\n\n            fn get_value_bigint_words(\n                env: Env,\n                value: Value,\n                sign_bit: *mut i64,\n                word_count: *mut usize,\n                words: *mut u64,\n            ) -> Status;\n        }\n    );\n}\n\n#[cfg(feature = \"napi-8\")]\nmod napi8 {\n    use super::super::types::*;\n\n    generate!(\n        #[cfg_attr(docsrs, doc(cfg(feature = \"napi-8\")))]\n        extern \"C\" {\n            fn object_freeze(env: Env, object: Value) -> Status;\n            fn object_seal(env: Env, object: Value) -> Status;\n            fn type_tag_object(env: Env, object: Value, tag: *const TypeTag) -> Status;\n            fn check_object_type_tag(\n                env: Env,\n                object: Value,\n                tag: *const TypeTag,\n                result: *mut bool,\n            ) -> Status;\n        }\n    );\n}\n\npub use napi1::*;\n#[cfg(feature = \"napi-4\")]\npub use napi4::*;\n#[cfg(feature = \"napi-5\")]\npub use napi5::*;\n#[cfg(feature = \"napi-6\")]\npub use napi6::*;\n#[cfg(feature = \"napi-8\")]\npub use napi8::*;\n\nuse super::{Env, Status};\n\n// This symbol is loaded separately because it is a prerequisite\nunsafe fn get_version(host: &libloading::Library, env: Env) -> Result<u32, libloading::Error> {\n    let get_version = host.get::<fn(Env, *mut u32) -> Status>(b\"napi_get_version\")?;\n    let mut version = 0;\n\n    assert_eq!(get_version(env, &mut version as *mut _), Status::Ok,);\n\n    Ok(version)\n}\n\npub(crate) unsafe fn load(env: Env) -> Result<(), libloading::Error> {\n    #[cfg(not(windows))]\n    let host = libloading::os::unix::Library::this().into();\n    #[cfg(windows)]\n    let host = libloading::os::windows::Library::this()?.into();\n\n    // This never fail since `get_version` is in N-API Version 1 and the module will fail\n    // with `Error: Module did not self-register` if N-API does not exist.\n    let actual_version = get_version(&host, env).expect(\"Failed to find N-API version\");\n\n    let expected_version = match () {\n        _ if cfg!(feature = \"napi-8\") => 8,\n        _ if cfg!(feature = \"napi-7\") => 7,\n        _ if cfg!(feature = \"napi-6\") => 6,\n        _ if cfg!(feature = \"napi-5\") => 5,\n        _ if cfg!(feature = \"napi-4\") => 4,\n        _ if cfg!(feature = \"napi-3\") => 3,\n        _ if cfg!(feature = \"napi-2\") => 2,\n        _ => 1,\n    };\n\n    if actual_version < expected_version {\n        eprintln!(\"Minimum required Node-API version {expected_version}, found {actual_version}.\\n\\nSee the Node-API support matrix for more details: https://nodejs.org/api/n-api.html#node-api-version-matrix\");\n    }\n\n    napi1::load(&host);\n\n    #[cfg(feature = \"napi-4\")]\n    napi4::load(&host);\n\n    #[cfg(feature = \"napi-5\")]\n    napi5::load(&host);\n\n    #[cfg(feature = \"napi-6\")]\n    napi6::load(&host);\n\n    #[cfg(feature = \"napi-8\")]\n    napi8::load(&host);\n\n    Ok(())\n}\n"
  },
  {
    "path": "crates/neon/src/sys/bindings/mod.rs",
    "content": "//! # FFI bindings to Node-API symbols\n//!\n//! Rust types generated from [Node-API](https://nodejs.org/api/n-api.html).\n\n// These types are manually copied from bindings generated from `bindgen`. To\n// update, use the following approach:\n//\n// * Run a debug build of Neon at least once to install `nodejs-sys`\n// * Open the generated bindings at `target/debug/build/nodejs-sys-*/out/bindings.rs`\n// * Copy the types needed into `types.rs` and `functions.rs`\n// * Modify to match Rust naming conventions:\n//   - Remove `napi_` prefixes\n//   - Use `PascalCase` for types\n//   - Rename types that match a reserved word\n\n/// Constructs the name of a N-API symbol as a string from a function identifier\n/// E.g., `get_undefined` becomes `\"napi_get_undefined\"`\nmacro_rules! napi_name {\n    // Explicitly replace identifiers that have been renamed from the N-API\n    // symbol because they would match a reserved word.\n    (typeof_value) => {\n        \"napi_typeof\"\n    };\n    // Default case: Stringify the identifier and prefix with `napi_`\n    ($name:ident) => {\n        concat!(\"napi_\", stringify!($name))\n    };\n}\n\n/// Generate dynamic bindings to N-API symbols from definitions in an\n/// block `extern \"C\"`.\n///\n/// * A single global mutable struct holds references to the N-API functions\n/// * The global `Napi` struct  is initialized with stubs that panic if called\n/// * A `load` function is generated that loads the N-API symbols from the\n///   host process and replaces the global struct with real implementations\n/// * `load` should be called exactly once before using any N-API functions\n/// * Wrapper functions are generated to delegate to fields in the `Napi` struct\n///\n/// Sample input:\n///\n/// ```ignore\n/// extern \"C\" {\n///     fn get_undefined(env: Env, result: *mut Value) -> Status;\n///     /* Additional functions may be included */  \n/// }\n/// ```\n///\n/// Generated output:\n///\n/// ```ignore\n/// // Each field is a pointer to a N-API function\n/// struct Napi {\n///     get_undefined: unsafe extern \"C\" fn(env: Env, result: *mut Value) -> Status,\n///     /* ... repeat for each N-API function */\n/// }\n///\n/// // Defines a panic function that is called if symbols have not been loaded\n/// #[inline(never)]\n/// fn panic_load<T>() -> T {\n///     panic!(\"Must load N-API bindings\")\n/// }\n///\n/// // Mutable global instance of the Napi struct\n/// // Initialized with stubs of N-API methods that panic\n/// static mut NAPI: Napi = {\n///     // Stubs are defined in a block to prevent naming conflicts with wrappers\n///     unsafe extern \"C\" fn get_undefined(_: Env, _: *mut Value) -> Status {\n///         panic_load()\n///     }\n///     /* ... repeat for each N-API function */\n///\n///     Napi {\n///         get_undefined,\n///         /* ... repeat for each N-API function */\n///     }\n/// };\n///\n/// // Load N-API symbols from the host process\n/// // # Safety: Must only be called once\n/// pub(super) unsafe fn load(\n///     host: &libloading::Library,\n///     actual_napi_version: u32,\n///     expected_napi_version: u32,\n/// ) -> Result<(), libloading::Error> {\n///     assert!(\n///         actual_napi_version >= expected_napi_version,\n///         \"Minimum required N-API version {}, found {}.\",\n///         expected_napi_version,\n///         actual_napi_version,\n///     );\n///\n///     NAPI = Napi {\n///         // Load each N-API symbol\n///         get_undefined: *host.get(\"napi_get_undefined\".as_bytes())?,\n///         /* ... repeat for each N-API function */\n///     };\n///\n///     Ok(())\n/// }\n///\n/// // Each N-API function has wrapper for easy calling. These calls are optimized\n/// // to a single pointer dereference.\n/// #[inline]\n/// pub(crate) unsafe fn get_undefined(env: Env, result: *mut Value) -> Status {\n///     (NAPI.get_undefined)(env, result)\n/// }\n/// ```\nmacro_rules! generate {\n    (#[$extern_attr:meta] extern \"C\" {\n        $($(#[$attr:meta])? fn $name:ident($($param:ident: $ptype:ty$(,)?)*)$( -> $rtype:ty)?;)+\n    }) => {\n        struct Napi {\n            $(\n                $name: unsafe extern \"C\" fn(\n                    $($param: $ptype,)*\n                )$( -> $rtype)*,\n            )*\n        }\n\n        #[inline(never)]\n        fn panic_load<T>() -> T {\n            panic!(\"Node-API symbol has not been loaded\")\n        }\n\n        static mut NAPI: Napi = {\n            $(\n                unsafe extern \"C\" fn $name($(_: $ptype,)*)$( -> $rtype)* {\n                    panic_load()\n                }\n            )*\n\n            Napi {\n                $(\n                    $name,\n                )*\n            }\n        };\n\n        pub(super) unsafe fn load(host: &libloading::Library) {\n            let print_warn = |err| eprintln!(\"WARN: {}\", err);\n\n            NAPI = Napi {\n                $(\n                    $name: match host.get(napi_name!($name).as_bytes()) {\n                        Ok(f) => *f,\n                        // Node compatible runtimes may not have full coverage of Node-API\n                        // (e.g., bun). Instead of failing to start, warn on start and\n                        // panic when the API is called.\n                        // https://github.com/Jarred-Sumner/bun/issues/158\n                        Err(err) => {\n                            print_warn(err);\n                            NAPI.$name\n                        },\n                    },\n                )*\n            };\n        }\n\n        $(\n            #[$extern_attr] $(#[$attr])? #[inline]\n            #[doc = concat!(\n                \"[`\",\n                napi_name!($name),\n                \"`](https://nodejs.org/api/n-api.html#\",\n                napi_name!($name),\n                \")\",\n            )]\n            pub unsafe fn $name($($param: $ptype,)*)$( -> ::core::result::Result<(), $rtype>)* {\n                #[allow(unused)]\n                let r = (NAPI.$name)($($param,)*);\n                $(match r {\n                    <$rtype>::Ok => Ok(()),\n                    status => Err(status)\n                })*\n            }\n        )*\n    };\n}\n\npub use self::{functions::*, types::*};\n\nmod functions;\nmod types;\n"
  },
  {
    "path": "crates/neon/src/sys/bindings/types.rs",
    "content": "use std::ffi::c_void;\n\n#[repr(C)]\n#[derive(Debug, Copy, Clone)]\n#[doc(hidden)]\npub struct Env__ {\n    _unused: [u8; 0],\n}\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-1\")))]\n/// [`napi_env`](https://nodejs.org/api/n-api.html#napi_env)\npub type Env = *mut Env__;\n\n#[repr(C)]\n#[derive(Debug, Copy, Clone)]\n#[doc(hidden)]\npub struct Value__ {\n    _unused: [u8; 0],\n}\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-1\")))]\n/// [`napi_value`](https://nodejs.org/api/n-api.html#napi_value)\npub type Value = *mut Value__;\n\n#[repr(C)]\n#[derive(Debug, Copy, Clone)]\n#[doc(hidden)]\npub struct CallbackInfo__ {\n    _unused: [u8; 0],\n}\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-1\")))]\n/// [`napi_callback_info`](https://nodejs.org/api/n-api.html#napi_callback_info)\npub type CallbackInfo = *mut CallbackInfo__;\n\n#[repr(C)]\n#[derive(Debug, Copy, Clone)]\n#[doc(hidden)]\npub struct EscapableHandleScope__ {\n    _unused: [u8; 0],\n}\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-1\")))]\n/// [`napi_escapable_handle_scope`](https://nodejs.org/api/n-api.html#napi_escapable_handle_scope)\npub type EscapableHandleScope = *mut EscapableHandleScope__;\n\n#[repr(C)]\n#[derive(Debug, Copy, Clone)]\n#[doc(hidden)]\npub struct HandleScope__ {\n    _unused: [u8; 0],\n}\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-1\")))]\n/// [`napi_handle_scope`](https://nodejs.org/api/n-api.html#napi_handle_scope)\npub type HandleScope = *mut HandleScope__;\n\n#[repr(C)]\n#[derive(Debug, Copy, Clone)]\n#[doc(hidden)]\npub struct Ref__ {\n    _unused: [u8; 0],\n}\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-1\")))]\n/// [`napi_ref`](https://nodejs.org/api/n-api.html#napi_ref)\npub type Ref = *mut Ref__;\n\n#[cfg(feature = \"napi-4\")]\n#[repr(C)]\n#[derive(Debug, Copy, Clone)]\n#[doc(hidden)]\npub struct ThreadsafeFunction__ {\n    _unused: [u8; 0],\n}\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-4\")))]\n#[cfg(feature = \"napi-4\")]\n/// [`napi_threadsafe_function`](https://nodejs.org/api/n-api.html#napi_threadsafe_function)\npub type ThreadsafeFunction = *mut ThreadsafeFunction__;\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-1\")))]\n/// [`napi_callback`](https://nodejs.org/api/n-api.html#napi_callback)\npub type Callback = Option<unsafe extern \"C\" fn(env: Env, info: CallbackInfo) -> Value>;\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-1\")))]\n/// [`napi_finalize`](https://nodejs.org/api/n-api.html#napi_finalize)\npub type Finalize =\n    Option<unsafe extern \"C\" fn(env: Env, finalize_data: *mut c_void, finalize_hint: *mut c_void)>;\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-4\")))]\n#[cfg(feature = \"napi-4\")]\n/// [`napi_threadsafe_function_call_js`](https://nodejs.org/api/n-api.html#napi_threadsafe_function_call_js)\npub type ThreadsafeFunctionCallJs = Option<\n    unsafe extern \"C\" fn(env: Env, js_callback: Value, context: *mut c_void, data: *mut c_void),\n>;\n\n#[allow(dead_code)]\n#[repr(u32)]\n#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-1\")))]\n/// [`napi_status`](https://nodejs.org/api/n-api.html#napi_status)\npub enum Status {\n    Ok = 0,\n    InvalidArg = 1,\n    ObjectExpected = 2,\n    StringExpected = 3,\n    NameExpected = 4,\n    FunctionExpected = 5,\n    NumberExpected = 6,\n    BooleanExpected = 7,\n    ArrayExpected = 8,\n    GenericFailure = 9,\n    PendingException = 10,\n    Cancelled = 11,\n    EscapeCalledTwice = 12,\n    HandleScopeMismatch = 13,\n    CallbackScopeMismatch = 14,\n    QueueFull = 15,\n    Closing = 16,\n    BigintExpected = 17,\n    DateExpected = 18,\n    ArraybufferExpected = 19,\n    DetachableArraybufferExpected = 20,\n    WouldDeadlock = 21,\n}\n\n#[allow(dead_code)]\n#[repr(u32)]\n#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-6\")))]\n/// [`napi_valuetype`](https://nodejs.org/api/n-api.html#napi_valuetype)\npub enum ValueType {\n    Undefined = 0,\n    Null = 1,\n    Boolean = 2,\n    Number = 3,\n    String = 4,\n    Symbol = 5,\n    Object = 6,\n    Function = 7,\n    External = 8,\n    BigInt = 9,\n}\n\n#[allow(dead_code)]\n#[repr(u32)]\n#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-1\")))]\n/// [`napi_typedarray_type`](https://nodejs.org/api/n-api.html#napi_typedarray_type)\npub enum TypedArrayType {\n    I8 = 0,\n    U8 = 1,\n    U8Clamped = 2,\n    I16 = 3,\n    U16 = 4,\n    I32 = 5,\n    U32 = 6,\n    F32 = 7,\n    F64 = 8,\n    I64 = 9,\n    U64 = 10,\n}\n\n#[allow(dead_code)]\n#[repr(u32)]\n#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-6\")))]\n#[cfg(feature = \"napi-6\")]\n/// [`napi_key_collection_mode`](https://nodejs.org/api/n-api.html#napi_key_collection_mode)\npub enum KeyCollectionMode {\n    IncludePrototypes = 0,\n    OwnOnly = 1,\n}\n\n#[allow(dead_code)]\n#[repr(u32)]\n#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-6\")))]\n#[cfg(feature = \"napi-6\")]\n/// [`napi_key_conversion`](https://nodejs.org/api/n-api.html#napi_key_conversion)\npub enum KeyConversion {\n    KeepNumbers = 0,\n    NumbersToStrings = 1,\n}\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-4\")))]\n#[cfg(feature = \"napi-4\")]\n#[allow(dead_code)]\n#[repr(u32)]\n#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]\n/// [`napi_threadsafe_function_call_mode`](https://nodejs.org/api/n-api.html#napi_threadsafe_function_call_mode)\npub enum ThreadsafeFunctionCallMode {\n    NonBlocking = 0,\n    Blocking = 1,\n}\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-4\")))]\n#[cfg(feature = \"napi-4\")]\n#[allow(dead_code)]\n#[repr(u32)]\n#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]\n/// [`napi_threadsafe_function_release_mode`](https://nodejs.org/api/n-api.html#napi_threadsafe_function_release_mode)\npub enum ThreadsafeFunctionReleaseMode {\n    Release = 0,\n    Abort = 1,\n}\n\n#[repr(transparent)]\n#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-6\")))]\n#[cfg(feature = \"napi-6\")]\n/// [`napi_key_filter`](https://nodejs.org/api/n-api.html#napi_key_filter)\npub struct KeyFilter(pub ::std::os::raw::c_uint);\n\n#[allow(dead_code)]\n#[cfg(feature = \"napi-6\")]\nimpl KeyFilter {\n    pub const ALL_PROPERTIES: KeyFilter = KeyFilter(0);\n    pub const WRITABLE: KeyFilter = KeyFilter(1);\n    pub const CONFIGURABLE: KeyFilter = KeyFilter(4);\n    pub const SKIP_STRINGS: KeyFilter = KeyFilter(8);\n    pub const SKIP_SYMBOLS: KeyFilter = KeyFilter(16);\n}\n\n#[cfg(feature = \"napi-6\")]\nimpl std::ops::BitOr<KeyFilter> for KeyFilter {\n    type Output = Self;\n    #[inline]\n    fn bitor(self, other: Self) -> Self {\n        KeyFilter(self.0 | other.0)\n    }\n}\n\n#[cfg(feature = \"napi-6\")]\nimpl std::ops::BitOrAssign for KeyFilter {\n    #[inline]\n    fn bitor_assign(&mut self, rhs: KeyFilter) {\n        self.0 |= rhs.0;\n    }\n}\n\n#[cfg(feature = \"napi-6\")]\nimpl std::ops::BitAnd<KeyFilter> for KeyFilter {\n    type Output = Self;\n    #[inline]\n    fn bitand(self, other: Self) -> Self {\n        KeyFilter(self.0 & other.0)\n    }\n}\n\n#[cfg(feature = \"napi-6\")]\nimpl std::ops::BitAndAssign for KeyFilter {\n    #[inline]\n    fn bitand_assign(&mut self, rhs: KeyFilter) {\n        self.0 &= rhs.0;\n    }\n}\n\n#[repr(C)]\n#[derive(Debug, Copy, Clone)]\n#[doc(hidden)]\npub struct AsyncWork__ {\n    _unused: [u8; 0],\n}\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-1\")))]\n/// [`napi_async_work`](https://nodejs.org/api/n-api.html#napi_async_work)\npub type AsyncWork = *mut AsyncWork__;\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-1\")))]\n/// [`napi_async_execute_callback`](https://nodejs.org/api/n-api.html#napi_async_execute_callback)\npub type AsyncExecuteCallback = Option<unsafe extern \"C\" fn(env: Env, data: *mut c_void)>;\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-1\")))]\n/// [`napi_async_complete_callback`](https://nodejs.org/api/n-api.html#napi_async_complete_callback)\npub type AsyncCompleteCallback =\n    Option<unsafe extern \"C\" fn(env: Env, status: Status, data: *mut c_void)>;\n\n#[repr(C)]\n#[derive(Debug, Copy, Clone)]\n#[doc(hidden)]\npub struct Deferred__ {\n    _unused: [u8; 0],\n}\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-1\")))]\n/// [`napi_deferred`](https://nodejs.org/api/n-api.html#napi_deferred)\npub type Deferred = *mut Deferred__;\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-8\")))]\n#[cfg(feature = \"napi-8\")]\n#[repr(C)]\n#[derive(Debug, Copy, Clone)]\n/// [`napi_type_tag`](https://nodejs.org/api/n-api.html#napi_type_tag)\npub struct TypeTag {\n    pub lower: u64,\n    pub upper: u64,\n}\n"
  },
  {
    "path": "crates/neon/src/sys/buffer.rs",
    "content": "#[cfg(feature = \"external-buffers\")]\nuse std::os::raw::c_void;\nuse std::{mem::MaybeUninit, slice};\n\nuse super::{\n    bindings as napi,\n    raw::{Env, Local},\n};\n\npub unsafe fn new(env: Env, len: usize) -> Result<Local, napi::Status> {\n    let (buf, bytes) = uninitialized(env, len)?;\n\n    std::ptr::write_bytes(bytes, 0, len);\n\n    Ok(buf)\n}\n\npub unsafe fn uninitialized(env: Env, len: usize) -> Result<(Local, *mut u8), napi::Status> {\n    let mut buf = MaybeUninit::uninit();\n    let mut bytes = MaybeUninit::uninit();\n    let status = napi::create_buffer(env, len, bytes.as_mut_ptr(), buf.as_mut_ptr());\n\n    match status {\n        Err(err @ napi::Status::PendingException) => return Err(err),\n        status => status.unwrap(),\n    };\n\n    Ok((buf.assume_init(), bytes.assume_init().cast()))\n}\n\n#[cfg(feature = \"external-buffers\")]\npub unsafe fn new_external<T>(env: Env, data: T) -> Local\nwhere\n    T: AsMut<[u8]> + Send,\n{\n    // Safety: Boxing could move the data; must box before grabbing a raw pointer\n    let mut data = Box::new(data);\n    let buf = data.as_mut().as_mut();\n    let length = buf.len();\n    let mut result = MaybeUninit::uninit();\n\n    napi::create_external_buffer(\n        env,\n        length,\n        buf.as_mut_ptr() as *mut _,\n        Some(drop_external::<T>),\n        Box::into_raw(data) as *mut _,\n        result.as_mut_ptr(),\n    )\n    .unwrap();\n\n    result.assume_init()\n}\n\n#[cfg(feature = \"external-buffers\")]\nunsafe extern \"C\" fn drop_external<T>(_env: Env, _data: *mut c_void, hint: *mut c_void) {\n    drop(Box::<T>::from_raw(hint as *mut _));\n}\n\n/// # Safety\n/// * Caller must ensure `env` and `buf` are valid\n/// * The lifetime `'a` does not exceed the lifetime of `Env` or `buf`\npub unsafe fn as_mut_slice<'a>(env: Env, buf: Local) -> &'a mut [u8] {\n    let mut data = MaybeUninit::uninit();\n    let mut size = 0usize;\n\n    napi::get_buffer_info(env, buf, data.as_mut_ptr(), &mut size as *mut _).unwrap();\n\n    if size == 0 {\n        return &mut [];\n    }\n\n    slice::from_raw_parts_mut(data.assume_init().cast(), size)\n}\n\n/// # Safety\n/// * Caller must ensure `env` and `buf` are valid\npub unsafe fn size(env: Env, buf: Local) -> usize {\n    let mut data = MaybeUninit::uninit();\n    let mut size = 0usize;\n\n    napi::get_buffer_info(env, buf, data.as_mut_ptr(), &mut size as *mut _).unwrap();\n\n    size\n}\n"
  },
  {
    "path": "crates/neon/src/sys/call.rs",
    "content": "use std::{mem::MaybeUninit, ptr::null_mut};\n\nuse smallvec::SmallVec;\n\nuse super::{\n    bindings as napi,\n    raw::{Env, FunctionCallbackInfo, Local},\n};\n\n// Number of arguments to allocate on the stack. This should be large enough\n// to cover most use cases without being wasteful.\n//\n// * If the number is too large, too much space is allocated and then filled\n//   with `undefined`.\n// * If the number is too small, getting arguments frequently takes two tries\n//   and requires heap allocation.\nconst ARGV_SIZE: usize = 4;\n\n#[repr(transparent)]\n/// List of JavaScript arguments to a function\n// `Arguments` is intended to be a small abstraction to hide the usage of\n// `SmallVec` allowing changes to `ARGV_SIZE` in a single location\npub struct Arguments(SmallVec<[Local; ARGV_SIZE]>);\n\nimpl Arguments {\n    #[inline]\n    /// Get an argument at a specific position\n    pub fn get(&self, i: usize) -> Option<Local> {\n        self.0.get(i).cloned()\n    }\n}\n\npub unsafe fn is_construct(env: Env, info: FunctionCallbackInfo) -> bool {\n    let mut target: MaybeUninit<Local> = MaybeUninit::zeroed();\n\n    napi::get_new_target(env, info, target.as_mut_ptr()).unwrap();\n\n    // get_new_target is guaranteed to assign to target, so it's initialized.\n    let target: Local = target.assume_init();\n\n    // By the get_new_target contract, target will either be NULL if the current\n    // function was called without `new`, or a valid napi_value handle if the current\n    // function was called with `new`.\n    !target.is_null()\n}\n\npub unsafe fn this(env: Env, info: FunctionCallbackInfo, out: &mut Local) {\n    napi::get_cb_info(env, info, null_mut(), null_mut(), out as *mut _, null_mut()).unwrap();\n}\n\n/// Gets the number of arguments passed to the function.\n// TODO: Remove this when `FunctionContext` is refactored to get call info upfront.\npub unsafe fn len(env: Env, info: FunctionCallbackInfo) -> usize {\n    let mut argc = 0usize;\n    napi::get_cb_info(\n        env,\n        info,\n        &mut argc as *mut _,\n        null_mut(),\n        null_mut(),\n        null_mut(),\n    )\n    .unwrap();\n    argc\n}\n\n/// Returns the function arguments for a call\npub unsafe fn argv(env: Env, info: FunctionCallbackInfo) -> Arguments {\n    // Allocate space on the stack for up to `ARGV_SIZE` values\n    let mut argv = MaybeUninit::<[Local; ARGV_SIZE]>::uninit();\n\n    // Starts as the size allocated; after `get_cb_info` it is the number of arguments\n    let mut argc = ARGV_SIZE;\n\n    napi::get_cb_info(\n        env,\n        info,\n        &mut argc as *mut _,\n        argv.as_mut_ptr().cast(),\n        null_mut(),\n        null_mut(),\n    )\n    .unwrap();\n\n    // We did not allocate enough space; allocate on the heap and try again\n    let argv = if argc > ARGV_SIZE {\n        // We know exactly how much space to reserve\n        let mut argv = Vec::with_capacity(argc);\n\n        napi::get_cb_info(\n            env,\n            info,\n            &mut argc as *mut _,\n            argv.as_mut_ptr(),\n            null_mut(),\n            null_mut(),\n        )\n        .unwrap();\n\n        // Set the size of `argv` to the number of initialized elements\n        argv.set_len(argc);\n        SmallVec::from_vec(argv)\n\n        // There were `ARGV_SIZE` or fewer arguments, use the stack allocated space\n    } else {\n        SmallVec::from_buf_and_len(argv.assume_init(), argc)\n    };\n\n    Arguments(argv)\n}\n"
  },
  {
    "path": "crates/neon/src/sys/convert.rs",
    "content": "use super::{\n    bindings as napi,\n    raw::{Env, Local},\n};\n\npub unsafe fn to_string(out: &mut Local, env: Env, value: Local) -> bool {\n    let status = napi::coerce_to_string(env, value, out as *mut _);\n\n    status.is_ok()\n}\n"
  },
  {
    "path": "crates/neon/src/sys/date.rs",
    "content": "use std::mem::MaybeUninit;\n\nuse super::{\n    bindings as napi,\n    raw::{Env, Local},\n};\n\n/// Create a new date object\n///\n/// # Safety\n///\n/// `env` is a raw pointer. Please ensure it points to a napi_env that is valid for the current context.\npub unsafe fn new_date(env: Env, value: f64) -> Local {\n    let mut local = MaybeUninit::zeroed();\n    napi::create_date(env, value, local.as_mut_ptr()).unwrap();\n    local.assume_init()\n}\n\n/// Get the value of a date object\n///\n/// # Safety\n///\n/// `env` is a raw pointer. Please ensure it points to a napi_env that is valid for the current context.\n/// `Local` must be an NAPI value associated with the given `Env`\npub unsafe fn value(env: Env, p: Local) -> f64 {\n    let mut value = 0.0;\n    napi::get_date_value(env, p, &mut value as *mut _).unwrap();\n    value\n}\n"
  },
  {
    "path": "crates/neon/src/sys/debug_send_wrapper.rs",
    "content": "//! Wrapper that ensures types are always used from the same thread\n//! in debug builds. It is a zero-cost in release builds.\n\npub(super) use wrapper::DebugSendWrapper;\n\n#[cfg(debug_assertions)]\nmod wrapper {\n    use std::ops::Deref;\n\n    #[repr(transparent)]\n    pub struct DebugSendWrapper<T>(send_wrapper::SendWrapper<T>);\n\n    impl<T> DebugSendWrapper<T> {\n        pub fn new(value: T) -> Self {\n            Self(send_wrapper::SendWrapper::new(value))\n        }\n\n        pub fn take(self) -> T {\n            self.0.take()\n        }\n    }\n\n    impl<T> Deref for DebugSendWrapper<T> {\n        type Target = T;\n\n        fn deref(&self) -> &Self::Target {\n            &self.0\n        }\n    }\n}\n\n#[cfg(not(debug_assertions))]\nmod wrapper {\n    use std::ops::Deref;\n\n    #[repr(transparent)]\n    pub struct DebugSendWrapper<T>(T);\n\n    impl<T> DebugSendWrapper<T> {\n        pub fn new(value: T) -> Self {\n            Self(value)\n        }\n\n        pub fn take(self) -> T {\n            self.0\n        }\n    }\n\n    impl<T> Deref for DebugSendWrapper<T> {\n        type Target = T;\n\n        fn deref(&self) -> &Self::Target {\n            &self.0\n        }\n    }\n}\n"
  },
  {
    "path": "crates/neon/src/sys/error.rs",
    "content": "use std::{mem::MaybeUninit, panic::Location, ptr};\n\nuse super::{\n    bindings as napi,\n    raw::{Env, Local},\n};\n\npub unsafe fn is_throwing(env: Env) -> bool {\n    let mut b: MaybeUninit<bool> = MaybeUninit::zeroed();\n\n    napi::is_exception_pending(env, b.as_mut_ptr()).unwrap();\n\n    b.assume_init()\n}\n\npub unsafe fn catch_error(env: Env, error: *mut Local) -> bool {\n    if !is_throwing(env) {\n        return false;\n    }\n\n    napi::get_and_clear_last_exception(env, error).unwrap();\n\n    true\n}\n\npub unsafe fn clear_exception(env: Env) {\n    let mut result = MaybeUninit::uninit();\n    napi::is_exception_pending(env, result.as_mut_ptr()).unwrap();\n\n    if !result.assume_init() {\n        return;\n    }\n\n    let mut result = MaybeUninit::uninit();\n    napi::get_and_clear_last_exception(env, result.as_mut_ptr()).unwrap();\n}\n\npub unsafe fn throw(env: Env, val: Local) {\n    napi::throw(env, val).unwrap();\n}\n\npub unsafe fn new_error(env: Env, out: &mut Local, msg: Local) {\n    let mut result = MaybeUninit::uninit();\n    napi::create_error(env, ptr::null_mut(), msg, result.as_mut_ptr()).unwrap();\n\n    *out = result.assume_init();\n}\n\npub unsafe fn new_type_error(env: Env, out: &mut Local, msg: Local) {\n    let mut result = MaybeUninit::uninit();\n    napi::create_type_error(env, ptr::null_mut(), msg, result.as_mut_ptr()).unwrap();\n\n    *out = result.assume_init();\n}\n\npub unsafe fn new_range_error(env: Env, out: &mut Local, msg: Local) {\n    let mut result = MaybeUninit::uninit();\n    napi::create_range_error(env, ptr::null_mut(), msg, result.as_mut_ptr()).unwrap();\n\n    *out = result.assume_init();\n}\n\npub unsafe fn throw_error_from_utf8(env: Env, msg: *const u8, len: i32) {\n    let mut out = MaybeUninit::uninit();\n\n    napi::create_string_utf8(env, msg as *const _, len as usize, out.as_mut_ptr()).unwrap();\n\n    let mut err = MaybeUninit::uninit();\n    napi::create_error(env, ptr::null_mut(), out.assume_init(), err.as_mut_ptr()).unwrap();\n\n    throw(env, err.assume_init());\n}\n\n#[track_caller]\npub(super) unsafe fn fatal_error(message: &str) -> ! {\n    let location = Location::caller().to_string();\n\n    napi::fatal_error(\n        location.as_ptr().cast(),\n        location.len(),\n        message.as_ptr().cast(),\n        message.len(),\n    );\n\n    unreachable!(\"Expected napi_fatal_error to exit the process\")\n}\n"
  },
  {
    "path": "crates/neon/src/sys/external.rs",
    "content": "use std::mem::MaybeUninit;\n\nuse super::{\n    bindings as napi,\n    debug_send_wrapper::DebugSendWrapper,\n    raw::{Env, Local},\n};\n\n/// `finalize_external` is invoked immediately before a `napi_external` is garbage collected\nextern \"C\" fn finalize_external<T: 'static>(\n    env: Env,\n    // Raw pointer to a `Box<T>` stored by a `napi_external`\n    data: *mut std::ffi::c_void,\n    // Pointer to a Rust `fn` stored in the `hint` parameter of a `napi_external` called\n    // with the contents of `data` immediately before the value is garbage collected.\n    hint: *mut std::ffi::c_void,\n) {\n    unsafe {\n        let data = Box::<DebugSendWrapper<T>>::from_raw(data as *mut _);\n        let finalizer: fn(Env, T) = std::mem::transmute(hint as *const ());\n\n        finalizer(env, data.take());\n    }\n}\n\n/// Returns a pointer to data stored in a `napi_external`\n/// Safety: `deref` must only be called with `napi_external` created by that\n/// module. Calling `deref` with an external created by another native module,\n/// even another neon module, is undefined behavior.\n/// <https://github.com/neon-bindings/neon/issues/591>\npub unsafe fn deref<T: 'static>(env: Env, local: Local) -> Option<*const T> {\n    let mut result = MaybeUninit::uninit();\n    napi::typeof_value(env, local, result.as_mut_ptr()).unwrap();\n\n    let result = result.assume_init();\n\n    // Ensure we have an external\n    if result != napi::ValueType::External {\n        return None;\n    }\n\n    // As a future improvement, this could be done with a dynamic symbol check instead of\n    // relying on the Node-API version compatibility at compile time.\n    #[cfg(feature = \"napi-8\")]\n    // Check the external came from this module\n    if !super::tag::check_object_type_tag(env, local, &crate::MODULE_TAG) {\n        return None;\n    }\n\n    let mut result = MaybeUninit::uninit();\n    napi::get_value_external(env, local, result.as_mut_ptr()).unwrap();\n\n    let v = result.assume_init();\n    let v = &**v.cast_const().cast::<DebugSendWrapper<T>>() as *const T;\n\n    Some(v)\n}\n\n/// Creates a `napi_external` from a Rust type\npub unsafe fn create<T: 'static>(env: Env, v: T, finalizer: fn(Env, T)) -> Local {\n    let v = Box::new(DebugSendWrapper::new(v));\n    let mut result = MaybeUninit::uninit();\n\n    let status = napi::create_external(\n        env,\n        Box::into_raw(v) as *mut _,\n        Some(finalize_external::<T>),\n        // Casting to `*const ()` is required to ensure the correct layout\n        // https://rust-lang.github.io/unsafe-code-guidelines/layout/function-pointers.html\n        finalizer as *const () as *mut _,\n        result.as_mut_ptr(),\n    );\n\n    // `napi_create_external` will only fail if the VM is in a throwing state\n    // or shutting down.\n    status.unwrap();\n\n    let external = result.assume_init();\n\n    #[cfg(feature = \"napi-8\")]\n    // Tag the object as coming from this module\n    super::tag::type_tag_object(env, external, &crate::MODULE_TAG);\n\n    external\n}\n"
  },
  {
    "path": "crates/neon/src/sys/fun.rs",
    "content": "//! Facilities for working with JS functions.\n\nuse std::{mem::MaybeUninit, os::raw::c_void, ptr};\n\nuse super::{\n    bindings as napi,\n    raw::{Env, Local},\n};\n\npub unsafe fn new<F>(env: Env, name: &str, callback: F) -> Result<Local, napi::Status>\nwhere\n    F: Fn(Env, napi::CallbackInfo) -> Local + 'static,\n{\n    let mut out = MaybeUninit::uninit();\n    let data = Box::into_raw(Box::new(callback));\n    let status = napi::create_function(\n        env,\n        name.as_ptr().cast(),\n        name.len(),\n        Some(call_boxed::<F>),\n        data.cast(),\n        out.as_mut_ptr(),\n    );\n\n    match status {\n        Err(err @ napi::Status::PendingException) => {\n            drop(Box::from_raw(data));\n\n            return Err(err);\n        }\n        status => status.unwrap(),\n    };\n\n    let out = out.assume_init();\n\n    #[cfg(feature = \"napi-5\")]\n    {\n        unsafe extern \"C\" fn drop_function<F>(\n            _env: Env,\n            _finalize_data: *mut c_void,\n            finalize_hint: *mut c_void,\n        ) {\n            drop(Box::from_raw(finalize_hint.cast::<F>()));\n        }\n\n        let status = napi::add_finalizer(\n            env,\n            out,\n            ptr::null_mut(),\n            Some(drop_function::<F>),\n            data.cast(),\n            ptr::null_mut(),\n        );\n\n        // If adding the finalizer fails the closure will leak, but it would\n        // be unsafe to drop it because there's no guarantee V8 won't use the\n        // pointer.\n        status.unwrap();\n    }\n\n    Ok(out)\n}\n\n// C ABI compatible function for invoking a boxed closure from the data field\n// of a Node-API JavaScript function\nunsafe extern \"C\" fn call_boxed<F>(env: Env, info: napi::CallbackInfo) -> Local\nwhere\n    F: Fn(Env, napi::CallbackInfo) -> Local + 'static,\n{\n    let mut data = MaybeUninit::uninit();\n    napi::get_cb_info(\n        env,\n        info,\n        ptr::null_mut(),\n        ptr::null_mut(),\n        ptr::null_mut(),\n        data.as_mut_ptr(),\n    )\n    .unwrap();\n\n    let callback = &*data.assume_init().cast::<F>();\n\n    callback(env, info)\n}\n\npub unsafe fn construct(\n    out: &mut Local,\n    env: Env,\n    fun: Local,\n    argc: usize,\n    argv: *const c_void,\n) -> bool {\n    let status = napi::new_instance(env, fun, argc, argv as *const _, out as *mut _);\n\n    status.is_ok()\n}\n"
  },
  {
    "path": "crates/neon/src/sys/lifecycle.rs",
    "content": "//! # Environment life cycle APIs\n//!\n//! These APIs map to the life cycle of a specific \"Agent\" or self-contained\n//! environment. If a Neon module is loaded multiple times (Web Workers, worker\n//! threads), these API will be handle data associated with a specific instance.\n//!\n//! See the [N-API Lifecycle][npai-docs] documentation for more details.\n//!\n//! [napi-docs]: https://nodejs.org/api/n-api.html#n_api_environment_life_cycle_apis\n\nuse std::{mem::MaybeUninit, os::raw::c_void, ptr};\n\nuse super::{bindings as napi, raw::Env};\n\n/// # Safety\n/// `env` must point to a valid `napi_env` for this thread\npub unsafe fn set_instance_data<T: Send + 'static>(env: Env, data: T) -> *mut T {\n    let data = Box::into_raw(Box::new(data));\n\n    napi::set_instance_data(env, data.cast(), Some(drop_box::<T>), ptr::null_mut()).unwrap();\n\n    data\n}\n\n/// # Safety\n/// * `T` must be the same type used in `set_instance_data`\n/// * Caller must ensure reference does not outlive `Env`\n/// * Return value may be `null`\n/// * `env` must point to a valid `napi_env` for this thread\npub unsafe fn get_instance_data<T: Send + 'static>(env: Env) -> *mut T {\n    let mut data = MaybeUninit::uninit();\n\n    napi::get_instance_data(env, data.as_mut_ptr()).unwrap();\n\n    data.assume_init().cast()\n}\n\nunsafe extern \"C\" fn drop_box<T>(_env: Env, data: *mut c_void, _hint: *mut c_void) {\n    drop(Box::<T>::from_raw(data.cast()));\n}\n"
  },
  {
    "path": "crates/neon/src/sys/mem.rs",
    "content": "use super::{\n    bindings as napi,\n    raw::{Env, Local},\n};\n\npub unsafe fn strict_equals(env: Env, lhs: Local, rhs: Local) -> bool {\n    let mut result = false;\n    napi::strict_equals(env, lhs, rhs, &mut result as *mut _).unwrap();\n    result\n}\n"
  },
  {
    "path": "crates/neon/src/sys/mod.rs",
    "content": "//! Raw bindings to [Node-API][node-api]\n//!\n//! [Node-API][node-api] is Node.js's API for building native addons. Neon is\n//! predominantly a safe wrapper for Node-API and most users should prefer the\n//! the high level abstractions [outside](crate) of the sys module.\n//!\n//! However, directly using Node-API can be a useful tool for accessing low\n//! level functionality not exposed by Neon or experimenting with extensions\n//! to Neon without needing to fork the project.\n//!\n//! [node-api]: https://nodejs.org/api/n-api.html\n//!\n//! ## Initialization\n//!\n//! Before any Node-API functions may be used, [`setup`] must be called at\n//! least once.\n//!\n//! ```rust,no_run\n//! # #[cfg(feature = \"sys\")]\n//! # {\n//! # let env = std::ptr::null_mut().cast();\n//! unsafe { neon::sys::setup(env); }\n//! # }\n//! ```\n//! **Note**: It is unnecessary to call [`setup`] if\n//! [`#[neon::main]`](crate::main) is used to initialize the addon.\n//!\n//! ## Safety\n//!\n//! The following are guidelines for ensuring safe usage of Node-API in Neon\n//! but, do not represent a comprehensive set of safety rules. If possible,\n//! users should avoid calling Neon methods or holding references to structures\n//! created by Neon when calling Node-API functions directly.\n//!\n//! ### Env\n//!\n//! Neon ensures safety by carefully restricting access to [`Env`]\n//! by wrapping it in a [`Context`](crate::context::Context). Usages of `Env`\n//! should follow Neon's borrowing rules of `Context`.\n//!\n//! It is unsound to use an `Env` if Rust's borrowing rules would prevent usage\n//! of the in scope `Context`.\n//!\n//! ### Values\n//!\n//! Neon [value types](crate::types) encapsulate references to\n//! [JavaScript values](bindings::Value) with a _known type_. It is unsound to\n//! construct a Neon value with a [`Value`] of the incorrect type.\n//!\n//! ## Example\n//!\n//! ```rust,no_run\n//! # #[cfg(feature = \"sys\")]\n//! # {\n//! # let env = std::ptr::null_mut().cast();\n//! use neon::{context::Cx, prelude::*, sys::bindings};\n//!\n//! let cx = unsafe {\n//!     neon::sys::setup(env);\n//!\n//!     Cx::from_raw(env)\n//! };\n//!\n//! let raw_string: bindings::Value = cx.string(\"Hello, World!\").to_raw();\n//! let js_string = unsafe { JsString::from_raw(&cx, raw_string) };\n//! # }\n//! ```\nuse std::{mem::MaybeUninit, sync::Once};\n\n// Bindings are re-exported here to minimize changes.\n// Follow-up issue: https://github.com/neon-bindings/neon/issues/982\npub(crate) use bindings::*;\n\npub(crate) mod array;\npub(crate) mod arraybuffer;\npub(crate) mod async_work;\npub(crate) mod buffer;\npub(crate) mod call;\npub(crate) mod convert;\npub(crate) mod error;\npub(crate) mod external;\npub(crate) mod fun;\npub(crate) mod mem;\npub(crate) mod no_panic;\npub(crate) mod object;\npub(crate) mod primitive;\npub(crate) mod promise;\npub(crate) mod raw;\npub(crate) mod reference;\npub(crate) mod scope;\npub(crate) mod string;\npub(crate) mod tag;\npub(crate) mod typedarray;\n\npub mod bindings;\n\n#[cfg(feature = \"napi-4\")]\npub(crate) mod tsfn;\n\n#[cfg(feature = \"napi-5\")]\npub(crate) mod date;\n\nmod debug_send_wrapper;\n#[cfg(feature = \"napi-6\")]\npub(crate) mod lifecycle;\n\n/// Create a JavaScript `String`, panicking if unsuccessful\n///\n/// # Safety\n/// * `env` is a `napi_env` valid for the current thread\n/// * The returned value does not outlive `env`\nunsafe fn string(env: Env, s: impl AsRef<str>) -> raw::Local {\n    let s = s.as_ref();\n    let mut result = MaybeUninit::uninit();\n\n    create_string_utf8(\n        env,\n        s.as_bytes().as_ptr() as *const _,\n        s.len(),\n        result.as_mut_ptr(),\n    )\n    .unwrap();\n\n    result.assume_init()\n}\n\nstatic SETUP: Once = Once::new();\n\n/// Loads Node-API symbols from the host process.\n///\n/// Must be called at least once before using any functions in bindings or\n/// they will panic.\n///\n/// # Safety\n/// `env` must be a valid `napi_env` for the current thread\npub unsafe fn setup(env: Env) {\n    SETUP.call_once(|| load(env).expect(\"Failed to load N-API symbols\"));\n}\n"
  },
  {
    "path": "crates/neon/src/sys/no_panic.rs",
    "content": "//! Utilities that _will_ not panic for use in contexts where unwinding would be\n//! undefined behavior.\n//!\n//! The following helpers do not panic and instead use `napi_fatal_error`\n//! to crash the process in a controlled way, making them safe for use in FFI\n//! callbacks.\n//!\n//! `#[track_caller]` is used on these helpers to ensure `fatal_error` reports\n//! the calling location instead of the helpers defined here.\n\nuse std::{\n    any::Any,\n    ffi::c_void,\n    mem::MaybeUninit,\n    panic::{catch_unwind, AssertUnwindSafe},\n    ptr,\n};\n\nuse super::{\n    bindings as napi,\n    debug_send_wrapper::DebugSendWrapper,\n    error::fatal_error,\n    raw::{Env, Local},\n};\n\ntype Panic = Box<dyn Any + Send + 'static>;\n\nconst UNKNOWN_PANIC_MESSAGE: &str = \"Unknown panic\";\n\n/// `FailureBoundary`] acts as boundary between Rust and FFI code, protecting\n/// a critical section of code from unhandled failure. It will catch both Rust\n/// panics and JavaScript exceptions. Attempts to handle failures are executed\n/// in order of ascending severity:\n///\n/// 1. Reject a `Promise` if a `Deferred` was provided\n/// 2. Emit a fatal exception\n/// 3. Abort the process with a message and location\n///\n/// This process will be aborted if any step unrecoverably fails. For example,\n/// if a `napi::Env` is unavailable, it is impossible to reject a `Promise` or\n/// emit a fatal exception.\npub struct FailureBoundary {\n    pub both: &'static str,\n    pub exception: &'static str,\n    pub panic: &'static str,\n}\n\nimpl FailureBoundary {\n    #[track_caller]\n    pub unsafe fn catch_failure<F>(&self, env: Env, deferred: Option<napi::Deferred>, f: F)\n    where\n        F: FnOnce(Option<Env>) -> Local,\n    {\n        // Make `env = None` if unable to call into JS\n        #[allow(clippy::unnecessary_lazy_evaluations)]\n        let env = can_call_into_js(env).then(|| env);\n\n        // Run the user supplied callback, catching panics\n        // This is unwind safe because control is never yielded back to the caller\n        let panic = catch_unwind(AssertUnwindSafe(move || f(env)));\n\n        // Unwrap the `Env`\n        let env = if let Some(env) = env {\n            env\n        } else {\n            // If there was a panic and we don't have an `Env`, crash the process\n            if let Err(panic) = panic {\n                let msg = panic_msg(&panic).unwrap_or(UNKNOWN_PANIC_MESSAGE);\n\n                fatal_error(msg);\n            }\n\n            // If we don't have an `Env`, we can't catch an exception, nothing more to try\n            return;\n        };\n\n        // Check and catch a thrown exception\n        let exception = catch_exception(env);\n\n        // Create an error message or return if there wasn't a panic or exception\n        let msg = match (exception, panic.as_ref()) {\n            // Exception and a panic\n            (Some(_), Err(_)) => self.both,\n\n            // Exception, but not a panic\n            (Some(err), Ok(_)) => {\n                // Reject the promise without wrapping\n                if let Some(deferred) = deferred {\n                    reject_deferred(env, deferred, err);\n\n                    return;\n                }\n\n                self.exception\n            }\n\n            // Panic, but not an exception\n            (None, Err(_)) => self.panic,\n\n            // No errors occurred! We're done!\n            (None, Ok(value)) => {\n                if let Some(deferred) = deferred {\n                    resolve_deferred(env, deferred, *value);\n                }\n\n                return;\n            }\n        };\n\n        // Reject the promise\n        if let Some(deferred) = deferred {\n            let error = create_error(env, msg, exception, panic.err());\n\n            reject_deferred(env, deferred, error);\n\n            return;\n        }\n\n        let error = create_error(env, msg, exception, panic.err());\n\n        // Trigger a fatal exception\n        fatal_exception(env, error);\n    }\n}\n\n// HACK: Force `NAPI_PREAMBLE` to run without executing any JavaScript to tell if it's\n// possible to call into JS.\n//\n// `NAPI_PREAMBLE` is a macro that checks if it is possible to call into JS.\n// https://github.com/nodejs/node/blob/5fad0b93667ffc6e4def52996b9529ac99b26319/src/js_native_api_v8.h#L211-L218\n//\n//  `napi_throw` starts by using `NAPI_PREAMBLE` and then a `CHECK_ARGS` on the `napi_value`. Since\n// we already know `env` is non-null, we expect the `null` value to cause a `napi_invalid_arg` error.\n// https://github.com/nodejs/node/blob/5fad0b93667ffc6e4def52996b9529ac99b26319/src/js_native_api_v8.cc#L1925-L1926\nfn can_call_into_js(env: Env) -> bool {\n    !env.is_null() && unsafe { napi::throw(env, ptr::null_mut()) == Err(napi::Status::InvalidArg) }\n}\n\n// We cannot use `napi_fatal_exception` because of this bug; instead, cause an\n// unhandled rejection which has similar behavior on recent versions of Node.\n// https://github.com/nodejs/node/issues/33771\nunsafe fn fatal_exception(env: Env, error: Local) {\n    let mut deferred = MaybeUninit::uninit();\n    let mut promise = MaybeUninit::uninit();\n\n    let deferred = match napi::create_promise(env, deferred.as_mut_ptr(), promise.as_mut_ptr()) {\n        Ok(()) => deferred.assume_init(),\n        _ => fatal_error(\"Failed to create a promise\"),\n    };\n\n    if napi::reject_deferred(env, deferred, error) != Ok(()) {\n        fatal_error(\"Failed to reject a promise\");\n    }\n}\n\n#[track_caller]\nunsafe fn create_error(\n    env: Env,\n    msg: &str,\n    exception: Option<Local>,\n    panic: Option<Panic>,\n) -> Local {\n    // Construct the `uncaughtException` Error object\n    let error = error_from_message(env, msg);\n\n    // Add the exception to the error\n    if let Some(exception) = exception {\n        set_property(env, error, \"cause\", exception);\n    };\n\n    // Add the panic to the error\n    if let Some(panic) = panic {\n        set_property(env, error, \"panic\", error_from_panic(env, panic));\n    }\n\n    error\n}\n\n#[track_caller]\nunsafe fn resolve_deferred(env: Env, deferred: napi::Deferred, value: Local) {\n    if napi::resolve_deferred(env, deferred, value) != Ok(()) {\n        fatal_error(\"Failed to resolve promise\");\n    }\n}\n\n#[track_caller]\nunsafe fn reject_deferred(env: Env, deferred: napi::Deferred, value: Local) {\n    if napi::reject_deferred(env, deferred, value) != Ok(()) {\n        fatal_error(\"Failed to reject promise\");\n    }\n}\n\n#[track_caller]\nunsafe fn catch_exception(env: Env) -> Option<Local> {\n    if !is_exception_pending(env) {\n        return None;\n    }\n\n    let mut error = MaybeUninit::uninit();\n\n    if napi::get_and_clear_last_exception(env, error.as_mut_ptr()) != Ok(()) {\n        fatal_error(\"Failed to get and clear the last exception\");\n    }\n\n    Some(error.assume_init())\n}\n\n#[track_caller]\nunsafe fn error_from_message(env: Env, msg: &str) -> Local {\n    let msg = create_string(env, msg);\n    let mut err = MaybeUninit::uninit();\n\n    let status = napi::create_error(env, ptr::null_mut(), msg, err.as_mut_ptr());\n\n    match status {\n        Ok(()) => err.assume_init(),\n        Err(_) => fatal_error(\"Failed to create an Error\"),\n    }\n}\n\n#[track_caller]\nunsafe fn error_from_panic(env: Env, panic: Panic) -> Local {\n    if let Some(msg) = panic_msg(&panic) {\n        error_from_message(env, msg)\n    } else {\n        let error = error_from_message(env, UNKNOWN_PANIC_MESSAGE);\n        let panic = external_from_panic(env, panic);\n\n        set_property(env, error, \"cause\", panic);\n        error\n    }\n}\n\n#[track_caller]\nunsafe fn set_property(env: Env, object: Local, key: &str, value: Local) {\n    let key = create_string(env, key);\n\n    if napi::set_property(env, object, key, value).is_err() {\n        fatal_error(\"Failed to set an object property\");\n    }\n}\n\n#[track_caller]\nunsafe fn panic_msg(panic: &Panic) -> Option<&str> {\n    if let Some(msg) = panic.downcast_ref::<&str>() {\n        Some(msg)\n    } else if let Some(msg) = panic.downcast_ref::<String>() {\n        Some(msg)\n    } else {\n        None\n    }\n}\n\nunsafe fn external_from_panic(env: Env, panic: Panic) -> Local {\n    let fail = || fatal_error(\"Failed to create a neon::types::JsBox from a panic\");\n    let mut result = MaybeUninit::uninit();\n\n    if napi::create_external(\n        env,\n        Box::into_raw(Box::new(DebugSendWrapper::new(panic))).cast(),\n        Some(finalize_panic),\n        ptr::null_mut(),\n        result.as_mut_ptr(),\n    )\n    .is_err()\n    {\n        fail();\n    }\n\n    let external = result.assume_init();\n\n    #[cfg(feature = \"napi-8\")]\n    if napi::type_tag_object(env, external, &*crate::MODULE_TAG).is_err() {\n        fail();\n    }\n\n    external\n}\n\nextern \"C\" fn finalize_panic(_env: Env, data: *mut c_void, _hint: *mut c_void) {\n    unsafe {\n        drop(Box::from_raw(data.cast::<Panic>()));\n    }\n}\n\n#[track_caller]\nunsafe fn create_string(env: Env, msg: &str) -> Local {\n    let mut string = MaybeUninit::uninit();\n\n    if napi::create_string_utf8(env, msg.as_ptr().cast(), msg.len(), string.as_mut_ptr()).is_err() {\n        fatal_error(\"Failed to create a String\");\n    }\n\n    string.assume_init()\n}\n\nunsafe fn is_exception_pending(env: Env) -> bool {\n    let mut throwing = false;\n\n    if napi::is_exception_pending(env, &mut throwing).is_err() {\n        fatal_error(\"Failed to check if an exception is pending\");\n    }\n\n    throwing\n}\n"
  },
  {
    "path": "crates/neon/src/sys/object.rs",
    "content": "use std::mem::MaybeUninit;\n\nuse super::{\n    bindings as napi,\n    raw::{Env, Local},\n};\n\n/// Mutates the `out` argument to refer to a `napi_value` containing a newly created JavaScript Object.\npub unsafe fn new(out: &mut Local, env: Env) {\n    napi::create_object(env, out as *mut _).unwrap();\n}\n\n#[cfg(feature = \"napi-8\")]\npub unsafe fn freeze(env: Env, obj: Local) -> Result<(), napi::Status> {\n    let status = napi::object_freeze(env, obj);\n    debug_assert!(matches!(\n        status,\n        Ok(()) | Err(napi::Status::PendingException | napi::Status::GenericFailure)\n    ));\n    status\n}\n\n#[cfg(feature = \"napi-8\")]\npub unsafe fn seal(env: Env, obj: Local) -> Result<(), napi::Status> {\n    napi::object_seal(env, obj)\n}\n\n#[cfg(feature = \"napi-6\")]\n/// Mutates the `out` argument to refer to a `napi_value` containing the own property names of the\n/// `object` as a JavaScript Array.\npub unsafe fn get_own_property_names(out: &mut Local, env: Env, object: Local) -> bool {\n    let mut property_names = MaybeUninit::uninit();\n\n    match napi::get_all_property_names(\n        env,\n        object,\n        napi::KeyCollectionMode::OwnOnly,\n        napi::KeyFilter::ALL_PROPERTIES | napi::KeyFilter::SKIP_SYMBOLS,\n        napi::KeyConversion::NumbersToStrings,\n        property_names.as_mut_ptr(),\n    ) {\n        Err(napi::Status::PendingException) => return false,\n        status => status.unwrap(),\n    }\n\n    *out = property_names.assume_init();\n\n    true\n}\n\n/// Mutate the `out` argument to refer to the value at `index` in the given `object`. Returns `false` if the value couldn't be retrieved.\npub unsafe fn get_index(out: &mut Local, env: Env, object: Local, index: u32) -> bool {\n    let status = napi::get_element(env, object, index, out as *mut _);\n\n    status.is_ok()\n}\n\n/// Sets the key value of a `napi_value` at the `index` provided. Returns `true` if the set\n/// succeeded.\n///\n/// The `out` parameter and the return value contain the same information for historical reasons,\n/// see [discussion].\n///\n/// [discussion]: https://github.com/neon-bindings/neon/pull/458#discussion_r344827965\npub unsafe fn set_index(out: &mut bool, env: Env, object: Local, index: u32, val: Local) -> bool {\n    let status = napi::set_element(env, object, index, val);\n    *out = status.is_ok();\n\n    *out\n}\n\n/// Mutate the `out` argument to refer to the value at a named `key` in the given `object`. Returns `false` if the value couldn't be retrieved.\npub unsafe fn get_string(\n    env: Env,\n    out: &mut Local,\n    object: Local,\n    key: *const u8,\n    len: i32,\n) -> bool {\n    let mut key_val = MaybeUninit::uninit();\n\n    // Not using `crate::string::new()` because it requires a _reference_ to a Local,\n    // while we only have uninitialized memory.\n    match napi::create_string_utf8(env, key as *const _, len as usize, key_val.as_mut_ptr()) {\n        Err(napi::Status::PendingException) => return false,\n        status => status.unwrap(),\n    }\n\n    // Not using napi_get_named_property() because the `key` may not be null terminated.\n    match napi::get_property(env, object, key_val.assume_init(), out as *mut _) {\n        Err(napi::Status::PendingException) => return false,\n        status => status.unwrap(),\n    }\n\n    true\n}\n\n/// Sets the key value of a `napi_value` at a named key. Returns `true` if the set succeeded.\n///\n/// The `out` parameter and the return value contain the same information for historical reasons,\n/// see [discussion].\n///\n/// [discussion]: https://github.com/neon-bindings/neon/pull/458#discussion_r344827965\npub unsafe fn set_string(\n    env: Env,\n    out: &mut bool,\n    object: Local,\n    key: *const u8,\n    len: i32,\n    val: Local,\n) -> bool {\n    let mut key_val = MaybeUninit::uninit();\n\n    *out = true;\n\n    match napi::create_string_utf8(env, key as *const _, len as usize, key_val.as_mut_ptr()) {\n        Err(napi::Status::PendingException) => {\n            *out = false;\n            return false;\n        }\n        status => status.unwrap(),\n    }\n\n    match napi::set_property(env, object, key_val.assume_init(), val) {\n        Err(napi::Status::PendingException) => {\n            *out = false;\n            return false;\n        }\n        status => status.unwrap(),\n    }\n\n    true\n}\n\n/// Mutates `out` to refer to the value of the property of `object` named by the `key` value.\n/// Returns false if the value couldn't be retrieved.\npub unsafe fn get(out: &mut Local, env: Env, object: Local, key: Local) -> bool {\n    let status = napi::get_property(env, object, key, out as *mut _);\n\n    status.is_ok()\n}\n\n/// Sets the property value of an `napi_value` object, named by another `value` `key`. Returns `true` if the set succeeded.\n///\n/// The `out` parameter and the return value contain the same information for historical reasons,\n/// see [discussion].\n///\n/// [discussion]: https://github.com/neon-bindings/neon/pull/458#discussion_r344827965\npub unsafe fn set(out: &mut bool, env: Env, object: Local, key: Local, val: Local) -> bool {\n    let status = napi::set_property(env, object, key, val);\n    *out = status.is_ok();\n\n    *out\n}\n"
  },
  {
    "path": "crates/neon/src/sys/primitive.rs",
    "content": "use super::{\n    bindings as napi,\n    raw::{Env, Local},\n};\n\n/// Mutates the `out` argument provided to refer to the global `undefined` object.\npub unsafe fn undefined(out: &mut Local, env: Env) {\n    napi::get_undefined(env, out as *mut Local).unwrap();\n}\n\n/// Mutates the `out` argument provided to refer to the global `null` object.\npub unsafe fn null(out: &mut Local, env: Env) {\n    napi::get_null(env, out as *mut Local).unwrap();\n}\n\n/// Mutates the `out` argument provided to refer to one of the global `true` or `false` objects.\npub unsafe fn boolean(out: &mut Local, env: Env, b: bool) {\n    napi::get_boolean(env, b, out as *mut Local).unwrap();\n}\n\n/// Get the boolean value out of a `Local` object. If the `Local` object does not contain a\n/// boolean, this function panics.\npub unsafe fn boolean_value(env: Env, p: Local) -> bool {\n    let mut value = false;\n    assert_eq!(\n        napi::get_value_bool(env, p, &mut value as *mut bool),\n        Ok(())\n    );\n    value\n}\n\n/// Mutates the `out` argument provided to refer to a newly created `Local` containing a\n/// JavaScript number.\npub unsafe fn number(out: &mut Local, env: Env, v: f64) {\n    napi::create_double(env, v, out as *mut Local).unwrap();\n}\n\n/// Gets the underlying value of an `Local` object containing a JavaScript number. Panics if\n/// the given `Local` is not a number.\npub unsafe fn number_value(env: Env, p: Local) -> f64 {\n    let mut value = 0.0;\n    napi::get_value_double(env, p, &mut value as *mut f64).unwrap();\n    value\n}\n"
  },
  {
    "path": "crates/neon/src/sys/promise.rs",
    "content": "//! JavaScript Promise and Deferred handle\n//!\n//! See: [Promises in Node-API](https://nodejs.org/api/n-api.html#n_api_promises)\n\nuse std::mem::MaybeUninit;\n\nuse super::{bindings as napi, raw::Env};\n\n/// Create a `Promise` and a `napi::Deferred` handle for resolving it\n///\n/// # Safety\n/// * `env` is a valid `napi_env` for the current thread\n/// * The returned `napi::Value` does not outlive `env`\npub unsafe fn create(env: Env) -> (napi::Deferred, napi::Value) {\n    let mut deferred = MaybeUninit::uninit();\n    let mut promise = MaybeUninit::uninit();\n\n    napi::create_promise(env, deferred.as_mut_ptr(), promise.as_mut_ptr()).unwrap();\n\n    (deferred.assume_init(), promise.assume_init())\n}\n\n/// Resolve a promise from a `napi::Deferred` handle\n///\n/// # Safety\n/// * `env` is a valid `napi_env` for the current thread\n/// * `resolution` is a valid `napi::Value`\npub unsafe fn resolve(env: Env, deferred: napi::Deferred, resolution: napi::Value) {\n    napi::resolve_deferred(env, deferred, resolution).unwrap();\n}\n\n/// Rejects a promise from a `napi::Deferred` handle\n///\n/// # Safety\n/// * `env` is a valid `napi_env` for the current thread\n/// * `rejection` is a valid `napi::Value`\npub unsafe fn reject(env: Env, deferred: napi::Deferred, rejection: napi::Value) {\n    napi::reject_deferred(env, deferred, rejection).unwrap();\n}\n\n#[cfg(feature = \"napi-6\")]\n/// Rejects a promise from a `napi::Deferred` handle with a string message\n///\n/// # Safety\n/// * `env` is a valid `napi_env` for the current thread\npub unsafe fn reject_err_message(env: Env, deferred: napi::Deferred, msg: impl AsRef<str>) {\n    let msg = super::string(env, msg);\n    let mut err = MaybeUninit::uninit();\n\n    napi::create_error(env, std::ptr::null_mut(), msg, err.as_mut_ptr()).unwrap();\n\n    reject(env, deferred, err.assume_init());\n}\n"
  },
  {
    "path": "crates/neon/src/sys/raw.rs",
    "content": "use super::bindings as napi;\n\npub type Local = napi::Value;\n\npub type FunctionCallbackInfo = napi::CallbackInfo;\n\npub type Env = napi::Env;\n"
  },
  {
    "path": "crates/neon/src/sys/reference.rs",
    "content": "use std::mem::MaybeUninit;\n\nuse super::{\n    bindings as napi,\n    raw::{Env, Local},\n};\n\npub unsafe fn new(env: Env, value: Local) -> napi::Ref {\n    let mut result = MaybeUninit::uninit();\n\n    napi::create_reference(env, value, 1, result.as_mut_ptr()).unwrap();\n\n    result.assume_init()\n}\n\n/// # Safety\n/// Must only be used from the same module context that created the reference\npub unsafe fn reference(env: Env, value: napi::Ref) -> usize {\n    let mut result = MaybeUninit::uninit();\n\n    napi::reference_ref(env, value, result.as_mut_ptr()).unwrap();\n\n    result.assume_init() as usize\n}\n\n/// # Safety\n/// Must only be used from the same module context that created the reference\npub unsafe fn unreference(env: Env, value: napi::Ref) {\n    let mut result = MaybeUninit::uninit();\n\n    napi::reference_unref(env, value, result.as_mut_ptr()).unwrap();\n\n    if result.assume_init() == 0 {\n        napi::delete_reference(env, value).unwrap();\n    }\n}\n\n/// # Safety\n/// Must only be used from the same module context that created the reference\npub unsafe fn get(env: Env, value: napi::Ref) -> Local {\n    let mut result = MaybeUninit::uninit();\n\n    napi::get_reference_value(env, value, result.as_mut_ptr()).unwrap();\n\n    result.assume_init()\n}\n"
  },
  {
    "path": "crates/neon/src/sys/scope.rs",
    "content": "use std::mem::MaybeUninit;\n\nuse super::{\n    bindings as napi,\n    raw::{Env, Local},\n};\n\npub(crate) struct HandleScope {\n    env: Env,\n    scope: napi::HandleScope,\n}\n\nimpl HandleScope {\n    pub(crate) unsafe fn new(env: Env) -> Self {\n        let mut scope = MaybeUninit::uninit();\n\n        napi::open_handle_scope(env, scope.as_mut_ptr()).unwrap();\n\n        Self {\n            env,\n            scope: scope.assume_init(),\n        }\n    }\n}\n\nimpl Drop for HandleScope {\n    fn drop(&mut self) {\n        unsafe {\n            let _status = napi::close_handle_scope(self.env, self.scope);\n\n            debug_assert_eq!(_status, Ok(()),);\n        }\n    }\n}\n\npub(crate) struct EscapableHandleScope {\n    env: Env,\n    scope: napi::EscapableHandleScope,\n}\n\nimpl EscapableHandleScope {\n    pub(crate) unsafe fn new(env: Env) -> Self {\n        let mut scope = MaybeUninit::uninit();\n\n        napi::open_escapable_handle_scope(env, scope.as_mut_ptr()).unwrap();\n\n        Self {\n            env,\n            scope: scope.assume_init(),\n        }\n    }\n\n    pub(crate) unsafe fn escape(&self, value: napi::Value) -> napi::Value {\n        let mut escapee = MaybeUninit::uninit();\n\n        napi::escape_handle(self.env, self.scope, value, escapee.as_mut_ptr()).unwrap();\n\n        escapee.assume_init()\n    }\n}\n\nimpl Drop for EscapableHandleScope {\n    fn drop(&mut self) {\n        unsafe {\n            let _status = napi::close_escapable_handle_scope(self.env, self.scope);\n\n            debug_assert_eq!(_status, Ok(()),);\n        }\n    }\n}\n\npub unsafe fn get_global(env: Env, out: &mut Local) {\n    super::get_global(env, out as *mut _).unwrap();\n}\n"
  },
  {
    "path": "crates/neon/src/sys/string.rs",
    "content": "use std::{mem::MaybeUninit, ptr};\n\nuse super::{\n    bindings as napi,\n    raw::{Env, Local},\n};\n\npub unsafe fn new(out: &mut Local, env: Env, data: *const u8, len: i32) -> bool {\n    let status = napi::create_string_utf8(env, data as *const _, len as usize, out);\n\n    status.is_ok()\n}\n\npub unsafe fn utf8_len(env: Env, value: Local) -> usize {\n    let mut len = MaybeUninit::uninit();\n    napi::get_value_string_utf8(env, value, ptr::null_mut(), 0, len.as_mut_ptr()).unwrap();\n\n    len.assume_init()\n}\n\npub unsafe fn data(env: Env, out: *mut u8, len: usize, value: Local) -> usize {\n    let mut read = MaybeUninit::uninit();\n\n    napi::get_value_string_utf8(env, value, out as *mut _, len, read.as_mut_ptr()).unwrap();\n\n    read.assume_init()\n}\n\npub unsafe fn utf16_len(env: Env, value: Local) -> usize {\n    let mut len = MaybeUninit::uninit();\n\n    napi::get_value_string_utf16(env, value, ptr::null_mut(), 0, len.as_mut_ptr()).unwrap();\n\n    len.assume_init()\n}\n\npub unsafe fn data_utf16(env: Env, out: *mut u16, len: usize, value: Local) -> usize {\n    let mut read = MaybeUninit::uninit();\n    napi::get_value_string_utf16(env, value, out, len, read.as_mut_ptr()).unwrap();\n\n    read.assume_init()\n}\n\npub unsafe fn run_script(out: &mut Local, env: Env, value: Local) -> bool {\n    let status = napi::run_script(env, value, out as *mut _);\n\n    status == Ok(())\n}\n"
  },
  {
    "path": "crates/neon/src/sys/tag.rs",
    "content": "use super::{\n    bindings as napi,\n    raw::{Env, Local},\n};\n\n/// Return true if an `napi_value` `val` has the expected value type.\nunsafe fn is_type(env: Env, val: Local, expect: napi::ValueType) -> bool {\n    let mut actual = napi::ValueType::Undefined;\n    napi::typeof_value(env, val, &mut actual as *mut _).unwrap();\n    actual == expect\n}\n\npub unsafe fn is_undefined(env: Env, val: Local) -> bool {\n    is_type(env, val, napi::ValueType::Undefined)\n}\n\npub unsafe fn is_null(env: Env, val: Local) -> bool {\n    is_type(env, val, napi::ValueType::Null)\n}\n\n/// Is `val` a JavaScript number?\npub unsafe fn is_number(env: Env, val: Local) -> bool {\n    is_type(env, val, napi::ValueType::Number)\n}\n\n/// Is `val` a JavaScript boolean?\npub unsafe fn is_boolean(env: Env, val: Local) -> bool {\n    is_type(env, val, napi::ValueType::Boolean)\n}\n\n/// Is `val` a JavaScript string?\npub unsafe fn is_string(env: Env, val: Local) -> bool {\n    is_type(env, val, napi::ValueType::String)\n}\n\npub unsafe fn is_object(env: Env, val: Local) -> bool {\n    is_type(env, val, napi::ValueType::Object)\n}\n\npub unsafe fn is_array(env: Env, val: Local) -> bool {\n    let mut result = false;\n    napi::is_array(env, val, &mut result as *mut _).unwrap();\n    result\n}\n\npub unsafe fn is_function(env: Env, val: Local) -> bool {\n    is_type(env, val, napi::ValueType::Function)\n}\n\npub unsafe fn is_error(env: Env, val: Local) -> bool {\n    let mut result = false;\n    napi::is_error(env, val, &mut result as *mut _).unwrap();\n    result\n}\n\n/// Is `val` a Node.js Buffer instance?\npub unsafe fn is_buffer(env: Env, val: Local) -> bool {\n    let mut result = false;\n    napi::is_buffer(env, val, &mut result as *mut _).unwrap();\n    result\n}\n\n/// Is `val` an ArrayBuffer instance?\npub unsafe fn is_arraybuffer(env: Env, val: Local) -> bool {\n    let mut result = false;\n    napi::is_arraybuffer(env, val, &mut result as *mut _).unwrap();\n    result\n}\n\n/// Is `val` a TypedArray instance?\npub unsafe fn is_typedarray(env: Env, val: Local) -> bool {\n    let mut result = false;\n    napi::is_typedarray(env, val, &mut result as *mut _).unwrap();\n    result\n}\n\n#[cfg(feature = \"napi-5\")]\npub unsafe fn is_date(env: Env, val: Local) -> bool {\n    let mut result = false;\n    napi::is_date(env, val, &mut result as *mut _).unwrap();\n    result\n}\n\n/// Is `val` a Promise?\n///\n/// # Safety\n/// * `env` is a valid `napi_env` for the current thread\npub unsafe fn is_promise(env: Env, val: Local) -> bool {\n    let mut result = false;\n    napi::is_promise(env, val, &mut result as *mut _).unwrap();\n    result\n}\n\n#[cfg(feature = \"napi-8\")]\npub unsafe fn type_tag_object(env: Env, object: Local, tag: &super::TypeTag) {\n    napi::type_tag_object(env, object, tag as *const _).unwrap();\n}\n\n#[cfg(feature = \"napi-8\")]\npub unsafe fn check_object_type_tag(env: Env, object: Local, tag: &super::TypeTag) -> bool {\n    let mut result = false;\n\n    napi::check_object_type_tag(env, object, tag as *const _, &mut result as *mut _).unwrap();\n    result\n}\n\n#[cfg(feature = \"napi-6\")]\npub unsafe fn is_bigint(env: Env, val: Local) -> bool {\n    is_type(env, val, napi::ValueType::BigInt)\n}\n"
  },
  {
    "path": "crates/neon/src/sys/tsfn.rs",
    "content": "//! Idiomatic Rust wrappers for N-API threadsafe functions\n\nuse std::{\n    ffi::c_void,\n    mem::MaybeUninit,\n    ptr,\n    sync::{Arc, Mutex},\n};\n\nuse super::{bindings as napi, no_panic::FailureBoundary, raw::Env};\n\nconst BOUNDARY: FailureBoundary = FailureBoundary {\n    both: \"A panic and exception occurred while executing a `neon::event::Channel::send` callback\",\n    exception: \"An exception occurred while executing a `neon::event::Channel::send` callback\",\n    panic: \"A panic occurred while executing a `neon::event::Channel::send` callback\",\n};\n\n#[derive(Debug)]\nstruct Tsfn(napi::ThreadsafeFunction);\n\nunsafe impl Send for Tsfn {}\n\nunsafe impl Sync for Tsfn {}\n\n#[derive(Debug)]\n/// Threadsafe Function encapsulate a Rust function pointer and N-API threadsafe\n/// function for scheduling tasks to execute on a JavaScript thread.\npub struct ThreadsafeFunction<T> {\n    tsfn: Tsfn,\n    is_finalized: Arc<Mutex<bool>>,\n    callback: fn(Option<Env>, T),\n}\n\n#[derive(Debug)]\nstruct Callback<T> {\n    callback: fn(Option<Env>, T),\n    data: T,\n}\n\n/// Error returned when scheduling a threadsafe function with some data\npub struct CallError;\n\nimpl<T: Send + 'static> ThreadsafeFunction<T> {\n    /// Creates a new unbounded N-API Threadsafe Function\n    /// Safety: `Env` must be valid for the current thread\n    pub unsafe fn new(env: Env, callback: fn(Option<Env>, T)) -> Self {\n        Self::with_capacity(env, 0, callback)\n    }\n\n    /// Creates a bounded N-API Threadsafe Function\n    /// Safety: `Env` must be valid for the current thread\n    pub unsafe fn with_capacity(\n        env: Env,\n        max_queue_size: usize,\n        callback: fn(Option<Env>, T),\n    ) -> Self {\n        let mut result = MaybeUninit::uninit();\n        let is_finalized = Arc::new(Mutex::new(false));\n\n        assert_eq!(\n            napi::create_threadsafe_function(\n                env,\n                std::ptr::null_mut(),\n                std::ptr::null_mut(),\n                super::string(env, \"neon threadsafe function\"),\n                max_queue_size,\n                // Always set the reference count to 1. Prefer using\n                // Rust `Arc` to maintain the struct.\n                1,\n                Arc::into_raw(is_finalized.clone()) as *mut _,\n                Some(Self::finalize),\n                std::ptr::null_mut(),\n                Some(Self::callback),\n                result.as_mut_ptr(),\n            ),\n            Ok(()),\n        );\n\n        Self {\n            tsfn: Tsfn(result.assume_init()),\n            is_finalized,\n            callback,\n        }\n    }\n\n    /// Schedule a threadsafe function to be executed with some data\n    pub fn call(\n        &self,\n        data: T,\n        is_blocking: Option<napi::ThreadsafeFunctionCallMode>,\n    ) -> Result<(), CallError> {\n        let is_blocking = is_blocking.unwrap_or(napi::ThreadsafeFunctionCallMode::Blocking);\n\n        let callback = Box::into_raw(Box::new(Callback {\n            callback: self.callback,\n            data,\n        }));\n\n        // Hold the lock before entering `call_threadsafe_function` so that\n        // `finalize_cb` would never complete.\n        let mut is_finalized = self.is_finalized.lock().unwrap();\n\n        let status = {\n            if *is_finalized {\n                Err(napi::Status::Closing)\n            } else {\n                unsafe {\n                    napi::call_threadsafe_function(self.tsfn.0, callback as *mut _, is_blocking)\n                }\n            }\n        };\n\n        match status {\n            Ok(()) => Ok(()),\n            Err(status) => {\n                // Prevent further calls to `call_threadsafe_function`\n                if status == napi::Status::Closing {\n                    *is_finalized = true;\n                }\n\n                // If the call failed, the callback won't execute\n                let _ = unsafe { Box::from_raw(callback) };\n\n                Err(CallError)\n            }\n        }\n    }\n\n    /// References a threadsafe function to prevent exiting the event loop until it has been dropped. (Default)\n    /// Safety: `Env` must be valid for the current thread\n    pub unsafe fn reference(&self, env: Env) {\n        napi::ref_threadsafe_function(env, self.tsfn.0).unwrap();\n    }\n\n    /// Unreferences a threadsafe function to allow exiting the event loop before it has been dropped.\n    /// Safety: `Env` must be valid for the current thread\n    pub unsafe fn unref(&self, env: Env) {\n        napi::unref_threadsafe_function(env, self.tsfn.0).unwrap();\n    }\n\n    // Provides a C ABI wrapper for a napi callback notifying us about tsfn\n    // being finalized.\n    unsafe extern \"C\" fn finalize(_env: Env, data: *mut c_void, _hint: *mut c_void) {\n        let is_finalized = Arc::from_raw(data as *mut Mutex<bool>);\n\n        *is_finalized.lock().unwrap() = true;\n    }\n\n    // Provides a C ABI wrapper for invoking the user supplied function pointer\n    // On panic or exception, creates a fatal exception of the form:\n    // Error(msg: string) {\n    //     // Exception thrown\n    //     cause?: Error,\n    //     // Panic occurred\n    //     panic?: Error(msg: string) {\n    //         // Opaque panic type if it wasn't a string\n    //         cause?: JsBox<Panic>\n    //     }\n    // }\n    unsafe extern \"C\" fn callback(\n        env: Env,\n        _js_callback: napi::Value,\n        _context: *mut c_void,\n        data: *mut c_void,\n    ) {\n        let Callback { callback, data } = *Box::from_raw(data as *mut Callback<T>);\n\n        BOUNDARY.catch_failure(env, None, move |env| {\n            callback(env, data);\n            ptr::null_mut()\n        });\n    }\n}\n\nimpl<T> Drop for ThreadsafeFunction<T> {\n    fn drop(&mut self) {\n        let is_finalized = self.is_finalized.lock().unwrap();\n\n        // tsfn was already finalized by `Environment::CleanupHandles()` in Node.js\n        if *is_finalized {\n            return;\n        }\n\n        unsafe {\n            debug_assert_eq!(\n                napi::release_threadsafe_function(\n                    self.tsfn.0,\n                    napi::ThreadsafeFunctionReleaseMode::Release,\n                ),\n                Ok(())\n            );\n        };\n    }\n}\n"
  },
  {
    "path": "crates/neon/src/sys/typedarray.rs",
    "content": "use std::{ffi::c_void, mem::MaybeUninit};\n\nuse super::{\n    bindings::{self as napi, TypedArrayType},\n    raw::{Env, Local},\n};\n\n#[derive(Debug)]\n/// Information describing a JavaScript [`TypedArray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray)\npub struct TypedArrayInfo {\n    pub typ: TypedArrayType,\n    pub length: usize,\n    pub data: *mut c_void,\n    pub buf: Local,\n    pub offset: usize,\n}\n\n/// Get [information](TypedArrayInfo) describing a JavaScript `TypedArray`\n///\n/// # Safety\n/// * `env` must be valid `napi_env` for the current scope\n/// * `value` must be a handle pointing to a `TypedArray`\npub unsafe fn info(env: Env, value: Local) -> TypedArrayInfo {\n    let mut info = MaybeUninit::<TypedArrayInfo>::zeroed();\n    let ptr = info.as_mut_ptr();\n\n    assert_eq!(\n        napi::get_typedarray_info(\n            env,\n            value,\n            &mut (*ptr).typ,\n            &mut (*ptr).length,\n            &mut (*ptr).data,\n            &mut (*ptr).buf,\n            &mut (*ptr).offset,\n        ),\n        Ok(()),\n    );\n\n    info.assume_init()\n}\n\npub unsafe fn new(\n    env: Env,\n    typ: TypedArrayType,\n    buffer: Local,\n    offset: usize,\n    len: usize,\n) -> Result<Local, napi::Status> {\n    let mut array = MaybeUninit::uninit();\n    let status = napi::create_typedarray(env, typ, len, buffer, offset, array.as_mut_ptr());\n\n    match status {\n        Err(err @ napi::Status::PendingException) => return Err(err),\n        status => status.unwrap(),\n    };\n\n    Ok(array.assume_init())\n}\n"
  },
  {
    "path": "crates/neon/src/thread/mod.rs",
    "content": "//! Thread-local storage for JavaScript threads.\n//!\n//! At runtime, an instance of a Node.js addon can contain its own local storage,\n//! which can then be shared and accessed as needed from Rust in a Neon module. This can\n//! be useful for setting up long-lived state that needs to be shared between calls\n//! of an addon's APIs.\n//!\n//! For example, an addon may wish to track the [thread ID][threadId] of each of its\n//! instances:\n//!\n//! ```\n//! # use neon::prelude::*;\n//! # use neon::thread::LocalKey;\n//! static THREAD_ID: LocalKey<u32> = LocalKey::new();\n//!\n//! pub fn thread_id(cx: &mut Cx) -> NeonResult<u32> {\n//!     THREAD_ID.get_or_try_init(cx, |cx| {\n//!         let require: Handle<JsFunction> = cx.global(\"require\")?;\n//!         let worker: Handle<JsObject> = require\n//!             .bind(cx)\n//!             .arg(\"node:worker_threads\")?\n//!             .call()?;\n//!         let thread_id: f64 = worker.prop(cx, \"threadId\").get()?;\n//!         Ok(thread_id as u32)\n//!     }).cloned()\n//! }\n//! ```\n//!\n//! ### The Addon Lifecycle\n//!\n//! For some use cases, a single shared global constant stored in a `static` variable\n//! might be sufficient:\n//!\n//! ```\n//! static MY_CONSTANT: &'static str = \"hello Neon\";\n//! ```\n//!\n//! This variable will be allocated when the addon is first loaded into the Node.js\n//! process. This works fine for single-threaded applications, or global thread-safe\n//! data.\n//!\n//! However, since the addition of [worker threads][workers] in Node v10,\n//! modules can be instantiated multiple times in a single Node process. So even\n//! though the dynamically-loaded binary library (i.e., the Rust implementation of\n//! the addon) is only loaded once in the running process, its [`#[main]`](crate::main)\n//! function can be executed multiple times with distinct module objects, one per application\n//! thread:\n//!\n//! ![The Node.js addon lifecycle, described in detail below.][lifecycle]\n//!\n//! This means that any thread-local data needs to be initialized separately for each\n//! instance of the addon. This module provides a simple container type, [`LocalKey`],\n//! for allocating and initializing thread-local data. (Technically, this data is stored in the\n//! addon's [module instance][environment], which is equivalent to being thread-local.)\n//!\n//! A common example is when an addon needs to maintain a reference to a JavaScript value. A\n//! reference can be [rooted](crate::handle::Root) and stored in a static, but references cannot\n//! be used across separate threads. By placing the reference in thread-local storage, an\n//! addon can ensure that each thread stores its own distinct reference:\n//!\n//! ```\n//! # use neon::prelude::*;\n//! # use neon::thread::LocalKey;\n//! # fn initialize_my_datatype<'cx, C: Context<'cx>>(cx: &mut C) -> JsResult<'cx, JsFunction> { unimplemented!() }\n//! static MY_CONSTRUCTOR: LocalKey<Root<JsFunction>> = LocalKey::new();\n//!\n//! pub fn my_constructor<'cx, C: Context<'cx>>(cx: &mut C) -> JsResult<'cx, JsFunction> {\n//!     let constructor = MY_CONSTRUCTOR.get_or_try_init(cx, |cx| {\n//!         let constructor: Handle<JsFunction> = initialize_my_datatype(cx)?;\n//!         Ok(constructor.root(cx))\n//!     })?;\n//!     Ok(constructor.to_inner(cx))\n//! }\n//! ```\n//!\n//! Notice that if this code were implemented without a `LocalKey`, it would panic whenever\n//! one thread stores an instance of the constructor and a different thread attempts to\n//! access it with the call to [`to_inner()`](crate::handle::Root::to_inner).\n//!\n//! ### When to Use Thread-Local Storage\n//!\n//! Single-threaded applications don't generally need to worry about thread-local data.\n//! There are two cases where Neon apps should consider storing static data in a\n//! `LocalKey` storage cell:\n//!\n//! - **Multi-threaded applications:** If your Node application uses the `Worker`\n//!   API, you'll want to store any static data that might get access from multiple\n//!   threads in thread-local data.\n//! - **Libraries:** If your addon is part of a library that could be used by multiple\n//!   applications, you'll want to store static data in thread-local data in case the\n//!   addon ends up instantiated by multiple threads in some future application.\n//!\n//! ### Why Not Use Standard TLS?\n//!\n//! Since the JavaScript engine may not tie JavaScript threads 1:1 to system threads,\n//! it is recommended to use this module instead of the Rust standard thread-local storage\n//! when associating data with a JavaScript thread.\n//!\n//! [environment]: https://nodejs.org/api/n-api.html#environment-life-cycle-apis\n//! [lifecycle]: https://raw.githubusercontent.com/neon-bindings/neon/main/doc/lifecycle.png\n//! [workers]: https://nodejs.org/api/worker_threads.html\n//! [threadId]: https://nodejs.org/api/worker_threads.html#workerthreadid\n\nuse std::any::Any;\nuse std::marker::PhantomData;\nuse std::sync::atomic::{AtomicUsize, Ordering};\n\nuse once_cell::sync::OnceCell;\n\nuse crate::context::Context;\nuse crate::lifecycle::LocalCell;\n\nstatic COUNTER: AtomicUsize = AtomicUsize::new(0);\n\nfn next_id() -> usize {\n    COUNTER.fetch_add(1, Ordering::SeqCst)\n}\n\n/// A JavaScript thread-local container that owns its contents, similar to\n/// [`std::thread::LocalKey`] but tied to a JavaScript thread rather\n/// than a system thread.\n///\n/// ### Initialization and Destruction\n///\n/// Initialization is dynamically performed on the first call to one of the `init` methods\n/// of `LocalKey`, and values that implement [`Drop`] get destructed when\n/// the JavaScript thread exits, i.e. when a worker thread terminates or the main thread\n/// terminates on process exit.\n#[derive(Default)]\npub struct LocalKey<T> {\n    _type: PhantomData<T>,\n    id: OnceCell<usize>,\n}\n\nimpl<T> LocalKey<T> {\n    /// Creates a new local value. This method is `const`, so it can be assigned to\n    /// static variables.\n    pub const fn new() -> Self {\n        Self {\n            _type: PhantomData,\n            id: OnceCell::new(),\n        }\n    }\n\n    fn id(&self) -> usize {\n        *self.id.get_or_init(next_id)\n    }\n}\n\nimpl<T: Any + Send + 'static> LocalKey<T> {\n    /// Gets the current value of the cell. Returns `None` if the cell has not\n    /// yet been initialized.\n    pub fn get<'cx, 'a, C>(&self, cx: &'a mut C) -> Option<&'cx T>\n    where\n        C: Context<'cx>,\n    {\n        // Unwrap safety: The type bound LocalKey<T> and the fact that every LocalKey has a unique\n        // id guarantees that the cell is only ever assigned instances of type T.\n        let r: Option<&T> =\n            LocalCell::get(cx, self.id()).map(|value| value.downcast_ref().unwrap());\n\n        // Safety: Since the Box is immutable and heap-allocated, it's guaranteed not to\n        // move or change for the duration of the context.\n        unsafe { std::mem::transmute::<Option<&'a T>, Option<&'cx T>>(r) }\n    }\n\n    /// Gets the current value of the cell, initializing it with the result of\n    /// calling `f` if it has not yet been initialized.\n    pub fn get_or_init<'cx, 'a, C, F>(&self, cx: &'a mut C, f: F) -> &'cx T\n    where\n        C: Context<'cx>,\n        F: FnOnce() -> T,\n    {\n        // Unwrap safety: The type bound LocalKey<T> and the fact that every LocalKey has a unique\n        // id guarantees that the cell is only ever assigned instances of type T.\n        let r: &T = LocalCell::get_or_init(cx, self.id(), || Box::new(f()))\n            .downcast_ref()\n            .unwrap();\n\n        // Safety: Since the Box is immutable and heap-allocated, it's guaranteed not to\n        // move or change for the duration of the context.\n        unsafe { std::mem::transmute::<&'a T, &'cx T>(r) }\n    }\n\n    /// Gets the current value of the cell, initializing it with the result of\n    /// calling `f` if it has not yet been initialized. Returns `Err` if the\n    /// callback triggers a JavaScript exception.\n    ///\n    /// # Panics\n    ///\n    /// During the execution of `f`, calling any methods on this `LocalKey` that\n    /// attempt to initialize it will panic.\n    pub fn get_or_try_init<'cx, 'a, C, E, F>(&self, cx: &'a mut C, f: F) -> Result<&'cx T, E>\n    where\n        C: Context<'cx>,\n        F: FnOnce(&mut C) -> Result<T, E>,\n    {\n        // Unwrap safety: The type bound LocalKey<T> and the fact that every LocalKey has a unique\n        // id guarantees that the cell is only ever assigned instances of type T.\n        let r: &T = LocalCell::get_or_try_init(cx, self.id(), |cx| Ok(Box::new(f(cx)?)))?\n            .downcast_ref()\n            .unwrap();\n\n        // Safety: Since the Box is immutable and heap-allocated, it's guaranteed not to\n        // move or change for the duration of the context.\n        Ok(unsafe { std::mem::transmute::<&'a T, &'cx T>(r) })\n    }\n}\n\nimpl<T: Any + Send + Default + 'static> LocalKey<T> {\n    /// Gets the current value of the cell, initializing it with the default value\n    /// if it has not yet been initialized.\n    pub fn get_or_init_default<'cx, 'a, C>(&self, cx: &'a mut C) -> &'cx T\n    where\n        C: Context<'cx>,\n    {\n        self.get_or_init(cx, Default::default)\n    }\n}\n"
  },
  {
    "path": "crates/neon/src/types_docs.rs",
    "content": "#[cfg_attr(feature = \"aquamarine\", aquamarine::aquamarine)]\n/// Representations of JavaScript's core builtin types.\n///\n/// ## Modeling JavaScript Types\n///\n/// All JavaScript values in Neon implement the abstract [`Value`](crate::types::Value)\n/// trait, which is the most generic way to work with JavaScript values. Neon provides a\n/// number of types that implement this trait, each representing a particular\n/// type of JavaScript value.\n///\n/// By convention, JavaScript types in Neon have the prefix `Js` in their name,\n/// such as [`JsNumber`](crate::types::JsNumber) (for the JavaScript `number`\n/// type) or [`JsFunction`](crate::types::JsFunction) (for the JavaScript\n/// `function` type).\n///\n/// ### Handles and Casts\n///\n/// Access to JavaScript values in Neon works through [handles](crate::handle),\n/// which ensure the safe interoperation between Rust and the JavaScript garbage\n/// collector. This means, for example, a Rust variable that stores a JavaScript string\n/// will have the type `Handle<JsString>` rather than [`JsString`](crate::types::JsString).\n///\n/// Neon types model the JavaScript type hierarchy through the use of *casts*.\n/// The [`Handle::upcast()`](crate::handle::Handle::upcast) method safely converts\n/// a handle to a JavaScript value of one type into a handle to a value of its\n/// supertype. For example, it's safe to treat a [`JsArray`](crate::types::JsArray)\n/// as a [`JsObject`](crate::types::JsObject), so you can do an \"upcast\" and it will\n/// never fail:\n///\n/// ```\n/// # use neon::prelude::*;\n/// fn as_object(array: Handle<JsArray>) -> Handle<JsObject> {\n///     let object: Handle<JsObject> = array.upcast();\n///     object\n/// }\n/// ```\n///\n/// Unlike upcasts, the [`Handle::downcast()`](crate::handle::Handle::downcast) method\n/// requires a runtime check to test a value's type at runtime, so it can fail with\n/// a [`DowncastError`](crate::handle::DowncastError):\n///\n/// ```\n/// # use neon::prelude::*;\n/// fn as_array<'a>(\n///     cx: &mut impl Context<'a>,\n///     object: Handle<'a, JsObject>\n/// ) -> JsResult<'a, JsArray> {\n///     object.downcast(cx).or_throw(cx)\n/// }\n/// ```\n///\n/// ### The JavaScript Type Hierarchy\n///\n/// The top of the JavaScript type hierarchy is modeled with the Neon type\n/// [`JsValue`](crate::types::JsValue). A [handle](crate::handle) to a `JsValue`\n/// can refer to any JavaScript value. (For TypeScript programmers, this can be\n/// thought of as similar to TypeScript's [`unknown`][unknown] type.)\n///\n/// From there, the type hierarchy divides into _object types_ and _primitive\n/// types_:\n///\n/// ```mermaid\n/// flowchart LR\n/// JsValue(JsValue)\n/// JsValue-->JsObject(JsObject)\n/// click JsValue \"./struct.JsValue.html\" \"JsValue\"\n/// click JsObject \"./struct.JsObject.html\" \"JsObject\"\n/// subgraph primitives [Primitive Types]\n///     JsBoolean(JsBoolean)\n///     JsNumber(JsNumber)\n///     JsString(JsString)\n///     JsNull(JsNull)\n///     JsUndefined(JsUndefined)\n///     click JsBoolean \"./struct.JsBoolean.html\" \"JsBoolean\"\n///     click JsNumber \"./struct.JsNumber.html\" \"JsNumber\"\n///     click JsString \"./struct.JsString.html\" \"JsString\"\n///     click JsNull \"./struct.JsNull.html\" \"JsNull\"\n///     click JsUndefined \"./struct.JsUndefined.html\" \"JsUndefined\"\n/// end\n/// JsValue-->primitives\n/// ```\n///\n/// The top of the object type hierarchy is [`JsObject`](crate::types::JsObject). A\n/// handle to a `JsObject` can refer to any JavaScript object.\n///\n/// The primitive types are the built-in JavaScript datatypes that are not object\n/// types: [`JsBoolean`](crate::types::JsBoolean), [`JsNumber`](crate::types::JsNumber),\n/// [`JsString`](crate::types::JsString), [`JsNull`](crate::types::JsNull), and\n/// [`JsUndefined`](crate::types::JsUndefined).\n///\n/// #### Object Types\n///\n/// The object type hierarchy further divides into a variety of different subtypes:\n///\n/// ```mermaid\n/// flowchart LR\n/// JsObject(JsObject)\n/// click JsObject \"./struct.JsObject.html\" \"JsObject\"\n/// subgraph objects [Standard Object Types]\n///     JsFunction(JsFunction)\n///     JsArray(JsArray)\n///     JsDate(JsDate)\n///     JsError(JsError)\n///     click JsFunction \"./struct.JsFunction.html\" \"JsFunction\"\n///     click JsArray \"./struct.JsArray.html\" \"JsArray\"\n///     click JsDate \"./struct.JsDate.html\" \"JsDate\"\n///     click JsError \"./struct.JsError.html\" \"JsError\"\n/// end\n/// subgraph typedarrays [Typed Arrays]\n///     JsBuffer(JsBuffer)\n///     JsArrayBuffer(JsArrayBuffer)\n///     JsTypedArray(\"JsTypedArray&lt;T&gt;\")\n///     click JsBuffer \"./struct.JsBuffer.html\" \"JsBuffer\"\n///     click JsArrayBuffer \"./struct.JsArrayBuffer.html\" \"JsArrayBuffer\"\n///     click JsTypedArray \"./struct.JsTypedArray.html\" \"JsTypedArray\"\n/// end\n/// subgraph custom [Custom Types]\n///     JsBox(JsBox)\n///     click JsBox \"./struct.JsBox.html\" \"JsBox\"\n/// end\n/// JsObject-->objects\n/// JsObject-->typedarrays\n/// JsObject-->custom\n/// ```\n///\n/// These include several categories of object types:\n/// - **Standard object types:** [`JsFunction`](crate::types::JsFunction),\n///   [`JsArray`](crate::types::JsArray), [`JsDate`](crate::types::JsDate), and\n///   [`JsError`](crate::types::JsError).\n/// - **Typed arrays:** [`JsBuffer`](crate::types::JsBuffer),\n///   [`JsArrayBuffer`](crate::types::JsArrayBuffer), and\n///   [`JsTypedArray<T>`](crate::types::JsTypedArray).\n/// - **Custom types:** [`JsBox`](crate::types::JsBox), a special Neon type that allows\n///   the creation of custom objects that own Rust data structures.\n///\n/// All object types implement the [`Object`](crate::object::Object) trait, which\n/// allows getting and setting properties of an object.\n///\n/// [unknown]: https://mariusschulz.com/blog/the-unknown-type-in-typescript#the-unknown-type\npub mod exports {\n    pub use crate::types_impl::*;\n}\n"
  },
  {
    "path": "crates/neon/src/types_impl/bigint.rs",
    "content": "//! Types for working with [`JsBigInt`].\n\nuse std::{error, fmt, mem::MaybeUninit};\n\nuse crate::{\n    context::{\n        internal::{ContextInternal, Env},\n        Context, Cx,\n    },\n    handle::{internal::TransparentNoCopyWrapper, Handle},\n    result::{NeonResult, ResultExt},\n    sys::{self, raw},\n    types::{private, JsBigInt, Value},\n};\n\n#[derive(Copy, Clone, Debug, PartialEq, Eq)]\n/// Indicates if a `JsBigInt` is positive or negative\npub enum Sign {\n    Positive,\n    Negative,\n}\n\n#[derive(Copy, Clone, Debug, PartialEq, Eq)]\n/// Indicates a lossless conversion from a [`JsBigInt`] to a Rust integer\n/// could not be performed.\n///\n/// Failures include:\n/// * Negative sign on an unsigned int\n/// * Overflow of an int\n/// * Underflow of a signed int\npub struct RangeError<T>(T);\n\nimpl<T> RangeError<T> {\n    /// Get the lossy value read from a `BigInt`. It may be truncated,\n    /// sign extended or wrapped.\n    pub fn into_inner(self) -> T {\n        self.0\n    }\n}\n\nimpl<T> fmt::Display for RangeError<T>\nwhere\n    T: fmt::Display,\n{\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(f, \"Loss of precision reading BigInt ({})\", self.0)\n    }\n}\n\nimpl<T> error::Error for RangeError<T> where T: fmt::Display + fmt::Debug {}\n\nimpl<T, E> ResultExt<T> for Result<T, RangeError<E>>\nwhere\n    E: fmt::Display,\n{\n    fn or_throw<'a, C: Context<'a>>(self, cx: &mut C) -> NeonResult<T> {\n        self.or_else(|err| cx.throw_range_error(err.to_string()))\n    }\n}\n\nimpl JsBigInt {\n    pub const POSITIVE: Sign = Sign::Positive;\n    pub const NEGATIVE: Sign = Sign::Negative;\n\n    /// Creates a `BigInt` from an [`i64`].\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # use neon::{prelude::*, types::JsBigInt};\n    /// # fn example(mut cx: FunctionContext) -> JsResult<JsBigInt> {\n    /// let value: Handle<JsBigInt> = JsBigInt::from_i64(&mut cx, 42);\n    /// # Ok(value)\n    /// # }\n    /// ```\n    pub fn from_i64<'cx, C>(cx: &mut C, n: i64) -> Handle<'cx, Self>\n    where\n        C: Context<'cx>,\n    {\n        let mut v = MaybeUninit::uninit();\n        let v = unsafe {\n            sys::create_bigint_int64(cx.env().to_raw(), n, v.as_mut_ptr()).unwrap();\n\n            v.assume_init()\n        };\n\n        Handle::new_internal(Self(v))\n    }\n\n    /// Creates a `BigInt` from a [`u64`].\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # use neon::{prelude::*, types::JsBigInt};\n    /// # fn example(mut cx: FunctionContext) -> JsResult<JsBigInt> {\n    /// let value: Handle<JsBigInt> = JsBigInt::from_u64(&mut cx, 42);\n    /// # Ok(value)\n    /// # }\n    /// ```\n    pub fn from_u64<'cx, C>(cx: &mut C, n: u64) -> Handle<'cx, Self>\n    where\n        C: Context<'cx>,\n    {\n        let mut v = MaybeUninit::uninit();\n        let v = unsafe {\n            sys::create_bigint_uint64(cx.env().to_raw(), n, v.as_mut_ptr()).unwrap();\n\n            v.assume_init()\n        };\n\n        Handle::new_internal(Self(v))\n    }\n\n    // Internal helper for creating a _signed_ `BigInt` from a [`u128`] magnitude\n    fn from_u128_sign<'cx, C>(cx: &mut C, sign: Sign, n: u128) -> Handle<'cx, Self>\n    where\n        C: Context<'cx>,\n    {\n        let n = n.to_le();\n        let digits = [n as u64, (n >> 64) as u64];\n\n        Self::from_digits_le(cx, sign, &digits)\n    }\n\n    /// Creates a `BigInt` from an [`i128`].\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # use neon::{prelude::*, types::JsBigInt};\n    /// # fn example(mut cx: FunctionContext) -> JsResult<JsBigInt> {\n    /// let value: Handle<JsBigInt> = JsBigInt::from_i128(&mut cx, 42);\n    /// # Ok(value)\n    /// # }\n    /// ```\n    pub fn from_i128<'cx, C>(cx: &mut C, n: i128) -> Handle<'cx, Self>\n    where\n        C: Context<'cx>,\n    {\n        if n >= 0 {\n            return Self::from_u128(cx, n as u128);\n        }\n\n        // Get the magnitude from a two's compliment negative\n        let n = u128::MAX - (n as u128) + 1;\n\n        Self::from_u128_sign(cx, Self::NEGATIVE, n)\n    }\n\n    /// Creates a `BigInt` from a [`u128`].\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # use neon::{prelude::*, types::JsBigInt};\n    /// # fn example(mut cx: FunctionContext) -> JsResult<JsBigInt> {\n    /// let value: Handle<JsBigInt> = JsBigInt::from_u128(&mut cx, 42);\n    /// # Ok(value)\n    /// # }\n    /// ```\n    pub fn from_u128<'cx, C>(cx: &mut C, n: u128) -> Handle<'cx, Self>\n    where\n        C: Context<'cx>,\n    {\n        Self::from_u128_sign(cx, Self::POSITIVE, n)\n    }\n\n    /// Creates a `BigInt` from a signed magnitude. The `BigInt` is calculated as:\\\n    /// `Sign * (digit[0] x (2⁶⁴)⁰ + digit[0] x (2⁶⁴)¹ + digit[0] x (2⁶⁴)² ...)`\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # use neon::{prelude::*, types::JsBigInt};\n    /// # fn example(mut cx: FunctionContext) -> JsResult<JsBigInt> {\n    /// // Creates a `BigInt` equal to `2n ** 128n`\n    /// let value: Handle<JsBigInt> = JsBigInt::from_digits_le(\n    ///     &mut cx,\n    ///     JsBigInt::POSITIVE,\n    ///     &[0, 0, 1],\n    /// );\n    /// # Ok(value)\n    /// # }\n    /// ```\n    //\n    // XXX: It's unclear if individual digits are expected to be little endian or native.\n    // The current code assumes _native_. Neon modules are currently broken on big-endian\n    // platforms. If this is fixed in the future, unit tests will determine if this\n    // assumption is accurate.\n    pub fn from_digits_le<'cx, C>(cx: &mut C, sign: Sign, digits: &[u64]) -> Handle<'cx, Self>\n    where\n        C: Context<'cx>,\n    {\n        let sign_bit = match sign {\n            Sign::Positive => 0,\n            Sign::Negative => 1,\n        };\n\n        let mut v = MaybeUninit::uninit();\n        let v = unsafe {\n            sys::create_bigint_words(\n                cx.env().to_raw(),\n                sign_bit,\n                digits.len(),\n                digits.as_ptr(),\n                v.as_mut_ptr(),\n            )\n            .unwrap();\n\n            v.assume_init()\n        };\n\n        Handle::new_internal(Self(v))\n    }\n\n    /// Reads an `i64` from a `BigInt`.\n    ///\n    /// Fails on overflow and underflow.\n    ///\n    /// # Example\n    ///\n    /// See [`JsBigInt`].\n    pub fn to_i64<'cx, C>(&self, cx: &mut C) -> Result<i64, RangeError<i64>>\n    where\n        C: Context<'cx>,\n    {\n        let mut n = 0;\n        let mut lossless = false;\n\n        unsafe {\n            sys::get_value_bigint_int64(cx.env().to_raw(), self.0, &mut n, &mut lossless).unwrap();\n        }\n\n        if lossless {\n            Ok(n)\n        } else {\n            Err(RangeError(n))\n        }\n    }\n\n    /// Reads a `u64` from a `BigInt`.\n    ///\n    /// Fails on overflow or a negative sign.\n    pub fn to_u64<'cx, C>(&self, cx: &mut C) -> Result<u64, RangeError<u64>>\n    where\n        C: Context<'cx>,\n    {\n        let mut n = 0;\n        let mut lossless = false;\n\n        unsafe {\n            sys::get_value_bigint_uint64(cx.env().to_raw(), self.0, &mut n, &mut lossless).unwrap();\n        }\n\n        if lossless {\n            Ok(n)\n        } else {\n            Err(RangeError(n))\n        }\n    }\n\n    /// Reads an `i128` from a `BigInt`.\n    ///\n    /// Fails on overflow and underflow.\n    pub fn to_i128<'cx, C>(&self, cx: &mut C) -> Result<i128, RangeError<i128>>\n    where\n        C: Context<'cx>,\n    {\n        let mut digits = [0; 2];\n        let (sign, num_digits) = self.read_digits_le(cx, &mut digits);\n\n        // Cast digits into a `u128` magnitude\n        let n = (digits[0] as u128) | ((digits[1] as u128) << 64);\n        let n = u128::from_le(n);\n\n        // Verify that the magnitude leaves room for the sign bit\n        let n = match sign {\n            Sign::Positive => {\n                if n > (i128::MAX as u128) {\n                    return Err(RangeError(i128::MAX));\n                } else {\n                    n as i128\n                }\n            }\n            Sign::Negative => {\n                if n > (i128::MAX as u128) + 1 {\n                    return Err(RangeError(i128::MIN));\n                } else {\n                    (n as i128).wrapping_neg()\n                }\n            }\n        };\n\n        // Leading zeroes are truncated and never returned. If there are additional\n        // digits, the number is out of range.\n        if num_digits > digits.len() {\n            Err(RangeError(n))\n        } else {\n            Ok(n)\n        }\n    }\n\n    /// Reads a `u128` from a `BigInt`.\n    ///\n    /// Fails on overflow or a negative sign.\n    pub fn to_u128<'cx, C>(&self, cx: &mut C) -> Result<u128, RangeError<u128>>\n    where\n        C: Context<'cx>,\n    {\n        let mut digits = [0; 2];\n        let (sign, num_digits) = self.read_digits_le(cx, &mut digits);\n\n        // Cast digits into a `u128` magnitude\n        let n = (digits[0] as u128) | ((digits[1] as u128) << 64);\n        let n = u128::from_le(n);\n\n        // Leading zeroes are truncated and never returned. If there are additional\n        // digits, the number is out of range.\n        if matches!(sign, Sign::Negative) || num_digits > digits.len() {\n            Err(RangeError(n))\n        } else {\n            Ok(n)\n        }\n    }\n\n    /// Gets a signed magnitude pair from a `BigInt`.\n    ///\n    /// The `BigInt` is calculated as:\\\n    /// `Sign * (digit[0] x (2⁶⁴)⁰ + digit[0] x (2⁶⁴)¹ + digit[0] x (2⁶⁴)² ...)`\n    pub fn to_digits_le<'cx, C>(&self, cx: &mut C) -> (Sign, Vec<u64>)\n    where\n        C: Context<'cx>,\n    {\n        let mut v = vec![0; self.len(cx)];\n        let (sign, len) = self.read_digits_le(cx, &mut v);\n\n        // It shouldn't be possible for the number of digits to change. If it\n        // it does, it's a correctness issue and not a soundness bug.\n        debug_assert_eq!(v.len(), len);\n\n        (sign, v)\n    }\n\n    /// Gets the sign from a `BigInt` and reads digits into a buffer.\n    /// The returned `usize` is the total number of digits in the `BigInt`.\n    ///\n    /// # Example\n    ///\n    /// Read a `u256` from a `BigInt`.\n    ///\n    /// ```\n    /// # use std::error::Error;\n    /// # use neon::{prelude::*, types::JsBigInt};\n    /// fn bigint_to_u256(cx: &mut FunctionContext, n: Handle<JsBigInt>) -> NeonResult<[u64; 4]> {\n    ///     let mut digits = [0; 4];\n    ///     let (sign, num_digits) = n.read_digits_le(cx, &mut digits);\n    ///\n    ///     if sign == JsBigInt::NEGATIVE {\n    ///         return cx.throw_error(\"Underflow reading u256 from BigInt\");\n    ///     }\n    ///\n    ///     if num_digits > digits.len() {\n    ///         return cx.throw_error(\"Overflow reading u256 from BigInt\");\n    ///     }\n    ///\n    ///     Ok(digits)\n    /// }\n    /// ```\n    pub fn read_digits_le<'cx, C>(&self, cx: &mut C, digits: &mut [u64]) -> (Sign, usize)\n    where\n        C: Context<'cx>,\n    {\n        let mut sign_bit = 0;\n        let mut word_count = digits.len();\n\n        unsafe {\n            sys::get_value_bigint_words(\n                cx.env().to_raw(),\n                self.0,\n                &mut sign_bit,\n                &mut word_count,\n                digits.as_mut_ptr(),\n            )\n            .unwrap();\n        }\n\n        let sign = if sign_bit == 0 {\n            Sign::Positive\n        } else {\n            Sign::Negative\n        };\n\n        (sign, word_count)\n    }\n\n    /// Gets the number of `u64` digits in a `BigInt`\n    pub fn len<'cx, C>(&self, cx: &mut C) -> usize\n    where\n        C: Context<'cx>,\n    {\n        // Get the length by reading into an empty slice and ignoring the sign\n        self.read_digits_le(cx, &mut []).1\n    }\n}\n\nimpl Value for JsBigInt {}\n\nunsafe impl TransparentNoCopyWrapper for JsBigInt {\n    type Inner = raw::Local;\n\n    fn into_inner(self) -> Self::Inner {\n        self.0\n    }\n}\n\nimpl private::ValueInternal for JsBigInt {\n    fn name() -> &'static str {\n        \"BigInt\"\n    }\n\n    fn is_typeof<Other: Value>(cx: &mut Cx, other: &Other) -> bool {\n        unsafe { sys::tag::is_bigint(cx.env().to_raw(), other.to_local()) }\n    }\n\n    fn to_local(&self) -> raw::Local {\n        self.0\n    }\n\n    unsafe fn from_local(_env: Env, h: raw::Local) -> Self {\n        Self(h)\n    }\n}\n"
  },
  {
    "path": "crates/neon/src/types_impl/boxed.rs",
    "content": "use std::{\n    any::{self, Any},\n    ops::Deref,\n};\n\nuse crate::{\n    context::{\n        internal::{ContextInternal, Env},\n        Context, Cx,\n    },\n    handle::{internal::TransparentNoCopyWrapper, Handle},\n    object::Object,\n    sys::{external, raw},\n    types::{boxed::private::JsBoxInner, private::ValueInternal, Value},\n};\n\ntype BoxAny = Box<dyn Any + 'static>;\n\nmod private {\n    pub struct JsBoxInner<T: 'static> {\n        pub(super) local: crate::sys::raw::Local,\n        // Cached raw pointer to the data contained in the `JsBox`. This value is\n        // required to implement `Deref` for `JsBox`. Unlike most `Js` types, `JsBox`\n        // is not a transparent wrapper around a `napi_value` and cannot implement `This`.\n        //\n        // Safety: `JsBox` cannot verify the lifetime. Store a raw pointer to force\n        // uses to be marked unsafe. In practice, it can be treated as `'static` but\n        // should only be exposed as part of a `Handle` tied to a `Context` lifetime.\n        // Safety: The value must not move on the heap; we must never give a mutable\n        // reference to the data until the `JsBox` is no longer accessible.\n        pub(super) raw_data: *const T,\n    }\n}\n\n/// A JavaScript smart pointer object that owns Rust data.\n///\n/// The type `JsBox<T>` provides shared ownership of a value of type `T`,\n/// allocated in the heap. The data is owned by the JavaScript engine and the\n/// lifetime is managed by the JavaScript garbage collector.\n///\n/// Shared references in Rust disallow mutation by default, and `JsBox` is no\n/// exception: you cannot generally obtain a mutable reference to something\n/// inside a `JsBox`. If you need to mutate through a `JsBox`, use\n/// [`Cell`](https://doc.rust-lang.org/std/cell/struct.Cell.html),\n/// [`RefCell`](https://doc.rust-lang.org/stable/std/cell/struct.RefCell.html),\n/// or one of the other types that provide\n/// [interior mutability](https://doc.rust-lang.org/book/ch15-05-interior-mutability.html).\n///\n/// Values contained by a `JsBox` must implement the `Finalize` trait. `Finalize::finalize`\n/// will execute with the value in a `JsBox` immediately before the `JsBox` is garbage\n/// collected. If no additional finalization is necessary, an emply implementation may\n/// be provided.\n///\n///\n/// ## `Deref` behavior\n///\n/// `JsBox<T>` automatically dereferences to `T` (via the `Deref` trait), so\n/// you can call `T`'s method on a value of type `JsBox<T>`.\n///\n/// ```rust\n/// # use neon::prelude::*;\n/// # fn my_neon_function(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n/// let vec: Handle<JsBox<Vec<_>>> = cx.boxed(vec![1, 2, 3]);\n///\n/// println!(\"Length: {}\", vec.len());\n/// # Ok(cx.undefined())\n/// # }\n/// ```\n///\n/// ## Examples\n///\n/// Passing some immutable data between Rust and JavaScript.\n///\n/// ```rust\n/// # use neon::prelude::*;\n/// # use std::path::{Path, PathBuf};\n/// fn create_path(mut cx: FunctionContext) -> JsResult<JsBox<PathBuf>> {\n///     let path = cx.argument::<JsString>(0)?.value(&mut cx);\n///     let path = Path::new(&path).to_path_buf();\n///\n///     Ok(cx.boxed(path))\n/// }\n///\n/// fn print_path(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n///     let path = cx.argument::<JsBox<PathBuf>>(0)?;\n///\n///     println!(\"{}\", path.display());\n///\n///     Ok(cx.undefined())\n/// }\n/// ```\n///\n/// Passing a user defined struct wrapped in a `RefCell` for mutability. This\n/// pattern is useful for creating classes in JavaScript.\n///\n/// ```rust\n/// # use neon::prelude::*;\n/// # use std::cell::RefCell;\n///\n/// type BoxedPerson = JsBox<RefCell<Person>>;\n///\n/// struct Person {\n///      name: String,\n/// }\n///\n/// impl Finalize for Person {}\n///\n/// impl Person {\n///     pub fn new(name: String) -> Self {\n///         Person { name }\n///     }\n///\n///     pub fn set_name(&mut self, name: String) {\n///         self.name = name;\n///     }\n///\n///     pub fn greet(&self) -> String {\n///         format!(\"Hello, {}!\", self.name)\n///     }\n/// }\n///\n/// fn person_new(mut cx: FunctionContext) -> JsResult<BoxedPerson> {\n///     let name = cx.argument::<JsString>(0)?.value(&mut cx);\n///     let person = RefCell::new(Person::new(name));\n///\n///     Ok(cx.boxed(person))\n/// }\n///\n/// fn person_set_name(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n///     let person = cx.argument::<BoxedPerson>(0)?;\n///     let mut person = person.borrow_mut();\n///     let name = cx.argument::<JsString>(1)?.value(&mut cx);\n///\n///     person.set_name(name);\n///\n///     Ok(cx.undefined())\n/// }\n///\n/// fn person_greet(mut cx: FunctionContext) -> JsResult<JsString> {\n///     let person = cx.argument::<BoxedPerson>(0)?;\n///     let person = person.borrow();\n///     let greeting = person.greet();\n///\n///     Ok(cx.string(greeting))\n/// }\n#[repr(transparent)]\npub struct JsBox<T: 'static>(JsBoxInner<T>);\n\nimpl<T: 'static> std::fmt::Debug for JsBoxInner<T> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"JsBox<{}>\", std::any::type_name::<T>())\n    }\n}\n\nimpl<T: 'static> std::fmt::Debug for JsBox<T> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        std::fmt::Debug::fmt(&self.0, f)\n    }\n}\n\n// Attempt to use a `napi_value` as a `napi_external` to unwrap a `BoxAny>\n/// Safety: `local` must be a `napi_value` that is valid for the lifetime `'a`.\nunsafe fn maybe_external_deref<'a>(env: Env, local: raw::Local) -> Option<&'a BoxAny> {\n    external::deref::<BoxAny>(env.to_raw(), local).map(|v| &*v)\n}\n\n// Custom `Clone` implementation since `T` might not be `Clone`\nimpl<T: 'static> Clone for JsBoxInner<T> {\n    fn clone(&self) -> Self {\n        *self\n    }\n}\n\nimpl<T: 'static> Object for JsBox<T> {}\n\nimpl<T: 'static> Copy for JsBoxInner<T> {}\n\nimpl<T: 'static> Value for JsBox<T> {}\n\nunsafe impl<T: 'static> TransparentNoCopyWrapper for JsBox<T> {\n    type Inner = JsBoxInner<T>;\n\n    fn into_inner(self) -> Self::Inner {\n        self.0\n    }\n}\n\nimpl<T: 'static> ValueInternal for JsBox<T> {\n    fn name() -> &'static str {\n        any::type_name::<Self>()\n    }\n\n    fn is_typeof<Other: Value>(cx: &mut Cx, other: &Other) -> bool {\n        let data = unsafe { maybe_external_deref(cx.env(), other.to_local()) };\n\n        data.map(|v| v.is::<T>()).unwrap_or(false)\n    }\n\n    fn downcast<Other: Value>(cx: &mut Cx, other: &Other) -> Option<Self> {\n        let local = other.to_local();\n        let data = unsafe { maybe_external_deref(cx.env(), local) };\n\n        // Attempt to downcast the `Option<&BoxAny>` to `Option<*const T>`\n        data.and_then(|v| v.downcast_ref())\n            .map(|raw_data| Self(JsBoxInner { local, raw_data }))\n    }\n\n    fn to_local(&self) -> raw::Local {\n        self.0.local\n    }\n\n    unsafe fn from_local(env: Env, local: raw::Local) -> Self {\n        let raw_data = unsafe { maybe_external_deref(env, local) }\n            .expect(\"Failed to unwrap napi_external as Box<Any>\")\n            .downcast_ref()\n            .expect(\"Failed to downcast Any\");\n\n        Self(JsBoxInner { local, raw_data })\n    }\n}\n\n/// Values contained by a `JsBox` must be `Finalize + 'static`\n///\n/// ### `Finalize`\n///\n/// The `sys::prelude::Finalize` trait provides a `finalize` method that will be called\n/// immediately before the `JsBox` is garbage collected.\n///\n/// ### `'static'\n///\n/// The lifetime of a `JsBox` is managed by the JavaScript garbage collector. Since Rust\n/// is unable to verify the lifetime of the contents, references must be valid for the\n/// entire duration of the program. This does not mean that the `JsBox` will be valid\n/// until the application terminates, only that its lifetime is indefinite.\nimpl<T: Finalize + 'static> JsBox<T> {\n    /// Constructs a new `JsBox` containing `value`.\n    pub fn new<'cx, C: Context<'cx>>(cx: &mut C, value: T) -> Handle<'cx, JsBox<T>> {\n        // This function will execute immediately before the `JsBox` is garbage collected.\n        // It unwraps the `napi_external`, downcasts the `BoxAny` and moves the type\n        // out of the `Box`. Lastly, it calls the trait method `Finalize::finalize` of the\n        // contained value `T`.\n        fn finalizer<U: Finalize + 'static>(env: raw::Env, data: BoxAny) {\n            let data = *data.downcast::<U>().unwrap();\n            let env = Env::from(env);\n\n            Cx::with_context(env, move |mut cx| data.finalize(&mut cx));\n        }\n\n        Self::create_external(cx, value, finalizer::<T>)\n    }\n}\n\nimpl<T: 'static> JsBox<T> {\n    pub(crate) fn manually_finalize<'cx>(cx: &mut Cx<'cx>, value: T) -> Handle<'cx, JsBox<T>> {\n        fn finalizer(_env: raw::Env, _data: BoxAny) {}\n\n        Self::create_external(cx, value, finalizer)\n    }\n\n    fn create_external<'cx, C: Context<'cx>>(\n        cx: &mut C,\n        value: T,\n        finalizer: fn(raw::Env, BoxAny),\n    ) -> Handle<'cx, JsBox<T>> {\n        let v = Box::new(value) as BoxAny;\n\n        // Since this value was just constructed, we know it is `T`\n        let raw_data = &*v as *const dyn Any as *const T;\n        let local = unsafe { external::create(cx.env().to_raw(), v, finalizer) };\n\n        Handle::new_internal(JsBox(JsBoxInner { local, raw_data }))\n    }\n}\n\nimpl<T: 'static> JsBox<T> {\n    /// Gets a reference to the inner value of a [`JsBox`]. This method is similar to\n    /// [dereferencing](JsBox::deref) a `JsBox` (e.g., `&*boxed`), but the lifetime\n    /// is _safely_ extended to `'cx`.\n    ///\n    /// See also [`Handle<JsBox>::as_inner`].\n    // N.B.: This would be cleaner with https://github.com/rust-lang/rust/issues/44874\n    pub fn deref<'cx>(v: &Handle<'cx, Self>) -> &'cx T {\n        v.as_inner()\n    }\n}\n\nimpl<'cx, T: 'static> Handle<'cx, JsBox<T>> {\n    /// Gets a reference to the inner value of a [`JsBox`]. This method is similar to\n    /// [dereferencing](JsBox::deref) a `JsBox` (e.g., `&*boxed`), but the lifetime\n    /// is _safely_ extended to `'cx`.\n    ///\n    /// See also [`JsBox::deref`].\n    pub fn as_inner(&self) -> &'cx T {\n        // # Safety\n        // JS values associated with an in-scope `Context` *cannot* be garbage collected.\n        // This value is guaranteed to live at least as long as `'cx`.\n        unsafe { &*self.0.raw_data }\n    }\n}\n\nimpl<T: 'static> Deref for JsBox<T> {\n    type Target = T;\n\n    fn deref(&self) -> &Self::Target {\n        // # Safety\n        // `T` will live at least as long as `JsBox<T>` because it may not be garbage\n        // collected while in scope and only immutable references can be obtained.\n        unsafe { &*self.0.raw_data }\n    }\n}\n\n/// A trait for finalizing values owned by the main JavaScript thread.\n///\n/// [`Finalize::finalize`] is executed on the main JavaScript thread\n/// immediately before garbage collection.\n///\n/// Values contained by a `JsBox` must implement `Finalize`.\n///\n/// ## Examples\n///\n/// `Finalize` provides a default implementation that does not perform any finalization.\n///\n/// ```rust\n/// # use neon::prelude::*;\n/// struct Point(f64, f64);\n///\n/// impl Finalize for Point {}\n/// ```\n///\n/// A `finalize` method may be specified for performing clean-up operations before dropping\n/// the contained value.\n///\n/// ```rust\n/// # use neon::prelude::*;\n/// struct Point(f64, f64);\n///\n/// impl Finalize for Point {\n///     fn finalize<'a, C: Context<'a>>(self, cx: &mut C) {\n///         cx.global_object()\n///             .method(cx.cx_mut(), \"emit\").unwrap()\n///             .args((\"gc_point\", self.0, self.1)).unwrap()\n///             .exec().unwrap();\n///     }\n/// }\n/// ```\npub trait Finalize: Sized {\n    fn finalize<'a, C: Context<'a>>(self, _: &mut C) {}\n}\n\n// Primitives\n\nimpl Finalize for bool {}\n\nimpl Finalize for char {}\n\nimpl Finalize for i8 {}\n\nimpl Finalize for i16 {}\n\nimpl Finalize for i32 {}\n\nimpl Finalize for i64 {}\n\nimpl Finalize for isize {}\n\nimpl Finalize for u8 {}\n\nimpl Finalize for u16 {}\n\nimpl Finalize for u32 {}\n\nimpl Finalize for u64 {}\n\nimpl Finalize for usize {}\n\nimpl Finalize for f32 {}\n\nimpl Finalize for f64 {}\n\n// Common types\n\nimpl Finalize for String {}\n\nimpl Finalize for std::path::PathBuf {}\n\n// Tuples\n\nmacro_rules! finalize_tuple_impls {\n    ($( $name:ident )+) => {\n        impl<$($name: Finalize),+> Finalize for ($($name,)+) {\n            fn finalize<'a, C: Context<'a>>(self, cx: &mut C) {\n                #![allow(non_snake_case)]\n                let ($($name,)+) = self;\n                ($($name.finalize(cx),)+);\n            }\n        }\n    };\n}\n\nimpl Finalize for () {}\nfinalize_tuple_impls! { T0 }\nfinalize_tuple_impls! { T0 T1 }\nfinalize_tuple_impls! { T0 T1 T2 }\nfinalize_tuple_impls! { T0 T1 T2 T3 }\nfinalize_tuple_impls! { T0 T1 T2 T3 T4 }\nfinalize_tuple_impls! { T0 T1 T2 T3 T4 T5 }\nfinalize_tuple_impls! { T0 T1 T2 T3 T4 T5 T6 }\nfinalize_tuple_impls! { T0 T1 T2 T3 T4 T5 T6 T7 }\n\n// Collections\n\nimpl<T: Finalize> Finalize for Vec<T> {\n    fn finalize<'a, C: Context<'a>>(self, cx: &mut C) {\n        for item in self {\n            item.finalize(cx);\n        }\n    }\n}\n\n// Smart pointers and other wrappers\n\nimpl<T: Finalize> Finalize for std::boxed::Box<T> {\n    fn finalize<'a, C: Context<'a>>(self, cx: &mut C) {\n        (*self).finalize(cx);\n    }\n}\n\nimpl<T: Finalize> Finalize for Option<T> {\n    fn finalize<'a, C: Context<'a>>(self, cx: &mut C) {\n        if let Some(v) = self {\n            v.finalize(cx);\n        }\n    }\n}\n\nimpl<T: Finalize> Finalize for std::rc::Rc<T> {\n    fn finalize<'a, C: Context<'a>>(self, cx: &mut C) {\n        if let Ok(v) = std::rc::Rc::try_unwrap(self) {\n            v.finalize(cx);\n        }\n    }\n}\n\nimpl<T: Finalize> Finalize for std::sync::Arc<T> {\n    fn finalize<'a, C: Context<'a>>(self, cx: &mut C) {\n        if let Ok(v) = std::sync::Arc::try_unwrap(self) {\n            v.finalize(cx);\n        }\n    }\n}\n\nimpl<T: Finalize> Finalize for std::sync::Mutex<T> {\n    fn finalize<'a, C: Context<'a>>(self, cx: &mut C) {\n        if let Ok(v) = self.into_inner() {\n            v.finalize(cx);\n        }\n    }\n}\n\nimpl<T: Finalize> Finalize for std::sync::RwLock<T> {\n    fn finalize<'a, C: Context<'a>>(self, cx: &mut C) {\n        if let Ok(v) = self.into_inner() {\n            v.finalize(cx);\n        }\n    }\n}\n\nimpl<T: Finalize> Finalize for std::cell::Cell<T> {\n    fn finalize<'a, C: Context<'a>>(self, cx: &mut C) {\n        self.into_inner().finalize(cx);\n    }\n}\n\nimpl<T: Finalize> Finalize for std::cell::RefCell<T> {\n    fn finalize<'a, C: Context<'a>>(self, cx: &mut C) {\n        self.into_inner().finalize(cx);\n    }\n}\n"
  },
  {
    "path": "crates/neon/src/types_impl/buffer/lock.rs",
    "content": "use std::{cell::RefCell, ops::Range};\n\nuse crate::{\n    context::Context,\n    types::buffer::{BorrowError, Ref, RefMut},\n};\n\n#[derive(Debug)]\n/// A temporary lock of an execution context.\n///\n/// While a lock is alive, no JavaScript code can be executed in the execution context.\n///\n/// Values that support the `Borrow` trait may be dynamically borrowed by passing a\n/// [`Lock`].\npub struct Lock<'cx, C> {\n    pub(super) cx: &'cx C,\n    pub(super) ledger: RefCell<Ledger>,\n}\n\nimpl<'a: 'cx, 'cx, C> Lock<'cx, C>\nwhere\n    C: Context<'a>,\n{\n    /// Constructs a new [`Lock`] and locks the VM. See also [`Context::lock`].\n    pub fn new(cx: &'cx mut C) -> Lock<'cx, C> {\n        Lock {\n            cx,\n            ledger: Default::default(),\n        }\n    }\n}\n\n#[derive(Debug, Default)]\n// Bookkeeping for dynamically check borrowing rules\n//\n// Ranges are open on the end: `[start, end)`\npub(super) struct Ledger {\n    // Mutable borrows. Should never overlap with other borrows.\n    pub(super) owned: Vec<Range<*const u8>>,\n\n    // Immutable borrows. May overlap or contain duplicates.\n    pub(super) shared: Vec<Range<*const u8>>,\n}\n\nimpl Ledger {\n    // Convert a slice of arbitrary type and size to a range of bytes addresses\n    //\n    // Alignment does not matter because we are only interested in bytes.\n    pub(super) fn slice_to_range<T>(data: &[T]) -> Range<*const u8> {\n        let Range { start, end } = data.as_ptr_range();\n\n        (start.cast())..(end.cast())\n    }\n\n    // Dynamically check a slice conforms to borrow rules before returning by\n    // using interior mutability of the ledger.\n    pub(super) fn try_borrow<'a, T>(\n        ledger: &'a RefCell<Self>,\n        data: &'a [T],\n    ) -> Result<Ref<'a, T>, BorrowError> {\n        if !data.is_empty() {\n            ledger.borrow_mut().try_add_borrow(data)?;\n        }\n\n        Ok(Ref { ledger, data })\n    }\n\n    // Dynamically check a mutable slice conforms to borrow rules before returning by\n    // using interior mutability of the ledger.\n    pub(super) fn try_borrow_mut<'a, T>(\n        ledger: &'a RefCell<Self>,\n        data: &'a mut [T],\n    ) -> Result<RefMut<'a, T>, BorrowError> {\n        if !data.is_empty() {\n            ledger.borrow_mut().try_add_borrow_mut(data)?;\n        }\n\n        Ok(RefMut { ledger, data })\n    }\n\n    // Try to add an immutable borrow to the ledger\n    fn try_add_borrow<T>(&mut self, data: &[T]) -> Result<(), BorrowError> {\n        let range = Self::slice_to_range(data);\n\n        // Check if the borrow overlaps with any active mutable borrow\n        check_overlap(&self.owned, &range)?;\n\n        // Record a record of the immutable borrow\n        self.shared.push(range);\n\n        Ok(())\n    }\n\n    // Try to add a mutable borrow to the ledger\n    fn try_add_borrow_mut<T>(&mut self, data: &mut [T]) -> Result<(), BorrowError> {\n        let range = Self::slice_to_range(data);\n\n        // Check if the borrow overlaps with any active mutable borrow\n        check_overlap(&self.owned, &range)?;\n\n        // Check if the borrow overlaps with any active immutable borrow\n        check_overlap(&self.shared, &range)?;\n\n        // Record a record of the mutable borrow\n        self.owned.push(range);\n\n        Ok(())\n    }\n}\n\nfn is_disjoint(a: &Range<*const u8>, b: &Range<*const u8>) -> bool {\n    b.start >= a.end || a.start >= b.end\n}\n\nfn check_overlap(\n    existing: &[Range<*const u8>],\n    range: &Range<*const u8>,\n) -> Result<(), BorrowError> {\n    if existing.iter().all(|i| is_disjoint(i, range)) {\n        Ok(())\n    } else {\n        Err(BorrowError::new())\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use std::cell::RefCell;\n    use std::error::Error;\n    use std::mem;\n    use std::slice;\n\n    use super::{BorrowError, Ledger};\n\n    // Super unsafe, but we only use it for testing `Ledger`\n    fn unsafe_aliased_slice<T>(data: &mut [T]) -> &'static mut [T] {\n        unsafe { slice::from_raw_parts_mut(data.as_mut_ptr(), data.len()) }\n    }\n\n    #[test]\n    fn test_overlapping_immutable_borrows() -> Result<(), Box<dyn Error>> {\n        let ledger = RefCell::new(Ledger::default());\n        let data = [0u8; 128];\n\n        Ledger::try_borrow(&ledger, &data[0..10])?;\n        Ledger::try_borrow(&ledger, &data[0..100])?;\n        Ledger::try_borrow(&ledger, &data[20..])?;\n\n        Ok(())\n    }\n\n    #[test]\n    fn test_nonoverlapping_borrows() -> Result<(), Box<dyn Error>> {\n        let ledger = RefCell::new(Ledger::default());\n        let mut data = [0; 16];\n        let (a, b) = data.split_at_mut(4);\n\n        let _a = Ledger::try_borrow_mut(&ledger, a)?;\n        let _b = Ledger::try_borrow(&ledger, b)?;\n\n        Ok(())\n    }\n\n    #[test]\n    fn test_overlapping_borrows() -> Result<(), Box<dyn Error>> {\n        let ledger = RefCell::new(Ledger::default());\n        let mut data = [0; 16];\n        let a = unsafe_aliased_slice(&mut data[4..8]);\n        let b = unsafe_aliased_slice(&mut data[6..12]);\n        let ab = Ledger::try_borrow(&ledger, a)?;\n\n        // Should fail because it overlaps\n        assert_eq!(\n            Ledger::try_borrow_mut(&ledger, b).unwrap_err(),\n            BorrowError::new(),\n        );\n\n        // Drop the first borrow\n        mem::drop(ab);\n\n        // Should succeed because previous borrow was dropped\n        let bb = Ledger::try_borrow_mut(&ledger, b)?;\n\n        // Should fail because it overlaps\n        assert_eq!(\n            Ledger::try_borrow(&ledger, a).unwrap_err(),\n            BorrowError::new(),\n        );\n\n        // Drop the second borrow\n        mem::drop(bb);\n\n        // Should succeed because previous borrow was dropped\n        let _ab = Ledger::try_borrow(&ledger, a)?;\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "crates/neon/src/types_impl/buffer/mod.rs",
    "content": "//! Types and traits for working with binary buffers.\n\nuse std::{\n    cell::RefCell,\n    error::Error,\n    fmt::{self, Debug, Display},\n    marker::PhantomData,\n    ops::{Deref, DerefMut},\n};\n\nuse crate::{\n    context::Context,\n    handle::Handle,\n    result::{JsResult, NeonResult, ResultExt},\n    types::{\n        buffer::lock::{Ledger, Lock},\n        JsArrayBuffer, JsTypedArray, Value,\n    },\n};\n\npub(crate) mod lock;\npub(super) mod types;\n\npub use types::Binary;\n\n/// A trait allowing Rust to borrow binary data from the memory buffer of JavaScript\n/// [typed arrays][typed-arrays].\n///\n/// This trait provides both statically and dynamically checked borrowing. As usual\n/// in Rust, mutable borrows are guaranteed not to overlap with other borrows.\n///\n/// # Example\n///\n/// ```\n/// # use neon::prelude::*;\n/// use neon::types::buffer::TypedArray;\n///\n/// fn double(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n///     let mut array: Handle<JsUint32Array> = cx.argument(0)?;\n///\n///     for elem in array.as_mut_slice(&mut cx).iter_mut() {\n///         *elem *= 2;\n///     }\n///\n///     Ok(cx.undefined())\n/// }\n/// ```\n///\n/// [typed-arrays]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays\npub trait TypedArray: Value {\n    type Item: Binary;\n\n    /// Statically checked immutable borrow of binary data.\n    ///\n    /// This may not be used if a mutable borrow is in scope. For the dynamically\n    /// checked variant see [`TypedArray::try_borrow`].\n    fn as_slice<'cx, 'a, C>(&self, cx: &'a C) -> &'a [Self::Item]\n    where\n        C: Context<'cx>;\n\n    /// Statically checked mutable borrow of binary data.\n    ///\n    /// This may not be used if any other borrow is in scope. For the dynamically\n    /// checked variant see [`TypedArray::try_borrow_mut`].\n    fn as_mut_slice<'cx, 'a, C>(&mut self, cx: &'a mut C) -> &'a mut [Self::Item]\n    where\n        C: Context<'cx>;\n\n    /// Dynamically checked immutable borrow of binary data, returning an error if the\n    /// the borrow would overlap with a mutable borrow.\n    ///\n    /// The borrow lasts until [`Ref`] exits scope.\n    ///\n    /// This is the dynamically checked version of [`TypedArray::as_slice`].\n    fn try_borrow<'cx, 'a, C>(&self, lock: &'a Lock<C>) -> Result<Ref<'a, Self::Item>, BorrowError>\n    where\n        C: Context<'cx>;\n\n    /// Dynamically checked mutable borrow of binary data, returning an error if the\n    /// the borrow would overlap with an active borrow.\n    ///\n    /// The borrow lasts until [`RefMut`] exits scope.\n    ///\n    /// This is the dynamically checked version of [`TypedArray::as_mut_slice`].\n    fn try_borrow_mut<'cx, 'a, C>(\n        &mut self,\n        lock: &'a Lock<C>,\n    ) -> Result<RefMut<'a, Self::Item>, BorrowError>\n    where\n        C: Context<'cx>;\n\n    /// Returns the size, in bytes, of the allocated binary data.\n    fn size<'cx, C>(&self, cx: &mut C) -> usize\n    where\n        C: Context<'cx>;\n\n    /// Constructs an instance from a slice by copying its contents.\n    fn from_slice<'cx, C>(cx: &mut C, slice: &[Self::Item]) -> JsResult<'cx, Self>\n    where\n        C: Context<'cx>;\n}\n\n#[derive(Debug)]\n/// Wraps binary data immutably borrowed from a JavaScript value.\npub struct Ref<'a, T> {\n    data: &'a [T],\n    ledger: &'a RefCell<Ledger>,\n}\n\n#[derive(Debug)]\n/// Wraps binary data mutably borrowed from a JavaScript value.\npub struct RefMut<'a, T> {\n    data: &'a mut [T],\n    ledger: &'a RefCell<Ledger>,\n}\n\nimpl<'a, T> Deref for Ref<'a, T> {\n    type Target = [T];\n\n    fn deref(&self) -> &Self::Target {\n        self.data\n    }\n}\n\nimpl<'a, T> Deref for RefMut<'a, T> {\n    type Target = [T];\n\n    fn deref(&self) -> &Self::Target {\n        self.data\n    }\n}\n\nimpl<'a, T> DerefMut for RefMut<'a, T> {\n    fn deref_mut(&mut self) -> &mut Self::Target {\n        self.data\n    }\n}\n\nimpl<'a, T> Drop for Ref<'a, T> {\n    fn drop(&mut self) {\n        if self.is_empty() {\n            return;\n        }\n\n        let mut ledger = self.ledger.borrow_mut();\n        let range = Ledger::slice_to_range(self.data);\n        let i = ledger.shared.iter().rposition(|r| r == &range).unwrap();\n\n        ledger.shared.remove(i);\n    }\n}\n\nimpl<'a, T> Drop for RefMut<'a, T> {\n    fn drop(&mut self) {\n        if self.is_empty() {\n            return;\n        }\n\n        let mut ledger = self.ledger.borrow_mut();\n        let range = Ledger::slice_to_range(self.data);\n        let i = ledger.owned.iter().rposition(|r| r == &range).unwrap();\n\n        ledger.owned.remove(i);\n    }\n}\n\n#[derive(Eq, PartialEq)]\n/// An error returned by [`TypedArray::try_borrow`] or [`TypedArray::try_borrow_mut`] indicating\n/// that a mutable borrow would overlap with another borrow.\n///\n/// [`BorrowError`] may be converted to an exception with [`ResultExt::or_throw`].\npub struct BorrowError {\n    _private: (),\n}\n\nimpl BorrowError {\n    fn new() -> Self {\n        BorrowError { _private: () }\n    }\n}\n\nimpl Error for BorrowError {}\n\nimpl Display for BorrowError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        Display::fmt(\"Borrow overlaps with an active mutable borrow\", f)\n    }\n}\n\nimpl Debug for BorrowError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"BorrowError\").finish()\n    }\n}\n\nimpl<T> ResultExt<T> for Result<T, BorrowError> {\n    fn or_throw<'a, C: Context<'a>>(self, cx: &mut C) -> NeonResult<T> {\n        self.or_else(|_| cx.throw_error(\"BorrowError\"))\n    }\n}\n\n/// Represents a typed region of an [`ArrayBuffer`](crate::types::JsArrayBuffer).\n///\n/// A `Region` can be created via the\n/// [`Handle<JsArrayBuffer>::region()`](crate::handle::Handle::region) or\n/// [`JsTypedArray::region()`](crate::types::JsTypedArray::region) methods.\n///\n/// A region is **not** checked for validity until it is converted to\n/// a typed array via [`to_typed_array()`](Region::to_typed_array) or\n/// [`JsTypedArray::from_region()`](crate::types::JsTypedArray::from_region).\n///\n/// # Example\n///\n/// ```\n/// # use neon::prelude::*;\n/// # fn f(mut cx: FunctionContext) -> JsResult<JsUint32Array> {\n/// // Allocate a 16-byte ArrayBuffer and a uint32 array of length 2 (i.e., 8 bytes)\n/// // starting at byte offset 4 of the buffer:\n/// //\n/// //       0       4       8       12      16\n/// //      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n/// // buf: | | | | | | | | | | | | | | | | |\n/// //      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n/// //               ^       ^\n/// //               |       |\n/// //              +-------+-------+\n/// //         arr: |       |       |\n/// //              +-------+-------+\n/// //               0       1       2\n/// let buf = cx.array_buffer(16)?;\n/// let arr = JsUint32Array::from_region(&mut cx, &buf.region(4, 2))?;\n/// # Ok(arr)\n/// # }\n/// ```\n#[derive(Clone, Copy)]\npub struct Region<'cx, T: Binary> {\n    buffer: Handle<'cx, JsArrayBuffer>,\n    offset: usize,\n    len: usize,\n    phantom: PhantomData<T>,\n}\n\nimpl<'cx, T> Region<'cx, T>\nwhere\n    T: Binary,\n    JsTypedArray<T>: Value,\n{\n    /// Returns the handle to the region's buffer.\n    pub fn buffer(&self) -> Handle<'cx, JsArrayBuffer> {\n        self.buffer\n    }\n\n    /// Returns the starting byte offset of the region.\n    pub fn offset(&self) -> usize {\n        self.offset\n    }\n\n    /// Returns the number of elements of type `T` in the region.\n    #[allow(clippy::len_without_is_empty)]\n    pub fn len(&self) -> usize {\n        self.len\n    }\n\n    /// Returns the size of the region in bytes, which is equal to\n    /// `(self.len() * size_of::<T>())`.\n    pub fn size(&self) -> usize {\n        self.len * std::mem::size_of::<T>()\n    }\n\n    /// Constructs a typed array for this buffer region.\n    ///\n    /// The resulting typed array has `self.len()` elements and a size of\n    /// `self.size()` bytes.\n    ///\n    /// Throws an exception if the region is invalid, for example if the starting\n    /// offset is not properly aligned, or the length goes beyond the end of the\n    /// buffer.\n    pub fn to_typed_array<'c, C>(&self, cx: &mut C) -> JsResult<'c, JsTypedArray<T>>\n    where\n        C: Context<'c>,\n    {\n        JsTypedArray::from_region(cx, self)\n    }\n}\n\nmod private {\n    use super::Binary;\n    use crate::sys::raw;\n    use std::fmt::{Debug, Formatter};\n    use std::marker::PhantomData;\n\n    pub trait Sealed {}\n\n    #[derive(Clone)]\n    pub struct JsTypedArrayInner<T: Binary> {\n        pub(super) local: raw::Local,\n        pub(super) buffer: raw::Local,\n        pub(super) _type: PhantomData<T>,\n    }\n\n    impl<T: Binary> Debug for JsTypedArrayInner<T> {\n        fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> {\n            f.write_str(\"JsTypedArrayInner { \")?;\n            f.write_str(\"local: \")?;\n            self.local.fmt(f)?;\n            f.write_str(\", buffer: \")?;\n            self.buffer.fmt(f)?;\n            f.write_str(\", _type: PhantomData\")?;\n            f.write_str(\" }\")?;\n            Ok(())\n        }\n    }\n\n    impl<T: Binary> Copy for JsTypedArrayInner<T> {}\n}\n"
  },
  {
    "path": "crates/neon/src/types_impl/buffer/types.rs",
    "content": "use std::{marker::PhantomData, slice};\n\nuse crate::{\n    context::{\n        internal::{ContextInternal, Env},\n        Context, Cx,\n    },\n    handle::{internal::TransparentNoCopyWrapper, Handle},\n    object::Object,\n    result::{JsResult, Throw},\n    sys::{self, raw, typedarray::TypedArrayInfo, TypedArrayType},\n    types_impl::{\n        buffer::{\n            lock::{Ledger, Lock},\n            private::{self, JsTypedArrayInner},\n            BorrowError, Ref, RefMut, Region, TypedArray,\n        },\n        private::ValueInternal,\n        Value,\n    },\n};\n\n#[cfg(feature = \"doc-comment\")]\nuse doc_comment::doc_comment;\n\n#[cfg(not(feature = \"doc-comment\"))]\nmacro_rules! doc_comment {\n    {$comment:expr, $decl:item} => { $decl };\n}\n\n/// The type of Node\n/// [`Buffer`](https://nodejs.org/api/buffer.html)\n/// objects.\n///\n/// # Example\n///\n/// ```\n/// # use neon::prelude::*;\n/// use neon::types::buffer::TypedArray;\n///\n/// fn make_sequence(mut cx: FunctionContext) -> JsResult<JsBuffer> {\n///     let len = cx.argument::<JsNumber>(0)?.value(&mut cx);\n///     let mut buffer = cx.buffer(len as usize)?;\n///\n///     for (i, elem) in buffer.as_mut_slice(&mut cx).iter_mut().enumerate() {\n///         *elem = i as u8;\n///     }\n///\n///     Ok(buffer)\n/// }\n/// ```\n#[derive(Debug)]\n#[repr(transparent)]\npub struct JsBuffer(raw::Local);\n\nimpl JsBuffer {\n    /// Constructs a new `Buffer` object, safely zero-filled.\n    ///\n    /// **See also:** [`Context::buffer`]\n    pub fn new<'a, C: Context<'a>>(cx: &mut C, len: usize) -> JsResult<'a, Self> {\n        unsafe {\n            let result = sys::buffer::new(cx.env().to_raw(), len);\n\n            if let Ok(buf) = result {\n                Ok(Handle::new_internal(Self(buf)))\n            } else {\n                Err(Throw::new())\n            }\n        }\n    }\n\n    /// Constructs a `JsBuffer` from a slice by copying its contents.\n    ///\n    /// This method is defined on `JsBuffer` as a convenience and delegates to\n    /// [`TypedArray::from_slice`][TypedArray::from_slice].\n    pub fn from_slice<'cx, C>(cx: &mut C, slice: &[u8]) -> JsResult<'cx, Self>\n    where\n        C: Context<'cx>,\n    {\n        <JsBuffer as TypedArray>::from_slice(cx, slice)\n    }\n\n    /// Constructs a new `Buffer` object with uninitialized memory\n    pub unsafe fn uninitialized<'a, C: Context<'a>>(cx: &mut C, len: usize) -> JsResult<'a, Self> {\n        let result = sys::buffer::uninitialized(cx.env().to_raw(), len);\n\n        if let Ok((buf, _)) = result {\n            Ok(Handle::new_internal(Self(buf)))\n        } else {\n            Err(Throw::new())\n        }\n    }\n\n    #[cfg(feature = \"external-buffers\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"external-buffers\")))]\n    /// Construct a new `Buffer` from bytes allocated by Rust.\n    ///\n    /// # Compatibility Note\n    ///\n    /// Some Node environments are built using V8's _sandboxed pointers_ functionality, which\n    /// [disallows the use of external buffers](https://www.electronjs.org/blog/v8-memory-cage).\n    /// In those environments, calling the underlying\n    /// [runtime function](https://nodejs.org/api/n-api.html#napi_create_external_buffer)\n    /// used by this method results in an immediate termination of the Node VM.\n    ///\n    /// As a result, this API is disabled by default. If you are confident that your code will\n    /// only be used in environments that disable sandboxed pointers, you can make use of this\n    /// method by enabling the **`external-buffers`** feature flag.\n    pub fn external<'a, C, T>(cx: &mut C, data: T) -> Handle<'a, Self>\n    where\n        C: Context<'a>,\n        T: AsMut<[u8]> + Send + 'static,\n    {\n        let env = cx.env().to_raw();\n        let value = unsafe { sys::buffer::new_external(env, data) };\n\n        Handle::new_internal(Self(value))\n    }\n}\n\nunsafe impl TransparentNoCopyWrapper for JsBuffer {\n    type Inner = raw::Local;\n\n    fn into_inner(self) -> Self::Inner {\n        self.0\n    }\n}\n\nimpl ValueInternal for JsBuffer {\n    fn name() -> &'static str {\n        \"Buffer\"\n    }\n\n    fn is_typeof<Other: Value>(cx: &mut Cx, other: &Other) -> bool {\n        unsafe { sys::tag::is_buffer(cx.env().to_raw(), other.to_local()) }\n    }\n\n    fn to_local(&self) -> raw::Local {\n        self.0\n    }\n\n    unsafe fn from_local(_env: Env, h: raw::Local) -> Self {\n        Self(h)\n    }\n}\n\nimpl Value for JsBuffer {}\n\nimpl Object for JsBuffer {}\n\nimpl private::Sealed for JsBuffer {}\n\nimpl TypedArray for JsBuffer {\n    type Item = u8;\n\n    fn as_slice<'cx, 'a, C>(&self, cx: &'a C) -> &'a [Self::Item]\n    where\n        C: Context<'cx>,\n    {\n        // # Safety\n        // Only the `Context` with the *most* narrow scope is accessible because `compute_scoped`\n        // and `execute_scope` take an exclusive reference to `Context`. A handle is always\n        // associated with a `Context` and the value will not be garbage collected while that\n        // `Context` is in scope. This means that the referenced data is valid *at least* as long\n        // as `Context`, even if the `Handle` is dropped.\n        unsafe { sys::buffer::as_mut_slice(cx.env().to_raw(), self.to_local()) }\n    }\n\n    fn as_mut_slice<'cx, 'a, C>(&mut self, cx: &'a mut C) -> &'a mut [Self::Item]\n    where\n        C: Context<'cx>,\n    {\n        // # Safety\n        // See `as_slice`\n        unsafe { sys::buffer::as_mut_slice(cx.env().to_raw(), self.to_local()) }\n    }\n\n    fn try_borrow<'cx, 'a, C>(&self, lock: &'a Lock<C>) -> Result<Ref<'a, Self::Item>, BorrowError>\n    where\n        C: Context<'cx>,\n    {\n        // The borrowed data must be guarded by `Ledger` before returning\n        Ledger::try_borrow(&lock.ledger, unsafe {\n            sys::buffer::as_mut_slice(lock.cx.env().to_raw(), self.to_local())\n        })\n    }\n\n    fn try_borrow_mut<'cx, 'a, C>(\n        &mut self,\n        lock: &'a Lock<C>,\n    ) -> Result<RefMut<'a, Self::Item>, BorrowError>\n    where\n        C: Context<'cx>,\n    {\n        // The borrowed data must be guarded by `Ledger` before returning\n        Ledger::try_borrow_mut(&lock.ledger, unsafe {\n            sys::buffer::as_mut_slice(lock.cx.env().to_raw(), self.to_local())\n        })\n    }\n\n    fn size<'cx, C: Context<'cx>>(&self, cx: &mut C) -> usize {\n        unsafe { sys::buffer::size(cx.env().to_raw(), self.to_local()) }\n    }\n\n    fn from_slice<'cx, C>(cx: &mut C, slice: &[u8]) -> JsResult<'cx, Self>\n    where\n        C: Context<'cx>,\n    {\n        let mut buffer = cx.buffer(slice.len())?;\n        let target = buffer.as_mut_slice(cx);\n        target.copy_from_slice(slice);\n        Ok(buffer)\n    }\n}\n\n/// The type of JavaScript\n/// [`ArrayBuffer`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer)\n/// objects.\n///\n/// # Example\n///\n/// ```\n/// # use neon::prelude::*;\n/// use neon::types::buffer::TypedArray;\n///\n/// fn make_sequence(mut cx: FunctionContext) -> JsResult<JsArrayBuffer> {\n///     let len = cx.argument::<JsNumber>(0)?.value(&mut cx);\n///     let mut buffer = cx.array_buffer(len as usize)?;\n///\n///     for (i, elem) in buffer.as_mut_slice(&mut cx).iter_mut().enumerate() {\n///         *elem = i as u8;\n///     }\n///\n///     Ok(buffer)\n/// }\n/// ```\n#[derive(Debug)]\n#[repr(transparent)]\npub struct JsArrayBuffer(raw::Local);\n\nimpl JsArrayBuffer {\n    /// Constructs a new `JsArrayBuffer` object, safely zero-filled.\n    ///\n    /// **See also:** [`Context::array_buffer`]\n    pub fn new<'a, C: Context<'a>>(cx: &mut C, len: usize) -> JsResult<'a, Self> {\n        unsafe {\n            let result = sys::arraybuffer::new(cx.env().to_raw(), len);\n\n            if let Ok(buf) = result {\n                Ok(Handle::new_internal(Self(buf)))\n            } else {\n                Err(Throw::new())\n            }\n        }\n    }\n\n    /// Constructs a `JsArrayBuffer` from a slice by copying its contents.\n    ///\n    /// This method is defined on `JsArrayBuffer` as a convenience and delegates to\n    /// [`TypedArray::from_slice`][TypedArray::from_slice].\n    pub fn from_slice<'cx, C>(cx: &mut C, slice: &[u8]) -> JsResult<'cx, Self>\n    where\n        C: Context<'cx>,\n    {\n        <JsArrayBuffer as TypedArray>::from_slice(cx, slice)\n    }\n\n    #[cfg(feature = \"external-buffers\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"external-buffers\")))]\n    /// Construct a new `JsArrayBuffer` from bytes allocated by Rust.\n    ///\n    /// # Compatibility Note\n    ///\n    /// Some Node environments are built using V8's _sandboxed pointers_ functionality, which\n    /// [disallows the use of external buffers](https://www.electronjs.org/blog/v8-memory-cage).\n    /// In those environments, calling the underlying\n    /// [runtime function](https://nodejs.org/api/n-api.html#napi_create_external_arraybuffer)\n    /// used by this method results in an immediate termination of the Node VM.\n    ///\n    /// As a result, this API is disabled by default. If you are confident that your code will\n    /// only be used in environments that disable sandboxed pointers, you can make use of this\n    /// method by enabling the **`external-buffers`** feature flag.\n    pub fn external<'a, C, T>(cx: &mut C, data: T) -> Handle<'a, Self>\n    where\n        C: Context<'a>,\n        T: AsMut<[u8]> + Send + 'static,\n    {\n        let env = cx.env().to_raw();\n        let value = unsafe { sys::arraybuffer::new_external(env, data) };\n\n        Handle::new_internal(Self(value))\n    }\n\n    /// Returns a region of this buffer.\n    ///\n    /// See also: [`Handle<JsArrayBuffer>::region()`](Handle::region) for a more\n    /// ergonomic form of this method.\n    pub fn region<'cx, T: Binary>(\n        buffer: &Handle<'cx, JsArrayBuffer>,\n        offset: usize,\n        len: usize,\n    ) -> Region<'cx, T> {\n        buffer.region(offset, len)\n    }\n}\n\nimpl<'cx> Handle<'cx, JsArrayBuffer> {\n    /// Returns a [`Region`] representing a typed\n    /// region of this buffer, starting at `offset` and containing `len` elements\n    /// of type `T`.\n    ///\n    /// The region is **not** checked for validity by this method. Regions are only\n    /// validated when they are converted to typed arrays.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # use neon::prelude::*;\n    /// # fn f(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    /// let buf: Handle<JsArrayBuffer> = cx.argument(0)?;\n    /// let region = buf.region::<u32>(64, 8);\n    /// println!(\"offset={}, len={}, size={}\", region.offset(), region.len(), region.size());\n    /// # Ok(cx.undefined())\n    /// # }\n    /// ```\n    ///\n    /// See the [`Region`] documentation for more information.\n    pub fn region<T: Binary>(&self, offset: usize, len: usize) -> Region<'cx, T> {\n        Region {\n            buffer: *self,\n            offset,\n            len,\n            phantom: PhantomData,\n        }\n    }\n}\n\nunsafe impl TransparentNoCopyWrapper for JsArrayBuffer {\n    type Inner = raw::Local;\n\n    fn into_inner(self) -> Self::Inner {\n        self.0\n    }\n}\n\nimpl ValueInternal for JsArrayBuffer {\n    fn name() -> &'static str {\n        \"JsArrayBuffer\"\n    }\n\n    fn is_typeof<Other: Value>(cx: &mut Cx, other: &Other) -> bool {\n        unsafe { sys::tag::is_arraybuffer(cx.env().to_raw(), other.to_local()) }\n    }\n\n    fn to_local(&self) -> raw::Local {\n        self.0\n    }\n\n    unsafe fn from_local(_env: Env, h: raw::Local) -> Self {\n        Self(h)\n    }\n}\n\nimpl Value for JsArrayBuffer {}\n\nimpl Object for JsArrayBuffer {}\n\nimpl private::Sealed for JsArrayBuffer {}\n\nimpl TypedArray for JsArrayBuffer {\n    type Item = u8;\n\n    fn as_slice<'cx, 'a, C>(&self, cx: &'a C) -> &'a [Self::Item]\n    where\n        C: Context<'cx>,\n    {\n        unsafe { sys::arraybuffer::as_mut_slice(cx.env().to_raw(), self.to_local()) }\n    }\n\n    fn as_mut_slice<'cx, 'a, C>(&mut self, cx: &'a mut C) -> &'a mut [Self::Item]\n    where\n        C: Context<'cx>,\n    {\n        unsafe { sys::arraybuffer::as_mut_slice(cx.env().to_raw(), self.to_local()) }\n    }\n\n    fn try_borrow<'cx, 'a, C>(&self, lock: &'a Lock<C>) -> Result<Ref<'a, Self::Item>, BorrowError>\n    where\n        C: Context<'cx>,\n    {\n        // The borrowed data must be guarded by `Ledger` before returning\n        Ledger::try_borrow(&lock.ledger, unsafe {\n            sys::arraybuffer::as_mut_slice(lock.cx.env().to_raw(), self.to_local())\n        })\n    }\n\n    fn try_borrow_mut<'cx, 'a, C>(\n        &mut self,\n        lock: &'a Lock<C>,\n    ) -> Result<RefMut<'a, Self::Item>, BorrowError>\n    where\n        C: Context<'cx>,\n    {\n        // The borrowed data must be guarded by `Ledger` before returning\n        Ledger::try_borrow_mut(&lock.ledger, unsafe {\n            sys::arraybuffer::as_mut_slice(lock.cx.env().to_raw(), self.to_local())\n        })\n    }\n\n    fn size<'cx, C: Context<'cx>>(&self, cx: &mut C) -> usize {\n        unsafe { sys::arraybuffer::size(cx.env().to_raw(), self.to_local()) }\n    }\n\n    fn from_slice<'cx, C>(cx: &mut C, slice: &[u8]) -> JsResult<'cx, Self>\n    where\n        C: Context<'cx>,\n    {\n        let len = slice.len();\n        let mut buffer = JsArrayBuffer::new(cx, len)?;\n        let target = buffer.as_mut_slice(cx);\n        target.copy_from_slice(slice);\n        Ok(buffer)\n    }\n}\n\n/// A marker trait for all possible element types of binary buffers.\n///\n/// This trait can only be implemented within the Neon library.\npub trait Binary: private::Sealed + Copy {\n    /// The internal Node-API enum value for this binary type.\n    const TYPE_TAG: TypedArrayType;\n}\n\n/// The family of JavaScript [typed array][typed-arrays] types.\n///\n/// ## Typed Arrays\n///\n/// JavaScript's [typed arrays][typed-arrays] are objects that allow efficiently reading\n/// and writing raw binary data in memory. In Neon, the generic type `JsTypedArray<T>`\n/// represents a JavaScript typed array with element type `T`. For example, a JavaScript\n/// [`Uint32Array`][Uint32Array] represents a compact array of 32-bit unsigned integers,\n/// and is represented in Neon as a `JsTypedArray<u32>`.\n///\n/// Neon also offers a set of convenience shorthands for concrete instances of\n/// `JsTypedArray`, named after their corresponding JavaScript type. For example,\n/// `JsTypedArray<u32>` can also be referred to as [`JsUint32Array`][JsUint32Array].\n///\n/// The following table shows the complete set of typed array types, with both their\n/// JavaScript and Neon types:\n///\n/// | Rust Type                      | Convenience Type                       | JavaScript Type                    |\n/// | ------------------------------ | -------------------------------------- | ---------------------------------- |\n/// | `JsTypedArray<`[`u8`][u8]`>`   | [`JsUint8Array`][JsUint8Array]         | [`Uint8Array`][Uint8Array]         |\n/// | `JsTypedArray<`[`i8`][i8]`>`   | [`JsInt8Array`][JsInt8Array]           | [`Int8Array`][Int8Array]           |\n/// | `JsTypedArray<`[`u16`][u16]`>` | [`JsUint16Array`][JsUint16Array]       | [`Uint16Array`][Uint16Array]       |\n/// | `JsTypedArray<`[`i16`][i16]`>` | [`JsInt16Array`][JsInt16Array]         | [`Int16Array`][Int16Array]         |\n/// | `JsTypedArray<`[`u32`][u32]`>` | [`JsUint32Array`][JsUint32Array]       | [`Uint32Array`][Uint32Array]       |\n/// | `JsTypedArray<`[`i32`][i32]`>` | [`JsInt32Array`][JsInt32Array]         | [`Int32Array`][Int32Array]         |\n/// | `JsTypedArray<`[`u64`][u64]`>` | [`JsBigUint64Array`][JsBigUint64Array] | [`BigUint64Array`][BigUint64Array] |\n/// | `JsTypedArray<`[`i64`][i64]`>` | [`JsBigInt64Array`][JsBigInt64Array]   | [`BigInt64Array`][BigInt64Array]   |\n/// | `JsTypedArray<`[`f32`][f32]`>` | [`JsFloat32Array`][JsFloat32Array]     | [`Float32Array`][Float32Array]     |\n/// | `JsTypedArray<`[`f64`][f64]`>` | [`JsFloat64Array`][JsFloat64Array]     | [`Float64Array`][Float64Array]     |\n///\n/// ### Example: Creating an integer array\n///\n/// This example creates a typed array of unsigned 32-bit integers with a user-specified\n/// length:\n///\n/// ```\n/// # use neon::prelude::*;\n/// fn create_int_array(mut cx: FunctionContext) -> JsResult<JsTypedArray<u32>> {\n///     let len = cx.argument::<JsNumber>(0)?.value(&mut cx) as usize;\n///     JsTypedArray::new(&mut cx, len)\n/// }\n/// ```\n///\n/// ## Buffers\n///\n/// Typed arrays are managed with the [`ArrayBuffer`][ArrayBuffer] type, which controls\n/// the storage of the underlying data buffer, and several typed views for managing access\n/// to the buffer. Neon provides access to the `ArrayBuffer` class with the\n/// [`JsArrayBuffer`](crate::types::JsArrayBuffer) type.\n///\n/// Node also provides a [`Buffer`][Buffer] type, which is built on top of `ArrayBuffer`\n/// and provides additional functionality. Neon provides access to the `Buffer` class\n/// with the [`JsBuffer`](crate::types::JsBuffer) type.\n///\n/// Many of Node's I/O APIs work with these types, and they can also be used for\n/// compact in-memory data structures, which can be shared efficiently between\n/// JavaScript and Rust without copying.\n///\n/// [u8]: std::primitive::u8\n/// [i8]: std::primitive::i8\n/// [u16]: std::primitive::u16\n/// [i16]: std::primitive::i16\n/// [u32]: std::primitive::u32\n/// [i32]: std::primitive::i32\n/// [u64]: std::primitive::u64\n/// [i64]: std::primitive::i64\n/// [f32]: std::primitive::f32\n/// [f64]: std::primitive::f64\n/// [JsUint8Array]: crate::types::JsUint8Array\n/// [JsInt8Array]: crate::types::JsInt8Array\n/// [JsUint16Array]: crate::types::JsUint16Array\n/// [JsInt16Array]: crate::types::JsInt16Array\n/// [JsUint32Array]: crate::types::JsUint32Array\n/// [JsInt32Array]: crate::types::JsInt32Array\n/// [JsBigUint64Array]: crate::types::JsBigUint64Array\n/// [JsBigInt64Array]: crate::types::JsBigInt64Array\n/// [JsFloat32Array]: crate::types::JsFloat32Array\n/// [JsFloat64Array]: crate::types::JsFloat64Array\n/// [Uint8Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array\n/// [Int8Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int8Array\n/// [Uint16Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint16Array\n/// [Int16Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int16Array\n/// [Uint32Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint32Array\n/// [Int32Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int32Array\n/// [BigUint64Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigUint64Array\n/// [BigInt64Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt64Array\n/// [Float32Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array\n/// [Float64Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float64Array\n/// [typed-arrays]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays\n/// [ArrayBuffer]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer\n/// [Buffer]: https://nodejs.org/api/buffer.html\n#[derive(Debug)]\n#[repr(transparent)]\npub struct JsTypedArray<T: Binary>(JsTypedArrayInner<T>);\n\nimpl<T: Binary> private::Sealed for JsTypedArray<T> {}\n\nunsafe impl<T: Binary> TransparentNoCopyWrapper for JsTypedArray<T> {\n    type Inner = JsTypedArrayInner<T>;\n\n    fn into_inner(self) -> Self::Inner {\n        self.0\n    }\n}\n\nimpl<T> TypedArray for JsTypedArray<T>\nwhere\n    T: Binary,\n    Self: Value,\n{\n    type Item = T;\n\n    fn as_slice<'cx, 'a, C>(&self, cx: &'a C) -> &'a [Self::Item]\n    where\n        C: Context<'cx>,\n    {\n        unsafe {\n            let env = cx.env().to_raw();\n            let value = self.to_local();\n            let info = sys::typedarray::info(env, value);\n\n            slice_from_info(info)\n        }\n    }\n\n    fn as_mut_slice<'cx, 'a, C>(&mut self, cx: &'a mut C) -> &'a mut [Self::Item]\n    where\n        C: Context<'cx>,\n    {\n        unsafe {\n            let env = cx.env().to_raw();\n            let value = self.to_local();\n            let info = sys::typedarray::info(env, value);\n\n            slice_from_info_mut(info)\n        }\n    }\n\n    fn try_borrow<'cx, 'b, C>(\n        &self,\n        lock: &'b Lock<'b, C>,\n    ) -> Result<Ref<'b, Self::Item>, BorrowError>\n    where\n        C: Context<'cx>,\n    {\n        unsafe {\n            let env = lock.cx.env().to_raw();\n            let value = self.to_local();\n            let info = sys::typedarray::info(env, value);\n\n            // The borrowed data must be guarded by `Ledger` before returning\n            Ledger::try_borrow(&lock.ledger, slice_from_info(info))\n        }\n    }\n\n    fn try_borrow_mut<'cx, 'a, C>(\n        &mut self,\n        lock: &'a Lock<'a, C>,\n    ) -> Result<RefMut<'a, Self::Item>, BorrowError>\n    where\n        C: Context<'cx>,\n    {\n        unsafe {\n            let env = lock.cx.env().to_raw();\n            let value = self.to_local();\n            let info = sys::typedarray::info(env, value);\n\n            // The borrowed data must be guarded by `Ledger` before returning\n            Ledger::try_borrow_mut(&lock.ledger, slice_from_info_mut(info))\n        }\n    }\n\n    fn size<'cx, C: Context<'cx>>(&self, cx: &mut C) -> usize {\n        self.len(cx) * std::mem::size_of::<Self::Item>()\n    }\n\n    fn from_slice<'cx, C>(cx: &mut C, slice: &[T]) -> JsResult<'cx, Self>\n    where\n        C: Context<'cx>,\n    {\n        let _elt_size = std::mem::size_of::<T>();\n        let size = std::mem::size_of_val(slice);\n        let buffer = cx.array_buffer(size)?;\n\n        let mut array = Self::from_buffer(cx, buffer)?;\n        let target = array.as_mut_slice(cx);\n        target.copy_from_slice(slice);\n\n        Ok(array)\n    }\n}\n\nimpl<T: Binary> JsTypedArray<T>\nwhere\n    JsTypedArray<T>: Value,\n{\n    /// Constructs an instance from a slice by copying its contents.\n    ///\n    /// This method is defined on `JsTypedArray` as a convenience and delegates to\n    /// [`TypedArray::from_slice`][TypedArray::from_slice].\n    pub fn from_slice<'cx, C>(cx: &mut C, slice: &[T]) -> JsResult<'cx, Self>\n    where\n        C: Context<'cx>,\n    {\n        <JsTypedArray<T> as TypedArray>::from_slice(cx, slice)\n    }\n}\n\nimpl<T> JsTypedArray<T>\nwhere\n    T: Binary,\n    Self: Value,\n{\n    /// Constructs a typed array that views `buffer`.\n    ///\n    /// The resulting typed array has `(buffer.size() / size_of::<T>())` elements.\n    pub fn from_buffer<'cx, 'b: 'cx, C>(\n        cx: &mut C,\n        buffer: Handle<'b, JsArrayBuffer>,\n    ) -> JsResult<'cx, Self>\n    where\n        C: Context<'cx>,\n    {\n        let size = buffer.size(cx);\n        let elt_size = std::mem::size_of::<T>();\n        let len = size / elt_size;\n\n        if (len * elt_size) != size {\n            return cx.throw_range_error(format!(\n                \"byte length of typed array should be a multiple of {elt_size}\"\n            ));\n        }\n\n        Self::from_region(cx, &buffer.region(0, len))\n    }\n\n    /// Constructs a typed array for the specified buffer region.\n    ///\n    /// The resulting typed array has `region.len()` elements and a size of\n    /// `region.size()` bytes.\n    ///\n    /// Throws an exception if the region is invalid, for example if the starting\n    /// offset is not properly aligned, or the length goes beyond the end of the\n    /// buffer.\n    pub fn from_region<'c, 'r, C>(cx: &mut C, region: &Region<'r, T>) -> JsResult<'c, Self>\n    where\n        C: Context<'c>,\n    {\n        let &Region {\n            buffer,\n            offset,\n            len,\n            ..\n        } = region;\n\n        let arr = unsafe {\n            sys::typedarray::new(\n                cx.env().to_raw(),\n                T::TYPE_TAG,\n                buffer.to_local(),\n                offset,\n                len,\n            )\n            .map_err(|_| Throw::new())?\n        };\n\n        Ok(Handle::new_internal(Self(JsTypedArrayInner {\n            local: arr,\n            buffer: buffer.to_local(),\n            _type: PhantomData,\n        })))\n    }\n\n    /// Returns information about the backing buffer region for this typed array.\n    pub fn region<'cx, C>(&self, cx: &mut C) -> Region<'cx, T>\n    where\n        C: Context<'cx>,\n    {\n        let env = cx.env();\n        let info = unsafe { sys::typedarray::info(env.to_raw(), self.to_local()) };\n\n        Region {\n            buffer: Handle::new_internal(unsafe { JsArrayBuffer::from_local(cx.env(), info.buf) }),\n            offset: info.offset,\n            len: info.length,\n            phantom: PhantomData,\n        }\n    }\n\n    /// Constructs a new typed array of length `len`.\n    ///\n    /// The resulting typed array has a newly allocated storage buffer of\n    /// size `(len * size_of::<T>())` bytes.\n    pub fn new<'cx, C>(cx: &mut C, len: usize) -> JsResult<'cx, Self>\n    where\n        C: Context<'cx>,\n    {\n        let buffer = cx.array_buffer(len * std::mem::size_of::<T>())?;\n        Self::from_region(cx, &buffer.region(0, len))\n    }\n\n    /// Returns the [`JsArrayBuffer`](JsArrayBuffer) that owns the underlying storage buffer\n    /// for this typed array.\n    ///\n    /// Note that the typed array might only reference a region of the buffer; use the\n    /// [`offset()`](JsTypedArray::offset) and\n    /// [`size()`](crate::types::buffer::TypedArray::size) methods to\n    /// determine the region.\n    pub fn buffer<'cx, C>(&self, cx: &mut C) -> Handle<'cx, JsArrayBuffer>\n    where\n        C: Context<'cx>,\n    {\n        Handle::new_internal(unsafe { JsArrayBuffer::from_local(cx.env(), self.0.buffer) })\n    }\n\n    /// Returns the offset (in bytes) of the typed array from the start of its\n    /// [`JsArrayBuffer`](JsArrayBuffer).\n    pub fn offset<'cx, C>(&self, cx: &mut C) -> usize\n    where\n        C: Context<'cx>,\n    {\n        let info = unsafe { sys::typedarray::info(cx.env().to_raw(), self.to_local()) };\n        info.offset\n    }\n\n    /// Returns the length of the typed array, i.e. the number of elements.\n    ///\n    /// Note that, depending on the element size, this is not necessarily the same as\n    /// [`size()`](crate::types::buffer::TypedArray::size). In particular:\n    ///\n    /// ```ignore\n    /// self.size() == self.len() * size_of::<T>()\n    /// ```\n    #[allow(clippy::len_without_is_empty)]\n    pub fn len<'cx, C>(&self, cx: &mut C) -> usize\n    where\n        C: Context<'cx>,\n    {\n        let info = unsafe { sys::typedarray::info(cx.env().to_raw(), self.to_local()) };\n        info.length\n    }\n}\n\nunsafe fn slice_from_info<'a, T>(info: TypedArrayInfo) -> &'a [T] {\n    if info.length == 0 {\n        &[]\n    } else {\n        slice::from_raw_parts(info.data.cast(), info.length)\n    }\n}\n\nunsafe fn slice_from_info_mut<'a, T>(info: TypedArrayInfo) -> &'a mut [T] {\n    if info.length == 0 {\n        &mut []\n    } else {\n        slice::from_raw_parts_mut(info.data.cast(), info.length)\n    }\n}\n\nmacro_rules! impl_typed_array {\n    ($typ:ident, $etyp:ty, $($pattern:pat_param)|+, $tag:ident, $alias:ident, $two:expr$(,)?) => {\n        impl private::Sealed for $etyp {}\n\n        impl Binary for $etyp {\n            const TYPE_TAG: TypedArrayType = TypedArrayType::$tag;\n        }\n\n        impl Value for JsTypedArray<$etyp> {}\n\n        impl Object for JsTypedArray<$etyp> {}\n\n        impl ValueInternal for JsTypedArray<$etyp> {\n            fn name() -> &'static str {\n                stringify!($typ)\n            }\n\n            fn is_typeof<Other: Value>(cx: &mut Cx, other: &Other) -> bool {\n                let env = cx.env().to_raw();\n                let other = other.to_local();\n\n                if unsafe { !sys::tag::is_typedarray(env, other) } {\n                    return false;\n                }\n\n                let info = unsafe { sys::typedarray::info(env, other) };\n\n                matches!(info.typ, $($pattern)|+)\n            }\n\n            fn to_local(&self) -> raw::Local {\n                self.0.local\n            }\n\n            unsafe fn from_local(env: Env, local: raw::Local) -> Self {\n                // Safety: Recomputing this information ensures that the lifetime of the\n                //         buffer handle matches the lifetime of the typed array handle.\n                let info = unsafe { sys::typedarray::info(env.to_raw(), local) };\n\n                Self(JsTypedArrayInner {\n                    local,\n                    buffer: info.buf,\n                    _type: PhantomData,\n                })\n            }\n        }\n\n        doc_comment! {\n            concat!(\n                \"The type of JavaScript [`\",\n                stringify!($typ),\n                \"`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/\",\n                stringify!($typ),\n                \") objects.\n\n# Example\n\n```\n# use neon::prelude::*;\nuse neon::types::buffer::TypedArray;\n\nfn double(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let mut array: Handle<\",\n                stringify!($alias),\n                \"> = cx.argument(0)?;\n\n    for elem in array.as_mut_slice(&mut cx).iter_mut() {\n        *elem *= \",\n                stringify!($two),\n                \";\n    }\n\n    Ok(cx.undefined())\n}\n```\",\n            ),\n            pub type $alias = JsTypedArray<$etyp>;\n        }\n    };\n}\n\nimpl_typed_array!(Int8Array, i8, TypedArrayType::I8, I8, JsInt8Array, 2);\nimpl_typed_array!(\n    Uint8Array,\n    u8,\n    TypedArrayType::U8 | TypedArrayType::U8Clamped,\n    U8,\n    JsUint8Array,\n    2,\n);\nimpl_typed_array!(Int16Array, i16, TypedArrayType::I16, I16, JsInt16Array, 2);\nimpl_typed_array!(Uint16Array, u16, TypedArrayType::U16, U16, JsUint16Array, 2);\nimpl_typed_array!(Int32Array, i32, TypedArrayType::I32, I32, JsInt32Array, 2);\nimpl_typed_array!(Uint32Array, u32, TypedArrayType::U32, U32, JsUint32Array, 2);\nimpl_typed_array!(\n    Float32Array,\n    f32,\n    TypedArrayType::F32,\n    F32,\n    JsFloat32Array,\n    2.0,\n);\nimpl_typed_array!(\n    Float64Array,\n    f64,\n    TypedArrayType::F64,\n    F64,\n    JsFloat64Array,\n    2.0,\n);\nimpl_typed_array!(\n    BigInt64Array,\n    i64,\n    TypedArrayType::I64,\n    I64,\n    JsBigInt64Array,\n    2,\n);\nimpl_typed_array!(\n    BigUint64Array,\n    u64,\n    TypedArrayType::U64,\n    U64,\n    JsBigUint64Array,\n    2,\n);\n"
  },
  {
    "path": "crates/neon/src/types_impl/date.rs",
    "content": "use std::{\n    error::Error,\n    fmt::{self, Debug},\n};\n\nuse super::{private::ValueInternal, Value};\n\nuse crate::{\n    context::{\n        internal::{ContextInternal, Env},\n        Context, Cx,\n    },\n    handle::{internal::TransparentNoCopyWrapper, Handle},\n    object::Object,\n    result::{JsResult, ResultExt},\n    sys::{self, raw},\n};\n\n/// The type of JavaScript\n/// [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date)\n/// objects.\n///\n/// # Example\n///\n/// The following shows an example of converting Rust\n/// [`SystemTime`](std::time::SystemTime) timestamps to JavaScript `Date` objects.\n///\n/// ```\n/// # use neon::prelude::*;\n/// use easy_cast::Cast; // for safe numeric conversions\n/// use neon::types::JsDate;\n/// use std::{error::Error, fs::File, time::SystemTime};\n///\n/// /// Return the \"modified\" timestamp for the file at the given path.\n/// fn last_modified(path: &str) -> Result<f64, Box<dyn Error>> {\n///     Ok(File::open(&path)?\n///         .metadata()?\n///         .modified()?\n///         .duration_since(SystemTime::UNIX_EPOCH)?\n///         .as_millis()\n///         .try_cast()?)\n/// }\n///\n/// fn modified(mut cx: FunctionContext) -> JsResult<JsDate> {\n///     let path: Handle<JsString> = cx.argument(0)?;\n///\n///     last_modified(&path.value(&mut cx))\n///         .and_then(|n| Ok(cx.date(n)?))\n///         .or_else(|err| cx.throw_error(err.to_string()))\n/// }\n/// ```\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-5\")))]\n#[derive(Debug)]\n#[repr(transparent)]\npub struct JsDate(raw::Local);\n\nimpl Value for JsDate {}\n\nunsafe impl TransparentNoCopyWrapper for JsDate {\n    type Inner = raw::Local;\n\n    fn into_inner(self) -> Self::Inner {\n        self.0\n    }\n}\n\n/// An error produced when constructing a date with an invalid value.\n#[derive(Debug)]\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-5\")))]\npub struct DateError(DateErrorKind);\n\nimpl DateError {\n    pub fn kind(&self) -> DateErrorKind {\n        self.0\n    }\n}\n\nimpl fmt::Display for DateError {\n    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {\n        fmt.write_str(self.0.as_str())\n    }\n}\n\nimpl Error for DateError {}\n\n/// The error kinds corresponding to `DateError`\n#[derive(Debug, Copy, Clone, PartialEq, Eq)]\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-5\")))]\npub enum DateErrorKind {\n    /// Produced for an initialization value greater than\n    /// [`JsDate::MAX_VALUE`](JsDate::MAX_VALUE).\n    Overflow,\n    /// Produced for an initialization value lesser than\n    /// [`JsDate::MIN_VALUE`](JsDate::MIN_VALUE).\n    Underflow,\n}\n\nimpl DateErrorKind {\n    fn as_str(&self) -> &'static str {\n        match *self {\n            DateErrorKind::Overflow => \"Date overflow\",\n            DateErrorKind::Underflow => \"Date underflow\",\n        }\n    }\n}\n\nimpl<'a, T: Value> ResultExt<Handle<'a, T>> for Result<Handle<'a, T>, DateError> {\n    /// Creates an `Error` on error\n    fn or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> JsResult<'a, T> {\n        self.or_else(|e| cx.throw_range_error(e.0.as_str()))\n    }\n}\n\nimpl JsDate {\n    /// The smallest possible `Date` value,\n    /// [defined by ECMAScript](https://www.ecma-international.org/ecma-262/5.1/#sec-15.7.3.3).\n    pub const MIN_VALUE: f64 = -8.64e15;\n    /// The largest possible `Date` value,\n    /// [defined by ECMAScript](https://www.ecma-international.org/ecma-262/5.1/#sec-15.7.3.2).\n    pub const MAX_VALUE: f64 = 8.64e15;\n\n    /// Creates a new `Date`. It errors when `value` is outside the range of valid JavaScript\n    /// `Date` values. When `value` is `NaN`, the operation will succeed but with an\n    /// invalid `Date`.\n    pub fn new<'a, C: Context<'a>, T: Into<f64>>(\n        cx: &mut C,\n        value: T,\n    ) -> Result<Handle<'a, JsDate>, DateError> {\n        let env = cx.env().to_raw();\n        let time = value.into();\n\n        if time > JsDate::MAX_VALUE {\n            return Err(DateError(DateErrorKind::Overflow));\n        } else if time < JsDate::MIN_VALUE {\n            return Err(DateError(DateErrorKind::Underflow));\n        }\n\n        let local = unsafe { sys::date::new_date(env, time) };\n        let date = Handle::new_internal(JsDate(local));\n        Ok(date)\n    }\n\n    /// Creates a new `Date` with lossy conversion for out of bounds `Date` values.\n    /// Out of bounds values will be treated as `NaN`.\n    pub fn new_lossy<'a, C: Context<'a>, V: Into<f64>>(cx: &mut C, value: V) -> Handle<'a, JsDate> {\n        let env = cx.env().to_raw();\n        let local = unsafe { sys::date::new_date(env, value.into()) };\n        Handle::new_internal(JsDate(local))\n    }\n\n    /// Gets the `Date`'s value. An invalid `Date` will return [`std::f64::NAN`].\n    pub fn value<'a, C: Context<'a>>(&self, cx: &mut C) -> f64 {\n        let env = cx.env().to_raw();\n        unsafe { sys::date::value(env, self.to_local()) }\n    }\n\n    /// Checks if the `Date`'s value is valid. A `Date` is valid if its value is\n    /// between [`JsDate::MIN_VALUE`] and [`JsDate::MAX_VALUE`] or if it is `NaN`.\n    pub fn is_valid<'a, C: Context<'a>>(&self, cx: &mut C) -> bool {\n        let value = self.value(cx);\n        (JsDate::MIN_VALUE..=JsDate::MAX_VALUE).contains(&value)\n    }\n}\n\nimpl ValueInternal for JsDate {\n    fn name() -> &'static str {\n        \"object\"\n    }\n\n    fn is_typeof<Other: Value>(cx: &mut Cx, other: &Other) -> bool {\n        unsafe { sys::tag::is_date(cx.env().to_raw(), other.to_local()) }\n    }\n\n    fn to_local(&self) -> raw::Local {\n        self.0\n    }\n\n    unsafe fn from_local(_env: Env, h: raw::Local) -> Self {\n        JsDate(h)\n    }\n}\n\nimpl Object for JsDate {}\n"
  },
  {
    "path": "crates/neon/src/types_impl/error.rs",
    "content": "//! Types and traits representing JavaScript error values.\n\nuse std::panic::{catch_unwind, UnwindSafe};\n\nuse crate::{\n    context::{\n        internal::{ContextInternal, Env},\n        Context, Cx,\n    },\n    handle::{internal::TransparentNoCopyWrapper, Handle},\n    object::Object,\n    result::{NeonResult, Throw},\n    sys::{self, raw},\n    types::{build, private::ValueInternal, utf8::Utf8, Value},\n};\n\n/// The type of JavaScript\n/// [`Error`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)\n/// objects.\n///\n/// # Example\n///\n/// ```\n/// # use neon::prelude::*;\n/// # fn test(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n/// // Create a type error:\n/// let err = cx.type_error(\"expected a number, found a string\")?;\n///\n/// // Add some custom diagnostic properties to the error:\n/// err.prop(&mut cx, \"expected\").set(\"number\")?;\n/// err.prop(&mut cx, \"found\").set(\"string\")?;\n///\n/// // Throw the error:\n/// cx.throw(err)?;\n/// # Ok(cx.undefined())\n/// # }\n/// ```\n#[repr(transparent)]\n#[derive(Debug)]\npub struct JsError(raw::Local);\n\nunsafe impl TransparentNoCopyWrapper for JsError {\n    type Inner = raw::Local;\n\n    fn into_inner(self) -> Self::Inner {\n        self.0\n    }\n}\n\nimpl ValueInternal for JsError {\n    fn name() -> &'static str {\n        \"Error\"\n    }\n\n    fn is_typeof<Other: Value>(cx: &mut Cx, other: &Other) -> bool {\n        unsafe { sys::tag::is_error(cx.env().to_raw(), other.to_local()) }\n    }\n\n    fn to_local(&self) -> raw::Local {\n        self.0\n    }\n\n    unsafe fn from_local(_env: Env, h: raw::Local) -> Self {\n        JsError(h)\n    }\n}\n\nimpl Value for JsError {}\n\nimpl Object for JsError {}\n\nimpl JsError {\n    /// Creates a direct instance of the [`Error`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error) class.\n    ///\n    /// **See also:** [`Context::error`]\n    pub fn error<'a, C: Context<'a>, S: AsRef<str>>(\n        cx: &mut C,\n        msg: S,\n    ) -> NeonResult<Handle<'a, JsError>> {\n        let msg = cx.string(msg.as_ref());\n        build(cx.env(), |out| unsafe {\n            sys::error::new_error(cx.env().to_raw(), out, msg.to_local());\n            true\n        })\n    }\n\n    /// Creates an instance of the [`TypeError`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/TypeError) class.\n    ///\n    /// **See also:** [`Context::type_error`]\n    pub fn type_error<'a, C: Context<'a>, S: AsRef<str>>(\n        cx: &mut C,\n        msg: S,\n    ) -> NeonResult<Handle<'a, JsError>> {\n        let msg = cx.string(msg.as_ref());\n        build(cx.env(), |out| unsafe {\n            sys::error::new_type_error(cx.env().to_raw(), out, msg.to_local());\n            true\n        })\n    }\n\n    /// Creates an instance of the [`RangeError`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RangeError) class.\n    ///\n    /// **See also:** [`Context::range_error`]\n    pub fn range_error<'a, C: Context<'a>, S: AsRef<str>>(\n        cx: &mut C,\n        msg: S,\n    ) -> NeonResult<Handle<'a, JsError>> {\n        let msg = cx.string(msg.as_ref());\n        build(cx.env(), |out| unsafe {\n            sys::error::new_range_error(cx.env().to_raw(), out, msg.to_local());\n            true\n        })\n    }\n}\n\npub(crate) fn convert_panics<T, F: UnwindSafe + FnOnce() -> NeonResult<T>>(\n    env: Env,\n    f: F,\n) -> NeonResult<T> {\n    match catch_unwind(f) {\n        Ok(result) => result,\n        Err(panic) => {\n            let msg = if let Some(string) = panic.downcast_ref::<String>() {\n                format!(\"internal error in Neon module: {string}\")\n            } else if let Some(str) = panic.downcast_ref::<&str>() {\n                format!(\"internal error in Neon module: {str}\")\n            } else {\n                \"internal error in Neon module\".to_string()\n            };\n            let (data, len) = Utf8::from(&msg[..]).truncate().lower();\n            unsafe {\n                sys::error::clear_exception(env.to_raw());\n                sys::error::throw_error_from_utf8(env.to_raw(), data, len);\n                Err(Throw::new())\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "crates/neon/src/types_impl/extract/array.rs",
    "content": "use std::{error, fmt, mem::MaybeUninit};\n\nuse crate::{\n    context::{internal::ContextInternal, Context, Cx},\n    handle::Handle,\n    result::{JsResult, NeonResult, Throw},\n    sys,\n    types::{\n        extract::{private, TryFromJs, TryIntoJs, TypeExpected},\n        private::ValueInternal,\n        JsArray, JsValue,\n    },\n};\n\n/// Extracts a [JavaScript array](JsArray) into a Rust collection or converts a collection to a JS array.\n///\n/// Any collection that implements [`FromIterator`] and [`IntoIterator`] can be extracted. Extraction\n/// fails with [`ArrayError`] if the value is not an array or an element fails to be extracted.\n///\n/// # Example\n///\n/// ```\n/// # use std::collections::HashSet;\n/// # use neon::types::extract::Array;\n/// #[neon::export]\n/// fn list_of_strings(Array(arr): Array<Vec<String>>) -> Array<Vec<String>> {\n///     Array(arr)\n/// }\n///\n/// #[neon::export]\n/// fn double(Array(arr): Array<Vec<f64>>) -> Array<impl Iterator<Item = f64>> {\n///     Array(arr.into_iter().map(|x| x * 2.0))\n/// }\n///\n/// #[neon::export]\n/// fn dedupe(set: Array<HashSet<String>>) -> Array<HashSet<String>> {\n///     set\n/// }\n/// ```\n///\n/// **Note**: Only native JS arrays are accepted. For typed arrays use [`Uint8Array`](super::Uint8Array),\n/// [`Float64Array`](super::Float64Array), etc.\npub struct Array<T>(pub T);\n\nimpl<T> private::Sealed for Array<T> {}\n\nimpl<'cx, T> TryFromJs<'cx> for Array<T>\nwhere\n    T: FromIterator<T::Item>,\n    T: IntoIterator,\n    T::Item: TryFromJs<'cx>,\n{\n    type Error = ArrayError<<T::Item as TryFromJs<'cx>>::Error>;\n\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        let env = cx.env().to_raw();\n        let v = v.to_local();\n        let len = unsafe {\n            let mut len = 0;\n\n            match sys::get_array_length(env, v, &mut len) {\n                Err(sys::Status::PendingException) => return Err(Throw::new()),\n                Err(sys::Status::ArrayExpected) => return Ok(Err(ArrayError::array())),\n                res => res.unwrap(),\n            }\n\n            len\n        };\n\n        (0..len)\n            .map(|i| {\n                let item = unsafe {\n                    let mut item = MaybeUninit::uninit();\n\n                    match sys::get_element(env, v, i, item.as_mut_ptr()) {\n                        Err(sys::Status::PendingException) => return Err(Throw::new()),\n                        res => res.unwrap(),\n                    }\n\n                    Handle::new_internal(JsValue::from_local(cx.env(), item.assume_init()))\n                };\n\n                match T::Item::try_from_js(cx, item) {\n                    Ok(Ok(item)) => Ok(Ok(item)),\n                    Ok(Err(err)) => Ok(Err(ArrayError::item(err))),\n                    Err(err) => Err(err),\n                }\n            })\n            .collect::<Result<Result<T, Self::Error>, Throw>>()\n            .map(|v| v.map(Array))\n    }\n}\n\nimpl<'cx, T> TryIntoJs<'cx> for Array<T>\nwhere\n    T: IntoIterator,\n    T::Item: TryIntoJs<'cx>,\n{\n    type Value = JsArray;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        let iter = self.0.into_iter();\n        let env = cx.env().to_raw();\n        let (len, _) = iter.size_hint();\n        let arr = unsafe {\n            let mut arr = MaybeUninit::uninit();\n\n            match sys::create_array_with_length(env, len, arr.as_mut_ptr()) {\n                Err(sys::Status::PendingException) => return Err(Throw::new()),\n                res => res.unwrap(),\n            }\n\n            arr.assume_init()\n        };\n\n        for (i, item) in iter.enumerate() {\n            let item = item.try_into_js(cx)?.to_local();\n            let Ok(i) = u32::try_from(i) else {\n                return cx.throw_error(\"Exceeded maximum length of an array\");\n            };\n\n            unsafe {\n                match sys::set_element(env, arr, i, item) {\n                    Err(sys::Status::PendingException) => return Err(Throw::new()),\n                    res => res.unwrap(),\n                }\n            }\n        }\n\n        unsafe { Ok(Handle::new_internal(JsArray::from_local(cx.env(), arr))) }\n    }\n}\n\n/// Error when extracting an [`Array<T>`]\n#[derive(Debug)]\npub enum ArrayError<E> {\n    /// Value was not a JavaScript array.\n    Array(TypeExpected<JsArray>),\n    /// An element failed to convert to `T::Item`.\n    Item(E),\n}\n\nimpl<E> ArrayError<E> {\n    fn array() -> Self {\n        Self::Array(TypeExpected::<JsArray>::new())\n    }\n\n    fn item(err: E) -> Self {\n        Self::Item(err)\n    }\n}\n\nimpl<E> fmt::Display for ArrayError<E>\nwhere\n    E: fmt::Display,\n{\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        match self {\n            ArrayError::Array(err) => write!(f, \"{}\", err),\n            ArrayError::Item(err) => write!(f, \"{}\", err),\n        }\n    }\n}\n\nimpl<E> error::Error for ArrayError<E> where E: error::Error {}\n\nimpl<'cx, E> TryIntoJs<'cx> for ArrayError<E>\nwhere\n    E: TryIntoJs<'cx>,\n{\n    type Value = JsValue;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        match self {\n            ArrayError::Array(err) => err.try_into_js(cx).map(|v| v.upcast()),\n            ArrayError::Item(err) => err.try_into_js(cx).map(|v| v.upcast()),\n        }\n    }\n}\n\nimpl<'cx, E> private::Sealed for ArrayError<E> where E: TryIntoJs<'cx> {}\n"
  },
  {
    "path": "crates/neon/src/types_impl/extract/boxed.rs",
    "content": "use crate::{\n    context::{Context, Cx},\n    handle::Handle,\n    result::{JsResult, NeonResult},\n    types::{\n        extract::{private, TryFromJs, TryIntoJs, TypeExpected},\n        Finalize, JsBox, JsValue,\n    },\n};\n\n/// Wrapper to extract `T` from a [`JsBox<T>`](JsBox) or create a [`JsBox`]\n/// from a `T`.\n///\n/// [`Boxed`] is especially useful for exporting async functions and tasks.\n///\n/// ```\n/// # use std::sync::Arc;\n/// # use neon::{prelude::*, types::extract::Boxed};\n/// struct Greeter {\n///     greeting: String,\n/// }\n///\n/// impl Finalize for Greeter {}\n///\n/// impl Greeter {\n///     fn new(greeting: String) -> Self {\n///         Self { greeting }\n///     }\n///\n///     fn greet(&self, name: &str) -> String {\n///         format!(\"{}, {name}!\", self.greeting)\n///     }\n/// }\n///\n/// #[neon::export]\n/// fn create_greeter(greeting: String) -> Boxed<Arc<Greeter>> {\n///     Boxed(Arc::new(Greeter::new(greeting)))\n/// }\n///\n/// #[neon::export(task)]\n/// fn greet(Boxed(greeter): Boxed<Arc<Greeter>>, name: String) -> String {\n///     greeter.greet(&name)\n/// }\n/// ```\npub struct Boxed<T>(pub T);\n\nimpl<'cx, T> TryFromJs<'cx> for Boxed<T>\nwhere\n    T: Clone + 'static,\n{\n    type Error = TypeExpected<JsBox<T>>;\n\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        match v.downcast::<JsBox<T>, _>(cx) {\n            Ok(v) => Ok(Ok(Self(T::clone(&v)))),\n            Err(_) => Ok(Err(TypeExpected::new())),\n        }\n    }\n}\n\nimpl<'cx, T> TryIntoJs<'cx> for Boxed<T>\nwhere\n    T: Finalize + 'static,\n{\n    type Value = JsBox<T>;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        Ok(cx.boxed(self.0))\n    }\n}\n\nimpl<T> private::Sealed for Boxed<T> {}\n"
  },
  {
    "path": "crates/neon/src/types_impl/extract/buffer.rs",
    "content": "use crate::{\n    context::Cx,\n    handle::Handle,\n    result::{JsResult, NeonResult},\n    types::{\n        buffer::{Binary, TypedArray},\n        extract::{private, TryFromJs, TryIntoJs, TypeExpected},\n        JsArrayBuffer, JsBigInt64Array, JsBigUint64Array, JsBuffer, JsFloat32Array, JsFloat64Array,\n        JsInt16Array, JsInt32Array, JsInt8Array, JsTypedArray, JsUint16Array, JsUint32Array,\n        JsUint8Array, JsValue, Value,\n    },\n};\n\n/// Wrapper for converting between bytes and [`JsArrayBuffer`](JsArrayBuffer)\npub struct ArrayBuffer<B>(pub B);\n\nimpl<'cx, B> TryFromJs<'cx> for ArrayBuffer<B>\nwhere\n    for<'b> B: From<&'b [u8]>,\n{\n    type Error = TypeExpected<JsBuffer>;\n\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        let v = match v.downcast::<JsArrayBuffer, _>(cx) {\n            Ok(v) => v,\n            Err(_) => return Ok(Err(Self::Error::new())),\n        };\n\n        Ok(Ok(ArrayBuffer(B::from(v.as_slice(cx)))))\n    }\n}\n\nimpl<'cx, B> TryIntoJs<'cx> for ArrayBuffer<B>\nwhere\n    B: AsRef<[u8]>,\n{\n    type Value = JsArrayBuffer;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        JsArrayBuffer::from_slice(cx, self.0.as_ref())\n    }\n}\n\nimpl<B> private::Sealed for ArrayBuffer<B> {}\n\n/// Wrapper for converting between bytes and [`JsBuffer`](JsBuffer)\npub struct Buffer<B>(pub B);\n\nimpl<'cx, B> TryFromJs<'cx> for Buffer<B>\nwhere\n    for<'b> B: From<&'b [u8]>,\n{\n    type Error = TypeExpected<JsBuffer>;\n\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        let v = match v.downcast::<JsBuffer, _>(cx) {\n            Ok(v) => v,\n            Err(_) => return Ok(Err(Self::Error::new())),\n        };\n\n        Ok(Ok(Buffer(B::from(v.as_slice(cx)))))\n    }\n}\n\nimpl<'cx, B> TryIntoJs<'cx> for Buffer<B>\nwhere\n    B: AsRef<[u8]>,\n{\n    type Value = JsBuffer;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        JsBuffer::from_slice(cx, self.0.as_ref())\n    }\n}\n\nimpl<B> private::Sealed for Buffer<B> {}\n\nimpl<'cx, T> TryIntoJs<'cx> for Vec<T>\nwhere\n    JsTypedArray<T>: Value,\n    T: Binary,\n{\n    type Value = JsTypedArray<T>;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        JsTypedArray::from_slice(cx, self.as_slice())\n    }\n}\n\nimpl<'cx, T> TryFromJs<'cx> for Vec<T>\nwhere\n    JsTypedArray<T>: Value,\n    T: Binary,\n{\n    type Error = TypeExpected<JsTypedArray<T>>;\n\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        let v = match v.downcast::<JsTypedArray<T>, _>(cx) {\n            Ok(v) => v,\n            Err(_) => return Ok(Err(Self::Error::new())),\n        };\n\n        Ok(Ok(v.as_slice(cx).to_vec()))\n    }\n}\n\nimpl<T> private::Sealed for Vec<T>\nwhere\n    JsTypedArray<T>: Value,\n    T: Binary,\n{\n}\n\nimpl<'cx, T, const N: usize> TryIntoJs<'cx> for [T; N]\nwhere\n    JsTypedArray<T>: Value,\n    T: Binary,\n{\n    type Value = JsTypedArray<T>;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        JsTypedArray::from_slice(cx, self.as_slice())\n    }\n}\n\nimpl<T, const N: usize> private::Sealed for [T; N]\nwhere\n    JsTypedArray<T>: Value,\n    T: Binary,\n{\n}\n\nimpl<'cx, T> TryIntoJs<'cx> for &[T]\nwhere\n    JsTypedArray<T>: Value,\n    T: Binary,\n{\n    type Value = JsTypedArray<T>;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        JsTypedArray::from_slice(cx, self)\n    }\n}\n\nimpl<T> private::Sealed for &[T]\nwhere\n    JsTypedArray<T>: Value,\n    T: Binary,\n{\n}\n\nmacro_rules! typed_array {\n    ($js:ident, $name:ident, $type:ty) => {\n        #[doc = concat!(\n            \"Wrapper for converting between a Rust `[\",\n            stringify!($type),\n            \"]` array type and a [`\",\n            stringify!($js),\n            \"`]\",\n        )]\n        pub struct $name<T>(pub T);\n\n        impl<'cx, T> TryIntoJs<'cx> for $name<T>\n        where\n            T: AsRef<[$type]>,\n        {\n            type Value = $js;\n\n            fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n                $js::from_slice(cx, self.0.as_ref())\n            }\n        }\n\n        impl<'cx, T> TryFromJs<'cx> for $name<T>\n        where\n            for<'a> T: From<&'a [$type]>,\n        {\n            type Error = TypeExpected<$js>;\n\n            fn try_from_js(\n                cx: &mut Cx<'cx>,\n                v: Handle<'cx, JsValue>,\n            ) -> NeonResult<Result<Self, Self::Error>> {\n                let v = match v.downcast::<$js, _>(cx) {\n                    Ok(v) => v,\n                    Err(_) => return Ok(Err(TypeExpected::new())),\n                };\n\n                Ok(Ok(Self(T::from(v.as_slice(cx)))))\n            }\n        }\n\n        impl<T> private::Sealed for $name<T> {}\n    };\n\n    ($(($js:ident, $name:ident, $type:ty),)*) => {\n        $(typed_array!($js, $name, $type);)*\n    };\n}\n\ntyped_array![\n    (JsInt8Array, Int8Array, i8),\n    (JsUint8Array, Uint8Array, u8),\n    (JsInt16Array, Int16Array, i16),\n    (JsUint16Array, Uint16Array, u16),\n    (JsInt32Array, Int32Array, i32),\n    (JsUint32Array, Uint32Array, u32),\n    (JsFloat32Array, Float32Array, f32),\n    (JsFloat64Array, Float64Array, f64),\n    (JsBigInt64Array, BigInt64Array, i64),\n    (JsBigUint64Array, BigUint64Array, u64),\n];\n"
  },
  {
    "path": "crates/neon/src/types_impl/extract/container.rs",
    "content": "use std::{\n    cell::{Ref, RefCell, RefMut},\n    rc::Rc,\n    sync::{Arc, LazyLock},\n};\n\nuse crate::{\n    context::{Context, Cx},\n    handle::Handle,\n    result::{JsResult, NeonResult},\n    types::{\n        extract::{TryFromJs, TryIntoJs},\n        JsBox, JsValue, Value,\n    },\n};\n\nuse super::error::TypeExpected;\n\nimpl<'cx, T: 'static> TryFromJs<'cx> for &'cx RefCell<T> {\n    type Error = TypeExpected<JsBox<RefCell<T>>>;\n\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        match v.downcast::<JsBox<RefCell<T>>, _>(cx) {\n            Ok(v) => Ok(Ok(JsBox::deref(&v))),\n            Err(_) => Ok(Err(TypeExpected::new())),\n        }\n    }\n}\n\nimpl<'cx, T: 'static> TryFromJs<'cx> for Ref<'cx, T> {\n    type Error = TypeExpected<JsBox<RefCell<T>>>;\n\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        match v.downcast::<JsBox<RefCell<T>>, _>(cx) {\n            Ok(v) => match JsBox::deref(&v).try_borrow() {\n                Ok(r) => Ok(Ok(r)),\n                Err(_) => cx.throw_error(\"RefCell is already mutably borrowed\"),\n            },\n            Err(_) => Ok(Err(TypeExpected::new())),\n        }\n    }\n}\n\nimpl<'cx, T: 'static> TryFromJs<'cx> for RefMut<'cx, T> {\n    type Error = TypeExpected<JsBox<RefCell<T>>>;\n\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        match v.downcast::<JsBox<RefCell<T>>, _>(cx) {\n            Ok(v) => match JsBox::deref(&v).try_borrow_mut() {\n                Ok(r) => Ok(Ok(r)),\n                Err(_) => cx.throw_error(\"RefCell is already borrowed\"),\n            },\n            Err(_) => Ok(Err(TypeExpected::new())),\n        }\n    }\n}\n\nimpl<'cx, T> TryIntoJs<'cx> for RefCell<T>\nwhere\n    T: 'static,\n{\n    type Value = JsBox<RefCell<T>>;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        Ok(JsBox::manually_finalize(cx, self))\n    }\n}\n\nimpl<'cx, T: 'static> TryFromJs<'cx> for Rc<T> {\n    type Error = TypeExpected<JsBox<Rc<T>>>;\n\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        match v.downcast::<JsBox<Rc<T>>, _>(cx) {\n            Ok(v) => Ok(Ok(Rc::clone(&v))),\n            Err(_) => Ok(Err(TypeExpected::new())),\n        }\n    }\n}\n\nimpl<'cx, T> TryIntoJs<'cx> for Rc<T>\nwhere\n    T: 'static,\n{\n    type Value = JsBox<Rc<T>>;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        Ok(JsBox::manually_finalize(cx, self))\n    }\n}\n\nimpl<'cx, T: 'static> TryFromJs<'cx> for Arc<T> {\n    type Error = TypeExpected<JsBox<Arc<T>>>;\n\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        match v.downcast::<JsBox<Arc<T>>, _>(cx) {\n            Ok(v) => Ok(Ok(Arc::clone(&v))),\n            Err(_) => Ok(Err(TypeExpected::new())),\n        }\n    }\n}\n\nimpl<'cx, T> TryIntoJs<'cx> for Arc<T>\nwhere\n    T: 'static,\n{\n    type Value = JsBox<Arc<T>>;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        Ok(JsBox::manually_finalize(cx, self))\n    }\n}\n\nimpl<'cx, T, V> TryIntoJs<'cx> for &LazyLock<T>\nwhere\n    T: 'static,\n    V: Value,\n    for<'a> &'a T: TryIntoJs<'cx, Value = V>,\n{\n    type Value = V;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        LazyLock::force(self).try_into_js(cx)\n    }\n}\n\nimpl<T> super::private::Sealed for &LazyLock<T> {}\n"
  },
  {
    "path": "crates/neon/src/types_impl/extract/either.rs",
    "content": "use std::{any, error, fmt};\n\nuse either::Either;\n\nuse crate::{\n    context::Cx,\n    handle::Handle,\n    object::Object,\n    result::{JsResult, NeonResult},\n    types::{\n        extract::{private, TryFromJs, TryIntoJs},\n        JsError, JsValue,\n    },\n};\n\nimpl<'cx, L, R> TryFromJs<'cx> for Either<L, R>\nwhere\n    L: TryFromJs<'cx>,\n    R: TryFromJs<'cx>,\n{\n    type Error = Error<L::Error, R::Error>;\n\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        let left = match L::try_from_js(cx, v)? {\n            Ok(l) => return Ok(Ok(Either::Left(l))),\n            Err(l) => l,\n        };\n\n        let right = match R::try_from_js(cx, v)? {\n            Ok(r) => return Ok(Ok(Either::Right(r))),\n            Err(r) => r,\n        };\n\n        Ok(Err(Error::new::<L, R>(left, right)))\n    }\n}\n\nimpl<'cx, L, R> TryIntoJs<'cx> for Either<L, R>\nwhere\n    L: TryIntoJs<'cx>,\n    R: TryIntoJs<'cx>,\n{\n    type Value = JsValue;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        match self {\n            Either::Left(v) => v.try_into_js(cx).map(|v| v.upcast()),\n            Either::Right(v) => v.try_into_js(cx).map(|v| v.upcast()),\n        }\n    }\n}\n\nimpl<L, R> private::Sealed for Either<L, R> {}\n\n#[derive(Debug)]\npub struct Error<L, R> {\n    left: (&'static str, L),\n    right: (&'static str, R),\n}\n\nimpl<'cx, L, R> Error<L, R> {\n    fn new<LT, RT>(left: L, right: R) -> Self\n    where\n        LT: TryFromJs<'cx, Error = L>,\n        RT: TryFromJs<'cx, Error = R>,\n    {\n        Self {\n            left: (any::type_name::<LT>(), left),\n            right: (any::type_name::<RT>(), right),\n        }\n    }\n}\n\nimpl<L, R> fmt::Display for Error<L, R>\nwhere\n    L: fmt::Display,\n    R: fmt::Display,\n{\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        writeln!(f, \"Either::Left: {}\", self.left.1)?;\n        write!(f, \"Either::Right: {}\", self.right.1)\n    }\n}\n\nimpl<L, R> error::Error for Error<L, R>\nwhere\n    L: error::Error,\n    R: error::Error,\n{\n}\n\nimpl<'cx, L, R> TryIntoJs<'cx> for Error<L, R>\nwhere\n    L: TryIntoJs<'cx>,\n    R: TryIntoJs<'cx>,\n{\n    type Value = JsError;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        let err = JsError::type_error(\n            cx,\n            format!(\"expected either {} or {}\", self.left.0, self.right.0,),\n        )?;\n\n        err.prop(cx, \"left\").set(self.left.1)?;\n        err.prop(cx, \"right\").set(self.right.1)?;\n\n        Ok(err)\n    }\n}\n\nimpl<L, R> private::Sealed for Error<L, R> {}\n"
  },
  {
    "path": "crates/neon/src/types_impl/extract/error.rs",
    "content": "use std::{convert::Infallible, error, fmt, marker::PhantomData};\n\nuse crate::{\n    context::{Context, Cx},\n    result::JsResult,\n    types::{\n        extract::{private, TryIntoJs},\n        JsError, JsValue, Value,\n    },\n};\n\ntype BoxError = Box<dyn error::Error + Send + Sync + 'static>;\n\n/// Error returned when a JavaScript value is not the type expected.\npub struct TypeExpected<T: Value>(PhantomData<T>);\n\nimpl<T: Value> TypeExpected<T> {\n    pub(super) fn new() -> Self {\n        Self(PhantomData)\n    }\n}\n\nimpl<T: Value> fmt::Display for TypeExpected<T> {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(f, \"expected {}\", T::name())\n    }\n}\n\nimpl<T: Value> fmt::Debug for TypeExpected<T> {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        f.debug_tuple(\"TypeExpected\").field(&T::name()).finish()\n    }\n}\n\nimpl<T: Value> error::Error for TypeExpected<T> {}\n\nimpl<'cx, T: Value> TryIntoJs<'cx> for TypeExpected<T> {\n    type Value = JsError;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        JsError::type_error(cx, self.to_string())\n    }\n}\n\nimpl<T: Value> private::Sealed for TypeExpected<T> {}\n\nimpl<'cx> TryIntoJs<'cx> for Infallible {\n    type Value = JsValue;\n\n    fn try_into_js(self, _: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        unreachable!()\n    }\n}\n\nimpl private::Sealed for Infallible {}\n\n#[derive(Debug)]\n/// Error that implements [`TryIntoJs`] and can produce specific error types.\n///\n/// [`Error`] implements [`From`] for most error types, allowing ergonomic error handling in\n/// exported functions with the `?` operator.\n///\n/// ### Example\n///\n/// ```\n/// use neon::types::extract::Error;\n///\n/// #[neon::export]\n/// fn read_file(path: String) -> Result<String, Error> {\n///     let contents = std::fs::read_to_string(path)?;\n///     Ok(contents)\n/// }\n/// ```\npub struct Error {\n    cause: BoxError,\n    kind: Option<ErrorKind>,\n}\n\n#[derive(Debug)]\nenum ErrorKind {\n    Error,\n    RangeError,\n    TypeError,\n}\n\nimpl Error {\n    /// Create a new [`Error`] from a `cause`\n    pub fn new<E>(cause: E) -> Self\n    where\n        E: Into<BoxError>,\n    {\n        Self::create(ErrorKind::Error, cause)\n    }\n\n    /// Create a `RangeError`\n    pub fn range_error<E>(cause: E) -> Self\n    where\n        E: Into<BoxError>,\n    {\n        Self::create(ErrorKind::RangeError, cause)\n    }\n\n    /// Create a `TypeError`\n    pub fn type_error<E>(cause: E) -> Self\n    where\n        E: Into<BoxError>,\n    {\n        Self::create(ErrorKind::TypeError, cause)\n    }\n\n    /// Check if error is a `RangeError`\n    pub fn is_range_error(&self) -> bool {\n        matches!(self.kind, Some(ErrorKind::RangeError))\n    }\n\n    /// Check if error is a `TypeError`\n    pub fn is_type_error(&self) -> bool {\n        matches!(self.kind, Some(ErrorKind::TypeError))\n    }\n\n    /// Get a reference to the underlying `cause`\n    pub fn cause(&self) -> &BoxError {\n        &self.cause\n    }\n\n    /// Extract the `std::error::Error` cause\n    pub fn into_cause(self) -> BoxError {\n        self.cause\n    }\n\n    fn create<E>(kind: ErrorKind, cause: E) -> Self\n    where\n        E: Into<BoxError>,\n    {\n        Self {\n            cause: cause.into(),\n            kind: Some(kind),\n        }\n    }\n}\n\n// Blanket impl allow for ergonomic `?` error handling from typical error types (including `anyhow`)\nimpl<E> From<E> for Error\nwhere\n    E: Into<BoxError>,\n{\n    fn from(cause: E) -> Self {\n        Self::new(cause)\n    }\n}\n\nimpl fmt::Display for Error {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(f, \"{:?}: {}\", self.kind, self.cause)\n    }\n}\n\n// N.B.: `TryFromJs` is not included. If Neon were to add support for additional error types,\n// this would be a *breaking* change. We will wait for user demand before providing this feature.\nimpl<'cx> TryIntoJs<'cx> for Error {\n    type Value = JsError;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        let message = self.cause.to_string();\n\n        match self.kind {\n            Some(ErrorKind::RangeError) => cx.range_error(message),\n            Some(ErrorKind::TypeError) => cx.type_error(message),\n            _ => cx.error(message),\n        }\n    }\n}\n"
  },
  {
    "path": "crates/neon/src/types_impl/extract/json.rs",
    "content": "//! Extract JavaScript values with JSON serialization\n//!\n//! For complex objects that implement [`serde::Serialize`] and [`serde::Deserialize`],\n//! it is more ergonomic--and often faster--to extract with JSON serialization. The [`Json`]\n//! extractor automatically calls `JSON.stringify` and `JSON.parse` as necessary.\n//!\n//! ```\n//! use neon::types::extract::Json;\n//!\n//! #[neon::export]\n//! fn sort(Json(mut strings): Json<Vec<String>>) -> Json<Vec<String>> {\n//!     strings.sort();\n//!     Json(strings)\n//! }\n//! ```\n\nuse std::{error, fmt};\n\nuse crate::{\n    context::{Context, Cx},\n    handle::Handle,\n    object::Object,\n    result::{JsResult, NeonResult},\n    types::{\n        extract::{private, TryFromJs, TryIntoJs},\n        JsError, JsFunction, JsObject, JsValue,\n    },\n};\n\n#[cfg(feature = \"napi-6\")]\nuse crate::{handle::Root, thread::LocalKey};\n\nfn global_json_stringify<'cx>(cx: &mut Cx<'cx>) -> JsResult<'cx, JsFunction> {\n    cx.global::<JsObject>(\"JSON\")?.get(cx, \"stringify\")\n}\n\n#[cfg(not(feature = \"napi-6\"))]\n// N.B.: This is not semantically identical to Node-API >= 6. Patching the global\n// method could cause differences between calls. However, threading a `Root` through\n// would require a significant refactor and \"don't do this or things will break\" is\n// fairly common in JS.\nfn json_stringify<'cx>(cx: &mut Cx<'cx>) -> JsResult<'cx, JsFunction> {\n    global_json_stringify(cx)\n}\n\n#[cfg(feature = \"napi-6\")]\nfn json_stringify<'cx>(cx: &mut Cx<'cx>) -> JsResult<'cx, JsFunction> {\n    static STRINGIFY: LocalKey<Root<JsFunction>> = LocalKey::new();\n\n    STRINGIFY\n        .get_or_try_init(cx, |cx| global_json_stringify(cx).map(|f| f.root(cx)))\n        .map(|f| f.to_inner(cx))\n}\n\nfn global_json_parse<'cx>(cx: &mut Cx<'cx>) -> JsResult<'cx, JsFunction> {\n    cx.global::<JsObject>(\"JSON\")?.get(cx, \"parse\")\n}\n\n#[cfg(not(feature = \"napi-6\"))]\nfn json_parse<'cx>(cx: &mut Cx<'cx>) -> JsResult<'cx, JsFunction> {\n    global_json_parse(cx)\n}\n\n#[cfg(feature = \"napi-6\")]\nfn json_parse<'cx>(cx: &mut Cx<'cx>) -> JsResult<'cx, JsFunction> {\n    static PARSE: LocalKey<Root<JsFunction>> = LocalKey::new();\n\n    PARSE\n        .get_or_try_init(cx, |cx| global_json_parse(cx).map(|f| f.root(cx)))\n        .map(|f| f.to_inner(cx))\n}\n\nfn parse<'cx>(cx: &mut Cx<'cx>, s: &str) -> JsResult<'cx, JsValue> {\n    let s = cx.string(s).upcast();\n\n    json_parse(cx)?.call(cx, s, [s])\n}\n\n/// Wrapper for converting between `T` and [`JsValue`](crate::types::JsValue) by\n/// serializing with JSON.\npub struct Json<T>(pub T);\n\nimpl<'cx, T> TryFromJs<'cx> for Json<T>\nwhere\n    for<'de> T: serde::de::Deserialize<'de>,\n{\n    type Error = Error;\n\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        let s = json_stringify(cx)?.call(cx, v, [v])?;\n        let res = match String::try_from_js(cx, s)? {\n            Ok(s) => serde_json::from_str(&s),\n            // If the type was not a `string`, it must be `undefined`\n            Err(_) => T::deserialize(serde::de::value::UnitDeserializer::new()),\n        };\n\n        Ok(res.map(Json).map_err(Error))\n    }\n}\n\nimpl<'cx, T> TryIntoJs<'cx> for Json<T>\nwhere\n    T: serde::Serialize,\n{\n    type Value = JsValue;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        TryIntoJs::try_into_js(&self, cx)\n    }\n}\n\nimpl<'cx, T> TryIntoJs<'cx> for &Json<T>\nwhere\n    T: serde::Serialize,\n{\n    type Value = JsValue;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        let s = serde_json::to_string(&self.0).or_else(|err| cx.throw_error(err.to_string()))?;\n\n        parse(cx, &s)\n    }\n}\n\nimpl<T> private::Sealed for Json<T> {}\n\nimpl<T> private::Sealed for &Json<T> {}\n\n/// Error returned when a value is invalid JSON\npub struct Error(serde_json::Error);\n\nimpl fmt::Display for Error {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        fmt::Display::fmt(&self.0, f)\n    }\n}\n\nimpl fmt::Debug for Error {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        fmt::Debug::fmt(&self.0, f)\n    }\n}\n\nimpl error::Error for Error {}\n\nimpl<'cx> TryIntoJs<'cx> for Error {\n    type Value = JsError;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        JsError::error(cx, self.to_string())\n    }\n}\n\nimpl private::Sealed for Error {}\n"
  },
  {
    "path": "crates/neon/src/types_impl/extract/mod.rs",
    "content": "//! Traits and utilities for extract Rust data from JavaScript values.\n//!\n//! The full list of included extractors can be found on [`TryFromJs`].\n//!\n//! ## Extracting Handles\n//!\n//! JavaScript arguments may be extracted into a Rust tuple.\n//!\n//! ```\n//! # use neon::{prelude::*, types::extract::*};\n//! fn greet(mut cx: FunctionContext) -> JsResult<JsString> {\n//!     let (greeting, name): (Handle<JsString>, Handle<JsString>) = cx.args()?;\n//!     let message = format!(\"{}, {}!\", greeting.value(&mut cx), name.value(&mut cx));\n//!\n//!     Ok(cx.string(message))\n//! }\n//! ```\n//!\n//! ## Extracting Native Types\n//!\n//! It's also possible to extract directly into native Rust types instead of a [`Handle`].\n//!\n//! ```\n//! # use neon::{prelude::*, types::extract::*};\n//! fn add(mut cx: FunctionContext) -> JsResult<JsNumber> {\n//!     let (a, b): (f64, f64) = cx.args()?;\n//!\n//!     Ok(cx.number(a + b))\n//! }\n//! ```\n//!\n//! ## Extracting [`Option`]\n//!\n//! It's also possible to mix [`Handle`], Rust types, and even [`Option`] for\n//! handling `null` and `undefined`.\n//!\n//! ```\n//! # use neon::{prelude::*, types::extract::*};\n//! fn get_or_default(mut cx: FunctionContext) -> JsResult<JsValue> {\n//!     let (n, default_value): (Option<f64>, Handle<JsValue>) = cx.args()?;\n//!\n//!     if let Some(n) = n {\n//!         return Ok(cx.number(n).upcast());\n//!     }\n//!\n//!     Ok(default_value)\n//! }\n//! ```\n//!\n//! ## Additional Extractors\n//!\n//! In some cases, the expected JavaScript type is ambiguous. For example, when\n//! trying to extract an [`f64`], the argument may be a `Date` instead of a `number`.\n//! Newtype extractors are provided to help.\n//!\n//! ```\n//! # use neon::{prelude::*, types::extract::*};\n//! # #[cfg(feature = \"napi-5\")]\n//! # use neon::types::JsDate;\n//!\n//! # #[cfg(feature = \"napi-5\")]\n//! fn add_hours(mut cx: FunctionContext) -> JsResult<JsDate> {\n//!     const MS_PER_HOUR: f64 = 60.0 * 60.0 * 1000.0;\n//!\n//!     let (Date(date), hours): (Date, f64) = cx.args()?;\n//!     let date = date + hours * MS_PER_HOUR;\n//!\n//!     cx.date(date).or_throw(&mut cx)\n//! }\n//! ```\n//!\n//! ## Overloaded Functions\n//!\n//! It's common in JavaScript to overload function signatures. This can be implemented with\n//! [`FunctionContext::args_opt`] or [`Context::try_catch`].\n//!\n//! ```\n//! # use neon::{prelude::*, types::extract::*};\n//!\n//! fn add(mut cx: FunctionContext, a: f64, b: f64) -> Handle<JsNumber> {\n//!     cx.number(a + b)\n//! }\n//!\n//! fn concat(mut cx: FunctionContext, a: String, b: String) -> Handle<JsString> {\n//!     cx.string(a + &b)\n//! }\n//!\n//! fn combine(mut cx: FunctionContext) -> JsResult<JsValue> {\n//!     if let Some((a, b)) = cx.args_opt()? {\n//!         return Ok(add(cx, a, b).upcast());\n//!     }\n//!\n//!     let (a, b) = cx.args()?;\n//!\n//!     Ok(concat(cx, a, b).upcast())\n//! }\n//! ```\n//!\n//! Note well, in this example, type annotations are not required on the tuple because\n//! Rust is able to infer it from the type arguments on `add` and `concat`.\n\nuse crate::{\n    context::{Context, Cx, FunctionContext},\n    handle::Handle,\n    result::{JsResult, NeonResult},\n    types::{JsValue, Value},\n};\n\npub use self::{\n    array::{Array, ArrayError},\n    boxed::Boxed,\n    buffer::{\n        ArrayBuffer, BigInt64Array, BigUint64Array, Buffer, Float32Array, Float64Array, Int16Array,\n        Int32Array, Int8Array, Uint16Array, Uint32Array, Uint8Array,\n    },\n    error::{Error, TypeExpected},\n    with::with,\n};\n\n#[cfg(feature = \"serde\")]\n#[cfg_attr(docsrs, doc(cfg(feature = \"serde\")))]\npub use self::json::Json;\n\n#[cfg(feature = \"serde\")]\n#[cfg_attr(docsrs, doc(cfg(feature = \"serde\")))]\npub mod json;\n\nmod array;\nmod boxed;\nmod buffer;\nmod container;\nmod either;\nmod error;\npub(crate) mod private;\nmod try_from_js;\nmod try_into_js;\nmod with;\n\n/// Extract Rust data from a JavaScript value\npub trait TryFromJs<'cx>\nwhere\n    Self: private::Sealed + Sized,\n{\n    type Error: TryIntoJs<'cx>;\n\n    /// Extract this Rust type from a JavaScript value\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>>;\n\n    /// Same as [`TryFromJs`], but all errors are converted to JavaScript exceptions\n    fn from_js(cx: &mut Cx<'cx>, v: Handle<'cx, JsValue>) -> NeonResult<Self> {\n        match Self::try_from_js(cx, v)? {\n            Ok(v) => Ok(v),\n            Err(err) => {\n                let err = err.try_into_js(cx)?;\n\n                cx.throw(err)\n            }\n        }\n    }\n}\n\n/// Convert Rust data into a JavaScript value\npub trait TryIntoJs<'cx>\nwhere\n    Self: private::Sealed,\n{\n    /// The type of JavaScript value that will be created\n    type Value: Value;\n\n    /// Convert `self` into a JavaScript value\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value>;\n}\n\n/// Extract a borrowed reference to Rust data from a JavaScript value\n///\n/// This trait is similar to [`TryFromJs`], but instead of extracting an owned value,\n/// it returns a guard that dereferences to a borrowed reference. This is useful for\n/// efficiently passing class instances by reference in method calls.\n///\n/// # Example\n///\n/// ```ignore\n/// // In a class method, accept another instance by reference\n/// pub fn distance(&self, other: &Point) -> f64 {\n///     // other is borrowed, not cloned\n/// }\n/// ```\n///\n/// The macro will automatically use `TryFromJsRef` when it sees `&T` parameters.\npub trait TryFromJsRef<'cx>\nwhere\n    Self: private::Sealed + Sized,\n{\n    /// A guard type that dereferences to `&Self` and keeps the borrow alive\n    type Guard: std::ops::Deref<Target = Self>;\n\n    /// The error type returned when extraction fails\n    type Error: TryIntoJs<'cx>;\n\n    /// Extract a borrowed reference from a JavaScript value\n    fn try_from_js_ref(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self::Guard, Self::Error>>;\n\n    /// Same as [`TryFromJsRef::try_from_js_ref`], but all errors are converted to JavaScript exceptions\n    fn from_js_ref(cx: &mut Cx<'cx>, v: Handle<'cx, JsValue>) -> NeonResult<Self::Guard> {\n        match Self::try_from_js_ref(cx, v)? {\n            Ok(guard) => Ok(guard),\n            Err(err) => {\n                let err = err.try_into_js(cx)?;\n                cx.throw(err)\n            }\n        }\n    }\n}\n\n/// Extract a mutable borrowed reference to Rust data from a JavaScript value\n///\n/// This trait is similar to [`TryFromJsRef`], but returns a guard that allows\n/// mutable access. This is useful for passing class instances by mutable reference\n/// in method calls.\n///\n/// # Example\n///\n/// ```ignore\n/// // In a class method, accept another instance by mutable reference\n/// pub fn swap_coordinates(&mut self, other: &mut Point) {\n///     std::mem::swap(&mut self.x, &mut other.x);\n///     std::mem::swap(&mut self.y, &mut other.y);\n/// }\n/// ```\n///\n/// The macro will automatically use `TryFromJsRefMut` when it sees `&mut T` parameters.\npub trait TryFromJsRefMut<'cx>\nwhere\n    Self: private::Sealed + Sized,\n{\n    /// A guard type that dereferences to `&mut Self` and keeps the mutable borrow alive\n    type Guard: std::ops::DerefMut<Target = Self>;\n\n    /// The error type returned when extraction fails\n    type Error: TryIntoJs<'cx>;\n\n    /// Extract a mutable borrowed reference from a JavaScript value\n    fn try_from_js_ref_mut(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self::Guard, Self::Error>>;\n\n    /// Same as [`TryFromJsRefMut::try_from_js_ref_mut`], but all errors are converted to JavaScript exceptions\n    fn from_js_ref_mut(cx: &mut Cx<'cx>, v: Handle<'cx, JsValue>) -> NeonResult<Self::Guard> {\n        match Self::try_from_js_ref_mut(cx, v)? {\n            Ok(guard) => Ok(guard),\n            Err(err) => {\n                let err = err.try_into_js(cx)?;\n                cx.throw(err)\n            }\n        }\n    }\n}\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-5\")))]\n#[cfg(feature = \"napi-5\")]\n/// Wrapper for converting between [`f64`] and [`JsDate`](super::JsDate)\npub struct Date(pub f64);\n\n/// Trait specifying values that may be extracted from function arguments.\n///\n/// **Note:** This trait is implemented for tuples of up to 32 values, but for\n/// the sake of brevity, only tuples up to size 8 are shown in this documentation.\npub trait FromArgs<'cx>: private::FromArgsInternal<'cx> {}\n\n// Functions as a noop zero-argument base case of [`from_args_impl`]\nimpl<'cx> private::FromArgsInternal<'cx> for () {\n    fn from_args(_cx: &mut FunctionContext<'cx>) -> NeonResult<Self> {\n        Ok(())\n    }\n\n    fn from_args_opt(_cx: &mut FunctionContext<'cx>) -> NeonResult<Option<Self>> {\n        Ok(Some(()))\n    }\n}\n\n// Functions as a zero-argument base case of [`from_args_impl`]\nimpl<'cx> FromArgs<'cx> for () {}\n\n// N.B.: `FromArgs` _could_ have a blanket impl for `T` where `T: FromArgsInternal`.\n// However, it is explicitly implemented in the macro in order for it to be included in docs.\nmacro_rules! from_args_impl {\n    ($(#[$attrs:meta])? [$($ty:ident),*]) => {\n        $(#[$attrs])?\n        impl<'cx, $($ty,)*> FromArgs<'cx> for ($($ty,)*)\n        where\n            $($ty: TryFromJs<'cx>,)*\n        {}\n\n        #[allow(non_snake_case)]\n        impl<'cx, $($ty,)*> private::FromArgsInternal<'cx> for ($($ty,)*)\n        where\n            $($ty: TryFromJs<'cx>,)*\n        {\n            fn from_args(cx: &mut FunctionContext<'cx>) -> NeonResult<Self> {\n                let [$($ty,)*] = cx.argv();\n\n                Ok(($($ty::from_js(cx, $ty)?,)*))\n            }\n\n            fn from_args_opt(cx: &mut FunctionContext<'cx>) -> NeonResult<Option<Self>> {\n                let [$($ty,)*] = cx.argv();\n\n                Ok(Some((\n                    $(match $ty::try_from_js(cx, $ty)? {\n                        Ok(v) => v,\n                        Err(_) => return Ok(None),\n                    },)*\n                )))\n            }\n        }\n    }\n}\n\nmacro_rules! from_args_expand {\n    ($(#[$attrs:meta])? [$($head:ident),*], []) => {};\n\n    ($(#[$attrs:meta])? [$($head:ident),*], [$cur:ident $(, $tail:ident)*]) => {\n        from_args_impl!($(#[$attrs])? [$($head,)* $cur]);\n        from_args_expand!($(#[$attrs])? [$($head,)* $cur], [$($tail),*]);\n    };\n}\n\nmacro_rules! from_args {\n    ([$($show:ident),*], [$($hide:ident),*]) => {\n        from_args_expand!([], [$($show),*]);\n        from_args_expand!(#[doc(hidden)] [$($show),*], [$($hide),*]);\n    };\n}\n\n// Implement `FromArgs` for tuples up to length `32`. The first list is included\n// in docs and the second list is `#[doc(hidden)]`.\nfrom_args!(\n    [T1, T2, T3, T4, T5, T6, T7, T8],\n    [\n        T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,\n        T27, T28, T29, T30, T31, T32\n    ]\n);\n"
  },
  {
    "path": "crates/neon/src/types_impl/extract/private.rs",
    "content": "use std::{\n    cell::{Ref, RefCell, RefMut},\n    rc::Rc,\n    sync::Arc,\n};\n\nuse crate::{\n    context::FunctionContext,\n    handle::{Handle, Root},\n    object::Object,\n    result::{NeonResult, Throw},\n    types::{\n        extract::{Error, TryIntoJs},\n        Value,\n    },\n};\n\npub trait Sealed {}\n\npub trait FromArgsInternal<'cx>: Sized {\n    fn from_args(cx: &mut FunctionContext<'cx>) -> NeonResult<Self>;\n\n    fn from_args_opt(cx: &mut FunctionContext<'cx>) -> NeonResult<Option<Self>>;\n}\n\nmacro_rules! impl_sealed {\n    ($ty:ident) => {\n        impl Sealed for $ty {}\n    };\n\n    ($($ty:ident),* $(,)*) => {\n        $(\n            impl_sealed!($ty);\n        )*\n    }\n}\n\nimpl Sealed for () {}\n\nimpl Sealed for &str {}\n\nimpl Sealed for &String {}\n\nimpl<'cx, V: Value> Sealed for Handle<'cx, V> {}\n\nimpl<O: Object> Sealed for Root<O> {}\n\nimpl<T> Sealed for Option<T> {}\n\nimpl<T, E> Sealed for Result<T, E> {}\n\nimpl<'cx, T> Sealed for Box<T> where T: TryIntoJs<'cx> {}\n\nimpl<T> Sealed for RefCell<T> {}\n\nimpl<T> Sealed for &RefCell<T> {}\n\nimpl<T> Sealed for Arc<T> {}\n\nimpl<T> Sealed for Rc<T> {}\n\nimpl<T> Sealed for Ref<'_, T> {}\n\nimpl<T> Sealed for RefMut<'_, T> {}\n\n#[cfg(feature = \"napi-5\")]\nimpl Sealed for super::Date {}\n\nimpl_sealed!(u8, u16, u32, i8, i16, i32, f32, f64, bool, String, Throw, Error,);\n"
  },
  {
    "path": "crates/neon/src/types_impl/extract/try_from_js.rs",
    "content": "// Implementations in this file are equivalent to a call to `.downcast()` and\n// `.value(&mut cx)`. These specialized versions provide a performance benefit\n// because they can combine two Node-API calls into a single call that both\n// gets the value and checks the type at the same time.\n\nuse std::{convert::Infallible, ptr};\n\nuse crate::{\n    context::{internal::ContextInternal, Cx},\n    handle::{Handle, Root},\n    object::Object,\n    result::{NeonResult, Throw},\n    sys,\n    types::{\n        extract::{TryFromJs, TypeExpected},\n        private::ValueInternal,\n        JsBoolean, JsNumber, JsString, JsValue, Value,\n    },\n};\n\n#[cfg(feature = \"napi-5\")]\nuse crate::types::{extract::Date, JsDate};\n\nimpl<'cx, V> TryFromJs<'cx> for Handle<'cx, V>\nwhere\n    V: Value,\n{\n    type Error = TypeExpected<V>;\n\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        Ok(v.downcast(cx).map_err(|_| TypeExpected::new()))\n    }\n}\n\nimpl<'cx, O> TryFromJs<'cx> for Root<O>\nwhere\n    O: Object,\n{\n    type Error = TypeExpected<O>;\n\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        Ok(match v.downcast::<O, _>(cx) {\n            Ok(v) => Ok(v.root(cx)),\n            Err(_) => Err(TypeExpected::new()),\n        })\n    }\n}\n\nimpl<'cx, T> TryFromJs<'cx> for Option<T>\nwhere\n    T: TryFromJs<'cx>,\n{\n    type Error = T::Error;\n\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        if is_null_or_undefined(cx, v)? {\n            return Ok(Ok(None));\n        }\n\n        T::try_from_js(cx, v).map(|v| v.map(Some))\n    }\n}\n\nimpl<'cx> TryFromJs<'cx> for f64 {\n    type Error = TypeExpected<JsNumber>;\n\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        let mut n = 0f64;\n\n        unsafe {\n            match sys::get_value_double(cx.env().to_raw(), v.to_local(), &mut n) {\n                Err(sys::Status::NumberExpected) => return Ok(Err(TypeExpected::new())),\n                Err(sys::Status::PendingException) => return Err(Throw::new()),\n                status => status.unwrap(),\n            };\n        }\n\n        Ok(Ok(n))\n    }\n}\n\nimpl<'cx> TryFromJs<'cx> for u32 {\n    type Error = TypeExpected<JsNumber>;\n\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        let mut n = 0u32;\n\n        unsafe {\n            match sys::get_value_uint32(cx.env().to_raw(), v.to_local(), &mut n) {\n                Err(sys::Status::NumberExpected) => return Ok(Err(TypeExpected::new())),\n                Err(sys::Status::PendingException) => return Err(Throw::new()),\n                status => status.unwrap(),\n            };\n        }\n\n        Ok(Ok(n))\n    }\n}\n\nimpl<'cx> TryFromJs<'cx> for i32 {\n    type Error = TypeExpected<JsNumber>;\n\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        let mut n = 0i32;\n\n        unsafe {\n            match sys::get_value_int32(cx.env().to_raw(), v.to_local(), &mut n) {\n                Err(sys::Status::NumberExpected) => return Ok(Err(TypeExpected::new())),\n                Err(sys::Status::PendingException) => return Err(Throw::new()),\n                status => status.unwrap(),\n            };\n        }\n\n        Ok(Ok(n))\n    }\n}\n\nimpl<'cx> TryFromJs<'cx> for bool {\n    type Error = TypeExpected<JsBoolean>;\n\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        let mut b = false;\n\n        unsafe {\n            match sys::get_value_bool(cx.env().to_raw(), v.to_local(), &mut b) {\n                Err(sys::Status::BooleanExpected) => return Ok(Err(TypeExpected::new())),\n                Err(sys::Status::PendingException) => return Err(Throw::new()),\n                status => status.unwrap(),\n            };\n        }\n\n        Ok(Ok(b))\n    }\n}\n\nimpl<'cx> TryFromJs<'cx> for String {\n    type Error = TypeExpected<JsString>;\n\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        let env = cx.env().to_raw();\n        let v = v.to_local();\n        let mut len = 0usize;\n\n        unsafe {\n            match sys::get_value_string_utf8(env, v, ptr::null_mut(), 0, &mut len) {\n                Err(sys::Status::StringExpected) => return Ok(Err(TypeExpected::new())),\n                Err(sys::Status::PendingException) => return Err(Throw::new()),\n                status => status.unwrap(),\n            };\n        }\n\n        // Make room for null terminator to avoid losing a character\n        let mut buf = Vec::<u8>::with_capacity(len + 1);\n        let mut written = 0usize;\n\n        unsafe {\n            assert_eq!(\n                sys::get_value_string_utf8(\n                    env,\n                    v,\n                    buf.as_mut_ptr().cast(),\n                    buf.capacity(),\n                    &mut written,\n                ),\n                Ok(())\n            );\n\n            debug_assert_eq!(len, written);\n            buf.set_len(len);\n\n            Ok(Ok(String::from_utf8_unchecked(buf)))\n        }\n    }\n}\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-5\")))]\n#[cfg(feature = \"napi-5\")]\nimpl<'cx> TryFromJs<'cx> for Date {\n    type Error = TypeExpected<JsDate>;\n\n    fn try_from_js(\n        cx: &mut Cx<'cx>,\n        v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        let mut d = 0f64;\n\n        unsafe {\n            match sys::get_date_value(cx.env().to_raw(), v.to_local(), &mut d) {\n                Err(sys::Status::DateExpected) => return Ok(Err(TypeExpected::new())),\n                Err(sys::Status::PendingException) => return Err(Throw::new()),\n                status => status.unwrap(),\n            };\n        }\n\n        Ok(Ok(Date(d)))\n    }\n}\n\n// This implementation primarily exists for macro authors. It is infallible, rather\n// than checking a type, to match the JavaScript conventions of ignoring additional\n// arguments.\n//\n// N.B.: There is a blanket impl of `FromArgs` for `T` where `T: TryFromJs` to make\n// the common case of `arity == 1` more ergonomic and avoid `(T)` is *not* a tuple\n// foot-gun (but, `(T,)` is). This creates ambiguity for `()`. Are we extracting\n// unit from the first argument of a function with `arity == 1` or is this a function\n// with `arity == 0`? By making extraction of unit infallible, we eliminate any\n// impact from the ambiguity.\nimpl<'cx> TryFromJs<'cx> for () {\n    type Error = Infallible;\n\n    fn try_from_js(\n        _cx: &mut Cx<'cx>,\n        _v: Handle<'cx, JsValue>,\n    ) -> NeonResult<Result<Self, Self::Error>> {\n        Ok(Ok(()))\n    }\n}\n\nfn is_null_or_undefined<V>(cx: &mut Cx, v: Handle<V>) -> NeonResult<bool>\nwhere\n    V: Value,\n{\n    let mut ty = sys::ValueType::Object;\n\n    unsafe {\n        match sys::typeof_value(cx.env().to_raw(), v.to_local(), &mut ty) {\n            Err(sys::Status::PendingException) => return Err(Throw::new()),\n            status => status.unwrap(),\n        };\n    }\n\n    Ok(matches!(\n        ty,\n        sys::ValueType::Undefined | sys::ValueType::Null,\n    ))\n}\n"
  },
  {
    "path": "crates/neon/src/types_impl/extract/try_into_js.rs",
    "content": "use crate::{\n    context::{Context, Cx},\n    handle::{Handle, Root},\n    object::Object,\n    result::{JsResult, Throw},\n    types::{extract::TryIntoJs, JsBoolean, JsNumber, JsString, JsUndefined, JsValue, Value},\n};\n\n#[cfg(feature = \"napi-5\")]\nuse crate::{\n    result::ResultExt,\n    types::{extract::Date, JsDate},\n};\n\nimpl<'cx, T> TryIntoJs<'cx> for Handle<'cx, T>\nwhere\n    T: Value,\n{\n    type Value = T;\n\n    fn try_into_js(self, _cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        Ok(self)\n    }\n}\n\nimpl<'cx, O> TryIntoJs<'cx> for Root<O>\nwhere\n    O: Object,\n{\n    type Value = O;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        Ok(self.into_inner(cx))\n    }\n}\n\nimpl<'cx, T, E> TryIntoJs<'cx> for Result<T, E>\nwhere\n    T: TryIntoJs<'cx>,\n    E: TryIntoJs<'cx>,\n{\n    type Value = T::Value;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        match self {\n            Ok(v) => v.try_into_js(cx),\n            Err(err) => {\n                let err = err.try_into_js(cx)?;\n\n                cx.throw(err)\n            }\n        }\n    }\n}\n\nimpl<'cx> TryIntoJs<'cx> for Throw {\n    type Value = JsValue;\n\n    fn try_into_js(self, _cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        Err(self)\n    }\n}\n\nimpl<'cx, T> TryIntoJs<'cx> for Option<T>\nwhere\n    T: TryIntoJs<'cx>,\n{\n    type Value = JsValue;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        if let Some(val) = self {\n            val.try_into_js(cx).map(|v| v.upcast())\n        } else {\n            Ok(cx.undefined().upcast())\n        }\n    }\n}\n\nimpl<'cx, T> TryIntoJs<'cx> for Box<T>\nwhere\n    T: TryIntoJs<'cx>,\n{\n    type Value = T::Value;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        (*self).try_into_js(cx)\n    }\n}\n\nmacro_rules! impl_number {\n    ($ty:ident) => {\n        impl<'cx> TryIntoJs<'cx> for $ty {\n            type Value = JsNumber;\n\n            fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n                Ok(cx.number(self))\n            }\n        }\n    };\n\n    ($($ty:ident),* $(,)?) => {\n        $(\n            impl_number!($ty);\n        )*\n    }\n}\n\nimpl_number!(u8, u16, u32, i8, i16, i32, f32, f64);\n\nimpl<'cx> TryIntoJs<'cx> for String {\n    type Value = JsString;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        Ok(cx.string(self))\n    }\n}\n\nimpl<'cx> TryIntoJs<'cx> for &str {\n    type Value = JsString;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        Ok(cx.string(self))\n    }\n}\n\nimpl<'cx> TryIntoJs<'cx> for &String {\n    type Value = JsString;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        Ok(cx.string(self))\n    }\n}\n\nimpl<'cx> TryIntoJs<'cx> for bool {\n    type Value = JsBoolean;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        Ok(cx.boolean(self))\n    }\n}\n\nimpl<'cx> TryIntoJs<'cx> for () {\n    type Value = JsUndefined;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        Ok(cx.undefined())\n    }\n}\n\n#[cfg(feature = \"napi-5\")]\nimpl<'cx> TryIntoJs<'cx> for Date {\n    type Value = JsDate;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        cx.date(self.0).or_throw(cx)\n    }\n}\n"
  },
  {
    "path": "crates/neon/src/types_impl/extract/with.rs",
    "content": "use crate::{\n    context::Cx,\n    result::JsResult,\n    types::{extract::TryIntoJs, Value},\n};\n\nstruct With<F>(pub F);\n\n/// Wraps a closure that will be lazily evaluated when [`TryIntoJs::try_into_js`] is\n/// called.\n///\n/// Useful for executing arbitrary code on the main thread before returning from a\n/// function exported with [`neon::export`](crate::export).\n///\n/// **Note:** The return type is [`JsResult`]. If you need to return a non-JavaScript type,\n/// call [`TryIntoJs::try_into_js`].\n///\n/// _See [`With`](With#Example) for example usage._\n///\n/// ## Example\n///\n/// ```\n/// # use neon::{prelude::*, types::extract::{self, TryIntoJs}};\n/// use std::time::Instant;\n///\n/// #[neon::export(task)]\n/// fn sum(nums: Vec<f64>) -> impl for<'cx> TryIntoJs<'cx> {\n///     let start = Instant::now();\n///     let sum = nums.into_iter().sum::<f64>();\n///     let log = format!(\"sum took {} ms\", start.elapsed().as_millis());\n///\n///     extract::with(move |cx| -> NeonResult<_> {\n///         cx.global::<JsObject>(\"console\")?\n///             .method(cx, \"log\")?\n///             .arg(&log)?\n///             .exec()?;\n///\n///         sum.try_into_js(cx)\n///     })\n/// }\n/// ```\npub fn with<V, F>(f: F) -> impl for<'cx> TryIntoJs<'cx, Value = V>\nwhere\n    V: Value,\n    for<'cx> F: FnOnce(&mut Cx<'cx>) -> JsResult<'cx, V>,\n{\n    With(f)\n}\n\nimpl<'cx, O, F> TryIntoJs<'cx> for With<F>\nwhere\n    O: TryIntoJs<'cx>,\n    F: FnOnce(&mut Cx<'cx>) -> O,\n{\n    type Value = O::Value;\n\n    fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {\n        (self.0)(cx).try_into_js(cx)\n    }\n}\n\nimpl<F> super::private::Sealed for With<F> {}\n"
  },
  {
    "path": "crates/neon/src/types_impl/function/mod.rs",
    "content": "//! Types and traits for working with JavaScript functions.\n\nuse smallvec::smallvec;\n\nuse crate::{\n    context::{Context, Cx},\n    handle::Handle,\n    object::Object,\n    result::{JsResult, NeonResult},\n    types::{\n        extract::{TryFromJs, TryIntoJs},\n        private::ValueInternal,\n        JsFunction, JsObject, JsValue, Value,\n    },\n};\n\npub(crate) mod private;\n\n/// A builder for making a JavaScript function call like `parseInt(\"42\")`.\n///\n/// The builder methods make it convenient to assemble the call from parts:\n/// ```\n/// # use neon::prelude::*;\n/// # fn foo(mut cx: FunctionContext) -> JsResult<JsNumber> {\n/// # let parse_int: Handle<JsFunction> = cx.global(\"parseInt\")?;\n/// let x: f64 = parse_int\n///     .bind(&mut cx)\n///     .arg(\"42\")?\n///     .call()?;\n/// # Ok(cx.number(x))\n/// # }\n/// ```\npub struct BindOptions<'a, 'cx: 'a> {\n    pub(crate) cx: &'a mut Cx<'cx>,\n    pub(crate) callee: Handle<'cx, JsValue>,\n    pub(crate) this: Option<Handle<'cx, JsValue>>,\n    pub(crate) args: private::ArgsVec<'cx>,\n}\n\nimpl<'a, 'cx: 'a> BindOptions<'a, 'cx> {\n    /// Set the value of `this` for the function call.\n    pub fn this<T: TryIntoJs<'cx>>(&mut self, this: T) -> NeonResult<&mut Self> {\n        let v = this.try_into_js(self.cx)?;\n        self.this = Some(v.upcast());\n        Ok(self)\n    }\n\n    /// Replaces the arguments list with the given arguments.\n    pub fn args<A: TryIntoArguments<'cx>>(&mut self, a: A) -> NeonResult<&mut Self> {\n        self.args = a.try_into_args_vec(self.cx)?;\n        Ok(self)\n    }\n\n    /// Replaces the arguments list with a list computed from a closure.\n    pub fn args_with<R, F>(&mut self, f: F) -> NeonResult<&mut Self>\n    where\n        R: TryIntoArguments<'cx>,\n        F: FnOnce(&mut Cx<'cx>) -> R,\n    {\n        self.args = f(self.cx).try_into_args_vec(self.cx)?;\n        Ok(self)\n    }\n\n    /// Add an argument to the arguments list.\n    pub fn arg<A: TryIntoJs<'cx>>(&mut self, a: A) -> NeonResult<&mut Self> {\n        let v = a.try_into_js(self.cx)?;\n        self.args.push(v.upcast());\n        Ok(self)\n    }\n\n    /// Add an argument to the arguments list, computed from a closure.\n    pub fn arg_with<R, F>(&mut self, f: F) -> NeonResult<&mut Self>\n    where\n        R: TryIntoJs<'cx>,\n        F: FnOnce(&mut Cx<'cx>) -> R,\n    {\n        let v = f(self.cx).try_into_js(self.cx)?;\n        self.args.push(v.upcast());\n        Ok(self)\n    }\n\n    /// Make the function call. If the function returns without throwing, the result value\n    /// is converted to a Rust value with `TryFromJs::from_js`.\n    pub fn call<R: TryFromJs<'cx>>(&mut self) -> NeonResult<R> {\n        let this = self.this.unwrap_or_else(|| self.cx.undefined().upcast());\n        let v: Handle<JsValue> = unsafe { self.callee.try_call(self.cx, this, &self.args)? };\n        R::from_js(self.cx, v)\n    }\n\n    /// Make the function call as a constructor. If the function returns without throwing, the\n    /// result value is converted to a Rust value with `TryFromJs::from_js`.\n    pub fn construct<R: TryFromJs<'cx>>(&mut self) -> NeonResult<R> {\n        let v: Handle<JsValue> = unsafe { self.callee.try_construct(self.cx, &self.args)? };\n        R::from_js(self.cx, v)\n    }\n\n    /// Make the function call for side effect, discarding the result value. This method is\n    /// preferable to [`call()`](BindOptions::call) when the result value isn't needed,\n    /// since it doesn't require specifying a result type.\n    pub fn exec(&mut self) -> NeonResult<()> {\n        let _ignore: Handle<JsValue> = self.call()?;\n        Ok(())\n    }\n}\n\n/// A builder for making a JavaScript function call like `parseInt(\"42\")`.\n///\n/// The builder methods make it convenient to assemble the call from parts:\n/// ```\n/// # use neon::prelude::*;\n/// # fn foo(mut cx: FunctionContext) -> JsResult<JsNumber> {\n/// # let parse_int: Handle<JsFunction> = cx.global(\"parseInt\")?;\n/// let x: Handle<JsNumber> = parse_int\n///     .call_with(&cx)\n///     .arg(cx.string(\"42\"))\n///     .apply(&mut cx)?;\n/// # Ok(x)\n/// # }\n/// ```\n#[deprecated(since = \"TBD\", note = \"use `JsFunction::bind()` instead\")]\n#[derive(Clone)]\npub struct CallOptions<'a> {\n    pub(crate) callee: Handle<'a, JsFunction>,\n    pub(crate) this: Option<Handle<'a, JsValue>>,\n    pub(crate) args: private::ArgsVec<'a>,\n}\n\nimpl<'a> CallOptions<'a> {\n    /// Set the value of `this` for the function call.\n    pub fn this<V: Value>(&mut self, this: Handle<'a, V>) -> &mut Self {\n        self.this = Some(this.upcast());\n        self\n    }\n\n    /// Add an argument to the arguments list.\n    pub fn arg<V: Value>(&mut self, arg: Handle<'a, V>) -> &mut Self {\n        self.args.push(arg.upcast());\n        self\n    }\n\n    /// Replaces the arguments list with the given arguments.\n    pub fn args<A: Arguments<'a>>(&mut self, args: A) -> &mut Self {\n        self.args = args.into_args_vec();\n        self\n    }\n\n    /// Make the function call. If the function returns without throwing, the result value\n    /// is downcast to the type `V`, throwing a `TypeError` if the downcast fails.\n    pub fn apply<'b: 'a, V: Value, C: Context<'b>>(&self, cx: &mut C) -> JsResult<'b, V> {\n        let this = self.this.unwrap_or_else(|| cx.undefined().upcast());\n        let v: Handle<JsValue> = self.callee.call(cx, this, &self.args)?;\n        v.downcast_or_throw(cx)\n    }\n\n    /// Make the function call for side effect, discarding the result value. This method is\n    /// preferable to [`apply()`](CallOptions::apply) when the result value isn't needed,\n    /// since it doesn't require specifying a result type.\n    pub fn exec<'b: 'a, C: Context<'b>>(&self, cx: &mut C) -> NeonResult<()> {\n        let this = self.this.unwrap_or_else(|| cx.undefined().upcast());\n        self.callee.call(cx, this, &self.args)?;\n        Ok(())\n    }\n}\n\n/// A builder for making a JavaScript constructor call like `new Array(16)`.\n///\n/// The builder methods make it convenient to assemble the call from parts:\n/// ```\n/// # use neon::prelude::*;\n/// # fn foo(mut cx: FunctionContext) -> JsResult<JsObject> {\n/// # let url: Handle<JsFunction> = cx.global(\"URL\")?;\n/// let obj = url\n///     .construct_with(&cx)\n///     .arg(cx.string(\"https://neon-bindings.com\"))\n///     .apply(&mut cx)?;\n/// # Ok(obj)\n/// # }\n/// ```\n#[deprecated(since = \"TBD\", note = \"use `JsFunction::bind()` instead\")]\n#[derive(Clone)]\npub struct ConstructOptions<'a> {\n    pub(crate) callee: Handle<'a, JsFunction>,\n    pub(crate) args: private::ArgsVec<'a>,\n}\n\nimpl<'a> ConstructOptions<'a> {\n    /// Add an argument to the arguments list.\n    pub fn arg<V: Value>(&mut self, arg: Handle<'a, V>) -> &mut Self {\n        self.args.push(arg.upcast());\n        self\n    }\n\n    /// Replaces the arguments list with the given arguments.\n    pub fn args<A: Arguments<'a>>(&mut self, args: A) -> &mut Self {\n        self.args = args.into_args_vec();\n        self\n    }\n\n    /// Make the constructor call. If the function returns without throwing, returns\n    /// the resulting object.\n    pub fn apply<'b: 'a, O: Object, C: Context<'b>>(&self, cx: &mut C) -> JsResult<'b, O> {\n        let v: Handle<JsObject> = self.callee.construct(cx, &self.args)?;\n        v.downcast_or_throw(cx)\n    }\n}\n\n/// The trait for specifying values to be converted into arguments for a function call.\n/// This trait is sealed and cannot be implemented by types outside of the Neon crate.\n///\n/// **Note:** This trait is implemented for tuples of up to 32 JavaScript values,\n/// but for the sake of brevity, only tuples up to size 8 are shown in this documentation.\npub trait TryIntoArguments<'cx>: private::TryIntoArgumentsInternal<'cx> {}\n\nimpl<'cx> private::TryIntoArgumentsInternal<'cx> for () {\n    fn try_into_args_vec(self, _cx: &mut Cx<'cx>) -> NeonResult<private::ArgsVec<'cx>> {\n        Ok(smallvec![])\n    }\n}\n\nimpl<'cx, T, E> private::TryIntoArgumentsInternal<'cx> for Result<T, E>\nwhere\n    T: private::TryIntoArgumentsInternal<'cx>,\n    E: TryIntoJs<'cx>,\n{\n    fn try_into_args_vec(self, cx: &mut Cx<'cx>) -> NeonResult<private::ArgsVec<'cx>> {\n        match self {\n            Ok(v) => v.try_into_args_vec(cx),\n            Err(err) => err.try_into_js(cx).and_then(|err| cx.throw(err)),\n        }\n    }\n}\n\nimpl<'cx, T, E> TryIntoArguments<'cx> for Result<T, E>\nwhere\n    T: TryIntoArguments<'cx>,\n    E: TryIntoJs<'cx>,\n{\n}\n\nmacro_rules! impl_into_arguments_expand {\n    {\n        $(#[$attrs:meta])?\n        [ $($prefix:ident ),* ];\n        [];\n    } => {};\n\n    {\n        $(#[$attrs:meta])?\n        [ $($prefix:ident),* ];\n        [ $head:ident $(, $tail:ident)* ];\n    } => {\n        $(#[$attrs])?\n        impl<'cx, $($prefix: TryIntoJs<'cx> + 'cx, )* $head: TryIntoJs<'cx> + 'cx> private::TryIntoArgumentsInternal<'cx> for ($($prefix, )* $head, ) {\n            #[allow(non_snake_case)]\n            fn try_into_args_vec(self, cx: &mut Cx<'cx>) -> NeonResult<private::ArgsVec<'cx>> {\n                let ($($prefix, )* $head, ) = self;\n                Ok(smallvec![ $($prefix.try_into_js(cx)?.upcast(),)* $head.try_into_js(cx)?.upcast() ])\n             }\n         }\n\n         $(#[$attrs])?\n         impl<'cx, $($prefix: TryIntoJs<'cx> + 'cx, )* $head: TryIntoJs<'cx> + 'cx> TryIntoArguments<'cx> for ($($prefix, )* $head, ) {}\n\n        impl_into_arguments_expand! {\n            $(#[$attrs])?\n            [ $($prefix, )* $head ];\n            [ $($tail),* ];\n        }\n   }\n}\n\nmacro_rules! impl_into_arguments {\n    {\n        [ $($show:ident),* ];\n        [ $($hide:ident),* ];\n    } => {\n        impl_into_arguments_expand! { []; [ $($show),* ]; }\n        impl_into_arguments_expand! { #[doc(hidden)] [ $($show),* ]; [ $($hide),* ]; }\n    }\n}\n\nimpl_into_arguments! {\n    // Tuples up to length 8 are included in the docs.\n    [V1, V2, V3, V4, V5, V6, V7, V8];\n\n    // Tuples up to length 32 are not included in the docs.\n    [\n        V9, V10, V11, V12, V13, V14, V15, V16,\n        V17, V18, V19, V20, V21, V22, V23, V24,\n        V25, V26, V27, V28, V29, V30, V31, V32\n    ];\n}\n\n/// The trait for specifying arguments for a function call. This trait is sealed and cannot\n/// be implemented by types outside of the Neon crate.\n///\n/// **Note:** This trait is implemented for tuples of up to 32 JavaScript values,\n/// but for the sake of brevity, only tuples up to size 8 are shown in this documentation.\npub trait Arguments<'a>: private::ArgumentsInternal<'a> {}\n\nimpl<'a> private::ArgumentsInternal<'a> for () {\n    fn into_args_vec(self) -> private::ArgsVec<'a> {\n        smallvec![]\n    }\n}\n\nimpl<'a> Arguments<'a> for () {}\n\nmacro_rules! impl_arguments_expand {\n    {\n        $(#[$attrs:meta])?\n        [ $($prefix:ident),* ];\n        [];\n    } => {};\n\n    {\n        $(#[$attrs:meta])?\n        [ $($prefix:ident),* ];\n        [ $head:ident $(, $tail:ident)* ];\n    } => {\n        $(#[$attrs])?\n        impl<'a, $($prefix: Value, )* $head: Value> private::ArgumentsInternal<'a> for ($(Handle<'a, $prefix>, )* Handle<'a, $head>, ) {\n            #[allow(non_snake_case)]\n            fn into_args_vec(self) -> private::ArgsVec<'a> {\n                let ($($prefix, )* $head, ) = self;\n                smallvec![$($prefix.upcast(),)* $head.upcast()]\n             }\n         }\n\n         $(#[$attrs])?\n         impl<'a, $($prefix: Value, )* $head: Value> Arguments<'a> for ($(Handle<'a, $prefix>, )* Handle<'a, $head>, ) {}\n\n         impl_arguments_expand! {\n            $(#[$attrs])?\n            [ $($prefix, )* $head ];\n            [ $($tail),* ];\n         }\n    };\n}\n\nmacro_rules! impl_arguments {\n    {\n        [ $($show:ident),* ];\n        [ $($hide:ident),* ];\n    } => {\n        impl_arguments_expand! { []; [ $($show),* ]; }\n        impl_arguments_expand! { #[doc(hidden)] [ $($show),* ]; [ $($hide),* ]; }\n    }\n}\n\nimpl_arguments! {\n    // Tuples up to length 8 are included in the docs.\n    [V1, V2, V3, V4, V5, V6, V7, V8];\n\n    // Tuples up to length 32 are not included in the docs.\n    [\n        V9, V10, V11, V12, V13, V14, V15, V16,\n        V17, V18, V19, V20, V21, V22, V23, V24,\n        V25, V26, V27, V28, V29, V30, V31, V32\n    ];\n}\n"
  },
  {
    "path": "crates/neon/src/types_impl/function/private.rs",
    "content": "use smallvec::SmallVec;\n\nuse crate::{context::Cx, handle::Handle, result::NeonResult, types::JsValue};\n\npub type ArgsVec<'a> = SmallVec<[Handle<'a, JsValue>; 8]>;\n\n/// This type marks the `TryIntoArguments` trait as sealed.\npub trait TryIntoArgumentsInternal<'cx> {\n    fn try_into_args_vec(self, cx: &mut Cx<'cx>) -> NeonResult<ArgsVec<'cx>>;\n}\n\n/// This type marks the `Arguments` trait as sealed.\npub trait ArgumentsInternal<'a> {\n    fn into_args_vec(self) -> ArgsVec<'a>;\n}\n"
  },
  {
    "path": "crates/neon/src/types_impl/mod.rs",
    "content": "// See types_docs.rs for top-level module API docs.\n\n#[cfg(feature = \"napi-6\")]\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-6\")))]\npub mod bigint;\npub(crate) mod boxed;\npub mod buffer;\n#[cfg(feature = \"napi-5\")]\npub(crate) mod date;\npub(crate) mod error;\npub mod extract;\npub mod function;\npub(crate) mod promise;\n\npub(crate) mod private;\npub(crate) mod utf8;\n\nuse std::{\n    any,\n    fmt::{self, Debug},\n};\n\nuse private::prepare_call;\nuse smallvec::smallvec;\n\nuse crate::{\n    context::{\n        internal::{ContextInternal, Env},\n        Context, Cx, FunctionContext,\n    },\n    handle::{\n        internal::{SuperType, TransparentNoCopyWrapper},\n        Handle,\n    },\n    object::Object,\n    result::{JsResult, NeonResult, ResultExt, Throw},\n    sys::{self, raw},\n    types::{\n        function::{BindOptions, CallOptions, ConstructOptions},\n        private::ValueInternal,\n        utf8::Utf8,\n    },\n};\n\npub use self::{\n    boxed::{Finalize, JsBox},\n    buffer::types::{\n        JsArrayBuffer, JsBigInt64Array, JsBigUint64Array, JsBuffer, JsFloat32Array, JsFloat64Array,\n        JsInt16Array, JsInt32Array, JsInt8Array, JsTypedArray, JsUint16Array, JsUint32Array,\n        JsUint8Array,\n    },\n    error::JsError,\n    promise::{Deferred, JsPromise},\n};\n\n#[cfg(feature = \"napi-5\")]\npub use self::date::{DateError, DateErrorKind, JsDate};\n\n#[cfg(all(feature = \"napi-5\", feature = \"futures\"))]\n#[cfg_attr(docsrs, doc(cfg(all(feature = \"napi-5\", feature = \"futures\"))))]\npub use self::promise::JsFuture;\n\n// This should be considered deprecated and will be removed:\n// https://github.com/neon-bindings/neon/issues/983\npub(crate) fn build<'a, T: Value, F: FnOnce(&mut raw::Local) -> bool>(\n    env: Env,\n    init: F,\n) -> JsResult<'a, T> {\n    unsafe {\n        let mut local: raw::Local = std::mem::zeroed();\n        if init(&mut local) {\n            Ok(Handle::new_internal(T::from_local(env, local)))\n        } else {\n            Err(Throw::new())\n        }\n    }\n}\n\nimpl<T: Value> SuperType<T> for JsValue {\n    fn upcast_internal(v: &T) -> JsValue {\n        JsValue(v.to_local())\n    }\n}\n\nimpl<T: Object> SuperType<T> for JsObject {\n    fn upcast_internal(v: &T) -> JsObject {\n        JsObject(v.to_local())\n    }\n}\n\n/// The trait shared by all JavaScript values.\npub trait Value: ValueInternal {\n    fn to_string<'cx, C: Context<'cx>>(&self, cx: &mut C) -> JsResult<'cx, JsString> {\n        let env = cx.env();\n        build(env, |out| unsafe {\n            sys::convert::to_string(out, env.to_raw(), self.to_local())\n        })\n    }\n\n    fn as_value<'cx, C: Context<'cx>>(&self, _: &mut C) -> Handle<'cx, JsValue> {\n        JsValue::new_internal(self.to_local())\n    }\n\n    #[cfg(feature = \"sys\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"sys\")))]\n    /// Get a raw reference to the wrapped Node-API value.\n    fn to_raw(&self) -> sys::Value {\n        self.to_local()\n    }\n\n    #[cfg(feature = \"sys\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"sys\")))]\n    /// Creates a value from a raw Node-API value.\n    ///\n    /// # Safety\n    ///\n    /// * `value` must be of type `Self`\n    /// * `value` must be valid for `'cx`\n    unsafe fn from_raw<'cx, C: Context<'cx>>(cx: &C, value: sys::Value) -> Handle<'cx, Self> {\n        Handle::new_internal(Self::from_local(cx.env(), value))\n    }\n}\n\n/// The type of any JavaScript value, i.e., the root of all types.\n///\n/// The `JsValue` type is a catch-all type that sits at the top of the\n/// [JavaScript type hierarchy](./index.html#the-javascript-type-hierarchy).\n/// All JavaScript values can be safely and statically\n/// [upcast](crate::handle::Handle::upcast) to `JsValue`; by contrast, a\n/// [downcast](crate::handle::Handle::downcast) of a `JsValue` to another type\n/// requires a runtime check.\n/// (For TypeScript programmers, this can be thought of as similar to TypeScript's\n/// [`unknown`](https://www.typescriptlang.org/docs/handbook/2/functions.html#unknown)\n/// type.)\n///\n/// The `JsValue` type can be useful for generic, dynamic, or otherwise\n/// hard-to-express API signatures, such as overloaded types:\n///\n/// ```\n/// # use neon::prelude::*;\n/// // Takes a string and adds the specified padding to the left.\n/// // If the padding is a string, it's added as-is.\n/// // If the padding is a number, then that number of spaces is added.\n/// fn pad_left(mut cx: FunctionContext) -> JsResult<JsString> {\n///     let string: Handle<JsString> = cx.argument(0)?;\n///     let padding: Handle<JsValue> = cx.argument(1)?;\n///\n///     let padding: String = if let Ok(str) = padding.downcast::<JsString, _>(&mut cx) {\n///         str.value(&mut cx)\n///     } else if let Ok(num) = padding.downcast::<JsNumber, _>(&mut cx) {\n///         \" \".repeat(num.value(&mut cx) as usize)\n///     } else {\n///         return cx.throw_type_error(\"expected string or number\");\n///     };\n///\n///     let new_value = padding + &string.value(&mut cx);\n///     Ok(cx.string(&new_value))\n/// }\n/// ```\n#[derive(Debug)]\n#[repr(transparent)]\npub struct JsValue(raw::Local);\n\nimpl Value for JsValue {}\n\nunsafe impl TransparentNoCopyWrapper for JsValue {\n    type Inner = raw::Local;\n\n    fn into_inner(self) -> Self::Inner {\n        self.0\n    }\n}\n\nimpl ValueInternal for JsValue {\n    fn name() -> &'static str {\n        \"any\"\n    }\n\n    fn is_typeof<Other: Value>(_cx: &mut Cx, _other: &Other) -> bool {\n        true\n    }\n\n    fn to_local(&self) -> raw::Local {\n        self.0\n    }\n\n    unsafe fn from_local(_env: Env, h: raw::Local) -> Self {\n        JsValue(h)\n    }\n}\n\nimpl JsValue {\n    pub(crate) fn new_internal<'a>(value: raw::Local) -> Handle<'a, JsValue> {\n        Handle::new_internal(JsValue(value))\n    }\n}\n\n/// The type of JavaScript\n/// [`undefined`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#primitive_values)\n/// primitives.\n///\n/// # Example\n///\n/// ```\n/// # use neon::prelude::*;\n/// # fn test(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n/// // Extract the console object:\n/// let console: Handle<JsObject> = cx.global(\"console\")?;\n///\n/// // The undefined value:\n/// let undefined = cx.undefined();\n///\n/// // Call console.log(undefined):\n/// console.method(&mut cx, \"log\")?.arg(undefined)?.exec()?;\n/// # Ok(undefined)\n/// # }\n/// ```\n#[derive(Debug)]\n#[repr(transparent)]\npub struct JsUndefined(raw::Local);\n\nimpl JsUndefined {\n    /// Creates an `undefined` value.\n    ///\n    /// Although this method can be called many times, all `undefined`\n    /// values are indistinguishable.\n    ///\n    /// **See also:** [`Context::undefined`]\n    pub fn new<'a, C: Context<'a>>(cx: &mut C) -> Handle<'a, JsUndefined> {\n        JsUndefined::new_internal(cx.env())\n    }\n\n    pub(crate) fn new_internal<'a>(env: Env) -> Handle<'a, JsUndefined> {\n        unsafe {\n            let mut local: raw::Local = std::mem::zeroed();\n            sys::primitive::undefined(&mut local, env.to_raw());\n            Handle::new_internal(JsUndefined(local))\n        }\n    }\n}\n\nimpl Value for JsUndefined {}\n\nunsafe impl TransparentNoCopyWrapper for JsUndefined {\n    type Inner = raw::Local;\n\n    fn into_inner(self) -> Self::Inner {\n        self.0\n    }\n}\n\nimpl ValueInternal for JsUndefined {\n    fn name() -> &'static str {\n        \"undefined\"\n    }\n\n    fn is_typeof<Other: Value>(cx: &mut Cx, other: &Other) -> bool {\n        unsafe { sys::tag::is_undefined(cx.env().to_raw(), other.to_local()) }\n    }\n\n    fn to_local(&self) -> raw::Local {\n        self.0\n    }\n\n    unsafe fn from_local(_env: Env, h: raw::Local) -> Self {\n        JsUndefined(h)\n    }\n}\n\n/// The type of JavaScript\n/// [`null`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#primitive_values)\n/// primitives.\n///\n/// # Example\n///\n/// ```\n/// # use neon::prelude::*;\n/// # fn test(mut cx: FunctionContext) -> JsResult<JsNull> {\n/// let null = cx.null();\n/// cx.global::<JsObject>(\"console\")?\n///     .method(&mut cx, \"log\")?\n///     .arg(null)?\n///     .exec()?;\n/// # Ok(null)\n/// # }\n/// ```\n#[derive(Debug)]\n#[repr(transparent)]\npub struct JsNull(raw::Local);\n\nimpl JsNull {\n    /// Creates a `null` value.\n    ///\n    /// Although this method can be called many times, all `null`\n    /// values are indistinguishable.\n    ///\n    /// **See also:** [`Context::null`]\n    pub fn new<'a, C: Context<'a>>(cx: &mut C) -> Handle<'a, JsNull> {\n        JsNull::new_internal(cx.env())\n    }\n\n    pub(crate) fn new_internal<'a>(env: Env) -> Handle<'a, JsNull> {\n        unsafe {\n            let mut local: raw::Local = std::mem::zeroed();\n            sys::primitive::null(&mut local, env.to_raw());\n            Handle::new_internal(JsNull(local))\n        }\n    }\n}\n\nimpl Value for JsNull {}\n\nunsafe impl TransparentNoCopyWrapper for JsNull {\n    type Inner = raw::Local;\n\n    fn into_inner(self) -> Self::Inner {\n        self.0\n    }\n}\n\nimpl ValueInternal for JsNull {\n    fn name() -> &'static str {\n        \"null\"\n    }\n\n    fn is_typeof<Other: Value>(cx: &mut Cx, other: &Other) -> bool {\n        unsafe { sys::tag::is_null(cx.env().to_raw(), other.to_local()) }\n    }\n\n    fn to_local(&self) -> raw::Local {\n        self.0\n    }\n\n    unsafe fn from_local(_env: Env, h: raw::Local) -> Self {\n        JsNull(h)\n    }\n}\n\n/// The type of JavaScript\n/// [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#primitive_values)\n/// primitives.\n///\n/// # Example\n///\n/// ```\n/// # use neon::prelude::*;\n/// # fn test(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n/// // The two Boolean values:\n/// let t = cx.boolean(true);\n/// let f = cx.boolean(false);\n///\n/// // Call console.log(true, false):\n/// cx.global::<JsObject>(\"console\")?.method(&mut cx, \"log\")?.args((t, f))?.exec()?;\n/// # Ok(cx.undefined())\n/// # }\n/// ```\n#[derive(Debug)]\n#[repr(transparent)]\npub struct JsBoolean(raw::Local);\n\nimpl JsBoolean {\n    /// Creates a Boolean value with value `b`.\n    ///\n    /// **See also:** [`Context::boolean`]\n    pub fn new<'a, C: Context<'a>>(cx: &mut C, b: bool) -> Handle<'a, JsBoolean> {\n        JsBoolean::new_internal(cx.env(), b)\n    }\n\n    pub(crate) fn new_internal<'a>(env: Env, b: bool) -> Handle<'a, JsBoolean> {\n        unsafe {\n            let mut local: raw::Local = std::mem::zeroed();\n            sys::primitive::boolean(&mut local, env.to_raw(), b);\n            Handle::new_internal(JsBoolean(local))\n        }\n    }\n\n    /// Returns the value of this Boolean as a Rust `bool`.\n    pub fn value<'a, C: Context<'a>>(&self, cx: &mut C) -> bool {\n        let env = cx.env().to_raw();\n        unsafe { sys::primitive::boolean_value(env, self.to_local()) }\n    }\n}\n\nimpl Value for JsBoolean {}\n\nunsafe impl TransparentNoCopyWrapper for JsBoolean {\n    type Inner = raw::Local;\n\n    fn into_inner(self) -> Self::Inner {\n        self.0\n    }\n}\n\nimpl ValueInternal for JsBoolean {\n    fn name() -> &'static str {\n        \"boolean\"\n    }\n\n    fn is_typeof<Other: Value>(cx: &mut Cx, other: &Other) -> bool {\n        unsafe { sys::tag::is_boolean(cx.env().to_raw(), other.to_local()) }\n    }\n\n    fn to_local(&self) -> raw::Local {\n        self.0\n    }\n\n    unsafe fn from_local(_env: Env, h: raw::Local) -> Self {\n        JsBoolean(h)\n    }\n}\n\n/// The type of JavaScript\n/// [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#primitive_values)\n/// primitives.\n///\n/// # Example\n///\n/// ```\n/// # use neon::prelude::*;\n/// # fn test(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n/// // Create a string:\n/// let s = cx.string(\"hello 🥹\");\n///\n/// // Call console.log(s):\n/// cx.global::<JsObject>(\"console\")?.method(&mut cx, \"log\")?.arg(s)?.exec()?;\n/// # Ok(cx.undefined())\n/// # }\n/// ```\n#[derive(Debug)]\n#[repr(transparent)]\npub struct JsString(raw::Local);\n\n/// An error produced when constructing a string that exceeds the limits of the runtime.\n#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]\npub struct StringOverflow(usize);\n\nimpl fmt::Display for StringOverflow {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(f, \"string size out of range: {}\", self.0)\n    }\n}\n\n/// The result of constructing a new `JsString`.\npub type StringResult<'a> = Result<Handle<'a, JsString>, StringOverflow>;\n\nimpl<'a> ResultExt<Handle<'a, JsString>> for StringResult<'a> {\n    fn or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> JsResult<'a, JsString> {\n        match self {\n            Ok(v) => Ok(v),\n            Err(e) => cx.throw_range_error(e.to_string()),\n        }\n    }\n}\n\nimpl Value for JsString {}\n\nunsafe impl TransparentNoCopyWrapper for JsString {\n    type Inner = raw::Local;\n\n    fn into_inner(self) -> Self::Inner {\n        self.0\n    }\n}\n\nimpl ValueInternal for JsString {\n    fn name() -> &'static str {\n        \"string\"\n    }\n\n    fn is_typeof<Other: Value>(cx: &mut Cx, other: &Other) -> bool {\n        unsafe { sys::tag::is_string(cx.env().to_raw(), other.to_local()) }\n    }\n\n    fn to_local(&self) -> raw::Local {\n        self.0\n    }\n\n    unsafe fn from_local(_env: Env, h: raw::Local) -> Self {\n        JsString(h)\n    }\n}\n\nimpl JsString {\n    /// Returns the size of the UTF-8 representation of this string,\n    /// measured in 8-bit code units.\n    ///\n    /// Equivalent to `self.value(cx).len()` (but more efficient).\n    ///\n    /// # Example\n    ///\n    /// The string `\"hello 🥹\"` encodes as 10 bytes in UTF-8:\n    ///\n    /// - 6 bytes for `\"hello \"` (including the space).\n    /// - 4 bytes for the emoji `\"🥹\"`.\n    ///\n    /// ```rust\n    /// # use neon::prelude::*;\n    /// # fn string_len(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    /// let str = cx.string(\"hello 🥹\");\n    /// assert_eq!(10, str.size(&mut cx));\n    /// # Ok(cx.undefined())\n    /// # }\n    /// ```\n    pub fn size<'a, C: Context<'a>>(&self, cx: &mut C) -> usize {\n        let env = cx.env().to_raw();\n\n        unsafe { sys::string::utf8_len(env, self.to_local()) }\n    }\n\n    /// Returns the size of the UTF-16 representation of this string,\n    /// measured in 16-bit code units.\n    ///\n    /// Equivalent to `self.to_utf16(cx).len()` (but more efficient).\n    ///\n    /// # Example\n    ///\n    /// The string `\"hello 🥹\"` encodes as 8 code units in UTF-16:\n    ///\n    /// - 6 `u16`s for `\"hello \"` (including the space).\n    /// - 2 `u16`s for the emoji `\"🥹\"`.\n    ///\n    /// ```rust\n    /// # use neon::prelude::*;\n    /// # fn string_len_utf16(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    /// let str = cx.string(\"hello 🥹\");\n    /// assert_eq!(8, str.size_utf16(&mut cx));\n    /// # Ok(cx.undefined())\n    /// # }\n    /// ```\n    pub fn size_utf16<'a, C: Context<'a>>(&self, cx: &mut C) -> usize {\n        let env = cx.env().to_raw();\n\n        unsafe { sys::string::utf16_len(env, self.to_local()) }\n    }\n\n    /// Convert this JavaScript string into a Rust [`String`].\n    ///\n    /// # Example\n    ///\n    /// This example function expects a single JavaScript string as argument\n    /// and prints it out.\n    ///\n    /// ```rust\n    /// # use neon::prelude::*;\n    /// fn print_string(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    ///     let s = cx.argument::<JsString>(0)?.value(&mut cx);\n    ///     println!(\"JavaScript string contents: {}\", s);\n    ///\n    ///     Ok(cx.undefined())\n    /// }\n    /// ```\n    pub fn value<'a, C: Context<'a>>(&self, cx: &mut C) -> String {\n        let env = cx.env().to_raw();\n\n        unsafe {\n            let capacity = sys::string::utf8_len(env, self.to_local()) + 1;\n            let mut buffer: Vec<u8> = Vec::with_capacity(capacity);\n            let len = sys::string::data(env, buffer.as_mut_ptr(), capacity, self.to_local());\n            buffer.set_len(len);\n            String::from_utf8_unchecked(buffer)\n        }\n    }\n\n    /// Convert this JavaScript string into a [`Vec<u16>`] encoded as UTF-16.\n    ///\n    /// The returned vector is guaranteed to be valid UTF-16, so libraries that handle\n    /// UTF-16-encoded strings can assume the content to be valid.\n    ///\n    /// # Example\n    ///\n    /// This example function expects a single JavaScript string as argument and prints it out\n    /// as a raw vector of `u16`s.\n    ///\n    /// ```rust\n    /// # use neon::prelude::*;\n    /// fn print_string_as_utf16(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    ///     let s = cx.argument::<JsString>(0)?.to_utf16(&mut cx);\n    ///     println!(\"JavaScript string as raw UTF-16: {:?}\", s);\n    ///\n    ///     Ok(cx.undefined())\n    /// }\n    /// ```\n    ///\n    /// This next example function also expects a single JavaScript string as argument and converts\n    /// to a [`Vec<u16>`], but utilizes the [`widestring`](https://crates.io/crates/widestring)\n    /// crate to handle the vector as a typical string.\n    ///\n    /// ```rust\n    /// # use neon::prelude::*;\n    /// use widestring::Utf16String;\n    ///\n    /// fn print_with_widestring(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    ///     let s = cx.argument::<JsString>(0)?.to_utf16(&mut cx);\n    ///\n    ///     // The returned vector is guaranteed to be valid UTF-16, so we can\n    ///     // safely skip the validation step.\n    ///     let s = unsafe { Utf16String::from_vec_unchecked(s) };\n    ///\n    ///     println!(\"JavaScript string as UTF-16: {}\", s);\n    ///\n    ///     Ok(cx.undefined())\n    /// }\n    /// ```\n    pub fn to_utf16<'a, C: Context<'a>>(&self, cx: &mut C) -> Vec<u16> {\n        let env = cx.env().to_raw();\n\n        unsafe {\n            let capacity = sys::string::utf16_len(env, self.to_local()) + 1;\n            let mut buffer: Vec<u16> = Vec::with_capacity(capacity);\n            let len = sys::string::data_utf16(env, buffer.as_mut_ptr(), capacity, self.to_local());\n            buffer.set_len(len);\n            buffer\n        }\n    }\n\n    /// Creates a new `JsString` value from a Rust string by copying its contents.\n    ///\n    /// This method panics if the string is longer than the maximum string size allowed\n    /// by the JavaScript engine.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # use neon::prelude::*;\n    /// # fn string_new(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    /// let str = JsString::new(&mut cx, \"hello 🥹\");\n    /// assert_eq!(10, str.size(&mut cx));\n    /// # Ok(cx.undefined())\n    /// # }\n    /// ```\n    ///\n    /// **See also:** [`Context::string`]\n    pub fn new<'a, C: Context<'a>, S: AsRef<str>>(cx: &mut C, val: S) -> Handle<'a, JsString> {\n        JsString::try_new(cx, val).unwrap()\n    }\n\n    /// Tries to create a new `JsString` value from a Rust string by copying its contents.\n    ///\n    /// Returns `Err(StringOverflow)` if the string is longer than the maximum string size\n    /// allowed by the JavaScript engine.\n    ///\n    /// # Example\n    ///\n    /// This example tries to construct a JavaScript string from a Rust string of\n    /// unknown length, and on overflow generates an alternate truncated string with\n    /// a suffix (`\"[…]\"`) to indicate the truncation.\n    ///\n    /// ```\n    /// # use neon::prelude::*;\n    /// # fn string_try_new(mut cx: FunctionContext) -> JsResult<JsString> {\n    /// # static str: &'static str = \"hello 🥹\";\n    /// let s = match JsString::try_new(&mut cx, str) {\n    ///     Ok(s) => s,\n    ///     Err(_) => cx.string(format!(\"{}[…]\", &str[0..32])),\n    /// };\n    /// # Ok(s)\n    /// # }\n    /// ```\n    pub fn try_new<'a, C: Context<'a>, S: AsRef<str>>(cx: &mut C, val: S) -> StringResult<'a> {\n        let val = val.as_ref();\n        match JsString::new_internal(cx.env(), val) {\n            Some(s) => Ok(s),\n            None => Err(StringOverflow(val.len())),\n        }\n    }\n\n    pub(crate) fn new_internal<'a>(env: Env, val: &str) -> Option<Handle<'a, JsString>> {\n        let (ptr, len) = if let Some(small) = Utf8::from(val).into_small() {\n            small.lower()\n        } else {\n            return None;\n        };\n\n        unsafe {\n            let mut local: raw::Local = std::mem::zeroed();\n            if sys::string::new(&mut local, env.to_raw(), ptr, len) {\n                Some(Handle::new_internal(JsString(local)))\n            } else {\n                None\n            }\n        }\n    }\n}\n\n/// The type of JavaScript\n/// [number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#primitive_values)\n/// primitives.\n///\n/// # Example\n///\n/// ```\n/// # use neon::prelude::*;\n/// # fn test(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n/// // Create a number:\n/// let n = cx.number(17.0);\n///\n/// // Call console.log(n):\n/// cx.global::<JsObject>(\"console\")?.method(&mut cx, \"log\")?.arg(n)?.exec()?;\n/// # Ok(cx.undefined())\n/// # }\n/// ```\n#[derive(Debug)]\n#[repr(transparent)]\npub struct JsNumber(raw::Local);\n\nimpl JsNumber {\n    /// Creates a new number with value `x`.\n    ///\n    /// **See also:** [`Context::number`]\n    pub fn new<'a, C: Context<'a>, T: Into<f64>>(cx: &mut C, x: T) -> Handle<'a, JsNumber> {\n        JsNumber::new_internal(cx.env(), x.into())\n    }\n\n    pub(crate) fn new_internal<'a>(env: Env, v: f64) -> Handle<'a, JsNumber> {\n        unsafe {\n            let mut local: raw::Local = std::mem::zeroed();\n            sys::primitive::number(&mut local, env.to_raw(), v);\n            Handle::new_internal(JsNumber(local))\n        }\n    }\n\n    /// Returns the value of this number as a Rust `f64`.\n    pub fn value<'a, C: Context<'a>>(&self, cx: &mut C) -> f64 {\n        let env = cx.env().to_raw();\n        unsafe { sys::primitive::number_value(env, self.to_local()) }\n    }\n}\n\nimpl Value for JsNumber {}\n\nunsafe impl TransparentNoCopyWrapper for JsNumber {\n    type Inner = raw::Local;\n\n    fn into_inner(self) -> Self::Inner {\n        self.0\n    }\n}\n\nimpl ValueInternal for JsNumber {\n    fn name() -> &'static str {\n        \"number\"\n    }\n\n    fn is_typeof<Other: Value>(cx: &mut Cx, other: &Other) -> bool {\n        unsafe { sys::tag::is_number(cx.env().to_raw(), other.to_local()) }\n    }\n\n    fn to_local(&self) -> raw::Local {\n        self.0\n    }\n\n    unsafe fn from_local(_env: Env, h: raw::Local) -> Self {\n        JsNumber(h)\n    }\n}\n\n/// The type of JavaScript\n/// [objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#objects),\n/// i.e., the root of all object types.\n///\n/// # Example\n///\n/// ```\n/// # use neon::prelude::*;\n/// # fn test(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n/// // Create an object:\n/// let obj = cx.empty_object()\n///     .prop(&mut cx, \"name\")\n///     .set(\"Neon\")?\n///     .prop(\"url\")\n///     .set(\"https://neon-bindings.com\")?\n///     .this();\n///\n/// // Call console.log(obj):\n/// cx.global::<JsObject>(\"console\")?.method(&mut cx, \"log\")?.arg(obj)?.exec()?;\n/// # Ok(cx.undefined())\n/// # }\n/// ```\n#[derive(Debug)]\n#[repr(transparent)]\npub struct JsObject(raw::Local);\n\nimpl Value for JsObject {}\n\nunsafe impl TransparentNoCopyWrapper for JsObject {\n    type Inner = raw::Local;\n\n    fn into_inner(self) -> Self::Inner {\n        self.0\n    }\n}\n\nimpl ValueInternal for JsObject {\n    fn name() -> &'static str {\n        \"object\"\n    }\n\n    fn is_typeof<Other: Value>(cx: &mut Cx, other: &Other) -> bool {\n        unsafe { sys::tag::is_object(cx.env().to_raw(), other.to_local()) }\n    }\n\n    fn to_local(&self) -> raw::Local {\n        self.0\n    }\n\n    unsafe fn from_local(_env: Env, h: raw::Local) -> Self {\n        JsObject(h)\n    }\n}\n\nimpl Object for JsObject {}\n\nimpl JsObject {\n    /// Creates a new empty object.\n    ///\n    /// **See also:** [`Context::empty_object`]\n    pub fn new<'a, C: Context<'a>>(c: &mut C) -> Handle<'a, JsObject> {\n        JsObject::new_internal(c.env())\n    }\n\n    pub(crate) fn new_internal<'a>(env: Env) -> Handle<'a, JsObject> {\n        JsObject::build(|out| unsafe { sys::object::new(out, env.to_raw()) })\n    }\n\n    pub(crate) fn build<'a, F: FnOnce(&mut raw::Local)>(init: F) -> Handle<'a, JsObject> {\n        unsafe {\n            let mut local: raw::Local = std::mem::zeroed();\n            init(&mut local);\n            Handle::new_internal(JsObject(local))\n        }\n    }\n}\n\n/// The type of JavaScript\n/// [`Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)\n/// objects.\n///\n/// An array is any JavaScript value for which\n/// [`Array.isArray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray)\n/// would return `true`.\n///\n/// # Example\n///\n/// ```\n/// # use neon::prelude::*;\n/// # fn foo(mut cx: FunctionContext) -> JsResult<JsArray> {\n/// // Create a new empty array:\n/// let a: Handle<JsArray> = cx.empty_array();\n///\n/// // Push some values onto the array:\n/// a.prop(&mut cx, 0).set(17)?;\n/// a.prop(&mut cx, 1).set(\"hello\")?;\n/// # Ok(a)\n/// # }\n/// ```\n#[derive(Debug)]\n#[repr(transparent)]\npub struct JsArray(raw::Local);\n\nimpl JsArray {\n    /// Constructs a new empty array of length `len`, equivalent to the JavaScript\n    /// expression `new Array(len)`.\n    ///\n    /// Note that for non-zero `len`, this creates a\n    /// [sparse array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections#sparse_arrays),\n    /// which can sometimes have surprising behavior. To ensure that a new array\n    /// is and remains dense (i.e., not sparse), consider creating an empty array\n    /// with `JsArray::new(cx, 0)` or `cx.empty_array()` and only appending\n    /// elements to the end of the array.\n    ///\n    /// **See also:** [`Context::empty_array`]\n    pub fn new<'a, C: Context<'a>>(cx: &mut C, len: usize) -> Handle<'a, JsArray> {\n        JsArray::new_internal(cx.env(), len)\n    }\n\n    pub(crate) fn new_internal<'a>(env: Env, len: usize) -> Handle<'a, JsArray> {\n        unsafe {\n            let mut local: raw::Local = std::mem::zeroed();\n            sys::array::new(&mut local, env.to_raw(), len);\n            Handle::new_internal(JsArray(local))\n        }\n    }\n\n    /// Copies the array contents into a new [`Vec`] by iterating through all indices\n    /// from 0 to `self.len()`.\n    ///\n    /// The length is dynamically checked on each iteration in case the array is modified\n    /// during the computation.\n    pub fn to_vec<'a, C: Context<'a>>(&self, cx: &mut C) -> NeonResult<Vec<Handle<'a, JsValue>>> {\n        let mut result = Vec::with_capacity(self.len_inner(cx.env()) as usize);\n        let mut i = 0;\n        loop {\n            // Since getting a property can trigger arbitrary code,\n            // we have to re-check the length on every iteration.\n            if i >= self.len_inner(cx.env()) {\n                return Ok(result);\n            }\n            result.push(self.get(cx, i)?);\n            i += 1;\n        }\n    }\n\n    fn len_inner(&self, env: Env) -> u32 {\n        unsafe { sys::array::len(env.to_raw(), self.to_local()) }\n    }\n\n    #[allow(clippy::len_without_is_empty)]\n    /// Returns the length of the array, equivalent to the JavaScript expression\n    /// [`this.length`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/length).\n    pub fn len<'a, C: Context<'a>>(&self, cx: &mut C) -> u32 {\n        self.len_inner(cx.env())\n    }\n\n    /// Indicates whether the array is empty, equivalent to\n    /// `self.len() == 0`.\n    pub fn is_empty<'a, C: Context<'a>>(&self, cx: &mut C) -> bool {\n        self.len(cx) == 0\n    }\n}\n\nimpl Value for JsArray {}\n\nunsafe impl TransparentNoCopyWrapper for JsArray {\n    type Inner = raw::Local;\n\n    fn into_inner(self) -> Self::Inner {\n        self.0\n    }\n}\n\nimpl ValueInternal for JsArray {\n    fn name() -> &'static str {\n        \"Array\"\n    }\n\n    fn is_typeof<Other: Value>(cx: &mut Cx, other: &Other) -> bool {\n        unsafe { sys::tag::is_array(cx.env().to_raw(), other.to_local()) }\n    }\n\n    fn to_local(&self) -> raw::Local {\n        self.0\n    }\n\n    unsafe fn from_local(_env: Env, h: raw::Local) -> Self {\n        JsArray(h)\n    }\n}\n\nimpl Object for JsArray {}\n\n/// The type of JavaScript\n/// [`Function`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function)\n/// objects.\n#[derive(Debug)]\n#[repr(transparent)]\n///\n/// A `JsFunction` may come from an existing JavaScript function, for example\n/// by extracting it from the property of another object such as the\n/// [global object](crate::context::Context::global), or it may be defined in Rust\n/// with [`JsFunction::new()`](JsFunction::new).\n///\n/// ## Calling functions\n///\n/// Neon provides a convenient syntax for calling JavaScript functions with the\n/// [`bind()`](JsFunction::bind) method, which produces a [`BindOptions`](BindOptions)\n/// struct that can be used to provide the function arguments (and optionally, the binding for\n/// `this`) before calling the function:\n/// ```\n/// # use neon::prelude::*;\n/// # fn foo(mut cx: FunctionContext) -> JsResult<JsNumber> {\n/// // Extract the parseInt function from the global object\n/// let parse_int: Handle<JsFunction> = cx.global(\"parseInt\")?;\n///\n/// // Call parseInt(\"42\")\n/// let x: Handle<JsNumber> = parse_int\n///     .bind(&mut cx)\n///     .arg(\"42\")?\n///     .call()?;\n/// # Ok(x)\n/// # }\n/// ```\n///\n/// ## Calling functions as constructors\n///\n/// A `JsFunction` can be called as a constructor (like `new Array(16)` or\n/// `new URL(\"https://neon-bindings.com\")`) with the\n/// [`construct()`](BindOptions::construct) method:\n/// ```\n/// # use neon::prelude::*;\n/// # fn foo(mut cx: FunctionContext) -> JsResult<JsObject> {\n/// // Extract the URL constructor from the global object\n/// let url: Handle<JsFunction> = cx.global(\"URL\")?;\n///\n/// // Call new URL(\"https://neon-bindings.com\")\n/// let obj = url\n///     .bind(&mut cx)\n///     .arg(\"https://neon-bindings.com\")?\n///     .construct()?;\n/// # Ok(obj)\n/// # }\n/// ```\n///\n/// ## Defining functions\n///\n/// JavaScript functions can be defined in Rust with the\n/// [`JsFunction::new()`](JsFunction::new) constructor, which takes\n/// a Rust implementation function and produces a JavaScript function.\n///\n/// ```\n/// # use neon::prelude::*;\n/// // A function implementation that adds 1 to its first argument\n/// fn add1(mut cx: FunctionContext) -> JsResult<JsNumber> {\n///     let x: Handle<JsNumber> = cx.argument(0)?;\n///     let v = x.value(&mut cx);\n///     Ok(cx.number(v + 1.0))\n/// }\n///\n/// # fn foo(mut cx: FunctionContext) -> JsResult<JsFunction> {\n/// // Define a new JsFunction implemented with the add1 function\n/// let f = JsFunction::new(&mut cx, add1)?;\n/// # Ok(f)\n/// # }\n/// ```\npub struct JsFunction {\n    raw: raw::Local,\n}\n\nimpl Object for JsFunction {}\n\nimpl JsFunction {\n    #[cfg(not(feature = \"napi-5\"))]\n    /// Returns a new `JsFunction` implemented by `f`.\n    pub fn new<'a, C, U>(\n        cx: &mut C,\n        f: fn(FunctionContext) -> JsResult<U>,\n    ) -> JsResult<'a, JsFunction>\n    where\n        C: Context<'a>,\n        U: Value,\n    {\n        let name = any::type_name_of_val(&f);\n\n        Self::new_internal(cx, f, name)\n    }\n\n    #[cfg(feature = \"napi-5\")]\n    /// Returns a new `JsFunction` implemented by `f`.\n    pub fn new<'a, C, F, V>(cx: &mut C, f: F) -> JsResult<'a, JsFunction>\n    where\n        C: Context<'a>,\n        F: Fn(FunctionContext) -> JsResult<V> + 'static,\n        V: Value,\n    {\n        let name = any::type_name::<F>();\n\n        Self::new_internal(cx, f, name)\n    }\n\n    #[cfg(not(feature = \"napi-5\"))]\n    /// Returns a new `JsFunction` implemented by `f` with specified name\n    pub fn with_name<'a, C, U>(\n        cx: &mut C,\n        name: &str,\n        f: fn(FunctionContext) -> JsResult<U>,\n    ) -> JsResult<'a, JsFunction>\n    where\n        C: Context<'a>,\n        U: Value,\n    {\n        Self::new_internal(cx, f, name)\n    }\n\n    #[cfg(feature = \"napi-5\")]\n    /// Returns a new `JsFunction` implemented by `f` with specified name\n    pub fn with_name<'a, C, F, V>(cx: &mut C, name: &str, f: F) -> JsResult<'a, JsFunction>\n    where\n        C: Context<'a>,\n        F: Fn(FunctionContext) -> JsResult<V> + 'static,\n        V: Value,\n    {\n        Self::new_internal(cx, f, name)\n    }\n\n    fn new_internal<'a, C, F, V>(cx: &mut C, f: F, name: &str) -> JsResult<'a, JsFunction>\n    where\n        C: Context<'a>,\n        F: Fn(FunctionContext) -> JsResult<V> + 'static,\n        V: Value,\n    {\n        use std::panic::AssertUnwindSafe;\n        use std::ptr;\n\n        use crate::context::CallbackInfo;\n        use crate::types::error::convert_panics;\n\n        let f = move |env: raw::Env, info| {\n            let env = env.into();\n            let info = unsafe { CallbackInfo::new(info) };\n\n            FunctionContext::with(env, &info, |cx| {\n                convert_panics(env, AssertUnwindSafe(|| f(cx)))\n                    .map(|v| v.to_local())\n                    // We do not have a Js Value to return, most likely due to an exception.\n                    // If we are in a throwing state, constructing a Js Value would be invalid.\n                    // While not explicitly written, the Node-API documentation includes many examples\n                    // of returning `NULL` when a native function does not return a value.\n                    // https://nodejs.org/api/n-api.html#n_api_napi_create_function\n                    .unwrap_or_else(|_: Throw| ptr::null_mut())\n            })\n        };\n\n        unsafe {\n            if let Ok(raw) = sys::fun::new(cx.env().to_raw(), name, f) {\n                Ok(Handle::new_internal(JsFunction { raw }))\n            } else {\n                Err(Throw::new())\n            }\n        }\n    }\n}\n\nimpl JsFunction {\n    /// Calls this function.\n    ///\n    /// **See also:** [`JsFunction::bind`].\n    pub fn call<'a, 'b, C: Context<'a>, T, AS>(\n        &self,\n        cx: &mut C,\n        this: Handle<'b, T>,\n        args: AS,\n    ) -> JsResult<'a, JsValue>\n    where\n        T: Value,\n        AS: AsRef<[Handle<'b, JsValue>]>,\n    {\n        unsafe { self.try_call(cx, this, args) }\n    }\n\n    /// Calls this function for side effect, discarding its result.\n    ///\n    /// **See also:** [`JsFunction::bind`].\n    pub fn exec<'a, 'b, C: Context<'a>, T, AS>(\n        &self,\n        cx: &mut C,\n        this: Handle<'b, T>,\n        args: AS,\n    ) -> NeonResult<()>\n    where\n        T: Value,\n        AS: AsRef<[Handle<'b, JsValue>]>,\n    {\n        self.call(cx, this, args)?;\n        Ok(())\n    }\n\n    /// Calls this function as a constructor.\n    ///\n    /// **See also:** [`JsFunction::bind`].\n    pub fn construct<'a, 'b, C: Context<'a>, AS>(\n        &self,\n        cx: &mut C,\n        args: AS,\n    ) -> JsResult<'a, JsObject>\n    where\n        AS: AsRef<[Handle<'b, JsValue>]>,\n    {\n        let (argc, argv) = unsafe { prepare_call(cx, args.as_ref()) }?;\n        let env = cx.env().to_raw();\n        build(cx.env(), |out| unsafe {\n            sys::fun::construct(out, env, self.to_local(), argc, argv)\n        })\n    }\n}\n\nimpl JsFunction {\n    /// Create a [`BindOptions`] builder for calling this function.\n    ///\n    /// The builder methods make it convenient to assemble the call from parts:\n    /// ```\n    /// # use neon::prelude::*;\n    /// # fn foo(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    /// # let parse_int: Handle<JsFunction> = cx.global(\"parseInt\")?;\n    /// let x: f64 = parse_int\n    ///     .bind(&mut cx)\n    ///     .arg(\"42\")?\n    ///     .call()?;\n    /// # Ok(cx.number(x))\n    /// # }\n    /// ```\n    pub fn bind<'a, 'cx: 'a>(&self, cx: &'a mut Cx<'cx>) -> BindOptions<'a, 'cx> {\n        let callee = self.as_value(cx);\n        BindOptions {\n            cx,\n            callee,\n            this: None,\n            args: smallvec![],\n        }\n    }\n}\n\nimpl JsFunction {\n    /// Create a [`CallOptions`](function::CallOptions) for calling this function.\n    #[deprecated(since = \"TBD\", note = \"use `JsFunction::bind` instead\")]\n    pub fn call_with<'a, C: Context<'a>>(&self, _cx: &C) -> CallOptions<'a> {\n        CallOptions {\n            this: None,\n            // # Safety\n            // Only a single context may be used at a time because parent scopes\n            // are locked with `&mut self`. Therefore, the lifetime of `CallOptions`\n            // will always be the most narrow scope possible.\n            callee: Handle::new_internal(unsafe { self.clone() }),\n            args: smallvec![],\n        }\n    }\n\n    /// Create a [`ConstructOptions`](function::ConstructOptions) for calling this function\n    /// as a constructor.\n    #[deprecated(since = \"TBD\", note = \"use `JsFunction::bind` instead\")]\n    pub fn construct_with<'a, C: Context<'a>>(&self, _cx: &C) -> ConstructOptions<'a> {\n        ConstructOptions {\n            // # Safety\n            // Only a single context may be used at a time because parent scopes\n            // are locked with `&mut self`. Therefore, the lifetime of `ConstructOptions`\n            // will always be the most narrow scope possible.\n            callee: Handle::new_internal(unsafe { self.clone() }),\n            args: smallvec![],\n        }\n    }\n\n    /// # Safety\n    /// The caller must wrap in a `Handle` with an appropriate lifetime.\n    unsafe fn clone(&self) -> Self {\n        Self { raw: self.raw }\n    }\n}\n\nimpl Value for JsFunction {}\n\nunsafe impl TransparentNoCopyWrapper for JsFunction {\n    type Inner = raw::Local;\n\n    fn into_inner(self) -> Self::Inner {\n        self.raw\n    }\n}\n\nimpl ValueInternal for JsFunction {\n    fn name() -> &'static str {\n        \"function\"\n    }\n\n    fn is_typeof<Other: Value>(cx: &mut Cx, other: &Other) -> bool {\n        unsafe { sys::tag::is_function(cx.env().to_raw(), other.to_local()) }\n    }\n\n    fn to_local(&self) -> raw::Local {\n        self.raw\n    }\n\n    unsafe fn from_local(_env: Env, h: raw::Local) -> Self {\n        JsFunction { raw: h }\n    }\n}\n\n#[cfg(feature = \"napi-6\")]\n#[cfg_attr(docsrs, doc(cfg(feature = \"napi-6\")))]\n#[derive(Debug)]\n#[repr(transparent)]\n/// The type of JavaScript\n/// [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)\n/// values.\n///\n/// # Example\n///\n/// The following shows an example of adding two numbers that exceed\n/// [`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER).\n///\n/// ```\n/// # use neon::{prelude::*, types::JsBigInt};\n///\n/// fn add_bigint(mut cx: FunctionContext) -> JsResult<JsBigInt> {\n///     // Get references to the `BigInt` arguments\n///     let a = cx.argument::<JsBigInt>(0)?;\n///     let b = cx.argument::<JsBigInt>(1)?;\n///\n///     // Convert the `BigInt` to `i64`\n///     let a = a.to_i64(&mut cx)\n///         // On failure, convert err to a `RangeError` exception\n///         .or_throw(&mut cx)?;\n///\n///     let b = b.to_i64(&mut cx).or_throw(&mut cx)?;\n///     let sum = a + b;\n///\n///     // Create a `BigInt` from the `i64` sum\n///     Ok(JsBigInt::from_i64(&mut cx, sum))\n/// }\n/// ```\npub struct JsBigInt(raw::Local);\n"
  },
  {
    "path": "crates/neon/src/types_impl/private.rs",
    "content": "use std::{ffi::c_void, mem::MaybeUninit};\n\nuse crate::{\n    context::{\n        internal::{ContextInternal, Env},\n        Context, Cx,\n    },\n    handle::{internal::TransparentNoCopyWrapper, Handle},\n    result::{JsResult, NeonResult, Throw},\n    sys::{self, bindings as napi, raw},\n    types::Value,\n};\n\nuse super::JsValue;\n\n// Maximum number of function arguments in V8.\nconst V8_ARGC_LIMIT: usize = 65535;\n\npub(crate) unsafe fn prepare_call<'a, 'b, C: Context<'a>>(\n    cx: &mut C,\n    args: &[Handle<'b, JsValue>],\n) -> NeonResult<(usize, *const c_void)> {\n    // Note: This cast is only save because `Handle<'_, JsValue>` is\n    // guaranteed to have the same layout as a pointer because `Handle`\n    // and `JsValue` are both `repr(C)` newtypes.\n    let argv = args.as_ptr().cast();\n    let argc = args.len();\n    if argc > V8_ARGC_LIMIT {\n        return cx.throw_range_error(\"too many arguments\");\n    }\n    Ok((argc, argv))\n}\n\npub trait ValueInternal: TransparentNoCopyWrapper + 'static {\n    fn name() -> &'static str;\n\n    fn is_typeof<Other: Value>(cx: &mut Cx, other: &Other) -> bool;\n\n    fn downcast<Other: Value>(cx: &mut Cx, other: &Other) -> Option<Self> {\n        if Self::is_typeof(cx, other) {\n            // # Safety\n            // `is_typeof` check ensures this is the correct JavaScript type\n            Some(unsafe { Self::from_local(cx.env(), other.to_local()) })\n        } else {\n            None\n        }\n    }\n\n    fn cast<'a, T: Value, F: FnOnce(raw::Local) -> T>(self, f: F) -> Handle<'a, T> {\n        Handle::new_internal(f(self.to_local()))\n    }\n\n    fn to_local(&self) -> raw::Local;\n\n    // # Safety\n    // JavaScript value must be of type `Self`\n    unsafe fn from_local(env: Env, h: raw::Local) -> Self;\n\n    unsafe fn try_call<'a, 'b, C: Context<'a>, T, AS>(\n        &self,\n        cx: &mut C,\n        this: Handle<'b, T>,\n        args: AS,\n    ) -> JsResult<'a, JsValue>\n    where\n        T: Value,\n        AS: AsRef<[Handle<'b, JsValue>]>,\n    {\n        let callee = self.to_local();\n        let (argc, argv) = unsafe { prepare_call(cx, args.as_ref()) }?;\n        let env = cx.env();\n        let mut result: MaybeUninit<raw::Local> = MaybeUninit::zeroed();\n\n        let status = napi::call_function(\n            env.to_raw(),\n            this.to_local(),\n            callee,\n            argc,\n            argv.cast(),\n            result.as_mut_ptr(),\n        );\n\n        check_call_status(cx, callee, status)?;\n\n        Ok(Handle::new_internal(JsValue::from_local(\n            env,\n            result.assume_init(),\n        )))\n    }\n\n    unsafe fn try_construct<'a, 'b, C: Context<'a>, AS>(\n        &self,\n        cx: &mut C,\n        args: AS,\n    ) -> JsResult<'a, JsValue>\n    where\n        AS: AsRef<[Handle<'b, JsValue>]>,\n    {\n        let callee = self.to_local();\n        let (argc, argv) = unsafe { prepare_call(cx, args.as_ref()) }?;\n        let env = cx.env();\n        let mut result: MaybeUninit<raw::Local> = MaybeUninit::zeroed();\n        let status =\n            napi::new_instance(env.to_raw(), callee, argc, argv.cast(), result.as_mut_ptr());\n\n        check_call_status(cx, callee, status)?;\n\n        Ok(Handle::new_internal(JsValue::from_local(\n            env,\n            result.assume_init(),\n        )))\n    }\n}\n\nunsafe fn check_call_status<'a, C: Context<'a>>(\n    cx: &mut C,\n    callee: raw::Local,\n    status: Result<(), sys::Status>,\n) -> NeonResult<()> {\n    match status {\n        Err(sys::Status::InvalidArg) if !sys::tag::is_function(cx.env().to_raw(), callee) => {\n            return cx.throw_error(\"not a function\");\n        }\n        Err(sys::Status::PendingException) => {\n            return Err(Throw::new());\n        }\n        status => status.unwrap(),\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "crates/neon/src/types_impl/promise.rs",
    "content": "use std::ptr;\n\nuse crate::{\n    context::{\n        internal::{ContextInternal, Env},\n        Context, Cx,\n    },\n    handle::{internal::TransparentNoCopyWrapper, Handle},\n    object::Object,\n    result::JsResult,\n    sys::{self, no_panic::FailureBoundary, raw},\n    types::{private::ValueInternal, Value},\n};\n\n#[cfg(feature = \"napi-4\")]\nuse crate::{\n    event::{Channel, JoinHandle, SendError},\n    types::extract::TryIntoJs,\n};\n\n#[cfg(feature = \"napi-6\")]\nuse crate::{\n    lifecycle::{DropData, InstanceData},\n    sys::tsfn::ThreadsafeFunction,\n};\n\n#[cfg(all(feature = \"napi-5\", feature = \"futures\"))]\nuse {\n    crate::event::{JoinError, SendThrow},\n    crate::result::NeonResult,\n    crate::types::{JsFunction, JsValue},\n    std::future::Future,\n    std::pin::Pin,\n    std::sync::Mutex,\n    std::task::{self, Poll},\n    tokio::sync::oneshot,\n};\n\n#[cfg(any(feature = \"napi-6\", all(feature = \"napi-5\", feature = \"futures\")))]\nuse std::sync::Arc;\n\nconst BOUNDARY: FailureBoundary = FailureBoundary {\n    both: \"A panic and exception occurred while resolving a `neon::types::Deferred`\",\n    exception: \"An exception occurred while resolving a `neon::types::Deferred`\",\n    panic: \"A panic occurred while resolving a `neon::types::Deferred`\",\n};\n\n#[derive(Debug)]\n#[repr(transparent)]\n/// The type of JavaScript\n/// [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)\n/// objects.\n///\n/// [`JsPromise`] instances may be constructed with [`Context::promise`], which\n/// produces both a promise and a [`Deferred`], which can be used to control\n/// the behavior of the promise. A `Deferred` struct is similar to the `resolve`\n/// and `reject` functions produced by JavaScript's standard\n/// [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise)\n/// constructor:\n///\n/// ```javascript\n/// let deferred;\n/// let promise = new Promise((resolve, reject) => {\n///   deferred = { resolve, reject };\n/// });\n/// ```\n///\n/// # Example\n///\n/// ```\n/// # use neon::prelude::*;\n/// fn resolve_promise(mut cx: FunctionContext) -> JsResult<JsPromise> {\n///     let (deferred, promise) = cx.promise();\n///     let msg = cx.string(\"Hello, World!\");\n///\n///     deferred.resolve(&mut cx, msg);\n///\n///     Ok(promise)\n/// }\n/// ```\n///\n/// # Example: Asynchronous task\n///\n/// This example uses the [linkify](https://crates.io/crates/linkify) crate in an\n/// asynchronous task, i.e. a\n/// [Node worker pool](https://nodejs.org/en/docs/guides/dont-block-the-event-loop/)\n/// thread, to find all the links in a text string.\n///\n/// Alternate implementations might use a custom Rust thread or thread pool to avoid\n/// blocking the worker pool; for more information, see the [`JsFuture`] example.\n///\n/// ```\n/// # use neon::prelude::*;\n/// use linkify::{LinkFinder, LinkKind};\n/// # #[cfg(feature = \"doc-dependencies\")]\n/// use easy_cast::Cast; // for safe numerical conversions\n///\n/// # #[cfg(feature = \"doc-dependencies\")]\n/// fn linkify(mut cx: FunctionContext) -> JsResult<JsPromise> {\n///     let text = cx.argument::<JsString>(0)?.value(&mut cx);\n///\n///     let promise = cx\n///         .task(move || {\n///             let (indices, kinds): (Vec<_>, Vec<_>) = LinkFinder::new()\n///                 // The spans() method fully partitions the text\n///                 // into a sequence of contiguous spans, some of which\n///                 // are plain text and some of which are links.\n///                 .spans(&text)\n///                 .map(|span| {\n///                     // The first span starts at 0 and the rest start\n///                     // at their preceding span's end index.\n///                     let end: u32 = span.end().cast();\n///\n///                     let kind: u8 = match span.kind() {\n///                         Some(LinkKind::Url) => 1,\n///                         Some(LinkKind::Email) => 2,\n///                         _ => 0,\n///                     };\n///\n///                     (end, kind)\n///                 })\n///                 .unzip();\n///             (indices, kinds)\n///         })\n///         .promise(|mut cx, (indices, kinds)| {\n///             let indices = JsUint32Array::from_slice(&mut cx, &indices)?;\n///             let kinds = JsUint8Array::from_slice(&mut cx, &kinds)?;\n///             Ok(cx.empty_object()\n///                 .prop(&mut cx, \"indices\")\n///                 .set(indices)?\n///                 .prop(\"kinds\")\n///                 .set(kinds)?\n///                 .this())\n///         });\n///\n///     Ok(promise)\n/// }\n/// ```\npub struct JsPromise(raw::Local);\n\nimpl JsPromise {\n    pub(crate) fn new<'a, C: Context<'a>>(cx: &mut C) -> (Deferred, Handle<'a, Self>) {\n        let (deferred, promise) = unsafe { sys::promise::create(cx.env().to_raw()) };\n        let deferred = Deferred {\n            internal: Some(NodeApiDeferred(deferred)),\n            #[cfg(feature = \"napi-6\")]\n            drop_queue: InstanceData::drop_queue(cx),\n        };\n\n        (deferred, Handle::new_internal(JsPromise(promise)))\n    }\n\n    /// Creates a new `Promise` immediately resolved with the given value. If the value is a\n    /// `Promise` or a then-able, it will be flattened.\n    ///\n    /// `JsPromise::resolve` is useful to ensure a value that might not be a `Promise` or\n    /// might not be a native promise is converted to a `Promise` before use.\n    pub fn resolve<'a, C: Context<'a>, T: Value>(cx: &mut C, value: Handle<T>) -> Handle<'a, Self> {\n        let (deferred, promise) = cx.promise();\n        deferred.resolve(cx, value);\n        promise\n    }\n\n    /// Creates a nwe `Promise` immediately rejected with the given error.\n    pub fn reject<'a, C: Context<'a>, E: Value>(cx: &mut C, err: Handle<E>) -> Handle<'a, Self> {\n        let (deferred, promise) = cx.promise();\n        deferred.reject(cx, err);\n        promise\n    }\n\n    #[cfg(all(feature = \"napi-5\", feature = \"futures\"))]\n    #[cfg_attr(docsrs, doc(cfg(all(feature = \"napi-5\", feature = \"futures\"))))]\n    /// Creates a [`Future`](std::future::Future) that can be awaited to receive the result of a\n    /// JavaScript `Promise`.\n    ///\n    /// A callback must be provided that maps a `Result` representing the resolution or rejection of\n    /// the `Promise` and returns a value as the `Future` output.\n    ///\n    /// _Note_: Unlike `Future`, `Promise` are eagerly evaluated and so are `JsFuture`.\n    pub fn to_future<'a, O, C, F>(&self, cx: &mut C, f: F) -> NeonResult<JsFuture<O>>\n    where\n        O: Send + 'static,\n        C: Context<'a>,\n        F: FnOnce(Cx, Result<Handle<JsValue>, Handle<JsValue>>) -> NeonResult<O> + Send + 'static,\n    {\n        let then = self.get::<JsFunction, _, _>(cx, \"then\")?;\n\n        let (tx, rx) = oneshot::channel();\n        let take_state = {\n            // Note: If this becomes a bottleneck, `unsafe` could be used to avoid it.\n            // The promise spec guarantees that it will only be used once.\n            let state = Arc::new(Mutex::new(Some((f, tx))));\n\n            move || {\n                state\n                    .lock()\n                    .ok()\n                    .and_then(|mut lock| lock.take())\n                    // This should never happen because `self` is a native `Promise`\n                    // and settling multiple times is a violation of the spec.\n                    .expect(\"Attempted to settle JsFuture multiple times\")\n            }\n        };\n\n        let resolve = JsFunction::new(cx, {\n            let take_state = take_state.clone();\n\n            move |mut cx| {\n                let (f, tx) = take_state();\n                let v = cx.argument::<JsValue>(0)?;\n\n                Cx::with_context(cx.env(), move |cx| {\n                    // Error indicates that the `Future` has already dropped; ignore\n                    let _ = tx.send(f(cx, Ok(v)).map_err(Into::into));\n                });\n\n                Ok(cx.undefined())\n            }\n        })?;\n\n        let reject = JsFunction::new(cx, {\n            move |mut cx| {\n                let (f, tx) = take_state();\n                let v = cx.argument::<JsValue>(0)?;\n\n                Cx::with_context(cx.env(), move |cx| {\n                    // Error indicates that the `Future` has already dropped; ignore\n                    let _ = tx.send(f(cx, Err(v)).map_err(Into::into));\n                });\n\n                Ok(cx.undefined())\n            }\n        })?;\n\n        then.exec(\n            cx,\n            Handle::new_internal(Self(self.0)),\n            [resolve.upcast(), reject.upcast()],\n        )?;\n\n        Ok(JsFuture { rx })\n    }\n}\n\nunsafe impl TransparentNoCopyWrapper for JsPromise {\n    type Inner = raw::Local;\n\n    fn into_inner(self) -> Self::Inner {\n        self.0\n    }\n}\n\nimpl ValueInternal for JsPromise {\n    fn name() -> &'static str {\n        \"Promise\"\n    }\n\n    fn is_typeof<Other: Value>(cx: &mut Cx, other: &Other) -> bool {\n        unsafe { sys::tag::is_promise(cx.env().to_raw(), other.to_local()) }\n    }\n\n    fn to_local(&self) -> raw::Local {\n        self.0\n    }\n\n    unsafe fn from_local(_env: Env, h: raw::Local) -> Self {\n        Self(h)\n    }\n}\n\nimpl Value for JsPromise {}\n\nimpl Object for JsPromise {}\n\n/// A controller struct that can be used to resolve or reject a [`JsPromise`].\n///\n/// It is recommended to settle a [`Deferred`] with [`Deferred::settle_with`] to ensure\n/// exceptions are caught.\n///\n/// On Node-API versions less than 6, dropping a [`Deferred`] without settling will\n/// cause a panic. On Node-API 6+, the associated [`JsPromise`] will be automatically\n/// rejected.\n///\n/// # Examples\n///\n/// See [`JsPromise`], [`JsFuture`].\npub struct Deferred {\n    internal: Option<NodeApiDeferred>,\n    #[cfg(feature = \"napi-6\")]\n    drop_queue: Arc<ThreadsafeFunction<DropData>>,\n}\n\nimpl Deferred {\n    /// Resolve a [`JsPromise`] with a JavaScript value\n    pub fn resolve<'a, V, C>(self, cx: &mut C, value: Handle<V>)\n    where\n        V: Value,\n        C: Context<'a>,\n    {\n        unsafe {\n            sys::promise::resolve(cx.env().to_raw(), self.into_inner(), value.to_local());\n        }\n    }\n\n    /// Reject a [`JsPromise`] with a JavaScript value\n    pub fn reject<'a, V, C>(self, cx: &mut C, value: Handle<V>)\n    where\n        V: Value,\n        C: Context<'a>,\n    {\n        unsafe {\n            sys::promise::reject(cx.env().to_raw(), self.into_inner(), value.to_local());\n        }\n    }\n\n    #[cfg(feature = \"napi-4\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"napi-4\")))]\n    /// Settle the [`JsPromise`] by sending a closure across a [`Channel`][`crate::event::Channel`]\n    /// to be executed on the main JavaScript thread.\n    ///\n    /// Usage is identical to [`Deferred::settle_with`].\n    ///\n    /// Returns a [`SendError`][crate::event::SendError] if sending the closure to the main JavaScript thread fails.\n    /// See [`Channel::try_send`][crate::event::Channel::try_send] for more details.\n    pub fn try_settle_with<V, F>(\n        self,\n        channel: &Channel,\n        complete: F,\n    ) -> Result<JoinHandle<()>, SendError>\n    where\n        V: Value,\n        F: FnOnce(Cx) -> JsResult<V> + Send + 'static,\n    {\n        channel.try_send(move |cx| {\n            self.try_catch_settle(cx, complete);\n            Ok(())\n        })\n    }\n\n    #[cfg(feature = \"napi-4\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"napi-4\")))]\n    /// Settle the [`JsPromise`] by sending a closure across a [`Channel`][crate::event::Channel]\n    /// to be executed on the main JavaScript thread.\n    ///\n    /// Panics if there is a libuv error.\n    ///\n    /// ```\n    /// # use neon::prelude::*;\n    /// # fn example(mut cx: FunctionContext) -> JsResult<JsPromise> {\n    /// let channel = cx.channel();\n    /// let (deferred, promise) = cx.promise();\n    ///\n    /// deferred.settle_with(&channel, move |mut cx| Ok(cx.number(42)));\n    ///\n    /// # Ok(promise)\n    /// # }\n    /// ```\n    pub fn settle_with<V, F>(self, channel: &Channel, complete: F) -> JoinHandle<()>\n    where\n        V: Value,\n        F: FnOnce(Cx) -> JsResult<V> + Send + 'static,\n    {\n        self.try_settle_with(channel, complete).unwrap()\n    }\n\n    #[cfg(feature = \"napi-4\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"napi-4\")))]\n    /// Settle the [`JsPromise`] by sending a type that implements [`TryIntoJs`] to the main JavaScript thread.\n    ///\n    /// Usage is identical to [`Deferred::settle`].\n    ///\n    /// Returns a [`SendError`][crate::event::SendError] if sending the closure to the main JavaScript thread fails.\n    /// See [`Channel::try_send`][crate::event::Channel::try_send] for more details.\n    pub fn try_settle<V, T>(self, channel: &Channel, v: T) -> Result<JoinHandle<()>, SendError>\n    where\n        for<'cx> T: TryIntoJs<'cx, Value = V> + Send + 'static,\n        V: Value,\n    {\n        self.try_settle_with::<V, _>(channel, move |mut cx| v.try_into_js(&mut cx))\n    }\n\n    #[cfg(feature = \"napi-4\")]\n    #[cfg_attr(docsrs, doc(cfg(feature = \"napi-4\")))]\n    /// Settle the [`JsPromise`] by sending a type that implements [`TryIntoJs`] to the main JavaScript thread.\n    ///\n    /// Panics if there is a libuv error.\n    ///\n    /// ```\n    /// # use neon::prelude::*;\n    /// # fn example(mut cx: FunctionContext) -> JsResult<JsPromise> {\n    /// let channel = cx.channel();\n    /// let (deferred, promise) = cx.promise();\n    ///\n    /// deferred.settle(&channel, 42f64);\n    ///\n    /// # Ok(promise)\n    /// # }\n    /// ```\n    pub fn settle<V, T>(self, channel: &Channel, v: T) -> JoinHandle<()>\n    where\n        for<'cx> T: TryIntoJs<'cx, Value = V> + Send + 'static,\n        V: Value,\n    {\n        self.try_settle(channel, v).unwrap()\n    }\n\n    pub(crate) fn try_catch_settle<'a, C, V, F>(self, cx: C, f: F)\n    where\n        C: Context<'a>,\n        V: Value,\n        F: FnOnce(C) -> JsResult<'a, V>,\n    {\n        unsafe {\n            BOUNDARY.catch_failure(\n                cx.env().to_raw(),\n                Some(self.into_inner()),\n                move |_| match f(cx) {\n                    Ok(value) => value.to_local(),\n                    Err(_) => ptr::null_mut(),\n                },\n            );\n        }\n    }\n\n    pub(crate) fn into_inner(mut self) -> sys::Deferred {\n        self.internal.take().unwrap().0\n    }\n}\n\n#[repr(transparent)]\npub(crate) struct NodeApiDeferred(sys::Deferred);\n\nunsafe impl Send for NodeApiDeferred {}\n\n#[cfg(feature = \"napi-6\")]\nimpl NodeApiDeferred {\n    pub(crate) unsafe fn leaked(self, env: raw::Env) {\n        sys::promise::reject_err_message(\n            env,\n            self.0,\n            \"`neon::types::Deferred` was dropped without being settled\",\n        );\n    }\n}\n\nimpl Drop for Deferred {\n    #[cfg(not(feature = \"napi-6\"))]\n    fn drop(&mut self) {\n        // If `None`, the `Deferred` has already been settled\n        if self.internal.is_none() {\n            return;\n        }\n\n        // Destructors are called during stack unwinding, prevent a double\n        // panic and instead prefer to leak.\n        if std::thread::panicking() {\n            eprintln!(\"Warning: neon::types::JsPromise leaked during a panic\");\n            return;\n        }\n\n        // Only panic if the event loop is still running\n        if let Ok(true) = crate::context::internal::IS_RUNNING.try_with(|v| *v.borrow()) {\n            panic!(\"Must settle a `neon::types::JsPromise` with `neon::types::Deferred`\");\n        }\n    }\n\n    #[cfg(feature = \"napi-6\")]\n    fn drop(&mut self) {\n        // If `None`, the `Deferred` has already been settled\n        if let Some(internal) = self.internal.take() {\n            let _ = self.drop_queue.call(DropData::Deferred(internal), None);\n        }\n    }\n}\n\n#[cfg(all(feature = \"napi-5\", feature = \"futures\"))]\n#[cfg_attr(docsrs, doc(cfg(all(feature = \"napi-5\", feature = \"futures\"))))]\n/// A type of JavaScript\n/// [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)\n/// object that acts as a [`Future`](std::future::Future).\n///\n/// Unlike typical `Future` implementations, `JsFuture`s are eagerly executed\n/// because they are backed by a `Promise`.\n///\n/// # Example\n///\n/// This example uses a `JsFuture` to take asynchronous binary data and perform\n/// potentially expensive computations on that data in a Rust thread.\n///\n/// The example uses a [Tokio](https://tokio.rs) thread pool (allocated and\n/// stored on demand with a [`OnceCell`](https://crates.io/crates/once_cell))\n/// to run the computations.\n///\n/// ```\n/// # use neon::prelude::*;\n/// use neon::types::buffer::TypedArray;\n/// use once_cell::sync::OnceCell;\n/// use tokio::runtime::Runtime;\n///\n/// // Lazily allocate a Tokio runtime to use as the thread pool.\n/// fn runtime(cx: &mut Cx) -> NeonResult<&'static Runtime> {\n///     static RUNTIME: OnceCell<Runtime> = OnceCell::new();\n///\n///     RUNTIME\n///         .get_or_try_init(Runtime::new)\n///         .or_else(|err| cx.throw_error(&err.to_string()))\n/// }\n///\n/// // async_compute: Promise<Float64Array> -> Promise<number>\n/// //\n/// // Takes a promise that produces a typed array and returns a promise that:\n/// // - awaits the typed array from the original promise;\n/// // - computes a value from the contents of the array in a background thread; and\n/// // - resolves once the computation is completed\n/// pub fn async_compute(mut cx: FunctionContext) -> JsResult<JsPromise> {\n///     let nums: Handle<JsPromise> = cx.argument(0)?;\n///\n///     // Convert the JS Promise to a Rust Future for use in a compute thread.\n///     let nums = nums.to_future(&mut cx, |mut cx, result| {\n///         // Get the promise's result value (or throw if it was rejected).\n///         let value = result.or_throw(&mut cx)?;\n///\n///         // Downcast the result value to a Float64Array.\n///         let array: Handle<JsFloat64Array> = value.downcast_or_throw(&mut cx)?;\n///\n///         // Convert the typed array to a Rust vector.\n///         let vec = array.as_slice(&cx).to_vec();\n///         Ok(vec)\n///     })?;\n///\n///     // Construct a result promise which will be fulfilled when the computation completes.\n///     let (deferred, promise) = cx.promise();\n///     let channel = cx.channel();\n///     let runtime = runtime(&mut cx)?;\n///\n///     // Perform the computation in a background thread using the Tokio thread pool.\n///     runtime.spawn(async move {\n///         // Await the JsFuture, which yields Result<Vec<f64>, JoinError>.\n///         let result = match nums.await {\n///             // Perform the computation. In this example, we just calculate the sum\n///             // of all values in the array; more involved examples might be running\n///             // compression or decompression algorithms, encoding or decoding media\n///             // codecs, image filters or other media transformations, etc.\n///             Ok(nums) => Ok(nums.into_iter().sum::<f64>()),\n///             Err(err) => Err(err)\n///         };\n///     \n///         // Resolve the result promise with the result of the computation.\n///         deferred.settle_with(&channel, |mut cx| {\n///             let result = result.or_throw(&mut cx)?;\n///             Ok(cx.number(result))\n///         });\n///     });\n///\n///     Ok(promise)\n/// }\n/// ```\npub struct JsFuture<T> {\n    // `Err` is always `Throw`, but `Throw` cannot be sent across threads\n    rx: oneshot::Receiver<Result<T, SendThrow>>,\n}\n\n#[cfg(all(feature = \"napi-5\", feature = \"futures\"))]\n#[cfg_attr(docsrs, doc(cfg(all(feature = \"napi-5\", feature = \"futures\"))))]\nimpl<T> Future for JsFuture<T> {\n    type Output = Result<T, JoinError>;\n\n    fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context) -> Poll<Self::Output> {\n        match Pin::new(&mut self.rx).poll(cx) {\n            Poll::Ready(result) => {\n                // Flatten `Result<Result<T, SendThrow>, RecvError>` by mapping to\n                // `Result<T, JoinError>`. This can be simplified by replacing the\n                // closure with a try-block after stabilization.\n                // https://doc.rust-lang.org/beta/unstable-book/language-features/try-blocks.html\n                let get_result = move || Ok(result??);\n\n                Poll::Ready(get_result())\n            }\n            Poll::Pending => Poll::Pending,\n        }\n    }\n}\n"
  },
  {
    "path": "crates/neon/src/types_impl/utf8.rs",
    "content": "use std::borrow::Cow;\n\nconst SMALL_MAX: usize = i32::MAX as usize;\n\n/// V8 APIs that take UTF-8 strings take their length in the form of 32-bit\n/// signed integers. This type represents a UTF-8 string that contains no\n/// more than `i32::MAX` bytes of code units.\npub struct SmallUtf8<'a> {\n    contents: Cow<'a, str>,\n}\n\nimpl<'a> SmallUtf8<'a> {\n    pub fn lower(&self) -> (*const u8, i32) {\n        (self.contents.as_ptr(), self.contents.len() as i32)\n    }\n}\n\n/// A UTF-8 string that can be lowered to a representation usable for V8\n/// APIs.\npub struct Utf8<'a> {\n    contents: Cow<'a, str>,\n}\n\nimpl<'a> From<&'a str> for Utf8<'a> {\n    fn from(s: &'a str) -> Self {\n        Utf8 {\n            contents: Cow::from(s),\n        }\n    }\n}\n\nimpl<'a> Utf8<'a> {\n    pub fn size(&self) -> usize {\n        self.contents.len()\n    }\n\n    pub fn into_small(self) -> Option<SmallUtf8<'a>> {\n        if self.size() < SMALL_MAX {\n            Some(SmallUtf8 {\n                contents: self.contents,\n            })\n        } else {\n            None\n        }\n    }\n\n    pub fn into_small_unwrap(self) -> SmallUtf8<'a> {\n        let size = self.size();\n        self.into_small().unwrap_or_else(|| {\n            panic!(\"{size} >= i32::MAX\");\n        })\n    }\n\n    pub fn truncate(self) -> SmallUtf8<'a> {\n        let size = self.size();\n        let mut contents = self.contents;\n\n        if size >= SMALL_MAX {\n            let s: &mut String = contents.to_mut();\n            s.truncate(SMALL_MAX - 3);\n            s.push_str(\"...\");\n        }\n\n        SmallUtf8 { contents }\n    }\n}\n"
  },
  {
    "path": "crates/neon-macros/Cargo.toml",
    "content": "[package]\nname = \"neon-macros\"\nversion = \"1.1.1\"\nauthors = [\"Dave Herman <david.herman@gmail.com>\"]\ndescription = \"Procedural macros supporting Neon\"\nrepository = \"https://github.com/neon-bindings/neon\"\nlicense = \"MIT/Apache-2.0\"\nedition = \"2021\"\n\n[lib]\nproc-macro = true\n\n[dependencies]\nproc-macro2 = \"1.0.79\"\nquote = \"1.0.33\"\nsyn = { version = \"2.0.57\", features = [\"full\"] }\n"
  },
  {
    "path": "crates/neon-macros/LICENSE-APACHE",
    "content": "                              Apache License\n                        Version 2.0, January 2004\n                     http://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n   \"License\" shall mean the terms and conditions for use, reproduction,\n   and distribution as defined by Sections 1 through 9 of this document.\n\n   \"Licensor\" shall mean the copyright owner or entity authorized by\n   the copyright owner that is granting the License.\n\n   \"Legal Entity\" shall mean the union of the acting entity and all\n   other entities that control, are controlled by, or are under common\n   control with that entity. For the purposes of this definition,\n   \"control\" means (i) the power, direct or indirect, to cause the\n   direction or management of such entity, whether by contract or\n   otherwise, or (ii) ownership of fifty percent (50%) or more of the\n   outstanding shares, or (iii) beneficial ownership of such entity.\n\n   \"You\" (or \"Your\") shall mean an individual or Legal Entity\n   exercising permissions granted by this License.\n\n   \"Source\" form shall mean the preferred form for making modifications,\n   including but not limited to software source code, documentation\n   source, and configuration files.\n\n   \"Object\" form shall mean any form resulting from mechanical\n   transformation or translation of a Source form, including but\n   not limited to compiled object code, generated documentation,\n   and conversions to other media types.\n\n   \"Work\" shall mean the work of authorship, whether in Source or\n   Object form, made available under the License, as indicated by a\n   copyright notice that is included in or attached to the work\n   (an example is provided in the Appendix below).\n\n   \"Derivative Works\" shall mean any work, whether in Source or Object\n   form, that is based on (or derived from) the Work and for which the\n   editorial revisions, annotations, elaborations, or other modifications\n   represent, as a whole, an original work of authorship. For the purposes\n   of this License, Derivative Works shall not include works that remain\n   separable from, or merely link (or bind by name) to the interfaces of,\n   the Work and Derivative Works thereof.\n\n   \"Contribution\" shall mean any work of authorship, including\n   the original version of the Work and any modifications or additions\n   to that Work or Derivative Works thereof, that is intentionally\n   submitted to Licensor for inclusion in the Work by the copyright owner\n   or by an individual or Legal Entity authorized to submit on behalf of\n   the copyright owner. For the purposes of this definition, \"submitted\"\n   means any form of electronic, verbal, or written communication sent\n   to the Licensor or its representatives, including but not limited to\n   communication on electronic mailing lists, source code control systems,\n   and issue tracking systems that are managed by, or on behalf of, the\n   Licensor for the purpose of discussing and improving the Work, but\n   excluding communication that is conspicuously marked or otherwise\n   designated in writing by the copyright owner as \"Not a Contribution.\"\n\n   \"Contributor\" shall mean Licensor and any individual or Legal Entity\n   on behalf of whom a Contribution has been received by Licensor and\n   subsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   copyright license to reproduce, prepare Derivative Works of,\n   publicly display, publicly perform, sublicense, and distribute the\n   Work and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   (except as stated in this section) patent license to make, have made,\n   use, offer to sell, sell, import, and otherwise transfer the Work,\n   where such license applies only to those patent claims licensable\n   by such Contributor that are necessarily infringed by their\n   Contribution(s) alone or by combination of their Contribution(s)\n   with the Work to which such Contribution(s) was submitted. If You\n   institute patent litigation against any entity (including a\n   cross-claim or counterclaim in a lawsuit) alleging that the Work\n   or a Contribution incorporated within the Work constitutes direct\n   or contributory patent infringement, then any patent licenses\n   granted to You under this License for that Work shall terminate\n   as of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\n   Work or Derivative Works thereof in any medium, with or without\n   modifications, and in Source or Object form, provided that You\n   meet the following conditions:\n\n   (a) You must give any other recipients of the Work or\n       Derivative Works a copy of this License; and\n\n   (b) You must cause any modified files to carry prominent notices\n       stating that You changed the files; and\n\n   (c) You must retain, in the Source form of any Derivative Works\n       that You distribute, all copyright, patent, trademark, and\n       attribution notices from the Source form of the Work,\n       excluding those notices that do not pertain to any part of\n       the Derivative Works; and\n\n   (d) If the Work includes a \"NOTICE\" text file as part of its\n       distribution, then any Derivative Works that You distribute must\n       include a readable copy of the attribution notices contained\n       within such NOTICE file, excluding those notices that do not\n       pertain to any part of the Derivative Works, in at least one\n       of the following places: within a NOTICE text file distributed\n       as part of the Derivative Works; within the Source form or\n       documentation, if provided along with the Derivative Works; or,\n       within a display generated by the Derivative Works, if and\n       wherever such third-party notices normally appear. The contents\n       of the NOTICE file are for informational purposes only and\n       do not modify the License. You may add Your own attribution\n       notices within Derivative Works that You distribute, alongside\n       or as an addendum to the NOTICE text from the Work, provided\n       that such additional attribution notices cannot be construed\n       as modifying the License.\n\n   You may add Your own copyright statement to Your modifications and\n   may provide additional or different license terms and conditions\n   for use, reproduction, or distribution of Your modifications, or\n   for any such Derivative Works as a whole, provided Your use,\n   reproduction, and distribution of the Work otherwise complies with\n   the conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\n   any Contribution intentionally submitted for inclusion in the Work\n   by You to the Licensor shall be under the terms and conditions of\n   this License, without any additional terms or conditions.\n   Notwithstanding the above, nothing herein shall supersede or modify\n   the terms of any separate license agreement you may have executed\n   with Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\n   names, trademarks, service marks, or product names of the Licensor,\n   except as required for reasonable and customary use in describing the\n   origin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\n   agreed to in writing, Licensor provides the Work (and each\n   Contributor provides its Contributions) on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n   implied, including, without limitation, any warranties or conditions\n   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n   PARTICULAR PURPOSE. You are solely responsible for determining the\n   appropriateness of using or redistributing the Work and assume any\n   risks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\n   whether in tort (including negligence), contract, or otherwise,\n   unless required by applicable law (such as deliberate and grossly\n   negligent acts) or agreed to in writing, shall any Contributor be\n   liable to You for damages, including any direct, indirect, special,\n   incidental, or consequential damages of any character arising as a\n   result of this License or out of the use or inability to use the\n   Work (including but not limited to damages for loss of goodwill,\n   work stoppage, computer failure or malfunction, or any and all\n   other commercial damages or losses), even if such Contributor\n   has been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\n   the Work or Derivative Works thereof, You may choose to offer,\n   and charge a fee for, acceptance of support, warranty, indemnity,\n   or other liability obligations and/or rights consistent with this\n   License. However, in accepting such obligations, You may act only\n   on Your own behalf and on Your sole responsibility, not on behalf\n   of any other Contributor, and only if You agree to indemnify,\n   defend, and hold each Contributor harmless for any liability\n   incurred by, or claims asserted against, such Contributor by reason\n   of your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work.\n\n   To apply the Apache License to your work, attach the following\n   boilerplate notice, with the fields enclosed by brackets \"[]\"\n   replaced with your own identifying information. (Don't include\n   the brackets!)  The text should be enclosed in the appropriate\n   comment syntax for the file format. We also recommend that a\n   file or class name and description of purpose be included on the\n   same \"printed page\" as the copyright notice for easier\n   identification within third-party archives.\n\nCopyright [yyyy] [name of copyright owner]\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n"
  },
  {
    "path": "crates/neon-macros/LICENSE-MIT",
    "content": "Copyright (c) 2015 David Herman\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "crates/neon-macros/src/class/meta.rs",
    "content": "#[derive(Default)]\npub(crate) struct Meta {\n    pub(super) kind: Kind,\n    pub(super) name: Option<syn::LitStr>,\n    pub(super) json: bool,\n    pub(super) context: bool,\n    pub(super) this: bool,\n}\n\n#[derive(Default)]\npub(super) enum Kind {\n    Async,\n    AsyncFn,\n    #[default]\n    Normal,\n    Task,\n}\n\n// Property metadata structure (simpler than method metadata)\n#[derive(Default)]\npub(crate) struct PropertyMeta {\n    pub(super) name: Option<syn::LitStr>,\n    pub(super) json: bool,\n}\n\npub(crate) struct PropertyParser;\n\nimpl syn::parse::Parser for PropertyParser {\n    type Output = PropertyMeta;\n\n    fn parse2(self, tokens: proc_macro2::TokenStream) -> syn::Result<Self::Output> {\n        let mut attr = PropertyMeta::default();\n        let parser = syn::meta::parser(|meta: syn::meta::ParseNestedMeta<'_>| {\n            if meta.path.is_ident(\"name\") {\n                attr.name = Some(meta.value()?.parse::<syn::LitStr>()?);\n                return Ok(());\n            }\n\n            if meta.path.is_ident(\"json\") {\n                attr.json = true;\n                return Ok(());\n            }\n\n            // Properties don't support method-specific attributes\n            if meta.path.is_ident(\"async\")\n                || meta.path.is_ident(\"task\")\n                || meta.path.is_ident(\"context\")\n                || meta.path.is_ident(\"this\")\n            {\n                return Err(meta.error(\"attribute not supported on const properties\"));\n            }\n\n            Err(meta.error(\"unsupported property attribute\"))\n        });\n\n        parser.parse2(tokens)?;\n\n        Ok(attr)\n    }\n}\n\n// Parser that preserves existing metadata (like async detection)\npub(crate) struct Parser(pub(crate) Meta);\n\nimpl syn::parse::Parser for Parser {\n    type Output = Meta;\n\n    fn parse2(self, tokens: proc_macro2::TokenStream) -> syn::Result<Self::Output> {\n        let Parser(mut attr) = self;\n        let parser = syn::meta::parser(|meta: syn::meta::ParseNestedMeta<'_>| {\n            if meta.path.is_ident(\"name\") {\n                attr.name = Some(meta.value()?.parse::<syn::LitStr>()?);\n                return Ok(());\n            }\n\n            if meta.path.is_ident(\"json\") {\n                attr.json = true;\n                return Ok(());\n            }\n\n            if meta.path.is_ident(\"context\") {\n                attr.context = true;\n                return Ok(());\n            }\n\n            if meta.path.is_ident(\"this\") {\n                attr.this = true;\n                return Ok(());\n            }\n\n            if meta.path.is_ident(\"async\") {\n                if matches!(attr.kind, Kind::AsyncFn) {\n                    return Err(\n                        meta.error(\"`async` attribute should not be used with an `async fn`\")\n                    );\n                }\n                attr.kind = Kind::Async;\n                return Ok(());\n            }\n\n            if meta.path.is_ident(\"task\") {\n                attr.kind = Kind::Task;\n                return Ok(());\n            }\n\n            Err(meta.error(\"unsupported property\"))\n        });\n\n        parser.parse2(tokens)?;\n\n        Ok(attr)\n    }\n}\n"
  },
  {
    "path": "crates/neon-macros/src/class/mod.rs",
    "content": "mod meta;\n\nuse super::name::is_valid_js_identifier;\nuse proc_macro2::TokenStream;\nuse syn::{spanned::Spanned, Ident, ImplItemFn, Type};\n\nstruct ClassItems {\n    consts: Vec<syn::ImplItemConst>,\n    fns: Vec<syn::ImplItemFn>,\n    constructor: Option<syn::ImplItemFn>,\n    has_finalizer: bool,\n}\n\n// Check if a method receiver is mutable (&mut self)\nfn is_receiver_mutable(sig: &syn::Signature) -> bool {\n    if let Some(syn::FnArg::Receiver(receiver)) = sig.inputs.first() {\n        receiver.mutability.is_some()\n    } else {\n        false\n    }\n}\n\n// Enum to track what kind of parameter we're dealing with\nenum ParamKind {\n    Value,\n    Ref(Box<syn::Type>), // The inner type of the reference (e.g., Point for &Point)\n    RefMut(Box<syn::Type>), // The inner type of the mutable reference (e.g., Point for &mut Point)\n}\n\nimpl ParamKind {\n    fn from_type(ty: &syn::Type) -> Self {\n        match ty {\n            syn::Type::Reference(type_ref) => {\n                // Any reference to a path type (e.g., &Point, &mut Point, &Message)\n                if let syn::Type::Path(_) = &*type_ref.elem {\n                    if type_ref.mutability.is_some() {\n                        ParamKind::RefMut(type_ref.elem.clone())\n                    } else {\n                        ParamKind::Ref(type_ref.elem.clone())\n                    }\n                } else {\n                    ParamKind::Value\n                }\n            }\n            _ => ParamKind::Value,\n        }\n    }\n}\n\n// Extract parameter types from signature, skipping self, context, and this\nfn extract_param_types(sig: &syn::Signature, has_context: bool, has_this: bool) -> Vec<ParamKind> {\n    let skip_count = 1 + (has_context as usize) + (has_this as usize);\n\n    sig.inputs\n        .iter()\n        .skip(skip_count)\n        .filter_map(|arg| match arg {\n            syn::FnArg::Typed(pat_type) => Some(ParamKind::from_type(&pat_type.ty)),\n            syn::FnArg::Receiver(_) => None,\n        })\n        .collect()\n}\n\nfn generate_method_wrapper(\n    meta: &meta::Meta,\n    class_id: &syn::Ident,\n    sig: &syn::Signature,\n) -> TokenStream {\n    // Validate method attributes\n    if let Err(err) = validate_method_attributes(meta, sig) {\n        return err.into_compile_error();\n    }\n\n    let internal_name = &sig.ident;\n    let external_name_string = match &meta.name {\n        Some(name) => name.value(),\n        None => crate::name::to_camel_case(&internal_name.to_string()),\n    };\n    let external_name_str = &external_name_string[..];\n    let is_mut = is_receiver_mutable(sig);\n\n    // Check for context parameter and generate context extraction/argument\n    let (context_extract, context_arg) = match context_parse(meta, sig) {\n        Ok((extract, arg)) => (extract, arg),\n        Err(err) => return err.into_compile_error(),\n    };\n\n    // Determine if method has context parameter\n    let has_context = context_arg.is_some();\n\n    // Check for this parameter\n    let has_this = check_this(meta, sig, has_context);\n\n    // Generate this extraction if needed\n    let this_extract = if has_this {\n        quote::quote!(\n            let js_this: neon::handle::Handle<neon::types::JsObject> = cx.this()?;\n            let this = neon::types::extract::TryFromJs::from_js(&mut cx, neon::handle::Handle::upcast(&js_this))?;\n        )\n    } else {\n        quote::quote!()\n    };\n\n    // Generate this argument for method call\n    let this_arg = if has_this {\n        quote::quote!(this,)\n    } else {\n        quote::quote!()\n    };\n\n    // Analyze parameter types to determine which are references\n    let param_types = extract_param_types(sig, has_context, has_this);\n    let num_args = param_types.len();\n\n    // Generate tuple fields for cx.args() extraction and type annotations\n    let (tuple_fields, ref_type_annotations): (Vec<_>, Vec<_>) = param_types\n        .iter()\n        .enumerate()\n        .map(|(i, param_kind)| {\n            let name = quote::format_ident!(\"a{i}\");\n            match param_kind {\n                ParamKind::Ref(_) | ParamKind::RefMut(_) => {\n                    // For reference parameters, extract as a generic arg then type annotate\n                    let obj_name = quote::format_ident!(\"a{i}_obj\");\n                    let annotation = quote::quote! {\n                        let #obj_name: neon::handle::Handle<neon::types::JsObject> = #obj_name;\n                    };\n                    (quote::quote!(#obj_name), Some(annotation))\n                }\n                ParamKind::Value => {\n                    // For value parameters, use existing logic with JSON wrapping if needed\n                    let field = if meta.json {\n                        quote::quote!(neon::types::extract::Json(#name))\n                    } else {\n                        quote::quote!(#name)\n                    };\n                    (field, None)\n                }\n            }\n        })\n        .unzip();\n\n    // Generate guard extraction code for reference parameters\n    let ref_guards = param_types.iter().enumerate().filter_map(|(i, param_kind)| {\n        match param_kind {\n            ParamKind::Ref(inner_type) => {\n                let obj_name = quote::format_ident!(\"a{i}_obj\");\n                let guard_name = quote::format_ident!(\"_guard_a{i}\");\n                let arg_name = quote::format_ident!(\"a{i}\");\n\n                Some(quote::quote! {\n                    let #guard_name = <#inner_type as neon::types::extract::TryFromJsRef>::from_js_ref(\n                        &mut cx,\n                        neon::handle::Handle::upcast(&#obj_name)\n                    )?;\n                    let #arg_name: &#inner_type = &*#guard_name;\n                })\n            }\n            ParamKind::RefMut(inner_type) => {\n                let obj_name = quote::format_ident!(\"a{i}_obj\");\n                let guard_name = quote::format_ident!(\"_guard_a{i}\");\n                let arg_name = quote::format_ident!(\"a{i}\");\n\n                Some(quote::quote! {\n                    let mut #guard_name = <#inner_type as neon::types::extract::TryFromJsRefMut>::from_js_ref_mut(\n                        &mut cx,\n                        neon::handle::Handle::upcast(&#obj_name)\n                    )?;\n                    let #arg_name: &mut #inner_type = &mut *#guard_name;\n                })\n            }\n            ParamKind::Value => None,\n        }\n    });\n\n    // Generate argument list for method call\n    let args = (0..num_args).map(|i| quote::format_ident!(\"a{i}\"));\n\n    // Tag whether we should JSON wrap results\n    let return_tag = if meta.json {\n        quote::format_ident!(\"NeonJsonTag\")\n    } else {\n        quote::format_ident!(\"NeonValueTag\")\n    };\n\n    // Generate result conversion based on JSON setting\n    let result_extract = quote::quote!({\n        use neon::macro_internal::{ToNeonMarker, #return_tag as NeonReturnTag};\n        (&res).to_neon_marker::<NeonReturnTag>().neon_into_js(&mut cx, res)\n    });\n\n    match meta.kind {\n        meta::Kind::Async => {\n            let borrow_call = if is_mut {\n                quote::quote! {\n                    let mut instance = instance_cell.borrow_mut();\n                    let instance = &mut *instance;\n                }\n            } else {\n                quote::quote! {\n                    let instance = instance_cell.borrow();\n                    let instance = &*instance;\n                }\n            };\n\n            quote::quote! {\n                JsFunction::with_name(cx, #external_name_str, |mut cx| {\n                    use neon::result::ResultExt;\n\n                    let js_this: neon::handle::Handle<neon::types::JsObject> = cx.this()?;\n                    let instance_cell: &std::cell::RefCell<#class_id> = neon::object::unwrap(&mut cx, js_this)?.or_throw(&mut cx)?;\n\n                    // Context extraction if needed\n                    #context_extract\n\n                    // This extraction if needed\n                    #this_extract\n\n                    // Extract non-context/this arguments with JSON wrapping if needed\n                    let (#(#tuple_fields,)*) = cx.args()?;\n\n                    // Type annotations for reference parameters\n                    #(#ref_type_annotations)*\n\n                    // Unwrap reference parameters and create guards\n                    #(#ref_guards)*\n\n                    // Borrow from RefCell\n                    #borrow_call\n\n                    // Call the method with &self or &mut self - developer controls cloning in their impl\n                    let fut = instance.#internal_name(#context_arg #this_arg #(#args),*);\n                    // Always use NeonValueTag for Future conversion, JSON only applies to final result\n                    let fut = {\n                        use neon::macro_internal::{ToNeonMarker, NeonValueTag};\n                        (&fut).to_neon_marker::<NeonValueTag>().into_neon_result(&mut cx, fut)?\n                    };\n                    neon::macro_internal::spawn(&mut cx, fut, |mut cx, res| #result_extract)\n                })\n            }\n        }\n        meta::Kind::AsyncFn => {\n            quote::quote! {\n                JsFunction::with_name(cx, #external_name_str, |mut cx| {\n                    use neon::result::ResultExt;\n\n                    let js_this: neon::handle::Handle<neon::types::JsObject> = cx.this()?;\n                    let instance_cell: &std::cell::RefCell<#class_id> = neon::object::unwrap(&mut cx, js_this)?.or_throw(&mut cx)?;\n\n                    // Context extraction if needed\n                    #context_extract\n\n                    // This extraction if needed\n                    #this_extract\n\n                    // Extract non-context/this arguments with JSON wrapping if needed\n                    let (#(#tuple_fields,)*) = cx.args()?;\n\n                    // Type annotations for reference parameters\n                    #(#ref_type_annotations)*\n\n                    // Unwrap reference parameters and create guards\n                    #(#ref_guards)*\n\n                    // Clone the instance to move into async fn (takes self by value)\n                    let instance_clone = instance_cell.borrow().clone();\n\n                    // Call the async fn method - it takes self by value to produce 'static Future\n                    let fut = instance_clone.#internal_name(#context_arg #this_arg #(#args),*);\n\n                    neon::macro_internal::spawn(&mut cx, fut, |mut cx, res| #result_extract)\n                })\n            }\n        }\n        meta::Kind::Task => {\n            quote::quote! {\n                JsFunction::with_name(cx, #external_name_str, |mut cx| {\n                    use neon::result::ResultExt;\n\n                    let js_this: neon::handle::Handle<neon::types::JsObject> = cx.this()?;\n                    let instance_cell: &std::cell::RefCell<#class_id> = neon::object::unwrap(&mut cx, js_this)?.or_throw(&mut cx)?;\n\n                    // Context extraction if needed\n                    #context_extract\n\n                    // This extraction if needed\n                    #this_extract\n\n                    // Clone the instance to move into the task (takes self by value)\n                    let instance_clone = instance_cell.borrow().clone();\n\n                    // Extract non-context/this arguments with JSON wrapping if needed\n                    let (#(#tuple_fields,)*) = cx.args()?;\n\n                    // Type annotations for reference parameters\n                    #(#ref_type_annotations)*\n\n                    // Unwrap reference parameters and create guards\n                    #(#ref_guards)*\n\n                    let promise = neon::context::Context::task(&mut cx, move || {\n                        instance_clone.#internal_name(#context_arg #this_arg #(#args),*)\n                    })\n                    .promise(|mut cx, res| #result_extract);\n                    Ok(promise.upcast::<neon::types::JsValue>())\n                })\n            }\n        }\n        meta::Kind::Normal => {\n            let borrow_call = if is_mut {\n                quote::quote! {\n                    let mut instance = instance_cell.borrow_mut();\n                    let instance = &mut *instance;\n                }\n            } else {\n                quote::quote! {\n                    let instance = instance_cell.borrow();\n                    let instance = &*instance;\n                }\n            };\n\n            quote::quote! {\n                JsFunction::with_name(cx, #external_name_str, |mut cx| {\n                    use neon::result::ResultExt;\n\n                    let js_this: neon::handle::Handle<neon::types::JsObject> = cx.this()?;\n                    let instance_cell: &std::cell::RefCell<#class_id> = neon::object::unwrap(&mut cx, js_this)?.or_throw(&mut cx)?;\n\n                    // Context extraction if needed\n                    #context_extract\n\n                    // This extraction if needed\n                    #this_extract\n\n                    // Extract non-context/this arguments with JSON wrapping if needed\n                    let (#(#tuple_fields,)*) = cx.args()?;\n\n                    // Type annotations for reference parameters\n                    #(#ref_type_annotations)*\n\n                    // Unwrap reference parameters and create guards\n                    #(#ref_guards)*\n\n                    // Borrow from RefCell\n                    #borrow_call\n\n                    let res = instance.#internal_name(#context_arg #this_arg #(#args),*);\n                    #result_extract\n                })\n            }\n        }\n    }\n}\n\n// Generate context extraction and argument for class methods\nfn context_parse(\n    opts: &meta::Meta,\n    sig: &syn::Signature,\n) -> syn::Result<(\n    Option<proc_macro2::TokenStream>,\n    Option<proc_macro2::TokenStream>,\n)> {\n    match opts.kind {\n        // Allow borrowing from context\n        meta::Kind::Async | meta::Kind::Normal if check_context(opts, sig)? => {\n            Ok((None, Some(quote::quote!(&mut cx,))))\n        }\n\n        // Require `'static` arguments\n        meta::Kind::AsyncFn | meta::Kind::Task if check_channel(opts, sig)? => Ok((\n            Some(quote::quote!(let ch = neon::context::Context::channel(&mut cx);)),\n            Some(quote::quote!(ch,)),\n        )),\n\n        _ => Ok((None, None)),\n    }\n}\n\n// Check if a sync method has a context argument (adapted from export function)\n// Key difference from #[export]: methods have &self as first param, so context is second param\nfn check_context(opts: &meta::Meta, sig: &syn::Signature) -> syn::Result<bool> {\n    // Extract the first argument (after &self)\n    let ty = match first_arg(opts, sig)? {\n        Some(arg) => arg,\n        None => return Ok(false),\n    };\n\n    // Extract the reference type\n    let ty = match &*ty.ty {\n        // Tried to use a borrowed Channel\n        syn::Type::Reference(ty) if !opts.context && is_channel_type(&ty.elem) => {\n            return Err(syn::Error::new(\n                ty.elem.span(),\n                \"Expected `&mut Cx` instead of a `Channel` reference.\",\n            ))\n        }\n\n        syn::Type::Reference(ty) => ty,\n\n        // Context needs to be a reference\n        _ if opts.context || is_context_type(&ty.ty) => {\n            return Err(syn::Error::new(\n                ty.ty.span(),\n                \"Context parameters must be a `&mut` reference. Try `&mut FunctionContext` or `&mut Cx`.\",\n            ))\n        }\n\n        // Hint that `Channel` should be swapped for `&mut Cx`\n        _ if is_channel_type(&ty.ty) => {\n            return Err(syn::Error::new(\n                ty.ty.span(),\n                \"Unexpected `Channel` in sync method. Use `&mut FunctionContext` for sync methods, or `Channel` in async/task methods.\",\n            ))\n        }\n\n        _ => return Ok(false),\n    };\n\n    // Not a forced or inferred context\n    if !opts.context && !is_context_type(&ty.elem) {\n        return Ok(false);\n    }\n\n    // Context argument must be mutable\n    if ty.mutability.is_none() {\n        return Err(syn::Error::new(ty.span(), \"Must be a `&mut` reference.\"));\n    }\n\n    // All tests passed!\n    Ok(true)\n}\n\n// Check if an async method has a Channel argument (adapted from export function)\nfn check_channel(opts: &meta::Meta, sig: &syn::Signature) -> syn::Result<bool> {\n    // Extract the first argument (after &self)\n    let ty = match first_arg(opts, sig)? {\n        Some(arg) => arg,\n        None => return Ok(false),\n    };\n\n    // Check the type\n    match &*ty.ty {\n        // Provided `&mut Channel` instead of `Channel`\n        syn::Type::Reference(ty) if opts.context || is_channel_type(&ty.elem) => {\n            Err(syn::Error::new(\n                ty.span(),\n                \"Expected an owned `Channel` instead of a reference.\",\n            ))\n        }\n\n        // Provided a `&mut Cx` instead of a `Channel`\n        syn::Type::Reference(ty) if is_context_type(&ty.elem) => Err(syn::Error::new(\n            ty.elem.span(),\n            \"Expected an owned `Channel` instead of a context reference.\",\n        )),\n\n        // Found a `Channel`\n        _ if opts.context || is_channel_type(&ty.ty) => Ok(true),\n\n        // Tried to use an owned `Cx`\n        _ if is_context_type(&ty.ty) => Err(syn::Error::new(\n            ty.ty.span(),\n            \"Context is not available in async functions. Try a `Channel` instead.\",\n        )),\n\n        _ => Ok(false),\n    }\n}\n\n// Extract the first argument (after &self) from a method signature\nfn first_arg<'a>(\n    opts: &meta::Meta,\n    sig: &'a syn::Signature,\n) -> syn::Result<Option<&'a syn::PatType>> {\n    // Extract the second argument (skip &self)\n    let arg = match sig.inputs.iter().nth(1) {\n        Some(arg) => arg,\n\n        // If context was forced, error to let the user know the mistake\n        None if opts.context => {\n            return Err(syn::Error::new(\n                sig.inputs.span(),\n                \"Expected a context argument after `&self` when using `#[neon(context)]`. Add a parameter like `cx: &mut FunctionContext` or remove the `context` attribute.\",\n            ))\n        }\n\n        None => return Ok(None),\n    };\n\n    // Expect a typed pattern; self receivers are not supported (but shouldn't appear here)\n    match arg {\n        syn::FnArg::Typed(ty) => Ok(Some(ty)),\n        syn::FnArg::Receiver(arg) => Err(syn::Error::new(\n            arg.span(),\n            \"Unexpected second receiver argument.\",\n        )),\n    }\n}\n\nfn is_context_type(ty: &syn::Type) -> bool {\n    let ident = match type_path_ident(ty) {\n        Some(ident) => ident,\n        None => return false,\n    };\n\n    ident == \"FunctionContext\" || ident == \"Cx\"\n}\n\nfn is_channel_type(ty: &syn::Type) -> bool {\n    let ident = match type_path_ident(ty) {\n        Some(ident) => ident,\n        None => return false,\n    };\n\n    ident == \"Channel\"\n}\n\n// Extract the identifier from the last segment of a type's path\nfn type_path_ident(ty: &syn::Type) -> Option<&syn::Ident> {\n    let segment = match ty {\n        syn::Type::Path(ty) => ty.path.segments.last()?,\n        _ => return None,\n    };\n\n    Some(&segment.ident)\n}\n\n// Validate method attributes for common errors and conflicts\nfn validate_method_attributes(meta: &meta::Meta, sig: &syn::Signature) -> syn::Result<()> {\n    // Check for conflicting async attributes\n    if matches!(meta.kind, meta::Kind::AsyncFn) && matches!(meta.kind, meta::Kind::Async) {\n        return Err(syn::Error::new(\n            sig.span(),\n            \"Cannot combine `async fn` with `#[neon(async)]` attribute\",\n        ));\n    }\n\n    // Check for async + task conflict\n    if matches!(meta.kind, meta::Kind::AsyncFn | meta::Kind::Async)\n        && matches!(meta.kind, meta::Kind::Task)\n    {\n        return Err(syn::Error::new(\n            sig.span(),\n            \"Cannot combine async method with `#[neon(task)]` attribute\",\n        ));\n    }\n\n    // Validate that async fn and task methods take self by value\n    if matches!(meta.kind, meta::Kind::AsyncFn | meta::Kind::Task) {\n        if let Some(syn::FnArg::Receiver(receiver)) = sig.inputs.first() {\n            if receiver.reference.is_some() {\n                // This is &self or &mut self, but we need self by value\n                let method_type = if matches!(meta.kind, meta::Kind::AsyncFn) {\n                    \"Async functions\"\n                } else {\n                    \"Task methods\"\n                };\n                let reason = if matches!(meta.kind, meta::Kind::AsyncFn) {\n                    \"This is required because async functions capture `self` in the Future, which must be `'static` for spawning.\"\n                } else {\n                    \"Since the instance is cloned before moving to the worker thread, taking `&self` would operate on a temporary reference to the clone, which is misleading.\"\n                };\n                return Err(syn::Error::new(\n                    receiver.span(),\n                    format!(\n                        \"{} in classes must take `self` by value, not `&self` or `&mut self`. {}\",\n                        method_type, reason\n                    ),\n                ));\n            }\n        } else {\n            let method_type = if matches!(meta.kind, meta::Kind::AsyncFn) {\n                \"Async functions\"\n            } else {\n                \"Task methods\"\n            };\n            return Err(syn::Error::new(\n                sig.span(),\n                format!(\n                    \"{} in classes must take `self` as their first parameter.\",\n                    method_type\n                ),\n            ));\n        }\n    }\n\n    // Check for self parameter in constructor\n    if sig.ident == \"new\" {\n        if let Some(syn::FnArg::Receiver(_)) = sig.inputs.first() {\n            return Err(syn::Error::new(\n                sig.ident.span(),\n                \"Constructor methods cannot have a `self` receiver\",\n            ));\n        }\n    } else {\n        fn starts_with_self_arg(sig: &syn::Signature) -> bool {\n            if let Some(first_arg) = sig.inputs.first() {\n                matches!(first_arg, syn::FnArg::Receiver(_))\n            } else {\n                false\n            }\n        }\n\n        // Check for self parameter in non-constructor methods\n        if !starts_with_self_arg(sig) {\n            return Err(syn::Error::new(\n                sig.ident.span(),\n                \"Class methods must have a `self` receiver (`&self` or `&mut self`) as their first parameter\",\n            ));\n        }\n    }\n\n    Ok(())\n}\n\n// Check if a method has a `this` parameter (adapted from export function)\n// For methods: &self is 1st, context is 2nd (optional), this is 3rd (or 2nd if no context)\nfn check_this(opts: &meta::Meta, sig: &syn::Signature, has_context: bool) -> bool {\n    static THIS: &str = \"this\";\n\n    // Forced `this` argument\n    if opts.this {\n        return true;\n    }\n\n    // Get the parameter after &self and optional context\n    let param_index = if has_context { 2 } else { 1 }; // Skip &self and optional context\n    let param = match sig.inputs.iter().nth(param_index) {\n        Some(param) => param,\n        None => return false,\n    };\n\n    // Ignore `self` type receivers (shouldn't happen at this index, but be safe)\n    let ty = match param {\n        syn::FnArg::Receiver(_) => return false,\n        syn::FnArg::Typed(ty) => ty,\n    };\n\n    // Check for `this` ident or a tuple struct\n    let pat = match &*ty.pat {\n        syn::Pat::Ident(ident) if ident.ident == THIS => return true,\n        syn::Pat::TupleStruct(pat) => pat,\n        _ => return false,\n    };\n\n    // Expect exactly one element in the tuple struct\n    let elem = match pat.elems.first() {\n        Some(elem) if pat.elems.len() == 1 => elem,\n        _ => return false,\n    };\n\n    // Must be an identifier named `this`\n    match elem {\n        syn::Pat::Ident(ident) => ident.ident == THIS,\n        _ => false,\n    }\n}\n\n// Check if constructor has a context parameter using same heuristic as export functions\n// * If the `context` attribute is included, must have at least one argument\n// * Inferred to be context if first arg is `&mut FunctionContext` or `&mut Cx`\n// * Context argument must be a `&mut` reference\nfn check_constructor_context(opts: &meta::Meta, sig: &syn::Signature) -> syn::Result<bool> {\n    // Extract the first argument\n    let ty = match sig.inputs.first() {\n        Some(syn::FnArg::Typed(ty)) => ty,\n        Some(syn::FnArg::Receiver(_)) => {\n            return Err(syn::Error::new(\n                sig.inputs.span(),\n                \"Constructor cannot have a `self` receiver\",\n            ))\n        }\n        None if opts.context => {\n            return Err(syn::Error::new(\n                sig.inputs.span(),\n                \"Expected a context argument. Try removing the `context` attribute.\",\n            ))\n        }\n        None => return Ok(false),\n    };\n\n    // Extract the reference type\n    let ty = match &*ty.ty {\n        syn::Type::Reference(ty) => ty,\n\n        // Context needs to be a reference\n        _ if opts.context || is_context_type(&ty.ty) => {\n            return Err(syn::Error::new(\n                ty.ty.span(),\n                \"Context must be a `&mut` reference.\",\n            ))\n        }\n\n        _ => return Ok(false),\n    };\n\n    // Not a forced or inferred context\n    if !opts.context && !is_context_type(&ty.elem) {\n        return Ok(false);\n    }\n\n    // Context argument must be mutable\n    if ty.mutability.is_none() {\n        return Err(syn::Error::new(ty.span(), \"Must be a `&mut` reference.\"));\n    }\n\n    // All tests passed!\n    Ok(true)\n}\n\n// Generate constructor wrapper with support for context, JSON, and Result types\nfn generate_constructor_wrapper(\n    meta: &meta::Meta,\n    class_id: &syn::Ident,\n    sig: &syn::Signature,\n    ctor_locals: &[Ident],\n) -> syn::Result<TokenStream> {\n    // Check for context parameter in constructor using same heuristic as export functions\n    let has_context = check_constructor_context(meta, sig)?;\n\n    // Determine which parameters are actual constructor arguments (skip context if present)\n    let param_offset = if has_context { 1 } else { 0 };\n    let arg_locals = &ctor_locals[param_offset..];\n\n    // Generate the arguments tuple extraction\n    let args_extract = {\n        // Wrap arguments in Json() if needed for deserialization\n        let tuple_fields = arg_locals.iter().map(|name| {\n            if meta.json {\n                quote::quote!(neon::types::extract::Json(#name))\n            } else {\n                quote::quote!(#name)\n            }\n        });\n\n        // Generate type inference tokens for each argument\n        let type_infers = arg_locals.iter().map(|_| {\n            quote::quote! { _ }\n        });\n\n        quote::quote! {\n            let (this, #(#tuple_fields,)*): (neon::handle::Handle<neon::types::JsObject>, #(#type_infers),*) = cx.args()?;\n        }\n    };\n\n    // Build the argument list for calling the constructor\n    let ctor_args = if has_context {\n        if arg_locals.is_empty() {\n            quote::quote! { &mut cx }\n        } else {\n            quote::quote! { &mut cx, #(#arg_locals),* }\n        }\n    } else {\n        quote::quote! { #(#arg_locals),* }\n    };\n\n    // Generate the constructor call with Result handling\n    let ctor_call = quote::quote! {\n        let result = #class_id::new(#ctor_args);\n\n        // Use ToNeonMarker to detect if result is Result<T, E> or just T\n        use neon::macro_internal::{ToNeonMarker, NeonValueTag};\n        let instance = (&result).to_neon_marker::<NeonValueTag>().into_neon_result(&mut cx, result)?;\n    };\n\n    // Generate the full wrapper\n    Ok(quote::quote! {\n        #args_extract\n        #ctor_call\n        neon::object::wrap(&mut cx, this, std::cell::RefCell::new(instance))?.or_throw(&mut cx)?;\n        Ok(cx.undefined())\n    })\n}\n\nfn group_class_items(items: Vec<syn::ImplItem>) -> Result<ClassItems, syn::Error> {\n    let mut consts = Vec::new();\n    let mut fns = Vec::new();\n    let mut constructor = None;\n    let mut has_finalizer = false;\n\n    for item in items {\n        match item {\n            syn::ImplItem::Const(c) => consts.push(c),\n            syn::ImplItem::Fn(f) => {\n                // Check if the function is a constructor\n                if f.sig.ident == \"new\" {\n                    if constructor.is_some() {\n                        let span = syn::spanned::Spanned::span(&f);\n                        let msg = \"Only one `new` constructor is allowed in a class.\";\n                        return Err(syn::Error::new(span, msg));\n                    }\n                    constructor = Some(f);\n                    continue; // Skip adding to fns\n                } else if f.sig.ident == \"finalize\" {\n                    if has_finalizer {\n                        let span = syn::spanned::Spanned::span(&f);\n                        let msg = \"Only one `finalize` method is allowed in a class.\";\n                        return Err(syn::Error::new(span, msg));\n                    }\n                    has_finalizer = true;\n                    continue; // Skip adding to fns\n                }\n                fns.push(f)\n            }\n            _ => {\n                let span = syn::spanned::Spanned::span(&item);\n                let msg = \"`neon::class` can only contain `const` and `fn` items.\";\n                return Err(syn::Error::new(span, msg));\n            }\n        }\n    }\n\n    Ok(ClassItems {\n        consts,\n        fns,\n        constructor,\n        has_finalizer,\n    })\n}\n\npub(crate) fn class(\n    _attr: proc_macro::TokenStream,\n    item: proc_macro::TokenStream,\n) -> proc_macro::TokenStream {\n    class_with_name(_attr, item, None)\n}\n\npub(crate) fn class_with_name(\n    _attr: proc_macro::TokenStream,\n    item: proc_macro::TokenStream,\n    custom_class_name: Option<String>,\n) -> proc_macro::TokenStream {\n    let mut impl_block = syn::parse_macro_input!(item as syn::ItemImpl);\n\n    // Parse the item as an implementation block\n    let syn::ItemImpl { self_ty, items, .. } = impl_block.clone();\n\n    let class_ident = match *self_ty {\n        syn::Type::Path(syn::TypePath {\n            path: syn::Path { segments, .. },\n            ..\n        }) => {\n            let syn::PathSegment { ident, .. } = segments.last().unwrap();\n            ident.clone()\n        }\n        _ => {\n            panic!(\"class must be implemented for a type name\");\n        }\n    };\n    let class_name = custom_class_name.unwrap_or_else(|| class_ident.to_string());\n\n    // Group the items into `const` and `fn` categories\n    let ClassItems {\n        consts,\n        fns,\n        constructor,\n        has_finalizer,\n    } = match group_class_items(items.clone()) {\n        Ok(items) => items,\n        Err(err) => {\n            // If sorting fails, return the error as a compile error\n            return err.to_compile_error().into();\n        }\n    };\n\n    // Parse constructor metadata\n    let ctor_meta = match &constructor {\n        Some(ctor) => {\n            let mut meta = meta::Meta::default();\n            let mut found_neon_attr = false;\n            for attr in &ctor.attrs {\n                if let syn::Meta::List(syn::MetaList { path, tokens, .. }) = &attr.meta {\n                    if path.is_ident(\"neon\") {\n                        if found_neon_attr {\n                            return syn::Error::new_spanned(\n                                attr,\n                                \"multiple #[neon(...)] attributes on constructor are not allowed\",\n                            )\n                            .to_compile_error()\n                            .into();\n                        }\n                        found_neon_attr = true;\n                        let parser = meta::Parser(meta);\n                        let tokens = tokens.clone();\n                        match syn::parse::Parser::parse2(parser, tokens) {\n                            Ok(parsed_meta) => meta = parsed_meta,\n                            Err(err) => return err.to_compile_error().into(),\n                        }\n                    }\n                }\n            }\n\n            // Validate that constructors don't use async/task attributes\n            if !matches!(meta.kind, meta::Kind::Normal) {\n                return syn::Error::new_spanned(\n                    &ctor.sig,\n                    \"Constructors cannot use #[neon(async)] or #[neon(task)] attributes\",\n                )\n                .to_compile_error()\n                .into();\n            }\n\n            // Validate that constructors don't use 'this' attribute\n            if meta.this {\n                return syn::Error::new_spanned(\n                    &ctor.sig,\n                    \"Constructors cannot use #[neon(this)] attribute\",\n                )\n                .to_compile_error()\n                .into();\n            }\n\n            Some(meta)\n        }\n        None => None,\n    };\n\n    let ctor_params = match &constructor {\n        Some(ImplItemFn { sig, .. }) => {\n            let mut params = Vec::new();\n            for (i, arg) in sig.inputs.iter().enumerate() {\n                match arg {\n                    syn::FnArg::Typed(pat_type) => {\n                        params.push(match pat_type.pat.as_ref() {\n                            syn::Pat::Ident(ident) => ident.ident.to_string(),\n                            // Rust identifiers can't begin with '$' so this can't conflict\n                            // with any user-provided identifiers.\n                            _ => format!(\"$arg{}\", i),\n                        });\n                    }\n                    syn::FnArg::Receiver(_) => {\n                        return syn::Error::new_spanned(\n                            arg,\n                            \"Constructor methods cannot have a `self` receiver\",\n                        )\n                        .to_compile_error()\n                        .into();\n                    }\n                }\n            }\n            params\n        }\n        None => {\n            vec![]\n        }\n    };\n\n    let ctor_locals: Vec<Ident> = match &constructor {\n        Some(ImplItemFn { sig, .. }) => sig\n            .inputs\n            .iter()\n            .enumerate()\n            .map(|(i, arg)| Ident::new(&format!(\"a{i}\"), arg.span()))\n            .collect::<Vec<_>>(),\n        None => {\n            vec![]\n        }\n    };\n\n    let ctor_infers: Vec<Type> = match &constructor {\n        Some(ImplItemFn { sig, .. }) => sig\n            .inputs\n            .iter()\n            .map(|_| {\n                Type::Infer(syn::TypeInfer {\n                    underscore_token: Default::default(),\n                })\n            })\n            .collect::<Vec<_>>(),\n        None => {\n            vec![]\n        }\n    };\n\n    let ctor_param_list = ctor_params.join(\", \");\n    let ctor_arg_list = format!(\n        \"{}{}\",\n        if ctor_params.is_empty() { \"\" } else { \", \" },\n        ctor_param_list\n    );\n\n    let mut method_names = String::new();\n    let mut prototype_patches = String::new();\n    let method_ids = fns.iter().map(|f| f.sig.ident.clone()).collect::<Vec<_>>();\n    let mut method_metas = Vec::new();\n\n    for f in &fns {\n        let fn_name = f.sig.ident.to_string();\n        method_names.push_str(&format!(\", {fn_name}Method\"));\n        // syn::parse_macro_input!(attr with parser);\n        let mut parsed = meta::Meta::default();\n\n        // Check if the function itself is async\n        if f.sig.asyncness.is_some() {\n            parsed.kind = meta::Kind::AsyncFn;\n        }\n\n        let mut found_neon_attr = false;\n        for syn::Attribute { meta, .. } in &f.attrs {\n            match meta {\n                syn::Meta::List(syn::MetaList { path, tokens, .. }) if path.is_ident(\"neon\") => {\n                    if found_neon_attr {\n                        return syn::Error::new_spanned(\n                            meta,\n                            \"multiple #[neon(...)] attributes on class method are not allowed\",\n                        )\n                        .to_compile_error()\n                        .into();\n                    }\n                    found_neon_attr = true;\n                    let parser = meta::Parser(parsed);\n                    let tokens = tokens.clone().into();\n                    parsed = syn::parse_macro_input!(tokens with parser);\n                }\n                _ => {}\n            }\n        }\n        let js_name = match parsed.name.clone() {\n            Some(name) => name.value(),\n            None => crate::name::to_camel_case(&fn_name),\n        };\n        prototype_patches.push_str(&format!(\"\\n    prototype.{js_name} = {fn_name}Method;\"));\n        method_metas.push(parsed);\n    }\n\n    // Process const items into static class properties\n    let mut property_names = Vec::new();\n    let mut property_assignments = Vec::new();\n    let mut property_ids = Vec::new();\n    let mut property_wrappers = Vec::new();\n    let mut used_js_names = std::collections::HashSet::with_capacity(consts.len()); // Pre-allocate\n\n    for const_item in &consts {\n        let const_name = &const_item.ident;\n        let property_id = quote::format_ident!(\"__{const_name}Property\");\n\n        // Parse property attributes\n        let mut property_meta = meta::PropertyMeta::default();\n        let mut found_neon_attr = false;\n        for attr in &const_item.attrs {\n            if let syn::Meta::List(syn::MetaList { path, tokens, .. }) = &attr.meta {\n                if path.is_ident(\"neon\") {\n                    if found_neon_attr {\n                        return syn::Error::new_spanned(\n                            attr,\n                            \"multiple #[neon(...)] attributes on const property are not allowed\",\n                        )\n                        .to_compile_error()\n                        .into();\n                    }\n                    found_neon_attr = true;\n                    let parser = meta::PropertyParser;\n                    let tokens = tokens.clone().into();\n                    property_meta = syn::parse_macro_input!(tokens with parser);\n                }\n            }\n        }\n\n        // Determine JavaScript property name (use custom name or default)\n        let js_property_name = match &property_meta.name {\n            Some(name) => {\n                let name_value = name.value();\n                // Validate JavaScript identifier\n                if !is_valid_js_identifier(&name_value) {\n                    return syn::Error::new_spanned(\n                        name,\n                        format!(\"'{}' is not a valid JavaScript identifier\", name_value),\n                    )\n                    .to_compile_error()\n                    .into();\n                }\n                name_value\n            }\n            None => const_name.to_string(),\n        };\n\n        // Check for name collisions\n        if !used_js_names.insert(js_property_name.clone()) {\n            return syn::Error::new_spanned(\n                const_item,\n                format!(\"duplicate property name '{}' - const property names must be unique in JavaScript\", js_property_name)\n            ).to_compile_error().into();\n        }\n\n        // Add to parameter list for JavaScript function\n        property_names.push(property_id.to_string());\n\n        // Add property assignment in JavaScript (immutable const properties)\n        property_assignments.push(format!(\n            \"\\n    Object.defineProperty({class_name}, '{js_property_name}', {{ value: {property_id}(), enumerable: true }});\"\n        ));\n\n        // Create property getter function with JSON support\n        let value_expr = if property_meta.json {\n            quote::quote! {\n                use neon::types::extract::{TryIntoJs, Json};\n                let value = Json(#class_ident::#const_name);\n                value.try_into_js(&mut cx).map(|v| v.upcast())\n            }\n        } else {\n            quote::quote! {\n                use neon::types::extract::TryIntoJs;\n                let value = #class_ident::#const_name;\n                value.try_into_js(&mut cx).map(|v| v.upcast())\n            }\n        };\n\n        let property_wrapper = quote::quote! {\n            neon::types::JsFunction::new(cx, |mut cx| -> neon::result::JsResult<neon::types::JsValue> {\n                #value_expr\n            })\n        };\n\n        property_ids.push(property_id);\n        property_wrappers.push(property_wrapper);\n    }\n\n    let property_params = if property_names.is_empty() {\n        String::new()\n    } else {\n        format!(\", {}\", property_names.join(\", \"))\n    };\n\n    let property_assignments = property_assignments.join(\"\");\n\n    let script = format!(\n        r#\"\n(function makeClass(wrap{method_names}{property_params}) {{\n  // Create the class exposed directly to JavaScript.\n  //\n  // The variables listed in method_names all come from\n  // Rust identifiers, so they cannot start with '$'.\n  function $makeExternal() {{\n    class {class_name} {{\n      constructor({ctor_param_list}) {{\n        wrap.call(this, this{ctor_arg_list});\n      }}\n    }}\n    const prototype = {class_name}.prototype;{prototype_patches}\n\n    // Add static class properties{property_assignments}\n\n    return {class_name};\n  }}\n\n  // Create the constructor used by Neon internally to construct\n  // instances from a pre-existing Rust struct. Calling this\n  // constructor directly will not create a valid instance.\n  // Neon must wrap the resulting object with the Rust struct\n  // before it can be handed back to JavaScript to be used.\n  //\n  // The variables listed in method_names all come from\n  // Rust identifiers, so they cannot start with '$'.\n  function $makeInternal(prototype) {{\n    function {class_name}() {{ }}\n    {class_name}.prototype = prototype;\n    return {class_name};\n  }}\n\n  // The variables listed in method_names all come from\n  // Rust identifiers, so they cannot start with '$'.\n  const $external = $makeExternal();\n  const $internal = $makeInternal($external.prototype);\n\n  return {{\n    external: $external,\n    internal: $internal\n  }};\n}})\n\"#\n    );\n\n    let make_new: TokenStream = if constructor.is_some() {\n        quote::quote! { #class_ident::new }\n    } else {\n        quote::quote! { <Self as ::std::default::Default>::default }\n    };\n\n    // Generate method wrappers based on their metadata\n    let method_wrappers: Vec<TokenStream> = fns\n        .iter()\n        .zip(&method_metas)\n        .map(|(f, meta)| generate_method_wrapper(meta, &class_ident, &f.sig))\n        .collect();\n\n    // Generate constructor wrapper implementation\n    let ctor_wrapper_impl = match (&constructor, &ctor_meta) {\n        (Some(ctor), Some(meta)) => {\n            match generate_constructor_wrapper(meta, &class_ident, &ctor.sig, &ctor_locals) {\n                Ok(wrapper) => wrapper,\n                Err(err) => return err.into_compile_error().into(),\n            }\n        }\n        _ => {\n            // Default constructor without metadata\n            quote::quote! {\n                let (this, #(#ctor_locals,)*): (Handle<JsObject>, #(#ctor_infers),*) = cx.args()?;\n                let instance = #make_new(#(#ctor_locals),*);\n                neon::object::wrap(&mut cx, this, std::cell::RefCell::new(instance))?.or_throw(&mut cx)?;\n                Ok(cx.undefined())\n            }\n        }\n    };\n\n    let impl_class_internal: TokenStream = quote::quote! {\n        impl neon::macro_internal::ClassInternal for #class_ident {\n            fn local<'cx>(cx: &mut neon::context::Cx<'cx>) -> neon::result::NeonResult<neon::macro_internal::ClassMetadata<'cx>> {\n                use neon::handle::{Handle, Root};\n                use neon::macro_internal::{ClassMetadata, RootClassMetadata};\n                use neon::thread::LocalKey;\n                use neon::types::{JsFunction, JsObject};\n\n                static CLASS_METADATA: LocalKey<RootClassMetadata> = LocalKey::new();\n\n                CLASS_METADATA\n                    .get_or_try_init(cx, |cx| Self::create(cx).map(|v| v.root(cx)))\n                    .map(|v| v.to_inner(cx))\n            }\n\n            fn create<'cx>(cx: &mut neon::context::Cx<'cx>) -> neon::result::NeonResult<neon::macro_internal::ClassMetadata<'cx>> {\n                use neon::handle::Handle;\n                use neon::types::{JsFunction, JsObject};\n                use neon::result::ResultExt;\n                use neon::context::Context;\n                use neon::object::Object;\n\n                let wrap = JsFunction::new(cx, |mut cx| {\n                    use neon::types::extract::TryFromJs;\n\n                    #ctor_wrapper_impl\n                });\n\n                // Create method functions using the appropriate wrapper based on metadata\n                #(let #method_ids = #method_wrappers;)*\n\n                // Create property getter functions\n                #(let #property_ids = #property_wrappers;)*\n\n                const CLASS_MAKER_SCRIPT: &str = #script;\n                let src = cx.string(CLASS_MAKER_SCRIPT);\n                let factory: Handle<JsFunction> = neon::reflect::eval(cx, src)?\n                    .downcast(cx)\n                    .or_throw(cx)?;\n                let pair: Handle<JsObject> = factory\n                    .bind(cx)\n                    .arg(wrap)?\n                    #( .arg(#method_ids)? )*\n                    #( .arg(#property_ids)? )*\n                    .call()?;\n                let external: Handle<JsFunction> = pair.prop(cx, \"external\").get()?;\n                let internal: Handle<JsFunction> = pair.prop(cx, \"internal\").get()?;\n                Ok(neon::macro_internal::new_class_metadata(external, internal))\n            }\n        }\n    };\n\n    // Generate the impl of `neon::object::Class` for the struct\n    let impl_class: TokenStream = quote::quote! {\n        impl neon::object::Class for #class_ident {\n            fn name() -> String {\n                stringify!(#class_ident).into()\n            }\n\n            fn constructor<'cx>(cx: &mut neon::context::Cx<'cx>) -> neon::result::JsResult<'cx, neon::types::JsFunction> {\n                Ok(<Self as neon::macro_internal::ClassInternal>::local(cx)?.constructor())\n            }\n        }\n    };\n\n    let impl_finalize: TokenStream = if has_finalizer {\n        quote::quote! {\n            impl neon::types::Finalize for #class_ident {\n                fn finalize<'a, C: neon::context::Context<'a>>(self, cx: &mut C) {\n                    Self::finalize(self, cx)\n                }\n            }\n        }\n    } else {\n        quote::quote! {\n            impl neon::types::Finalize for #class_ident {\n                fn finalize<'a, C: neon::context::Context<'a>>(self, _cx: &mut C) {}\n            }\n        }\n    };\n\n    let impl_sealed: TokenStream = quote::quote! {\n        impl neon::macro_internal::Sealed for #class_ident {}\n    };\n\n    // This leverages the following hack: https://github.com/rust-lang/rust/issues/48214#issuecomment-2557829956\n    // Adding an artificial `for<'a>` generalization circumvents the need for the unstable `trivial_bounds` feature.\n    // This allows us to conditionally require `Clone` only for types that actually make use of `TryFromJs`.\n    let impl_try_from_js: TokenStream = quote::quote! {\n        impl<'cx> neon::types::extract::TryFromJs<'cx> for #class_ident where for<'a> Self: Clone {\n            type Error = neon::macro_internal::WrapError;\n\n            fn try_from_js(cx: &mut neon::context::Cx<'cx>, value: neon::handle::Handle<'cx, neon::types::JsValue>) -> neon::result::NeonResult<Result<Self, Self::Error>> {\n                use neon::result::ResultExt;\n\n                match neon::object::unwrap::<std::cell::RefCell<Self>, _>(cx, value) {\n                    Ok(Ok(instance_cell)) => Ok(Ok(Self::clone(&*instance_cell.borrow()))),\n                    Ok(Err(err)) => Ok(Err(err)),\n                    Err(err) => Err(err),\n                }\n            }\n        }\n    };\n\n    let impl_try_into_js: TokenStream = quote::quote! {\n        impl<'cx> neon::types::extract::TryIntoJs<'cx> for #class_ident {\n            type Value = neon::types::JsObject;\n\n            fn try_into_js(self, cx: &mut neon::context::Cx<'cx>) -> neon::result::JsResult<'cx, Self::Value> {\n                use neon::result::ResultExt;\n\n                let object: neon::handle::Handle<neon::types::JsObject> =\n                    neon::macro_internal::internal_constructor::<Self>(cx)?.bind(cx).construct()?;\n                neon::macro_internal::object::wrap(cx, object, std::cell::RefCell::new(self))?.or_throw(cx)?;\n                Ok(object)\n            }\n        }\n    };\n\n    let impl_try_from_js_ref: TokenStream = quote::quote! {\n        impl<'cx> neon::types::extract::TryFromJsRef<'cx> for #class_ident {\n            type Guard = std::cell::Ref<'cx, Self>;\n            type Error = neon::macro_internal::WrapError;\n\n            fn try_from_js_ref(\n                cx: &mut neon::context::Cx<'cx>,\n                value: neon::handle::Handle<'cx, neon::types::JsValue>\n            ) -> neon::result::NeonResult<Result<Self::Guard, Self::Error>> {\n                use neon::result::ResultExt;\n\n                match neon::object::unwrap::<std::cell::RefCell<Self>, _>(cx, value) {\n                    Ok(Ok(instance_cell)) => Ok(Ok(instance_cell.borrow())),\n                    Ok(Err(err)) => Ok(Err(err)),\n                    Err(err) => Err(err),\n                }\n            }\n        }\n    };\n\n    let impl_try_from_js_ref_mut: TokenStream = quote::quote! {\n        impl<'cx> neon::types::extract::TryFromJsRefMut<'cx> for #class_ident {\n            type Guard = std::cell::RefMut<'cx, Self>;\n            type Error = neon::macro_internal::WrapError;\n\n            fn try_from_js_ref_mut(\n                cx: &mut neon::context::Cx<'cx>,\n                value: neon::handle::Handle<'cx, neon::types::JsValue>\n            ) -> neon::result::NeonResult<Result<Self::Guard, Self::Error>> {\n                use neon::result::ResultExt;\n\n                match neon::object::unwrap::<std::cell::RefCell<Self>, _>(cx, value) {\n                    Ok(Ok(instance_cell)) => Ok(Ok(instance_cell.borrow_mut())),\n                    Ok(Err(err)) => Ok(Err(err)),\n                    Err(err) => Err(err),\n                }\n            }\n        }\n    };\n\n    // Remove #[neon(...)] attributes from methods and const items in the impl block\n    for item in &mut impl_block.items {\n        match item {\n            syn::ImplItem::Fn(f) => {\n                f.attrs.retain(\n                    |attr| !matches!(&attr.meta, syn::Meta::List(list) if list.path.is_ident(\"neon\")),\n                );\n            }\n            syn::ImplItem::Const(c) => {\n                c.attrs.retain(\n                    |attr| !matches!(&attr.meta, syn::Meta::List(list) if list.path.is_ident(\"neon\")),\n                );\n            }\n            _ => {}\n        }\n    }\n\n    quote::quote! {\n        #impl_block\n        #impl_class_internal\n        #impl_class\n        #impl_finalize\n        #impl_sealed\n        #impl_try_from_js\n        #impl_try_into_js\n        #impl_try_from_js_ref\n        #impl_try_from_js_ref_mut\n    }\n    .into()\n}\n"
  },
  {
    "path": "crates/neon-macros/src/export/class/meta.rs",
    "content": "use syn::parse::{Parse, ParseStream};\n\n/// Metadata for class exports\n#[derive(Default)]\npub(crate) struct Meta {\n    /// Name for the JavaScript class itself (used in class definition)\n    pub class_name: Option<String>,\n    /// Name for the module export binding\n    pub export_name: Option<String>,\n}\n\nimpl Parse for Meta {\n    fn parse(input: ParseStream) -> syn::Result<Self> {\n        // Parse \"class\" token\n        let class_token: syn::Ident = input.parse()?;\n        if class_token != \"class\" {\n            return Err(syn::Error::new(\n                class_token.span(),\n                \"Expected 'class' in export attribute\",\n            ));\n        }\n\n        let mut meta = Meta::default();\n\n        // Check for parenthesized attributes: class(name = \"...\")\n        if input.peek(syn::token::Paren) {\n            let content;\n            syn::parenthesized!(content in input);\n\n            // Parse attributes inside parentheses\n            while !content.is_empty() {\n                let name_token: syn::Ident = content.parse()?;\n\n                match name_token.to_string().as_str() {\n                    \"name\" => {\n                        content.parse::<syn::Token![=]>()?;\n                        let name_value: syn::LitStr = content.parse()?;\n                        meta.class_name = Some(name_value.value());\n                    }\n                    _ => {\n                        return Err(syn::Error::new(\n                            name_token.span(),\n                            format!(\"Unknown class attribute '{}'\", name_token),\n                        ));\n                    }\n                }\n\n                // Parse optional comma\n                if content.parse::<syn::Token![,]>().is_err() {\n                    break;\n                }\n            }\n        }\n\n        // Check if there are additional attributes after \"class\" or \"class(...)\"\n        if input.parse::<syn::Token![,]>().is_ok() {\n            // Parse additional attributes like name = \"...\"\n            while !input.is_empty() {\n                let name_token: syn::Ident = input.parse()?;\n\n                match name_token.to_string().as_str() {\n                    \"name\" => {\n                        input.parse::<syn::Token![=]>()?;\n                        let name_value: syn::LitStr = input.parse()?;\n                        meta.export_name = Some(name_value.value());\n                    }\n                    _ => {\n                        return Err(syn::Error::new(\n                            name_token.span(),\n                            format!(\"Unknown attribute '{}'\", name_token),\n                        ));\n                    }\n                }\n\n                // Parse optional comma\n                if input.parse::<syn::Token![,]>().is_err() {\n                    break;\n                }\n            }\n        }\n\n        Ok(meta)\n    }\n}\n\n/// Parser for class export metadata\npub(crate) struct Parser;\n\nimpl syn::parse::Parser for Parser {\n    type Output = Meta;\n\n    fn parse2(self, tokens: proc_macro2::TokenStream) -> syn::Result<Self::Output> {\n        syn::parse2(tokens)\n    }\n}\n"
  },
  {
    "path": "crates/neon-macros/src/export/class.rs",
    "content": "use proc_macro2::TokenStream;\nuse quote::quote;\nuse syn::spanned::Spanned;\n\npub(crate) mod meta;\n\npub(super) fn export(meta: meta::Meta, input: syn::ItemImpl) -> proc_macro::TokenStream {\n    // Extract the class name from the impl block\n    let class_ident = match extract_class_ident(&input) {\n        Ok(ident) => ident,\n        Err(err) => return err.into_compile_error().into(),\n    };\n\n    let rust_class_name = class_ident.to_string();\n\n    // Determine the JavaScript class name and export name based on the parsed metadata\n    // CASE 1: #[export(class, name = \"X\")] -> both class and export use \"X\"\n    // CASE 2: #[export(class(name = \"X\"))] -> both class and export use \"X\"\n    // CASE 3: #[export(class(name = \"X\"), name = \"Y\")] -> class uses \"X\", export uses \"Y\"\n    let (js_class_name, export_name) = match (meta.class_name, meta.export_name) {\n        // CASE 3: Both specified - use each for its purpose\n        (Some(class_name), Some(export_name)) => (Some(class_name), export_name),\n\n        // CASE 2: Only class name specified - use for both\n        (Some(class_name), None) => {\n            let export_name = class_name.clone();\n            (Some(class_name), export_name)\n        }\n\n        // CASE 1: Only export name specified - use for both\n        (None, Some(export_name)) => {\n            let class_name = export_name.clone();\n            (Some(class_name), export_name)\n        }\n\n        // Default: No names specified - use Rust type name\n        (None, None) => (None, rust_class_name.clone()),\n    };\n\n    // Generate the class using the existing class implementation\n    let class_input: proc_macro::TokenStream = quote!(#input).into();\n    let class_output =\n        crate::class::class_with_name(proc_macro::TokenStream::new(), class_input, js_class_name);\n    let class_tokens: TokenStream = class_output.into();\n\n    // Use the determined export name\n    let export_name = quote!(#export_name);\n\n    // Create the export registration function\n    let create_name = quote::format_ident!(\"__NEON_EXPORT_CREATE__{}\", class_ident);\n    let create_fn = quote!(\n        #[doc(hidden)]\n        #[allow(non_snake_case)]\n        #[neon::macro_internal::linkme::distributed_slice(neon::macro_internal::EXPORTS)]\n        #[linkme(crate = neon::macro_internal::linkme)]\n        fn #create_name<'cx>(\n            cx: &mut neon::context::ModuleContext<'cx>,\n        ) -> neon::result::NeonResult<(&'static str, neon::handle::Handle<'cx, neon::types::JsValue>)> {\n            use neon::object::Class;\n            static NAME: &str = #export_name;\n\n            #class_ident::constructor(cx).map(|v| (\n                NAME,\n                neon::handle::Handle::upcast(&v),\n            ))\n        }\n    );\n\n    // Combine the class implementation with the export registration\n    quote!(\n        #class_tokens\n        #create_fn\n    )\n    .into()\n}\n\n// Extract the class identifier from an impl block\nfn extract_class_ident(input: &syn::ItemImpl) -> syn::Result<syn::Ident> {\n    match &*input.self_ty {\n        syn::Type::Path(syn::TypePath {\n            path: syn::Path { segments, .. },\n            ..\n        }) => {\n            let syn::PathSegment { ident, .. } = segments\n                .last()\n                .ok_or_else(|| syn::Error::new(input.self_ty.span(), \"Expected type name\"))?;\n            Ok(ident.clone())\n        }\n        _ => Err(syn::Error::new(\n            input.self_ty.span(),\n            \"Class export can only be applied to named types\",\n        )),\n    }\n}\n"
  },
  {
    "path": "crates/neon-macros/src/export/function/meta.rs",
    "content": "#[derive(Default)]\npub(crate) struct Meta {\n    pub(super) kind: Kind,\n    pub(super) name: Option<syn::LitStr>,\n    pub(super) json: bool,\n    pub(super) context: bool,\n    pub(super) this: bool,\n}\n\n#[derive(Default)]\npub(super) enum Kind {\n    Async,\n    AsyncFn,\n    #[default]\n    Normal,\n    Task,\n}\n\nimpl Meta {\n    fn set_name(&mut self, meta: syn::meta::ParseNestedMeta) -> syn::Result<()> {\n        self.name = Some(meta.value()?.parse::<syn::LitStr>()?);\n\n        Ok(())\n    }\n\n    fn force_json(&mut self, _meta: syn::meta::ParseNestedMeta) -> syn::Result<()> {\n        self.json = true;\n\n        Ok(())\n    }\n\n    fn force_context(&mut self, _meta: syn::meta::ParseNestedMeta) -> syn::Result<()> {\n        self.context = true;\n\n        Ok(())\n    }\n\n    fn force_this(&mut self, _meta: syn::meta::ParseNestedMeta) -> syn::Result<()> {\n        self.this = true;\n\n        Ok(())\n    }\n\n    fn make_async(&mut self, meta: syn::meta::ParseNestedMeta) -> syn::Result<()> {\n        if matches!(self.kind, Kind::AsyncFn) {\n            return Err(meta.error(\"`async` attribute should not be used with an `async fn`\"));\n        }\n\n        self.kind = Kind::Async;\n\n        Ok(())\n    }\n\n    fn make_task(&mut self, _meta: syn::meta::ParseNestedMeta) -> syn::Result<()> {\n        self.kind = Kind::Task;\n\n        Ok(())\n    }\n}\n\npub(crate) struct Parser(syn::ItemFn);\n\nimpl Parser {\n    pub(crate) fn new(item: syn::ItemFn) -> Self {\n        Self(item)\n    }\n}\n\nimpl syn::parse::Parser for Parser {\n    type Output = (syn::ItemFn, Meta);\n\n    fn parse2(self, tokens: proc_macro2::TokenStream) -> syn::Result<Self::Output> {\n        let Self(item) = self;\n        let mut attr = Meta::default();\n\n        if item.sig.asyncness.is_some() {\n            attr.kind = Kind::AsyncFn;\n        }\n\n        let parser = syn::meta::parser(|meta| {\n            if meta.path.is_ident(\"name\") {\n                return attr.set_name(meta);\n            }\n\n            if meta.path.is_ident(\"json\") {\n                return attr.force_json(meta);\n            }\n\n            if meta.path.is_ident(\"context\") {\n                return attr.force_context(meta);\n            }\n\n            if meta.path.is_ident(\"this\") {\n                return attr.force_this(meta);\n            }\n\n            if meta.path.is_ident(\"async\") {\n                return attr.make_async(meta);\n            }\n\n            if meta.path.is_ident(\"task\") {\n                return attr.make_task(meta);\n            }\n\n            Err(meta.error(\"unsupported property\"))\n        });\n\n        parser.parse2(tokens)?;\n\n        Ok((item, attr))\n    }\n}\n"
  },
  {
    "path": "crates/neon-macros/src/export/function/mod.rs",
    "content": "use syn::spanned::Spanned;\n\nuse crate::export::function::meta::Kind;\n\npub(crate) mod meta;\n\npub(super) fn export(meta: meta::Meta, input: syn::ItemFn) -> proc_macro::TokenStream {\n    let syn::ItemFn {\n        attrs,\n        vis,\n        sig,\n        block,\n    } = input;\n\n    let name = &sig.ident;\n\n    // Generate the context or channel argument for the function\n    let (context_extract, context_arg) = match context_parse(&meta, &sig) {\n        Ok(arg) => arg,\n        Err(err) => return err.into_compile_error().into(),\n    };\n\n    // Extract `this` if necessary\n    let has_this = check_this(&meta, &sig, context_arg.is_some());\n    let this_arg = has_this.then(|| quote::quote!(this,));\n    let this_extract = has_this.then(|| {\n        quote::quote!(\n            let this = cx.this()?;\n            let this = neon::types::extract::TryFromJs::from_js(&mut cx, this)?;\n        )\n    });\n\n    // Generate an argument list used when calling the original function\n    let num_args = count_args(&sig, context_arg.is_some(), has_this);\n    let args = (0..num_args).map(|i| quote::format_ident!(\"a{i}\"));\n\n    // Generate the tuple fields used to destructure `cx.args()`. Wrap in `Json` if necessary.\n    let tuple_fields = args.clone().map(|name| {\n        if meta.json {\n            quote::quote!(neon::types::extract::Json(#name))\n        } else {\n            quote::quote!(#name)\n        }\n    });\n\n    // Tag whether we should JSON wrap results\n    let return_tag = if meta.json {\n        quote::format_ident!(\"NeonJsonTag\")\n    } else {\n        quote::format_ident!(\"NeonValueTag\")\n    };\n\n    // Convert the result\n    // N.B.: Braces are intentionally included to avoid leaking trait to function body\n    let result_extract = quote::quote!({\n        use neon::macro_internal::{ToNeonMarker, #return_tag as NeonReturnTag};\n\n        (&res).to_neon_marker::<NeonReturnTag>().neon_into_js(&mut cx, res)\n    });\n\n    // Generate the call to the original function\n    let call_body = match meta.kind {\n        Kind::Async => quote::quote!(\n            #context_extract\n            #this_extract\n            let (#(#tuple_fields,)*) = cx.args()?;\n            let fut = #name(#context_arg #this_arg #(#args),*);\n            let fut = {\n                use neon::macro_internal::{ToNeonMarker, NeonValueTag};\n\n                (&fut).to_neon_marker::<NeonValueTag>().into_neon_result(&mut cx, fut)?\n            };\n\n            neon::macro_internal::spawn(&mut cx, fut, |mut cx, res| #result_extract)\n        ),\n        Kind::AsyncFn => quote::quote!(\n            #context_extract\n            #this_extract\n            let (#(#tuple_fields,)*) = cx.args()?;\n            let fut = #name(#context_arg #this_arg #(#args),*);\n\n            neon::macro_internal::spawn(&mut cx, fut, |mut cx, res| #result_extract)\n        ),\n        Kind::Normal => quote::quote!(\n            #context_extract\n            #this_extract\n            let (#(#tuple_fields,)*) = cx.args()?;\n            let res = #name(#context_arg #this_arg #(#args),*);\n\n            #result_extract\n        ),\n        Kind::Task => quote::quote!(\n            #context_extract\n            #this_extract\n            let (#(#tuple_fields,)*) = cx.args()?;\n            let promise = neon::context::Context::task(&mut cx, move || #name(#context_arg #this_arg #(#args),*))\n                .promise(|mut cx, res| #result_extract);\n\n            Ok(neon::handle::Handle::upcast(&promise))\n        ),\n    };\n\n    // Generate the wrapper function\n    let wrapper_name = quote::format_ident!(\"__NEON_EXPORT_WRAPPER__{name}\");\n    let wrapper_fn = quote::quote!(\n        #[doc(hidden)]\n        fn #wrapper_name(mut cx: neon::context::FunctionContext) -> neon::result::JsResult<neon::types::JsValue> {\n            #call_body\n        }\n    );\n\n    // Default export name as identity unless a name is provided\n    let export_name = meta\n        .name\n        .map(|name| quote::quote!(#name))\n        .unwrap_or_else(|| {\n            let name = crate::name::to_camel_case(&name.to_string());\n            quote::quote!(#name)\n        });\n\n    // Generate the function that is registered to create the function on addon initialization.\n    // Braces are included to prevent names from polluting user code.\n    let create_name = quote::format_ident!(\"__NEON_EXPORT_CREATE__{name}\");\n    let create_fn = quote::quote!({\n        #[doc(hidden)]\n        #[neon::macro_internal::linkme::distributed_slice(neon::macro_internal::EXPORTS)]\n        #[linkme(crate = neon::macro_internal::linkme)]\n        fn #create_name<'cx>(\n            cx: &mut neon::context::ModuleContext<'cx>,\n        ) -> neon::result::NeonResult<(&'static str, neon::handle::Handle<'cx, neon::types::JsValue>)> {\n            static NAME: &str = #export_name;\n\n            #wrapper_fn\n\n            neon::types::JsFunction::with_name(cx, NAME, #wrapper_name).map(|v| (\n                NAME,\n                neon::handle::Handle::upcast(&v),\n            ))\n        }\n    });\n\n    // Output the original function with the generated `create_fn` inside of it\n    quote::quote!(\n        #(#attrs) *\n        #vis #sig {\n            #create_fn\n            #block\n        }\n    )\n    .into()\n}\n\n// Determine the number of arguments to the function\nfn count_args(sig: &syn::Signature, has_context: bool, has_this: bool) -> usize {\n    let n = sig.inputs.len();\n\n    match (has_context, has_this) {\n        (true, true) => n - 2,\n        (false, false) => n,\n        _ => n - 1,\n    }\n}\n\n// Generate the context extraction and argument for the function\nfn context_parse(\n    opts: &meta::Meta,\n    sig: &syn::Signature,\n) -> syn::Result<(\n    Option<proc_macro2::TokenStream>,\n    Option<proc_macro2::TokenStream>,\n)> {\n    match opts.kind {\n        // Allow borrowing from context\n        Kind::Async | Kind::Normal if check_context(opts, sig)? => {\n            Ok((None, Some(quote::quote!(&mut cx,))))\n        }\n\n        // Require `'static` arguments\n        Kind::AsyncFn | Kind::Task if check_channel(opts, sig)? => Ok((\n            Some(quote::quote!(let ch = neon::context::Context::channel(&mut cx);)),\n            Some(quote::quote!(ch,)),\n        )),\n\n        _ => Ok((None, None)),\n    }\n}\n\n// Checks if a _sync_ function has a context argument and if it is valid\n// * If the `context` attribute is included, must be at least one argument\n// * Inferred to be context if named `FunctionContext` or `Cx`\n// * Context argument must be a `&mut` reference\n// * First argument must not be `Channel`\n// * Must not be a `self` receiver\nfn check_context(opts: &meta::Meta, sig: &syn::Signature) -> syn::Result<bool> {\n    // Extract the first argument\n    let ty = match first_arg(opts, sig)? {\n        Some(arg) => arg,\n        None => return Ok(false),\n    };\n\n    // Extract the reference type\n    let ty = match &*ty.ty {\n        // Tried to use a borrowed Channel\n        syn::Type::Reference(ty) if !opts.context && is_channel_type(&ty.elem) => {\n            return Err(syn::Error::new(\n                ty.elem.span(),\n                \"Expected `&mut Cx` instead of a `Channel` reference.\",\n            ))\n        }\n\n        syn::Type::Reference(ty) => ty,\n\n        // Context needs to be a reference\n        _ if opts.context || is_context_type(&ty.ty) => {\n            return Err(syn::Error::new(\n                ty.ty.span(),\n                \"Context must be a `&mut` reference.\",\n            ))\n        }\n\n        // Hint that `Channel` should be swapped for `&mut Cx`\n        _ if is_channel_type(&ty.ty) => {\n            return Err(syn::Error::new(\n                ty.ty.span(),\n                \"Expected `&mut Cx` instead of `Channel`.\",\n            ))\n        }\n\n        _ => return Ok(false),\n    };\n\n    // Not a forced or inferred context\n    if !opts.context && !is_context_type(&ty.elem) {\n        return Ok(false);\n    }\n\n    // Context argument must be mutable\n    if ty.mutability.is_none() {\n        return Err(syn::Error::new(ty.span(), \"Must be a `&mut` reference.\"));\n    }\n\n    // All tests passed!\n    Ok(true)\n}\n\n// Checks if a _async_ function has a Channel argument and if it is valid\n// * If the `context` attribute is included, must be at least one argument\n// * Inferred to be channel if named `Channel`\n// * Channel argument must not be a reference\n// * First argument must not be `FunctionContext` or `Cx`\n// * Must not be a `self` receiver\nfn check_channel(opts: &meta::Meta, sig: &syn::Signature) -> syn::Result<bool> {\n    // Extract the first argument\n    let ty = match first_arg(opts, sig)? {\n        Some(arg) => arg,\n        None => return Ok(false),\n    };\n\n    // Check the type\n    match &*ty.ty {\n        // Provided `&mut Channel` instead of `Channel`\n        syn::Type::Reference(ty) if opts.context || is_channel_type(&ty.elem) => {\n            Err(syn::Error::new(\n                ty.span(),\n                \"Expected an owned `Channel` instead of a reference.\",\n            ))\n        }\n\n        // Provided a `&mut Cx` instead of a `Channel`\n        syn::Type::Reference(ty) if is_context_type(&ty.elem) => Err(syn::Error::new(\n            ty.elem.span(),\n            \"Expected an owned `Channel` instead of a context reference.\",\n        )),\n\n        // Found a `Channel`\n        _ if opts.context || is_channel_type(&ty.ty) => Ok(true),\n\n        // Tried to use an owned `Cx`\n        _ if is_context_type(&ty.ty) => Err(syn::Error::new(\n            ty.ty.span(),\n            \"Context is not available in async functions. Try a `Channel` instead.\",\n        )),\n\n        _ => Ok(false),\n    }\n}\n\n// Extract the first argument, that may be a context, of a function\nfn first_arg<'a>(\n    opts: &meta::Meta,\n    sig: &'a syn::Signature,\n) -> syn::Result<Option<&'a syn::PatType>> {\n    // Extract the first argument\n    let arg = match sig.inputs.first() {\n        Some(arg) => arg,\n\n        // If context was forced, error to let the user know the mistake\n        None if opts.context => {\n            return Err(syn::Error::new(\n                sig.inputs.span(),\n                \"Expected a context argument. Try removing the `context` attribute.\",\n            ))\n        }\n\n        None => return Ok(None),\n    };\n\n    // Expect a typed pattern; self receivers are not supported\n    match arg {\n        syn::FnArg::Typed(ty) => Ok(Some(ty)),\n        syn::FnArg::Receiver(arg) => Err(syn::Error::new(\n            arg.span(),\n            \"Exported functions cannot receive `self`.\",\n        )),\n    }\n}\n\nfn is_context_type(ty: &syn::Type) -> bool {\n    let ident = match type_path_ident(ty) {\n        Some(ident) => ident,\n        None => return false,\n    };\n\n    ident == \"FunctionContext\" || ident == \"Cx\"\n}\n\nfn is_channel_type(ty: &syn::Type) -> bool {\n    let ident = match type_path_ident(ty) {\n        Some(ident) => ident,\n        None => return false,\n    };\n\n    ident == \"Channel\"\n}\n\n// Extract the identifier from the last segment of a type's path\nfn type_path_ident(ty: &syn::Type) -> Option<&syn::Ident> {\n    let segment = match ty {\n        syn::Type::Path(ty) => ty.path.segments.last()?,\n        _ => return None,\n    };\n\n    Some(&segment.ident)\n}\n\n// Determine if the function has a `this` argument. It will be either the `0th` element\n// or, if a context argument is included, the `1st`.\nfn check_this(opts: &meta::Meta, sig: &syn::Signature, has_context: bool) -> bool {\n    static THIS: &str = \"this\";\n\n    // Forced `this` argument\n    if opts.this {\n        return true;\n    }\n\n    // Get the first argument, skipping context\n    let first = if has_context {\n        sig.inputs.iter().nth(1)\n    } else {\n        sig.inputs.first()\n    };\n\n    // No other arguments; return early\n    let first = match first {\n        Some(first) => first,\n        None => return false,\n    };\n\n    // Ignore `self` type receivers; those aren't used for `this`\n    let ty = match first {\n        syn::FnArg::Receiver(_) => return false,\n        syn::FnArg::Typed(ty) => ty,\n    };\n\n    // Check for `this` ident or a tuple struct\n    let pat = match &*ty.pat {\n        syn::Pat::Ident(ident) if ident.ident == THIS => return true,\n        syn::Pat::TupleStruct(pat) => pat,\n        _ => return false,\n    };\n\n    // Expect exactly one element in the tuple struct\n    let elem = match pat.elems.first() {\n        Some(elem) if pat.elems.len() == 1 => elem,\n        _ => return false,\n    };\n\n    // Must be an identifier named `this`\n    match elem {\n        syn::Pat::Ident(ident) => ident.ident == THIS,\n        _ => false,\n    }\n}\n"
  },
  {
    "path": "crates/neon-macros/src/export/global/meta.rs",
    "content": "#[derive(Default)]\npub(crate) struct Meta {\n    pub(super) name: Option<syn::LitStr>,\n    pub(super) json: bool,\n}\n\npub(crate) struct Parser;\n\nimpl syn::parse::Parser for Parser {\n    type Output = Meta;\n\n    fn parse2(self, tokens: proc_macro2::TokenStream) -> syn::Result<Self::Output> {\n        let mut attr = Meta::default();\n        let parser = syn::meta::parser(|meta| {\n            if meta.path.is_ident(\"name\") {\n                attr.name = Some(meta.value()?.parse::<syn::LitStr>()?);\n\n                return Ok(());\n            }\n\n            if meta.path.is_ident(\"json\") {\n                attr.json = true;\n\n                return Ok(());\n            }\n\n            Err(meta.error(\"unsupported property\"))\n        });\n\n        parser.parse2(tokens)?;\n\n        Ok(attr)\n    }\n}\n"
  },
  {
    "path": "crates/neon-macros/src/export/global/mod.rs",
    "content": "pub(crate) mod meta;\n\n// Create a new block expression for the RHS of an assignment\npub(super) fn export(meta: meta::Meta, name: &syn::Ident, expr: Box<syn::Expr>) -> Box<syn::Expr> {\n    // Name for the registered create function\n    let create_name = quote::format_ident!(\"__NEON_EXPORT_CREATE__{name}\");\n\n    // Default export name as identity unless a name is provided\n    let export_name = meta\n        .name\n        .map(|name| quote::quote!(#name))\n        .unwrap_or_else(|| quote::quote!(stringify!(#name)));\n\n    // If `json` is enabled, wrap the value in `Json` before `TryIntoJs` is called\n    let value = if meta.json {\n        quote::quote!(neon::types::extract::Json(&#name))\n    } else {\n        quote::quote!(#name)\n    };\n\n    // Generate the function that is registered to create the global on addon initialization.\n    // Braces are included to prevent names from polluting user code.\n    //\n    // N.B.: The `linkme(..)` attribute informs the `distributed_slice(..)` macro where\n    // to find the `linkme` crate. It is re-exported from neon to avoid dependents from\n    // needing to adding a direct dependency on `linkme`. It is an undocumented feature.\n    // https://github.com/dtolnay/linkme/issues/54\n    let create_fn = quote::quote!({\n        #[doc(hidden)]\n        #[neon::macro_internal::linkme::distributed_slice(neon::macro_internal::EXPORTS)]\n        #[linkme(crate = neon::macro_internal::linkme)]\n        fn #create_name<'cx>(\n            cx: &mut neon::context::ModuleContext<'cx>,\n        ) -> neon::result::NeonResult<(&'static str, neon::handle::Handle<'cx, neon::types::JsValue>)> {\n            use neon::types::extract::TryIntoJs;\n\n            // This leverages autoderef to support several different types:\n            // * If value is `&T` and `&T: TryIntoJs`, it will deref `&&T` to `&T`\n            // * If value is `T` and `&T: TryIntoJs`, it will call as is\n            // * If value is `&T` and `T: TryIntoJs` and `Copy`, it will copy and call\n            (&#value).try_into_js(cx).map(|v| (#export_name, neon::handle::Handle::upcast(&v)))\n        }\n    });\n\n    // Create a block to hold the original expression and the registered crate function\n    let expr = quote::quote!({\n        #create_fn\n        #expr\n    });\n\n    // Create an expression from the token stream\n    Box::new(syn::Expr::Verbatim(expr))\n}\n"
  },
  {
    "path": "crates/neon-macros/src/export/mod.rs",
    "content": "mod class;\nmod function;\nmod global;\n\n// N.B.: Meta attribute parsing happens in this function because `syn::parse_macro_input!`\n// must be called from a function that returns `proc_macro::TokenStream`.\npub(crate) fn export(\n    attr: proc_macro::TokenStream,\n    item: proc_macro::TokenStream,\n) -> proc_macro::TokenStream {\n    // Parse item to determine the type of export\n    let item = syn::parse_macro_input!(item as syn::Item);\n\n    match item {\n        // Export a function\n        syn::Item::Fn(item) => {\n            let parser = function::meta::Parser::new(item);\n            let (item, meta) = syn::parse_macro_input!(attr with parser);\n\n            function::export(meta, item)\n        }\n\n        // Export a `const`\n        syn::Item::Const(mut item) => {\n            let meta = syn::parse_macro_input!(attr with global::meta::Parser);\n\n            item.expr = global::export(meta, &item.ident, item.expr);\n\n            quote::quote!(#item).into()\n        }\n\n        // Export a `static`\n        syn::Item::Static(mut item) => {\n            let meta = syn::parse_macro_input!(attr with global::meta::Parser);\n\n            item.expr = global::export(meta, &item.ident, item.expr);\n\n            quote::quote!(#item).into()\n        }\n\n        // Export a class (impl block)\n        syn::Item::Impl(item) => {\n            let meta = syn::parse_macro_input!(attr with class::meta::Parser);\n\n            class::export(meta, item)\n        }\n\n        // Return an error span for all other types\n        _ => unsupported(item),\n    }\n}\n\n// Generate an error for unsupported item types\nfn unsupported(item: syn::Item) -> proc_macro::TokenStream {\n    let span = syn::spanned::Spanned::span(&item);\n    let msg = \"`neon::export` can only be applied to functions, consts, statics, and classes (impl blocks).\";\n    let err = syn::Error::new(span, msg);\n\n    err.into_compile_error().into()\n}\n"
  },
  {
    "path": "crates/neon-macros/src/lib.rs",
    "content": "//! Procedural macros supporting [Neon](https://docs.rs/neon/latest/neon/)\n\nmod class;\nmod export;\npub(crate) mod name;\n\n#[proc_macro_attribute]\npub fn main(\n    _attr: proc_macro::TokenStream,\n    item: proc_macro::TokenStream,\n) -> proc_macro::TokenStream {\n    let syn::ItemFn {\n        attrs,\n        vis,\n        sig,\n        block,\n    } = syn::parse_macro_input!(item as syn::ItemFn);\n\n    let name = &sig.ident;\n    let export_name = quote::format_ident!(\"__NEON_MAIN__{name}\");\n    let export_fn = quote::quote!({\n        #[neon::macro_internal::linkme::distributed_slice(neon::macro_internal::MAIN)]\n        #[linkme(crate = neon::macro_internal::linkme)]\n        fn #export_name(cx: neon::context::ModuleContext) -> neon::result::NeonResult<()> {\n            #name(cx)\n        }\n    });\n\n    quote::quote!(\n        #(#attrs) *\n        #vis #sig {\n            #export_fn\n            #block\n        }\n    )\n    .into()\n}\n\n#[proc_macro_attribute]\npub fn export(\n    attr: proc_macro::TokenStream,\n    item: proc_macro::TokenStream,\n) -> proc_macro::TokenStream {\n    export::export(attr, item)\n}\n\n#[proc_macro_attribute]\npub fn class(\n    attr: proc_macro::TokenStream,\n    item: proc_macro::TokenStream,\n) -> proc_macro::TokenStream {\n    class::class(attr, item)\n}\n"
  },
  {
    "path": "crates/neon-macros/src/name.rs",
    "content": "// Convert identifiers to camel case with the following rules:\n// * All leading and trailing underscores are preserved\n// * All other underscores are removed\n// * Characters immediately following a non-leading underscore are uppercased\n// * Bail (no conversion) if an unexpected condition is encountered:\n//   - Uppercase character\n//   - More than one adjacent interior underscore\npub(crate) fn to_camel_case(name: &str) -> String {\n    let mut out = String::with_capacity(name.len());\n    let mut it = name.chars();\n    let mut next = it.next();\n    let mut count = 0usize;\n\n    // Keep leading underscores\n    while matches!(next, Some('_')) {\n        out.push('_');\n        next = it.next();\n    }\n\n    // Convert to camel case\n    while let Some(c) = next {\n        match c {\n            // Keep a count for maintaining trailing underscores\n            '_' => count += 1,\n\n            // Bail if there is an unexpected uppercase character or extra underscore\n            _ if c.is_uppercase() || count >= 2 => {\n                return name.to_string();\n            }\n\n            // Don't uppercase the middle of a word\n            _ if count == 0 => {\n                out.push(c);\n                count = 0;\n            }\n\n            // Uppercase characters following an underscore\n            _ => {\n                out.extend(c.to_uppercase());\n                count = 0;\n            }\n        }\n\n        next = it.next();\n    }\n\n    // We don't know underscores are a suffix until iteration has completed;\n    // add them back.\n    for _ in 0..count {\n        out.push('_');\n    }\n\n    out\n}\n\n// Validate JavaScript identifier names\npub(crate) fn is_valid_js_identifier(name: &str) -> bool {\n    if name.is_empty() {\n        return false;\n    }\n\n    // Check first character (must be letter, $, or _)\n    let first_char = name.chars().next().unwrap();\n    if !first_char.is_ascii_alphabetic() && first_char != '$' && first_char != '_' {\n        return false;\n    }\n\n    // Check remaining characters (must be alphanumeric, $, or _)\n    for ch in name.chars().skip(1) {\n        if !ch.is_ascii_alphanumeric() && ch != '$' && ch != '_' {\n            return false;\n        }\n    }\n\n    // Check against JavaScript reserved words\n    !matches!(\n        name,\n        \"await\"\n            | \"break\"\n            | \"case\"\n            | \"catch\"\n            | \"class\"\n            | \"const\"\n            | \"continue\"\n            | \"debugger\"\n            | \"default\"\n            | \"delete\"\n            | \"do\"\n            | \"else\"\n            | \"enum\"\n            | \"export\"\n            | \"extends\"\n            | \"false\"\n            | \"finally\"\n            | \"for\"\n            | \"function\"\n            | \"if\"\n            | \"import\"\n            | \"in\"\n            | \"instanceof\"\n            | \"new\"\n            | \"null\"\n            | \"return\"\n            | \"super\"\n            | \"switch\"\n            | \"this\"\n            | \"throw\"\n            | \"true\"\n            | \"try\"\n            | \"typeof\"\n            | \"var\"\n            | \"void\"\n            | \"while\"\n            | \"with\"\n            | \"yield\"\n            | \"let\"\n            | \"static\"\n            | \"implements\"\n            | \"interface\"\n            | \"package\"\n            | \"private\"\n            | \"protected\"\n            | \"public\"\n    )\n}\n\n#[cfg(test)]\nmod test {\n    #[test]\n    fn to_camel_case() {\n        use super::to_camel_case;\n\n        assert_eq!(to_camel_case(\"\"), \"\");\n        assert_eq!(to_camel_case(\"one\"), \"one\");\n        assert_eq!(to_camel_case(\"two_words\"), \"twoWords\");\n        assert_eq!(to_camel_case(\"three_word_name\"), \"threeWordName\");\n        assert_eq!(to_camel_case(\"extra__underscore\"), \"extra__underscore\");\n        assert_eq!(to_camel_case(\"PreserveCase\"), \"PreserveCase\");\n        assert_eq!(to_camel_case(\"PreServe_case\"), \"PreServe_case\");\n        assert_eq!(to_camel_case(\"_preserve_leading\"), \"_preserveLeading\");\n        assert_eq!(to_camel_case(\"__preserve_leading\"), \"__preserveLeading\");\n        assert_eq!(to_camel_case(\"preserve_trailing_\"), \"preserveTrailing_\");\n        assert_eq!(to_camel_case(\"preserve_trailing__\"), \"preserveTrailing__\");\n        assert_eq!(to_camel_case(\"_preserve_both_\"), \"_preserveBoth_\");\n        assert_eq!(to_camel_case(\"__preserve_both__\"), \"__preserveBoth__\");\n        assert_eq!(to_camel_case(\"_\"), \"_\");\n        assert_eq!(to_camel_case(\"__\"), \"__\");\n        assert_eq!(to_camel_case(\"___\"), \"___\");\n    }\n}\n"
  },
  {
    "path": "doc/MIGRATION_GUIDE_0.10.md",
    "content": "# Neon 0.10 Migration Guide\n\nWith the API improvements of Neon 0.10, a few backwards-incompatible changes have been introduced. This migration guide provides all the information you should need to make the (small!) code changes required for upgrading to Neon 0.10.\n\nWe have made an effort to minimize these changes, and believe they should typically lead to simpler, clearer code. **If you run into any trouble migrating your code to 0.10, please file an issue or reach out for help on the [community Slack](https://rust-bindings.slack.com/)!**\n\n# Major changes\n\n## Object property access is generic\n\nTo improve the ergonomics of the common case of downcasting the result of property access to a specific type, the signature of `Object::get()` has been changed to have a generic return type. This means that code that follows `Object::get()` with `.downcast_or_throw()` or `.downcast::<V>().or_throw()` no longer needs to do so.\n\n**Before:**\n\n```rust\nobj.get(&mut cx, \"name\")?.downcast::<V, _>(&mut cx).or_throw(&mut cx)?\n```\n\n**After (option 1):**\n\n```rust\nobj.get::<V, _, _>(&mut cx, \"name\")?\n```\n\n**After (option 2):**\n\n```rust\nlet v: Handle<V> = obj.get(&mut cx, \"name\")?\n```\n\nSince `Object::get()` throws an exception when types don't match, use the new `Object::get_value()` or `Object::get_opt()` methods for cases that accept a wider range of allowable types.\n\n**Before:**\n\n```rust\nlet field: Option<Handle<JsBoolean>> = obj\n    .get(&mut cx, \"optionalField\")?\n    .downcast(&mut cx)\n    .ok();\n```\n\n**After:**\n\n```rust\nlet field: Option<Handle<JsBoolean>> = obj.get_opt(&mut cx, \"optionalField\")?;\n```\n\n**Before:**\n\n```rust\nlet length = obj.get(&mut cx, \"length\")?;\nlet length: Option<Handle<JsNumber>> = if length.is_a::<JsNull, _>(&mut cx) {\n    None\n} else {\n    Some(length.downcast_or_throw(&mut cx)?)\n};\n```\n\n**After:**\n\n```rust\nlet length = obj.get_value(&mut cx, \"length\")?;\nlet length: Option<Handle<JsNumber>> = if length.is_a::<JsNull, _>(&mut cx) {\n    None\n} else {\n    Some(length.downcast_or_throw(&mut cx)?)\n};\n```\n\n\n## Layered APIs for function calls\n\nThe API for calling (or constructing, i.e. the Neon equivalent of the JavaScript `new` operator) a JS function has been split into two layered alternatives. The existing `.call()` and `.construct()` functions are now a lower-level primitive, which no longer offers automatic downcasting of arguments or result. But Neon 0.10 now offers a more convenient API for calling functions with an options object and method chaining, with the introduction of the `.call_with()` and `.construct_with()` methods.\n\n### Example: Calling a function\n\n**Before:**\n\n```rust\nlet s: Handle<JsString> = ...;\nlet n: Handle<JsNumber> = ...;\nlet args: Vec<Handle<JsValue>> = vec![s.upcast(), n.upcast()];\nlet this = cx.global();\nf.call(&mut cx, this, args)\n```\n\n**After (low-level API):**\n\n```rust\nlet s: Handle<JsString> = cx.string(\"hello\");\nlet n: Handle<JsNumber> = cx.number(42);\nlet this = cx.global();\nf.call(&mut cx, this, [s.upcast(), n.upcast()])\n```\n\n**After (high-level API):**\n\n```rust\nf.call_with(&cx)\n .args((cx.string(\"hello\"), cx.number(42)))\n .apply(&mut cx)\n```\n\n### Example: Constructing with a function\n\n**Before:**\n\n```rust\nlet s: Handle<JsString> = ...;\nlet n: Handle<JsNumber> = ...;\nlet args: Vec<Handle<JsValue>> = vec![s.upcast(), n.upcast()];\nf.construct(&mut cx, args)\n```\n\n**After (low-level API):**\n\n```rust\nlet s: Handle<JsString> = ...;\nlet n: Handle<JsNumber> = ...;\nf.construct(&mut cx, [s.upcast(), n.upcast()])\n```\n\n**After (high-level API):**\n\n```rust\nlet s: Handle<JsString> = ...;\nlet n: Handle<JsNumber> = ...;\nf.construct_with(&cx)\n .args((s, n))\n .apply(&mut cx)\n```\n\n## Idiomatic typed arrays\n\nNeon 0.10 replaces the previous typed array API with a more idiomatic API. JavaScript typed arrays (e.g. [`Uint32Array`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint32Array)) can be represented with corresponding Rust types (e.g. [`JsTypedArray<u32>`](https://docs.rs/neon/0.10.0-alpha.3/neon/types/struct.JsTypedArray.html)), allowing easy access to their internals as Rust slices.\n\n### Example: Reading a buffer\n\n**Before:**\n\n```rust\nlet b: Handle<JsArrayBuffer> = ...;\n{\n    let guard = cx.lock();\n    let data = b.borrow(&guard);\n    let slice = data.as_slice::<u32>();\n    ...\n}\n```\n\n**After:**\n\n```rust\nlet b: Handle<JsTypedArray<u32>> = ...;\nlet slice = b.as_slice(&cx);\n```\n\n### Example: Reading and writing buffers\n\n**Before:**\n\n```rust\nlet b1: Handle<JsArrayBuffer> = ...;\nlet b2: Handle<JsArrayBuffer> = ...;\n{\n    let guard = cx.lock();\n    let data1 = b1.borrow(&guard);\n    let data2 = b2.borrow(&guard);\n    let slice1 = data1.as_slice::<u32>();\n    let slice2 = data2.as_slice::<u32>();\n    ...\n}\n```\n\n**After:**\n\n```rust\nlet src_buf: Handle<JsTypedArray<u32>> = ...;\nlet dst_buf: Handle<JsTypedArray<u32>> = ...;\n{\n    let lock = cx.lock();\n    let src = src_buf.as_slice(&lock).unwrap();\n    let dst = dst_buf.as_mut_slice(&lock).unwrap();\n    ...\n}\n```\n\n### Example: Casting buffer types\n\nPrevious versions of Neon came with a special datatype for casting the data of an ArrayBuffer, but this had incomplete handling of unaligned data and is deprecated in Neon 0.10. Crates like [bytemuck](https://crates.io/crates/bytemuck) can be used for casting buffer slices.\n\n**Before:**\n\n```rust\nlet b: Handle<JsArrayBuffer> = ...;\n{\n    let guard = cx.lock();\n    let data = b.borrow(&guard);\n    let u8_slice = data.as_slice::<u8>();\n    let f32_slice = data.as_slice::<f32>();\n    ...\n}\n```\n\n**After:**\n\n```rust\nuse bytemuck::cast_slice;\n\nlet b: Handle<JsArrayBuffer> = ...;\nlet u8_slice = b.as_slice(&cx);\nlet f32_slice: &[f32] = cast_slice(u8_slice);\n```\n\n# Minor changes\n\n## Uncaught errors in tasks\n\nStarting with 0.10, uncaught errors (whether Rust panics or JavaScript exceptions) in a task are now captured and reported to Node as an [`unhandledRejection ` event](https://nodejs.org/api/process.html#event-unhandledrejection). Previously, an uncaught JavaScript exception would be ignored. To handle uncaught exceptions, either wrap the body of a task with [`try_catch`](https://docs.rs/neon/0.10.0-alpha.3/neon/context/trait.Context.html#method.try_catch) or, alternatively, capture all uncaught rejections in Node with `process.on(\"unhandledRejection, (err) => {})`.\n\n**Before:**\n\n```rust\ncx.task(|| \"hello\".to_string())\n  .and_then(|mut cx, _| {\n      cx.throw_error(\"ignore me\")\n  })\n```\n\n**After:**\n\n```rust\ncx.task(|| \"hello\".to_string())\n  .and_then(|mut cx, _| {\n      let _ = cx.try_catch(() {\n          cx.throw_error(\"ignore me\")\n      });\n      Ok(())\n  })\n```\n\n## `Channel::send` returns `JoinHandle`\n\nThe [`Channel::send()`](https://docs.rs/neon/0.10.0-alpha.3/neon/event/struct.Channel.html#method.send) method now returns a [`JoinHandle`](https://docs.rs/neon/0.10.0-alpha.3/neon/event/struct.JoinHandle.html) type instead of `()`, allowing code to optionally and conveniently block on the result with [`JoinHandle::join()`](https://docs.rs/neon/0.10.0-alpha.3/neon/event/struct.JoinHandle.html#method.join). Non-blocking code should usually work with little to no change; sometimes a semicolon may be needed to explicitly ignore the `JoinHandle`.\n\n**Before:**\n\n```rust\nfn helper<'a, C: Context<'a>>(cx: &mut C, ch: Channel) {\n    ch.send(...)\n}\n```\n\n**After:**\n\n```rust\nfn helper<'a, C: Context<'a>>(cx: &mut C, ch: Channel) {\n    ch.send(...);\n}\n```\n\n## Value types aren't cloneable\n\nPrevious versions of Neon had a safety bug in allowing types that implement the [`Value`](https://docs.rs/neon/0.10.0-alpha.3/neon/types/trait.Value.html) trait to be cloned. This has been fixed in Neon 0.10. It should be rare for code to ever need to clone a value. In most cases where this may be occurring, a [`Handle`](https://docs.rs/neon/0.10.0-alpha.3/neon/handle/struct.Handle.html) or reference (`&`) should work. For longer-lived use cases such as storing a value in a Rust static variable, use a [`Root`](https://docs.rs/neon/0.10.0-alpha.3/neon/handle/struct.Root.html).\n\n**Before:**\n\n```rust\nfn helper<'a, C: Context<'a>>(cx: &mut C, s: JsString) -> ... {\n    ...\n}\n```\n\n**After:**\n\n```rust\nfn helper<'a, C: Context<'a>>(cx: &mut C, s: Handle<JsString>) -> ... {\n    ...\n}\n```\n\n## Context methods now all take `&mut self`\n\nContext methods such as [`execute_scoped`](https://docs.rs/neon/0.10.0-alpha.3/neon/context/trait.Context.html#method.execute_scoped), [`compute_scoped`](https://docs.rs/neon/0.10.0-alpha.3/neon/context/trait.Context.html#method.compute_scoped), and [`lock`](https://docs.rs/neon/0.10.0-alpha.3/neon/context/trait.Context.html#method.lock) all take `&mut self` instead of the previous `&self`. This was necessary for safety and is more consistent with other `Context` methods. In normal usage, this should not require code changes.\n\n## `Throw` is unconstructable\n\nThe [`Throw`](https://docs.rs/neon/0.10.0-alpha.3/neon/result/struct.Throw.html) type can no longer be explicitly constructed, and cannot be shared across threads. This makes it harder to accidentally mis-report a [`NeonResult`](https://docs.rs/neon/0.10.0-alpha.3/neon/result/type.NeonResult.html) value by reusing a stale `Throw` value. Existing code that uses `Throw` for application-specific use cases should use a custom struct or enum instead.\n"
  },
  {
    "path": "doc/MIGRATION_GUIDE_1.0.0.md",
    "content": "# Neon 1.0.0 Migration Guide\n\n> **Note:** This migration guide assumes a project is using Neon 0.10 without Node-API backend. If using an older version or the legacy backend, see the [previous migration guide](MIGRATION_GUIDE_0.10.md). \n\nThe Neon 1.0 has stabilized and brings a more consistent and ergonomic API. There are a few (minor) breaking changes and this guide will help walk through them! \n\n## Removed Traits\n\nA few traits have been removed because they were either redundant or only used for features that no longer exist.\n\n### `Managed`\n\nThe `Managed` trait marked values that were _managed_ by the JavaScript VM. It was redundant with the `Value` trait. Trait bounds referencing `Managed` may be either removed or replaced with `Value`.\n\n#### Before\n\n```rust\nfn example<V>(h: Handle<V>)\nwhere\n    V: Managed,\n{\n}\n```\n\n#### After\n\n```rust\nfn example<V>(h: Handle<V>)\nwhere\n    V: Value,\n{\n}\n```\n\n### `CallContext`, `This`, and `T` in `JsFunction<T>`\n\nThe `This` trait marked values for `cx.this()` in `JsFunction`. However, it was not type checked and could result in a panic at runtime. Instead, `cx.this()` always returns a `JsValue`. Since, `JsFunction`'s `T` parameter had a default, in many cases no changes are necessary. In some cases, the `T` parameter will need to be removed and a `downcast` added.\n\n#### Before\n\n```rust\n// `CallContext<JsObject>` is equivalent to `FunctionContext`\nfn example(mut cx: CallContext<JsObject>) -> JsResult<JsUndefined> {\n    let a = cx.this().get::<JsValue, _, _>(&mut cx, \"a\")?;\n\n    Ok(cx.undefined())\n}\n```\n\n#### After\n\n```rust\nfn example(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let a = cx.this::<JsObject>()?.get::<JsValue, _, _>(&mut cx, \"a\")?;\n\n    Ok(cx.undefined())\n}\n```\n\n### `JsResultExt`\n\nThe `JsResultExt` trait provided a `.or_throw(&mut cx)` to allow converting a Rust error into a JavaScript exception. However, it required `T: Value`. It has been replaced with a more generic `ResultExt` trait. Most usages only require replacing `JsResultExt` with `ResultExt`. In some cases, an additional `T: Value` bound will need to be added or removed.\n\n#### Before\n\n```rust\nuse neon::result::JsResultExt;\n```\n\n#### After\n\n```rust\nuse neon::result::ResultExt;\n```\n\n## `usize` indexes and lengths\n\nNeon inconsistently used `u32`, `usize`, and sometimes even `i32` for indexes and lengths. For consistency with Rust, `usize` is used everywhere. Update explicit types to use `usize` and remove type casting. Implicit types do not need to be updated.\n\n#### Before\n\n```rust\nfn example(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let arr = cx.empty_array();\n    let msg = cx.string(\"Hello!\");\n\n    arr.set(&mut cx, 0u32, msg)?;\n\n    Ok(cx.undefined())\n}\n```\n\n#### After\n\n```rust\nfn example(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let arr = cx.empty_array();\n    let msg = cx.string(\"Hello!\");\n\n    arr.set(&mut cx, 0usize, msg)?;\n\n    Ok(cx.undefined())\n}\n```\n\n## Feature Flags\n\nNeon `0.10` made extensive use of feature flags for features that had not been stabilized (e.g., `try-catch-api`, `channel-api`). All features have been stabilized and the feature flags removed. Resolve by removing these features from the project's `Cargo.toml`.\n\nTwo feature flags are still exist: `napi-N` for the Node-API version and `futures` for compatibility between Rust `Future` and JavaScript `Promise`.\n"
  },
  {
    "path": "doc/MIGRATION_GUIDE_NAPI.md",
    "content": "# N-API Migration Guide\n\n## What is this about?\n\nSince v10, Node.js supports an improved API for building native modules, known as [N-API](https://nodejs.org/api/n-api.html). N-API offers a clearer, more complete, and more stable API layer for writing Node.js plugins than previous Node versions did.\n\nThe Neon community has been [hard at work](https://github.com/neon-bindings/neon/issues/444) porting the library to a new backend based on N-API.\n\n### Why N-API?\n\nSome key benefits of the new backend include:\n- Compiled Neon modules will work in all versions of Node _without needing to be recompiled_, guaranteed!\n- You can precompile Neon-based libraries to be completely transparent to downstream consumers.\n- The build process is streamlined, making Neon apps more reliable and easier to debug.\n- The stability guarantees of N-API allow us to avoid risk of incompatible changes to future releases of Neon.\n\n### What does this mean for me?\n\nPorting Neon to N-API has been mostly transparent, but it has required a few backwards-incompatible changes. This guide provides instructions on how to migrate existing apps to the new N-API backend.\n\nFortunately, the guaranteed stability of N-API means that once Neon users do this migration, we have increased confidence in the stability of Neon. We expect this to be the **last major breaking change before reaching Neon 1.0.**\n\nIf you have any trouble porting, **please reach out to us** with a Neon issue or on the community Slack! We want to help everyone upgrade as smoothly and seamlessly as possible.\n\n\n## Getting started\n\n### Supported Node versions\n\nThe N-API backend of Neon requires a minimum Node version of 10.0.\n\n### Enabling the N-API backend\n\nTo enable the N-API backend, you need to:\n\n1. Remove `build.rs` from the project directory and `build = \"build.rs\"` from the `Cargo.toml`. The N-API backend does not require a Cargo build script.\n2. Disable the default features (for now, the default features select the legacy backend) by setting `default-features = false`; and\n3. Enable the appropriate feature flag in your `Cargo.toml` to select the N-API version you need support for (each N-API version N uses the feature flag `\"napi-N\"`, for example `\"napi-4\"` for N-API version 4).\n\nAs a rule, you should choose the **oldest version of N-API that has the APIs you need.** (We will be adding N-API version requirements to the Neon API docs to make this clearer in the future.) You can consult the [official N-API feature matrix](https://nodejs.org/api/n-api.html#n_api_node_api_version_matrix) to see which N-API versions come with various versions of Node.\n\n```toml\n[dependencies.neon]\nversion = \"0.9.1\"\ndefault-features = false\nfeatures = [\"napi-4\"]\n```\n\n\n## Minor API changes\n\n### Context\n\nMany methods that previously did not require context (e.g., `JsString::size`) now require a context. In many cases, this means adding an additional argument or using a convenience method on the `Context` trait.\n\n#### Affected methods\n\n##### Handle\n\n* `Handle`\n    - `is_a`\n    - `downcast`\n\n`Handle::downcast` also requires a second type argument for the context type. This can usually be inferred, so you can typically use `_`.\n\n**Before:**\n```rust\nvalue.downcast::<JsNumber>()\n```\n\n**After:**\n\n```rust\nvalue.downcast::<JsNumber, _>(&mut cx)\n```\n\n##### Primitive types\n\n* `JsBoolean`\n    - `value`\n* `JsNull`\n    - `new`\n* `JsString`\n    - `size`\n    - `value`\n* `JsNumber`\n    - `value`\n* `JsUndefined`\n    - `new`\n\n##### Object APIs\n\n* `PropertyKey`\n    - `get_from`\n    - `set_from`\n\n### Handle equality\n\nHandles no longer implement `Eq` or `PartialEq`, which had underspecified behavior. Use `Value::strict_equals` instead to invoke the behavior of JavaScript's `===` operator.\n\n## Major API changes\n\nThe N-API backend introduces two categories of significant change:\n\n1. Embedding Rust data, which is no longer done through the awkward and complex `declare_types!` (i.e. classes) macro, but through a simpler primitive: the `JsBox` API.\n2. Concurrency, which is offered through the Event Queue API instead of the Task API or Event Handlers, both of which are deprecated and removed in the N-API backend.\n\n### Embedding Rust data\n\nThe `declare_types!` macro is deprecated and replaced by the `JsBox` type.\n\n_Rationale:_ The `declare_types!` macro provides a syntax for defining classes, but requires substantial boilerplate and is unergonomic for simple cases and tends to interact poorly with IDEs. It's also not flexible enough to express the full range of JavaScript classes syntax and semantics. With the `JsBox` type, it's easy to embed Rust data in JavaScript objects, which can then be nested inside of more feature-rich classes defined in pure JavaScript (or TypeScript).\n\n**Before:**\n\n```rust\nstruct User {\n    first_name: String,\n    last_name: String,\n}\n\nimpl User {\n    fn full_name(&self) -> String {\n        format!(\"{} {}\", self.first_name, self.last_name)\n    }\n}\n\ndeclare_types! {\n    class JsUser for User {\n        init(mut cx) {\n            let first_name = cx.argument::<JsString>(0)?;\n            let last_name = cx.argument::<JsString>(1)?;\n            Ok(User { first_name, last_name })\n        }\n\n        method full_name(mut cx) {\n            let this = cx.this();\n            let guard = cx.lock();\n            let user = this.borrow(&guard);\n            let full_name = user.full_name();\n            Ok(cx.string(full_name).upcast())\n        }\n    }\n}\n```\n\n**After:**\n\nOn the Rust side, the wrapped type must implement the `Finalize` trait, but this comes with a default implementation so it can be implemented with an empty `impl` block:\n\n```rust\nstruct User {\n    first_name: String,\n    last_name: String,\n}\n\nimpl Finalize for User { }\n```\n\nThe type can then be exposed to JavaScript with simple functions that wrap `User` in a `JsBox`:\n\n```rust\nfn create_user(mut cx: FunctionContext) -> JsResult<JsBox<User>> {\n    let first_name = cx.argument::<JsString>(0)?.value(&mut cx);\n    let last_name = cx.argument::<JsString>(1)?.value(&mut cx);\n    Ok(cx.boxed(User { first_name, last_name }))\n}\n\nfn user_full_name(mut cx: FunctionContext) -> JsResult<JsString> {\n    let user = cx.argument::<JsBox<User>>(0)?;\n    let full_name = user.full_name();\n    Ok(cx.string(full_name))\n}\n```\n\nFinally, you can provide an idiomatic JavaScript interface to the type by wrapping the boxed type in a class:\n\n```js\nclass User {\n    constructor(firstName, lastName) {\n        this.boxed = addon.createUser(firstName, lastName);\n    }\n\n    fullName() {\n        return addon.userFullName(this.boxed);\n    }\n}\n```\n\n### Concurrency\n\nThe supported mechanism for concurrency is the Channel API (`neon::event::Channel`). This feature has not yet stabilized, so to use this API, you'll also need to enable the `\"channel-api\"` feature flag as well:\n\n```toml\n[dependencies.neon]\nversion = \"0.9.1\"\ndefault-features = false\nfeatures = [\"napi-6\", \"channel-api\"]\n```\n\n#### Deprecated: Task API\n\nThe Task API (`neon::task`) is deprecated, and should in most cases be translated to using the Event Queue API.\n\n_Rationale:_ The Task API was built on top of the low-level libuv thread pool, which manages the concurrency of the Node.js system internals and should rarely be exposed to user-level programs. For most use cases, Neon users took advantage of this API as the only way to implement background, asynchronous computations. The Event Queue API is a more general-purpose, convenient, and safe way of achieving that purpose.\n\nThat said, **if you believe you need access to the libuv thread pool, please [file an issue in the Neon repository](https://github.com/neon-bindings/neon/issues) with a description of your use case to let us know about it.** We don't believe this is commonly needed, but we don't want to leave you stuck! \n\n**Before:**\n\nWith the `Task` API it was possible to define background computations off the main JavaScript thread, but these could only be run within the libuv thread pool--which runs all the system logic for the internals of Node.js. This gave Neon programmers a real power but forced them to contend with Node.js system tasks.\n\n```rust\nimpl Task for MyTask {\n    type Output = i32;\n    type Error = String;\n    type JsEvent = JsNumber;\n\n    fn perform(&self) -> Result<Self::Output, Self::Error> {\n        // compute the result...\n    }\n\n    fn complete(self, mut cx: TaskContext, result: Result<Self::Output, Self::Error>) -> JsResult<Self::JsEvent> {\n        match result {\n            Ok(n) => {\n                Ok(cx.number(n))\n            }\n            Err(s) => {\n                cx.throw_error(s)\n            }\n        }\n    }\n}\n\npub fn start_task(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let callback = cx.argument::<JsFunction>(0)?;\n    MyTask.schedule(callback);\n    Ok(cx.undefined())\n}\n```\n\n**After:**\n\nWith the N-API backend, Neon programmers can use their own native threads and avoid competing with the Node.js system internals. This also brings some convenience since it doesn't require defining any custom trait implementations.\n\n```rust\npub fn start_task(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let callback = cx.argument::<JsFunction>(0)?.root(&mut cx);\n    let queue = cx.queue();\n\n    std::thread::spawn(move || {\n        let result = // compute the result...\n        queue.send(move |mut cx| {\n            let callback = callback.into_inner(&mut cx);\n            let this = cx.undefined();\n            let args = match result {\n                Ok(n) => vec![\n                    cx.null().upcast::<JsValue>(),\n                    cx.number(result).upcast()\n                ],\n                Err(msg) => vec![\n                    cx.error(msg).upcast()\n                ]\n            };\n            callback.call(&mut cx, this, args)?;\n            Ok(())\n        });\n    });\n\n    Ok(cx.undefined())\n}\n```\n\n#### Deprecated: Event Handler API\n\nThe Event Handler API (`neon::event::EventHandler`) is deprecated and should be replaced by the Event Queue API.\n\n_Rationale_: The Event Handler API had multiple issues with safety, memory leaks, and ergonomics ([1](https://github.com/neon-bindings/neon/issues/551), [2](https://github.com/neon-bindings/rfcs/issues/31)).\n\n**Before:**\n\n```rust\npub fn start_task(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let callback = cx.argument::<JsFunction>(0)?;\n    let handler = EventHandler::new(callback);\n    thread::spawn(move || {\n        let result = // compute the result...\n        handler.schedule(move |cx| {\n            vec![cx.number(result).upcast()]\n        });\n    });\n    Ok(cx.undefined())\n}\n```\n\n**After:**\n\n```rust\npub fn start_task(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let callback = cx.argument::<JsFunction>(0)?.root(&mut cx);\n    let queue = cx.queue();\n\n    std::thread::spawn(move || {\n        let result = // compute the result...\n        queue.send(move |mut cx| {\n            let callback = callback.into_inner(&mut cx);\n            let this = cx.undefined();\n            let args = vec![\n                cx.null().upcast::<JsValue>(),\n                cx.number(result).upcast()\n            ];\n            callback.call(&mut cx, this, args)?;\n            Ok(())\n        });\n    });\n\n    Ok(cx.undefined())\n}\n```\n\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"neon-workspace\",\n  \"private\": true,\n  \"scripts\": {\n    \"prettier\": \"prettier -w \\\"**/*.{js,json,ts,yml}\\\"\",\n    \"prettier:check\": \"prettier -c \\\"**/*.{js,json,ts,yml}\\\"\",\n    \"test\": \"npm run test:rust && npm run test:js\",\n    \"test:rust\": \"cargo neon-test\",\n    \"test:js\": \"npm test --workspaces --if-present\"\n  },\n  \"workspaces\": [\n    \"pkgs/*\",\n    \"test/*\",\n    \"bench\"\n  ],\n  \"devDependencies\": {\n    \"prettier\": \"^2.7.1\"\n  }\n}\n"
  },
  {
    "path": "pkgs/cargo-cp-artifact/LICENSE",
    "content": "MIT License\n\nCopyright (c) 2021 The Neon Project\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "pkgs/cargo-cp-artifact/README.md",
    "content": "# cargo-cp-artifact\n\n`cargo-cp-artifact` is a small command line utility for parsing cargo metadata output and copying a compiler artifact to a desired location.\n\n## Installation\n\n```sh\nnpm install -g cargo-cp-artifact\n```\n\n## Usage\n\n```\ncargo-cp-artifact --artifact artifact-kind crate-name output-file -- wrapped-command\n```\n\n`cargo-cp-artifact` accepts a list of crate name and artifact kind to output file mappings and a command to wrap.`cargo-cp-artifact` will read `stdout` of the wrapped command and parse it as [cargo metadata](https://doc.rust-lang.org/cargo/reference/external-tools.html#json-messages). Compiler artifacts that match arguments provided will be copied to the target destination.\n\nWhen wrapping a `cargo` command, it is necessary to include a `json` format to `--message-format`.\n\n### Arguments\n\nMultiple arguments are allowed to copy multiple build artifacts.\n\n#### `--artifact`\n\n_Alias: `-a`_\n\nFollowed by *three* arguments: `artifact-kind crate-name output-file`\n\n#### `--npm`\n\n_Alias: `-n`_\n\nFollowed by *two* arguments: `artifact-kind output-file`\n\nThe crate name will be read from the `npm_package_name` environment variable. If the package name includes a namespace (`@namespace/package`), the namespace will be removed when matching the crate name (`package`).\n\n### Artifact Kind\n\nValid artifact kinds are `bin`, `cdylib`, and `dylib`. They may be abbreviated as `b`, `c`, and `d` respectively.\n\nFor example, `-ac` is the equivalent of `--artifact cdylib`.\n\n## Examples\n\n### Wrapping cargo\n\n```sh\ncargo-cp-artifact -a cdylib my-crate lib/index.node -- cargo build --message-format=json-render-diagnostics\n```\n\n### Parsing a file\n\n```sh\ncargo-cp-artifact -a cdylib my-crate lib/index.node -- cat build-output.txt\n```\n\n### `npm` script\n\n`package.json`\n```json\n{\n    \"name\": \"my-crate\",\n    \"scripts\": {\n        \"build\": \"cargo-cp-artifact -nc lib/index.node -- cargo build --message-format=json-render-diagnostics\"\n    }\n}\n```\n\n```sh\nnpm run build\n\n# Additional arguments may be passed\nnpm run build -- --feature=serde\n```\n\n## Why does this exist?\n\nAt the time of writing, `cargo` does not include a configuration for outputting a library or binary to a specified location. An `--out-dir` option [exists on nightly](https://github.com/rust-lang/cargo/issues/6790), but does not allow specifying the name of the file.\n\nIt's surprisingly difficult to reliably find the location of a cargo compiler artifact. It is impacted by many parameters, including:\n\n* Build profile\n* Target, default or specified\n* Crate name and name transforms\n\nHowever, `cargo` can emit metadata on `stdout` while continuing to provide human readable diagnostics on `stderr`. The metadata may be parsed to more easily and reliably find the location of compiler artifacts.\n\n`cargo-cp-artifact` chooses to wrap a command as a child process instead of reading `stdin` for two reasons:\n\n1. Removes the need for `-o pipefile` when integrating with build tooling which may need to be platform agnostic.\n2. Allows additional arguments to be provided when used in an [`npm` script](https://docs.npmjs.com/cli/v6/using-npm/scripts).\n"
  },
  {
    "path": "pkgs/cargo-cp-artifact/bin/cargo-cp-artifact.js",
    "content": "#!/usr/bin/env node\n\"use strict\";\n\nconst run = require(\"..\");\n\nrun(process.argv.slice(2), process.env);\n"
  },
  {
    "path": "pkgs/cargo-cp-artifact/package.json",
    "content": "{\n  \"name\": \"cargo-cp-artifact\",\n  \"version\": \"0.1.9\",\n  \"description\": \"Copies compiler artifacts emitted by rustc by parsing Cargo metadata\",\n  \"main\": \"src/index.js\",\n  \"files\": [\n    \"bin\",\n    \"src\"\n  ],\n  \"bin\": {\n    \"cargo-cp-artifact\": \"bin/cargo-cp-artifact.js\"\n  },\n  \"scripts\": {\n    \"test\": \"mocha test\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/neon-bindings/neon.git\"\n  },\n  \"keywords\": [\n    \"cargo\",\n    \"rust\",\n    \"neon\"\n  ],\n  \"author\": \"K.J. Valencik\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/neon-bindings/neon/issues\"\n  },\n  \"homepage\": \"https://github.com/neon-bindings/neon/tree/main/pkgs/cargo-cp-artifact\",\n  \"devDependencies\": {\n    \"mocha\": \"^10.2.0\"\n  }\n}\n"
  },
  {
    "path": "pkgs/cargo-cp-artifact/src/args.js",
    "content": "\"use strict\";\n\nclass ParseError extends Error {}\n\nconst NPM_ENV = \"npm_package_name\";\nconst EXPECTED_COMMAND = [\n  \"Missing command to execute.\",\n  [\n    \"cargo-cp-artifact -a cdylib my-crate index.node\",\n    \"--\",\n    \"cargo build --message-format=json-render-diagnostics\",\n  ].join(\" \"),\n].join(\"\\n\");\n\nfunction validateArtifactType(artifactType) {\n  switch (artifactType) {\n    case \"b\":\n    case \"bin\":\n      return \"bin\";\n    case \"c\":\n    case \"cdylib\":\n      return \"cdylib\";\n    case \"d\":\n    case \"dylib\":\n      return \"dylib\";\n    default:\n  }\n\n  throw new ParseError(`Unexpected artifact type: ${artifactType}`);\n}\n\nfunction getArtifactName({ artifactType, crateName }) {\n  return `${artifactType}:${crateName}`;\n}\n\nfunction getCrateNameFromEnv(env) {\n  if (!env.hasOwnProperty(NPM_ENV)) {\n    throw new ParseError(\n      [\n        `Could not find the \\`${NPM_ENV}\\` environment variable.`,\n        \"Expected to be executed from an `npm` command.\",\n      ].join(\" \")\n    );\n  }\n\n  const name = env[NPM_ENV];\n  const firstSlash = name.indexOf(\"/\");\n\n  // This is a namespaced package; assume the crate is the un-namespaced version\n  if (name[0] === \"@\" && firstSlash > 0) {\n    return name.slice(firstSlash + 1);\n  }\n\n  return name;\n}\n\nfunction parse(argv, env) {\n  const artifacts = {};\n  let tokens = argv;\n\n  function getNext() {\n    if (!tokens.length) {\n      throw new ParseError(EXPECTED_COMMAND);\n    }\n\n    const next = tokens[0];\n    tokens = tokens.slice(1);\n    return next;\n  }\n\n  function getArtifactType(token) {\n    if (token[1] !== \"-\" && token.length === 3) {\n      return validateArtifactType(token[2]);\n    }\n\n    return validateArtifactType(getNext());\n  }\n\n  function pushArtifact(artifact) {\n    const name = getArtifactName(artifact);\n\n    artifacts[name] = artifacts[name] || [];\n    artifacts[name].push(artifact.outputFile);\n  }\n\n  while (tokens.length) {\n    const token = getNext();\n\n    // End of CLI arguments\n    if (token === \"--\") {\n      break;\n    }\n\n    if (\n      token === \"--artifact\" ||\n      (token.length <= 3 && token.startsWith(\"-a\"))\n    ) {\n      const artifactType = getArtifactType(token);\n      const crateName = getNext();\n      const outputFile = getNext();\n\n      pushArtifact({ artifactType, crateName, outputFile });\n      continue;\n    }\n\n    if (token === \"--npm\" || (token.length <= 3 && token.startsWith(\"-n\"))) {\n      const artifactType = getArtifactType(token);\n      const crateName = getCrateNameFromEnv(env);\n      const outputFile = getNext();\n\n      pushArtifact({ artifactType, crateName, outputFile });\n      continue;\n    }\n\n    throw new ParseError(`Unexpected option: ${token}`);\n  }\n\n  if (!tokens.length) {\n    throw new ParseError(EXPECTED_COMMAND);\n  }\n\n  const cmd = getNext();\n\n  return {\n    artifacts,\n    cmd,\n    args: tokens,\n  };\n}\n\nmodule.exports = { ParseError, getArtifactName, parse };\n"
  },
  {
    "path": "pkgs/cargo-cp-artifact/src/index.js",
    "content": "\"use strict\";\n\nconst { spawn } = require(\"child_process\");\nconst {\n  promises: { copyFile, mkdir, stat, unlink },\n} = require(\"fs\");\nconst { dirname, extname } = require(\"path\");\nconst readline = require(\"readline\");\n\nconst { ParseError, getArtifactName, parse } = require(\"./args\");\n\nfunction run(argv, env) {\n  const options = parseArgs(argv, env);\n  const copied = {};\n\n  const cp = spawn(options.cmd, options.args, {\n    stdio: [\"inherit\", \"pipe\", \"inherit\"],\n    shell: process.platform === \"win32\",\n  });\n\n  const rl = readline.createInterface({ input: cp.stdout });\n\n  cp.on(\"error\", (err) => {\n    if (options.cmd === \"cargo\" && err.code === \"ENOENT\") {\n      console.error(`Error: could not find the \\`cargo\\` executable.\n\nYou can find instructions for installing Rust and Cargo at:\n\n    https://www.rust-lang.org/tools/install\n\n`);\n    } else {\n      console.error(err);\n    }\n    process.exitCode = 1;\n  });\n\n  cp.on(\"exit\", (code) => {\n    if (!process.exitCode) {\n      process.exitCode = code;\n    }\n  });\n\n  rl.on(\"line\", (line) => {\n    try {\n      processCargoBuildLine(options, copied, line);\n    } catch (err) {\n      console.error(err);\n      process.exitCode = 1;\n    }\n  });\n\n  process.on(\"exit\", () => {\n    Object.keys(options.artifacts).forEach((name) => {\n      if (!copied[name]) {\n        console.error(`Did not copy \"${name}\"`);\n\n        if (!process.exitCode) {\n          process.exitCode = 1;\n        }\n      }\n    });\n  });\n}\n\nfunction processCargoBuildLine(options, copied, line) {\n  const data = JSON.parse(line);\n  const { filenames, reason, target } = data;\n\n  if (!data || reason !== \"compiler-artifact\" || !target) {\n    return;\n  }\n\n  const { kind: kinds, name } = data.target;\n\n  if (!Array.isArray(kinds) || !Array.isArray(filenames)) {\n    return;\n  }\n\n  // `kind` and `filenames` zip up as key/value pairs\n  kinds.forEach((kind, i) => {\n    const filename = filenames[i];\n    const { key, outputFiles } =\n      getOutputFiles(kind, name, options.artifacts) || {};\n\n    if (!outputFiles || !filename) {\n      return;\n    }\n\n    Promise.all(\n      outputFiles.map((outputFile) => copyArtifact(filename, outputFile))\n    )\n      .then(() => {\n        copied[key] = true;\n      })\n      .catch((err) => {\n        process.exitCode = 1;\n        console.error(err);\n      });\n  });\n}\n\nfunction getOutputFiles(kind, name, artifacts) {\n  const key = getArtifactName({ artifactType: kind, crateName: name });\n  const outputFiles = artifacts[key];\n\n  if (outputFiles) {\n    return { key, outputFiles };\n  }\n\n  // Cargo started replacing `-` with `_` in artifact names. Reverse the process\n  // and check again. https://github.com/rust-lang/cargo/issues/13867\n  const altKey = key.replace(/_/g, \"-\");\n\n  return {\n    key: altKey,\n    outputFiles: artifacts[altKey],\n  };\n}\n\nasync function isNewer(filename, outputFile) {\n  try {\n    const prevStats = await stat(outputFile);\n    const nextStats = await stat(filename);\n\n    return nextStats.mtime > prevStats.mtime;\n  } catch (_err) {}\n\n  return true;\n}\n\nasync function copyArtifact(filename, outputFile) {\n  if (!(await isNewer(filename, outputFile))) {\n    return;\n  }\n\n  const outputDir = dirname(outputFile);\n\n  // Don't try to create the current directory\n  if (outputDir && outputDir !== \".\") {\n    await mkdir(outputDir, { recursive: true });\n  }\n\n  // Apple Silicon (M1, etc.) requires shared libraries to be signed. However,\n  // the macOS code signing cache isn't cleared when overwriting a file.\n  // Deleting the file before copying works around the issue.\n  //\n  // Unfortunately, this workaround is incomplete because the file must be\n  // deleted from the location it is loaded. If further steps in the user's\n  // build process copy or move the file in place, the code signing cache\n  // will not be cleared.\n  //\n  // https://github.com/neon-bindings/neon/issues/911\n  if (extname(outputFile) === \".node\") {\n    try {\n      await unlink(outputFile);\n    } catch (_e) {\n      // Ignore errors; the file might not exist\n    }\n  }\n\n  await copyFile(filename, outputFile);\n}\n\nfunction parseArgs(argv, env) {\n  try {\n    return parse(argv, env);\n  } catch (err) {\n    if (err instanceof ParseError) {\n      quitError(err.message);\n    } else {\n      throw err;\n    }\n  }\n}\n\nfunction quitError(msg) {\n  console.error(msg);\n  process.exit(1);\n}\n\nmodule.exports = run;\n"
  },
  {
    "path": "pkgs/cargo-cp-artifact/test/args.js",
    "content": "\"use strict\";\n\nconst assert = require(\"assert\");\n\nconst { parse } = require(\"../src/args\");\n\ndescribe(\"Argument Parsing\", () => {\n  it(\"throws on invalid artifact type\", () => {\n    assert.throws(() => parse([\"-an\", \"a\", \"b\", \"--\"]), /artifact type/);\n  });\n\n  it(\"npm must have an environment variable\", () => {\n    assert.throws(() => parse([\"-nc\", \"a\", \"b\", \"--\"], {}), /environment/);\n  });\n\n  it(\"must provide a command\", () => {\n    assert.throws(() => parse([\"-ac\", \"a\", \"b\"]), /Missing command/);\n    assert.throws(() => parse([\"-ac\", \"a\", \"b\", \"--\"]), /Missing command/);\n  });\n\n  it(\"cannot provide invalid option\", () => {\n    assert.throws(() => parse([\"-q\"], {}), /Unexpected option/);\n  });\n\n  it(\"should be able to use --artifact\", () => {\n    const args = \"bin my-crate my-bin -- a b c\".split(\" \");\n    const expected = {\n      artifacts: {\n        \"bin:my-crate\": [\"my-bin\"],\n      },\n      cmd: \"a\",\n      args: [\"b\", \"c\"],\n    };\n\n    assert.deepStrictEqual(parse([\"--artifact\", ...args]), expected);\n    assert.deepStrictEqual(parse([\"-a\", ...args]), expected);\n  });\n\n  it(\"should be able to use --npm\", () => {\n    const args = \"bin my-bin -- a b c\".split(\" \");\n    const env = {\n      npm_package_name: \"my-crate\",\n    };\n\n    const expected = {\n      artifacts: {\n        \"bin:my-crate\": [\"my-bin\"],\n      },\n      cmd: \"a\",\n      args: [\"b\", \"c\"],\n    };\n\n    assert.deepStrictEqual(parse([\"--npm\", ...args], env), expected);\n    assert.deepStrictEqual(parse([\"-n\", ...args], env), expected);\n  });\n\n  it(\"should be able to use short-hand for crate type with -a\", () => {\n    const args = \"-ab my-crate my-bin -- a b c\".split(\" \");\n    const expected = {\n      artifacts: {\n        \"bin:my-crate\": [\"my-bin\"],\n      },\n      cmd: \"a\",\n      args: [\"b\", \"c\"],\n    };\n\n    assert.deepStrictEqual(parse(args), expected);\n  });\n\n  it(\"should be able to use short-hand for crate type with -n\", () => {\n    const args = \"-nb my-bin -- a b c\".split(\" \");\n    const env = {\n      npm_package_name: \"my-crate\",\n    };\n\n    const expected = {\n      artifacts: {\n        \"bin:my-crate\": [\"my-bin\"],\n      },\n      cmd: \"a\",\n      args: [\"b\", \"c\"],\n    };\n\n    assert.deepStrictEqual(parse(args, env), expected);\n  });\n\n  it(\"should remove namespace from package name\", () => {\n    const args = \"-nc index.node -- a b c\".split(\" \");\n    const env = {\n      npm_package_name: \"@my-namespace/my-crate\",\n    };\n\n    const expected = {\n      artifacts: {\n        \"cdylib:my-crate\": [\"index.node\"],\n      },\n      cmd: \"a\",\n      args: [\"b\", \"c\"],\n    };\n\n    assert.deepStrictEqual(parse(args, env), expected);\n  });\n\n  it(\"should be able to provide multiple artifacts\", () => {\n    const args = `\n      -nb my-bin\n      --artifact d a b\n      -ac my-crate index.node\n      --npm bin other-copy\n      -- a b c\n    `\n      .trim()\n      .split(\"\\n\")\n      .map((line) => line.trim())\n      .join(\" \")\n      .split(\" \");\n\n    const env = {\n      npm_package_name: \"my-crate\",\n    };\n\n    assert.deepStrictEqual(parse(args, env), {\n      artifacts: {\n        \"bin:my-crate\": [\"my-bin\", \"other-copy\"],\n        \"dylib:a\": [\"b\"],\n        \"cdylib:my-crate\": [\"index.node\"],\n      },\n      cmd: \"a\",\n      args: [\"b\", \"c\"],\n    });\n  });\n});\n"
  },
  {
    "path": "pkgs/create-neon/.mocharc.json",
    "content": "{\n  \"extension\": [\"ts\"],\n  \"spec\": \"dist/test/**/*.js\",\n  \"timeout\": 5000\n}\n"
  },
  {
    "path": "pkgs/create-neon/README.md",
    "content": "# Create Neon\n\nThe `create-neon` tool bootstraps [Neon](https://neon-bindings.com) projects, which allows developers to build binary Node modules written in [Rust](https://www.rust-lang.org).\n\n## Usage\n\nYou can conveniently use this tool with the [`npm init`](https://docs.npmjs.com/cli/v7/commands/npm-init) syntax:\n\n### Creating a Simple Project\n\nTo create a simple Neon project that consists purely of Rust code:\n\n```sh\n$ npm init neon[@latest] -- [<opts> ...] my-project\n```\n\n**Note:** The initial `--` is necessary for `npm init` to pass any command-line options to Neon.\n\n**Note:** The `@latest` ensures that npm uses the latest version of this tool.\n\n#### Global Options\n\n```sh\n-y|--yes  Skip interactive `npm init` questionnaire.\n```\n\n### Creating a Portable Library\n\nNeon also makes it easy to create **portable, cross-platform libraries** by publishing pre-built binaries. This means you can implement your Node.js library in Rust and publish the binaries so that users of your library (and any downstream users of theirs!) on all major hardware and operating systems can take a dependency on your library---_without having to install Rust or run any builds_.\n\nTo create a portable npm library with pre-built binaries:\n\n```sh\n$ npm init neon[@latest] -- [<opts> ...] --lib [<lib-opts> ...] my-project\n```\n\n**Note:** The initial `--` is necessary for `npm init` to pass any command-line options to Neon.\n\nThis will generate a project that can be used by pure JavaScript or TypeScript consumers without them even being aware of the use of Rust under the hood. It achieves this by publishing pre-built binaries for common Node platform architectures that are loaded just-in-time by a JS wrapper module.\n\nThis command generates the necessary npm and CI/CD configuration boilerplate to require nearly zero manual installation on typical GitHub-hosted repos. The only manual step required is to configure GitHub Actions with the necessary npm access token to enable automated publishing.\n\nThis command chooses the most common setup by default, but allows customization with fine-grained configuration options. These configuration options can also be modified later with the [Neon CLI](https://www.npmjs.com/package/@neon-rs/cli).\n\n#### Library Options\n\n```sh\n--ci none|github       CI/CD provider to generate config for.\n                       (Default: github)\n--bins none|npm[:org]  Cache provider to publish pre-built binaries.\n                       (Default: npm, with org inferred from package)\n--platform <platform>  Binary platform to add support to this library for.\n                       This option can be specified multiple times.\n                       (Default: macos, linux, windows)\n```\n"
  },
  {
    "path": "pkgs/create-neon/data/templates/.gitignore.hbs",
    "content": "target\nindex.node\n**/node_modules\n**/.DS_Store\nnpm-debug.log*{{#eq options.library.lang compare=\"ts\"}}\nlib\n{{/eq}}\ncargo.log\ncross.log\n"
  },
  {
    "path": "pkgs/create-neon/data/templates/Cargo.toml.hbs",
    "content": "[package]\nname = {{crate.escaped.name}}\nversion = {{crate.escaped.version}}\n{{#if crate.description}}\ndescription = {{crate.escaped.description}}\n{{/if}}\n{{#if crate.author}}\nauthors = [{{crate.escaped.author}}]\n{{/if}}\n{{#if crate.license}}\nlicense = {{crate.escaped.license}}\n{{/if}}\nedition = \"2024\"\nexclude = [\"index.node\"]\n\n[lib]\ncrate-type = [\"cdylib\"]\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\nneon = \"{{versions.neon}}\"\n"
  },
  {
    "path": "pkgs/create-neon/data/templates/README.md.hbs",
    "content": "# {{package.name}}\n\n{{#if package.description}}\n**{{package.name}}:** {{package.description}}\n\n{{/if}}\nThis project was bootstrapped by [create-neon](https://www.npmjs.com/package/create-neon).\n\n## Building {{package.name}}\n\nBuilding {{package.name}} requires a [supported version of Node and Rust](https://github.com/neon-bindings/neon#platform-support).\n\nTo run the build, run:\n\n```sh\n$ npm run build\n```\n\nThis command uses the [@neon-rs/cli](https://www.npmjs.com/package/@neon-rs/cli) utility to assemble the binary Node addon from the output of `cargo`.\n\n## Exploring {{package.name}}\n\nAfter building {{package.name}}, you can explore its exports at the Node console:\n\n{{#if options.library}}\n```sh\n$ npm i\n$ npm run build\n$ node\n> require('.').greeting('node')\n{ message: 'hello node' }\n```\n{{else}}\n```sh\n$ npm i\n$ npm run build\n$ node\n> require('.').hello('node')\n'hello node'\n```\n{{/if}}\n\n## Available Scripts\n\nIn the project directory, you can run:\n\n{{#unless options.library}}\n#### `npm install`\n\nInstalls the project, including running `npm run build`.\n\n{{/unless}}\n#### `npm run build`\n\nBuilds the Node addon (`index.node`) from source, generating a release build with `cargo --release`.\n\nAdditional [`cargo build`](https://doc.rust-lang.org/cargo/commands/cargo-build.html) arguments may be passed to `npm run build` and similar commands. For example, to enable a [cargo feature](https://doc.rust-lang.org/cargo/reference/features.html):\n\n```\nnpm run build -- --feature=beetle\n```\n\n#### `npm run debug`\n\nSimilar to `npm run build` but generates a debug build with `cargo`.\n\n#### `npm run cross`\n\nSimilar to `npm run build` but uses [cross-rs](https://github.com/cross-rs/cross) to cross-compile for another platform. Use the [`CARGO_BUILD_TARGET`](https://doc.rust-lang.org/cargo/reference/config.html#buildtarget) environment variable to select the build target.\n\n{{#eq options.library.ci.type compare=\"github\"}}\n#### `npm run release`\n\nInitiate a full build and publication of a new patch release of this library via GitHub Actions.\n\n#### `npm run dryrun`\n\nInitiate a dry run of a patch release of this library via GitHub Actions. This performs a full build but does not publish the final result.\n\n{{/eq}}\n#### `npm test`\n\nRuns the unit tests by calling `cargo test`. You can learn more about [adding tests to your Rust code](https://doc.rust-lang.org/book/ch11-01-writing-tests.html) from the [Rust book](https://doc.rust-lang.org/book/).\n\n## Project Layout\n\nThe directory structure of this project is:\n\n```\n{{package.name}}/\n├── Cargo.toml\n├── README.md\n{{#if options.library}}\n├── lib/\n{{#eq options.library.lang compare=\"ts\"}}\n├── src/\n|   ├── index.mts\n|   └── index.cts\n├── crates/\n|   └── {{package.name}}/\n|       └── src/\n|           └── lib.rs\n{{/eq}}\n├── platforms/\n{{else}}\n├── src/\n|   └── lib.rs\n├── index.node\n{{/if}}\n├── package.json\n└── target/\n```\n\n| Entry          | Purpose                                                                                                                                  |\n|----------------|------------------------------------------------------------------------------------------------------------------------------------------|\n| `Cargo.toml`   | The Cargo [manifest file](https://doc.rust-lang.org/cargo/reference/manifest.html), which informs the `cargo` command.                   |\n| `README.md`    | This file.                                                                                                                               |\n{{#if options.library}}\n{{#eq options.library.lang compare=\"ts\"}}\n| `lib/`         | The directory containing the generated output from [tsc](https://typescriptlang.org).                                                    |\n| `src/`         | The directory containing the TypeScript source files.                                                                                    |\n| `index.mts`    | Entry point for when this library is loaded via [ESM `import`](https://nodejs.org/api/esm.html#modules-ecmascript-modules) syntax.       |\n| `index.cts`    | Entry point for when this library is loaded via [CJS `require`](https://nodejs.org/api/modules.html#requireid).                          |\n| `crates/`      | The directory tree containing the Rust source code for the project.                                                                      |\n| `lib.rs`       | Entry point for the Rust source code.                                                                                                          |\n{{else}}\n| `lib/`         | The directory containing The directory containing the JavaScript source files.                                                           |\n{{/eq}}\n| `platforms/`   | The directory containing distributions of the binary addon backend for each platform supported by this library.                          |\n{{else}}\n| `src/`         | The directory tree containing the Rust source code for the project.                                                                      |\n| `lib.rs`       | Entry point for the Rust source code.                                                                                                          |\n| `index.node`   | The main module, a [Node addon](https://nodejs.org/api/addons.html) generated by the build and pointed to by `\"main\"` in `package.json`. |\n{{/if}}\n| `package.json` | The npm [manifest file](https://docs.npmjs.com/cli/v7/configuring-npm/package-json), which informs the `npm` command.                    |\n| `target/`      | Binary artifacts generated by the Rust build.                                                                                            |\n\n## Learn More\n\nLearn more about:\n\n- [Neon](https://neon-bindings.com).\n- [Rust](https://www.rust-lang.org).\n- [Node](https://nodejs.org).\n"
  },
  {
    "path": "pkgs/create-neon/data/templates/Workspace.toml.hbs",
    "content": "[workspace]\nmembers = [\"crates/{{crate.name}}\"]\nresolver = \"3\"\n"
  },
  {
    "path": "pkgs/create-neon/data/templates/ci/github/build.yml.hbs",
    "content": "name: Build\n\non:\n  workflow_call:\n    inputs:\n      ref:\n        description: 'The branch, tag, or SHA to check out'\n        required: true\n        type: string\n      update-version:\n        description: 'Update version before building?'\n        required: false\n        type: boolean\n        default: false\n      version:\n        description: 'Version update (ignored if update-version is false)'\n        required: false\n        type: string\n        default: 'patch'\n      github-release:\n        description: 'Publish GitHub release?'\n        required: false\n        type: boolean\n        default: false\n      tag:\n        description: 'The release tag (ignored if github-release is false)'\n        required: false\n        type: string\n        default: ''\n\njobs:\n  matrix:\n    name: Matrix\n    runs-on: ubuntu-latest\n    outputs:\n      matrix: {{#$}} steps.matrix.outputs.result {{/$}}\n    steps:\n      - name: Checkout Code\n        uses: actions/checkout@{{versions.actions.verified.checkout}}\n        with:\n          ref: {{#$}} inputs.ref {{/$}}\n      - name: Setup Neon Environment\n        uses: ./.github/actions/setup\n        with:\n          use-rust: false\n      - name: Look Up Matrix Data\n        id: matrixData\n        shell: bash\n        run: echo \"json=$(npx neon show ci github | jq -rc)\" | tee -a $GITHUB_OUTPUT\n      - name: Compute Matrix\n        id: matrix\n        uses: actions/github-script@{{versions.actions.verified.githubScript}}\n        with:\n          script: |\n            const platforms = {{#$}} steps.matrixData.outputs.json {{/$}};\n            const macOS = platforms.macOS.map(platform => {\n              return { os: \"macos-latest\", platform, script: \"build\" };\n            });\n            const windows = platforms.Windows.map(platform => {\n              return { os: \"windows-latest\", platform, script: \"build\" };\n            });\n            const linux = platforms.Linux.map(platform => {\n              return { os: \"ubuntu-latest\", platform, script: \"cross\" };\n            });\n            return [...macOS, ...windows, ...linux];\n\n  binaries:\n    name: Binaries\n    needs: [matrix]\n    strategy:\n      matrix:\n        cfg: {{#$}} fromJSON(needs.matrix.outputs.matrix) {{/$}}\n    runs-on: {{#$}} matrix.cfg.os {{/$}}\n    permissions:\n      contents: write\n    steps:\n      - name: Checkout Code\n        uses: actions/checkout@{{versions.actions.verified.checkout}}\n        with:\n          ref: {{#$}} inputs.ref {{/$}}\n      - name: Setup Neon Environment\n        id: neon\n        uses: ./.github/actions/setup\n        with:\n          use-cross: {{#$}} matrix.cfg.script == 'cross' {{/$}}\n          platform: {{#$}} matrix.cfg.platform {{/$}}\n      - name: Update Version\n        if: {{#$}} inputs.update-version {{/$}}\n        shell: bash\n        run: |\n          git config --global user.name $ACTIONS_USER\n          git config --global user.email $ACTIONS_EMAIL\n          npm version {{#$}} inputs.version {{/$}} -m \"v%s\"\n      - name: Build\n        shell: bash\n        env:\n          CARGO_BUILD_TARGET: {{#$}} steps.neon.outputs.target {{/$}}\n          NEON_BUILD_PLATFORM: {{#$}} matrix.cfg.platform {{/$}}\n        run: npm run {{#$}} matrix.cfg.script {{/$}}\n      - name: Pack\n        id: pack\n        shell: bash\n        run: |\n          mkdir -p dist\n          echo filename=$(basename $(npm pack ./platforms/{{#$}} matrix.cfg.platform {{/$}} --silent --pack-destination=./dist --json | jq -r '.[0].filename')) | tee -a $GITHUB_OUTPUT\n      - name: Release\n        if: {{#$}} inputs.github-release {{/$}}\n        uses: softprops/action-gh-release@{{versions.actions.unverified.ghRelease.sha}} # {{versions.actions.unverified.ghRelease.tag}}\n        with:\n          files: ./dist/{{#$}} steps.pack.outputs.filename {{/$}}\n          tag_name: {{#$}} inputs.tag {{/$}}\n\n  main:\n    name: Main\n    needs: [matrix]\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout Code\n        uses: actions/checkout@{{versions.actions.verified.checkout}}\n        with:\n          ref: {{#$}} inputs.ref {{/$}}\n      - name: Setup Neon Environment\n        uses: ./.github/actions/setup\n        with:\n          use-rust: false\n      - name: Pack\n        id: pack\n        shell: bash\n        run: |\n          mkdir -p dist\n          echo \"filename=$(npm pack --silent --pack-destination=./dist)\" | tee -a $GITHUB_OUTPUT\n      - name: Release\n        if: {{#$}} inputs.github-release {{/$}}\n        uses: softprops/action-gh-release@{{versions.actions.unverified.ghRelease.sha}} # {{versions.actions.unverified.ghRelease.tag}}\n        with:\n          files: ./dist/{{#$}} steps.pack.outputs.filename {{/$}}\n          tag_name: {{#$}} inputs.tag {{/$}}\n"
  },
  {
    "path": "pkgs/create-neon/data/templates/ci/github/release.yml.hbs",
    "content": "name: Release\n\nrun-name: |\n  {{#$}} (inputs.dryrun && 'Dry run')\n   || format('Release: {0}', (inputs.version == 'custom' && inputs.custom) || inputs.version) {{/$}}\n\non:\n  workflow_dispatch:\n    inputs:\n      dryrun:\n        description: 'Dry run (no npm publish)'\n        required: false\n        type: boolean\n        default: true\n      version:\n        description: 'Version component to update (or \"custom\" to provide exact version)'\n        required: true\n        type: choice\n        options:\n          - patch\n          - minor\n          - major\n          - prepatch\n          - preminor\n          - premajor\n          - prerelease\n          - custom\n      custom:\n        description: 'Custom version'\n        required: false\n        default: ''\n\njobs:\n  setup:\n    name: Setup\n    runs-on: ubuntu-latest\n    permissions:\n      contents: write\n    outputs:\n      dryrun: {{#$}} steps.dryrun.outputs.dryrun {{/$}}\n      publish: {{#$}} steps.publish.outputs.publish {{/$}}\n      ref: {{#$}} steps.tag.outputs.tag || github.event.repository.default_branch {{/$}}\n      tag: {{#$}} steps.tag.outputs.tag || '' {{/$}}\n    steps:\n      - name: Validate Workflow Inputs\n        if: {{#$}} inputs.version == 'custom' && inputs.custom == '' {{/$}}\n        shell: bash\n        run: |\n          echo '::error::No custom version number provided'\n          exit 1\n      - id: dryrun\n        name: Validate Dry Run Event\n        if: {{#$}} inputs.dryrun {{/$}}\n        shell: bash\n        run: echo dryrun=true | tee -a $GITHUB_OUTPUT\n      - id: publish\n        name: Validate Publish Event\n        if: {{#$}} !inputs.dryrun {{/$}}\n        shell: bash\n        env:\n          NPM_TOKEN: {{#$}} secrets.NPM_TOKEN {{/$}}\n        run: |\n          if [[ -z $NPM_TOKEN ]]; then\n            echo \"::error::Secret NPM_TOKEN is not defined for this GitHub repo.\"\n            echo \"::error::To publish to npm, this action requires:\"\n            echo \"::error:: • an npm access token;\"\n            echo \"::error:: • with Read-Write access to this project's npm packages;\"\n            echo \"::error:: • stored as a repo secret named NPM_TOKEN.\"\n            echo \"::error::See https://docs.npmjs.com/about-access-tokens for info about creating npm tokens.\"\n            echo \"::error:: 💡 The simplest method is to create a Classic npm token of type Automation.\"\n            echo \"::error:: 💡 For greater security, consider using a Granual access token.\"\n            echo \"::error::See https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions for info about how to store GitHub repo secrets.\"\n            exit 1\n          fi\n          echo publish=true | tee -a $GITHUB_OUTPUT\n      - name: Checkout Code\n        uses: actions/checkout@{{versions.actions.verified.checkout}}\n      - name: Setup Neon Environment\n        uses: ./.github/actions/setup\n        with:\n          use-rust: false\n      - name: Tag Release\n        if: {{#$}} !inputs.dryrun {{/$}}\n        id: tag\n        shell: bash\n        run: |\n          git config --global user.name $ACTIONS_USER\n          git config --global user.email $ACTIONS_EMAIL\n          npm version -m 'v%s' '{{#$}} (inputs.version == 'custom' && inputs.custom) || inputs.version {{/$}}'\n          git push --follow-tags\n          echo tag=$(git describe --abbrev=0) | tee -a $GITHUB_OUTPUT\n\n  build:\n    name: Build\n    needs: [setup]\n    permissions:\n      contents: write\n    uses: ./.github/workflows/build.yml\n    with:\n      ref: {{#$}} needs.setup.outputs.ref {{/$}}\n      tag: {{#$}} needs.setup.outputs.tag {{/$}}\n      update-version: {{#$}} !!needs.setup.outputs.dryrun {{/$}}\n      version: {{#$}} (inputs.version == 'custom' && inputs.custom) || inputs.version {{/$}}\n      github-release: {{#$}} !!needs.setup.outputs.publish {{/$}}\n\n  publish:\n    name: Publish\n    if: {{#$}} needs.setup.outputs.publish {{/$}}\n    needs: [setup, build]\n    runs-on: ubuntu-latest\n    permissions:\n      contents: write\n    steps:\n      - name: Checkout Code\n        uses: actions/checkout@{{versions.actions.verified.checkout}}\n        with:\n          ref: {{#$}} needs.setup.outputs.ref {{/$}}\n      - name: Setup Neon Environment\n        uses: ./.github/actions/setup\n        with:\n          use-rust: false\n      - name: Fetch\n        uses: robinraju/release-downloader@{{versions.actions.unverified.releaseDownloader.sha}} # {{versions.actions.unverified.releaseDownloader.tag}}\n        with:\n          tag: {{#$}} needs.setup.outputs.tag {{/$}}\n          fileName: \"*.tgz\"\n          out-file-path: ./dist\n      - name: Publish\n        shell: bash\n        env:\n          NODE_AUTH_TOKEN: {{#$}} secrets.NPM_TOKEN {{/$}}\n        run: |\n          for p in ./dist/*.tgz ; do\n            npm publish --access public $p\n          done\n"
  },
  {
    "path": "pkgs/create-neon/data/templates/ci/github/setup.yml.hbs",
    "content": "name: 'Setup Neon'\ndescription: 'Setup the Neon toolchain.'\ninputs:\n  platform:\n    description: 'Platform being built for.'\n    required: false\n    default: ''\n  use-rust:\n    description: 'Install Rust?'\n    required: false\n    default: 'true'\n  use-cross:\n    description: 'Install cross-rs?'\n    required: false\n    default: 'false'\n  workspace:\n    description: 'Path to workspace being setup.'\n    required: false\n    default: '.'\noutputs:\n  rust:\n    description: 'Rust version installed.'\n    value: {{#$}} steps.rust.outputs.version {{/$}}\n  node:\n    description: 'Node version installed.'\n    value: {{#$}} steps.node.outputs.version {{/$}}\n  target:\n    description: 'Rust target architecture installed.'\n    value: {{#$}} steps.target.outputs.target {{/$}}\nruns:\n  using: \"composite\"\n  steps:\n    - name: Set Environment Variables\n      uses: falti/dotenv-action@{{versions.actions.unverified.dotenv.sha}} # {{versions.actions.unverified.dotenv.tag}}\n      with:\n        path: ./.github/.env\n        export-variables: true\n        keys-case: bypass\n    - name: Install Node\n      uses: actions/setup-node@{{versions.actions.verified.setupNode}}\n      with:\n        node-version: {{#$}} env.NODE_VERSION {{/$}}\n        registry-url: {{#$}} env.NPM_REGISTRY {{/$}}\n        cache: npm\n    - name: Install Dependencies\n      shell: bash  \n      run: npm ci   \n    - name: Compute Rust Target\n      if: {{#$}} inputs['use-rust'] == 'true' {{/$}}\n      id: target\n      shell: bash\n      run: echo target=$(npx neon list-platforms | jq -r '.[\"{{#$}} inputs.platform {{/$}}\"]') | tee -a $GITHUB_OUTPUT\n      working-directory: {{#$}} inputs.workspace {{/$}}\n    - name: Install Rust\n      if: {{#$}} inputs['use-rust'] == 'true' {{/$}}\n      uses: actions-rs/toolchain@{{versions.actions.verified.setupRust}}\n      with:\n        toolchain: {{#$}} env.RUST_VERSION {{/$}}\n        target: {{#$}} steps.target.outputs.target {{/$}}\n        override: true\n    - name: Install cross-rs\n      if: {{#$}} inputs['use-cross'] == 'true' {{/$}}\n      uses: baptiste0928/cargo-install@{{versions.actions.verified.cargoInstall}}\n      with:\n        crate: cross\n    - name: Node Version\n      id: node\n      shell: bash\n      run: |\n        echo version=$(node -e 'console.log(process.versions.node)') | tee -a $GITHUB_OUTPUT\n    - name: Rust Version\n      if: {{#$}} inputs['use-rust'] == 'true' {{/$}}\n      id: rust\n      shell: bash\n      run: |\n        echo version=$(cargo -Vv | fgrep release: | cut -d' ' -f2) | tee -a $GITHUB_OUTPUT\n"
  },
  {
    "path": "pkgs/create-neon/data/templates/ci/github/test.yml.hbs",
    "content": "name: Test\n\nrun-name: |\n  {{#$}} (github.event_name == 'pull_request' && format('Test (PR #{0}): {1}', github.event.number, github.event.pull_request.title))\n   || format('Test: {0}', github.event.head_commit.message) {{/$}}\n\non:\n  # Event: A maintainer has pushed commits or merged a PR to main.\n  push:\n    # Limiting push events to 'main' prevents duplicate runs of this workflow\n    # when maintainers push to internal PRs.\n    branches:\n      - main\n\n  # Event: A contributor has created or updated a PR.\n  pull_request:\n    types: [opened, synchronize, reopened, labeled]\n    branches:\n      - main\n\njobs:\n  pr:\n    name: Pull Request Details\n    runs-on: ubuntu-latest\n    if: {{#$}} github.event_name == 'pull_request' {{/$}}\n    outputs:\n      branch: {{#$}} steps.pr-ref.outputs.branch || github.event.repository.default_branch {{/$}}\n    steps:\n      - name: PR Branch\n        id: pr-ref\n        shell: bash\n        run: echo \"branch=$(gh pr view $PR_NO --repo $REPO --json headRefName --jq '.headRefName')\" | tee -a \"$GITHUB_OUTPUT\"\n        env:\n          REPO: {{#$}} github.repository {{/$}}\n          PR_NO: {{#$}} github.event.number {{/$}}\n          GH_TOKEN: {{#$}} github.token {{/$}}\n\n  # Labeling a PR with a `ci:full-matrix` label does a full matrix build on\n  # every run of this workflow for that PR, in addition to the other tests.\n  full-matrix:\n    name: Build\n    if: {{#$}} github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'ci:full-matrix') {{/$}}\n    needs: [pr]\n    permissions:\n      contents: write\n    uses: ./.github/workflows/build.yml\n    with:\n      ref: {{#$}} needs.pr.outputs.branch {{/$}}\n      update-version: true\n      github-release: false\n\n  unit-tests:\n    name: Unit Tests\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout Code\n        uses: actions/checkout@{{versions.actions.verified.checkout}}\n      - name: Setup Neon Environment\n        id: neon\n        uses: ./.github/actions/setup\n        with:\n          platform: linux-x64-gnu\n      - name: Build\n        shell: bash\n        env:\n          CARGO_BUILD_TARGET: {{#$}} steps.neon.outputs.target {{/$}}\n          NEON_BUILD_PLATFORM: linux-x64-gnu\n        run: npm run debug\n      - name: Test\n        shell: bash\n        run: npm test\n"
  },
  {
    "path": "pkgs/create-neon/data/templates/lib.rs.hbs",
    "content": "// Use #[neon::export] to export Rust functions as JavaScript functions.\n// See more at: https://docs.rs/neon/latest/neon/attr.export.html\n\n#[neon::export]\nfn hello(name: String) -> String {\n    format!(\"hello {name}\")\n}\n\n// Use #[neon::main] to add additional behavior at module loading time.\n// See more at: https://docs.rs/neon/latest/neon/attr.main.html\n\n// #[neon::main]\n// fn main(_cx: ModuleContext) -> NeonResult<()> {\n//     println!(\"module is loaded!\");\n//     Ok(())\n// }\n"
  },
  {
    "path": "pkgs/create-neon/data/templates/manifest/base/default.json.hbs",
    "content": "\n{\n  \"name\": \"{{options.fullName}}\",\n  \"version\": \"{{options.version}}\",\n  \"main\": \"index.node\",\n  \"scripts\": {},\n  \"devDependencies\": {\n    \"@neon-rs/cli\": \"{{versions.neonCLI}}\"{{#eq options.library.lang compare=\"ts\"}},\n    \"@tsconfig/node{{versions.tsconfigNode.major}}\": \"^{{versions.tsconfigNode.semver}}\",\n    \"@types/node\": \"^{{versions.typesNode}}\",\n    \"typescript\": \"^{{versions.typescript}}\"{{/eq}}\n  }\n}\n"
  },
  {
    "path": "pkgs/create-neon/data/templates/manifest/base/library.json.hbs",
    "content": "\n{\n  \"name\": \"{{options.fullName}}\",\n  \"version\": \"{{options.version}}\",\n{{#eq options.library.module compare=\"esm\"}}\n  \"exports\": {\n    \".\": {\n      \"import\": {\n        \"types\": \"./lib/index.d.mts\",\n        \"default\": \"./lib/index.mjs\"\n      },\n      \"require\": {\n        \"types\": \"./lib/index.d.cts\",\n        \"default\": \"./lib/index.cjs\"\n      }\n    }\n  },\n{{/eq}}\n  \"types\": \"./lib/index.d.cts\",\n  \"main\": \"./lib/index.cjs\",\n  \"files\": [\n    \"lib/**/*.?({c,m}){t,j}s\"\n  ],\n  \"scripts\": {},\n  \"neon\": {\n    \"type\": \"library\",\n{{#eq options.library.cache.type compare=\"npm\"}}\n{{#if options.library.cache.org}}\n    \"org\": \"{{options.library.cache.org}}\",\n{{/if}}\n{{#if options.library.cache.prefix}}\n    \"prefix\": \"{{options.library.cache.prefix}}\",\n{{/if}}\n{{/eq}}\n    \"platforms\": {},\n    \"load\": \"./src/load.cts\"\n  },\n  \"devDependencies\": {\n    \"@neon-rs/cli\": \"^{{versions.neonCLI}}\"{{#eq options.library.lang compare=\"ts\"}},\n    \"@tsconfig/node{{versions.tsconfigNode.major}}\": \"^{{versions.tsconfigNode.semver}}\",\n    \"@types/node\": \"^{{versions.typesNode}}\",\n    \"typescript\": \"^{{versions.typescript}}\"{{/eq}}\n  },\n  \"dependencies\": {\n    \"@neon-rs/load\": \"^{{versions.neonLoad}}\"\n  }\n}\n"
  },
  {
    "path": "pkgs/create-neon/data/templates/ts/index.cts.hbs",
    "content": "// This module is the CJS entry point for the library.\n\n// The Rust addon.\nimport * as addon from './load.cjs';\n\n// Use this declaration to assign types to the addon's exports,\n// which otherwise by default are `any`.\ndeclare module \"./load.cjs\" {\n  function hello(name: string): string;\n}\n\nexport type Greeting = {\n  message: string\n};\n\nexport function greeting(name: string): Greeting {\n  const message = addon.hello(name);\n  return { message };\n}\n"
  },
  {
    "path": "pkgs/create-neon/data/templates/ts/index.mts.hbs",
    "content": "// This module is the ESM entry point for the library.\n\nexport * from './index.cjs';\n"
  },
  {
    "path": "pkgs/create-neon/data/templates/ts/load.cts.hbs",
    "content": "// This module loads the platform-specific build of the addon on\n// the current system. The supported platforms are registered in\n// the `platforms` object below, whose entries can be managed by\n// by the Neon CLI:\n//\n//   https://www.npmjs.com/package/@neon-rs/cli\n\nmodule.exports = require('@neon-rs/load').proxy({\n  platforms: {},\n  debug: () => require('../index.node')\n});\n"
  },
  {
    "path": "pkgs/create-neon/data/templates/tsconfig.json.hbs",
    "content": "{\n{{#eq options.library.lang compare=\"ts\"}}\n  \"extends\": \"@tsconfig/node{{versions.tsconfigNode.major}}/tsconfig.json\",\n  \"compilerOptions\": {\n    \"module\": \"node{{versions.tsconfigNode.module}}\",\n    \"declaration\": true,\n    \"outDir\": \"lib\",\n  },\n  \"exclude\": [\"lib\"]\n{{else}}\n  \"extends\": \"@tsconfig/node{{versions.tsconfigNode.major}}/tsconfig.json\"\n{{/eq}}\n}\n"
  },
  {
    "path": "pkgs/create-neon/data/versions.json",
    "content": "{\n  \"neon\": \"1.1\",\n  \"neonCLI\": \"0.1.82\",\n  \"neonLoad\": \"0.1.82\",\n  \"typescript\": \"5.3.3\",\n  \"typesNode\": \"20.11.16\",\n  \"tsconfigNode\": {\n    \"major\": \"20\",\n    \"semver\": \"20.1.4\",\n    \"module\": \"16\"\n  },\n  \"node\": \"20\",\n  \"actions\": {\n    \"verified\": {\n      \"checkout\": \"v3\",\n      \"githubScript\": \"v7\",\n      \"setupNode\": \"v3\",\n      \"setupRust\": \"v1\",\n      \"cargoInstall\": \"v2\",\n      \"neonBuild\": \"v0.9\",\n      \"neonPublish\": \"v0.4.1\"\n    },\n    \"unverified\": {\n      \"dotenv\": {\n        \"tag\": \"v1.1.2\",\n        \"sha\": \"d1cd55661714e830a6e26f608f81d36e23424fed\"\n      },\n      \"ghRelease\": {\n        \"tag\": \"v2.0.4\",\n        \"sha\": \"9d7c94cfd0a1f3ed45544c887983e9fa900f0564\"\n      },\n      \"releaseDownloader\": {\n        \"tag\": \"v1.10\",\n        \"sha\": \"c39a3b234af58f0cf85888573d361fb6fa281534\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "pkgs/create-neon/dev/expect.ts",
    "content": "import { ChildProcess } from \"child_process\";\nimport { Readable, Writable } from \"stream\";\nimport readStream from \"stream-to-string\";\nimport { readChunks } from \"../src/shell.js\";\n\nfunction splitLines(s: string): string[] {\n  return s.split(/([^\\n]*\\r?\\n)/).filter((x) => x);\n}\n\nfunction isCompleteLine(s: string): boolean {\n  return s.endsWith(\"\\n\");\n}\n\nclass LinesBuffer {\n  // INVARIANT: (this.buffer.length > 0) &&\n  //            !isCompleteLine(this.buffer[this.buffer.length - 1])\n  // In other words, the last line in the buffer is always incomplete.\n  private buffer: string[];\n\n  constructor() {\n    this.buffer = [\"\"];\n  }\n\n  add(lines: string[]) {\n    if (lines.length === 0) {\n      return;\n    }\n    if (isCompleteLine(lines[lines.length - 1])) {\n      lines.push(\"\");\n    }\n    this.buffer[this.buffer.length - 1] += lines.shift();\n    this.buffer = this.buffer.concat(lines);\n  }\n\n  // Finds and removes lines from the buffer up to and including\n  // the first line that satisfies the predicate p.\n  // Returns the extracted lines, or null if no such line exists.\n  find(p: (s: string) => boolean): string[] | null {\n    let index = this.buffer.findIndex(p);\n    if (index === -1) {\n      return null;\n    }\n    let extracted = this.buffer.splice(0, index + 1);\n    if (this.buffer.length === 0) {\n      this.buffer.push(\"\");\n    }\n    return extracted;\n  }\n}\n\ninterface Pattern {\n  expect(session: Session): AsyncGenerator<string[]>;\n}\n\ntype QA = { q: string; a: string };\n\nclass ExpectLine implements Pattern {\n  optional: QA[];\n  required: QA;\n\n  constructor(optional: QA[], required: QA) {\n    this.optional = optional;\n    this.required = required;\n  }\n\n  async *expect(session: Session): AsyncGenerator<string[]> {\n    // Use a wrapper stream so that early exit from the for-await loop doesn't\n    // cancel the underlying stream.\n    let stdout = Readable.toWeb(session.stdout).values({ preventCancel: true });\n\n    for await (let chunk of stdout) {\n      session.buffer.add(splitLines(chunk));\n\n      let maxFound = -1;\n\n      // Check for optional lines\n      for (let i = 0; i < this.optional.length; i++) {\n        let found = session.buffer.find((line) =>\n          line.startsWith(this.optional[i].q)\n        );\n        if (found) {\n          session.stdin.write(this.optional[i].a + \"\\n\");\n          maxFound = i;\n          yield found;\n        }\n      }\n\n      // Remove from queue any lines that were found\n      this.optional.splice(0, maxFound + 1);\n\n      // Check for required line\n      let found = session.buffer.find((line) =>\n        line.startsWith(this.required.q)\n      );\n      if (found) {\n        session.stdin.write(this.required.a + \"\\n\");\n        yield found;\n        return;\n      }\n    }\n  }\n}\n\n// We don't currently have any scripts that end with an optional line, but if we did we'd need this class.\nclass ExpectEOF implements Pattern {\n  optional: QA[];\n\n  constructor(optional: QA[]) {\n    this.optional = optional;\n    throw new Error(\"Class not implemented.\");\n  }\n\n  async *expect(session: Session): AsyncGenerator<string[]> {\n    throw new Error(\"Method not implemented.\");\n  }\n}\n\nclass Script {\n  clauses: Pattern[];\n\n  constructor(src: Record<string, string>) {\n    this.clauses = [];\n\n    let keys = Object.keys(src);\n    let i = 0;\n    let optional: QA[] = [];\n\n    while (i < keys.length) {\n      if (keys[i].startsWith(\"?\")) {\n        // Collect optional lines\n        optional.push({ q: keys[i].substring(1).trim(), a: src[keys[i]] });\n      } else {\n        // Collect required line\n        this.clauses.push(\n          new ExpectLine(optional, { q: keys[i], a: src[keys[i]] })\n        );\n        optional = [];\n      }\n      i++;\n    }\n\n    if (optional.length > 0) {\n      this.clauses.push(new ExpectEOF(optional));\n    }\n  }\n\n  async *run(session: Session): AsyncGenerator<string[]> {\n    for (let clause of this.clauses) {\n      for await (let lines of clause.expect(session)) {\n        yield lines;\n      }\n    }\n  }\n}\n\nclass Session {\n  buffer: LinesBuffer;\n  stdin: Writable;\n  stdout: Readable;\n\n  constructor(stdin: Writable, stdout: Readable) {\n    this.buffer = new LinesBuffer();\n    this.stdin = stdin;\n    this.stdout = readChunks(stdout);\n  }\n}\n\nfunction exit(child: ChildProcess): Promise<number | null> {\n  let resolve: (code: number | null) => void;\n  let result: Promise<number | null> = new Promise((res) => {\n    resolve = res;\n  });\n  child.on(\"exit\", (code) => {\n    resolve(code);\n  });\n  return result;\n}\n\nexport default async function expect(\n  child: ChildProcess,\n  src: Record<string, string>\n): Promise<void> {\n  let output: string[][] = [];\n  let script = new Script(src);\n  let session = new Session(child.stdin!, child.stdout!);\n  for await (let lines of script.run(session)) {\n    output.push(lines);\n  }\n  let stderr = await readStream(child.stderr!);\n  let code = await exit(child);\n  switch (code) {\n    case null:\n      throw new Error(\"child process interrupted\");\n    case 0:\n      return;\n    default:\n      console.log(\"stderr: \" + stderr.trim());\n      console.log(\"stdout: \" + JSON.stringify(output));\n      throw new Error(\"child process exited with code \" + code);\n  }\n}\n"
  },
  {
    "path": "pkgs/create-neon/package.json",
    "content": "{\n  \"name\": \"create-neon\",\n  \"version\": \"0.7.0\",\n  \"description\": \"Create Neon projects with no build configuration.\",\n  \"type\": \"module\",\n  \"exports\": \"./dist/src/bin/create-neon.js\",\n  \"author\": \"Dave Herman <david.herman@gmail.com>\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/neon-bindings/neon/issues\"\n  },\n  \"homepage\": \"https://github.com/neon-bindings/neon#readme\",\n  \"bin\": {\n    \"create-neon\": \"dist/src/bin/create-neon.js\"\n  },\n  \"files\": [\n    \"dist/src/**/*\",\n    \"dist/data/**/*\"\n  ],\n  \"scripts\": {\n    \"build\": \"tsc && rm -rf dist/data && cp -r data dist/data/ && ls -R dist/data\",\n    \"prepublishOnly\": \"npm run build\",\n    \"pretest\": \"npm run build\",\n    \"test\": \"mocha\",\n    \"manual-interactive-test\": \"npm run build && rm -rf create-neon-manual-test-project && node ./dist/src/bin/create-neon.js create-neon-manual-test-project\",\n    \"manual-test\": \"npm run build && rm -rf create-neon-manual-test-project && node ./dist/src/bin/create-neon.js --lib --yes create-neon-manual-test-project\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/neon-bindings/neon.git\"\n  },\n  \"keywords\": [\n    \"neon\"\n  ],\n  \"devDependencies\": {\n    \"@tsconfig/node18\": \"^18.2.2\",\n    \"@types/chai\": \"^4.3.11\",\n    \"@types/command-line-args\": \"^5.2.3\",\n    \"@types/command-line-usage\": \"^5.0.4\",\n    \"@types/handlebars-helpers\": \"^0.5.6\",\n    \"@types/mocha\": \"^10.0.6\",\n    \"@types/node\": \"^20.10.1\",\n    \"chai\": \"^4.3.10\",\n    \"execa\": \"^8.0.1\",\n    \"mocha\": \"^10.2.0\",\n    \"stream-to-string\": \"^1.2.1\",\n    \"toml\": \"^3.0.0\",\n    \"typescript\": \"^5.3.2\"\n  },\n  \"dependencies\": {\n    \"@neon-rs/manifest\": \"^0.2.1\",\n    \"chalk\": \"^5.3.0\",\n    \"command-line-args\": \"^5.2.1\",\n    \"command-line-usage\": \"^7.0.1\",\n    \"handlebars\": \"^4.7.8\",\n    \"handlebars-helpers\": \"^0.10.0\"\n  }\n}\n"
  },
  {
    "path": "pkgs/create-neon/src/bin/create-neon.ts",
    "content": "#!/usr/bin/env node\n\nimport commandLineArgs from \"command-line-args\";\nimport { printErrorWithUsage } from \"../print.js\";\nimport { createNeon } from \"../index.js\";\nimport { Cache } from \"../cache.js\";\nimport { NPM } from \"../cache/npm.js\";\nimport { CI } from \"../ci.js\";\nimport { GitHub } from \"../ci/github.js\";\nimport { Lang, ModuleType } from \"../create/creator.js\";\nimport {\n  NodePlatform,\n  PlatformPreset,\n  isNodePlatform,\n  isPlatformPreset,\n} from \"@neon-rs/manifest/platform\";\n\nconst OPTIONS = [\n  { name: \"app\", type: Boolean, defaultValue: false },\n  { name: \"lib\", type: Boolean, defaultValue: false },\n  { name: \"bins\", type: String, defaultValue: \"none\" },\n  { name: \"platform\", type: String, multiple: true, defaultValue: [\"common\"] },\n  { name: \"ci\", alias: \"c\", type: String, defaultValue: \"github\" },\n  { name: \"yes\", alias: \"y\", type: Boolean, defaultValue: false },\n];\n\ntry {\n  const opts = commandLineArgs(OPTIONS, { stopAtFirstUnknown: true });\n\n  if (opts.app && opts.lib) {\n    throw new Error(\"Cannot choose both --app and --lib\");\n  }\n\n  if (!opts._unknown || opts._unknown.length === 0) {\n    throw new Error(\"No package name given\");\n  }\n\n  if (opts._unknown.length > 1) {\n    throw new Error(`unexpected argument (${opts._unknown[1]})`);\n  }\n\n  const [pkg] = opts._unknown;\n  const { org, basename } = /^((?<org>@[^/]+)\\/)?(?<basename>.*)/.exec(pkg)\n    ?.groups as {\n    org?: string;\n    basename: string;\n  };\n  const fullName = org ? pkg : basename;\n  const platforms = parsePlatforms(opts.platform);\n  const cache = parseCache(opts.lib, opts.bins, basename, org);\n  const ci = parseCI(opts.ci);\n\n  if (opts.yes) {\n    process.env[\"npm_configure_yes\"] = \"true\";\n  }\n\n  createNeon({\n    org,\n    basename,\n    fullName,\n    version: \"0.1.0\",\n    library: opts.lib\n      ? {\n          lang: Lang.TS,\n          module: ModuleType.ESM,\n          cache,\n          ci,\n          platforms,\n        }\n      : null,\n    app: opts.app ? true : opts.lib ? false : null,\n    // Even if the user specifies this with a flag (e.g. `npm init -y neon`),\n    // `npm init` sets this env var to 'true' before invoking create-neon.\n    // So this is the most general way to check this configuration option.\n    interactive: process.env[\"npm_configure_yes\"] !== \"true\",\n  });\n} catch (e) {\n  printErrorWithUsage(e);\n  process.exit(1);\n}\n\nfunction parsePlatforms(\n  platforms: string[]\n):\n  | NodePlatform\n  | PlatformPreset\n  | (NodePlatform | PlatformPreset)[]\n  | undefined {\n  if (platforms.length === 0) {\n    return undefined;\n  } else if (platforms.length === 1) {\n    const platform = platforms[0];\n    if (isNodePlatform(platform) || isPlatformPreset(platform)) {\n      return platform;\n    }\n    throw new TypeError(`expected platform or preset, got ${platform}`);\n  } else {\n    return platforms.map((platform) => {\n      if (isNodePlatform(platform) || isPlatformPreset(platform)) {\n        return platform;\n      }\n      throw new TypeError(`expected platform or preset, got ${platform}`);\n    });\n  }\n}\n\nfunction parseCI(ci: string): CI | undefined {\n  switch (ci) {\n    case \"none\":\n      return undefined;\n    case \"github\":\n      return new GitHub();\n    default:\n      throw new Error(\n        `Unrecognized CI system ${ci}, expected 'github' or 'none'`\n      );\n  }\n}\n\nfunction parseCache(\n  lib: boolean,\n  bins: string,\n  pkg: string,\n  org: string | undefined\n): Cache | undefined {\n  const defaultPrefix = org ? `${pkg}-` : \"\";\n  org ??= `@${pkg}`;\n\n  // CASE: npm create neon -- --app logos-r-us\n  // CASE: npm create neon -- --app @acme/logos-r-us\n  //   - <no binaries cache>\n  if (bins === \"none\" && !lib) {\n    return undefined;\n  }\n\n  // CASE: npm create neon -- --lib logo-generator\n  // CASE: npm create neon -- --lib --bins npm logo-generator\n  //   - lib: `logo-generator`\n  //   - bin: `@logo-generator/darwin-arm64`\n\n  // CASE: npm create neon -- --lib @acme/logo-generator\n  // CASE: npm create neon -- --lib --bins npm @acme/logo-generator\n  //   - lib: `@acme/logo-generator`\n  //   - bin: `@acme/logo-generator-darwin-arm64`\n  if (bins === \"none\" || bins === \"npm\") {\n    return new NPM(org, defaultPrefix);\n  }\n\n  // CASE: npm create neon -- --lib --bins=npm:acme logo-generator\n  //   lib: logo-generator\n  //   bin: @acme/logo-generator-darwin-arm64\n\n  // CASE: npm create neon -- --lib --bins=npm:acme/libs-logo-generator- logo-generator\n  //   lib: logo-generator\n  //   bin: @acme/libs-logo-generator-darwin-arm64\n\n  // CASE: npm create neon -- --lib --bins=npm:acme-libs @acme/logo-generator\n  //   lib: @acme-libs/logo-generator\n  //   bin: @acme-libs/logo-generator-darwin-arm64\n  if (bins.startsWith(\"npm:\")) {\n    const split = bins.substring(4).split(\"/\", 2);\n    const org = split[0].replace(/^@?/, \"@\"); // don't care if they include the @ or not\n    const prefix = split.length > 1 ? split[1] : defaultPrefix;\n    return new NPM(org, prefix);\n  }\n\n  throw new Error(\n    `Unrecognized binaries cache ${bins}, expected 'npm[:org[/prefix]]' or 'none'`\n  );\n}\n"
  },
  {
    "path": "pkgs/create-neon/src/cache/npm.ts",
    "content": "import { Cache } from \"../cache.js\";\n\nexport class NPM implements Cache {\n  readonly org: string;\n  readonly prefix: string;\n\n  readonly type: string = \"npm\";\n\n  constructor(org: string, prefix: string) {\n    this.org = org;\n    this.prefix = prefix;\n  }\n}\n"
  },
  {
    "path": "pkgs/create-neon/src/cache.ts",
    "content": "export interface Cache {\n  readonly type: string;\n}\n"
  },
  {
    "path": "pkgs/create-neon/src/ci/github.ts",
    "content": "import handlebars from \"handlebars\";\nimport { CI } from \"../ci.js\";\nimport path from \"node:path\";\n\nconst TEMPLATES: Record<string, string> = {\n  \"setup.yml.hbs\": path.join(\".github\", \"actions\", \"setup\", \"action.yml\"),\n  \".env.hbs\": path.join(\".github\", \".env\"),\n  \"build.yml.hbs\": path.join(\".github\", \"workflows\", \"build.yml\"),\n  \"release.yml.hbs\": path.join(\".github\", \"workflows\", \"release.yml\"),\n  \"test.yml.hbs\": path.join(\".github\", \"workflows\", \"test.yml\"),\n};\n\nfunction githubDelegate(\n  this: any,\n  options: handlebars.HelperOptions\n): handlebars.SafeString {\n  return new handlebars.SafeString(\"${{\" + options.fn(this) + \"}}\");\n}\n\nexport class GitHub implements CI {\n  constructor() {}\n\n  readonly type: string = \"github\";\n\n  templates(): Record<string, string> {\n    return TEMPLATES;\n  }\n\n  setup(): void {\n    handlebars.registerHelper(\"$\", githubDelegate);\n  }\n\n  scripts(): Record<string, string> {\n    return {\n      release: \"gh workflow run release.yml -f dryrun=false -f version=patch\",\n      dryrun: \"gh workflow run publish.yml -f dryrun=true\",\n    };\n  }\n}\n"
  },
  {
    "path": "pkgs/create-neon/src/ci.ts",
    "content": "export interface CI {\n  readonly type: string;\n  templates(): Record<string, string>;\n  setup(): void;\n  scripts(): Record<string, string>;\n}\n"
  },
  {
    "path": "pkgs/create-neon/src/create/app.ts",
    "content": "import { Creator, ProjectOptions } from \"./creator.js\";\n\nexport class AppCreator extends Creator {\n  constructor(options: ProjectOptions) {\n    super(options);\n  }\n\n  scripts(): Record<string, string> {\n    return {\n      test: \"cargo test\",\n      \"cargo-build\":\n        \"cargo build --message-format=json-render-diagnostics > cargo.log\",\n      \"cross-build\":\n        \"cross build --message-format=json-render-diagnostics > cross.log\",\n      \"postcargo-build\": \"neon dist < cargo.log\",\n      \"postcross-build\": \"neon dist -m /target < cross.log\",\n      debug: \"npm run cargo-build --\",\n      build: \"npm run cargo-build -- --release\",\n      cross: \"npm run cross-build -- --release\",\n    };\n  }\n}\n"
  },
  {
    "path": "pkgs/create-neon/src/create/creator.ts",
    "content": "import die from \"../die.js\";\nimport { mktemp } from \"../fs.js\";\nimport * as path from \"node:path\";\nimport * as fs from \"node:fs/promises\";\nimport { Context } from \"../expand/context.js\";\nimport { expand, expandTo } from \"../expand/index.js\";\nimport { npmInit } from \"../shell.js\";\nimport { Cache } from \"../cache.js\";\nimport { CI } from \"../ci.js\";\nimport { NodePlatform, PlatformPreset } from \"@neon-rs/manifest/platform\";\n\nexport enum Lang {\n  JS = \"js\",\n  DTS = \"dts\",\n  TS = \"ts\",\n}\n\nexport enum ModuleType {\n  ESM = \"esm\",\n  CJS = \"cjs\",\n}\n\nexport type LibraryOptions = {\n  lang: Lang;\n  module: ModuleType;\n  cache?: Cache;\n  ci?: CI | undefined;\n  platforms?: NodePlatform | PlatformPreset | (NodePlatform | PlatformPreset)[];\n};\n\nexport type ProjectOptions = {\n  org?: string | undefined;\n  basename: string;\n  fullName: string;\n  version: string;\n  library: LibraryOptions | null;\n  app: boolean | null;\n  cache?: Cache | undefined;\n  ci?: CI | undefined;\n  interactive: boolean;\n};\n\nfunction stripNpmNamespace(pkg: string): string {\n  return /^@[^/]+\\/(?<stripped>.*)/.exec(pkg)?.groups?.stripped || pkg;\n}\n\nexport abstract class Creator {\n  protected _options: ProjectOptions;\n  protected _temp: string = \"\";\n  protected _tempPkg: string = \"\";\n\n  static async for(options: ProjectOptions): Promise<Creator> {\n    if (options.library) {\n      const LibCreator = (await import(\"./lib.js\")).LibCreator;\n      return new LibCreator(options);\n    } else {\n      const AppCreator = (await import(\"./app.js\")).AppCreator;\n      return new AppCreator(options);\n    }\n  }\n\n  constructor(options: ProjectOptions) {\n    this._options = options;\n  }\n\n  async create(cx: Context): Promise<void> {\n    try {\n      this._temp = await mktemp();\n      this._tempPkg = path.join(this._temp, this._options.basename);\n\n      await fs.mkdir(this._tempPkg);\n    } catch (err: any) {\n      await die(\n        `Could not create \\`${this._options.basename}\\`: ${err.message}`,\n        this._temp\n      );\n    }\n\n    await this.prepare(cx);\n\n    const manifest = await npmInit(\n      cx.options.interactive,\n      cx.options.interactive ? [] : [\"--yes\"],\n      this._tempPkg,\n      this._temp\n    );\n\n    try {\n      cx.package = {\n        name: manifest.name,\n        version: manifest.version,\n        author: manifest.author,\n        license: manifest.license,\n        description: manifest.description,\n      };\n\n      const crateName = stripNpmNamespace(manifest.name);\n\n      cx.crate = {\n        name: crateName,\n        version: manifest.version,\n        author: manifest.author,\n        description: manifest.description,\n        license: manifest.license,\n        escaped: {\n          name: JSON.stringify(crateName),\n          version: JSON.stringify(manifest.version),\n          author: manifest.author ? JSON.stringify(manifest.author) : undefined,\n          description: manifest.description\n            ? JSON.stringify(manifest.description)\n            : undefined,\n          license: manifest.license\n            ? JSON.stringify(manifest.license)\n            : undefined,\n        },\n      };\n    } catch (err: any) {\n      await die(\n        \"Could not create `package.json`: \" + err.message,\n        this._tempPkg\n      );\n    }\n\n    await this.createNeonBoilerplate(cx);\n\n    try {\n      await fs.rename(this._tempPkg, this._options.basename);\n      await fs.rmdir(this._temp);\n    } catch (err: any) {\n      await die(\n        `Could not create \\`${this._options.basename}\\`: ${err.message}`,\n        this._tempPkg\n      );\n    }\n  }\n\n  async createNeonBoilerplate(cx: Context): Promise<void> {\n    const templates = this.templates(cx.package!.name);\n    for (const source of Object.keys(templates)) {\n      const target = path.join(this._tempPkg, templates[source]);\n      await expandTo(source, target, cx);\n    }\n  }\n\n  // Write initial values to prevent `npm init` from asking unnecessary questions.\n  async prepare(cx: Context): Promise<void> {\n    const template = `manifest/base/${this.baseTemplate()}`;\n\n    const base = JSON.parse(await expand(template, cx));\n    base.scripts = this.scripts();\n    const filename = path.join(this._tempPkg, \"package.json\");\n    await fs.writeFile(filename, JSON.stringify(base));\n  }\n\n  templates(_pkg: string): Record<string, string> {\n    return {\n      \".gitignore.hbs\": \".gitignore\",\n      \"Cargo.toml.hbs\": \"Cargo.toml\",\n      \"README.md.hbs\": \"README.md\",\n      \"lib.rs.hbs\": path.join(\"src\", \"lib.rs\"),\n    };\n  }\n\n  scripts(): Record<string, string> {\n    return {};\n  }\n\n  baseTemplate(): string {\n    return \"default.json.hbs\";\n  }\n}\n"
  },
  {
    "path": "pkgs/create-neon/src/create/lib.ts",
    "content": "import { Creator, ProjectOptions, LibraryOptions, Lang } from \"./creator.js\";\nimport { Context } from \"../expand/context.js\";\nimport * as path from \"node:path\";\nimport { expandTo } from \"../expand/index.js\";\nimport { LibraryManifest } from \"@neon-rs/manifest\";\nimport {\n  NodePlatform,\n  PlatformPreset,\n  isNodePlatform,\n} from \"@neon-rs/manifest/platform\";\n\nconst TS_TEMPLATES: Record<string, string> = {\n  \"tsconfig.json.hbs\": \"tsconfig.json\",\n  \"ts/index.cts.hbs\": path.join(\"src\", \"index.cts\"),\n  \"ts/index.mts.hbs\": path.join(\"src\", \"index.mts\"),\n  \"ts/load.cts.hbs\": path.join(\"src\", \"load.cts\"),\n};\n\nexport class LibCreator extends Creator {\n  private _libOptions: LibraryOptions;\n\n  constructor(options: ProjectOptions) {\n    super(options);\n    this._libOptions = options.library!;\n    if (this._libOptions.ci) {\n      this._libOptions.ci.setup();\n    }\n  }\n\n  templates(pkg: string): Record<string, string> {\n    return this._libOptions.lang === Lang.TS\n      ? {\n          \".gitignore.hbs\": \".gitignore\",\n          \"Cargo.toml.hbs\": path.join(\"crates\", pkg, \"Cargo.toml\"),\n          \"Workspace.toml.hbs\": \"Cargo.toml\",\n          \"README.md.hbs\": \"README.md\",\n          \"lib.rs.hbs\": path.join(\"crates\", pkg, \"src\", \"lib.rs\"),\n        }\n      : super.templates(pkg);\n  }\n\n  async createNeonBoilerplate(cx: Context): Promise<void> {\n    await super.createNeonBoilerplate(cx);\n\n    if (this._libOptions.lang === Lang.TS) {\n      await this.createTSBoilerplate(cx);\n    }\n\n    if (this._libOptions.ci) {\n      await this.createCIBoilerplate(cx);\n    }\n\n    await this.addPlatforms(cx);\n  }\n\n  async createTSBoilerplate(cx: Context): Promise<void> {\n    for (const source of Object.keys(TS_TEMPLATES)) {\n      const target = path.join(this._tempPkg, TS_TEMPLATES[source]);\n      await expandTo(source, target, cx);\n    }\n  }\n\n  async createCIBoilerplate(cx: Context): Promise<void> {\n    const templates = this._libOptions.ci!.templates();\n    for (const source of Object.keys(templates)) {\n      const target = path.join(this._tempPkg, templates[source]);\n      await expandTo(`ci/${this._libOptions.ci!.type}/${source}`, target, cx);\n    }\n  }\n\n  async addPlatforms(cx: Context): Promise<void> {\n    const manifest = await LibraryManifest.load(this._tempPkg);\n\n    const platforms: (NodePlatform | PlatformPreset)[] = Array.isArray(\n      this._libOptions.platforms\n    )\n      ? this._libOptions.platforms\n      : !this._libOptions.platforms\n      ? [\"common\"]\n      : [this._libOptions.platforms];\n\n    for (const platform of platforms) {\n      if (isNodePlatform(platform)) {\n        await manifest.addNodePlatform(platform);\n      } else {\n        await manifest.addPlatformPreset(platform);\n      }\n    }\n\n    await manifest.saveChanges((msg) => {});\n  }\n\n  scripts(): Record<string, string> {\n    const tscAnd = this._libOptions.lang === Lang.TS ? \"tsc &&\" : \"\";\n\n    let scripts: Record<string, string> = {\n      test: `${tscAnd}cargo test`,\n      \"cargo-build\": `${tscAnd}cargo build --message-format=json-render-diagnostics > cargo.log`,\n      \"cross-build\": `${tscAnd}cross build --message-format=json-render-diagnostics > cross.log`,\n      \"postcargo-build\": \"neon dist < cargo.log\",\n      \"postcross-build\": \"neon dist -m /target < cross.log\",\n      debug: \"npm run cargo-build --\",\n      build: \"npm run cargo-build -- --release\",\n      cross: \"npm run cross-build -- --release\",\n      prepack: `${tscAnd}neon update`,\n      version: \"neon bump --binaries platforms && git add .\",\n    };\n\n    if (this._libOptions.ci) {\n      Object.assign(scripts, this._libOptions.ci.scripts());\n    }\n\n    return scripts;\n  }\n\n  baseTemplate(): string {\n    return \"library.json.hbs\";\n  }\n}\n"
  },
  {
    "path": "pkgs/create-neon/src/die.ts",
    "content": "import { promises as fs } from \"fs\";\n\nfunction deleteNeonDir(dir: string): Promise<void> {\n  return fs.rm(dir, { force: true, recursive: true });\n}\n\nexport default async function die(\n  message: string,\n  tmpFolderName?: string | undefined\n): Promise<never> {\n  console.error(`❌ ${message}`);\n  if (tmpFolderName) {\n    await deleteNeonDir(tmpFolderName);\n  }\n  process.exit(1);\n}\n"
  },
  {
    "path": "pkgs/create-neon/src/expand/context.ts",
    "content": "import { ProjectOptions } from \"../create/creator.js\";\nimport { VERSIONS, Versions } from \"./versions.js\";\n\nexport type ManifestData = {\n  name: string;\n  version: string;\n  description: string | undefined;\n  author: string | undefined;\n  license: string | undefined;\n};\n\ntype CrateData = ManifestData & {\n  // The same manifest data but escaped as string literals\n  // so they can be embedded in TOML.\n  escaped: ManifestData;\n};\n\nexport class Context {\n  options: ProjectOptions;\n  package: ManifestData | undefined;\n  crate: CrateData | undefined;\n  versions: Versions;\n\n  constructor(options: ProjectOptions) {\n    this.options = options;\n    this.package = undefined;\n    this.crate = undefined;\n    this.versions = VERSIONS;\n  }\n}\n"
  },
  {
    "path": "pkgs/create-neon/src/expand/index.ts",
    "content": "import { promises as fs } from \"fs\";\nimport handlebars from \"handlebars\";\nimport helpers from \"handlebars-helpers\";\nimport * as path from \"path\";\nimport { Context } from \"./context.js\";\n\nconst TEMPLATES_DIR = new URL(\n  path.join(\"..\", \"..\", \"data\", \"templates\", \"/\"),\n  import.meta.url\n);\n\nconst COMPARISON_HELPERS = helpers(\"comparison\");\n\nhandlebars.registerHelper(\"eq\", COMPARISON_HELPERS.eq);\n\nexport async function expand(source: string, cx: Context): Promise<string> {\n  let template = await fs.readFile(new URL(source, TEMPLATES_DIR), \"utf8\");\n  let compiled = handlebars.compile(template, { noEscape: true });\n  return compiled(cx);\n}\n\nexport async function expandTo(source: string, target: string, cx: Context) {\n  await fs.mkdir(path.dirname(target), { recursive: true });\n  const expanded = await expand(source, cx);\n  // The 'wx' flag creates the file but fails if it already exists.\n  await fs.writeFile(target, expanded, { flag: \"wx\" });\n}\n"
  },
  {
    "path": "pkgs/create-neon/src/expand/versions.ts",
    "content": "// This whole module is a bummer but was the best I could figure out since:\n// - Using @sindresorhus packages like 'chalk' and 'execa' forces a project to use Node's native ESM support.\n// - This means the tsconfig must generate a modern format like es2022.\n// - When generating ESM, TS doesn't support importing JSON files with static typing without import assertions.\n// - Import assertions are not yet stable in Node, and produce an instability warning.\n//\n// So for the time being, this module simply implements the static typing explicitly.\n// If and when TS adds back and way to infer the static types when importing a JSON file\n// and generates a stable format that Node doesn't complain about, we can eliminate this\n// boilerplate wrapper module.\n\nimport { createRequire } from \"module\";\n\nexport type Versions = {\n  neon: string;\n  neonCLI: string;\n  neonLoad: string;\n  typescript: string;\n  typesNode: string;\n  tsconfigNode: {\n    major: string;\n    semver: string;\n    module: string;\n  };\n  node: string;\n  actions: {\n    checkout: string;\n    githubScript: string;\n    setupNode: string;\n    setupRust: string;\n    cargoInstall: string;\n    neonBuild: string;\n    neonPublish: string;\n    dotenv: string;\n    ghRelease: string;\n    releaseDownloader: string;\n  };\n};\n\nconst KEYS = [\n  \"neon\",\n  \"neonCLI\",\n  \"neonLoad\",\n  \"typescript\",\n  \"typesNode\",\n  \"tsconfigNode\",\n  \"node\",\n  \"actions\",\n];\n\nfunction assertIsVersions(data: unknown): asserts data is Versions {\n  if (!data || typeof data !== \"object\") {\n    throw new TypeError(\"expected object\");\n  }\n  KEYS.forEach((key) => {\n    if (!(key in data)) {\n      throw new TypeError(`require '${key}' property not found`);\n    }\n  });\n}\n\nconst dynamicRequire = createRequire(import.meta.url);\n\nfunction load(): Versions {\n  const data = dynamicRequire(\"../../data/versions.json\");\n  assertIsVersions(data);\n  return data;\n}\n\nexport const VERSIONS: Versions = load();\n"
  },
  {
    "path": "pkgs/create-neon/src/fs.ts",
    "content": "import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { existsSync, rmSync } from \"node:fs\";\n\nexport async function assertCanMkdir(dir: string) {\n  // pretty lightweight way to check both that folder doesn't exist and\n  // that the user has write permissions.\n  await fs.mkdir(dir);\n  await fs.rmdir(dir);\n}\n\nexport async function mktemp(): Promise<string> {\n  const tmpFolderName = await fs.mkdtemp(\"neon-\");\n  const tmpFolderAbsPath = path.join(process.cwd(), tmpFolderName);\n  function cleanupTmp() {\n    try {\n      if (existsSync(tmpFolderAbsPath)) {\n        rmSync(tmpFolderAbsPath, { recursive: true });\n      }\n    } catch (e) {\n      console.error(`warning: could not delete ${tmpFolderName}: ${e}`);\n    }\n  }\n  process.on(\"exit\", cleanupTmp);\n  process.on(\"SIGINT\", cleanupTmp);\n  process.on(\"uncaughtException\", cleanupTmp);\n  return tmpFolderName;\n}\n"
  },
  {
    "path": "pkgs/create-neon/src/index.ts",
    "content": "import { Context } from \"./expand/context.js\";\nimport {\n  NodePlatform,\n  PlatformPreset,\n  isNodePlatform,\n  isPlatformPreset,\n} from \"@neon-rs/manifest/platform\";\nimport { Dialog, oneOf } from \"./shell.js\";\nimport { NPM } from \"./cache/npm.js\";\nimport { GitHub } from \"./ci/github.js\";\nimport { Creator, ProjectOptions, Lang, ModuleType } from \"./create/creator.js\";\nimport { assertCanMkdir } from \"./fs.js\";\nimport die from \"./die.js\";\n\nconst CREATE_NEON_PRELUDE: string = `\nThis utility will walk you through creating a Neon project.\nIt only covers the most common items, and tries to guess sensible defaults.\n  \nUse \\`npm install <pkg>\\` afterwards to install a package and\nsave it as a dependency in the package.json file.\n  \nUse \\`npm run build\\` to build the Neon project from source.\n  \nPress ^C at any time to quit.      \n`.trim();\n\nasync function askProjectType(options: ProjectOptions) {\n  const dialog = new Dialog();\n  const ty = await dialog.ask({\n    prompt: \"project type\",\n    parse: oneOf({ app: \"app\" as const, lib: \"lib\" as const }),\n    default: \"app\" as const,\n    error: 'type should be a valid Neon project type (\"app\" or \"lib\").',\n  });\n\n  if (ty === \"lib\") {\n    const platforms: (NodePlatform | PlatformPreset)[] = await dialog.ask({\n      prompt: \"target platforms\",\n      parse: (v: string): (NodePlatform | PlatformPreset)[] => {\n        const a = v.split(\",\").map((s) => s.trim());\n        if (a.some((elt) => !isNodePlatform(elt) && !isPlatformPreset(elt))) {\n          throw new Error(\"parse error\");\n        }\n        return a as (NodePlatform | PlatformPreset)[];\n      },\n      default: [\"common\"],\n      error:\n        \"platforms should be a comma-separated list of platforms or platform presets.\",\n    });\n\n    const cache = await dialog.ask({\n      prompt: \"binary cache\",\n      parse: oneOf({ npm: \"npm\" as const, none: undefined }),\n      default: \"npm\" as const,\n      error:\n        'cache should be a supported Neon binary cache type (\"npm\" or \"none\").',\n    });\n\n    const org =\n      cache === \"npm\"\n        ? (\n            await dialog.ask({\n              prompt: \"cache org\",\n              parse: (v: string): string => v,\n              default: options.org ?? `@${options.basename}`,\n            })\n          ).replace(/^@?/, \"@\") // don't care if they include the @ or not\n        : null;\n\n    const prefix =\n      cache === \"npm\" && org === `@${options.basename}`\n        ? \"\"\n        : cache === \"npm\"\n        ? await dialog.ask({\n            prompt: \"cache prefix\",\n            parse: (v: string): string => v,\n            default: `${options.basename}-`,\n          })\n        : null;\n\n    const ci = await dialog.ask({\n      prompt: \"ci provider\",\n      parse: oneOf({ npm: \"github\" as const, none: undefined }),\n      default: \"github\" as const,\n      error:\n        'provider should be a supported Neon CI provider (\"github\" or \"none\").',\n    });\n\n    options.library = {\n      lang: Lang.TS,\n      module: ModuleType.ESM,\n      cache: cache === \"npm\" ? new NPM(org!, prefix!) : undefined,\n      ci: ci === \"github\" ? new GitHub() : undefined,\n      platforms: platforms.length === 1 ? platforms[0] : platforms,\n    };\n  } else {\n    options.app = true;\n  }\n  dialog.end();\n}\n\nexport async function createNeon(options: ProjectOptions): Promise<void> {\n  try {\n    await assertCanMkdir(options.basename);\n  } catch (err: any) {\n    await die(`Could not create \\`${options.basename}\\`: ${err.message}`);\n  }\n\n  const cx = new Context(options);\n\n  // Print a Neon variation of the `npm init` prelude text.\n  if (options.interactive) {\n    console.log(CREATE_NEON_PRELUDE);\n  }\n\n  // If neither --lib nor --app was specified, find out.\n  if (options.library === null && options.app === null) {\n    if (options.interactive) {\n      await askProjectType(options);\n    } else {\n      options.app = true;\n    }\n  }\n\n  const creator = await Creator.for(options);\n  await creator.create(cx);\n\n  console.log(\n    `✨ Created Neon project \\`${options.fullName}\\`. Happy 🦀 hacking! ✨`\n  );\n}\n"
  },
  {
    "path": "pkgs/create-neon/src/print.ts",
    "content": "import commandLineUsage from \"command-line-usage\";\nimport chalk from \"chalk\";\n\nfunction pink(text: string): string {\n  return chalk.bold.hex(\"#e75480\")(text);\n}\n\nfunction green(text: string): string {\n  return chalk.bold.greenBright(text);\n}\n\nfunction blue(text: string): string {\n  return chalk.bold.cyanBright(text);\n}\n\nfunction yellow(text: string): string {\n  return chalk.bold.yellowBright(text);\n}\n\nfunction bold(text: string): string {\n  return chalk.bold(text);\n}\n\nfunction mainUsage(): string {\n  const sections = [\n    {\n      content: `✨ ${pink(\n        \"create-neon:\"\n      )} create a new Neon project with zero configuration ✨`,\n      raw: true,\n    },\n    {\n      header: green(\"Examples:\"),\n      content: [\n        `${blue(\"$\")} ${bold(\"npm init neon my-package\")}`,\n        \"\",\n        \"Create a Neon project `my-package`.\",\n        \"\",\n        `${blue(\"$\")} ${bold(\"npm init neon --lib my-lib\")}`,\n        \"\",\n        \"Create a Neon library `my-lib`, pre-configured to publish pre-builds for common Node target platforms as binary packages under the `@my-lib` org. The generated project includes GitHub CI/CD actions for testing and publishing.\",\n        \"\",\n        `${blue(\"$\")} ${bold(\n          \"npm init neon --lib my-library --target desktop\"\n        )}`,\n        \"\",\n        \"Similar but configured to target just common Node desktop platforms.\",\n      ],\n    },\n    {\n      header: blue(\"Usage:\"),\n      content: `${blue(\n        \"$\"\n      )} npm init neon [--lib] [--bins <bins>] [--ci <ci>] [--target <tgt>]* <pkg>`,\n    },\n    {\n      header: yellow(\"Options:\"),\n      content: [\n        {\n          name: \"--lib\",\n          summary:\n            \"Configure package as a library. (Implied defaults: `--bins npm` and `--ci github`)\",\n        },\n        {\n          name: \"--bins npm[:@<org>]\",\n          summary:\n            \"Configure for pre-built binaries published to npm. (Default org: <pkg>)\",\n        },\n        {\n          name: \"--bins none\",\n          summary: \"Do not configure for pre-built binaries. (Default)\",\n        },\n        {\n          name: \"--target <tgt>\",\n          summary:\n            \"May be used to specify one or more targets for pre-built binaries. (Default: common)\",\n        },\n        {\n          name: \"--ci github\",\n          summary: \"Generate CI/CD configuration for GitHub Actions. (Default)\",\n        },\n        { name: \"--ci none\", summary: \"Do not generate CI/CD configuration.\" },\n        { name: \"<pkg>\", summary: \"Package name.\" },\n      ],\n    },\n  ];\n\n  return commandLineUsage(sections).trim();\n}\n\nexport function printMainUsage() {\n  console.error(mainUsage());\n}\n\nexport function printErrorWithUsage(e: any) {\n  console.error(mainUsage());\n  console.error();\n  printError(e);\n}\n\nexport function printError(e: any) {\n  console.error(\n    chalk.bold.red(\"error:\") +\n      \" \" +\n      (e instanceof Error ? e.message : String(e))\n  );\n}\n"
  },
  {
    "path": "pkgs/create-neon/src/shell.ts",
    "content": "import { ChildProcess, spawn } from \"node:child_process\";\nimport { PassThrough, Readable, Writable } from \"node:stream\";\nimport { StringDecoder } from \"node:string_decoder\";\nimport readline from \"node:readline/promises\";\nimport * as path from \"node:path\";\nimport * as fs from \"node:fs/promises\";\n\nexport function readChunks(input: Readable): Readable {\n  let output = new PassThrough({ objectMode: true });\n\n  // Raise the default limit on listeners to avoid warnings.\n  output.setMaxListeners(20);\n\n  let decoder = new StringDecoder(\"utf8\");\n  input.on(\"data\", (data) => {\n    output.write(decoder.write(data));\n  });\n  input.on(\"close\", () => {\n    output.write(decoder.end());\n    output.end();\n  });\n  return output;\n}\n\ntype NpmInitExit = {\n  code: number | null;\n  signal: string | null;\n};\n\n// A child process representing a modified `npm init` invocation:\n// - If interactive, the initial prelude of stdout text is suppressed\n//   so we can present a modified prelude for create-neon.\n// - The process is being run in a temp subdirectory, so any output that\n//   includes the temp directory in a path is transformed to remove it.\nclass NpmInitProcess {\n  private _regexp: RegExp;\n  private _child: ChildProcess;\n\n  constructor(interactive: boolean, args: string[], cwd: string, tmp: string) {\n    this._regexp = new RegExp(tmp + \".\");\n    this._child = spawn(\"npm\", [\"init\", ...args], {\n      stdio: [\"inherit\", \"pipe\", \"inherit\"],\n      shell: true,\n      cwd,\n    });\n    this.filterStdout({ interactive }).then(() => {});\n  }\n\n  exit(): Promise<NpmInitExit> {\n    let resolve: (exit: NpmInitExit) => void;\n    const result: Promise<NpmInitExit> = new Promise((res) => {\n      resolve = res;\n    });\n    this._child.on(\"exit\", (code, signal) => {\n      resolve({ code, signal });\n    });\n    return result;\n  }\n\n  async filterStdout(opts: { interactive: boolean }) {\n    // We'll suppress the `npm init` interactive prelude text,\n    // in favor of printing our own create-neon version of the text.\n    let inPrelude = opts.interactive;\n\n    for await (const chunk of readChunks(this._child.stdout!)) {\n      const lines = (chunk as string).split(/\\r?\\n/);\n      if (opts.interactive && inPrelude) {\n        // If there's a prompt, it'll be at the end of the data chunk\n        // since npm init will have flushed stdout to block on stdin.\n        if (!lines[lines.length - 1].match(/^[a-z ]+:/)) {\n          // We're still in the prelude so suppress all the lines and\n          // wait for the next chunk of stdout data.\n          continue;\n        }\n\n        // Suppress the prelude lines up to the prompt.\n        lines.splice(0, lines.length - 1);\n        inPrelude = false;\n      }\n\n      // Print out all the lines.\n      lines.forEach((line, i) => {\n        // Remove the temp dir from any paths printed out by `npm init`.\n        process.stdout.write(line.replace(this._regexp, \"\"));\n        if (i < lines.length - 1) {\n          process.stdout.write(\"\\n\");\n        }\n      });\n    }\n  }\n}\n\n// Standard order of package.json keys generated by `npm init`.\nconst NPM_INIT_KEYS = [\n  \"name\",\n  \"version\",\n  \"description\",\n  \"main\",\n  \"scripts\",\n  \"author\",\n  \"license\",\n];\n\nfunction sort(json: any): any {\n  // First copy the keys in the order specified in NPM_INIT_KEYS.\n  let next = NPM_INIT_KEYS.filter((key) => json.hasOwnProperty(key))\n    .map((key) => [key, json[key]])\n    .reduce((acc, [key, val]) => Object.assign(acc, { [key]: val }), {});\n\n  // Then copy any remaining keys in the original order.\n  return Object.assign(next, json);\n}\n\nexport async function npmInit(\n  interactive: boolean,\n  args: string[],\n  cwd: string,\n  tmp: string\n): Promise<any> {\n  const child = new NpmInitProcess(interactive, args, cwd, tmp);\n  const { code, signal } = await child.exit();\n\n  if (code === null) {\n    process.kill(process.pid, signal!);\n  } else if (code !== 0) {\n    process.exit(code);\n  }\n\n  const filename = path.join(cwd, \"package.json\");\n\n  const sorted = sort(JSON.parse(await fs.readFile(filename, \"utf8\")));\n\n  await fs.writeFile(filename, JSON.stringify(sorted, undefined, 2) + \"\\n\");\n\n  return sorted;\n}\n\nexport type Parser<T> = (v: string) => T;\n\nexport function oneOf<T extends {}>(opts: T): Parser<T[keyof T]> {\n  return (v: string) => {\n    for (const key in opts) {\n      if (v === key) {\n        return opts[key];\n      }\n    }\n    throw new Error(\"parse error\");\n  };\n}\n\nexport interface Question<T> {\n  prompt: string;\n  parse: Parser<T>;\n  default: T;\n  error?: string;\n}\n\nexport class Dialog {\n  private _rl: readline.Interface | undefined;\n\n  constructor() {\n    this._rl = readline.createInterface({\n      input: process.stdin,\n      output: process.stdout,\n    });\n  }\n\n  private rl(): readline.Interface {\n    if (!this._rl) {\n      throw new Error(\"dialog already ended\");\n    }\n    return this._rl;\n  }\n\n  end() {\n    this.rl().close();\n    this._rl = undefined;\n  }\n\n  async ask<T>(opts: Question<T>): Promise<T> {\n    while (true) {\n      try {\n        const answer = (\n          await this.rl().question(\n            `neon ${opts.prompt}: (${String(opts.default)}) `\n          )\n        ).trim();\n        return answer === \"\" ? opts.default : opts.parse(answer);\n      } catch (_ignored) {\n        if (opts.error) {\n          console.log(`Sorry, ${opts.error}`);\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "pkgs/create-neon/test/create-neon.ts",
    "content": "import { assert } from \"chai\";\nimport { spawn } from \"child_process\";\nimport * as path from \"path\";\nimport { promises as fs } from \"fs\";\nimport * as TOML from \"toml\";\nimport expect from \"../dev/expect.js\";\nimport { execa } from \"execa\";\nimport { fileURLToPath } from \"url\";\n\nconst NODE: string = process.execPath;\nconst CREATE_NEON = fileURLToPath(\n  new URL(path.join(\"..\", \"src\", \"bin\", \"create-neon.js\"), import.meta.url)\n);\n\ndescribe(\"Command-line argument validation\", () => {\n  it(\"requires an argument\", async () => {\n    try {\n      await execa(NODE, [CREATE_NEON]);\n      assert.fail(\"should fail when no argument is supplied\");\n    } catch (expected) {\n      assert.isTrue(true);\n    }\n  });\n\n  it(\"fails if the directory already exists\", async () => {\n    try {\n      await execa(NODE, [CREATE_NEON, \"src\"]);\n      assert.fail(\"should fail when directory exists\");\n    } catch (expected) {\n      assert.isTrue(true);\n    }\n  });\n});\n\nconst PROJECT = \"create-neon-test-project\";\nconst NAMESPACED_PROJECT = \"@dherman/create-neon-test-project\";\n\ndescribe(\"Project creation\", () => {\n  afterEach(async () => {\n    await fs.rm(PROJECT, { recursive: true, maxRetries: 3 });\n  });\n\n  it(\"succeeds with --yes\", async () => {\n    try {\n      await execa(NODE, [CREATE_NEON, \"--yes\", PROJECT]);\n    } catch (error: any) {\n      assert.fail(\"create-neon unexpectedly failed: \" + error.message);\n    }\n  });\n\n  it(\"succeeds with all default answers\", async () => {\n    try {\n      await expect(spawn(NODE, [CREATE_NEON, \"--app\", PROJECT]), {\n        \"package name:\": \"\",\n        \"version:\": \"\",\n        \"description:\": \"\",\n        \"git repository:\": \"\",\n        \"keywords:\": \"\",\n        \"author:\": \"\",\n        \"license:\": \"\",\n        \"?type\": \"\",\n        \"Is this OK?\": \"\",\n      });\n    } catch (error: any) {\n      assert.fail(\"create-neon unexpectedly failed: \" + error.message);\n    }\n\n    let json = JSON.parse(\n      await fs.readFile(path.join(PROJECT, \"package.json\"), {\n        encoding: \"utf8\",\n      })\n    );\n\n    assert.strictEqual(json.name, PROJECT);\n    assert.strictEqual(json.main, \"index.node\");\n    assert.strictEqual(json.version, \"0.1.0\");\n    assert.strictEqual(json.scripts.test, \"cargo test\");\n    assert.isString(json.license);\n    assert.strictEqual(json.description, \"\");\n    assert.strictEqual(json.author, \"\");\n\n    let toml = TOML.parse(\n      await fs.readFile(path.join(PROJECT, \"Cargo.toml\"), { encoding: \"utf8\" })\n    );\n\n    assert.strictEqual(toml.package.name, PROJECT);\n    assert.strictEqual(toml.package.version, \"0.1.0\");\n    assert.strictEqual(toml.package.license, json.license);\n    assert.deepEqual(toml.lib[\"crate-type\"], [\"cdylib\"]);\n  });\n\n  it(\"handles quotation marks in author and description\", async () => {\n    try {\n      await expect(spawn(NODE, [CREATE_NEON, \"--app\", PROJECT]), {\n        \"package name:\": \"\",\n        \"version:\": \"\",\n        \"description:\": 'the \"hello world\" of examples',\n        \"git repository:\": \"\",\n        \"keywords:\": \"\",\n        \"author:\": '\"Dave Herman\" <dherman@example.com>',\n        \"license:\": \"\",\n        \"?type\": \"\",\n        \"Is this OK?\": \"\",\n      });\n    } catch (error) {\n      assert.fail(\"create-neon unexpectedly failed\");\n    }\n\n    let json = JSON.parse(\n      await fs.readFile(path.join(PROJECT, \"package.json\"), {\n        encoding: \"utf8\",\n      })\n    );\n\n    assert.strictEqual(json.description, 'the \"hello world\" of examples');\n    assert.strictEqual(json.author, '\"Dave Herman\" <dherman@example.com>');\n\n    let toml = TOML.parse(\n      await fs.readFile(path.join(PROJECT, \"Cargo.toml\"), { encoding: \"utf8\" })\n    );\n\n    assert.strictEqual(\n      toml.package.description,\n      'the \"hello world\" of examples'\n    );\n    assert.deepEqual(toml.package.authors, [\n      '\"Dave Herman\" <dherman@example.com>',\n    ]);\n  });\n\n  it(\"asks Neon project type if not specified\", async () => {\n    try {\n      await expect(spawn(NODE, [CREATE_NEON, PROJECT]), {\n        \"neon project type\": \"\",\n        \"package name:\": \"\",\n        \"version:\": \"\",\n        \"description:\": \"\",\n        \"git repository:\": \"\",\n        \"keywords:\": \"\",\n        \"author:\": \"\",\n        \"license:\": \"\",\n        \"?type\": \"\",\n        \"Is this OK?\": \"\",\n      });\n    } catch (error: any) {\n      assert.fail(\"create-neon unexpectedly failed: \" + error.message);\n    }\n\n    JSON.parse(\n      await fs.readFile(path.join(PROJECT, \"package.json\"), {\n        encoding: \"utf8\",\n      })\n    );\n\n    TOML.parse(\n      await fs.readFile(path.join(PROJECT, \"Cargo.toml\"), { encoding: \"utf8\" })\n    );\n  });\n\n  it(\"asks Neon lib questions interactively\", async () => {\n    try {\n      await expect(spawn(NODE, [CREATE_NEON, PROJECT]), {\n        \"neon project type\": \"lib\",\n        \"neon target platforms\": \"\",\n        \"neon binary cache\": \"\",\n        \"neon cache org\": \"\",\n        \"neon ci provider\": \"\",\n        \"package name:\": \"\",\n        \"version:\": \"\",\n        \"description:\": \"\",\n        \"git repository:\": \"\",\n        \"keywords:\": \"\",\n        \"author:\": \"\",\n        \"license:\": \"\",\n        \"?type\": \"\",\n        \"Is this OK?\": \"\",\n      });\n    } catch (error: any) {\n      assert.fail(\"create-neon unexpectedly failed: \" + error.message);\n    }\n\n    let json = JSON.parse(\n      await fs.readFile(path.join(PROJECT, \"package.json\"), {\n        encoding: \"utf8\",\n      })\n    );\n\n    assert.strictEqual(json.neon.type, \"library\");\n    assert.strictEqual(json.neon.org, \"@create-neon-test-project\");\n    assert.notProperty(json.neon, \"prefix\");\n    assert.strictEqual(json.neon.platforms, \"common\");\n    assert.strictEqual(json.neon.load, \"./src/load.cts\");\n\n    TOML.parse(\n      await fs.readFile(path.join(PROJECT, \"Cargo.toml\"), { encoding: \"utf8\" })\n    );\n  });\n\n  it(\"asks for a prefix when Neon lib is namespaced\", async () => {\n    try {\n      await expect(spawn(NODE, [CREATE_NEON, NAMESPACED_PROJECT]), {\n        \"neon project type\": \"lib\",\n        \"neon target platforms\": \"\",\n        \"neon binary cache\": \"\",\n        \"neon cache org\": \"\",\n        \"neon cache prefix\": \"\",\n        \"neon ci provider\": \"\",\n        \"package name:\": \"\",\n        \"version:\": \"\",\n        \"description:\": \"\",\n        \"git repository:\": \"\",\n        \"keywords:\": \"\",\n        \"author:\": \"\",\n        \"license:\": \"\",\n        \"?type\": \"\",\n        \"Is this OK?\": \"\",\n      });\n    } catch (error: any) {\n      assert.fail(\"create-neon unexpectedly failed: \" + error.message);\n    }\n\n    let json = JSON.parse(\n      await fs.readFile(path.join(PROJECT, \"package.json\"), {\n        encoding: \"utf8\",\n      })\n    );\n\n    assert.strictEqual(json.neon.type, \"library\");\n    assert.strictEqual(json.neon.org, \"@dherman\");\n    assert.strictEqual(json.neon.prefix, \"create-neon-test-project-\");\n    assert.strictEqual(json.neon.platforms, \"common\");\n    assert.strictEqual(json.neon.load, \"./src/load.cts\");\n\n    TOML.parse(\n      await fs.readFile(path.join(PROJECT, \"Cargo.toml\"), { encoding: \"utf8\" })\n    );\n  });\n});\n"
  },
  {
    "path": "pkgs/create-neon/tsconfig.json",
    "content": "{\n  \"extends\": \"@tsconfig/node18/tsconfig.json\",\n  \"compilerOptions\": {\n    \"module\": \"es2022\",\n    \"moduleResolution\": \"bundler\",\n    \"outDir\": \"dist\",\n    \"noImplicitAny\": true,\n    \"resolveJsonModule\": true\n  },\n  \"include\": [\"src/**/*\", \"dev/**/*\", \"test/**/*\"],\n  \"exclude\": [\"./node_modules/\", \"./dist/\"]\n}\n"
  },
  {
    "path": "test/electron/Cargo.toml",
    "content": "[package]\nname = \"electron-tests\"\nversion = \"0.1.0\"\nedition = \"2021\"\nauthors = [\"The Neon Community\"]\nlicense = \"MIT/Apache-2.0\"\n\n[lib]\ncrate-type = [\"cdylib\"]\n\n[dependencies.neon]\npath = \"../../crates/neon\"\n"
  },
  {
    "path": "test/electron/README.md",
    "content": "# neon-electron-quick-start\n\nThis is a minimal Electron application based on the [Quick Start Guide](https://electronjs.org/docs/tutorial/quick-start) within the Electron documentation combined with [Neon](https://neon-bindings.com).\n"
  },
  {
    "path": "test/electron/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->\n    <meta http-equiv=\"Content-Security-Policy\" content=\"default-src 'self'; script-src 'self'\">\n    <meta http-equiv=\"X-Content-Security-Policy\" content=\"default-src 'self'; script-src 'self'\">\n    <title>Neon Electron Test</title>\n  </head>\n  <body>\n    <h1 id=\"greeting\"></h1>\n\n    <!-- You can also require other files to run in this process -->\n    <script src=\"./renderer.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "test/electron/main.js",
    "content": "// Modules to control application life and create native browser window\nconst { app, BrowserWindow } = require(\"electron\");\nconst path = require(\"path\");\n\nfunction createWindow() {\n  // Create the browser window.\n  const mainWindow = new BrowserWindow({\n    width: 800,\n    height: 600,\n    webPreferences: {\n      contextIsolation: true,\n      preload: path.join(__dirname, \"preload.js\"),\n      nodeIntegration: true,\n    },\n  });\n\n  // and load the index.html of the app.\n  mainWindow.loadFile(\"index.html\");\n\n  // Open the DevTools.\n  // mainWindow.webContents.openDevTools()\n}\n\n// This method will be called when Electron has finished\n// initialization and is ready to create browser windows.\n// Some APIs can only be used after this event occurs.\napp.whenReady().then(() => {\n  createWindow();\n\n  app.on(\"activate\", function () {\n    // On macOS it's common to re-create a window in the app when the\n    // dock icon is clicked and there are no other windows open.\n    if (BrowserWindow.getAllWindows().length === 0) createWindow();\n  });\n});\n\n// Quit when all windows are closed\napp.on(\"window-all-closed\", function () {\n  app.quit();\n});\n"
  },
  {
    "path": "test/electron/main.test.js",
    "content": "\"use strict\";\n\nconst assert = require(\"assert\");\nconst path = require(\"path\");\n\nconst { _electron: electron } = require(\"playwright\");\nconst { test } = require(\"@playwright/test\");\n\ntest(\"greeting\", async () => {\n  const app = await electron.launch({\n    args: [path.join(__dirname, \"main.js\")],\n  });\n  const page = await app.firstWindow();\n  const header = page.locator(\"#greeting\");\n  const text = await header.textContent();\n\n  assert.strictEqual(text, \"Hello, World!\");\n});\n"
  },
  {
    "path": "test/electron/package.json",
    "content": "{\n  \"name\": \"electron-tests\",\n  \"version\": \"0.1.0\",\n  \"description\": \"Electron acceptance test suite for Neon\",\n  \"main\": \"main.js\",\n  \"author\": \"The Neon Community\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"install\": \"cargo-cp-artifact -nc index.node -- cargo build --message-format=json-render-diagnostics\",\n    \"start\": \"electron .\",\n    \"test\": \"playwright test\"\n  },\n  \"repository\": \"https://github.com/electron/electron-quick-start\",\n  \"devDependencies\": {\n    \"@playwright/test\": \"^1.40.1\",\n    \"cargo-cp-artifact\": \"^0.1.9\",\n    \"electron\": \"^27.1.3\",\n    \"playwright\": \"^1.40.1\"\n  }\n}\n"
  },
  {
    "path": "test/electron/preload.js",
    "content": "const native = require(\"./index.node\");\n\nwindow.addEventListener(\"DOMContentLoaded\", () => {\n  document.getElementById(\"greeting\").innerText = native.hello();\n});\n"
  },
  {
    "path": "test/electron/renderer.js",
    "content": "// This file is required by the index.html file and will\n// be executed in the renderer process for that window.\n// No Node.js APIs are available in this process because\n// `nodeIntegration` is turned off. Use `preload.js` to\n// selectively enable features needed in the rendering\n// process.\n"
  },
  {
    "path": "test/electron/src/lib.rs",
    "content": "use neon::prelude::*;\n\nfn hello(mut cx: FunctionContext) -> JsResult<JsString> {\n    Ok(cx.string(\"Hello, World!\"))\n}\n\n#[neon::main]\nfn main(mut cx: ModuleContext) -> NeonResult<()> {\n    cx.export_function(\"hello\", hello)?;\n\n    Ok(())\n}\n"
  },
  {
    "path": "test/napi/.gitignore",
    "content": "native/target\nnative/index.node\nnative/artifacts.json\n**/*~\n**/node_modules\n**/.DS_Store\n"
  },
  {
    "path": "test/napi/Cargo.toml",
    "content": "[package]\nname = \"napi-tests\"\nversion = \"0.1.0\"\nauthors = [\"The Neon Community <david.herman@gmail.com>\"]\nlicense = \"MIT\"\nexclude = [\"artifacts.json\", \"index.node\"]\nedition = \"2021\"\n\n[lib]\ncrate-type = [\"cdylib\"]\n\n[dependencies]\neither = \"1.13.0\"\nnum-bigint-dig = \"0.9.1\"\nonce_cell = \"1.18.0\"\nserde = { version = \"1.0\", features = [\"derive\"] }\ntokio = { version = \"1.34.0\", features = [\"rt-multi-thread\"] }\n\n[dependencies.neon]\npath = \"../../crates/neon\"\nfeatures = [\"futures\", \"napi-experimental\", \"external-buffers\", \"serde\", \"tokio\"]\n"
  },
  {
    "path": "test/napi/README.md",
    "content": "# napi\n\nAcceptance test suite for Neon with N-API backend\n"
  },
  {
    "path": "test/napi/lib/arrays.js",
    "content": "var addon = require(\"..\");\nvar assert = require(\"chai\").assert;\n\ndescribe(\"JsArray\", function () {\n  it(\"return a JsArray built in Rust\", function () {\n    assert.deepEqual([], addon.return_js_array());\n  });\n\n  it(\"return a JsArray with a number at index 0\", function () {\n    assert.deepEqual([9000], addon.return_js_array_with_number());\n  });\n\n  it(\"return a JsArray with an string at index 0\", function () {\n    assert.deepEqual([\"hello node\"], addon.return_js_array_with_string());\n  });\n\n  it(\"can read from a JsArray\", function () {\n    assert.strictEqual(addon.read_js_array([1234]), 1234);\n  });\n\n  it(\"returns undefined when accessing outside JsArray bounds\", function () {\n    assert.strictEqual(addon.read_js_array([]), undefined);\n  });\n});\n"
  },
  {
    "path": "test/napi/lib/bigint.js",
    "content": "const addon = require(\"..\");\n\ndescribe(\"JsBigInt\", () => {\n  const suite = addon.bigint_suite();\n\n  for (const [k, v] of Object.entries(suite)) {\n    it(k, v);\n  }\n});\n"
  },
  {
    "path": "test/napi/lib/boxed.js",
    "content": "const addon = require(\"..\");\nconst { expect } = require(\"chai\");\nconst assert = require(\"chai\").assert;\n\nclass Person {\n  constructor(name) {\n    this._person = addon.person_new(name);\n  }\n\n  greet() {\n    return addon.person_greet(this._person);\n  }\n}\n\nclass RefPerson {\n  constructor(name) {\n    this._person = addon.ref_person_new(name);\n  }\n\n  greet() {\n    return addon.ref_person_greet(this._person);\n  }\n\n  setName(name) {\n    addon.ref_person_set_name(this._person, name);\n\n    return this;\n  }\n\n  fail() {\n    addon.ref_person_fail(this._person);\n  }\n}\n\ndescribe(\"boxed\", function () {\n  it(\"can call methods\", function () {\n    const person = new Person(\"World\");\n    const greeting = person.greet();\n\n    assert.strictEqual(greeting, \"Hello, World!\");\n  });\n\n  it(\"can call methods wrapped in a RefCell\", function () {\n    const person = new RefPerson(\"World\");\n    const greeting = person.greet();\n\n    assert.strictEqual(greeting, \"Hello, World!\");\n  });\n\n  it(\"can mutate with ref cell\", function () {\n    const person = new RefPerson(\"World\").setName(\"Universe\");\n    const greeting = person.greet();\n\n    assert.strictEqual(greeting, \"Hello, Universe!\");\n  });\n\n  it(\"should dynamically check borrowing rules\", function () {\n    assert.throws(() => new RefPerson(\"World\").fail(), /already borrowed/);\n  });\n\n  it(\"should type check externals\", function () {\n    // `any::type_name` does not guarantee exact format\n    // failed downcast to neon::types::boxed::JsBox<napi::js::boxed::Person>\n    assert.throws(\n      () => addon.person_greet({}),\n      /failed to downcast.*JsBox.*Person/\n    );\n  });\n\n  it(\"should type check dynamic type\", function () {\n    const unit = addon.external_unit();\n\n    assert.throws(() => addon.person_greet(unit), /failed to downcast/);\n  });\n});\n"
  },
  {
    "path": "test/napi/lib/class.js",
    "content": "const addon = require(\"..\");\nconst assert = require(\"chai\").assert;\n\ndescribe(\"wrapping\", function () {\n  it(\"should be able to wrap a Rust value in an object\", () => {\n    const msg = \"Hello, World!\";\n    const o = {};\n\n    addon.wrapString(o, msg);\n    assert.strictEqual(addon.unwrapString(o), msg);\n  });\n\n  it(\"should not be able to wrap an object twice\", () => {\n    const o = {};\n\n    addon.wrapString(o, \"Hello, World!\");\n    assert.throws(\n      () => addon.wrapString(o, \"nope\"),\n      /non-class instance expected/\n    );\n  });\n\n  it(\"should not be able to unwrap an object that was not wrapped\", () => {\n    const o = {};\n\n    assert.throws(() => addon.unwrapString(o), /class instance expected/);\n  });\n});\n\ndescribe(\"classes\", function () {\n  it(\"can create a Message class\", function () {\n    const Message = addon.Message;\n\n    const message = new Message(\"Hello, Neon, this is your test speaking.\");\n    assert.instanceOf(message, Message);\n    assert.strictEqual(\n      message.read(),\n      \"Hello, Neon, this is your test speaking.\"\n    );\n    const message2 = message.concat(new Message(\"  <<FNORD>>\"));\n    assert.strictEqual(\n      message2.read(),\n      \"Hello, Neon, this is your test speaking.  <<FNORD>>\"\n    );\n  });\n\n  it(\"class methods have normal-looking function names\", function () {\n    const util = require(\"util\");\n    const Message = addon.Message;\n    const message = new Message(\"test\");\n    const StringBuffer = addon.StringBuffer;\n    const buffer = new StringBuffer();\n\n    assert.strictEqual(message.read.name, \"read\");\n    assert.strictEqual(message.append.name, \"append\");\n    assert.strictEqual(message.concat.name, \"concat\");\n    assert.strictEqual(buffer.includes.name, \"includes\");\n    assert.strictEqual(buffer.trimStart.name, \"trimStart\");\n    assert.strictEqual(buffer.trimEnd.name, \"trimEnd\");\n\n    assert.strictEqual(util.inspect(message.read), \"[Function: read]\");\n    assert.strictEqual(util.inspect(message.append), \"[Function: append]\");\n    assert.strictEqual(util.inspect(message.concat), \"[Function: concat]\");\n    assert.strictEqual(util.inspect(buffer.includes), \"[Function: includes]\");\n    assert.strictEqual(util.inspect(buffer.trimStart), \"[Function: trimStart]\");\n    assert.strictEqual(util.inspect(buffer.trimEnd), \"[Function: trimEnd]\");\n\n    assert.strictEqual(\n      message.read.toString(),\n      \"function read() { [native code] }\"\n    );\n    assert.strictEqual(\n      message.append.toString(),\n      \"function append() { [native code] }\"\n    );\n    assert.strictEqual(\n      message.concat.toString(),\n      \"function concat() { [native code] }\"\n    );\n\n    assert.strictEqual(\n      \"[object Function]\",\n      Object.prototype.toString.call(message.read)\n    );\n    assert.strictEqual(\n      \"[object Function]\",\n      Object.prototype.toString.call(message.append)\n    );\n    assert.strictEqual(\n      \"[object Function]\",\n      Object.prototype.toString.call(message.concat)\n    );\n\n    assert.strictEqual(\n      buffer.includes.toString(),\n      \"function includes() { [native code] }\"\n    );\n    assert.strictEqual(\n      buffer.trimStart.toString(),\n      \"function trimStart() { [native code] }\"\n    );\n    assert.strictEqual(\n      buffer.trimEnd.toString(),\n      \"function trimEnd() { [native code] }\"\n    );\n  });\n\n  it(\"can mutate a Message with &mut self\", function () {\n    const Message = addon.Message;\n\n    const message = new Message(\"Hello\");\n    assert.strictEqual(message.read(), \"Hello\");\n    message.append(\", World\");\n    assert.strictEqual(message.read(), \"Hello, World\");\n    message.append(\"!\");\n    assert.strictEqual(message.read(), \"Hello, World!\");\n  });\n\n  it(\"can subclass a Neon class\", function () {\n    const Message = addon.Message;\n\n    class LoudMessage extends Message {\n      shout() {\n        return this.read().toUpperCase();\n      }\n    }\n\n    const message = new LoudMessage(\"Hello, Neon, this is your test speaking.\");\n    assert.instanceOf(message, Message);\n    assert.instanceOf(message, LoudMessage);\n    assert.strictEqual(\n      message.read(),\n      \"Hello, Neon, this is your test speaking.\"\n    );\n    assert.strictEqual(\n      message.shout(),\n      \"HELLO, NEON, THIS IS YOUR TEST SPEAKING.\"\n    );\n    const message2 = message.concat(new Message(\"  <<FNORD>>\"));\n    assert.strictEqual(\n      message2.read(),\n      \"Hello, Neon, this is your test speaking.  <<FNORD>>\"\n    );\n    assert.throws(() => message2.shout());\n  });\n\n  it(\"can create a Point class\", function () {\n    const Point = addon.Point;\n\n    const point = new Point(1, 2);\n    assert.instanceOf(point, Point);\n    assert.strictEqual(point.x(), 1);\n    assert.strictEqual(point.y(), 2);\n\n    const point2 = new Point(3, 4);\n    assert.instanceOf(point2, Point);\n    assert.strictEqual(point2.x(), 3);\n    assert.strictEqual(point2.y(), 4);\n    assert.strictEqual(point.distance(point2), Math.sqrt(8));\n  });\n\n  it(\"fails with a TypeError when passing a non-object as &Point argument\", function () {\n    const Point = addon.Point;\n\n    const point = new Point(1, 2);\n    assert.instanceOf(point, Point);\n    assert.strictEqual(point.x(), 1);\n    assert.strictEqual(point.y(), 2);\n\n    assert.throws(() => {\n      point.distance(42);\n    }, TypeError);\n  });\n\n  it(\"can mutate a Point with &mut self\", function () {\n    const Point = addon.Point;\n\n    const point = new Point(10, 20);\n    assert.strictEqual(point.x(), 10);\n    assert.strictEqual(point.y(), 20);\n\n    point.moveBy(5, 3);\n    assert.strictEqual(point.x(), 15);\n    assert.strictEqual(point.y(), 23);\n\n    point.setX(100);\n    assert.strictEqual(point.x(), 100);\n    assert.strictEqual(point.y(), 23);\n\n    point.setY(200);\n    assert.strictEqual(point.x(), 100);\n    assert.strictEqual(point.y(), 200);\n  });\n\n  it(\"can swap coordinates between two Points using &mut references\", function () {\n    const Point = addon.Point;\n\n    const p1 = new Point(10, 20);\n    const p2 = new Point(30, 40);\n\n    assert.strictEqual(p1.x(), 10);\n    assert.strictEqual(p1.y(), 20);\n    assert.strictEqual(p2.x(), 30);\n    assert.strictEqual(p2.y(), 40);\n\n    p1.swapCoords(p2);\n\n    assert.strictEqual(p1.x(), 30);\n    assert.strictEqual(p1.y(), 40);\n    assert.strictEqual(p2.x(), 10);\n    assert.strictEqual(p2.y(), 20);\n  });\n\n  it(\"fails with a TypeError when passing a non-object as &mut Point argument\", function () {\n    const Point = addon.Point;\n\n    const point = new Point(1, 2);\n    assert.instanceOf(point, Point);\n    assert.strictEqual(point.x(), 1);\n    assert.strictEqual(point.y(), 2);\n\n    assert.throws(() => {\n      point.swapCoords(42);\n    }, TypeError);\n  });\n\n  it(\"fails with TypeError when passing wrong type to Message.concat\", function () {\n    const Message = addon.Message;\n    const Point = addon.Point;\n    const message = new Message(\"Hello\");\n    const point = new Point(1, 2);\n\n    // Test with various wrong types\n    assert.throws(\n      () => message.concat(null),\n      TypeError,\n      /expected object/,\n      \"should reject null\"\n    );\n    assert.throws(\n      () => message.concat(undefined),\n      TypeError,\n      /expected object/,\n      \"should reject undefined\"\n    );\n    assert.throws(\n      () => message.concat(\"string\"),\n      TypeError,\n      /expected object/,\n      \"should reject string\"\n    );\n    assert.throws(\n      () => message.concat(42),\n      TypeError,\n      /expected object/,\n      \"should reject number\"\n    );\n    assert.throws(\n      () => message.concat({ value: \"test\" }),\n      TypeError,\n      /class instance expected/,\n      \"should reject plain object\"\n    );\n    assert.throws(\n      () => message.concat([]),\n      TypeError,\n      /class instance expected/,\n      \"should reject array\"\n    );\n    assert.throws(\n      () => message.concat(point),\n      TypeError,\n      /expected instance of.*Message/,\n      \"should reject instance of different class\"\n    );\n  });\n\n  it(\"fails with TypeError when passing wrong type to Point.midpoint\", function () {\n    const Point = addon.Point;\n    const point = new Point(5, 10);\n\n    // Test with various wrong types\n    assert.throws(\n      () => point.midpoint(null),\n      TypeError,\n      /expected object/,\n      \"should reject null\"\n    );\n    assert.throws(\n      () => point.midpoint(undefined),\n      TypeError,\n      /expected object/,\n      \"should reject undefined\"\n    );\n    assert.throws(\n      () => point.midpoint(\"string\"),\n      TypeError,\n      /expected object/,\n      \"should reject string\"\n    );\n    assert.throws(\n      () => point.midpoint(123),\n      TypeError,\n      /expected object/,\n      \"should reject number\"\n    );\n    assert.throws(\n      () => point.midpoint({ x: 1, y: 2 }),\n      TypeError,\n      /class instance expected/,\n      \"should reject plain object\"\n    );\n  });\n\n  it(\"fails with TypeError when mixing different class types\", function () {\n    const Point = addon.Point;\n    const Message = addon.Message;\n\n    const point = new Point(1, 2);\n    const message = new Message(\"test\");\n\n    // Try to pass a Message where a Point is expected\n    try {\n      point.distance(message);\n      assert.fail(\"should have thrown an error\");\n    } catch (e) {\n      assert.instanceOf(e, TypeError);\n      assert.match(e.message, /expected instance of.*Point/);\n      // Uncomment to see the actual error message:\n      // console.log(\"Point error:\", e.message);\n    }\n\n    // Try to pass a Point where a Message is expected\n    try {\n      message.concat(point);\n      assert.fail(\"should have thrown an error\");\n    } catch (e) {\n      assert.instanceOf(e, TypeError);\n      assert.match(e.message, /expected instance of.*Message/);\n      // Uncomment to see the actual error message:\n      // console.log(\"Message error:\", e.message);\n    }\n  });\n\n  it(\"Point class has const properties\", function () {\n    const Point = addon.Point;\n\n    // Test basic const properties\n    assert.strictEqual(Point.ORIGIN_X, 0);\n    assert.strictEqual(Point.ORIGIN_Y, 0);\n\n    // Test const property with custom name\n    assert.strictEqual(Point.maxCoordinate, 1000);\n\n    // Test const property with JSON serialization\n    assert.deepEqual(Point.DEFAULT_MESSAGE, [\"hello\", \"point\"]);\n  });\n\n  it(\"Point const properties are immutable\", function () {\n    const Point = addon.Point;\n\n    // Store original values\n    const originalX = Point.ORIGIN_X;\n    const originalMaxCoord = Point.maxCoordinate;\n\n    // Attempt to modify properties (should silently fail in non-strict mode)\n    Point.ORIGIN_X = 999;\n    Point.maxCoordinate = 5000;\n\n    // Values should be unchanged\n    assert.strictEqual(Point.ORIGIN_X, originalX);\n    assert.strictEqual(Point.maxCoordinate, originalMaxCoord);\n\n    // Check property descriptors\n    const descX = Object.getOwnPropertyDescriptor(Point, \"ORIGIN_X\");\n    assert.strictEqual(descX.writable, false);\n    assert.strictEqual(descX.configurable, false);\n    assert.strictEqual(descX.enumerable, true);\n\n    const descMaxCoord = Object.getOwnPropertyDescriptor(\n      Point,\n      \"maxCoordinate\"\n    );\n    assert.strictEqual(descMaxCoord.writable, false);\n    assert.strictEqual(descMaxCoord.configurable, false);\n    assert.strictEqual(descMaxCoord.enumerable, true);\n  });\n\n  it(\"Point supports complex const expressions\", function () {\n    const Point = addon.Point;\n\n    // Test computed const expressions\n    assert.strictEqual(Point.COMPUTED_VALUE, 42); // 10 + 20 + 12\n    assert.strictEqual(Point.SIZE_OF_F64, 8); // std::mem::size_of::<f64>()\n    assert.strictEqual(Point.STRING_LENGTH, 7); // \"complex\".len()\n\n    // Verify they're immutable\n    const original = Point.COMPUTED_VALUE;\n    Point.COMPUTED_VALUE = 999;\n    assert.strictEqual(Point.COMPUTED_VALUE, original);\n  });\n\n  it(\"Point supports edge case const expressions\", function () {\n    const Point = addon.Point;\n\n    // Test boolean const\n    assert.strictEqual(Point.IS_2D, true);\n    assert.strictEqual(typeof Point.IS_2D, \"boolean\");\n\n    // Test conditional const expression\n    assert.strictEqual(Point.MAX_DIMENSION, 2147483647);\n\n    // Test match expression const\n    assert.strictEqual(Point.COORDINATE_BYTES, 4);\n\n    // Test const with arithmetic\n    assert.strictEqual(Point.DOUBLE_100_SQUARED, 20000); // 100^2 * 2\n\n    // Test string with special characters (renamed property)\n    assert.strictEqual(Point.specialString, 'Hello\\nWorld\\t\"quoted\"\\r\\n');\n\n    // Test negative number\n    assert.strictEqual(Point.NEGATIVE_OFFSET, -42);\n\n    // Test large integer (approximate)\n    assert.strictEqual(Point.MAX_SAFE_INTEGER_APPROX, 2147483647);\n\n    // Test const starting with underscore\n    assert.strictEqual(Point._PRIVATE_CONST, 999);\n\n    // Verify all edge case properties are immutable\n    const props = [\n      \"IS_2D\",\n      \"MAX_DIMENSION\",\n      \"COORDINATE_BYTES\",\n      \"DOUBLE_100_SQUARED\",\n      \"specialString\",\n      \"NEGATIVE_OFFSET\",\n      \"MAX_SAFE_INTEGER_APPROX\",\n      \"_PRIVATE_CONST\",\n    ];\n\n    props.forEach((prop) => {\n      const descriptor = Object.getOwnPropertyDescriptor(Point, prop);\n      assert.strictEqual(\n        descriptor.writable,\n        false,\n        `${prop} should not be writable`\n      );\n      assert.strictEqual(\n        descriptor.configurable,\n        false,\n        `${prop} should not be configurable`\n      );\n      assert.strictEqual(\n        descriptor.enumerable,\n        true,\n        `${prop} should be enumerable`\n      );\n    });\n  });\n\n  it(\"can create a StringBuffer class with Default constructor\", function () {\n    const StringBuffer = addon.StringBuffer;\n\n    const buffer = new StringBuffer();\n    buffer.push(\"Hello\");\n    buffer.push(\" \");\n    buffer.push(\"World\");\n    assert.strictEqual(buffer.toString(), \"Hello World\");\n  });\n\n  it(\"can use a renamed method in StringBuffer\", function () {\n    const StringBuffer = addon.StringBuffer;\n\n    const buffer = new StringBuffer();\n    buffer.push(\"  Hello  \");\n    assert.strictEqual(buffer.trimStart(), \"Hello  \");\n    assert.strictEqual(buffer.trimEnd(), \"  Hello\");\n\n    assert.isTrue(buffer.includes(\"Hello\"));\n    assert.isFalse(buffer.includes(\"World\"));\n  });\n\n  // async tests\n  it(\"AsyncClass should create instance\", function () {\n    const AsyncClass = addon.AsyncClass;\n    const instance = new AsyncClass(\"hello\");\n    assert.ok(instance instanceof AsyncClass);\n  });\n\n  it(\"AsyncClass should have sync method\", function () {\n    const AsyncClass = addon.AsyncClass;\n    const instance = new AsyncClass(\"hello\");\n    assert.strictEqual(instance.syncMethod(), \"hello\");\n  });\n\n  it(\"AsyncClass should have async method\", async function () {\n    const AsyncClass = addon.AsyncClass;\n    const instance = new AsyncClass(\"hello\");\n    const result = await instance.asyncMethod(\" world\");\n    assert.strictEqual(result, \"hello world\");\n  });\n\n  it(\"AsyncClass should have task method for CPU-intensive work\", async function () {\n    const AsyncClass = addon.AsyncClass;\n    const instance = new AsyncClass(\"test\");\n    const result = await instance.heavyComputation();\n    // Sum of 0..99 = (99 * 100) / 2 = 4950\n    assert.strictEqual(result, 4950);\n  });\n\n  it(\"AsyncClass should have JSON method\", function () {\n    const AsyncClass = addon.AsyncClass;\n    const instance = new AsyncClass(\"test\");\n    const input = [\"item1\", \"item2\", \"item3\"];\n    const result = instance.jsonMethod(input);\n\n    assert.strictEqual(typeof result, \"object\");\n    assert.strictEqual(result.class_value, \"test\");\n    assert.strictEqual(result.input_count, \"3\");\n    assert.strictEqual(result.first_item, \"item1\");\n  });\n\n  it(\"AsyncClass should have explicit async method (Meta::Async)\", async function () {\n    const AsyncClass = addon.AsyncClass;\n    const instance = new AsyncClass(\"test\");\n    const result = await instance.explicitAsyncMethod(3);\n    assert.strictEqual(result, \"Processing: test * 3\");\n  });\n\n  it(\"AsyncClass should have explicit async method with clone\", async function () {\n    const AsyncClass = addon.AsyncClass;\n    const instance = new AsyncClass(\"test\");\n    const result = await instance.explicitAsyncClone(\" cloned\");\n    assert.strictEqual(result, \"test cloned\");\n  });\n\n  it(\"AsyncClass should have method with context parameter\", function () {\n    const AsyncClass = addon.AsyncClass;\n    const instance = new AsyncClass(\"hello\");\n    const result = instance.methodWithContext(3);\n    // \"hello\".length = 5, so 5 * 3 = 15\n    assert.strictEqual(result, 15);\n  });\n\n  it(\"AsyncClass should have method with explicit context attribute\", function () {\n    const AsyncClass = addon.AsyncClass;\n    const instance = new AsyncClass(\"test\");\n    const result = instance.methodWithExplicitContext(\" suffix\");\n    assert.strictEqual(result, \"test: suffix\");\n  });\n\n  it(\"AsyncClass should have task method with channel parameter\", async function () {\n    const AsyncClass = addon.AsyncClass;\n    const instance = new AsyncClass(\"test\");\n    const result = await instance.taskWithChannel(5);\n    assert.strictEqual(result, \"Task with channel: test * 5\");\n  });\n\n  it(\"AsyncClass should have async fn method with channel parameter\", async function () {\n    const AsyncClass = addon.AsyncClass;\n    const instance = new AsyncClass(\"test\");\n    const result = await instance.asyncFnWithChannel(\" async\");\n    assert.strictEqual(result, \"AsyncFn with channel: test async\");\n  });\n\n  it(\"AsyncClass should have method with this parameter\", function () {\n    const AsyncClass = addon.AsyncClass;\n    const instance = new AsyncClass(\"test\");\n    const result = instance.methodWithThis(\" data\");\n    assert.strictEqual(\n      result,\n      \"Instance: test, JS object available, data:  data\"\n    );\n  });\n\n  it(\"AsyncClass should have method with explicit this attribute\", function () {\n    const AsyncClass = addon.AsyncClass;\n    const instance = new AsyncClass(\"test\");\n    const result = instance.methodWithExplicitThis(\" suffix\");\n    assert.strictEqual(result, \"Explicit this: test suffix\");\n  });\n\n  it(\"AsyncClass should have method with context and this\", function () {\n    const AsyncClass = addon.AsyncClass;\n    const instance = new AsyncClass(\"hello\");\n    const result = instance.methodWithContextAndThis(4);\n    // \"hello\".length = 5, so 5 * 4 = 20\n    assert.strictEqual(result, 20);\n  });\n\n  it(\"AsyncClass should have reasonable performance for simple methods\", function () {\n    const AsyncClass = addon.AsyncClass;\n    const instance = new AsyncClass(\"test\");\n    const start = process.hrtime.bigint();\n\n    // Run 1000 simple method calls\n    for (let i = 0; i < 1000; i++) {\n      instance.simpleMethod(i);\n    }\n\n    const end = process.hrtime.bigint();\n    const durationMs = Number(end - start) / 1000000; // Convert to milliseconds\n\n    // Should complete 1000 calls in reasonable time (less than 100ms is very good)\n    assert(\n      durationMs < 1000,\n      `Performance test took ${durationMs}ms for 1000 calls`\n    );\n  });\n\n  it(\"AsyncClass should handle JSON methods efficiently\", function () {\n    const AsyncClass = addon.AsyncClass;\n    const instance = new AsyncClass(\"test\");\n    const testData = [1, 2, 3, 4, 5];\n\n    const start = process.hrtime.bigint();\n\n    // Run 100 JSON method calls\n    for (let i = 0; i < 100; i++) {\n      const result = instance.jsonMethodPerf(testData);\n      assert.deepStrictEqual(result, [2, 4, 6, 8, 10]);\n    }\n\n    const end = process.hrtime.bigint();\n    const durationMs = Number(end - start) / 1000000;\n\n    // JSON serialization has overhead but should still be reasonable\n    assert(\n      durationMs < 1000,\n      `JSON performance test took ${durationMs}ms for 100 calls`\n    );\n  });\n\n  it(\"AsyncClass should handle context methods efficiently\", function () {\n    const AsyncClass = addon.AsyncClass;\n    const instance = new AsyncClass(\"test\");\n\n    const start = process.hrtime.bigint();\n\n    // Run 1000 context method calls\n    for (let i = 0; i < 1000; i++) {\n      const result = instance.contextMethodPerf(i);\n      assert.strictEqual(result, i * 3);\n    }\n\n    const end = process.hrtime.bigint();\n    const durationMs = Number(end - start) / 1000000;\n\n    // Context methods should have minimal overhead\n    assert(\n      durationMs < 1000,\n      `Context performance test took ${durationMs}ms for 1000 calls`\n    );\n  });\n\n  it(\"AsyncClass async method consumes self\", async function () {\n    const AsyncClass = addon.AsyncClass;\n    const instance = new AsyncClass(\"test\");\n    await instance.asyncMethod(\" once\");\n\n    // This should fail because the instance has been consumed\n    // In practice, we might want to document this limitation\n    // or find a better approach for async methods\n  });\n\n  it(\"AsyncClass has const properties\", function () {\n    const AsyncClass = addon.AsyncClass;\n\n    // Test basic const property\n    assert.strictEqual(AsyncClass.DEFAULT_TIMEOUT, 5000);\n\n    // Test const property with custom name and JSON serialization\n    assert.deepEqual(AsyncClass.version, [1, 0, 0]);\n  });\n\n  it(\"AsyncClass should have explicit async JSON method\", async function () {\n    const AsyncClass = addon.AsyncClass;\n    const instance = new AsyncClass(\"test\");\n    const input = [1, 2, 3, 4, 5];\n    const result = await instance.explicitAsyncJsonMethod(input);\n\n    assert.deepStrictEqual(result, [2, 4, 6, 8, 10]);\n  });\n\n  it(\"AsyncClass should have auto-detected async JSON method\", async function () {\n    const AsyncClass = addon.AsyncClass;\n    const instance = new AsyncClass(\"test\");\n    const input = [1, 2, 3, 4, 5];\n    const result = await instance.asyncJsonMethod(input);\n\n    // Should multiply each element by 2\n    assert.deepStrictEqual(result, [2, 4, 6, 8, 10]);\n  });\n\n  it(\"can create Point instances from Rust code\", function () {\n    const Point = addon.Point;\n\n    // Test creating instance via Rust function (Rust → JS path)\n    const rustPoint = addon.createPointFromRust(10, 20);\n\n    // Verify it's an instance of the class\n    assert.instanceOf(rustPoint, Point);\n    assert.strictEqual(rustPoint.x(), 10);\n    assert.strictEqual(rustPoint.y(), 20);\n\n    // Test that Rust-created and JS-created instances are compatible\n    const jsPoint = new Point(5, 10);\n    const distance = rustPoint.distance(jsPoint);\n\n    // Distance between (10, 20) and (5, 10) = sqrt((10-5)^2 + (20-10)^2) = sqrt(25 + 100) = sqrt(125)\n    assert.strictEqual(distance, Math.sqrt(125));\n  });\n\n  it(\"can create origin Point from Rust\", function () {\n    const Point = addon.Point;\n\n    const origin = addon.createPointOrigin();\n    assert.instanceOf(origin, Point);\n    assert.strictEqual(origin.x(), 0);\n    assert.strictEqual(origin.y(), 0);\n  });\n\n  it(\"can transform Points in Rust and return new instances\", function () {\n    const Point = addon.Point;\n\n    // Create point in JS\n    const original = new Point(3, 4);\n\n    // Pass to Rust, transform, and get back new instance\n    const doubled = addon.doublePointCoords(original);\n\n    // Verify the returned point\n    assert.instanceOf(doubled, Point);\n    assert.strictEqual(doubled.x(), 6);\n    assert.strictEqual(doubled.y(), 8);\n\n    // Verify original is unchanged\n    assert.strictEqual(original.x(), 3);\n    assert.strictEqual(original.y(), 4);\n  });\n});\n\ndescribe(\"constructor features\", function () {\n  const {\n    FallibleCounter,\n    ContextCounter,\n    JsonConfig,\n    ValidatedConfig,\n    Argv,\n    Secret,\n    Carousel,\n    Expando,\n  } = addon;\n\n  describe(\"nullary constructor\", function () {\n    it(\"should support nullary constructors\", () => {\n      const carousel = new Carousel();\n      assert.strictEqual(carousel.next(), \"Welcome to the Neon Carousel!\");\n      assert.strictEqual(\n        carousel.next(),\n        \"Enjoy seamless Rust and JavaScript integration.\"\n      );\n      assert.strictEqual(\n        carousel.next(),\n        \"Experience high performance with native modules.\"\n      );\n      assert.strictEqual(\n        carousel.next(),\n        \"Build robust applications with ease.\"\n      );\n      assert.strictEqual(carousel.next(), \"Thank you for using Neon!\");\n      assert.strictEqual(carousel.next(), \"Welcome to the Neon Carousel!\");\n    });\n  });\n\n  describe(\"Result return types\", function () {\n    it(\"should create instance when constructor succeeds\", () => {\n      const counter = new FallibleCounter(50);\n      assert.strictEqual(counter.get(), 50);\n      counter.increment();\n      assert.strictEqual(counter.get(), 51);\n    });\n\n    it(\"should throw error when constructor fails\", () => {\n      assert.throws(() => new FallibleCounter(150), /Value must be <= 100/);\n    });\n\n    it(\"should work with edge case: maximum valid value\", () => {\n      const counter = new FallibleCounter(100);\n      assert.strictEqual(counter.get(), 100);\n    });\n  });\n\n  describe(\"Context parameter support\", function () {\n    it(\"should create instance with context parameter\", () => {\n      const counter = new ContextCounter(42);\n      assert.strictEqual(counter.get(), 42);\n    });\n\n    it(\"should work with different values\", () => {\n      const counter1 = new ContextCounter(10);\n      const counter2 = new ContextCounter(20);\n      assert.strictEqual(counter1.get(), 10);\n      assert.strictEqual(counter2.get(), 20);\n    });\n\n    it(\"should provide correct cx.this() to constructor\", () => {\n      const o = new Expando();\n      assert.strictEqual(o.expando(), 42);\n    });\n  });\n\n  describe(\"JSON support\", function () {\n    it(\"should create instance from JSON object\", () => {\n      const config = new JsonConfig({\n        name: \"test\",\n        count: 5,\n        enabled: true,\n      });\n      assert.strictEqual(config.name(), \"test\");\n      assert.strictEqual(config.count(), 5);\n      assert.strictEqual(config.enabled(), true);\n    });\n\n    it(\"should work with different JSON values\", () => {\n      const config = new JsonConfig({\n        name: \"another\",\n        count: 100,\n        enabled: false,\n      });\n      assert.strictEqual(config.name(), \"another\");\n      assert.strictEqual(config.count(), 100);\n      assert.strictEqual(config.enabled(), false);\n    });\n  });\n\n  describe(\"Combined features: context + Result\", function () {\n    it(\"should propagate errors with nullable JSON array\", () => {\n      assert.throws(\n        () =>\n          new Secret(() => {\n            throw new Error(\"Access denied\");\n          }),\n        /Access denied/\n      );\n    });\n  });\n\n  describe(\"Combined features: context + JSON + Result\", function () {\n    it(\"should create an instance with JSON array\", () => {\n      const argv = new Argv([\"1\", \"2\", \"3\", \"4\", \"5\"]);\n      assert.strictEqual(argv.len(), 5);\n      assert.strictEqual(argv.get(0), \"1\");\n      assert.strictEqual(argv.get(4), \"5\");\n    });\n\n    it(\"should create instance with empty JSON array\", () => {\n      const argv = new Argv([]);\n      assert.strictEqual(argv.len(), 0);\n    });\n\n    it(\"should create instance with nullable JSON array\", () => {\n      const argv = new Argv(null);\n      assert.strictEqual(argv.len(), process.argv.length);\n      for (let i = 0; i < process.argv.length; i++) {\n        assert.strictEqual(argv.get(i), process.argv[i]);\n      }\n    });\n\n    it(\"should create instance when validation passes\", () => {\n      const config = new ValidatedConfig({\n        name: \"valid\",\n        count: 500,\n      });\n      assert.strictEqual(config.name(), \"valid\");\n      assert.strictEqual(config.count(), 500);\n    });\n\n    it(\"should throw error when name is empty\", () => {\n      assert.throws(\n        () => new ValidatedConfig({ name: \"\", count: 10 }),\n        /Name cannot be empty/\n      );\n    });\n\n    it(\"should throw error when count is too large\", () => {\n      assert.throws(\n        () => new ValidatedConfig({ name: \"test\", count: 2000 }),\n        /Count must be <= 1000/\n      );\n    });\n\n    it(\"should work with edge case: maximum valid count\", () => {\n      const config = new ValidatedConfig({\n        name: \"edge\",\n        count: 1000,\n      });\n      assert.strictEqual(config.count(), 1000);\n    });\n  });\n});\n"
  },
  {
    "path": "test/napi/lib/coercions.js",
    "content": "var addon = require(\"..\");\nvar assert = require(\"chai\").assert;\n\ndescribe(\"coercions\", function () {\n  it(\"can stringify\", function () {\n    assert.strictEqual(addon.to_string([1, 2, 3]), \"1,2,3\");\n    assert.strictEqual(addon.to_string(new Map()), \"[object Map]\");\n    assert.strictEqual(addon.to_string({ a: \"b\" }), \"[object Object]\");\n  });\n});\n"
  },
  {
    "path": "test/napi/lib/container.js",
    "content": "const addon = require(\"..\");\nconst { expect } = require(\"chai\");\nconst assert = require(\"chai\").assert;\n\ndescribe(\"Container type extractors\", function () {\n  it(\"can produce and consume a RefCell\", function () {\n    const cell = addon.createStringRefCell(\"my sekret mesij\");\n    const s = addon.readStringRefCell(cell);\n    assert.strictEqual(s, \"my sekret mesij\");\n  });\n\n  it(\"can produce and modify a RefCell\", function () {\n    const cell = addon.createStringRefCell(\"new\");\n    addon.writeStringRefCell(cell, \"modified\");\n    assert.strictEqual(addon.readStringRefCell(cell), \"modified\");\n  });\n\n  it(\"can concatenate a RefCell<String> with a String\", function () {\n    const cell = addon.createStringRefCell(\"hello\");\n    const s = addon.stringRefCellConcat(cell, \" world\");\n    assert.strictEqual(s, \"hello world\");\n  });\n\n  it(\"fail with a type error when not given a RefCell\", function () {\n    try {\n      addon.stringRefCellConcat(\"hello\", \" world\");\n      assert.fail(\"should have thrown\");\n    } catch (err) {\n      assert.instanceOf(err, TypeError);\n      assert.strictEqual(\n        err.message,\n        \"expected neon::types_impl::boxed::JsBox<core::cell::RefCell<alloc::string::String>>\"\n      );\n    }\n  });\n\n  it(\"dynamically fail when borrowing a mutably borrowed RefCell\", function () {\n    const cell = addon.createStringRefCell(\"hello\");\n    try {\n      addon.borrowMutAndThen(cell, () => {\n        addon.stringRefConcat(cell, \" world\");\n      });\n      assert.fail(\"should have thrown\");\n    } catch (err) {\n      assert.instanceOf(err, Error);\n      assert.include(err.message, \"already mutably borrowed\");\n    }\n  });\n\n  it(\"dynamically fail when modifying a borrowed RefCell\", function () {\n    const cell = addon.createStringRefCell(\"hello\");\n    try {\n      addon.borrowAndThen(cell, () => {\n        addon.writeStringRef(cell, \"world\");\n      });\n      assert.fail(\"should have thrown\");\n    } catch (err) {\n      assert.instanceOf(err, Error);\n      assert.include(err.message, \"already borrowed\");\n    }\n  });\n\n  it(\"can produce and consume an Rc\", function () {\n    const cell = addon.createStringRc(\"my sekret mesij\");\n    const s = addon.readStringRc(cell);\n    assert.strictEqual(s, \"my sekret mesij\");\n  });\n\n  it(\"can produce and consume an Arc\", function () {\n    const cell = addon.createStringArc(\"my sekret mesij\");\n    const s = addon.readStringArc(cell);\n    assert.strictEqual(s, \"my sekret mesij\");\n  });\n});\n"
  },
  {
    "path": "test/napi/lib/date.js",
    "content": "var addon = require(\"..\");\nvar assert = require(\"chai\").assert;\n\ndescribe(\"JsDate\", function () {\n  it(\"should create a date\", function () {\n    const date = addon.create_date();\n    assert.instanceOf(date, Date);\n  });\n\n  it(\"should create date from time\", function () {\n    const date = addon.create_date_from_value(31415);\n    assert.instanceOf(date, Date);\n    assert.equal(date.toUTCString(), new Date(31415).toUTCString());\n  });\n\n  it(\"should check if date is valid\", function () {\n    const dateIsValid = addon.check_date_is_valid(31415);\n    assert.isTrue(dateIsValid);\n  });\n\n  it(\"should try new date\", function () {\n    assert.isUndefined(addon.try_new_date());\n  });\n\n  it(\"should try new lossy date\", function () {\n    assert.isUndefined(addon.try_new_lossy_date());\n  });\n\n  it(\"should handle nan dates\", function () {\n    assert.isUndefined(addon.nan_dates());\n  });\n\n  it(\"should check if date is invalid\", function () {\n    const date = addon.create_and_get_invalid_date();\n    assert.isNaN(date);\n  });\n\n  it(\"should get date value\", function () {\n    const dateValue = addon.get_date_value();\n    assert.equal(dateValue, 31415);\n  });\n});\n"
  },
  {
    "path": "test/napi/lib/errors.js",
    "content": "const addon = require(\"..\");\nconst assert = require(\"chai\").assert;\n\ndescribe(\"errors\", function () {\n  it(\"should be able to create an error\", function () {\n    const msg = \"Oh, no!\";\n    const err = addon.new_error(msg);\n\n    assert.instanceOf(err, Error);\n    assert.strictEqual(err.message, msg);\n  });\n\n  it(\"should be able to create a type error\", function () {\n    const msg = \"Type error? From Rust?!\";\n    const err = addon.new_type_error(msg);\n\n    assert.instanceOf(err, TypeError);\n    assert.instanceOf(err, Error);\n    assert.strictEqual(err.message, msg);\n  });\n\n  it(\"should be able to create a range error\", function () {\n    const msg = \"Out of Bounds\";\n    const err = addon.new_range_error(msg);\n\n    assert.instanceOf(err, RangeError);\n    assert.instanceOf(err, Error);\n    assert.strictEqual(err.message, msg);\n  });\n\n  it(\"should be able to throw an error\", function () {\n    const msg = \"Out of Bounds\";\n\n    assert.throws(() => addon.throw_error(msg), msg);\n  });\n\n  it(\"should be able to stringify a downcast error\", function () {\n    let msg = addon.downcast_error();\n    assert.strictEqual(msg, \"failed to downcast string to number\");\n  });\n});\n"
  },
  {
    "path": "test/napi/lib/export.js",
    "content": "const assert = require(\"assert\");\n\nconst addon = require(\"..\");\n\ndescribe(\"neon::export macro\", () => {\n  describe(\"globals\", globals);\n  describe(\"functions\", functions);\n  describe(\"classes\", classes);\n});\n\nfunction globals() {\n  it(\"values\", () => {\n    assert.strictEqual(addon.NUMBER, 42);\n    assert.strictEqual(addon.STRING, \"Hello, World!\");\n    assert.strictEqual(addon.renamedString, \"Hello, World!\");\n  });\n\n  it(\"json\", () => {\n    assert.deepStrictEqual(addon.MESSAGES, [\"hello\", \"neon\"]);\n    assert.deepStrictEqual(addon.renamedMessages, [\"hello\", \"neon\"]);\n  });\n\n  it(\"LazyLock\", () => {\n    assert.strictEqual(addon.LAZY_LOCK_HELLO, \"Hello, Neon!\");\n  });\n}\n\nfunction functions() {\n  it(\"void function\", () => {\n    assert.strictEqual(addon.noArgsOrReturn(), undefined);\n  });\n\n  it(\"add - sync\", () => {\n    assert.strictEqual(addon.simpleAdd(1, 2), 3);\n    assert.strictEqual(addon.renamedAdd(1, 2), 3);\n  });\n\n  it(\"add - task\", async () => {\n    const p1 = addon.addTask(1, 2);\n    const p2 = addon.renamedAddTask(1, 2);\n\n    assert.ok(p1 instanceof Promise);\n    assert.ok(p2 instanceof Promise);\n\n    assert.strictEqual(await p1, 3);\n    assert.strictEqual(await p2, 3);\n  });\n\n  it(\"json sort\", () => {\n    const arr = [\"b\", \"c\", \"a\"];\n    const expected = [...arr].sort();\n\n    assert.deepStrictEqual(addon.jsonSort(arr), expected);\n    assert.deepStrictEqual(addon.renamedJsonSort(arr), expected);\n  });\n\n  it(\"json sort - task\", async () => {\n    const arr = [\"b\", \"c\", \"a\"];\n    const expected = [...arr].sort();\n    const p1 = addon.jsonSortTask(arr);\n    const p2 = addon.renamedJsonSortTask(arr);\n\n    assert.ok(p1 instanceof Promise);\n    assert.ok(p2 instanceof Promise);\n\n    assert.deepStrictEqual(await p1, expected);\n    assert.deepStrictEqual(await p2, expected);\n  });\n\n  it(\"can use context and handles\", () => {\n    const actual = addon.concatWithCxAndHandle(\"Hello,\", \" World!\");\n    const expected = \"Hello, World!\";\n\n    assert.strictEqual(actual, expected);\n  });\n\n  it(\"error conversion\", () => {\n    const msg = \"Oh, no!\";\n    const expected = new Error(msg);\n\n    assert.throws(() => addon.failWithThrow(msg), expected);\n  });\n\n  it(\"tasks are concurrent\", async () => {\n    const time = 500;\n    const sleep = (ms) => new Promise((r) => setTimeout(r, ms));\n    const start = process.hrtime.bigint();\n\n    await Promise.all([addon.sleepTask(time), sleep(time)]);\n\n    const end = process.hrtime.bigint();\n    const duration = end - start;\n\n    // If `addon.sleepTask` blocks the thread, the tasks will run sequentially\n    // and take a minimum of 2x `time`. Since they are run concurrently, we\n    // expect the time to be closer to 1x `time`.\n    const maxExpected = 2000000n * BigInt(time);\n\n    assert.ok(duration < maxExpected);\n  });\n\n  it(\"can use generic Cx in exported functions\", () => {\n    assert.strictEqual(addon.numberWithCx(42), 42);\n  });\n\n  it(\"i32 parameters\", () => {\n    assert.strictEqual(addon.addI32(5, 3), 8);\n    assert.strictEqual(addon.addI32(-10, 20), 10);\n    assert.strictEqual(addon.addI32(-5, -3), -8);\n    assert.strictEqual(addon.toI32(Infinity), 0);\n    assert.strictEqual(addon.toI32(-Infinity), 0);\n  });\n\n  it(\"u32 parameters\", () => {\n    assert.strictEqual(addon.addU32(5, 3), 8);\n    assert.strictEqual(addon.addU32(100, 200), 300);\n    assert.strictEqual(addon.addU32(0, 42), 42);\n    assert.strictEqual(addon.toU32(Infinity), 0);\n    assert.strictEqual(addon.toU32(-Infinity), 0);\n  });\n}\n\nfunction classes() {\n  it(\"can create and use exported class\", () => {\n    const ExportedPoint = addon.ExportedPoint;\n\n    // Test that the class was exported\n    assert.strictEqual(typeof ExportedPoint, \"function\");\n\n    // Test const properties\n    assert.strictEqual(ExportedPoint.ORIGIN_X, 0.0);\n    assert.strictEqual(ExportedPoint.ORIGIN_Y, 0.0);\n\n    // Test class instantiation and methods\n    const point1 = new ExportedPoint(3, 4);\n    const point2 = new ExportedPoint(0, 0);\n\n    assert.strictEqual(point1.x(), 3);\n    assert.strictEqual(point1.y(), 4);\n    assert.strictEqual(point2.x(), 0);\n    assert.strictEqual(point2.y(), 0);\n\n    // Test distance calculation\n    assert.strictEqual(point1.distance(point2), 5); // 3-4-5 triangle\n  });\n\n  it('can use custom export name - CASE 1: class, name = \"...\"', () => {\n    const RenamedClass = addon.RenamedClass;\n\n    // Test that the class was exported with custom name\n    assert.strictEqual(typeof RenamedClass, \"function\");\n\n    // Test that the original name is not exported\n    assert.strictEqual(addon.CustomNamedClass, undefined);\n\n    // Test class functionality\n    const instance = new RenamedClass(\"test value\");\n    assert.strictEqual(instance.getValue(), \"test value\");\n\n    // Test that the class name itself is RenamedClass\n    assert.strictEqual(RenamedClass.name, \"RenamedClass\");\n  });\n\n  it('CASE 2: class(name = \"...\") - parenthesized syntax', () => {\n    const ParenRenamedClass = addon.ParenRenamedClass;\n\n    // Test that the class was exported with the name from class(name = \"...\")\n    assert.strictEqual(typeof ParenRenamedClass, \"function\");\n\n    // Test that the original Rust name is not exported\n    assert.strictEqual(addon.Case2Class, undefined);\n\n    // Test class functionality\n    const instance = new ParenRenamedClass(\"hello\");\n    assert.strictEqual(instance.getMessage(), \"hello\");\n\n    // Test that the JavaScript class name is ParenRenamedClass\n    assert.strictEqual(ParenRenamedClass.name, \"ParenRenamedClass\");\n  });\n\n  it('CASE 3: class(name = \"Internal\"), name = \"External\" - separate names', () => {\n    const ExternalExportName = addon.ExternalExportName;\n\n    // Test that the class was exported with the outer name\n    assert.strictEqual(typeof ExternalExportName, \"function\");\n\n    // Test that the Rust name is not exported\n    assert.strictEqual(addon.Case3Class, undefined);\n\n    // Test that the inner class name is not directly exported\n    assert.strictEqual(addon.InternalClassName, undefined);\n\n    // Test class functionality\n    const instance = new ExternalExportName(42);\n    assert.strictEqual(instance.getData(), 42);\n\n    // Test that the JavaScript class name is the inner name (InternalClassName)\n    // but the export binding is the outer name (ExternalExportName)\n    assert.strictEqual(ExternalExportName.name, \"InternalClassName\");\n  });\n\n  it(\"can export async fn with JSON\", async () => {\n    const input = [1, 2, 3, 4, 5];\n    const result = await addon.exportAsyncJsonTest(input);\n\n    // Should multiply each element by 3\n    assert.deepStrictEqual(result, [3, 6, 9, 12, 15]);\n  });\n}\n"
  },
  {
    "path": "test/napi/lib/extract.js",
    "content": "const assert = require(\"assert\");\n\nconst addon = require(\"..\");\n\ndescribe(\"Extractors\", () => {\n  it(\"Single Argument\", () => {\n    assert.strictEqual(addon.extract_single_add_one(41), 42);\n  });\n\n  it(\"Kitchen Sink\", () => {\n    const symbol = Symbol(\"Test\");\n    const values = [\n      true,\n      42,\n      undefined,\n      \"hello\",\n      new Date(),\n      symbol,\n      new ArrayBuffer(100),\n      new Uint8Array(Buffer.from(\"Buffer\")),\n      Buffer.from(\"Uint8Array\"),\n    ];\n\n    // Pass `null` and `undefined` for `None`\n    assert.deepStrictEqual(addon.extract_values(...values, null), [\n      ...values,\n      undefined,\n      undefined,\n    ]);\n\n    // Pass values for optional\n    assert.deepStrictEqual(addon.extract_values(...values, 100, \"exists\"), [\n      ...values,\n      100,\n      \"exists\",\n    ]);\n  });\n\n  it(\"Buffers\", () => {\n    const test = (TypedArray) => {\n      const buf = new ArrayBuffer(24);\n      const view = new TypedArray(buf);\n\n      view[0] = 8;\n      view[1] = 16;\n      view[2] = 18;\n\n      assert.strictEqual(addon.extract_buffer_sum(view), 42);\n    };\n\n    test(Uint8Array);\n    test(Uint16Array);\n    test(Uint32Array);\n    test(Int8Array);\n    test(Int16Array);\n    test(Int32Array);\n    test(Float32Array);\n    test(Float64Array);\n  });\n\n  it(\"TypedArray\", () => {\n    assert.deepStrictEqual(\n      Buffer.from(addon.bufferConcat(Buffer.from(\"abc\"), Buffer.from(\"def\"))),\n      Buffer.from(\"abcdef\")\n    );\n\n    assert.deepStrictEqual(\n      Buffer.from(addon.stringToBuf(\"Hello, World!\")),\n      Buffer.from(\"Hello, World!\")\n    );\n  });\n\n  it(\"JSON\", () => {\n    assert.strictEqual(addon.extract_json_sum([1, 2, 3, 4]), 10);\n    assert.strictEqual(addon.extract_json_sum([8, 16, 18]), 42);\n    assert.strictEqual(addon.extractJsonOption(42), 42);\n    assert.strictEqual(addon.extractJsonOption(null), null);\n    assert.strictEqual(addon.extractJsonOption(), null);\n  });\n\n  it(\"Either\", () => {\n    assert.strictEqual(addon.extractEither(\"hello\"), \"String: hello\");\n    assert.strictEqual(addon.extractEither(42), \"Number: 42\");\n\n    assert.throws(\n      () => addon.extractEither({}),\n      (err) => {\n        assert.match(err.message, /expected either.*String.*f64/);\n        assert.match(err.left.message, /expected string/);\n        assert.match(err.right.message, /expected number/);\n\n        return true;\n      }\n    );\n  });\n\n  it(\"With\", async () => {\n    assert.strictEqual(await addon.sleepWithJs(1.5), 1.5);\n    assert.strictEqual(await addon.sleepWithJsSync(1.5), 1.5);\n    assert.strictEqual(await addon.sleepWith(1.5), 1.5);\n    assert.strictEqual(await addon.sleepWithSync(1.5), 1.5);\n  });\n\n  it(\"Array\", () => {\n    assert.deepStrictEqual(addon.extractArrayVec([1, 2, 3]), [1, 2, 3]);\n    assert.deepStrictEqual(addon.extractArrayDouble([1, 2, 3]), [2, 4, 6]);\n    assert.deepStrictEqual(\n      addon.extractArrayDedupe([\"a\", \"a\", \"b\", \"c\", \"c\"]).sort(),\n      [\"a\", \"b\", \"c\"]\n    );\n  });\n});\n"
  },
  {
    "path": "test/napi/lib/functions.js",
    "content": "var addon = require(\"..\");\nvar assert = require(\"chai\").assert;\n\nconst STRICT = function () {\n  \"use strict\";\n  return this;\n};\nconst SLOPPY = Function(\"return this;\");\n\nfunction isStrict(f) {\n  try {\n    f.caller;\n    return false;\n  } catch (e) {\n    return true;\n  }\n}\n\ndescribe(\"JsFunction\", function () {\n  it(\"return a JsFunction built in Rust\", function () {\n    assert.isFunction(addon.return_js_function());\n  });\n\n  it(\"return a JsFunction built in Rust that implements x => x + 1\", function () {\n    assert.equal(addon.return_js_function()(41), 42);\n  });\n\n  it(\"call a JsFunction built in JS that implements x => x + 1\", function () {\n    assert.equal(\n      addon.call_js_function(function (x) {\n        return x + 1;\n      }),\n      17\n    );\n  });\n\n  it(\"call a JsFunction built in JS with call_with\", function () {\n    assert.equal(\n      addon.call_js_function_idiomatically(function (x) {\n        return x + 1;\n      }),\n      17\n    );\n  });\n\n  it(\"call a JsFunction built in JS with .bind().apply()\", function () {\n    assert.equal(\n      addon.call_js_function_with_bind(function (a, b, c, d, e) {\n        return a * b * c * d * e;\n      }),\n      1 * 2 * 3 * 4 * 5\n    );\n  });\n\n  it(\"call a JsFunction build in JS with .bind and .args_with\", function () {\n    assert.equal(\n      addon.call_js_function_with_bind_and_args_with(function (a, b, c) {\n        return a + b + c;\n      }),\n      1 + 2 + 3\n    );\n  });\n\n  it(\"call a JsFunction build in JS with .bind and .args and With\", function () {\n    assert.equal(\n      addon.call_js_function_with_bind_and_args_and_with(function (a, b, c) {\n        return a + b + c;\n      }),\n      1 + 2 + 3\n    );\n  });\n\n  it(\"call parseInt with .bind().apply()\", function () {\n    assert.equal(addon.call_parse_int_with_bind(), 42);\n  });\n\n  it(\"call a JsFunction built in JS with .bind and .exec\", function () {\n    let local = 41;\n    addon.call_js_function_with_bind_and_exec(function (x) {\n      local += x;\n    });\n    assert.equal(local, 42);\n  });\n\n  it(\"call a JsFunction built in JS as a constructor with .bind and .construct\", function () {\n    function MyClass(number, string) {\n      this.number = number;\n      this.string = string;\n    }\n\n    const obj = addon.call_js_constructor_with_bind(MyClass);\n\n    assert.instanceOf(obj, MyClass);\n    assert.equal(obj.number, 42);\n    assert.equal(obj.string, \"hello\");\n  });\n\n  it(\"bind a JsFunction to an object\", function () {\n    const result = addon.bind_js_function_to_object(function () {\n      return this.prop;\n    });\n\n    assert.equal(result, 42);\n  });\n\n  it(\"bind a strict JsFunction to a number\", function () {\n    assert.isTrue(isStrict(STRICT));\n\n    // strict mode functions are allowed to have a primitive this binding\n    const result = addon.bind_js_function_to_number(STRICT);\n\n    assert.strictEqual(result, 42);\n  });\n\n  it(\"bind a sloppy JsFunction to a primitive\", function () {\n    assert.isFalse(isStrict(SLOPPY));\n\n    // legacy JS functions (aka \"sloppy mode\") replace primitive this bindings\n    // with object wrappers, so 42 will get wrapped as new Number(42)\n    const result = addon.bind_js_function_to_number(SLOPPY);\n\n    assert.instanceOf(result, Number);\n    assert.strictEqual(typeof result, \"object\");\n    assert.strictEqual(result.valueOf(), 42);\n  });\n\n  it(\"call a JsFunction with zero args\", function () {\n    assert.equal(addon.call_js_function_with_zero_args(), -Infinity);\n  });\n\n  it(\"call a JsFunction with one arg\", function () {\n    assert.equal(addon.call_js_function_with_one_arg(), 1.0);\n  });\n\n  it(\"call a JsFunction with two args\", function () {\n    assert.equal(addon.call_js_function_with_two_args(), 2.0);\n  });\n\n  it(\"call a JsFunction with three args\", function () {\n    assert.equal(addon.call_js_function_with_three_args(), 3.0);\n  });\n\n  it(\"call a JsFunction with four args\", function () {\n    assert.equal(addon.call_js_function_with_four_args(), 4.0);\n  });\n\n  it(\"call a JsFunction with a custom this\", function () {\n    assert.equal(\n      addon.call_js_function_with_custom_this(function () {\n        return this;\n      }).secret,\n      42\n    );\n  });\n\n  it(\"call a JsFunction with the default this\", function () {\n    addon.call_js_function_with_implicit_this(function () {\n      \"use strict\"; // ensure the undefined this isn't replaced with the global object\n      assert.strictEqual(this, undefined);\n    });\n  });\n\n  it(\"exec a JsFunction with the default this\", function () {\n    addon.exec_js_function_with_implicit_this(function () {\n      \"use strict\"; // ensure the undefined this isn't replaced with the global object\n      assert.strictEqual(this, undefined);\n    });\n  });\n\n  it(\"call a JsFunction with a heterogeneously typed tuple\", function () {\n    assert.deepEqual(addon.call_js_function_with_heterogeneous_tuple(), [\n      1,\n      \"hello\",\n      true,\n    ]);\n  });\n\n  it(\"new a JsFunction\", function () {\n    assert.equal(addon.construct_js_function(Date), 1970);\n  });\n\n  it(\"new a JsFunction with construct_with\", function () {\n    assert.equal(addon.construct_js_function_idiomatically(Date), 1970);\n  });\n\n  it(\"new a JsFunction with construct_with to create an array\", function () {\n    assert.deepEqual(\n      addon.construct_js_function_with_overloaded_result(),\n      [1, 2, 3]\n    );\n  });\n\n  it(\"got two parameters, a string and a number\", function () {\n    addon.check_string_and_number(\"string\", 42);\n  });\n\n  it(\"converts a Rust panic to a throw in a function\", function () {\n    assert.throws(\n      function () {\n        addon.panic();\n      },\n      Error,\n      /^internal error in Neon module: zomg$/\n    );\n  });\n\n  it(\"lets panic override a throw\", function () {\n    assert.throws(\n      function () {\n        addon.panic_after_throw();\n      },\n      Error,\n      /^internal error in Neon module: this should override the RangeError$/\n    );\n  });\n\n  it(\"computes the right number of arguments\", function () {\n    assert.equal(addon.num_arguments(), 0);\n    assert.equal(addon.num_arguments(\"a\"), 1);\n    assert.equal(addon.num_arguments(\"a\", \"b\"), 2);\n    assert.equal(addon.num_arguments(\"a\", \"b\", \"c\"), 3);\n    assert.equal(addon.num_arguments(\"a\", \"b\", \"c\", \"d\"), 4);\n  });\n\n  it(\"gets the right `this`-value\", function () {\n    var o = { iamobject: \"i am object\" };\n    assert.equal(addon.return_this.call(o), o);\n\n    var d = new Date();\n    assert.equal(addon.return_this.call(d), d);\n\n    var n = 19;\n    assert.notStrictEqual(addon.return_this.call(n), n);\n  });\n\n  it(\"can manipulate an object `this` binding\", function () {\n    var o = { modified: false };\n    addon.require_object_this.call(o);\n    assert.equal(o.modified, true);\n    // Doesn't throw because of implicit primitive wrapping:\n    addon.require_object_this.call(42);\n  });\n\n  it(\"implicitly gets global\", function () {\n    var global = new Function(\"return this\")();\n    assert.equal(addon.return_this.call(undefined), global);\n  });\n\n  it(\"exposes an argument via arguments_opt iff it is there\", function () {\n    assert.equal(addon.is_argument_zero_some(), false);\n    assert.equal(addon.is_argument_zero_some(\"a\"), true);\n    assert.equal(addon.is_argument_zero_some(\"a\", \"b\"), true);\n    assert.equal(addon.is_argument_zero_some.call(null), false);\n    assert.equal(addon.is_argument_zero_some.call(null, [\"a\"]), true);\n    assert.equal(addon.is_argument_zero_some.call(null, [\"a\", \"b\"]), true);\n  });\n\n  it(\"correctly casts an argument via cx.arguments\", function () {\n    assert.equal(addon.require_argument_zero_string(\"foobar\"), \"foobar\");\n    assert.throws(function () {\n      addon.require_argument_zero_string(new Date());\n    }, TypeError);\n    assert.throws(function () {\n      addon.require_argument_zero_string(17);\n    }, TypeError);\n  });\n\n  it(\"executes a scoped computation\", function () {\n    assert.equal(addon.execute_scoped(), 99);\n  });\n\n  it(\"computes a value in a scoped computation\", function () {\n    const o = {};\n\n    assert.equal(addon.compute_scoped(), 99);\n    assert.equal(addon.recompute_scoped(o), o);\n  });\n\n  it(\"catches an exception with cx.try_catch\", function () {\n    var error = new Error(\"Something bad happened\");\n    assert.equal(addon.throw_and_catch(error), error);\n    assert.equal(addon.throw_and_catch(42), 42);\n    assert.equal(addon.throw_and_catch(\"a string\"), \"a string\");\n    assert.equal(\n      addon.call_and_catch(() => {\n        throw \"shade\";\n      }),\n      \"shade\"\n    );\n    assert.equal(\n      addon.call_and_catch(() => {\n        throw (\n          addon.call_and_catch(() => {\n            throw (\n              addon.call_and_catch(() => {\n                throw \"once\";\n              }) + \" upon\"\n            );\n          }) + \" a\"\n        );\n      }) + \" time\",\n      \"once upon a time\"\n    );\n  });\n\n  it(\"gets a regular value with cx.try_catch\", function () {\n    assert.equal(\n      addon.call_and_catch(() => {\n        return 42;\n      }),\n      42\n    );\n  });\n\n  it(\"can return Rust type from cx.try_catch\", function () {\n    const n = Math.random();\n    assert.strictEqual(addon.get_number_or_default(n), n);\n    assert.strictEqual(addon.get_number_or_default(), 0);\n  });\n\n  it(\"always provides an object for the this-binding\", function () {\n    var meta1 = addon.assume_this_is_an_object.call(null);\n    assert.strictEqual(meta1.prototype, Object.getPrototypeOf(global));\n    assert.strictEqual(meta1.hasOwn, false);\n    assert.strictEqual(meta1.property, Object.getPrototypeOf(global).toString);\n\n    var meta2 = addon.assume_this_is_an_object.call(42);\n    assert.strictEqual(meta2.prototype, Number.prototype);\n    assert.strictEqual(meta2.hasOwn, false);\n    assert.strictEqual(meta2.property, Number.prototype.toString);\n\n    var meta3 = addon.assume_this_is_an_object.call(Object.create(null));\n    assert.strictEqual(meta3.prototype, null);\n    assert.strictEqual(meta3.hasOwn, false);\n    assert.strictEqual(meta3.property, undefined);\n\n    var meta4 = addon.assume_this_is_an_object.call({ toString: 17 });\n    assert.strictEqual(meta4.prototype, Object.prototype);\n    assert.strictEqual(meta4.hasOwn, true);\n    assert.strictEqual(meta4.property, 17);\n  });\n\n  it(\"distinguishes calls from constructs\", function () {\n    assert.equal(addon.is_construct.call({}).wasConstructed, false);\n    assert.equal(new addon.is_construct().wasConstructed, true);\n  });\n\n  it(\"should be able to call a function from a closure\", function () {\n    assert.strictEqual(addon.count_called() + 1, addon.count_called());\n  });\n\n  (global.gc ? it : it.skip)(\n    \"should drop function when going out of scope\",\n    function (cb) {\n      // Run from an `IIFE` to ensure that `f` is out of scope and eligible for garbage\n      // collection when `global.gc()` is executed.\n      (() => {\n        const msg = \"Hello, World!\";\n        const f = addon.caller_with_drop_callback(() => msg, cb);\n\n        assert.strictEqual(f(), msg);\n      })();\n\n      global.gc();\n    }\n  );\n});\n"
  },
  {
    "path": "test/napi/lib/futures.js",
    "content": "const assert = require(\"assert\");\n\nconst addon = require(\"..\");\n\nasync function assertRejects(f, ...args) {\n  try {\n    await f();\n  } catch (err) {\n    assert.throws(() => {\n      throw err;\n    }, ...args);\n\n    return;\n  }\n\n  assert.throws(() => {}, ...args);\n}\n\ndescribe(\"Futures\", () => {\n  describe(\"Channel\", () => {\n    it(\"should be able to await channel result\", async () => {\n      const sum = await addon.lazy_async_add(\n        () => 1,\n        () => 2\n      );\n\n      assert.strictEqual(sum, 3);\n    });\n\n    it(\"exceptions should be handled\", async () => {\n      await assertRejects(async () => {\n        await addon.lazy_async_add(\n          () => 1,\n          () => {\n            throw new Error(\"Failed to get Y\");\n          }\n        );\n      }, /exception/i);\n    });\n  });\n\n  describe(\"JsFuture\", () => {\n    it(\"should be able to convert a promise to a future\", async () => {\n      const nums = new Float64Array([1, 2, 3, 4]);\n      const sum = await addon.lazy_async_sum(async () => nums);\n\n      assert.strictEqual(sum, 10);\n    });\n\n    it(\"should catch promise rejection\", async () => {\n      await assertRejects(async () => {\n        await addon.lazy_async_sum(async () => {\n          throw new Error(\"Oh, no!\");\n        });\n      }, /exception/i);\n    });\n  });\n\n  describe(\"Exported Async Functions\", () => {\n    it(\"should be able to call `async fn`\", async () => {\n      assert.strictEqual(await addon.asyncFnAdd(1, 2), 3);\n    });\n\n    it(\"should be able to call fn with async block\", async () => {\n      assert.strictEqual(await addon.asyncAdd(1, 2), 3);\n    });\n\n    it(\"should be able to call fallible `async fn`\", async () => {\n      assert.strictEqual(await addon.asyncFnDiv(10, 2), 5);\n\n      await assertRejects(() => addon.asyncFnDiv(10, 0), /Divide by zero/);\n    });\n\n    it(\"should be able to call fallible fn with async block\", async () => {\n      assert.strictEqual(await addon.asyncDiv(10, 2), 5);\n\n      await assertRejects(() => addon.asyncDiv(10, 0), /Divide by zero/);\n    });\n\n    it(\"should be able to code on the event loop before and after async\", async () => {\n      let startCalled = false;\n      let endCalled = false;\n      const eventHandler = (event) => {\n        switch (event) {\n          case \"start\":\n            startCalled = true;\n            break;\n          case \"end\":\n            endCalled = true;\n            break;\n        }\n      };\n\n      process.on(\"async_with_events\", eventHandler);\n\n      try {\n        let res = await addon.asyncWithEvents([\n          [1, 2],\n          [3, 4],\n          [5, 6],\n        ]);\n\n        assert.deepStrictEqual([...res], [2, 12, 30]);\n        assert.ok(startCalled, \"Did not emit start event\");\n        assert.ok(endCalled, \"Did not emit end event\");\n      } finally {\n        process.off(\"async_with_events\", eventHandler);\n      }\n    });\n  });\n});\n"
  },
  {
    "path": "test/napi/lib/hello.js",
    "content": "var addon = require(\"..\");\nvar assert = require(\"chai\").assert;\n\ndescribe(\"hello\", function () {\n  it(\"should export a greeting\", function () {\n    assert.strictEqual(addon.greeting, \"Hello, World!\");\n    assert.strictEqual(addon.greeting, addon.greetingCopy);\n  });\n\n  it(\"should export global singletons for JS primitives\", function () {\n    assert.strictEqual(addon.undefined, undefined);\n    assert.ok(addon.hasOwnProperty(\"undefined\"));\n    assert.strictEqual(addon.null, null);\n    assert.strictEqual(addon.true, true);\n    assert.strictEqual(addon.false, false);\n  });\n\n  it(\"should export numbers\", function () {\n    assert.strictEqual(addon.one, 1);\n    assert.strictEqual(addon.two, 2.1);\n  });\n\n  it(\"should be able to create JS objects in rust\", function () {\n    assert.deepEqual(addon.rustCreated, {\n      0: 1,\n      a: 1,\n      whatever: true,\n    });\n  });\n\n  it(\"should export a Rust function\", function () {\n    assert.strictEqual(addon.add1(2), 3.0);\n  });\n});\n"
  },
  {
    "path": "test/napi/lib/numbers.js",
    "content": "var addon = require(\"..\");\nvar assert = require(\"chai\").assert;\n\ndescribe(\"JsNumber\", function () {\n  it(\"return a JsNumber built in Rust\", function () {\n    assert.equal(addon.return_js_number(), 9000);\n  });\n\n  it(\"return a JsNumber for a large int built in Rust\", function () {\n    assert.equal(addon.return_large_js_number(), 4294967296);\n  });\n\n  it(\"return a negative JsNumber int built in Rust\", function () {\n    assert.equal(addon.return_negative_js_number(), -9000);\n  });\n\n  it(\"return a JsNumber float built in Rust\", function () {\n    assert.equal(addon.return_float_js_number(), 1.4747);\n  });\n\n  it(\"return a negative JsNumber float built in Rust\", function () {\n    assert.equal(addon.return_negative_float_js_number(), -1.4747);\n  });\n\n  describe(\"round trips\", function () {\n    it(\"accept and return a number\", function () {\n      assert.equal(addon.accept_and_return_js_number(1), 1);\n    });\n\n    it(\"accept and return a large number as a JsNumber\", function () {\n      assert.equal(\n        addon.accept_and_return_large_js_number(9007199254740991),\n        9007199254740991\n      );\n    });\n\n    it(\"will be safe below Number.MAX_SAFE_INTEGER\", function () {\n      assert.notEqual(\n        addon.accept_and_return_large_js_number(9007199254740990),\n        9007199254740991\n      );\n    });\n\n    it(\"will not be save above Number.MAX_SAFE_INTEGER\", function () {\n      assert.equal(\n        addon.accept_and_return_large_js_number(9007199254740993),\n        9007199254740992\n      );\n    });\n\n    it(\"accept and return a float as a JsNumber\", function () {\n      assert.equal(addon.accept_and_return_float_js_number(0.23423), 0.23423);\n    });\n\n    it(\"accept and return a negative number as a JsNumber\", function () {\n      assert.equal(addon.accept_and_return_negative_js_number(-55), -55);\n    });\n  });\n});\n"
  },
  {
    "path": "test/napi/lib/objects.js",
    "content": "var addon = require(\"..\");\nvar assert = require(\"chai\").assert;\n\ndescribe(\"JsObject\", function () {\n  it(\"return the v8::Global object\", function () {\n    assert(global === addon.return_js_global_object());\n  });\n\n  it(\"return a JsObject built in Rust\", function () {\n    assert.deepEqual({}, addon.return_js_object());\n  });\n\n  it(\"return a JsObject with a number key value pair\", function () {\n    assert.deepEqual({ number: 9000 }, addon.return_js_object_with_number());\n  });\n\n  it(\"return a JsObject with an string key value pair\", function () {\n    assert.deepEqual(\n      { string: \"hello node\" },\n      addon.return_js_object_with_string()\n    );\n  });\n\n  it(\"return a JsObject with mixed content key value pairs\", function () {\n    assert.deepEqual(\n      { number: 9000, string: \"hello node\" },\n      addon.return_js_object_with_mixed_content()\n    );\n  });\n\n  it(\"freeze a JsObject\", function () {\n    const originalValue = 1;\n    const obj = { x: originalValue };\n\n    assert.doesNotThrow(function () {\n      addon.freeze_js_object(obj);\n    }, \"freeze_js_object should not throw\");\n\n    obj.x = 2;\n    assert.equal(\n      obj.x,\n      originalValue,\n      \"freeze_js_object should not allow mutation\"\n    );\n\n    const shouldNotFreeze = new Uint32Array(8);\n    assert.throws(function () {\n      addon.freeze_js_object(shouldNotFreeze);\n    });\n  });\n\n  it(\"seal a JsObject\", function () {\n    const obj = { x: 1 };\n\n    assert.doesNotThrow(function () {\n      addon.seal_js_object(obj);\n    }, \"seal_js_object should not throw\");\n\n    delete obj.x;\n    assert.isOk(obj.x, \"seal_js_object should not allow property deletion\");\n\n    const shouldNotSeal = new Uint32Array(8);\n    assert.throws(function () {\n      addon.freeze_js_object(shouldNotSeal);\n    });\n  });\n\n  it(\"returns only own properties from get_own_property_names\", function () {\n    var superObject = {\n      a: 1,\n    };\n\n    var childObject = Object.create(superObject);\n    childObject.b = 2;\n\n    assert.deepEqual(\n      addon.get_own_property_names(childObject),\n      Object.getOwnPropertyNames(childObject)\n    );\n  });\n\n  it(\"does not return Symbols from get_own_property_names\", function () {\n    var object = {};\n    object[\"this should be a thing\"] = 0;\n    object[Symbol(\"this should not be a thing\")] = 1;\n\n    assert.deepEqual(\n      addon.get_own_property_names(object),\n      Object.getOwnPropertyNames(object)\n    );\n    assert.equal(addon.get_own_property_names(object).length, 1);\n  });\n\n  it(\"data borrowed on the heap can be held longer than the handle\", function () {\n    const msg = \"Hello, World!\";\n    const buf = Buffer.from(msg);\n\n    assert.strictEqual(addon.byte_length(msg), buf.length);\n    assert.strictEqual(addon.byte_length(buf), buf.length);\n  });\n\n  it(\"calling Object::call_with() properly calls object methods\", function () {\n    const obj = {\n      value: 42,\n      nullary() {\n        return this.value;\n      },\n      unary(x) {\n        return this.value + x;\n      },\n    };\n\n    assert.strictEqual(addon.call_nullary_method(obj), 42);\n    assert.strictEqual(addon.call_unary_method(obj, 17), 59);\n  });\n\n  it(\"calling Object::call_with() with a symbol method name works\", function () {\n    const sym = Symbol.for(\"mySymbol\");\n    const obj = {\n      [sym]() {\n        return \"hello\";\n      },\n    };\n\n    assert.strictEqual(addon.call_symbol_method(obj, sym), \"hello\");\n  });\n\n  it(\"extracts an object property with .prop()\", function () {\n    const obj = { number: 3.141593 };\n\n    assert.strictEqual(addon.get_property_with_prop(obj), 3.141593);\n  });\n\n  it(\"sets an object property with .prop()\", function () {\n    const obj = { number: 3.141593 };\n\n    addon.set_property_with_prop(obj);\n\n    assert.strictEqual(obj.number, 42);\n  });\n\n  it(\"calls a method with .prop()\", function () {\n    const obj = {\n      name: \"Diana Prince\",\n      setName(name) {\n        this.name = name;\n      },\n      toString() {\n        return `[object ${this.name}]`;\n      },\n    };\n\n    assert.strictEqual(obj.toString(), \"[object Diana Prince]\");\n    assert.strictEqual(\n      addon.call_methods_with_prop(obj),\n      \"[object Wonder Woman]\"\n    );\n    assert.strictEqual(obj.toString(), \"[object Wonder Woman]\");\n  });\n\n  it(\"throws a TypeError when calling a non-method with .prop()\", function () {\n    const obj = {\n      number: 42,\n    };\n\n    assert.throws(() => {\n      addon.call_non_method_with_prop(obj);\n    }, /not a function/);\n  });\n});\n"
  },
  {
    "path": "test/napi/lib/strings.js",
    "content": "var addon = require(\"..\");\nvar { assert, expect } = require(\"chai\");\n\ndescribe(\"JsString\", function () {\n  it(\"should return a JsString built in Rust\", function () {\n    assert.equal(addon.return_js_string(), \"hello node\");\n  });\n  it(\"should return a raw valid UTF-16 string built in Rust\", function () {\n    const decoder = new TextDecoder(\"utf-16\");\n    assert.equal(decoder.decode(addon.return_js_string_utf16()), \"hello 🥹\");\n  });\n  describe(\"encoding\", function () {\n    it(\"should return the UTF-8 string length\", function () {\n      assert.equal(addon.return_length_utf8(\"hello 🥹\"), 10);\n    });\n    it(\"should return the UTF-16 string length\", function () {\n      assert.equal(addon.return_length_utf16(\"hello 🥹\"), 8);\n    });\n  });\n  describe(\"run_as_script\", function () {\n    it(\"should return the evaluated value\", function () {\n      assert.equal(addon.run_string_as_script(\"6 * 7\"), 42);\n    });\n    it(\"should throw if the script throws\", function () {\n      expect(() =>\n        addon.run_string_as_script('throw new Error(\"b1-66er\")')\n      ).to.throw(\"b1-66er\");\n    });\n    it(\"should throw SyntaxError if the string has invalid syntax\", function () {\n      expect(() => addon.run_string_as_script(\"invalid js code\")).to.throw(\n        SyntaxError\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "test/napi/lib/threads.js",
    "content": "const addon = require(\"..\");\nconst assert = require(\"chai\").assert;\n\n(function () {\n  // These tests require GC exposed to shutdown properly; skip if it is not\n  return typeof global.gc === \"function\" ? describe : describe.skip;\n})()(\"sync\", function () {\n  let unhandledRejectionListeners = [];\n\n  beforeEach(() => {\n    unhandledRejectionListeners = process.listeners(\"unhandledRejection\");\n  });\n\n  afterEach(() => {\n    // Restore listeners\n    process.removeAllListeners(\"unhandledRejection\");\n    unhandledRejectionListeners.forEach((listener) =>\n      process.on(\"unhandledRejection\", listener)\n    );\n\n    // Force garbage collection to shutdown `Channel`\n    global.gc();\n  });\n\n  it(\"can create and deref a root\", function () {\n    const expected = {};\n    const result = addon.useless_root(expected);\n\n    assert.strictEqual(expected, result);\n  });\n\n  it(\"should be able to callback from another thread\", function (cb) {\n    addon.thread_callback(cb);\n  });\n\n  it(\"should be able to callback from multiple threads\", function (cb) {\n    const n = 4;\n    const set = new Set([...new Array(n)].map((_, i) => i));\n\n    addon.multi_threaded_callback(n, function (x) {\n      if (!set.delete(x)) {\n        cb(new Error(`Unexpected callback value: ${x}`));\n      }\n\n      if (set.size === 0) {\n        cb();\n      }\n    });\n  });\n\n  it(\"should be able to use an async greeter\", function (cb) {\n    const greeter = addon.greeter_new(\"Hello, World!\", function (greeting) {\n      if (greeting === \"Hello, World!\") {\n        cb();\n      } else {\n        new Error(\"Greeting did not match\");\n      }\n    });\n\n    addon.greeter_greet(greeter);\n  });\n\n  it(\"should run callback on drop\", function (cb) {\n    // IIFE to allow GC\n    (function () {\n      addon.greeter_new(\n        \"Hello, World!\",\n        function () {},\n        function () {\n          // No assert needed; test will timeout\n          cb();\n        }\n      );\n    })();\n\n    global.gc();\n  });\n\n  it(\"should be able to unref channel\", function () {\n    // If the Channel is not unreferenced, the test runner will not cleanly exit\n    addon.leak_channel();\n  });\n\n  it(\"should drop leaked Root from the global queue\", function (cb) {\n    addon.drop_global_queue(cb);\n\n    // Asynchronously GC to give the task queue a chance to execute\n    setTimeout(() => global.gc(), 10);\n  });\n\n  it(\"should be able to join on the result of a channel\", function (cb) {\n    // `msg` is closed over by multiple functions. A function that returns the\n    // current value is passed to the Neon function `addon.channel_join`. Additionally,\n    // the value is modified after `10ms` in a timeout.\n    let msg = \"Uninitialized\";\n\n    // The `addon.channel_join` function will wait 100ms before fetching the current\n    // value of `msg` using the first closure. The second closure is called\n    // after fetching and processing the message. We expect the message to already\n    // have been changed.\n    addon.channel_join(\n      () => msg,\n      (res) => {\n        assert.strictEqual(res, \"Received: Hello, World!\");\n        cb();\n      }\n    );\n\n    // Change the value of `msg` after 10ms. This should happen before `addon.channel_join`\n    // fetches it.\n    setTimeout(() => {\n      msg = \"Hello, World!\";\n    }, 10);\n  });\n\n  it(\"should be able to sum numbers on the libuv pool\", async function () {\n    const nums = new Float64Array(\n      [...new Array(10000)].map(() => Math.random())\n    );\n    const expected = nums.reduce((y, x) => y + x, 0);\n    const actual = await addon.sum(nums);\n\n    assert.strictEqual(expected, actual);\n  });\n\n  it(\"should be able to resolve a promise manually\", async function () {\n    const nums = new Float64Array(\n      [...new Array(10000)].map(() => Math.random())\n    );\n    const expected = nums.reduce((y, x) => y + x, 0);\n    const actual = await addon.sum_manual_promise(nums);\n\n    assert.strictEqual(expected, actual);\n  });\n\n  it(\"should be able to resolve a promise from a rust thread\", async function () {\n    const nums = new Float64Array(\n      [...new Array(10000)].map(() => Math.random())\n    );\n    const expected = nums.reduce((y, x) => y + x, 0);\n    const actual = await addon.sum_rust_thread(nums);\n\n    assert.strictEqual(expected, actual);\n  });\n\n  it(\"should reject promise if leaked\", async function () {\n    try {\n      await addon.leak_promise();\n    } catch (err) {\n      assert.instanceOf(err, Error);\n      assert.ok(/Deferred/.test(err));\n    }\n  });\n\n  it(\"should throw an unhandledRejection when panicking in a channel\", function (cb) {\n    const msg = \"Hello, Panic!\";\n\n    process.removeAllListeners(\"unhandledRejection\");\n    process.once(\"unhandledRejection\", (err) => {\n      try {\n        assert.instanceOf(err, Error);\n        assert.ok(\n          /panic/i.test(err.message),\n          \"Expected error message to indicate a panic\"\n        );\n        assert.ok(\n          !/exception/i.test(err.message),\n          \"Expected error message not to indicate an exception\"\n        );\n        assert.strictEqual(err.cause, undefined);\n        assert.instanceOf(err.panic, Error);\n        assert.strictEqual(err.panic.message, msg);\n        assert.strictEqual(err.panic.cause, undefined);\n\n        cb();\n      } catch (err) {\n        cb(err);\n      }\n    });\n\n    addon.channel_panic(msg);\n  });\n\n  it(\"should throw an unhandledRejection when throwing in a channel\", function (cb) {\n    const msg = \"Hello, Throw!\";\n\n    process.removeAllListeners(\"unhandledRejection\");\n    process.once(\"unhandledRejection\", (err) => {\n      try {\n        assert.instanceOf(err, Error);\n        assert.ok(\n          !/panic/i.test(err.message),\n          \"Expected error message not to indicate a panic\"\n        );\n        assert.ok(\n          /exception/i.test(err.message),\n          \"Expected error message to indicate an exception\"\n        );\n        assert.strictEqual(err.panic, undefined);\n        assert.instanceOf(err.cause, Error);\n        assert.strictEqual(err.cause.message, msg);\n\n        cb();\n      } catch (err) {\n        cb(err);\n      }\n    });\n\n    addon.channel_throw(msg);\n  });\n\n  it(\"should throw an unhandledRejection when panicking and throwing in a channel\", function (cb) {\n    const msg = \"Oh, no!\";\n\n    process.removeAllListeners(\"unhandledRejection\");\n    process.once(\"unhandledRejection\", (err) => {\n      try {\n        assert.instanceOf(err, Error);\n        assert.ok(\n          /panic/i.test(err.message),\n          \"Expected error message to indicate a panic\"\n        );\n        assert.ok(\n          /exception/i.test(err.message),\n          \"Expected error message to indicate an exception\"\n        );\n        assert.instanceOf(err.panic, Error);\n        assert.instanceOf(err.cause, Error);\n        assert.strictEqual(err.cause.message, msg);\n\n        cb();\n      } catch (err) {\n        cb(err);\n      }\n    });\n\n    addon.channel_panic_throw(msg);\n  });\n\n  it(\"should be able to downcast a panic in a channel\", function (cb) {\n    const msg = \"Hello, Secret Panic!\";\n\n    process.removeAllListeners(\"unhandledRejection\");\n    process.once(\"unhandledRejection\", (err) => {\n      try {\n        assert.instanceOf(err.panic, Error);\n        assert.ok(\n          /panic/i.test(err.message),\n          \"Expected error message to indicate a panic\"\n        );\n        assert.strictEqual(addon.custom_panic_downcast(err.panic.cause), msg);\n\n        cb();\n      } catch (err) {\n        cb(err);\n      }\n    });\n\n    addon.channel_custom_panic(msg);\n  });\n\n  it(\"should throw an unhandledRejection when panicking in a task\", function (cb) {\n    const msg = \"Hello, Panic!\";\n\n    process.removeAllListeners(\"unhandledRejection\");\n    process.once(\"unhandledRejection\", (err) => {\n      try {\n        assert.instanceOf(err, Error);\n        assert.ok(\n          /panic/i.test(err.message),\n          \"Expected error message to indicate a panic\"\n        );\n        assert.ok(\n          !/exception/i.test(err.message),\n          \"Expected error message not to indicate an exception\"\n        );\n        assert.strictEqual(err.cause, undefined);\n        assert.instanceOf(err.panic, Error);\n        assert.strictEqual(err.panic.message, msg);\n        assert.strictEqual(err.panic.cause, undefined);\n\n        cb();\n      } catch (err) {\n        cb(err);\n      }\n    });\n\n    addon.task_panic_execute(msg);\n  });\n\n  it(\"should throw an unhandledRejection when panicking in a task complete\", function (cb) {\n    const msg = \"Hello, Panic!\";\n\n    process.removeAllListeners(\"unhandledRejection\");\n    process.once(\"unhandledRejection\", (err) => {\n      try {\n        assert.instanceOf(err, Error);\n        assert.ok(\n          /panic/i.test(err.message),\n          \"Expected error message to indicate a panic\"\n        );\n        assert.ok(\n          !/exception/i.test(err.message),\n          \"Expected error message not to indicate an exception\"\n        );\n        assert.strictEqual(err.cause, undefined);\n        assert.instanceOf(err.panic, Error);\n        assert.strictEqual(err.panic.message, msg);\n        assert.strictEqual(err.panic.cause, undefined);\n\n        cb();\n      } catch (err) {\n        cb(err);\n      }\n    });\n\n    addon.task_panic_complete(msg);\n  });\n\n  it(\"should throw an unhandledRejection when throwing in a task complete\", function (cb) {\n    const msg = \"Hello, Throw!\";\n\n    process.removeAllListeners(\"unhandledRejection\");\n    process.once(\"unhandledRejection\", (err) => {\n      try {\n        assert.instanceOf(err, Error);\n        assert.ok(\n          !/panic/i.test(err.message),\n          \"Expected error message not to indicate a panic\"\n        );\n        assert.ok(\n          /exception/i.test(err.message),\n          \"Expected error message to indicate an exception\"\n        );\n        assert.strictEqual(err.panic, undefined);\n        assert.instanceOf(err.cause, Error);\n        assert.strictEqual(err.cause.message, msg);\n\n        cb();\n      } catch (err) {\n        cb(err);\n      }\n    });\n\n    addon.task_throw(msg);\n  });\n\n  it(\"should throw an unhandledRejection when panicking and throwing in a task complete\", function (cb) {\n    const msg = \"Oh, no!\";\n\n    process.removeAllListeners(\"unhandledRejection\");\n    process.once(\"unhandledRejection\", (err) => {\n      try {\n        assert.instanceOf(err, Error);\n        assert.ok(\n          /panic/i.test(err.message),\n          \"Expected error message to indicate a panic\"\n        );\n        assert.ok(\n          /exception/i.test(err.message),\n          \"Expected error message to indicate an exception\"\n        );\n        assert.instanceOf(err.panic, Error);\n        assert.instanceOf(err.cause, Error);\n        assert.strictEqual(err.cause.message, msg);\n\n        cb();\n      } catch (err) {\n        cb(err);\n      }\n    });\n\n    addon.task_panic_throw(msg);\n  });\n\n  it(\"should be able to downcast a panic in a task\", function (cb) {\n    const msg = \"Hello, Secret Panic!\";\n\n    process.removeAllListeners(\"unhandledRejection\");\n    process.once(\"unhandledRejection\", (err) => {\n      try {\n        assert.instanceOf(err.panic, Error);\n        assert.ok(\n          /panic/i.test(err.message),\n          \"Expected error message to indicate a panic\"\n        );\n        assert.strictEqual(addon.custom_panic_downcast(err.panic.cause), msg);\n\n        cb();\n      } catch (err) {\n        cb(err);\n      }\n    });\n\n    addon.task_custom_panic(msg);\n  });\n\n  it(\"should be able to reject a promise in a task\", async function () {\n    const msg = \"Rejected!\";\n\n    try {\n      await addon.task_reject_promise(msg);\n\n      throw new Error(\"Did not throw\");\n    } catch (err) {\n      assert.instanceOf(err, Error);\n      assert.strictEqual(err.message, msg);\n    }\n  });\n\n  it(\"panic in a task should reject the promise\", async function () {\n    const msg = \"Rejected!\";\n\n    try {\n      await addon.task_panic_execute_promise(msg);\n\n      throw new Error(\"Did not throw\");\n    } catch (err) {\n      assert.instanceOf(err, Error);\n      assert.instanceOf(err.panic, Error);\n      assert.strictEqual(err.panic.message, msg);\n    }\n  });\n\n  it(\"panic in a task should reject the promise\", async function () {\n    const msg = \"Rejected!\";\n\n    try {\n      await addon.task_panic_complete_promise(msg);\n\n      throw new Error(\"Did not throw\");\n    } catch (err) {\n      assert.instanceOf(err, Error);\n      assert.instanceOf(err.panic, Error);\n      assert.strictEqual(err.panic.message, msg);\n    }\n  });\n\n  it(\"panic and exception in a task should reject the promise\", async function () {\n    const msg = \"Rejected!\";\n\n    try {\n      await addon.task_panic_throw_promise(msg);\n\n      throw new Error(\"Did not throw\");\n    } catch (err) {\n      assert.instanceOf(err, Error);\n      assert.ok(\n        /panic/i.test(err.message),\n        \"Expected error message to indicate a panic\"\n      );\n      assert.ok(\n        /exception/i.test(err.message),\n        \"Expected error message to indicate an exception\"\n      );\n      assert.instanceOf(err.panic, Error);\n      assert.instanceOf(err.cause, Error);\n      assert.strictEqual(err.cause.message, msg);\n    }\n  });\n\n  it(\"should be able to reject a promise settling with a channel\", async function () {\n    const msg = \"Rejected!\";\n\n    try {\n      await addon.deferred_settle_with_throw(msg);\n\n      throw new Error(\"Did not throw\");\n    } catch (err) {\n      assert.instanceOf(err, Error);\n      assert.strictEqual(err.message, msg);\n    }\n  });\n\n  it(\"should reject a promise when panicking while settling with a channel\", async function () {\n    const msg = \"Rejected!\";\n\n    try {\n      await addon.deferred_settle_with_throw(msg);\n\n      throw new Error(\"Did not throw\");\n    } catch (err) {\n      assert.instanceOf(err, Error);\n      assert.strictEqual(err.message, msg);\n    }\n  });\n\n  it(\"should reject a promise when panicking and throwing while settling with a channel\", async function () {\n    const msg = \"Rejected!\";\n\n    try {\n      await addon.deferred_settle_with_panic(msg);\n\n      throw new Error(\"Did not throw\");\n    } catch (err) {\n      assert.instanceOf(err, Error);\n      assert.ok(\n        /panic/i.test(err.message),\n        \"Expected error message to indicate a panic\"\n      );\n      assert.instanceOf(err.panic, Error);\n    }\n  });\n\n  it(\"should be able to settle a promise with a Rust value\", async function () {\n    assert.strictEqual(await addon.settleHelloWorld(), \"Hello, World!\");\n  });\n});\n"
  },
  {
    "path": "test/napi/lib/typedarrays.js",
    "content": "var addon = require(\"..\");\nvar assert = require(\"chai\").assert;\n\nconst { Worker, isMainThread, parentPort } = require(\"worker_threads\");\n\nif (!isMainThread) {\n  parentPort.on(\"message\", (message) => {\n    // transfer it back\n    parentPort.postMessage(message, [message]);\n  });\n\n  return;\n}\n\n// A background thread we can transfer buffers to as a way to force\n// them to be detached (see the `detach` function).\nconst DETACH_WORKER = new Worker(__filename);\n\n// Allow the test harness to spin down the background thread and exit\n// when the main thread completes.\nDETACH_WORKER.unref();\n\nfunction detach(buffer) {\n  if (!(buffer instanceof ArrayBuffer)) {\n    throw new TypeError();\n  }\n\n  DETACH_WORKER.postMessage(buffer, [buffer]);\n\n  return new Promise((resolve) => DETACH_WORKER.once(\"message\", resolve));\n}\n\ndescribe(\"Typed arrays\", function () {\n  it(\"correctly reads a TypedArray using the borrow API\", function () {\n    var b = new ArrayBuffer(32);\n    var a = new Int32Array(b, 4, 4);\n    a[0] = 49;\n    a[1] = 1350;\n    a[2] = 11;\n    a[3] = 237;\n    assert.equal(addon.read_typed_array_with_borrow(a, 0), 49);\n    assert.equal(addon.read_typed_array_with_borrow(a, 1), 1350);\n    assert.equal(addon.read_typed_array_with_borrow(a, 2), 11);\n    assert.equal(addon.read_typed_array_with_borrow(a, 3), 237);\n  });\n\n  it(\"correctly writes to a TypedArray using the borrow_mut API\", function () {\n    var b = new ArrayBuffer(32);\n    var a = new Int32Array(b, 4, 4);\n    addon.write_typed_array_with_borrow_mut(a, 0, 43);\n    assert.equal(a[0], 43);\n    addon.write_typed_array_with_borrow_mut(a, 1, 1000);\n    assert.equal(a[1], 1000);\n    addon.write_typed_array_with_borrow_mut(a, 2, 22);\n    assert.equal(a[2], 22);\n    addon.write_typed_array_with_borrow_mut(a, 3, 243);\n    assert.equal(a[3], 243);\n  });\n\n  it(\"correctly reads a Buffer as a typed array\", function () {\n    var a = Buffer.from([49, 135, 11, 237]);\n    assert.equal(addon.read_u8_typed_array(a, 0), 49);\n    assert.equal(addon.read_u8_typed_array(a, 1), 135);\n    assert.equal(addon.read_u8_typed_array(a, 2), 11);\n    assert.equal(addon.read_u8_typed_array(a, 3), 237);\n  });\n\n  it(\"copies the contents of one typed array to another\", function () {\n    const a = new Uint32Array([1, 2, 3, 4]);\n    const b = new Uint32Array(a.length);\n\n    addon.copy_typed_array(a, b);\n\n    assert.deepEqual([...a], [...b]);\n  });\n\n  it(\"cannot borrow overlapping buffers\", function () {\n    const buf = new ArrayBuffer(20);\n    const arr = new Uint32Array(buf);\n    const a = new Uint32Array(buf, 4, 2);\n    const b = new Uint32Array(buf, 8, 2);\n\n    assert.throws(() => addon.copy_typed_array(a, b));\n  });\n\n  it(\"gets a 16-byte, zeroed ArrayBuffer\", function () {\n    var b = addon.return_array_buffer();\n    assert.equal(b.byteLength, 16);\n    assert.equal(new Uint32Array(b)[0], 0);\n    assert.equal(new Uint32Array(b)[1], 0);\n    assert.equal(new Uint32Array(b)[2], 0);\n    assert.equal(new Uint32Array(b)[3], 0);\n  });\n\n  it(\"correctly reads an ArrayBuffer using the lock API\", function () {\n    var b = new ArrayBuffer(16);\n    var a = new Uint32Array(b);\n    a[0] = 47;\n    a[1] = 133;\n    a[2] = 9;\n    a[3] = 88888888;\n    assert.equal(addon.read_array_buffer_with_lock(a, 0), 47);\n    assert.equal(addon.read_array_buffer_with_lock(a, 1), 133);\n    assert.equal(addon.read_array_buffer_with_lock(a, 2), 9);\n    assert.equal(addon.read_array_buffer_with_lock(a, 3), 88888888);\n  });\n\n  it(\"correctly reads an ArrayBuffer using the borrow API\", function () {\n    var b = new ArrayBuffer(4);\n    var a = new Uint8Array(b);\n    a[0] = 49;\n    a[1] = 135;\n    a[2] = 11;\n    a[3] = 237;\n    assert.equal(addon.read_array_buffer_with_borrow(b, 0), 49);\n    assert.equal(addon.read_array_buffer_with_borrow(b, 1), 135);\n    assert.equal(addon.read_array_buffer_with_borrow(b, 2), 11);\n    assert.equal(addon.read_array_buffer_with_borrow(b, 3), 237);\n  });\n\n  it(\"correctly writes to an ArrayBuffer using the lock API\", function () {\n    var b = new ArrayBuffer(16);\n    addon.write_array_buffer_with_lock(b, 0, 3);\n    assert.equal(new Uint8Array(b)[0], 3);\n    addon.write_array_buffer_with_lock(b, 1, 42);\n    assert.equal(new Uint8Array(b)[1], 42);\n    addon.write_array_buffer_with_lock(b, 2, 127);\n    assert.equal(new Uint8Array(b)[2], 127);\n    addon.write_array_buffer_with_lock(b, 3, 255);\n    assert.equal(new Uint8Array(b)[3], 255);\n  });\n\n  it(\"correctly writes to an ArrayBuffer using the borrow_mut API\", function () {\n    var b = new ArrayBuffer(4);\n    addon.write_array_buffer_with_borrow_mut(b, 0, 43);\n    assert.equal(new Uint8Array(b)[0], 43);\n    addon.write_array_buffer_with_borrow_mut(b, 1, 100);\n    assert.equal(new Uint8Array(b)[1], 100);\n    addon.write_array_buffer_with_borrow_mut(b, 2, 22);\n    assert.equal(new Uint8Array(b)[2], 22);\n    addon.write_array_buffer_with_borrow_mut(b, 3, 243);\n    assert.equal(new Uint8Array(b)[3], 243);\n  });\n\n  it(\"gets a 16-byte, uninitialized Buffer\", function () {\n    var b = addon.return_uninitialized_buffer();\n    assert.ok(b.length === 16);\n  });\n\n  it(\"gets a 16-byte, zeroed Buffer\", function () {\n    var b = addon.return_buffer();\n    assert.ok(b.equals(Buffer.alloc(16)));\n  });\n\n  it(\"gets a 16-byte buffer initialized from a slice\", function () {\n    var b = addon.return_array_buffer_from_slice(16);\n    var a = new Uint8Array(b);\n    for (var i = 0; i < 16; i++) {\n      assert.strictEqual(a[i], i);\n    }\n  });\n\n  it(\"gets an external Buffer\", function () {\n    var expected = \"String to copy\";\n    var buf = addon.return_external_buffer(expected);\n    assert.instanceOf(buf, Buffer);\n    assert.strictEqual(buf.toString(), expected);\n  });\n\n  it(\"gets an external ArrayBuffer\", function () {\n    var expected = \"String to copy\";\n    var buf = addon.return_external_array_buffer(expected);\n    assert.instanceOf(buf, ArrayBuffer);\n    assert.strictEqual(Buffer.from(buf).toString(), expected);\n  });\n\n  it(\"gets a typed array constructed from an ArrayBuffer\", function () {\n    var b = new ArrayBuffer(64);\n    var i8 = addon.return_int8array_from_arraybuffer(b);\n    assert.strictEqual(i8.byteLength, 64);\n    assert.strictEqual(i8.length, 64);\n    i8[0] = 0x17;\n    i8[1] = -0x17;\n    assert.deepEqual([...i8.slice(0, 2)], [0x17, -0x17]);\n\n    var b = new ArrayBuffer(64);\n    var i16 = addon.return_int16array_from_arraybuffer(b);\n    assert.strictEqual(i16.byteLength, 64);\n    assert.strictEqual(i16.length, 32);\n    i16[0] = 0x1234;\n    i16[1] = -1;\n    i16[2] = -2;\n    i16[3] = 0x5678;\n    assert.deepEqual([...i16.slice(0, 4)], [0x1234, -1, -2, 0x5678]);\n    var u8 = new Uint8Array(b);\n    assert.deepEqual(\n      [...u8.slice(0, 8)],\n      [0x34, 0x12, 0xff, 0xff, 0xfe, 0xff, 0x78, 0x56]\n    );\n\n    var b = new ArrayBuffer(64);\n    var u32 = addon.return_uint32array_from_arraybuffer(b);\n    assert.strictEqual(u32.byteLength, 64);\n    assert.strictEqual(u32.length, 16);\n    u32[0] = 0x12345678;\n    var u8 = new Uint8Array(b);\n    assert.deepEqual([...u8.slice(0, 4)], [0x78, 0x56, 0x34, 0x12]);\n\n    var b = new ArrayBuffer(64);\n    var f64 = addon.return_float64array_from_arraybuffer(b);\n    assert.strictEqual(f64.byteLength, 64);\n    assert.strictEqual(f64.length, 8);\n    f64[0] = 1.0;\n    f64[1] = 2.0;\n    f64[2] = 3.141592653589793;\n    assert.deepEqual([...f64.slice(0, 3)], [1.0, 2.0, 3.141592653589793]);\n    assert.deepEqual(\n      [...new Float64Array(b).slice(0, 3)],\n      [1.0, 2.0, 3.141592653589793]\n    );\n\n    var b = new ArrayBuffer(64);\n    var u64 = addon.return_biguint64array_from_arraybuffer(b);\n    assert.strictEqual(u64.byteLength, 64);\n    assert.strictEqual(u64.length, 8);\n    u64[0] = 0x1234567887654321n;\n    u64[1] = 0xcafed00d1337c0den;\n    var u8 = new Uint8Array(b);\n    assert.deepEqual(\n      [...u64.slice(0, 2)],\n      [0x1234567887654321n, 0xcafed00d1337c0den]\n    );\n    assert.deepEqual(\n      [...u8.slice(0, 16)],\n      [\n        0x21, 0x43, 0x65, 0x87, 0x78, 0x56, 0x34, 0x12, 0xde, 0xc0, 0x37, 0x13,\n        0x0d, 0xd0, 0xfe, 0xca,\n      ]\n    );\n  });\n\n  it(\"gets a new typed array\", function () {\n    var i32 = addon.return_new_int32array(16);\n    assert.strictEqual(i32.constructor, Int32Array);\n    assert.strictEqual(i32.byteLength, 64);\n    assert.strictEqual(i32.length, 16);\n    assert.deepEqual(\n      [...i32],\n      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n    );\n  });\n\n  it(\"gets a typed array copied from a slice\", function () {\n    var i32 = addon.return_int32array_from_slice(16);\n    for (var i = 0; i < 16; i++) {\n      assert.strictEqual(i32[i], i);\n    }\n  });\n\n  it(\"gets correct typed array info\", function () {\n    var buf = new ArrayBuffer(128);\n\n    var a = addon.return_int8array_from_arraybuffer(buf);\n    var info = addon.get_typed_array_info(a);\n\n    assert.strictEqual(buf, a.buffer);\n    assert.strictEqual(0, a.byteOffset);\n    assert.strictEqual(128, a.length);\n    assert.strictEqual(128, a.byteLength);\n\n    assert.strictEqual(buf, info.buffer);\n    assert.strictEqual(0, info.byteOffset);\n    assert.strictEqual(128, info.length);\n    assert.strictEqual(128, info.byteLength);\n\n    var a = addon.return_int16array_from_arraybuffer(buf);\n    var info = addon.get_typed_array_info(a);\n\n    assert.strictEqual(buf, a.buffer);\n    assert.strictEqual(0, a.byteOffset);\n    assert.strictEqual(64, a.length);\n    assert.strictEqual(128, a.byteLength);\n\n    assert.strictEqual(buf, info.buffer);\n    assert.strictEqual(0, info.byteOffset);\n    assert.strictEqual(64, info.length);\n    assert.strictEqual(128, info.byteLength);\n\n    var a = addon.return_uint32array_from_arraybuffer(buf);\n    var info = addon.get_typed_array_info(a);\n\n    assert.strictEqual(buf, a.buffer);\n    assert.strictEqual(0, a.byteOffset);\n    assert.strictEqual(32, a.length);\n    assert.strictEqual(128, a.byteLength);\n\n    assert.strictEqual(buf, info.buffer);\n    assert.strictEqual(0, info.byteOffset);\n    assert.strictEqual(32, info.length);\n    assert.strictEqual(128, info.byteLength);\n\n    var a = addon.return_biguint64array_from_arraybuffer(buf);\n    var info = addon.get_typed_array_info(a);\n\n    assert.strictEqual(buf, a.buffer);\n    assert.strictEqual(0, a.byteOffset);\n    assert.strictEqual(16, a.length);\n    assert.strictEqual(128, a.byteLength);\n\n    assert.strictEqual(buf, info.buffer);\n    assert.strictEqual(0, info.byteOffset);\n    assert.strictEqual(16, info.length);\n    assert.strictEqual(128, info.byteLength);\n  });\n\n  it(\"correctly constructs a view over a slice of a buffer\", function () {\n    var buf = new ArrayBuffer(128);\n\n    var a = addon.return_uint32array_from_arraybuffer_region(buf, 16, 4);\n    var info = addon.get_typed_array_info(a);\n\n    assert.strictEqual(buf, a.buffer);\n    assert.strictEqual(16, a.byteOffset);\n    assert.strictEqual(4, a.length);\n    assert.strictEqual(16, a.byteLength);\n\n    assert.strictEqual(buf, info.buffer);\n    assert.strictEqual(16, info.byteOffset);\n    assert.strictEqual(4, info.length);\n    assert.strictEqual(16, info.byteLength);\n\n    a[0] = 17;\n    a[1] = 42;\n    a[2] = 100;\n    a[3] = 1000;\n\n    var left = buf.slice(0, 16);\n    var middle = buf.slice(16, 32);\n    var right = buf.slice(32);\n\n    assert.deepEqual(new Uint8Array(16), new Uint8Array(left));\n    assert.deepEqual(\n      new Uint8Array([17, 0, 0, 0, 42, 0, 0, 0, 100, 0, 0, 0, 232, 3, 0, 0]),\n      new Uint8Array(middle)\n    );\n    assert.deepEqual(new Uint8Array(96), new Uint8Array(right));\n  });\n\n  it(\"properly fails to construct typed arrays with invalid arguments\", function () {\n    var buf = new ArrayBuffer(32);\n    try {\n      addon.return_uint32array_from_arraybuffer_region(buf, 1, 4);\n      assert.fail(\"should have thrown for unaligned offset\");\n    } catch (expected) {}\n\n    try {\n      addon.return_uint32array_from_arraybuffer_region(buf, 100, 104);\n      assert.fail(\"should have thrown for bounds check failure\");\n    } catch (expected) {}\n\n    try {\n      addon.return_uint32array_from_arraybuffer_region(buf, 0, 5);\n      assert.fail(\"should have thrown for invalid length\");\n    } catch (expected) {}\n\n    try {\n      addon.return_uint32array_from_arraybuffer_region(buf, 0, 10);\n      assert.fail(\"should have thrown for excessive length\");\n    } catch (expected) {}\n  });\n\n  it(\"correctly reads a Buffer using the lock API\", function () {\n    var b = Buffer.allocUnsafe(16);\n    b.writeUInt8(147, 0);\n    b.writeUInt8(113, 1);\n    b.writeUInt8(109, 2);\n    b.writeUInt8(189, 3);\n    assert.equal(addon.read_buffer_with_lock(b, 0), 147);\n    assert.equal(addon.read_buffer_with_lock(b, 1), 113);\n    assert.equal(addon.read_buffer_with_lock(b, 2), 109);\n    assert.equal(addon.read_buffer_with_lock(b, 3), 189);\n  });\n\n  it(\"correctly reads a Buffer using the borrow API\", function () {\n    var b = Buffer.from([149, 224, 70, 229]);\n    assert.equal(addon.read_buffer_with_borrow(b, 0), 149);\n    assert.equal(addon.read_buffer_with_borrow(b, 1), 224);\n    assert.equal(addon.read_buffer_with_borrow(b, 2), 70);\n    assert.equal(addon.read_buffer_with_borrow(b, 3), 229);\n  });\n\n  it(\"correctly writes to a Buffer using the lock API\", function () {\n    var b = Buffer.allocUnsafe(16);\n    b.fill(0);\n    addon.write_buffer_with_lock(b, 0, 6);\n    assert.equal(b.readUInt8(0), 6);\n    addon.write_buffer_with_lock(b, 1, 61);\n    assert.equal(b.readUInt8(1), 61);\n    addon.write_buffer_with_lock(b, 2, 45);\n    assert.equal(b.readUInt8(2), 45);\n    addon.write_buffer_with_lock(b, 3, 216);\n    assert.equal(b.readUInt8(3), 216);\n  });\n\n  it(\"correctly writes to a Buffer using the borrow_mut API\", function () {\n    var b = Buffer.alloc(4);\n    addon.write_buffer_with_borrow_mut(b, 0, 16);\n    assert.equal(b[0], 16);\n    addon.write_buffer_with_borrow_mut(b, 1, 100);\n    assert.equal(b[1], 100);\n    addon.write_buffer_with_borrow_mut(b, 2, 232);\n    assert.equal(b[2], 232);\n    addon.write_buffer_with_borrow_mut(b, 3, 55);\n    assert.equal(b[3], 55);\n  });\n\n  it(\"copies from a source buffer to a destination with borrow API\", function () {\n    for (const f of [addon.copy_buffer, addon.copy_buffer_with_borrow]) {\n      const a = Buffer.from([1, 2, 3]);\n      const b = Buffer.from([0, 0, 0, 4, 5, 6]);\n\n      // Full\n      addon.copy_buffer(a, b);\n      assert.deepEqual([...b], [1, 2, 3, 4, 5, 6]);\n\n      // Empty buffers\n      addon.copy_buffer(Buffer.alloc(0), Buffer.alloc(0));\n    }\n  });\n\n  it(\"zeroes the byteLength when an ArrayBuffer is detached\", function () {\n    var buf = new ArrayBuffer(16);\n    assert.strictEqual(buf.byteLength, 16);\n    assert.strictEqual(addon.get_arraybuffer_byte_length(buf), 16);\n\n    detach(buf);\n\n    assert.strictEqual(buf.byteLength, 0);\n    assert.strictEqual(addon.get_arraybuffer_byte_length(buf), 0);\n  });\n\n  function testDetach(\n    arr,\n    addonFn,\n    byteLengthBefore,\n    lengthBefore,\n    byteOffsetBefore\n  ) {\n    let { before, after } = addonFn(arr, (arr) => detach(arr.buffer));\n\n    assert.strictEqual(before.byteLength, byteLengthBefore);\n    assert.strictEqual(before.length, lengthBefore);\n    assert.strictEqual(before.byteOffset, byteOffsetBefore);\n    assert.strictEqual(after.byteLength, 0);\n    assert.strictEqual(after.length, 0);\n    assert.strictEqual(after.byteOffset, 0);\n  }\n\n  it(\"provides correct metadata when detaching a typed array's buffer\", function () {\n    var buf = new ArrayBuffer(16);\n    var arr = new Uint32Array(buf, 4, 2);\n    var buf = arr.buffer;\n\n    assert.strictEqual(buf.byteLength, 16);\n\n    assert.strictEqual(arr.byteLength, 8);\n    assert.strictEqual(arr.length, 2);\n    assert.strictEqual(arr.byteOffset, 4);\n\n    var info = addon.get_typed_array_info(arr);\n\n    assert.strictEqual(info.byteLength, 8);\n    assert.strictEqual(info.length, 2);\n    assert.strictEqual(info.byteOffset, 4);\n    assert.strictEqual(info.buffer, buf);\n\n    testDetach(arr, addon.detach_same_handle, 8, 2, 4);\n\n    var info = addon.get_typed_array_info(arr);\n\n    assert.strictEqual(buf.byteLength, 0);\n\n    assert.strictEqual(arr.buffer, buf);\n    assert.strictEqual(arr.byteLength, 0);\n    assert.strictEqual(arr.length, 0);\n    assert.strictEqual(arr.byteOffset, 0);\n\n    assert.strictEqual(info.byteLength, 0);\n    assert.strictEqual(info.length, 0);\n    assert.strictEqual(info.byteOffset, 0);\n    assert.strictEqual(info.buffer, buf);\n  });\n\n  it(\"provides correct metadata when detaching an escaped typed array's buffer\", function () {\n    var buf = new ArrayBuffer(16);\n    testDetach(new Uint32Array(buf, 4, 2), addon.detach_and_escape, 8, 2, 4);\n  });\n\n  it(\"provides correct metadata when detaching a casted typed array's buffer\", function () {\n    var buf = new ArrayBuffer(16);\n    testDetach(new Uint32Array(buf, 4, 2), addon.detach_and_cast, 8, 2, 4);\n  });\n\n  it(\"provides correct metadata when detaching an un-rooted typed array's buffer\", function () {\n    var buf = new ArrayBuffer(16);\n    testDetach(new Uint32Array(buf, 4, 2), addon.detach_and_unroot, 8, 2, 4);\n  });\n\n  it(\"doesn't validate regions without instantiating\", function () {\n    var buf = new ArrayBuffer(64);\n\n    try {\n      addon.build_f32_region(buf, 1, 4, false);\n    } catch (e) {\n      assert.fail(\n        \"misaligned region shouldn't be validated without instantiating\"\n      );\n    }\n\n    try {\n      addon.build_f32_region(buf, 0, 20, false);\n    } catch (e) {\n      assert.fail(\n        \"region overrun shouldn't be validated without instantiating\"\n      );\n    }\n\n    try {\n      addon.build_f64_region(buf, 1, 4, false);\n    } catch (e) {\n      assert.fail(\n        \"misaligned region shouldn't be validated without instantiating\"\n      );\n    }\n\n    try {\n      addon.build_f64_region(buf, 0, 10, false);\n    } catch (e) {\n      assert.fail(\n        \"region overrun shouldn't be validated without instantiating\"\n      );\n    }\n  });\n\n  it(\"validates regions when instantiating\", function () {\n    var buf = new ArrayBuffer(64);\n\n    try {\n      addon.build_f32_region(buf, 1, 4, false);\n      assert.fail(\"misaligned region should be validated when instantiating\");\n    } catch (expected) {}\n\n    try {\n      addon.build_f32_region(buf, 0, 20, false);\n      assert.fail(\"region overrun should be validated when instantiating\");\n    } catch (expected) {}\n\n    try {\n      addon.build_f64_region(buf, 1, 4, true);\n      assert.fail(\"misaligned region should be validated when instantiating\");\n    } catch (expected) {}\n\n    try {\n      addon.build_f64_region(buf, 0, 10, true);\n      assert.fail(\"region overrun should be validated when instantiating\");\n    } catch (expected) {}\n  });\n});\n"
  },
  {
    "path": "test/napi/lib/types.js",
    "content": "var addon = require(\"..\");\nvar assert = require(\"chai\").assert;\n\ndescribe(\"type checks\", function () {\n  it(\"is_array\", function () {\n    assert(addon.is_array([]));\n    assert(addon.is_array(new Array()));\n    assert(!addon.is_array(null));\n    assert(!addon.is_array(1));\n    assert(!addon.is_array({ 0: \"a\", 1: \"b\", length: 2 }));\n  });\n\n  it(\"is_array_buffer\", function () {\n    assert(addon.is_array_buffer(new ArrayBuffer(0)));\n    assert(!addon.is_array_buffer(new DataView(new ArrayBuffer(0))));\n    assert(!addon.is_array_buffer(new Uint8Array(1024)));\n    assert(!addon.is_array_buffer(Buffer.alloc(64)));\n    assert(!addon.is_array_buffer([]));\n    assert(!addon.is_array_buffer(\"hello world\"));\n  });\n\n  it(\"is_uint32_array\", function () {\n    assert(addon.is_uint32_array(new Uint32Array(0)));\n    assert(!addon.is_uint32_array(new Uint16Array(0)));\n  });\n\n  it(\"is_boolean\", function () {\n    assert(addon.is_boolean(true));\n    assert(addon.is_boolean(false));\n    assert(!addon.is_boolean(new Boolean(true)));\n    assert(!addon.is_boolean(new Boolean(false)));\n  });\n\n  it(\"is_buffer\", function () {\n    assert(addon.is_buffer(Buffer.alloc(64)));\n    assert(addon.is_buffer(new Uint8Array(64)));\n    assert(!addon.is_buffer(new ArrayBuffer(64)));\n  });\n\n  it(\"is_error\", function () {\n    assert(addon.is_error(new Error()));\n    assert(addon.is_error(new TypeError()));\n    class SubclassError extends Error {}\n    assert(addon.is_error(new SubclassError()));\n    assert(!addon.is_error(\"something went wrong!\"));\n  });\n\n  it(\"is_null\", function () {\n    assert(addon.is_null(null));\n    assert(!addon.is_null(undefined));\n    assert(!addon.is_null(\"anything other than null\"));\n  });\n\n  it(\"is_number\", function () {\n    assert(addon.is_number(0));\n    assert(addon.is_number(1.4526456453));\n    assert(addon.is_number(NaN));\n    assert(!addon.is_number(new Number(2)));\n    assert(!addon.is_number(\"42\"));\n  });\n\n  it(\"is_object\", function () {\n    assert(addon.is_object({}));\n    assert(addon.is_object(new Number(1)));\n    assert(addon.is_object(new String(\"1\")));\n    // Unlike `typeof`, is_object does *not* consider `null` to be an Object.\n    assert(!addon.is_object(null));\n    assert(!addon.is_object(undefined));\n    assert(!addon.is_object(1));\n    assert(!addon.is_object(\"1\"));\n  });\n\n  it(\"is_string\", function () {\n    assert(addon.is_string(\"1\"));\n    assert(!addon.is_string(new String(\"1\")));\n  });\n\n  it(\"is_undefined\", function () {\n    assert(addon.is_undefined(undefined));\n    assert(!addon.is_undefined(null));\n    assert(!addon.is_undefined(\"anything other than undefined\"));\n  });\n\n  it(\"strict_equals\", function () {\n    assert(addon.strict_equals(17, 17));\n    assert(!addon.strict_equals(17, 18));\n    let o1 = {};\n    let o2 = {};\n    assert(addon.strict_equals(o1, o1));\n    assert(!addon.strict_equals(o1, o2));\n    assert(!addon.strict_equals(o1, 17));\n  });\n});\n"
  },
  {
    "path": "test/napi/lib/workers.js",
    "content": "const assert = require(\"assert\");\nconst {\n  Worker,\n  isMainThread,\n  parentPort,\n  threadId,\n  workerData,\n} = require(\"worker_threads\");\n\nconst addon = require(\"..\");\n\n// Receive a message, try that method and return the error message\nif (!isMainThread) {\n  // RACE: Attempt to reproduce shutdown race condition bug. This depends on timings\n  // that may differ across systems. It should not produce spurious failures, but may\n  // succeed even if the presence of a bug.\n  addon.reject_after(new Error(\"Oh, no!\"), 200).catch(() => {});\n\n  // Reproduce another shutdown bug; this one isn't timing-dependent.\n  let boxed_channels = addon.box_channels();\n\n  addon.get_or_init_thread_id(threadId);\n\n  parentPort.once(\"message\", (message) => {\n    try {\n      switch (message) {\n        case \"get_and_replace\":\n          addon.get_and_replace({});\n          break;\n        case \"get_or_init\":\n          addon.get_or_init(() => ({}));\n          break;\n        case \"get_or_init_clone\":\n          addon.get_or_init_clone(() => ({}));\n          break;\n        case \"get_thread_id\":\n          {\n            let id = addon.get_or_init_thread_id(NaN);\n            parentPort.postMessage(id);\n          }\n          break;\n        default:\n          throw new Error(`Unexpected message: ${message}`);\n      }\n\n      throw new Error(\"Did not throw an exception\");\n    } catch (err) {\n      parentPort.postMessage(err);\n    }\n  });\n\n  if (workerData === \"notify_when_startup_complete\") {\n    parentPort.postMessage(\"startup_complete\");\n  }\n\n  return;\n}\n\n// From here on, we're in the main thread.\n\n// Set the `THREAD_ID` Global value in the main thread cell.\naddon.get_or_init_thread_id(threadId);\n\ndescribe(\"Worker / Root Tagging Tests\", () => {\n  describe(\"Single Threaded\", () => {\n    it(\"should be able to stash a global with `get_and_replace`\", () => {\n      const first = {};\n      const second = {};\n\n      assert.strictEqual(addon.get_and_replace(first), undefined);\n      assert.strictEqual(addon.get_and_replace(second), first);\n      assert.strictEqual(addon.get_and_replace({}), second);\n    });\n\n    it(\"should be able to lazily initialize with `get_or_init`\", () => {\n      const o = {};\n\n      assert.strictEqual(\n        addon.get_or_init(() => o),\n        o\n      );\n      assert.strictEqual(\n        addon.get_or_init(() => ({})),\n        o\n      );\n      assert.strictEqual(addon.get_or_init(), o);\n    });\n\n    it(\"should be able to lazily initialize with `get_or_init_clone`\", () => {\n      const o = {};\n\n      assert.strictEqual(\n        addon.get_or_init_clone(() => o),\n        o\n      );\n      assert.strictEqual(\n        addon.get_or_init_clone(() => ({})),\n        o\n      );\n      assert.strictEqual(addon.get_or_init_clone(), o);\n    });\n  });\n\n  // Note: These tests require that the previous set of tests have run or else they will fail\n  describe(\"Multi-Threaded\", () => {\n    it(\"should fail to use `get_and_replace`\", (cb) => {\n      const worker = new Worker(__filename);\n      after(() => worker.terminate());\n\n      worker.once(\"message\", (message) => {\n        assert.ok(/wrong module/.test(message));\n        cb();\n      });\n\n      worker.postMessage(\"get_and_replace\");\n    });\n\n    it(\"should fail to use `get_or_init`\", (cb) => {\n      const worker = new Worker(__filename);\n      after(() => worker.terminate());\n\n      worker.once(\"message\", (message) => {\n        assert.ok(/wrong module/.test(message));\n        cb();\n      });\n\n      worker.postMessage(\"get_or_init\");\n    });\n\n    it(\"should fail to use `get_or_init`\", (cb) => {\n      const worker = new Worker(__filename);\n      after(() => worker.terminate());\n\n      worker.once(\"message\", (message) => {\n        assert.ok(/wrong module/.test(message));\n        cb();\n      });\n\n      worker.postMessage(\"get_or_init_clone\");\n    });\n  });\n});\n\ndescribe(\"Instance-local storage\", () => {\n  it(\"should be able to read an instance local from the main thread\", () => {\n    let lookedUpId = addon.get_or_init_thread_id(NaN);\n    assert(!Number.isNaN(lookedUpId));\n    assert.strictEqual(lookedUpId, threadId);\n  });\n\n  it(\"should be able to store rooted objects in instance locals\", () => {\n    addon.stash_global_object();\n    assert.strictEqual(global, addon.unstash_global_object());\n  });\n\n  it(\"should gracefully panic upon reentrant get_or_try_init\", () => {\n    // 1. Global should start out uninitialized\n    assert.strictEqual(null, addon.get_reentrant_value());\n\n    // 2. Re-entrancy should panic\n    let innerClosureExecuted = false;\n    try {\n      let result = addon.reentrant_try_init(() => {\n        addon.reentrant_try_init(() => {\n          innerClosureExecuted = true;\n        });\n      });\n      assert.fail(\"should have panicked on re-entrancy\");\n    } catch (expected) {\n      assert.strictEqual(\n        innerClosureExecuted,\n        false,\n        \"inner closure should not have executed\"\n      );\n    }\n\n    try {\n      // 3. Local should still be uninitialized\n      assert.strictEqual(null, addon.get_reentrant_value());\n\n      // 4. Successful fallible initialization\n      let result = addon.reentrant_try_init(() => {});\n      assert.strictEqual(42, result);\n      assert.strictEqual(42, addon.get_reentrant_value());\n    } catch (unexpected) {\n      assert.fail(\"couldn't set reentrant local after initial failure\");\n    }\n  });\n\n  it(\"should allocate separate locals for each addon instance\", (cb) => {\n    let mainThreadId = addon.get_or_init_thread_id(NaN);\n    assert(!Number.isNaN(mainThreadId));\n\n    const worker = new Worker(__filename);\n    after(() => worker.terminate());\n\n    worker.once(\"message\", (message) => {\n      assert.strictEqual(typeof message, \"number\");\n      assert.notStrictEqual(message, mainThreadId);\n      let mainThreadIdAgain = addon.get_or_init_thread_id(NaN);\n      assert(!Number.isNaN(mainThreadIdAgain));\n      assert.strictEqual(mainThreadIdAgain, mainThreadId);\n      cb();\n    });\n\n    worker.postMessage(\"get_thread_id\");\n  });\n\n  it(\"should be able to exit a worker without a crash\", (cb) => {\n    const worker = new Worker(__filename, {\n      workerData: \"notify_when_startup_complete\",\n    });\n\n    worker.once(\"message\", async () => {\n      await worker.terminate();\n      setTimeout(cb, 200);\n    });\n  });\n});\n"
  },
  {
    "path": "test/napi/package.json",
    "content": "{\n  \"name\": \"napi-tests\",\n  \"version\": \"0.1.0\",\n  \"description\": \"Acceptance test suite for Neon with N-API backend\",\n  \"author\": \"The Neon Community\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"install\": \"cargo-cp-artifact -nc index.node -- cargo build --message-format=json-render-diagnostics\",\n    \"mocha\": \"mocha\",\n    \"test\": \"mocha --v8-expose-gc --timeout 5000 --recursive lib\"\n  },\n  \"devDependencies\": {\n    \"cargo-cp-artifact\": \"^0.1.9\",\n    \"chai\": \"^4.3.10\",\n    \"mocha\": \"^10.2.0\"\n  }\n}\n"
  },
  {
    "path": "test/napi/src/js/arrays.rs",
    "content": "use neon::prelude::*;\n\npub fn return_js_array(mut cx: FunctionContext) -> JsResult<JsArray> {\n    Ok(cx.empty_array())\n}\n\npub fn return_js_array_with_number(mut cx: FunctionContext) -> JsResult<JsArray> {\n    let array: Handle<JsArray> = JsArray::new(&mut cx, 1);\n    let n = cx.number(9000.0);\n    array.set(&mut cx, 0, n)?;\n    Ok(array)\n}\n\npub fn return_js_array_with_string(mut cx: FunctionContext) -> JsResult<JsArray> {\n    let array: Handle<JsArray> = JsArray::new(&mut cx, 1);\n    let s = cx.string(\"hello node\");\n    array.set(&mut cx, 0, s)?;\n    Ok(array)\n}\n\npub fn read_js_array(mut cx: FunctionContext) -> JsResult<JsValue> {\n    let array: Handle<JsArray> = cx.argument(0)?;\n    let first_element = array.get(&mut cx, 0)?;\n\n    Ok(first_element)\n}\n"
  },
  {
    "path": "test/napi/src/js/bigint.rs",
    "content": "/// Tests for [`JsBigInt`]. All unit tests are prefixed with `test_` and exported by\n/// [`bigint_suite`].\nuse std::{any, cmp::PartialEq, fmt, panic, str::FromStr};\n\nuse neon::{\n    prelude::*,\n    types::{\n        bigint::{RangeError, Sign},\n        JsBigInt,\n    },\n};\n\nuse num_bigint_dig::BigInt;\n\n// Helper that converts panics to exceptions to allow `.unwrap()` usage in unit tests\nfn panic_catch<'cx, F, C>(cx: &mut C, f: F) -> JsResult<'cx, JsFunction>\nwhere\n    F: Fn(&mut FunctionContext) -> NeonResult<()> + 'static,\n    C: Context<'cx>,\n{\n    JsFunction::new(cx, move |mut cx| {\n        panic::catch_unwind(panic::AssertUnwindSafe(|| f(&mut cx))).or_else(|panic| {\n            if let Some(s) = panic.downcast_ref::<&str>() {\n                cx.throw_error(s)\n            } else if let Some(s) = panic.downcast_ref::<String>() {\n                cx.throw_error(s)\n            } else {\n                panic::resume_unwind(panic)\n            }\n        })??;\n\n        Ok(cx.undefined())\n    })\n}\n\n// Export a test that is expected not to throw\nfn export<F>(cx: &mut FunctionContext, o: &JsObject, f: F) -> NeonResult<()>\nwhere\n    F: Fn(&mut FunctionContext) -> NeonResult<()> + 'static,\n{\n    let f = panic_catch(cx, f)?;\n\n    o.set(cx, any::type_name::<F>(), f)?;\n\n    Ok(())\n}\n\n// Export a test that is expected to return a `bigint::Error`\nfn export_lossy<T, F>(cx: &mut FunctionContext, o: &JsObject, f: F) -> NeonResult<()>\nwhere\n    F: Fn(&mut FunctionContext) -> NeonResult<Result<T, RangeError<T>>> + 'static,\n{\n    let f = panic_catch(cx, move |cx| {\n        if f(cx)?.is_err() {\n            return Ok(());\n        }\n\n        cx.throw_error(\"Expected a lossy error\")\n    })?;\n\n    o.set(cx, any::type_name::<F>(), f)?;\n\n    Ok(())\n}\n\n// Small helper for `eval` of a script from a Rust string. This is used\n// for creating `BigInt` inline from literals (e.g., `0n`).\nfn eval<'cx, C>(cx: &mut C, script: &str) -> JsResult<'cx, JsValue>\nwhere\n    C: Context<'cx>,\n{\n    let script = cx.string(script);\n\n    neon::reflect::eval(cx, script)\n}\n\n// Throws an exception if `l !== r` where operands are JavaScript values\nfn strict_eq<'cx, L, R, C>(l: Handle<'cx, L>, r: Handle<'cx, R>, cx: &mut C) -> NeonResult<()>\nwhere\n    L: Value,\n    R: Value,\n    C: Context<'cx>,\n{\n    if l.strict_equals(cx, r) {\n        return Ok(());\n    }\n\n    let l = l.to_string(cx)?.value(cx);\n    let r = r.to_string(cx)?.value(cx);\n\n    cx.throw_error(format!(\"Expected {l} to equal {r}\"))\n}\n\n// Throws an exception if `l != r` where operands are Rust values\nfn assert_eq<'cx, L, R, C>(l: L, r: R, cx: &mut C) -> NeonResult<()>\nwhere\n    L: fmt::Debug + PartialEq<R>,\n    R: fmt::Debug,\n    C: Context<'cx>,\n{\n    if l == r {\n        return Ok(());\n    }\n\n    cx.throw_error(format!(\"Expected {l:?} to equal {r:?}\"))\n}\n\n// Create a `JsBigInt` from a `BigInt`\nfn bigint<'cx, C>(cx: &mut C, n: &str) -> JsResult<'cx, JsBigInt>\nwhere\n    C: Context<'cx>,\n{\n    let n = BigInt::from_str(n).or_else(|err| cx.throw_error(err.to_string()))?;\n    let (sign, n) = n.to_bytes_le();\n    let n = n\n        .chunks(8)\n        .map(|c| {\n            let mut x = [0; 8];\n\n            (x[..c.len()]).copy_from_slice(c);\n\n            u64::from_le_bytes(x)\n        })\n        .collect::<Vec<_>>();\n\n    let sign = if matches!(sign, num_bigint_dig::Sign::Minus) {\n        Sign::Negative\n    } else {\n        Sign::Positive\n    };\n\n    Ok(JsBigInt::from_digits_le(cx, sign, &n))\n}\n\n// Convert a `JsBigInt` to a `BigInt`\nfn to_bigint<'cx, V, C>(b: Handle<V>, cx: &mut C) -> NeonResult<BigInt>\nwhere\n    V: Value,\n    C: Context<'cx>,\n{\n    let (sign, digits) = b.downcast_or_throw::<JsBigInt, _>(cx)?.to_digits_le(cx);\n    let sign = match sign {\n        Sign::Positive => num_bigint_dig::Sign::Plus,\n        Sign::Negative => num_bigint_dig::Sign::Minus,\n    };\n\n    Ok(BigInt::from_slice_native(sign, &digits))\n}\n\nfn test_from_u64(cx: &mut FunctionContext) -> NeonResult<()> {\n    strict_eq(JsBigInt::from_u64(cx, 0), eval(cx, \"0n\")?, cx)?;\n    strict_eq(JsBigInt::from_u64(cx, 42), eval(cx, \"42n\")?, cx)?;\n    strict_eq(\n        JsBigInt::from_u64(cx, u64::MAX),\n        eval(cx, &(u64::MAX.to_string() + \"n\"))?,\n        cx,\n    )?;\n\n    Ok(())\n}\n\nfn test_from_i64(cx: &mut FunctionContext) -> NeonResult<()> {\n    strict_eq(JsBigInt::from_i64(cx, 0), eval(cx, \"0n\")?, cx)?;\n    strict_eq(JsBigInt::from_i64(cx, 42), eval(cx, \"42n\")?, cx)?;\n    strict_eq(JsBigInt::from_i64(cx, -42), eval(cx, \"-42n\")?, cx)?;\n\n    strict_eq(\n        JsBigInt::from_i64(cx, i64::MAX),\n        eval(cx, &(i64::MAX.to_string() + \"n\"))?,\n        cx,\n    )?;\n\n    strict_eq(\n        JsBigInt::from_i64(cx, i64::MIN),\n        eval(cx, &(i64::MIN.to_string() + \"n\"))?,\n        cx,\n    )?;\n\n    Ok(())\n}\n\nfn test_from_u128(cx: &mut FunctionContext) -> NeonResult<()> {\n    strict_eq(JsBigInt::from_u128(cx, 0), eval(cx, \"0n\")?, cx)?;\n    strict_eq(JsBigInt::from_u128(cx, 42), eval(cx, \"42n\")?, cx)?;\n\n    strict_eq(\n        JsBigInt::from_u128(cx, u128::MAX),\n        eval(cx, \"2n ** 128n - 1n\")?,\n        cx,\n    )?;\n\n    strict_eq(\n        JsBigInt::from_u128(cx, u128::MAX - 1),\n        eval(cx, \"2n ** 128n - 2n\")?,\n        cx,\n    )?;\n\n    Ok(())\n}\n\nfn test_from_i128(cx: &mut FunctionContext) -> NeonResult<()> {\n    strict_eq(JsBigInt::from_i128(cx, 0), eval(cx, \"0n\")?, cx)?;\n    strict_eq(JsBigInt::from_i128(cx, 42), eval(cx, \"42n\")?, cx)?;\n    strict_eq(JsBigInt::from_i128(cx, -42), eval(cx, \"-42n\")?, cx)?;\n\n    strict_eq(\n        JsBigInt::from_i128(cx, i128::MAX),\n        eval(cx, \"2n ** 127n - 1n\")?,\n        cx,\n    )?;\n\n    strict_eq(\n        JsBigInt::from_i128(cx, i128::MAX - 1),\n        eval(cx, \"2n ** 127n - 2n\")?,\n        cx,\n    )?;\n\n    strict_eq(\n        JsBigInt::from_i128(cx, i128::MIN),\n        eval(cx, \"-(2n ** 127n)\")?,\n        cx,\n    )?;\n\n    strict_eq(\n        JsBigInt::from_i128(cx, i128::MIN + 1),\n        eval(cx, \"-(2n ** 127n - 1n)\")?,\n        cx,\n    )?;\n\n    Ok(())\n}\n\nfn test_from_digits_le(cx: &mut FunctionContext) -> NeonResult<()> {\n    strict_eq(bigint(cx, \"0\")?, eval(cx, \"0n\")?, cx)?;\n    strict_eq(bigint(cx, \"42\")?, eval(cx, \"42n\")?, cx)?;\n    strict_eq(bigint(cx, \"-42\")?, eval(cx, \"-42n\")?, cx)?;\n\n    strict_eq(\n        bigint(cx, \"170141183460469231731687303715884105727\")?,\n        eval(cx, \"170141183460469231731687303715884105727n\")?,\n        cx,\n    )?;\n\n    strict_eq(\n        bigint(cx, \"-170141183460469231731687303715884105728\")?,\n        eval(cx, \"-170141183460469231731687303715884105728n\")?,\n        cx,\n    )?;\n\n    strict_eq(\n        bigint(cx, \"10000000000000000000000000000000000000000\")?,\n        eval(cx, \"10000000000000000000000000000000000000000n\")?,\n        cx,\n    )?;\n\n    strict_eq(\n        bigint(cx, \"-10000000000000000000000000000000000000000\")?,\n        eval(cx, \"-10000000000000000000000000000000000000000n\")?,\n        cx,\n    )?;\n\n    Ok(())\n}\n\nfn test_to_u64(cx: &mut FunctionContext) -> NeonResult<()> {\n    assert_eq(JsBigInt::from_u64(cx, 0).to_u64(cx).or_throw(cx)?, 0, cx)?;\n    assert_eq(JsBigInt::from_u64(cx, 42).to_u64(cx).or_throw(cx)?, 42, cx)?;\n\n    assert_eq(\n        JsBigInt::from_u64(cx, u64::MAX).to_u64(cx).or_throw(cx)?,\n        u64::MAX,\n        cx,\n    )?;\n\n    Ok(())\n}\n\nfn test_to_i64(cx: &mut FunctionContext) -> NeonResult<()> {\n    assert_eq(JsBigInt::from_i64(cx, 0).to_i64(cx).or_throw(cx)?, 0, cx)?;\n    assert_eq(JsBigInt::from_i64(cx, 42).to_i64(cx).or_throw(cx)?, 42, cx)?;\n    assert_eq(\n        JsBigInt::from_i64(cx, -42).to_i64(cx).or_throw(cx)?,\n        -42,\n        cx,\n    )?;\n\n    assert_eq(\n        JsBigInt::from_i64(cx, i64::MAX).to_i64(cx).or_throw(cx)?,\n        i64::MAX,\n        cx,\n    )?;\n\n    assert_eq(\n        JsBigInt::from_i64(cx, i64::MIN).to_i64(cx).or_throw(cx)?,\n        i64::MIN,\n        cx,\n    )?;\n\n    Ok(())\n}\n\nfn test_to_u128(cx: &mut FunctionContext) -> NeonResult<()> {\n    assert_eq(JsBigInt::from_u128(cx, 0).to_u128(cx).or_throw(cx)?, 0, cx)?;\n    assert_eq(\n        JsBigInt::from_u128(cx, 42).to_u128(cx).or_throw(cx)?,\n        42,\n        cx,\n    )?;\n\n    assert_eq(\n        JsBigInt::from_u128(cx, u128::MAX)\n            .to_u128(cx)\n            .or_throw(cx)?,\n        u128::MAX,\n        cx,\n    )?;\n\n    // Extra trailing zeroes\n    assert_eq(\n        JsBigInt::from_digits_le(cx, JsBigInt::POSITIVE, &[u64::MAX, u64::MAX, 0, 0, 0, 0])\n            .to_u128(cx)\n            .or_throw(cx)?,\n        u128::MAX,\n        cx,\n    )?;\n\n    Ok(())\n}\n\nfn test_to_i128(cx: &mut FunctionContext) -> NeonResult<()> {\n    assert_eq(JsBigInt::from_i128(cx, 0).to_i128(cx).or_throw(cx)?, 0, cx)?;\n    assert_eq(\n        JsBigInt::from_i128(cx, 42).to_i128(cx).or_throw(cx)?,\n        42,\n        cx,\n    )?;\n    assert_eq(\n        JsBigInt::from_i128(cx, -42).to_i128(cx).or_throw(cx)?,\n        -42,\n        cx,\n    )?;\n\n    assert_eq(\n        JsBigInt::from_i128(cx, i128::MAX)\n            .to_i128(cx)\n            .or_throw(cx)?,\n        i128::MAX,\n        cx,\n    )?;\n\n    assert_eq(\n        JsBigInt::from_i128(cx, i128::MIN)\n            .to_i128(cx)\n            .or_throw(cx)?,\n        i128::MIN,\n        cx,\n    )?;\n\n    Ok(())\n}\n\nfn test_to_digits_le(cx: &mut FunctionContext) -> NeonResult<()> {\n    assert_eq(\n        to_bigint(eval(cx, \"0n\")?, cx)?,\n        BigInt::from_str(\"0\").unwrap(),\n        cx,\n    )?;\n\n    assert_eq(\n        to_bigint(eval(cx, \"42n\")?, cx)?,\n        BigInt::from_str(\"42\").unwrap(),\n        cx,\n    )?;\n\n    assert_eq(\n        to_bigint(eval(cx, \"-42n\")?, cx)?,\n        BigInt::from_str(\"-42\").unwrap(),\n        cx,\n    )?;\n\n    assert_eq(\n        to_bigint(eval(cx, \"170141183460469231731687303715884105727n\")?, cx)?,\n        BigInt::from_str(\"170141183460469231731687303715884105727\").unwrap(),\n        cx,\n    )?;\n\n    assert_eq(\n        to_bigint(eval(cx, \"-170141183460469231731687303715884105728n\")?, cx)?,\n        BigInt::from_str(\"-170141183460469231731687303715884105728\").unwrap(),\n        cx,\n    )?;\n\n    assert_eq(\n        to_bigint(eval(cx, \"10000000000000000000000000000000000000000n\")?, cx)?,\n        BigInt::from_str(\"10000000000000000000000000000000000000000\").unwrap(),\n        cx,\n    )?;\n\n    assert_eq(\n        to_bigint(eval(cx, \"-10000000000000000000000000000000000000000n\")?, cx)?,\n        BigInt::from_str(\"-10000000000000000000000000000000000000000\").unwrap(),\n        cx,\n    )?;\n\n    Ok(())\n}\n\nfn test_very_large_number(cx: &mut FunctionContext) -> NeonResult<()> {\n    // 2048-bit prime generated with `crypto.generatePrimeSync(2048)`\n    // Note: Unlike the rest of the tests, this number is big-endian\n    let n = BigInt::from_bytes_be(\n        num_bigint_dig::Sign::Plus,\n        &[\n            228, 178, 58, 23, 125, 164, 107, 153, 254, 98, 85, 252, 29, 61, 8, 237, 212, 36, 173,\n            205, 116, 52, 16, 155, 131, 82, 59, 211, 132, 139, 212, 101, 10, 26, 60, 44, 172, 86,\n            50, 42, 9, 124, 188, 236, 77, 46, 209, 64, 239, 34, 99, 8, 235, 165, 5, 41, 159, 211,\n            186, 197, 140, 111, 43, 15, 111, 132, 255, 148, 36, 12, 25, 221, 208, 162, 234, 45, 22,\n            13, 251, 157, 103, 50, 181, 2, 53, 81, 15, 137, 129, 10, 130, 212, 74, 125, 80, 188,\n            19, 218, 236, 189, 234, 145, 234, 232, 9, 218, 167, 111, 33, 62, 81, 96, 83, 125, 242,\n            217, 179, 211, 109, 16, 210, 250, 133, 130, 86, 182, 110, 213, 74, 78, 34, 210, 88, 3,\n            178, 73, 231, 53, 188, 187, 76, 247, 205, 154, 190, 200, 211, 75, 63, 34, 246, 160,\n            193, 98, 7, 85, 40, 208, 47, 157, 34, 120, 235, 136, 101, 88, 174, 149, 180, 114, 197,\n            230, 116, 47, 152, 253, 212, 191, 90, 151, 204, 6, 51, 179, 73, 128, 141, 192, 107, 74,\n            205, 130, 56, 115, 202, 96, 79, 187, 196, 49, 118, 18, 251, 34, 64, 208, 38, 25, 35,\n            195, 231, 195, 201, 224, 110, 205, 213, 92, 192, 23, 48, 165, 126, 145, 18, 30, 230,\n            83, 229, 187, 138, 177, 74, 15, 209, 151, 83, 160, 246, 77, 59, 228, 57, 112, 165, 4,\n            10, 11, 95, 213, 115, 187, 240, 57, 5, 117,\n        ],\n    );\n\n    assert_eq(to_bigint(eval(cx, &(n.to_string() + \"n\"))?, cx)?, n, cx)?;\n\n    Ok(())\n}\n\nfn test_i64_out_of_range(cx: &mut FunctionContext) -> NeonResult<Result<i64, RangeError<i64>>> {\n    Ok(JsBigInt::from_i128(cx, (i64::MIN as i128) - 1).to_i64(cx))\n}\n\nfn test_u64_out_of_range(cx: &mut FunctionContext) -> NeonResult<Result<u64, RangeError<u64>>> {\n    Ok(JsBigInt::from_u128(cx, (u64::MAX as u128) + 1).to_u64(cx))\n}\n\nfn test_i128_extra_digits(cx: &mut FunctionContext) -> NeonResult<Result<i128, RangeError<i128>>> {\n    let res = eval(cx, \"2n ** 128n\")?\n        .downcast_or_throw::<JsBigInt, _>(cx)?\n        .to_i128(cx);\n\n    Ok(res)\n}\n\nfn test_i128_overflow(cx: &mut FunctionContext) -> NeonResult<Result<i128, RangeError<i128>>> {\n    let res = eval(cx, \"2n ** 127n\")?\n        .downcast_or_throw::<JsBigInt, _>(cx)?\n        .to_i128(cx);\n\n    Ok(res)\n}\n\nfn test_i128_underflow(cx: &mut FunctionContext) -> NeonResult<Result<i128, RangeError<i128>>> {\n    let res = eval(cx, \"-(2n ** 127n + 1n)\")?\n        .downcast_or_throw::<JsBigInt, _>(cx)?\n        .to_i128(cx);\n\n    Ok(res)\n}\n\nfn test_u128_overflow(cx: &mut FunctionContext) -> NeonResult<Result<i128, RangeError<i128>>> {\n    let res = eval(cx, \"2n ** 127n\")?\n        .downcast_or_throw::<JsBigInt, _>(cx)?\n        .to_i128(cx);\n\n    Ok(res)\n}\n\nfn test_u128_underflow(cx: &mut FunctionContext) -> NeonResult<Result<u128, RangeError<u128>>> {\n    let res = eval(cx, \"-1n\")?\n        .downcast_or_throw::<JsBigInt, _>(cx)?\n        .to_u128(cx);\n\n    Ok(res)\n}\n\n// Creates a map (object) of test name to functions to be executed by a JavaScript\n// test runner.\npub fn bigint_suite(mut cx: FunctionContext) -> JsResult<JsObject> {\n    let o = cx.empty_object();\n\n    // `Ok` tests\n    export(&mut cx, &o, test_from_u64)?;\n    export(&mut cx, &o, test_from_i64)?;\n    export(&mut cx, &o, test_from_u128)?;\n    export(&mut cx, &o, test_from_i128)?;\n    export(&mut cx, &o, test_from_digits_le)?;\n    export(&mut cx, &o, test_to_u64)?;\n    export(&mut cx, &o, test_to_i64)?;\n    export(&mut cx, &o, test_to_u128)?;\n    export(&mut cx, &o, test_to_i128)?;\n    export(&mut cx, &o, test_to_digits_le)?;\n    export(&mut cx, &o, test_very_large_number)?;\n\n    // `Err` tests\n    export_lossy(&mut cx, &o, test_i64_out_of_range)?;\n    export_lossy(&mut cx, &o, test_u64_out_of_range)?;\n    export_lossy(&mut cx, &o, test_i128_extra_digits)?;\n    export_lossy(&mut cx, &o, test_i128_overflow)?;\n    export_lossy(&mut cx, &o, test_i128_underflow)?;\n    export_lossy(&mut cx, &o, test_u128_overflow)?;\n    export_lossy(&mut cx, &o, test_u128_underflow)?;\n\n    Ok(o)\n}\n"
  },
  {
    "path": "test/napi/src/js/boxed.rs",
    "content": "use std::cell::RefCell;\n\nuse neon::{prelude::*, types::extract::Boxed};\n\npub struct Person {\n    name: String,\n}\n\nimpl Finalize for Person {}\n\nimpl Person {\n    fn new(name: impl ToString) -> Self {\n        Self {\n            name: name.to_string(),\n        }\n    }\n\n    fn greet(&self) -> String {\n        format!(\"Hello, {}!\", self.name)\n    }\n\n    fn set_name(&mut self, name: impl ToString) {\n        self.name = name.to_string();\n    }\n}\n\npub fn person_new(mut cx: FunctionContext) -> JsResult<JsBox<Person>> {\n    let name = cx.argument::<JsString>(0)?.value(&mut cx);\n    let person = Person::new(name);\n\n    Ok(cx.boxed(person))\n}\n\npub fn person_greet(mut cx: FunctionContext) -> JsResult<JsString> {\n    let person = cx.argument::<JsBox<Person>>(0)?;\n    let greeting = cx.string(person.greet());\n\n    Ok(greeting)\n}\n\npub fn ref_person_new(mut cx: FunctionContext) -> JsResult<JsValue> {\n    let name = cx.argument::<JsString>(0)?.value(&mut cx);\n    let person = RefCell::new(Person::new(name));\n\n    Ok(cx.boxed(person).upcast())\n}\n\npub fn ref_person_greet(mut cx: FunctionContext) -> JsResult<JsString> {\n    let person = cx.argument::<JsBox<RefCell<Person>>>(0)?;\n    let greeting = cx.string(person.borrow().greet());\n\n    Ok(greeting)\n}\n\npub fn ref_person_set_name(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let person = cx.argument::<JsBox<RefCell<Person>>>(0)?;\n    let name = cx.argument::<JsString>(1)?.value(&mut cx);\n\n    person.borrow_mut().set_name(name);\n\n    Ok(cx.undefined())\n}\n\npub fn ref_person_fail(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let person = cx.argument::<JsBox<RefCell<Person>>>(0)?;\n    let _borrow = person.borrow();\n    let _borrow_mut = person.borrow_mut();\n\n    Ok(cx.undefined())\n}\n\npub fn external_unit(mut cx: FunctionContext) -> JsResult<JsBox<()>> {\n    Ok(cx.boxed(()))\n}\n\n#[neon::export]\nfn create_boxed_string(s: String) -> Boxed<String> {\n    Boxed(s)\n}\n\n#[neon::export]\nfn boxed_string_concat(Boxed(this): Boxed<String>, rhs: String) -> String {\n    this + &rhs\n}\n\n#[neon::export]\n// N.B.: Intentionally including unused `cx` and not using tuple struct pattern to test the macro\nfn boxed_string_repeat(_cx: &mut FunctionContext, this: Boxed<String>, n: f64) -> String {\n    this.0.repeat(n as usize)\n}\n"
  },
  {
    "path": "test/napi/src/js/class.rs",
    "content": "use std::{collections::HashMap, future::Future};\n\nuse neon::{event::Channel, prelude::*, types::extract::Json};\n\n#[neon::export]\nfn wrap_string(cx: &mut Cx, o: Handle<JsObject>, s: String) -> NeonResult<()> {\n    neon::macro_internal::object::wrap(cx, o, s)?.or_throw(cx)\n}\n\n#[neon::export]\nfn unwrap_string(cx: &mut Cx, o: Handle<JsObject>) -> NeonResult<String> {\n    neon::macro_internal::object::unwrap(cx, o)?\n        .cloned()\n        .or_throw(cx)\n}\n\n#[derive(Debug, Clone)]\npub struct Message {\n    value: String,\n}\n\n#[neon::class]\nimpl Message {\n    pub fn new(value: String) -> Self {\n        Self { value }\n    }\n\n    pub fn read(&self) -> &str {\n        &self.value\n    }\n\n    pub fn concat(&self, other: &Self) -> Self {\n        Self {\n            value: format!(\"{}{}\", self.value, other.value),\n        }\n    }\n\n    pub fn append(&mut self, suffix: String) {\n        self.value.push_str(&suffix);\n    }\n\n    pub fn finalize<'a, C: Context<'a>>(self, _cx: &mut C) {\n        println!(\"Finalizing Message with value: {}\", self.value);\n    }\n}\n\n#[derive(Debug, Clone)]\npub struct Point {\n    x: u32,\n    y: u32,\n}\n\n#[neon::class]\nimpl Point {\n    // Basic const properties\n    const ORIGIN_X: u32 = 0;\n    const ORIGIN_Y: u32 = 0;\n\n    // Const property with custom name\n    #[neon(name = \"maxCoordinate\")]\n    const MAX_COORD: u32 = 1000;\n\n    // Const property with simple JSON (string slice)\n    #[neon(json)]\n    const DEFAULT_MESSAGE: &'static [&'static str] = &[\"hello\", \"point\"];\n\n    // Test complex const expressions\n    const COMPUTED_VALUE: u32 = 10 + 20 + 12;\n    const SIZE_OF_F64: u32 = std::mem::size_of::<f64>() as u32;\n    const STRING_LENGTH: u32 = \"complex\".len() as u32;\n\n    // Test const expressions that use type information\n    const SELF_SIZE: u32 = std::mem::size_of::<Self>() as u32;\n    const POINT_ALIGNMENT: u32 = std::mem::align_of::<Point>() as u32;\n\n    // Edge case: boolean const\n    const IS_2D: bool = true;\n\n    // Edge case: const expression with conditionals\n    const MAX_DIMENSION: u32 = if std::mem::size_of::<u32>() == 4 {\n        2147483647\n    } else {\n        65535\n    };\n\n    // Edge case: const expression with match\n    const COORDINATE_BYTES: u32 = match std::mem::size_of::<u32>() {\n        4 => 4,\n        8 => 8,\n        _ => 0,\n    };\n\n    // Edge case: const expression with arithmetic (can't use sqrt in const)\n    const DOUBLE_100_SQUARED: u32 = 100_u32.pow(2) * 2;\n\n    // Edge case: string with special characters\n    #[neon(name = \"specialString\")]\n    const SPECIAL_CHARS: &'static str = \"Hello\\nWorld\\t\\\"quoted\\\"\\r\\n\";\n\n    // Edge case: negative number\n    const NEGATIVE_OFFSET: i32 = -42;\n\n    // Edge case: const with underscores (use u32 instead of u64 for now)\n    const MAX_SAFE_INTEGER_APPROX: u32 = 2147483647;\n\n    // Edge case: const starting with underscore (valid in JS)\n    const _PRIVATE_CONST: u32 = 999;\n\n    pub fn new(x: u32, y: u32) -> Self {\n        Self { x, y }\n    }\n\n    pub fn x(&self) -> u32 {\n        self.x\n    }\n\n    pub fn y(&self) -> u32 {\n        self.y\n    }\n\n    pub fn distance(&self, other: &Self) -> f64 {\n        let dx = (self.x as i32 - other.x as i32).pow(2);\n        let dy = (self.y as i32 - other.y as i32).pow(2);\n        ((dx + dy) as f64).sqrt()\n    }\n\n    pub fn midpoint(&self, other: &Self) -> Self {\n        Self {\n            x: (self.x + other.x) / 2,\n            y: (self.y + other.y) / 2,\n        }\n    }\n\n    pub fn swap_coords(&mut self, other: &mut Self) {\n        std::mem::swap(&mut self.x, &mut other.x);\n        std::mem::swap(&mut self.y, &mut other.y);\n    }\n\n    pub fn move_by(&mut self, dx: u32, dy: u32) {\n        self.x += dx;\n        self.y += dy;\n    }\n\n    pub fn set_x(&mut self, x: u32) {\n        self.x = x;\n    }\n\n    pub fn set_y(&mut self, y: u32) {\n        self.y = y;\n    }\n}\n\n#[derive(Debug, Default)]\npub struct StringBuffer {\n    buffer: String,\n}\n\n#[neon::class]\nimpl StringBuffer {\n    pub fn push(&mut self, s: String) {\n        self.buffer.push_str(&s);\n    }\n\n    #[allow(clippy::inherent_to_string)]\n    pub fn to_string(&self) -> String {\n        self.buffer.clone()\n    }\n\n    #[neon(name = \"includes\")]\n    pub fn contains(&self, s: String) -> bool {\n        self.buffer.contains(&s)\n    }\n\n    #[neon(name = \"trimStart\")]\n    pub fn trim_start(&self) -> String {\n        self.buffer.trim_start().to_string()\n    }\n\n    pub fn trim_end(&self) -> String {\n        self.buffer.trim_end().to_string()\n    }\n}\n\n// Test class with async methods\n#[derive(Debug, Clone)]\npub struct AsyncClass {\n    value: String,\n}\n\n#[neon::class]\nimpl AsyncClass {\n    // Simple const property\n    const DEFAULT_TIMEOUT: u32 = 5000;\n\n    // Const property with custom name and simple JSON\n    #[neon(name = \"version\", json)]\n    const VERSION_NUMBERS: &'static [u32] = &[1, 0, 0];\n\n    pub fn new(value: String) -> Self {\n        Self { value }\n    }\n\n    // This would fail to compile if we tried to use &self:\n    // pub async fn async_method(&self, suffix: String) -> String {\n    //     format!(\"{}{}\", self.value, suffix)\n    // }\n\n    // Async method that takes ownership (required for 'static Future)\n    pub async fn async_method(self, suffix: String) -> String {\n        // Simulate async work\n        format!(\"{}{}\", self.value, suffix)\n    }\n\n    // Task method for CPU-intensive work\n    #[neon(task)]\n    pub fn heavy_computation(self) -> u32 {\n        // Simulate CPU-intensive work\n        let mut result = 0;\n        for i in 0..100 {\n            result += i;\n        }\n        result\n    }\n\n    // Normal synchronous method for comparison\n    pub fn sync_method(&self) -> String {\n        self.value.clone()\n    }\n\n    // JSON method for testing serde serialization\n    #[neon(json)]\n    pub fn json_method(&self, data: Vec<String>) -> HashMap<String, String> {\n        let mut result = HashMap::new();\n        result.insert(\"class_value\".to_string(), self.value.clone());\n        result.insert(\"input_count\".to_string(), data.len().to_string());\n        result.insert(\n            \"first_item\".to_string(),\n            data.first().unwrap_or(&\"none\".to_string()).clone(),\n        );\n        result\n    }\n\n    // Explicit async method - developer controls cloning\n    #[neon(async)]\n    pub fn explicit_async_method(&self, multiplier: i32) -> impl Future<Output = String> + 'static {\n        // Can do sync work here on main thread\n        let base_value = format!(\"Processing: {}\", self.value);\n\n        // Must return 'static Future, so can't borrow &self\n        async move {\n            // Simulate async work\n            format!(\"{} * {}\", base_value, multiplier)\n        }\n    }\n\n    // Explicit async method that clones by choice\n    #[neon(async)]\n    pub fn explicit_async_clone(&self, suffix: String) -> impl Future<Output = String> + 'static {\n        // Developer explicitly chooses to clone for 'static Future\n        let value_clone = self.value.clone();\n\n        async move { format!(\"{}{}\", value_clone, suffix) }\n    }\n\n    // Method with context parameter (sync)\n    pub fn method_with_context<'a>(\n        &self,\n        cx: &mut FunctionContext<'a>,\n        multiplier: i32,\n    ) -> JsResult<'a, JsNumber> {\n        let result = self.value.len() as f64 * multiplier as f64;\n        Ok(cx.number(result))\n    }\n\n    // Method with explicit context attribute\n    #[neon(context)]\n    pub fn method_with_explicit_context(&self, _ctx: &mut Cx, suffix: String) -> String {\n        format!(\"{}:{}\", self.value, suffix)\n    }\n\n    // Task method with Channel parameter\n    #[neon(task)]\n    pub fn task_with_channel(self, _ch: Channel, multiplier: i32) -> String {\n        // Channel is available for background tasks\n        format!(\"Task with channel: {} * {}\", self.value, multiplier)\n    }\n\n    // AsyncFn method with Channel parameter\n    pub async fn async_fn_with_channel(self, _ch: Channel, suffix: String) -> String {\n        // Channel is available for async functions\n        format!(\"AsyncFn with channel: {}{}\", self.value, suffix)\n    }\n\n    #[allow(unused_variables)]\n    // Method with this parameter (should auto-detect)\n    pub fn method_with_this(&self, this: Handle<JsObject>, data: String) -> String {\n        // Access to both Rust instance and JavaScript object\n        format!(\n            \"Instance: {}, JS object available, data: {}\",\n            self.value, data\n        )\n    }\n\n    // Method with explicit this attribute\n    #[neon(this)]\n    pub fn method_with_explicit_this(&self, _js_obj: Handle<JsObject>, suffix: String) -> String {\n        format!(\"Explicit this: {}{}\", self.value, suffix)\n    }\n\n    // Method with context and this\n    #[neon(this)]\n    pub fn method_with_context_and_this<'a>(\n        &self,\n        cx: &mut FunctionContext<'a>,\n        _this: Handle<JsObject>,\n        multiplier: i32,\n    ) -> JsResult<'a, JsNumber> {\n        let result = self.value.len() as f64 * multiplier as f64;\n        Ok(cx.number(result))\n    }\n\n    // Performance test methods\n    pub fn simple_method(&self, x: i32) -> i32 {\n        x * 2\n    }\n\n    #[neon(json)]\n    pub fn json_method_perf(&self, data: Vec<i32>) -> Vec<i32> {\n        data.into_iter().map(|x| x * 2).collect()\n    }\n\n    pub fn context_method_perf(&self, _cx: &mut FunctionContext, x: i32) -> i32 {\n        x * 3\n    }\n\n    // Test explicit async + JSON combination\n    #[neon(async, json)]\n    pub fn explicit_async_json_method(\n        &self,\n        data: Vec<i32>,\n    ) -> impl Future<Output = Vec<i32>> + 'static {\n        let data_clone = data;\n        async move {\n            // Simulate async work with JSON serialization\n            data_clone.into_iter().map(|x| x * 2).collect()\n        }\n    }\n\n    #[neon(json)]\n    pub async fn async_json_method(self, data: Vec<i32>) -> Vec<i32> {\n        data.into_iter().map(|x| x * 2).collect()\n    }\n}\n\n// Test Rust → JS path: Create class instance in Rust and return to JS\n#[neon::export]\npub fn create_point_from_rust(x: u32, y: u32) -> Point {\n    Point::new(x, y)\n}\n\n// Test Rust → JS with transformation\n#[neon::export]\npub fn create_point_origin() -> Point {\n    Point::new(Point::ORIGIN_X, Point::ORIGIN_Y)\n}\n\n// Test Rust → JS: Accept a point, transform it, and return a new point\n#[neon::export]\npub fn double_point_coords(point: Point) -> Point {\n    Point::new(point.x() * 2, point.y() * 2)\n}\n\n// Test class with Result return type in constructor\n#[derive(Debug, Clone)]\npub struct FallibleCounter {\n    value: u32,\n}\n\n#[neon::class]\nimpl FallibleCounter {\n    pub fn new(value: u32) -> Result<Self, String> {\n        if value > 100 {\n            Err(\"Value must be <= 100\".to_string())\n        } else {\n            Ok(Self { value })\n        }\n    }\n\n    pub fn get(&self) -> u32 {\n        self.value\n    }\n\n    pub fn increment(&mut self) {\n        self.value += 1;\n    }\n}\n\n// Test class with context parameter in constructor (auto-inferred, no attribute needed)\n#[derive(Debug, Clone)]\npub struct ContextCounter {\n    value: u32,\n}\n\ntype AlsoCx<'cx> = Cx<'cx>;\n\n#[neon::class]\nimpl ContextCounter {\n    #[neon(context)]\n    pub fn new(_cx: &mut AlsoCx, value: u32) -> Self {\n        // Could use context to access JavaScript values, call functions, etc.\n        // Context is auto-detected because first param is &mut Cx\n        Self { value }\n    }\n\n    pub fn get(&self) -> u32 {\n        self.value\n    }\n}\n\n// Test class with JSON in constructor\n#[derive(Debug, Clone, serde::Deserialize)]\npub struct JsonConfig {\n    name: String,\n    count: u32,\n    enabled: bool,\n}\n\n#[neon::class]\nimpl JsonConfig {\n    #[neon(json)]\n    pub fn new(config: JsonConfig) -> Self {\n        config\n    }\n\n    pub fn name(&self) -> String {\n        self.name.clone()\n    }\n\n    pub fn count(&self) -> u32 {\n        self.count\n    }\n\n    pub fn enabled(&self) -> bool {\n        self.enabled\n    }\n}\n\n// Test class combining all features: context (auto-inferred), JSON, and Result\n#[derive(Debug, Clone, serde::Deserialize)]\npub struct ValidatedConfig {\n    name: String,\n    count: u32,\n}\n\n#[neon::class]\nimpl ValidatedConfig {\n    #[neon(json)]\n    pub fn new(_cx: &mut Cx, config: ValidatedConfig) -> Result<Self, String> {\n        // Validate the configuration\n        if config.name.is_empty() {\n            return Err(\"Name cannot be empty\".to_string());\n        }\n        if config.count > 1000 {\n            return Err(\"Count must be <= 1000\".to_string());\n        }\n        Ok(config)\n    }\n\n    pub fn name(&self) -> String {\n        self.name.clone()\n    }\n\n    pub fn count(&self) -> u32 {\n        self.count\n    }\n}\n\npub struct Secret {\n    pub value: String,\n}\n\n#[neon::class]\nimpl Secret {\n    pub fn new(cx: &mut Cx, init: Handle<JsValue>) -> NeonResult<Self> {\n        if let Ok(js_str) = init.downcast::<JsString, _>(cx) {\n            let secret_str: String = js_str.value(cx);\n            return Ok(Self { value: secret_str });\n        }\n        if let Ok(js_thunk) = init.downcast::<JsFunction, _>(cx) {\n            let this = cx.undefined();\n            let js_result: Handle<JsValue> = js_thunk.call(cx, this, vec![])?;\n            let secret_str: String = js_result.to_string(cx)?.value(cx);\n            return Ok(Self { value: secret_str });\n        }\n        Ok(Self {\n            value: \"default_secret\".to_string(),\n        })\n    }\n\n    pub fn reveal(&self) -> String {\n        self.value.clone()\n    }\n}\n\npub struct Argv {\n    pub args: Vec<String>,\n}\n\n#[neon::class]\nimpl Argv {\n    #[neon(json)]\n    pub fn new(cx: &mut Cx, args: Option<Vec<String>>) -> NeonResult<Self> {\n        let args = if let Some(args) = args {\n            args\n        } else {\n            // Use global_object() instead of global() to avoid swallowing exceptions\n            // from property getters. The global() method internally calls get() which\n            // catches PendingException and converts it to a generic error.\n            let global = cx.global_object();\n            let process: Handle<JsObject> = global.prop(cx, \"process\").get()?;\n            let Json(args): Json<Vec<String>> = process.prop(cx, \"argv\").get()?;\n            args\n        };\n        Ok(Self { args })\n    }\n\n    pub fn len(&self) -> u32 {\n        self.args.len() as u32\n    }\n\n    pub fn get(&self, index: u32) -> Option<String> {\n        self.args.get(index as usize).cloned()\n    }\n}\n\nconst CAROUSEL_MESSAGES: [&str; 5] = [\n    \"Welcome to the Neon Carousel!\",\n    \"Enjoy seamless Rust and JavaScript integration.\",\n    \"Experience high performance with native modules.\",\n    \"Build robust applications with ease.\",\n    \"Thank you for using Neon!\",\n];\n\npub struct Carousel {\n    state: u32,\n}\n\n#[neon::class]\nimpl Carousel {\n    pub fn new() -> Self {\n        Self { state: 0 }\n    }\n\n    pub fn next(&mut self) -> String {\n        let message = CAROUSEL_MESSAGES[self.state as usize];\n        self.state = (self.state + 1) % CAROUSEL_MESSAGES.len() as u32;\n        message.to_string()\n    }\n}\n\n#[derive(Debug, Clone, Copy)]\npub struct Expando;\n\n#[neon::class]\nimpl Expando {\n    pub fn new(cx: &mut FunctionContext) -> NeonResult<Self> {\n        let this: Handle<JsObject> = cx.this()?;\n        this.prop(cx, \"__weirdNeonExpandoKey__\").set(42)?;\n        Ok(Self)\n    }\n\n    pub fn expando(self, cx: &mut FunctionContext) -> NeonResult<i32> {\n        let this: Handle<JsObject> = cx.this()?;\n        let value: Handle<JsNumber> = this.prop(cx, \"__weirdNeonExpandoKey__\").get()?;\n        Ok(value.value(cx) as i32)\n    }\n}\n"
  },
  {
    "path": "test/napi/src/js/coercions.rs",
    "content": "use neon::prelude::*;\n\npub fn to_string(mut cx: FunctionContext) -> JsResult<JsString> {\n    let arg: Handle<JsValue> = cx.argument(0)?;\n    arg.to_string(&mut cx)\n}\n"
  },
  {
    "path": "test/napi/src/js/container.rs",
    "content": "use neon::prelude::*;\n\nuse std::{\n    cell::{Ref, RefCell, RefMut},\n    rc::Rc,\n    sync::Arc,\n};\n\n#[neon::export]\nfn create_string_ref_cell(s: String) -> RefCell<String> {\n    RefCell::new(s)\n}\n\n#[neon::export]\nfn read_string_ref_cell(s: &RefCell<String>) -> String {\n    s.borrow().clone()\n}\n\n#[neon::export]\nfn write_string_ref_cell(s: &RefCell<String>, value: String) {\n    *s.borrow_mut() = value;\n}\n\n#[neon::export]\nfn string_ref_cell_concat(lhs: &RefCell<String>, rhs: String) -> String {\n    lhs.borrow().clone() + &rhs\n}\n\n#[neon::export]\nfn string_ref_concat(lhs: Ref<String>, rhs: String) -> String {\n    lhs.clone() + &rhs\n}\n\n#[neon::export]\nfn write_string_ref(mut s: RefMut<String>, value: String) {\n    *s = value;\n}\n\n#[neon::export]\nfn borrow_and_then<'cx>(\n    cx: &mut Cx<'cx>,\n    cell: &RefCell<String>,\n    f: Handle<JsFunction>,\n) -> JsResult<'cx, JsString> {\n    let s = cell.borrow();\n    f.bind(cx).exec()?;\n    Ok(cx.string(s.clone()))\n}\n\n#[neon::export]\nfn borrow_mut_and_then<'cx>(\n    cx: &mut Cx<'cx>,\n    cell: &RefCell<String>,\n    f: Handle<JsFunction>,\n) -> JsResult<'cx, JsString> {\n    let mut s = cell.borrow_mut();\n    f.bind(cx).exec()?;\n    *s = \"overwritten\".to_string();\n    Ok(cx.string(s.clone()))\n}\n\n#[neon::export]\nfn create_string_rc(s: String) -> Rc<String> {\n    Rc::new(s)\n}\n\n#[neon::export]\nfn read_string_rc(s: Rc<String>) -> String {\n    (*s).clone()\n}\n\n#[neon::export]\nfn create_string_arc(s: String) -> Arc<String> {\n    Arc::new(s)\n}\n\n#[neon::export]\nfn read_string_arc(s: Arc<String>) -> String {\n    (*s).clone()\n}\n"
  },
  {
    "path": "test/napi/src/js/date.rs",
    "content": "use neon::{prelude::*, types::JsDate};\n\npub fn create_date(mut cx: FunctionContext) -> JsResult<JsDate> {\n    let date = JsDate::new_lossy(&mut cx, 31415);\n    Ok(date)\n}\n\npub fn create_date_from_value(mut cx: FunctionContext) -> JsResult<JsDate> {\n    let time = cx.argument::<JsNumber>(0)?.value(&mut cx);\n    let date = JsDate::new_lossy(&mut cx, time);\n    Ok(date)\n}\n\npub fn check_date_is_valid(mut cx: FunctionContext) -> JsResult<JsBoolean> {\n    let time = cx.argument::<JsNumber>(0)?.value(&mut cx);\n    let date = JsDate::new_lossy(&mut cx, time);\n    let is_valid = date.is_valid(&mut cx);\n    Ok(cx.boolean(is_valid))\n}\n\npub fn try_new_date(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let _date_overflow = JsDate::new(&mut cx, JsDate::MAX_VALUE + 1.0);\n    let _date_underflow = JsDate::new(&mut cx, JsDate::MIN_VALUE - 1.0);\n    let nan_date = JsDate::new(&mut cx, f64::NAN);\n    assert!(nan_date.unwrap().value(&mut cx).is_nan());\n    Ok(cx.undefined())\n}\n\npub fn try_new_lossy_date(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let date_overflow = JsDate::new(&mut cx, JsDate::MAX_VALUE + 1.0);\n    let date_underflow = JsDate::new(&mut cx, JsDate::MIN_VALUE - 1.0);\n    assert_eq!(\n        date_overflow.unwrap_err().kind(),\n        neon::types::DateErrorKind::Overflow\n    );\n    assert_eq!(\n        date_underflow.unwrap_err().kind(),\n        neon::types::DateErrorKind::Underflow\n    );\n    Ok(cx.undefined())\n}\n\npub fn nan_dates(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let date_nan = JsDate::new(&mut cx, f64::NAN).unwrap();\n    assert!(!date_nan.is_valid(&mut cx));\n    assert!(date_nan.value(&mut cx).is_nan());\n\n    let date_nan_lossy = JsDate::new_lossy(&mut cx, f64::NAN);\n    assert!(!date_nan_lossy.is_valid(&mut cx));\n    assert!(date_nan_lossy.value(&mut cx).is_nan());\n\n    Ok(cx.undefined())\n}\n\npub fn check_date_is_invalid(mut cx: FunctionContext) -> JsResult<JsBoolean> {\n    let time = JsDate::MIN_VALUE - 1.0;\n    let date = JsDate::new_lossy(&mut cx, time);\n    let is_valid = date.is_valid(&mut cx);\n    let _val = date.value(&mut cx);\n    Ok(cx.boolean(is_valid))\n}\n\npub fn create_and_get_invalid_date(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let time = JsDate::MAX_VALUE + 1.0;\n    assert!(!JsDate::new_lossy(&mut cx, time).is_valid(&mut cx));\n    assert!(JsDate::new_lossy(&mut cx, time).value(&mut cx).is_nan());\n\n    let time = JsDate::MIN_VALUE - 1.0;\n    assert!(!JsDate::new_lossy(&mut cx, time).is_valid(&mut cx));\n    assert!(JsDate::new_lossy(&mut cx, time).value(&mut cx).is_nan());\n\n    let time = JsDate::MAX_VALUE + 2.0;\n    assert!(!JsDate::new_lossy(&mut cx, time).is_valid(&mut cx));\n    assert!(JsDate::new_lossy(&mut cx, time).value(&mut cx).is_nan());\n\n    let time = JsDate::MAX_VALUE + 3.0;\n    assert!(!JsDate::new_lossy(&mut cx, time).is_valid(&mut cx));\n    assert!(JsDate::new_lossy(&mut cx, time).value(&mut cx).is_nan());\n\n    let time = JsDate::MAX_VALUE + 1_000.0;\n    let date = JsDate::new_lossy(&mut cx, time);\n    assert!(!date.is_valid(&mut cx));\n    assert!(JsDate::new_lossy(&mut cx, time).value(&mut cx).is_nan());\n    let date_val = date.value(&mut cx);\n\n    Ok(cx.number(date_val))\n}\n\npub fn get_date_value(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let date = JsDate::new_lossy(&mut cx, 31415);\n    let value = date.value(&mut cx);\n    Ok(cx.number(value))\n}\n"
  },
  {
    "path": "test/napi/src/js/errors.rs",
    "content": "use neon::prelude::*;\n\npub fn new_error(mut cx: FunctionContext) -> JsResult<JsError> {\n    let msg = cx.argument::<JsString>(0)?.value(&mut cx);\n\n    cx.error(msg)\n}\n\npub fn new_type_error(mut cx: FunctionContext) -> JsResult<JsError> {\n    let msg = cx.argument::<JsString>(0)?.value(&mut cx);\n\n    cx.type_error(msg)\n}\n\npub fn new_range_error(mut cx: FunctionContext) -> JsResult<JsError> {\n    let msg = cx.argument::<JsString>(0)?.value(&mut cx);\n\n    cx.range_error(msg)\n}\n\npub fn throw_error(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let msg = cx.argument::<JsString>(0)?.value(&mut cx);\n\n    cx.throw_error(msg)\n}\n\npub fn downcast_error(mut cx: FunctionContext) -> JsResult<JsString> {\n    let s = cx.string(\"hi\");\n    if let Err(e) = s.downcast::<JsNumber, _>(&mut cx) {\n        Ok(cx.string(format!(\"{e}\")))\n    } else {\n        panic!()\n    }\n}\n"
  },
  {
    "path": "test/napi/src/js/export.rs",
    "content": "use std::sync::LazyLock;\n\nuse neon::{\n    prelude::*,\n    types::extract::{Boxed, Error},\n};\n\n#[neon::export]\nconst NUMBER: u8 = 42;\n\n#[neon::export]\nstatic STRING: &str = \"Hello, World!\";\n\n#[neon::export]\nstatic LAZY_LOCK_HELLO: LazyLock<String> = LazyLock::new(|| String::from(\"Hello, Neon!\"));\n\n#[neon::export(name = \"renamedString\")]\nstatic RENAMED_STRING: &str = STRING;\n\n#[neon::export(json)]\nstatic MESSAGES: &[&str] = &[\"hello\", \"neon\"];\n\n#[neon::export(name = \"renamedMessages\", json)]\nstatic RENAMED_MESSAGES: &[&str] = MESSAGES;\n\n#[neon::export]\nfn no_args_or_return() {}\n\n#[neon::export]\nfn simple_add(a: f64, b: f64) -> f64 {\n    a + b\n}\n\n#[neon::export(name = \"renamedAdd\")]\nfn rs_renamed_add(a: f64, b: f64) -> f64 {\n    simple_add(a, b)\n}\n\n#[neon::export(task)]\nfn add_task(a: f64, b: f64) -> f64 {\n    simple_add(a, b)\n}\n\n#[neon::export(task, name = \"renamedAddTask\")]\nfn rs_renamed_add_task(a: f64, b: f64) -> f64 {\n    add_task(a, b)\n}\n\n#[neon::export(json)]\nfn json_sort(mut items: Vec<String>) -> Vec<String> {\n    items.sort();\n    items\n}\n\n#[neon::export(json, name = \"renamedJsonSort\")]\nfn rs_renamed_json_sort(items: Vec<String>) -> Vec<String> {\n    json_sort(items)\n}\n\n#[neon::export(json, task)]\nfn json_sort_task(items: Vec<String>) -> Vec<String> {\n    json_sort(items)\n}\n\n#[neon::export(json, name = \"renamedJsonSortTask\", task)]\nfn rs_renamed_json_sort_task(items: Vec<String>) -> Vec<String> {\n    json_sort(items)\n}\n\n#[neon::export]\nfn concat_with_cx_and_handle<'cx>(\n    cx: &mut FunctionContext<'cx>,\n    a: String,\n    b: Handle<'cx, JsString>,\n) -> Handle<'cx, JsString> {\n    let b = b.value(cx);\n\n    cx.string(a + &b)\n}\n\n#[neon::export]\nfn fail_with_throw(msg: String) -> Result<(), Error> {\n    fn always_fails(msg: String) -> Result<(), String> {\n        Err(msg)\n    }\n\n    // `?` converts `String` into `Error`\n    always_fails(msg)?;\n\n    Ok(())\n}\n\n#[neon::export(task)]\nfn sleep_task(ms: f64) {\n    use std::{thread, time::Duration};\n\n    thread::sleep(Duration::from_millis(ms as u64));\n}\n\n#[neon::export]\nfn number_with_cx<'cx>(cx: &mut Cx<'cx>, n: f64) -> Handle<'cx, JsNumber> {\n    cx.number(n)\n}\n\n#[neon::export]\nfn simple_self(this: Handle<JsObject>) -> Handle<JsObject> {\n    this\n}\n\n#[neon::export]\nfn boxed_self(Boxed(this): Boxed<String>) -> String {\n    this\n}\n\n#[neon::export]\nfn boxed_string(s: String) -> Boxed<String> {\n    Boxed(s)\n}\n\n#[neon::export]\nfn add_i32(a: i32, b: i32) -> i32 {\n    a + b\n}\n\n#[neon::export]\nfn add_u32(a: u32, b: u32) -> u32 {\n    a + b\n}\n\n#[neon::export]\nfn to_i32(n: i32) -> i32 {\n    n\n}\n\n#[neon::export]\nfn to_u32(n: u32) -> u32 {\n    n\n}\n\n// Test the new #[neon::export(class)] shorthand syntax\n#[derive(Clone)]\npub struct ExportedPoint {\n    x: f64,\n    y: f64,\n}\n\n#[neon::export(class)]\nimpl ExportedPoint {\n    const ORIGIN_X: f64 = 0.0;\n    const ORIGIN_Y: f64 = 0.0;\n\n    pub fn new(x: f64, y: f64) -> Self {\n        Self { x, y }\n    }\n\n    pub fn x(&self) -> f64 {\n        self.x\n    }\n\n    pub fn y(&self) -> f64 {\n        self.y\n    }\n\n    pub fn distance(&self, other: Self) -> f64 {\n        let dx = self.x - other.x();\n        let dy = self.y - other.y();\n        (dx * dx + dy * dy).sqrt()\n    }\n}\n\n// Test the shorthand syntax with custom name (CASE 1: both names use outer name)\n#[derive(Clone)]\npub struct CustomNamedClass {\n    value: String,\n}\n\n#[neon::export(class, name = \"RenamedClass\")]\nimpl CustomNamedClass {\n    pub fn new(value: String) -> Self {\n        Self { value }\n    }\n\n    pub fn get_value(&self) -> String {\n        self.value.clone()\n    }\n}\n\n// Test CASE 2: class(name = \"...\") syntax - both class and export use same name\n#[derive(Clone)]\npub struct Case2Class {\n    message: String,\n}\n\n#[neon::export(class(name = \"ParenRenamedClass\"))]\nimpl Case2Class {\n    pub fn new(message: String) -> Self {\n        Self { message }\n    }\n\n    pub fn get_message(&self) -> String {\n        self.message.clone()\n    }\n}\n\n// Test CASE 3: separate class name and export name\n#[derive(Clone)]\npub struct Case3Class {\n    data: i32,\n}\n\n#[neon::export(class(name = \"InternalClassName\"), name = \"ExternalExportName\")]\nimpl Case3Class {\n    pub fn new(data: i32) -> Self {\n        Self { data }\n    }\n\n    pub fn get_data(&self) -> i32 {\n        self.data\n    }\n}\n\n// Test async fn + JSON with export macro (compare to class limitation)\n#[neon::export(json)]\npub async fn export_async_json_test(data: Vec<i32>) -> Vec<i32> {\n    // Simulate async work with JSON serialization\n    data.into_iter().map(|x| x * 3).collect()\n}\n"
  },
  {
    "path": "test/napi/src/js/extract.rs",
    "content": "use either::Either;\nuse neon::{prelude::*, types::extract::*};\nuse std::collections::HashSet;\n\npub fn extract_values(mut cx: FunctionContext) -> JsResult<JsArray> {\n    #[allow(clippy::type_complexity)]\n    let (\n        boolean,\n        number,\n        unit,\n        string,\n        Date(date),\n        value,\n        array_buf,\n        buf,\n        view,\n        opt_number,\n        opt_string,\n    ): (\n        bool,\n        f64,\n        (),\n        String,\n        Date,\n        Handle<JsValue>,\n        ArrayBuffer<Vec<u8>>,\n        Vec<u8>,\n        Buffer<Vec<u8>>,\n        Option<f64>,\n        Option<String>,\n    ) = cx.args()?;\n\n    let values = [\n        boolean.try_into_js(&mut cx)?.upcast(),\n        number.try_into_js(&mut cx)?.upcast(),\n        unit.try_into_js(&mut cx)?.upcast(),\n        string.try_into_js(&mut cx)?.upcast(),\n        Date(date).try_into_js(&mut cx)?.upcast(),\n        value,\n        array_buf.try_into_js(&mut cx)?.upcast(),\n        buf.try_into_js(&mut cx)?.upcast(),\n        view.try_into_js(&mut cx)?.upcast(),\n        opt_number\n            .map(|n| cx.number(n).upcast::<JsValue>())\n            .unwrap_or_else(|| cx.undefined().upcast()),\n        opt_string\n            .map(|n| cx.string(n).upcast::<JsValue>())\n            .unwrap_or_else(|| cx.undefined().upcast()),\n    ];\n\n    let arr = cx.empty_array();\n\n    for (i, v) in values.into_iter().enumerate() {\n        arr.set(&mut cx, i as u32, v)?;\n    }\n\n    Ok(arr)\n}\n\npub fn extract_buffer_sum(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    fn sum<'cx, T>(\n        cx: &mut FunctionContext<'cx>,\n        buf: Vec<T>,\n        map: impl Fn(T) -> f64,\n    ) -> JsResult<'cx, JsNumber> {\n        Ok(cx.number(buf.into_iter().map(map).sum::<f64>()))\n    }\n\n    // `Float32Array`\n    if let Some(buf) = cx.arg_opt::<Vec<f32>>()? {\n        return sum(&mut cx, buf, |n| n.into());\n    }\n\n    // `Float32Array`\n    if let Some(buf) = cx.arg_opt::<Vec<f64>>()? {\n        return sum(&mut cx, buf, |n| n);\n    }\n\n    // `Buffer`\n    if let Some(Buffer(buf)) = cx.arg_opt()? {\n        return sum(&mut cx, buf, |n| n as f64);\n    }\n\n    // `ArrayBuffer`\n    if let Some(ArrayBuffer(buf)) = cx.arg_opt()? {\n        return sum(&mut cx, buf, |n| n as f64);\n    }\n\n    // `Uint8Array`\n    if let Some(buf) = cx.arg_opt::<Vec<u8>>()? {\n        return sum(&mut cx, buf, |n| n as f64);\n    }\n\n    // `Uint16Array`\n    if let Some(buf) = cx.arg_opt::<Vec<u16>>()? {\n        return sum(&mut cx, buf, |n| n as f64);\n    }\n\n    // `Uint32Array`\n    if let Some(buf) = cx.arg_opt::<Vec<u32>>()? {\n        return sum(&mut cx, buf, |n| n as f64);\n    }\n\n    // `Uint64Array`\n    if let Some(buf) = cx.arg_opt::<Vec<u64>>()? {\n        return sum(&mut cx, buf, |n| n as f64);\n    }\n\n    // `Int8Array`\n    if let Some(buf) = cx.arg_opt::<Vec<i8>>()? {\n        return sum(&mut cx, buf, |n| n as f64);\n    }\n\n    // `Int16Array`\n    if let Some(buf) = cx.arg_opt::<Vec<i16>>()? {\n        return sum(&mut cx, buf, |n| n as f64);\n    }\n\n    // `Int32Array`\n    if let Some(buf) = cx.arg_opt::<Vec<i32>>()? {\n        return sum(&mut cx, buf, |n| n as f64);\n    }\n\n    // `Int64Array`\n    let buf: Vec<i64> = cx.arg()?;\n\n    sum(&mut cx, buf, |n| n as f64)\n}\n\npub fn extract_json_sum(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let Json::<Vec<f64>>(nums) = cx.arg()?;\n\n    Ok(cx.number(nums.into_iter().sum::<f64>()))\n}\n\npub fn extract_single_add_one(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let n: f64 = cx.arg()?;\n\n    Ok(cx.number(n + 1.0))\n}\n\n#[neon::export(json)]\npub fn extract_json_option(maybe_x: Option<f64>) -> Option<f64> {\n    maybe_x\n}\n\n#[neon::export]\npub fn extract_either(either: Either<String, f64>) -> String {\n    match either {\n        Either::Left(s) => format!(\"String: {s}\"),\n        Either::Right(n) => format!(\"Number: {n}\"),\n    }\n}\n\n#[neon::export]\n// TypedArrays can be extracted and returned\npub fn buffer_concat(mut a: Vec<u8>, Uint8Array(b): Uint8Array<Vec<u8>>) -> ArrayBuffer<Vec<u8>> {\n    a.extend(b);\n    ArrayBuffer(a)\n}\n\n#[neon::export]\n// Extractors work with anything that can be used as slice of the correct type\npub fn string_to_buf(s: String) -> Uint8Array<String> {\n    Uint8Array(s)\n}\n\n#[neon::export(task)]\n// Ensure that `with` produces a closure that can be moved across thread boundaries\n// and can return a JavaScript value.\nfn sleep_with_js(n: f64) -> impl for<'cx> TryIntoJs<'cx> {\n    use std::{thread, time::Duration};\n\n    thread::sleep(Duration::from_millis(n as u64));\n\n    with(move |cx| Ok(cx.number(n)))\n}\n\n#[neon::export]\n// Ensure that `with` can be used synchronously\nfn sleep_with_js_sync(n: f64) -> impl for<'cx> TryIntoJs<'cx> {\n    sleep_with_js(n)\n}\n\n#[neon::export(task)]\n// Ensure that `With` can be used Rust data\nfn sleep_with(n: f64) -> impl for<'cx> TryIntoJs<'cx> {\n    use std::{thread, time::Duration};\n\n    thread::sleep(Duration::from_millis(n as u64));\n\n    with(move |cx| n.try_into_js(cx))\n}\n\n#[neon::export]\n// Ensure that `With` can be used Rust data synchronously\nfn sleep_with_sync(n: f64) -> impl for<'cx> TryIntoJs<'cx> {\n    sleep_with(n)\n}\n\n#[neon::export]\nfn extract_array_vec(Array(arr): Array<Vec<f64>>) -> Array<Vec<f64>> {\n    Array(arr)\n}\n\n#[neon::export]\nfn extract_array_double(Array(arr): Array<Vec<f64>>) -> Array<impl Iterator<Item = f64>> {\n    Array(arr.into_iter().map(|x| x * 2.0))\n}\n\n#[neon::export]\nfn extract_array_dedupe(set: Array<HashSet<String>>) -> Array<HashSet<String>> {\n    set\n}\n"
  },
  {
    "path": "test/napi/src/js/functions.rs",
    "content": "use neon::{prelude::*, types::extract};\n\nfn add1(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let x = cx.argument::<JsNumber>(0)?.value(&mut cx);\n    Ok(cx.number(x + 1.0))\n}\n\npub fn return_js_function(mut cx: FunctionContext) -> JsResult<JsFunction> {\n    JsFunction::new(&mut cx, add1)\n}\n\npub fn call_js_function(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let f = cx.argument::<JsFunction>(0)?;\n    let args = [cx.number(16.0).upcast()];\n    let null = cx.null();\n    f.call(&mut cx, null, args)?\n        .downcast::<JsNumber, _>(&mut cx)\n        .or_throw(&mut cx)\n}\n\npub fn call_js_function_idiomatically(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    cx.argument::<JsFunction>(0)?\n        .call_with(&cx)\n        .this(cx.null())\n        .arg(cx.number(16.0))\n        .apply(&mut cx)\n}\n\npub fn call_js_function_with_bind(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let n: f64 = cx\n        .argument::<JsFunction>(0)?\n        .bind(&mut cx)\n        .args((1, 2, 3))?\n        .arg(4)?\n        .arg_with(|cx| cx.number(5))?\n        .call()?;\n    Ok(cx.number(n))\n}\n\npub fn call_js_function_with_bind_and_args_with(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let n: f64 = cx\n        .argument::<JsFunction>(0)?\n        .bind(&mut cx)\n        .args_with(|_| (1, 2, 3))?\n        .call()?;\n    Ok(cx.number(n))\n}\n\npub fn call_js_function_with_bind_and_args_and_with(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let n: f64 = cx\n        .argument::<JsFunction>(0)?\n        .bind(&mut cx)\n        .arg(extract::with(|cx| Ok(cx.number(1))))?\n        .arg(2)?\n        .arg(3)?\n        .call()?;\n    Ok(cx.number(n))\n}\n\npub fn call_parse_int_with_bind(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let parse_int: Handle<JsFunction> = cx.global(\"parseInt\")?;\n    let x: f64 = parse_int.bind(&mut cx).arg(\"41\")?.call()?;\n    Ok(cx.number(x + 1.0))\n}\n\npub fn call_js_function_with_bind_and_exec(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    cx.argument::<JsFunction>(0)?.bind(&mut cx).arg(1)?.exec()?;\n    Ok(cx.undefined())\n}\n\npub fn call_js_constructor_with_bind(mut cx: FunctionContext) -> JsResult<JsObject> {\n    cx.argument::<JsFunction>(0)?\n        .bind(&mut cx)\n        .args((42, \"hello\"))?\n        .construct()\n}\n\npub fn bind_js_function_to_object(mut cx: FunctionContext) -> JsResult<JsValue> {\n    let f = cx.argument::<JsFunction>(0)?;\n    let obj = cx.empty_object();\n    obj.prop(&mut cx, \"prop\").set(42)?;\n    f.bind(&mut cx).this(obj)?.call()\n}\n\npub fn bind_js_function_to_number(mut cx: FunctionContext) -> JsResult<JsValue> {\n    let f = cx.argument::<JsFunction>(0)?;\n    f.bind(&mut cx).this(42)?.call()\n}\n\nfn get_math_max<'a>(cx: &mut FunctionContext<'a>) -> JsResult<'a, JsFunction> {\n    let math: Handle<JsObject> = cx.global(\"Math\")?;\n    let max: Handle<JsFunction> = math.get(cx, \"max\")?;\n    Ok(max)\n}\n\npub fn call_js_function_with_zero_args(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    get_math_max(&mut cx)?.call_with(&cx).apply(&mut cx)\n}\n\npub fn call_js_function_with_one_arg(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    get_math_max(&mut cx)?\n        .call_with(&cx)\n        .arg(cx.number(1.0))\n        .apply(&mut cx)\n}\n\npub fn call_js_function_with_two_args(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    get_math_max(&mut cx)?\n        .call_with(&cx)\n        .arg(cx.number(1.0))\n        .arg(cx.number(2.0))\n        .apply(&mut cx)\n}\n\npub fn call_js_function_with_three_args(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    get_math_max(&mut cx)?\n        .call_with(&cx)\n        .arg(cx.number(1.0))\n        .arg(cx.number(2.0))\n        .arg(cx.number(3.0))\n        .apply(&mut cx)\n}\n\npub fn call_js_function_with_four_args(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    get_math_max(&mut cx)?\n        .call_with(&cx)\n        .arg(cx.number(1.0))\n        .arg(cx.number(2.0))\n        .arg(cx.number(3.0))\n        .arg(cx.number(4.0))\n        .apply(&mut cx)\n}\n\npub fn call_js_function_with_custom_this(mut cx: FunctionContext) -> JsResult<JsObject> {\n    let custom_this = cx.empty_object();\n    let secret = cx.number(42.0);\n    custom_this.set(&mut cx, \"secret\", secret)?;\n    cx.argument::<JsFunction>(0)?\n        .call_with(&cx)\n        .this(custom_this)\n        .apply(&mut cx)\n}\n\npub fn call_js_function_with_implicit_this(mut cx: FunctionContext) -> JsResult<JsValue> {\n    cx.argument::<JsFunction>(0)?\n        .call_with(&cx)\n        .arg(cx.number(42))\n        .apply(&mut cx)\n}\n\npub fn exec_js_function_with_implicit_this(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    cx.argument::<JsFunction>(0)?\n        .call_with(&cx)\n        .arg(cx.number(42))\n        .exec(&mut cx)?;\n    Ok(cx.undefined())\n}\n\npub fn call_js_function_with_heterogeneous_tuple(mut cx: FunctionContext) -> JsResult<JsArray> {\n    cx.global::<JsFunction>(\"Array\")?\n        .call_with(&cx)\n        .args((cx.number(1.0), cx.string(\"hello\"), cx.boolean(true)))\n        .apply(&mut cx)\n}\n\npub fn construct_js_function(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let f = cx.argument::<JsFunction>(0)?;\n    let zero = cx.number(0.0);\n    let o = f.construct(&mut cx, [zero.upcast()])?;\n    let get_utc_full_year_method: Handle<JsFunction> = o.get(&mut cx, \"getUTCFullYear\")?;\n    let args: Vec<Handle<JsValue>> = vec![];\n    get_utc_full_year_method\n        .call(&mut cx, o.upcast::<JsValue>(), args)?\n        .downcast::<JsNumber, _>(&mut cx)\n        .or_throw(&mut cx)\n}\n\npub fn construct_js_function_idiomatically(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let o: Handle<JsObject> = cx\n        .argument::<JsFunction>(0)?\n        .construct_with(&cx)\n        .arg(cx.number(0.0))\n        .apply(&mut cx)?;\n    let get_utc_full_year_method: Handle<JsFunction> = o.get(&mut cx, \"getUTCFullYear\")?;\n    get_utc_full_year_method\n        .call_with(&cx)\n        .this(o)\n        .apply(&mut cx)\n}\n\npub fn construct_js_function_with_overloaded_result(mut cx: FunctionContext) -> JsResult<JsArray> {\n    let f: Handle<JsFunction> = cx.global(\"Array\")?;\n    f.construct_with(&cx)\n        .arg(cx.number(1))\n        .arg(cx.number(2))\n        .arg(cx.number(3))\n        .apply(&mut cx)\n}\n\npub fn check_string_and_number(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    cx.argument::<JsString>(0)?;\n    cx.argument::<JsNumber>(1)?;\n    Ok(cx.undefined())\n}\n\npub fn panic(_: FunctionContext) -> JsResult<JsUndefined> {\n    panic!(\"zomg\")\n}\n\npub fn panic_after_throw(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    cx.throw_range_error::<_, ()>(\"entering throw state with a RangeError\")\n        .unwrap_err();\n    panic!(\"this should override the RangeError\")\n}\n\npub fn num_arguments(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let n = cx.len();\n    Ok(cx.number(n as i32))\n}\n\npub fn return_this(mut cx: FunctionContext) -> JsResult<JsValue> {\n    cx.this()\n}\n\npub fn require_object_this(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let this = cx.this::<JsObject>()?;\n    let t = cx.boolean(true);\n    this.set(&mut cx, \"modified\", t)?;\n    Ok(cx.undefined())\n}\n\npub fn is_argument_zero_some(mut cx: FunctionContext) -> JsResult<JsBoolean> {\n    let b = cx.argument_opt(0).is_some();\n    Ok(cx.boolean(b))\n}\n\npub fn require_argument_zero_string(mut cx: FunctionContext) -> JsResult<JsString> {\n    let s = cx.argument(0)?;\n    Ok(s)\n}\n\npub fn execute_scoped(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let mut i = 0;\n    for _ in 1..100 {\n        cx.execute_scoped(|mut cx| {\n            let n = cx.number(1);\n            i += n.value(&mut cx) as i32;\n        });\n    }\n    Ok(cx.number(i))\n}\n\npub fn compute_scoped(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let mut i = cx.number(0);\n    for _ in 1..100 {\n        i = cx.compute_scoped(|mut cx| {\n            let n = cx.number(1);\n            let left = i.value(&mut cx) as i32;\n            let right = n.value(&mut cx) as i32;\n            Ok(cx.number(left + right))\n        })?;\n    }\n    Ok(i)\n}\n\n// Simple identity function to verify that a handle can be moved to `compute_scoped`\n// closure and re-escaped.\npub fn recompute_scoped(mut cx: FunctionContext) -> JsResult<JsValue> {\n    let value = cx.argument::<JsValue>(0)?;\n\n    cx.compute_scoped(move |_| Ok(value))\n}\n\npub fn throw_and_catch(mut cx: FunctionContext) -> JsResult<JsValue> {\n    let v = cx\n        .argument_opt(0)\n        .unwrap_or_else(|| cx.undefined().upcast());\n\n    cx.try_catch(|cx| cx.throw(v))\n        .map(|_: ()| Ok(cx.string(\"unreachable\").upcast()))\n        .unwrap_or_else(Ok)\n}\n\npub fn call_and_catch(mut cx: FunctionContext) -> JsResult<JsValue> {\n    let f: Handle<JsFunction> = cx.argument(0)?;\n    Ok(cx\n        .try_catch(|cx| f.call_with(cx).this(cx.global_object()).apply(cx))\n        .unwrap_or_else(|err| err))\n}\n\npub fn get_number_or_default(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let n = cx\n        .try_catch(|cx| Ok(cx.argument::<JsNumber>(0)?.value(cx)))\n        .unwrap_or(0.0);\n\n    Ok(cx.number(n))\n}\n\npub fn assume_this_is_an_object(mut cx: FunctionContext) -> JsResult<JsObject> {\n    let this: Handle<JsObject> = cx.this()?;\n    let result: Handle<JsObject> = cx.empty_object();\n    let object_class: Handle<JsFunction> = cx.global(\"Object\")?;\n    let get_prototype_of: Handle<JsFunction> = object_class.get(&mut cx, \"getPrototypeOf\")?;\n    let object_prototype: Handle<JsObject> = object_class.get(&mut cx, \"prototype\")?;\n    let has_own_property: Handle<JsFunction> = object_prototype.get(&mut cx, \"hasOwnProperty\")?;\n    let proto: Result<Handle<JsValue>, Handle<JsValue>> =\n        cx.try_catch(|cx| get_prototype_of.call_with(cx).arg(this).apply(cx));\n    let proto: Handle<JsValue> = proto.unwrap_or_else(|_| cx.undefined().upcast());\n    let has_own: Handle<JsBoolean> = has_own_property\n        .call_with(&cx)\n        .this(this)\n        .arg(cx.string(\"toString\"))\n        .apply(&mut cx)?;\n    let prop: Handle<JsValue> = this.get(&mut cx, \"toString\")?;\n    result.set(&mut cx, \"prototype\", proto)?;\n    result.set(&mut cx, \"hasOwn\", has_own)?;\n    result.set(&mut cx, \"property\", prop)?;\n    Ok(result)\n}\n\npub fn is_construct(mut cx: FunctionContext) -> JsResult<JsObject> {\n    let this = cx.this::<JsObject>()?;\n    let construct = matches!(cx.kind(), CallKind::Construct);\n    let construct = cx.boolean(construct);\n    this.set(&mut cx, \"wasConstructed\", construct)?;\n    Ok(this)\n}\n\n// `function caller_with_drop_callback(wrappedCallback, dropCallback)`\n//\n// `wrappedCallback` will be called each time the returned function is\n// called to verify we have successfully dynamically created a function\n// from a closure.\n//\n// `dropCallback` will be called when the closure is dropped to test that\n// closures are not leaking. The unit test should pass the test callback here.\npub fn caller_with_drop_callback(mut cx: FunctionContext) -> JsResult<JsFunction> {\n    struct Callback {\n        f: Root<JsFunction>,\n        drop: Option<Root<JsFunction>>,\n        channel: Channel,\n    }\n\n    // Call `dropCallback` when `Callback` is dropped as a sentinel to observe\n    // the closure isn't leaked when the function is garbage collected\n    impl Drop for Callback {\n        fn drop(&mut self) {\n            let callback = self.drop.take();\n\n            self.channel.send(move |mut cx| {\n                let this = cx.undefined();\n                let args: [Handle<JsValue>; 0] = [];\n\n                // Execute the unit test callback to end the test successfully\n                callback\n                    .unwrap()\n                    .into_inner(&mut cx)\n                    .call(&mut cx, this, args)?;\n\n                Ok(())\n            });\n        }\n    }\n\n    let callback = Callback {\n        f: cx.argument::<JsFunction>(0)?.root(&mut cx),\n        drop: Some(cx.argument::<JsFunction>(1)?.root(&mut cx)),\n        channel: cx.channel(),\n    };\n\n    JsFunction::new(&mut cx, move |mut cx| {\n        let this = cx.undefined();\n        let args: [Handle<JsValue>; 0] = [];\n\n        callback.f.to_inner(&mut cx).call(&mut cx, this, args)\n    })\n}\n"
  },
  {
    "path": "test/napi/src/js/futures.rs",
    "content": "use std::future::Future;\n\nuse neon::{\n    prelude::*,\n    types::{\n        buffer::TypedArray,\n        extract::{self, Error, Json, TryIntoJs},\n    },\n};\n\nuse crate::runtime;\n\n// Accepts two functions that take no parameters and return numbers.\n// Resolves with the sum of the two numbers.\n// Purpose: Test the `Future` implementation on `JoinHandle`\npub fn lazy_async_add(mut cx: FunctionContext) -> JsResult<JsPromise> {\n    let get_x = cx.argument::<JsFunction>(0)?.root(&mut cx);\n    let get_y = cx.argument::<JsFunction>(1)?.root(&mut cx);\n    let channel = cx.channel();\n    let runtime = runtime(&mut cx)?;\n    let (deferred, promise) = cx.promise();\n\n    runtime.spawn(async move {\n        let result = channel\n            .send(move |mut cx| {\n                let get_x = get_x.into_inner(&mut cx);\n                let get_y = get_y.into_inner(&mut cx);\n\n                let x: Handle<JsNumber> = get_x.call_with(&cx).apply(&mut cx)?;\n                let y: Handle<JsNumber> = get_y.call_with(&cx).apply(&mut cx)?;\n\n                Ok((x.value(&mut cx), y.value(&mut cx)))\n            })\n            .await\n            .map(|(x, y)| x + y);\n\n        deferred.settle_with(&channel, move |mut cx| {\n            let result = result.or_throw(&mut cx)?;\n\n            Ok(cx.number(result))\n        });\n    });\n\n    Ok(promise)\n}\n\n// Accepts a function that returns a `Promise<Float64Array>`.\n// Resolves with the sum of all numbers.\n// Purpose: Test `JsPromise::to_future`.\npub fn lazy_async_sum(mut cx: FunctionContext) -> JsResult<JsPromise> {\n    let nums = cx\n        .argument::<JsFunction>(0)?\n        .call_with(&cx)\n        .apply::<JsPromise, _>(&mut cx)?\n        .to_future(&mut cx, |mut cx, nums| {\n            let nums = nums\n                .or_throw(&mut cx)?\n                .downcast_or_throw::<JsTypedArray<f64>, _>(&mut cx)?\n                .as_slice(&cx)\n                .to_vec();\n\n            Ok(nums)\n        })?;\n\n    let (deferred, promise) = cx.promise();\n    let channel = cx.channel();\n    let runtime = runtime(&mut cx)?;\n\n    runtime.spawn(async move {\n        let result = nums.await.map(|nums| nums.into_iter().sum::<f64>());\n\n        deferred.settle_with(&channel, move |mut cx| {\n            let result = result.or_throw(&mut cx)?;\n\n            Ok(cx.number(result))\n        });\n    });\n\n    Ok(promise)\n}\n\n#[neon::export]\nasync fn async_fn_add(a: f64, b: f64) -> f64 {\n    a + b\n}\n\n#[neon::export(async)]\nfn async_add(a: f64, b: f64) -> impl Future<Output = f64> {\n    async move { a + b }\n}\n\n#[neon::export]\nasync fn async_fn_div(a: f64, b: f64) -> Result<f64, Error> {\n    if b == 0.0 {\n        return Err(Error::from(\"Divide by zero\"));\n    }\n\n    Ok(a / b)\n}\n\n#[neon::export(async)]\nfn async_div(cx: &mut FunctionContext) -> NeonResult<impl Future<Output = Result<f64, Error>>> {\n    let (a, b): (f64, f64) = cx.args()?;\n\n    Ok(async move {\n        if b == 0.0 {\n            return Err(Error::from(\"Divide by zero\"));\n        }\n\n        Ok(a / b)\n    })\n}\n\n#[neon::export(async)]\nfn async_with_events(\n    cx: &mut FunctionContext,\n    Json(data): Json<Vec<(f64, f64)>>,\n) -> NeonResult<impl Future<Output = impl for<'cx> TryIntoJs<'cx>>> {\n    fn emit(cx: &mut Cx, state: &str) -> NeonResult<()> {\n        cx.global::<JsObject>(\"process\")?\n            .call_method_with(cx, \"emit\")?\n            .arg(cx.string(\"async_with_events\"))\n            .arg(cx.string(state))\n            .exec(cx)\n    }\n\n    emit(cx, \"start\")?;\n\n    Ok(async move {\n        let res = data.into_iter().map(|(a, b)| a * b).collect::<Vec<_>>();\n\n        extract::with(move |cx| -> NeonResult<_> {\n            emit(cx, \"end\")?;\n            res.try_into_js(cx)\n        })\n    })\n}\n\n#[neon::export]\nasync fn await_callback(ch: Channel, cb: Root<JsFunction>) -> Result<Root<JsObject>, Error> {\n    let res = ch\n        .send(move |mut cx| {\n            let this = cx.undefined();\n\n            cb.into_inner(&mut cx)\n                .call(&mut cx, this, [])\n                .and_then(|v| v.downcast_or_throw::<JsObject, _>(&mut cx))\n                .map(|v| v.root(&mut cx))\n        })\n        .await?;\n\n    Ok(res)\n}\n"
  },
  {
    "path": "test/napi/src/js/numbers.rs",
    "content": "use neon::prelude::*;\n\npub fn return_js_number(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    Ok(cx.number(9000_f64))\n}\n\npub fn return_large_js_number(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    Ok(cx.number(4294967296_f64))\n}\n\npub fn return_negative_js_number(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    Ok(cx.number(-9000_f64))\n}\n\npub fn return_float_js_number(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    Ok(cx.number(1.4747_f64))\n}\n\npub fn return_negative_float_js_number(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    Ok(cx.number(-1.4747_f64))\n}\n\npub fn accept_and_return_js_number(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let number: Handle<JsNumber> = cx.argument(0)?;\n    Ok(number)\n}\n\npub fn accept_and_return_large_js_number(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let number: Handle<JsNumber> = cx.argument(0)?;\n    Ok(number)\n}\n\npub fn accept_and_return_float_js_number(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let number: Handle<JsNumber> = cx.argument(0)?;\n    Ok(number)\n}\n\npub fn accept_and_return_negative_js_number(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let number: Handle<JsNumber> = cx.argument(0)?;\n    Ok(number)\n}\n"
  },
  {
    "path": "test/napi/src/js/objects.rs",
    "content": "use std::borrow::Cow;\n\nuse neon::{prelude::*, types::buffer::TypedArray};\n\npub fn return_js_global_object(mut cx: FunctionContext) -> JsResult<JsObject> {\n    Ok(cx.global_object())\n}\n\npub fn return_js_object(mut cx: FunctionContext) -> JsResult<JsObject> {\n    Ok(cx.empty_object())\n}\n\npub fn return_js_object_with_mixed_content(mut cx: FunctionContext) -> JsResult<JsObject> {\n    let js_object: Handle<JsObject> = cx.empty_object();\n    let n = cx.number(9000.0);\n    js_object.set(&mut cx, \"number\", n)?;\n    let s = cx.string(\"hello node\");\n    js_object.set(&mut cx, \"string\", s)?;\n    Ok(js_object)\n}\n\npub fn return_js_object_with_number(mut cx: FunctionContext) -> JsResult<JsObject> {\n    let js_object: Handle<JsObject> = cx.empty_object();\n    let n = cx.number(9000.0);\n    js_object.set(&mut cx, \"number\", n)?;\n    Ok(js_object)\n}\n\npub fn return_js_object_with_string(mut cx: FunctionContext) -> JsResult<JsObject> {\n    let js_object: Handle<JsObject> = cx.empty_object();\n    let s = cx.string(\"hello node\");\n    js_object.set(&mut cx, \"string\", s)?;\n    Ok(js_object)\n}\n\npub fn freeze_js_object(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let obj: Handle<JsObject> = cx.argument::<JsObject>(0)?;\n    match obj.freeze(&mut cx) {\n        Ok(_) => Ok(cx.undefined()),\n        Err(e) => cx.throw_error(e.to_string()),\n    }\n}\n\npub fn seal_js_object(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let obj: Handle<JsObject> = cx.argument::<JsObject>(0)?;\n    match obj.seal(&mut cx) {\n        Ok(_) => Ok(cx.undefined()),\n        Err(e) => cx.throw_error(e.to_string()),\n    }\n}\n\n// Accepts either a `JsString` or `JsBuffer` and returns the contents as\n// as bytes; avoids copying.\nfn get_bytes<'cx, 'a, C>(cx: &'a mut C, v: Handle<JsValue>) -> NeonResult<Cow<'a, [u8]>>\nwhere\n    C: Context<'cx>,\n{\n    if let Ok(v) = v.downcast::<JsString, _>(cx) {\n        return Ok(Cow::Owned(v.value(cx).into_bytes()));\n    }\n\n    if let Ok(v) = v.downcast::<JsBuffer, _>(cx) {\n        return Ok(Cow::Borrowed(v.as_slice(cx)));\n    }\n\n    cx.throw_type_error(\"Value must be a string or Buffer\")\n}\n\npub fn byte_length(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let v = cx.argument::<JsValue>(0)?;\n    let bytes = get_bytes(&mut cx, v)?;\n\n    // `v` is dropped here, but `bytes` is still valid since the data is on the V8 heap\n\n    let len = bytes.len();\n\n    Ok(cx.number(len as f64))\n}\n\npub fn call_nullary_method(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let obj: Handle<JsObject> = cx.argument::<JsObject>(0)?;\n    obj.call_method_with(&mut cx, \"nullary\")?.apply(&mut cx)\n}\n\npub fn call_unary_method(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let obj: Handle<JsObject> = cx.argument::<JsObject>(0)?;\n    let x: Handle<JsNumber> = cx.argument::<JsNumber>(1)?;\n    obj.call_method_with(&mut cx, \"unary\")?\n        .arg(x)\n        .apply(&mut cx)\n}\n\npub fn call_symbol_method(mut cx: FunctionContext) -> JsResult<JsString> {\n    let obj: Handle<JsObject> = cx.argument::<JsObject>(0)?;\n    let sym: Handle<JsValue> = cx.argument::<JsValue>(1)?;\n    obj.call_method_with(&mut cx, sym)?.apply(&mut cx)\n}\n\npub fn get_property_with_prop(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let obj: Handle<JsObject> = cx.argument::<JsObject>(0)?;\n    let n: f64 = obj.prop(&mut cx, \"number\").get()?;\n    Ok(cx.number(n))\n}\n\npub fn set_property_with_prop(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let obj: Handle<JsObject> = cx.argument::<JsObject>(0)?;\n    obj.prop(&mut cx, \"number\").set(42)?;\n    Ok(cx.undefined())\n}\n\npub fn call_methods_with_prop(mut cx: FunctionContext) -> JsResult<JsString> {\n    let obj: Handle<JsObject> = cx.argument::<JsObject>(0)?;\n    obj.prop(&mut cx, \"setName\")\n        .bind()?\n        .arg(\"Wonder Woman\")?\n        .exec()?;\n    obj.prop(&mut cx, \"toString\").bind()?.call()\n}\n\npub fn call_non_method_with_prop(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let obj: Handle<JsObject> = cx.argument::<JsObject>(0)?;\n    obj.prop(&mut cx, \"number\").bind()?.exec()?;\n    Ok(cx.undefined())\n}\n"
  },
  {
    "path": "test/napi/src/js/strings.rs",
    "content": "use neon::{prelude::*, reflect::eval};\n\npub fn return_js_string(mut cx: FunctionContext) -> JsResult<JsString> {\n    Ok(cx.string(\"hello node\"))\n}\n\npub fn return_js_string_utf16(mut cx: FunctionContext) -> JsResult<JsTypedArray<u16>> {\n    let raw = \"hello 🥹\".encode_utf16().collect::<Vec<_>>();\n    JsTypedArray::from_slice(&mut cx, &raw)\n}\n\npub fn return_length_utf8(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let value = cx.argument::<JsString>(0)?.value(&mut cx);\n    Ok(cx.number(value.len() as f64))\n}\n\npub fn return_length_utf16(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let value = cx.argument::<JsString>(0)?.to_utf16(&mut cx);\n    Ok(cx.number(value.len() as f64))\n}\n\npub fn run_string_as_script(mut cx: FunctionContext) -> JsResult<JsValue> {\n    let string_script = cx.argument::<JsString>(0)?;\n    eval(&mut cx, string_script)\n}\n"
  },
  {
    "path": "test/napi/src/js/threads.rs",
    "content": "use std::{cell::RefCell, sync::Arc, time::Duration};\n\nuse neon::{\n    prelude::*,\n    types::{buffer::TypedArray, extract::Error},\n};\n\npub fn useless_root(mut cx: FunctionContext) -> JsResult<JsObject> {\n    let object = cx.argument::<JsObject>(0)?;\n    let root = object.root(&mut cx);\n    let object = root.into_inner(&mut cx);\n\n    Ok(object)\n}\n\npub fn thread_callback(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let callback = cx.argument::<JsFunction>(0)?.root(&mut cx);\n    let channel = cx.channel();\n\n    std::thread::spawn(move || {\n        channel.send(move |mut cx| callback.into_inner(&mut cx).call_with(&cx).exec(&mut cx))\n    });\n\n    Ok(cx.undefined())\n}\n\npub fn multi_threaded_callback(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let n = cx.argument::<JsNumber>(0)?.value(&mut cx);\n    let callback = cx.argument::<JsFunction>(1)?.root(&mut cx);\n    let channel = Arc::new(cx.channel());\n\n    for i in 0..(n as usize) {\n        let callback = callback.clone(&mut cx);\n        let channel = Arc::clone(&channel);\n\n        std::thread::spawn(move || {\n            channel.send(move |mut cx| {\n                callback\n                    .into_inner(&mut cx)\n                    .call_with(&cx)\n                    .arg(cx.number(i as f64))\n                    .exec(&mut cx)\n            })\n        });\n    }\n\n    callback.drop(&mut cx);\n\n    Ok(cx.undefined())\n}\n\ntype BoxedGreeter = JsBox<RefCell<AsyncGreeter>>;\n\npub struct AsyncGreeter {\n    greeting: String,\n    callback: Root<JsFunction>,\n    shutdown: Option<Root<JsFunction>>,\n    channel: Arc<Channel>,\n}\n\nimpl AsyncGreeter {\n    fn greet<'a, C: Context<'a>>(&self, mut cx: C) -> JsResult<'a, JsUndefined> {\n        let greeting = self.greeting.clone();\n        let callback = self.callback.clone(&mut cx);\n        let channel = Arc::clone(&self.channel);\n\n        std::thread::spawn(move || {\n            channel.send(|mut cx| {\n                callback\n                    .into_inner(&mut cx)\n                    .call_with(&cx)\n                    .arg(cx.string(greeting))\n                    .exec(&mut cx)\n            })\n        });\n\n        Ok(cx.undefined())\n    }\n}\n\nimpl Finalize for AsyncGreeter {\n    fn finalize<'a, C: Context<'a>>(self, cx: &mut C) {\n        let Self {\n            callback, shutdown, ..\n        } = self;\n\n        if let Some(shutdown) = shutdown {\n            let _ = shutdown.into_inner(cx).call_with(cx).exec(cx);\n        }\n\n        callback.drop(cx);\n    }\n}\n\npub fn greeter_new(mut cx: FunctionContext) -> JsResult<BoxedGreeter> {\n    let greeting = cx.argument::<JsString>(0)?.value(&mut cx);\n    let callback = cx.argument::<JsFunction>(1)?.root(&mut cx);\n    let shutdown = cx.argument_opt(2);\n\n    let channel = cx.channel();\n    let shutdown = shutdown\n        .map(|v| v.downcast_or_throw::<JsFunction, _>(&mut cx))\n        .transpose()?\n        .map(|v| v.root(&mut cx));\n\n    let greeter = cx.boxed(RefCell::new(AsyncGreeter {\n        greeting,\n        callback,\n        shutdown,\n        channel: Arc::new(channel),\n    }));\n\n    Ok(greeter)\n}\n\npub fn greeter_greet(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let greeter = cx.argument::<BoxedGreeter>(0)?;\n    let greeter = greeter.borrow();\n\n    greeter.greet(cx)\n}\n\npub fn leak_channel(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let channel = Box::new({\n        let mut channel = cx.channel();\n        channel.unref(&mut cx);\n        channel\n    });\n\n    Box::leak(channel);\n\n    Ok(cx.undefined())\n}\n\npub fn drop_global_queue(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    struct Wrapper {\n        callback: Option<Root<JsFunction>>,\n        channel: Channel,\n    }\n\n    impl Finalize for Wrapper {}\n\n    // To verify that the type is dropped on the global drop queue, the callback\n    // is called from the `Drop` impl on `Wrapper`\n    impl Drop for Wrapper {\n        fn drop(&mut self) {\n            if let Some(callback) = self.callback.take() {\n                self.channel.send(|mut cx| {\n                    callback\n                        .into_inner(&mut cx)\n                        .call_with(&cx)\n                        .arg(cx.undefined())\n                        .exec(&mut cx)\n                });\n            }\n        }\n    }\n\n    let callback = cx.argument::<JsFunction>(0)?.root(&mut cx);\n    let channel = cx.channel();\n\n    let wrapper = cx.boxed(Wrapper {\n        callback: Some(callback),\n        channel,\n    });\n\n    // Put the `Wrapper` instance in a `Root` and drop it\n    // Without the global drop queue, this will panic\n    let _ = wrapper.root(&mut cx);\n\n    Ok(cx.undefined())\n}\n\npub fn channel_join(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    // Function to fetch a message for processing\n    let get_message = cx.argument::<JsFunction>(0)?.root(&mut cx);\n    // Callback into JavaScript with completion\n    let callback = cx.argument::<JsFunction>(1)?.root(&mut cx);\n    let channel = cx.channel();\n\n    // Spawn a Rust thread to stop blocking the event loop\n    std::thread::spawn(move || {\n        // Give a chance for the data to change\n        std::thread::sleep(Duration::from_millis(100));\n\n        // Get the current message\n        let message = channel\n            .send(move |mut cx| {\n                let this = cx.undefined();\n\n                get_message\n                    .into_inner(&mut cx)\n                    .call(&mut cx, this, [])?\n                    .downcast_or_throw::<JsString, _>(&mut cx)\n                    .map(|v| v.value(&mut cx))\n            })\n            .join()\n            .unwrap();\n\n        // Process the message\n        let response = format!(\"Received: {message}\");\n\n        // Call back to JavaScript with the response\n        channel.send(move |mut cx| {\n            let this = cx.undefined();\n            let args = [cx.string(response).upcast()];\n\n            callback.into_inner(&mut cx).call(&mut cx, this, args)?;\n\n            Ok(())\n        });\n    });\n\n    Ok(cx.undefined())\n}\n\npub fn sum(mut cx: FunctionContext) -> JsResult<JsPromise> {\n    let nums = cx.argument::<JsTypedArray<f64>>(0)?.as_slice(&cx).to_vec();\n\n    let promise = cx\n        .task(move || nums.into_iter().sum())\n        .promise(|mut cx, n: f64| Ok(cx.number(n)));\n\n    Ok(promise)\n}\n\npub fn sum_manual_promise(mut cx: FunctionContext) -> JsResult<JsPromise> {\n    let nums = cx.argument::<JsTypedArray<f64>>(0)?.as_slice(&cx).to_vec();\n\n    let (deferred, promise) = cx.promise();\n\n    cx.task(move || nums.into_iter().sum())\n        .and_then(move |mut cx, n: f64| {\n            let n = cx.number(n);\n            deferred.resolve(&mut cx, n);\n            Ok(())\n        });\n\n    Ok(promise)\n}\n\npub fn sum_rust_thread(mut cx: FunctionContext) -> JsResult<JsPromise> {\n    let nums = cx.argument::<JsTypedArray<f64>>(0)?.as_slice(&cx).to_vec();\n\n    let channel = cx.channel();\n    let (deferred, promise) = cx.promise();\n\n    std::thread::spawn(move || {\n        let n: f64 = nums.into_iter().sum();\n\n        deferred.settle_with(&channel, move |mut cx| Ok(cx.number(n)));\n    });\n\n    Ok(promise)\n}\n\npub fn leak_promise(mut cx: FunctionContext) -> JsResult<JsPromise> {\n    let (_, promise) = cx.promise();\n\n    Ok(promise)\n}\n\npub fn channel_panic(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let msg = cx.argument::<JsString>(0)?.value(&mut cx);\n    let channel = cx.channel();\n\n    std::thread::spawn(move || {\n        channel.send(move |_| -> NeonResult<()> {\n            panic!(\"{}\", msg);\n        })\n    });\n\n    Ok(cx.undefined())\n}\n\npub fn channel_throw(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let msg = cx.argument::<JsString>(0)?.value(&mut cx);\n    let channel = cx.channel();\n\n    std::thread::spawn(move || {\n        channel.send(move |mut cx| {\n            cx.throw_error(msg)?;\n            Ok(())\n        })\n    });\n\n    Ok(cx.undefined())\n}\n\npub fn channel_panic_throw(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let msg = cx.argument::<JsString>(0)?.value(&mut cx);\n    let channel = cx.channel();\n\n    std::thread::spawn(move || {\n        channel.send(move |mut cx| {\n            // Throw an exception, but ignore the `Err(Throw)`\n            let _ = cx.throw_error::<_, ()>(msg);\n            // Attempting to throw another error while already throwing should `panic`\n            cx.throw_error(\"Unreachable\")?;\n\n            Ok(())\n        })\n    });\n\n    Ok(cx.undefined())\n}\n\nstruct CustomPanic(String);\n\npub fn channel_custom_panic(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let msg = cx.argument::<JsString>(0)?.value(&mut cx);\n    let channel = cx.channel();\n\n    std::thread::spawn(move || {\n        channel.send(move |_| -> NeonResult<()> {\n            std::panic::panic_any(CustomPanic(msg));\n        })\n    });\n\n    Ok(cx.undefined())\n}\n\npub fn custom_panic_downcast(mut cx: FunctionContext) -> JsResult<JsString> {\n    let panic = cx.argument::<JsBox<CustomPanic>>(0)?;\n\n    Ok(cx.string(&panic.0))\n}\n\npub fn task_panic_execute(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let msg = cx.argument::<JsString>(0)?.value(&mut cx);\n\n    cx.task(move || panic!(\"{}\", msg)).and_then(|_, _| Ok(()));\n\n    Ok(cx.undefined())\n}\n\npub fn task_panic_complete(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let msg = cx.argument::<JsString>(0)?.value(&mut cx);\n\n    cx.task(|| {}).and_then(move |_, _| panic!(\"{}\", msg));\n\n    Ok(cx.undefined())\n}\n\npub fn task_throw(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let msg = cx.argument::<JsString>(0)?.value(&mut cx);\n\n    cx.task(|| {}).and_then(move |mut cx, _| {\n        cx.throw_error(msg)?;\n        Ok(())\n    });\n\n    Ok(cx.undefined())\n}\n\npub fn task_panic_throw(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let msg = cx.argument::<JsString>(0)?.value(&mut cx);\n\n    cx.task(|| {}).and_then(move |mut cx, _| {\n        // Throw an exception, but ignore the `Err(Throw)`\n        let _ = cx.throw_error::<_, ()>(msg);\n        // Attempting to throw another error while already throwing should `panic`\n        cx.throw_error(\"Unreachable\")?;\n\n        Ok(())\n    });\n\n    Ok(cx.undefined())\n}\n\npub fn task_custom_panic(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let msg = cx.argument::<JsString>(0)?.value(&mut cx);\n\n    cx.task(move || std::panic::panic_any(CustomPanic(msg)))\n        .and_then(|_, _| Ok(()));\n\n    Ok(cx.undefined())\n}\n\npub fn task_reject_promise(mut cx: FunctionContext) -> JsResult<JsPromise> {\n    let msg = cx.argument::<JsString>(0)?.value(&mut cx);\n    let promise = cx\n        .task(move || {})\n        .promise::<JsValue, _>(move |mut cx, _| cx.throw_error(msg));\n\n    Ok(promise)\n}\n\npub fn task_panic_execute_promise(mut cx: FunctionContext) -> JsResult<JsPromise> {\n    let msg = cx.argument::<JsString>(0)?.value(&mut cx);\n    let promise = cx\n        .task(move || panic!(\"{}\", msg))\n        .promise(|mut cx, _| Ok(cx.undefined()));\n\n    Ok(promise)\n}\n\npub fn task_panic_complete_promise(mut cx: FunctionContext) -> JsResult<JsPromise> {\n    let msg = cx.argument::<JsString>(0)?.value(&mut cx);\n    let promise = cx\n        .task(|| ())\n        .promise::<JsValue, _>(move |_, _| panic!(\"{}\", msg));\n\n    Ok(promise)\n}\n\npub fn task_panic_throw_promise(mut cx: FunctionContext) -> JsResult<JsPromise> {\n    let msg = cx.argument::<JsString>(0)?.value(&mut cx);\n    let promise = cx.task(|| ()).promise(move |mut cx, _| {\n        // Throw an exception, but ignore the `Err(Throw)`\n        let _ = cx.throw_error::<_, ()>(msg);\n        // Attempting to throw another error while already throwing should `panic`\n        cx.throw_error(\"Unreachable\")?;\n\n        Ok(cx.undefined())\n    });\n\n    Ok(promise)\n}\n\npub fn deferred_settle_with_throw(mut cx: FunctionContext) -> JsResult<JsPromise> {\n    let msg = cx.argument::<JsString>(0)?.value(&mut cx);\n    let (deferred, promise) = cx.promise();\n    let channel = cx.channel();\n\n    std::thread::spawn(move || {\n        deferred.try_settle_with(&channel, move |mut cx| {\n            cx.throw_error(msg)?;\n\n            Ok(cx.undefined())\n        })\n    });\n\n    Ok(promise)\n}\n\npub fn deferred_settle_with_panic(mut cx: FunctionContext) -> JsResult<JsPromise> {\n    let msg = cx.argument::<JsString>(0)?.value(&mut cx);\n    let (deferred, promise) = cx.promise();\n    let channel = cx.channel();\n\n    std::thread::spawn(move || {\n        deferred.try_settle_with::<JsValue, _>(&channel, move |_| {\n            panic!(\"{}\", msg);\n        })\n    });\n\n    Ok(promise)\n}\n\npub fn deferred_settle_with_panic_throw(mut cx: FunctionContext) -> JsResult<JsPromise> {\n    let msg = cx.argument::<JsString>(0)?.value(&mut cx);\n    let (deferred, promise) = cx.promise();\n    let channel = cx.channel();\n\n    std::thread::spawn(move || {\n        deferred.try_settle_with(&channel, move |mut cx| {\n            // Throw an exception, but ignore the `Err(Throw)`\n            let _ = cx.throw_error::<_, ()>(msg);\n            // Attempting to throw another error while already throwing should `panic`\n            cx.throw_error(\"Unreachable\")?;\n\n            Ok(cx.undefined())\n        })\n    });\n\n    Ok(promise)\n}\n\n#[neon::export(task)]\nfn block_task_callback(ch: Channel, cb: Root<JsFunction>) -> Result<Root<JsObject>, Error> {\n    let res = ch\n        .send(move |mut cx| {\n            let this = cx.undefined();\n\n            cb.into_inner(&mut cx)\n                .call(&mut cx, this, [])\n                .and_then(|v| v.downcast_or_throw::<JsObject, _>(&mut cx))\n                .map(|v| v.root(&mut cx))\n        })\n        .join()?;\n\n    Ok(res)\n}\n\n#[neon::export]\nfn settle_hello_world<'cx>(cx: &mut Cx<'cx>) -> JsResult<'cx, JsPromise> {\n    let (d, promise) = cx.promise();\n    let ch = cx.channel();\n\n    std::thread::spawn(move || {\n        d.settle(&ch, \"Hello, World!\");\n    });\n\n    Ok(promise)\n}\n"
  },
  {
    "path": "test/napi/src/js/typedarrays.rs",
    "content": "use neon::{\n    prelude::*,\n    types::buffer::{Binary, BorrowError, TypedArray},\n};\n\npub fn return_array_buffer(mut cx: FunctionContext) -> JsResult<JsArrayBuffer> {\n    let b: Handle<JsArrayBuffer> = cx.array_buffer(16)?;\n    Ok(b)\n}\n\npub fn return_array_buffer_from_slice(mut cx: FunctionContext) -> JsResult<JsArrayBuffer> {\n    let len = cx.argument::<JsNumber>(0)?.value(&mut cx) as usize;\n    let v = (0..len).map(|i| i as u8).collect::<Vec<_>>();\n\n    JsArrayBuffer::from_slice(&mut cx, &v)\n}\n\npub fn read_array_buffer_with_lock(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let buf = cx.argument::<JsTypedArray<u32>>(0)?;\n    let i = cx.argument::<JsNumber>(1)?.value(&mut cx) as usize;\n    let lock = cx.lock();\n    let n = buf.try_borrow(&lock).map(|buf| buf[i]).or_throw(&mut cx)?;\n\n    Ok(cx.number(n))\n}\n\npub fn read_array_buffer_with_borrow(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let buf = cx.argument::<JsArrayBuffer>(0)?;\n    let i = cx.argument::<JsNumber>(1)?.value(&mut cx) as usize;\n    let n = buf.as_slice(&cx)[i];\n\n    Ok(cx.number(n as f64))\n}\n\npub fn write_array_buffer_with_lock(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let mut b: Handle<JsArrayBuffer> = cx.argument(0)?;\n    let i = cx.argument::<JsNumber>(1)?.value(&mut cx) as u32 as usize;\n    let x = cx.argument::<JsNumber>(2)?.value(&mut cx) as u8;\n    let lock = cx.lock();\n\n    b.try_borrow_mut(&lock)\n        .map(|mut slice| {\n            slice[i] = x;\n        })\n        .or_throw(&mut cx)?;\n\n    Ok(cx.undefined())\n}\n\npub fn write_array_buffer_with_borrow_mut(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let mut buf = cx.argument::<JsArrayBuffer>(0)?;\n    let i = cx.argument::<JsNumber>(1)?.value(&mut cx) as usize;\n    let n = cx.argument::<JsNumber>(2)?.value(&mut cx) as u8;\n\n    buf.as_mut_slice(&mut cx)[i] = n;\n\n    Ok(cx.undefined())\n}\n\npub fn read_typed_array_with_borrow(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let buf = cx.argument::<JsTypedArray<i32>>(0)?;\n    let i = cx.argument::<JsNumber>(1)?.value(&mut cx) as usize;\n    let n = buf.as_slice(&cx)[i];\n\n    Ok(cx.number(n as f64))\n}\n\npub fn write_typed_array_with_borrow_mut(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let mut buf = cx.argument::<JsTypedArray<i32>>(0)?;\n    let i = cx.argument::<JsNumber>(1)?.value(&mut cx) as usize;\n    let n = cx.argument::<JsNumber>(2)?.value(&mut cx) as i32;\n\n    buf.as_mut_slice(&mut cx)[i] = n;\n\n    Ok(cx.undefined())\n}\n\npub fn read_u8_typed_array(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let buf = cx.argument::<JsTypedArray<u8>>(0)?;\n    let i = cx.argument::<JsNumber>(1)?.value(&mut cx) as usize;\n    let n = buf.as_slice(&cx)[i];\n\n    Ok(cx.number(n as f64))\n}\n\npub fn copy_typed_array(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let source = cx.argument::<JsTypedArray<u32>>(0)?;\n    let mut dest = cx.argument::<JsTypedArray<u32>>(1)?;\n    let mut run = || -> Result<_, BorrowError> {\n        let lock = cx.lock();\n        let source = source.try_borrow(&lock)?;\n        let mut dest = dest.try_borrow_mut(&lock)?;\n\n        dest.copy_from_slice(&source);\n\n        Ok(())\n    };\n\n    run().or_throw(&mut cx)?;\n\n    Ok(cx.undefined())\n}\n\npub fn return_uninitialized_buffer(mut cx: FunctionContext) -> JsResult<JsBuffer> {\n    let b: Handle<JsBuffer> = unsafe { JsBuffer::uninitialized(&mut cx, 16)? };\n    Ok(b)\n}\n\npub fn return_buffer(mut cx: FunctionContext) -> JsResult<JsBuffer> {\n    let b: Handle<JsBuffer> = cx.buffer(16)?;\n    Ok(b)\n}\n\npub fn return_external_buffer(mut cx: FunctionContext) -> JsResult<JsBuffer> {\n    let data = cx.argument::<JsString>(0)?.value(&mut cx);\n    let buf = JsBuffer::external(&mut cx, data.into_bytes());\n\n    Ok(buf)\n}\n\npub fn return_external_array_buffer(mut cx: FunctionContext) -> JsResult<JsArrayBuffer> {\n    let data = cx.argument::<JsString>(0)?.value(&mut cx);\n    let buf = JsArrayBuffer::external(&mut cx, data.into_bytes());\n\n    Ok(buf)\n}\n\npub fn return_int8array_from_arraybuffer(mut cx: FunctionContext) -> JsResult<JsInt8Array> {\n    let buf = cx.argument::<JsArrayBuffer>(0)?;\n    JsInt8Array::from_buffer(&mut cx, buf)\n}\n\npub fn return_int16array_from_arraybuffer(mut cx: FunctionContext) -> JsResult<JsInt16Array> {\n    let buf = cx.argument::<JsArrayBuffer>(0)?;\n    JsInt16Array::from_buffer(&mut cx, buf)\n}\n\npub fn return_uint32array_from_arraybuffer(mut cx: FunctionContext) -> JsResult<JsUint32Array> {\n    let buf = cx.argument::<JsArrayBuffer>(0)?;\n    JsUint32Array::from_buffer(&mut cx, buf)\n}\n\npub fn return_float64array_from_arraybuffer(mut cx: FunctionContext) -> JsResult<JsFloat64Array> {\n    let buf = cx.argument::<JsArrayBuffer>(0)?;\n    JsFloat64Array::from_buffer(&mut cx, buf)\n}\n\npub fn return_biguint64array_from_arraybuffer(\n    mut cx: FunctionContext,\n) -> JsResult<JsBigUint64Array> {\n    let buf = cx.argument::<JsArrayBuffer>(0)?;\n    JsBigUint64Array::from_buffer(&mut cx, buf)\n}\n\npub fn return_new_int32array(mut cx: FunctionContext) -> JsResult<JsInt32Array> {\n    let len = cx.argument::<JsNumber>(0)?.value(&mut cx) as usize;\n    JsInt32Array::new(&mut cx, len)\n}\n\npub fn return_int32array_from_slice(mut cx: FunctionContext) -> JsResult<JsInt32Array> {\n    let len: Handle<JsNumber> = cx.argument(0)?;\n    let len: f64 = len.value(&mut cx);\n    let len: u32 = len as u32;\n    let mut v: Vec<i32> = Vec::new();\n    for i in 0..len {\n        v.push(i as i32);\n    }\n    let a: Handle<JsInt32Array> = JsInt32Array::from_slice(&mut cx, &v)?;\n    Ok(a)\n}\n\npub fn return_uint32array_from_arraybuffer_region(\n    mut cx: FunctionContext,\n) -> JsResult<JsUint32Array> {\n    let buf = cx.argument::<JsArrayBuffer>(0)?;\n    let offset = cx.argument::<JsNumber>(1)?;\n    let offset = offset.value(&mut cx);\n    let len = cx.argument::<JsNumber>(2)?;\n    let len = len.value(&mut cx);\n    JsUint32Array::from_region(&mut cx, &buf.region(offset as usize, len as usize))\n}\n\npub fn get_arraybuffer_byte_length(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let buf = cx.argument::<JsArrayBuffer>(0)?;\n    let size = buf.size(&mut cx);\n    let n = cx.number(size as u32);\n    Ok(n)\n}\n\nfn typed_array_info<'cx, C, T: Binary>(\n    cx: &mut C,\n    a: Handle<'cx, JsTypedArray<T>>,\n) -> JsResult<'cx, JsObject>\nwhere\n    C: Context<'cx>,\n    JsTypedArray<T>: Value,\n{\n    let offset = a.offset(cx);\n    let offset = cx.number(offset as u32);\n\n    let len = a.len(cx);\n    let len = cx.number(len as u32);\n\n    let size = a.size(cx);\n    let size = cx.number(size as u32);\n\n    let buffer = a.buffer(cx);\n\n    let obj = cx.empty_object();\n\n    obj.set(cx, \"byteOffset\", offset)?;\n    obj.set(cx, \"length\", len)?;\n    obj.set(cx, \"byteLength\", size)?;\n    obj.set(cx, \"buffer\", buffer)?;\n\n    Ok(obj)\n}\n\nfn detach_and_then<'cx, F>(mut cx: FunctionContext<'cx>, f: F) -> JsResult<'cx, JsObject>\nwhere\n    F: FnOnce(\n        &mut FunctionContext<'cx>,\n        Handle<'cx, JsUint32Array>,\n    ) -> NeonResult<Option<Handle<'cx, JsUint32Array>>>,\n{\n    let mut a = cx.argument::<JsUint32Array>(0)?;\n    let detach = cx.argument::<JsFunction>(1)?;\n\n    let before = typed_array_info(&mut cx, a)?;\n\n    detach.call_with(&cx).arg(a).exec(&mut cx)?;\n\n    if let Some(new_array) = f(&mut cx, a)? {\n        a = new_array;\n    }\n\n    let after = typed_array_info(&mut cx, a)?;\n\n    let result = cx.empty_object();\n\n    result.set(&mut cx, \"before\", before)?;\n    result.set(&mut cx, \"after\", after)?;\n\n    Ok(result)\n}\n\npub fn detach_same_handle(cx: FunctionContext) -> JsResult<JsObject> {\n    detach_and_then(cx, |_, _| Ok(None))\n}\n\npub fn detach_and_escape(cx: FunctionContext) -> JsResult<JsObject> {\n    detach_and_then(cx, |cx, a| {\n        let a = cx.compute_scoped(|_| Ok(a))?;\n        Ok(Some(a))\n    })\n}\n\npub fn detach_and_cast(cx: FunctionContext) -> JsResult<JsObject> {\n    detach_and_then(cx, |cx, a| {\n        let v = a.upcast::<JsValue>();\n        let a = v.downcast_or_throw::<JsUint32Array, _>(cx)?;\n        Ok(Some(a))\n    })\n}\n\npub fn detach_and_unroot(cx: FunctionContext) -> JsResult<JsObject> {\n    detach_and_then(cx, |cx, a| {\n        let root = a.root(cx);\n        let a = root.into_inner(cx);\n        Ok(Some(a))\n    })\n}\n\npub fn get_typed_array_info(mut cx: FunctionContext) -> JsResult<JsObject> {\n    let x = cx.argument::<JsValue>(0)?;\n\n    if let Ok(a) = x.downcast::<JsTypedArray<u8>, _>(&mut cx) {\n        typed_array_info(&mut cx, a)\n    } else if let Ok(a) = x.downcast::<JsTypedArray<i8>, _>(&mut cx) {\n        typed_array_info(&mut cx, a)\n    } else if let Ok(a) = x.downcast::<JsTypedArray<u16>, _>(&mut cx) {\n        typed_array_info(&mut cx, a)\n    } else if let Ok(a) = x.downcast::<JsTypedArray<i16>, _>(&mut cx) {\n        typed_array_info(&mut cx, a)\n    } else if let Ok(a) = x.downcast::<JsTypedArray<u32>, _>(&mut cx) {\n        typed_array_info(&mut cx, a)\n    } else if let Ok(a) = x.downcast::<JsTypedArray<i32>, _>(&mut cx) {\n        typed_array_info(&mut cx, a)\n    } else if let Ok(a) = x.downcast::<JsTypedArray<u64>, _>(&mut cx) {\n        typed_array_info(&mut cx, a)\n    } else if let Ok(a) = x.downcast::<JsTypedArray<i64>, _>(&mut cx) {\n        typed_array_info(&mut cx, a)\n    } else if let Ok(a) = x.downcast::<JsTypedArray<f32>, _>(&mut cx) {\n        typed_array_info(&mut cx, a)\n    } else if let Ok(a) = x.downcast::<JsTypedArray<f64>, _>(&mut cx) {\n        typed_array_info(&mut cx, a)\n    } else {\n        cx.throw_type_error(\"expected a typed array\")\n    }\n}\n\npub fn build_f32_region(mut cx: FunctionContext) -> JsResult<JsValue> {\n    let buf: Handle<JsArrayBuffer> = cx.argument(0)?;\n    let offset: Handle<JsNumber> = cx.argument(1)?;\n    let offset: usize = offset.value(&mut cx) as u32 as usize;\n    let len: Handle<JsNumber> = cx.argument(2)?;\n    let len: usize = len.value(&mut cx) as u32 as usize;\n    let convert: Handle<JsBoolean> = cx.argument(3)?;\n    let convert: bool = convert.value(&mut cx);\n\n    let region = buf.region::<f32>(offset, len);\n\n    if convert {\n        let arr = region.to_typed_array(&mut cx)?;\n        Ok(arr.upcast())\n    } else {\n        Ok(cx.undefined().upcast())\n    }\n}\n\npub fn build_f64_region(mut cx: FunctionContext) -> JsResult<JsValue> {\n    let buf: Handle<JsArrayBuffer> = cx.argument(0)?;\n    let offset: Handle<JsNumber> = cx.argument(1)?;\n    let offset: usize = offset.value(&mut cx) as u32 as usize;\n    let len: Handle<JsNumber> = cx.argument(2)?;\n    let len: usize = len.value(&mut cx) as u32 as usize;\n    let convert: Handle<JsBoolean> = cx.argument(3)?;\n    let convert: bool = convert.value(&mut cx);\n\n    let region = buf.region::<f64>(offset, len);\n\n    if convert {\n        let arr = region.to_typed_array(&mut cx)?;\n        Ok(arr.upcast())\n    } else {\n        Ok(cx.undefined().upcast())\n    }\n}\n\npub fn read_buffer_with_lock(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let b: Handle<JsBuffer> = cx.argument(0)?;\n    let i = cx.argument::<JsNumber>(1)?.value(&mut cx) as usize;\n    let lock = cx.lock();\n    let x = b\n        .try_borrow(&lock)\n        .map(|slice| slice[i])\n        .or_throw(&mut cx)?;\n\n    Ok(cx.number(x))\n}\n\npub fn read_buffer_with_borrow(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let buf = cx.argument::<JsBuffer>(0)?;\n    let i = cx.argument::<JsNumber>(1)?.value(&mut cx) as usize;\n    let n = buf.as_slice(&cx)[i];\n\n    Ok(cx.number(n as f64))\n}\n\npub fn write_buffer_with_lock(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let mut b: Handle<JsBuffer> = cx.argument(0)?;\n    let i = cx.argument::<JsNumber>(1)?.value(&mut cx) as usize;\n    let x = cx.argument::<JsNumber>(2)?.value(&mut cx) as u8;\n    let lock = cx.lock();\n\n    b.try_borrow_mut(&lock)\n        .map(|mut slice| slice[i] = x)\n        .or_throw(&mut cx)?;\n\n    Ok(cx.undefined())\n}\n\npub fn write_buffer_with_borrow_mut(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let mut buf = cx.argument::<JsBuffer>(0)?;\n    let i = cx.argument::<JsNumber>(1)?.value(&mut cx) as usize;\n    let n = cx.argument::<JsNumber>(2)?.value(&mut cx) as u8;\n\n    buf.as_mut_slice(&mut cx)[i] = n;\n\n    Ok(cx.undefined())\n}\n\npub fn copy_buffer(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let a = cx.argument::<JsTypedArray<u8>>(0)?;\n    let mut b = cx.argument::<JsTypedArray<u8>>(1)?;\n    let a_len = a.as_slice(&cx).len();\n    let b_len = b.as_slice(&cx).len();\n    let n = a_len.min(b_len);\n    let a = a.as_slice(&cx)[..n].to_vec();\n\n    b.as_mut_slice(&mut cx)[..n].copy_from_slice(&a);\n\n    Ok(cx.undefined())\n}\n\npub fn copy_buffer_with_borrow(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    let a = cx.argument::<JsTypedArray<u8>>(0)?;\n    let mut b = cx.argument::<JsTypedArray<u8>>(1)?;\n    let lock = cx.lock();\n    let (Ok(a), Ok(mut b)) = (a.try_borrow(&lock), b.try_borrow_mut(&lock)) else {\n        return cx.throw_error(\"Borrow Error\");\n    };\n\n    let n = a.len().min(b.len());\n\n    b[..n].copy_from_slice(&a);\n    drop((a, b));\n\n    Ok(cx.undefined())\n}\n"
  },
  {
    "path": "test/napi/src/js/types.rs",
    "content": "use neon::prelude::*;\n\npub fn is_string(mut cx: FunctionContext) -> JsResult<JsBoolean> {\n    let val: Handle<JsValue> = cx.argument(0)?;\n    let result = val.is_a::<JsString, _>(&mut cx);\n    Ok(cx.boolean(result))\n}\n\npub fn is_array(mut cx: FunctionContext) -> JsResult<JsBoolean> {\n    let val: Handle<JsValue> = cx.argument(0)?;\n    let result = val.is_a::<JsArray, _>(&mut cx);\n    Ok(cx.boolean(result))\n}\n\npub fn is_array_buffer(mut cx: FunctionContext) -> JsResult<JsBoolean> {\n    let val: Handle<JsValue> = cx.argument(0)?;\n    let result = val.is_a::<JsArrayBuffer, _>(&mut cx);\n    Ok(cx.boolean(result))\n}\n\npub fn is_uint32_array(mut cx: FunctionContext) -> JsResult<JsBoolean> {\n    let val: Handle<JsValue> = cx.argument(0)?;\n    let result = val.is_a::<JsTypedArray<u32>, _>(&mut cx);\n    Ok(cx.boolean(result))\n}\n\npub fn is_boolean(mut cx: FunctionContext) -> JsResult<JsBoolean> {\n    let val: Handle<JsValue> = cx.argument(0)?;\n    let result = val.is_a::<JsBoolean, _>(&mut cx);\n    Ok(cx.boolean(result))\n}\n\npub fn is_buffer(mut cx: FunctionContext) -> JsResult<JsBoolean> {\n    let val: Handle<JsValue> = cx.argument(0)?;\n    let result = val.is_a::<JsBuffer, _>(&mut cx);\n    Ok(cx.boolean(result))\n}\n\npub fn is_error(mut cx: FunctionContext) -> JsResult<JsBoolean> {\n    let val: Handle<JsValue> = cx.argument(0)?;\n    let result = val.is_a::<JsError, _>(&mut cx);\n    Ok(cx.boolean(result))\n}\n\npub fn is_null(mut cx: FunctionContext) -> JsResult<JsBoolean> {\n    let val: Handle<JsValue> = cx.argument(0)?;\n    let result = val.is_a::<JsNull, _>(&mut cx);\n    Ok(cx.boolean(result))\n}\n\npub fn is_number(mut cx: FunctionContext) -> JsResult<JsBoolean> {\n    let val: Handle<JsValue> = cx.argument(0)?;\n    let result = val.is_a::<JsNumber, _>(&mut cx);\n    Ok(cx.boolean(result))\n}\n\npub fn is_object(mut cx: FunctionContext) -> JsResult<JsBoolean> {\n    let val: Handle<JsValue> = cx.argument(0)?;\n    let result = val.is_a::<JsObject, _>(&mut cx);\n    Ok(cx.boolean(result))\n}\n\npub fn is_undefined(mut cx: FunctionContext) -> JsResult<JsBoolean> {\n    let val: Handle<JsValue> = cx.argument(0)?;\n    let is_string = val.is_a::<JsUndefined, _>(&mut cx);\n    Ok(cx.boolean(is_string))\n}\n\npub fn strict_equals(mut cx: FunctionContext) -> JsResult<JsBoolean> {\n    let v1: Handle<JsValue> = cx.argument(0)?;\n    let v2: Handle<JsValue> = cx.argument(1)?;\n    let eq = v1.strict_equals(&mut cx, v2);\n    Ok(cx.boolean(eq))\n}\n"
  },
  {
    "path": "test/napi/src/js/workers.rs",
    "content": "use std::{convert::TryFrom, sync::Mutex, thread, time::Duration};\n\nuse once_cell::sync::{Lazy, OnceCell};\n\nuse neon::prelude::*;\nuse neon::thread::LocalKey;\n\npub fn get_and_replace(mut cx: FunctionContext) -> JsResult<JsValue> {\n    static OBJECT: Lazy<Mutex<Option<Root<JsObject>>>> = Lazy::new(Default::default);\n\n    let mut global = OBJECT.lock().unwrap_or_else(|err| err.into_inner());\n    let next = cx.argument::<JsObject>(0)?.root(&mut cx);\n    let previous = global.replace(next);\n\n    Ok(match previous {\n        None => cx.undefined().upcast(),\n        Some(previous) => previous.into_inner(&mut cx).upcast(),\n    })\n}\n\npub fn get_or_init(mut cx: FunctionContext) -> JsResult<JsObject> {\n    static OBJECT: OnceCell<Root<JsObject>> = OnceCell::new();\n\n    let o = OBJECT.get_or_try_init(|| {\n        cx.argument::<JsFunction>(0)?\n            .call_with(&cx)\n            .apply::<JsObject, _>(&mut cx)\n            .map(|v| v.root(&mut cx))\n    })?;\n\n    Ok(o.to_inner(&mut cx))\n}\n\npub fn get_or_init_clone(mut cx: FunctionContext) -> JsResult<JsObject> {\n    static OBJECT: OnceCell<Root<JsObject>> = OnceCell::new();\n\n    let o = OBJECT.get_or_try_init(|| {\n        cx.argument::<JsFunction>(0)?\n            .call_with(&cx)\n            .apply::<JsObject, _>(&mut cx)\n            .map(|v| v.root(&mut cx))\n    })?;\n\n    // Note: This intentionally uses `clone` instead of `to_inner` in order to\n    // test the `clone` method.\n    Ok(o.clone(&mut cx).into_inner(&mut cx))\n}\n\nstatic THREAD_ID: LocalKey<u32> = LocalKey::new();\n\npub fn get_or_init_thread_id(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let id = cx.argument::<JsNumber>(0)?.value(&mut cx) as u32;\n    let id: &u32 = THREAD_ID.get_or_init(&mut cx, || id);\n    Ok(cx.number(*id))\n}\n\nstatic REENTRANT_LOCAL: LocalKey<u32> = LocalKey::new();\n\npub fn reentrant_try_init(mut cx: FunctionContext) -> JsResult<JsNumber> {\n    let f = cx.argument::<JsFunction>(0)?;\n    let n = REENTRANT_LOCAL.get_or_try_init(&mut cx, |cx| {\n        f.call_with(cx).exec(cx)?;\n        Ok(42)\n    })?;\n    Ok(cx.number(*n))\n}\n\npub fn get_reentrant_value(mut cx: FunctionContext) -> JsResult<JsValue> {\n    let value = REENTRANT_LOCAL.get(&mut cx).cloned();\n    match value {\n        Some(n) => Ok(cx.number(n).upcast()),\n        None => Ok(cx.null().upcast()),\n    }\n}\n\nstatic GLOBAL_OBJECT: LocalKey<Root<JsObject>> = LocalKey::new();\n\npub fn stash_global_object(mut cx: FunctionContext) -> JsResult<JsUndefined> {\n    GLOBAL_OBJECT.get_or_try_init(&mut cx, |cx| {\n        let global = cx.global_object();\n        let global: Root<JsObject> = Root::new(cx, &global);\n        Ok(global)\n    })?;\n    Ok(cx.undefined())\n}\n\npub fn unstash_global_object(mut cx: FunctionContext) -> JsResult<JsValue> {\n    Ok(match GLOBAL_OBJECT.get(&mut cx) {\n        Some(root) => root.to_inner(&mut cx).upcast(),\n        None => cx.null().upcast(),\n    })\n}\n\npub fn reject_after(mut cx: FunctionContext) -> JsResult<JsPromise> {\n    let err = cx.argument::<JsObject>(0)?.root(&mut cx);\n    let ms = cx.argument::<JsNumber>(1)?.value(&mut cx) as i64;\n    let ms = u64::try_from(ms)\n        .or_else(|err| cx.throw_error(err.to_string()))\n        .map(Duration::from_millis)?;\n\n    let promise =\n        cx.task(move || thread::sleep(ms))\n            .promise(move |mut cx, _| -> JsResult<JsValue> {\n                let err = err.into_inner(&mut cx);\n\n                cx.throw(err)\n            });\n\n    Ok(promise)\n}\n\npub struct Channels {\n    _channel_1: Channel,\n    _channel_2: Channel,\n}\nimpl Finalize for Channels {}\n\npub fn box_channels(mut cx: FunctionContext) -> JsResult<JsBox<Channels>> {\n    let channels = Channels {\n        _channel_1: cx.channel(),\n        _channel_2: cx.channel(),\n    };\n\n    Ok(cx.boxed(channels))\n}\n"
  },
  {
    "path": "test/napi/src/lib.rs",
    "content": "use neon::{object::Class, prelude::*};\nuse once_cell::sync::OnceCell;\nuse tokio::runtime::Runtime;\n\nuse crate::js::{\n    arrays::*, boxed::*, coercions::*, date::*, errors::*, functions::*, numbers::*, objects::*,\n    strings::*, threads::*, typedarrays::*, types::*,\n};\n\nmod js {\n    pub mod arrays;\n    pub mod bigint;\n    pub mod boxed;\n    pub mod class;\n    pub mod coercions;\n    pub mod container;\n    pub mod date;\n    pub mod errors;\n    pub mod export;\n    pub mod extract;\n    pub mod functions;\n    pub mod futures;\n    pub mod numbers;\n    pub mod objects;\n    pub mod strings;\n    pub mod threads;\n    pub mod typedarrays;\n    pub mod types;\n    pub mod workers;\n}\n\n#[neon::main]\nfn main(mut cx: ModuleContext) -> NeonResult<()> {\n    let rt = runtime(&mut cx)?;\n\n    neon::set_global_executor(&mut cx, rt).or_else(|_| cx.throw_error(\"executor already set\"))?;\n    neon::registered().export(&mut cx)?;\n\n    assert!(neon::registered().into_iter().next().is_some());\n\n    let greeting = cx.string(\"Hello, World!\");\n    let greeting_copy = greeting.value(&mut cx);\n    let greeting_copy = cx.string(greeting_copy);\n\n    cx.export_value(\"greeting\", greeting)?;\n    cx.export_value(\"greetingCopy\", greeting_copy)?;\n\n    // Global singletons.\n    let undefined = cx.undefined();\n    let null = cx.null();\n    let b_true = cx.boolean(true);\n    let b_false = cx.boolean(false);\n\n    assert!(b_true.value(&mut cx));\n    assert!(!b_false.value(&mut cx));\n\n    cx.export_value(\"undefined\", undefined)?;\n    cx.export_value(\"null\", null)?;\n    cx.export_value(\"true\", b_true)?;\n    cx.export_value(\"false\", b_false)?;\n\n    let one = cx.number(1);\n    let two = cx.number(2.1);\n    assert!((one.value(&mut cx) - 1.0).abs() < f64::EPSILON);\n    assert!((two.value(&mut cx) - 2.1).abs() < f64::EPSILON);\n    cx.export_value(\"one\", one)?;\n    cx.export_value(\"two\", two)?;\n\n    // Plain objects.\n    let rust_created = cx.empty_object();\n    {\n        let a = cx.number(1);\n        // set at name\n        rust_created.set(&mut cx, \"a\", a)?;\n        // set at index\n        rust_created.set(&mut cx, 0, a)?;\n    }\n    {\n        let whatever = cx.boolean(true);\n        rust_created.set(&mut cx, \"whatever\", whatever)?;\n    }\n\n    assert!(\n        ({\n            let v: Handle<JsNumber> = rust_created.get(&mut cx, \"a\")?;\n            v.value(&mut cx)\n        } - 1.0f64)\n            .abs()\n            < f64::EPSILON\n    );\n    assert!(\n        ({\n            let v: Handle<JsNumber> = rust_created.get(&mut cx, 0)?;\n            v.value(&mut cx)\n        } - 1.0f64)\n            .abs()\n            < f64::EPSILON\n    );\n    assert!({\n        let v: Handle<JsBoolean> = rust_created.get(&mut cx, \"whatever\")?;\n        v.value(&mut cx)\n    });\n\n    let property_names = rust_created\n        .get_own_property_names(&mut cx)?\n        .to_vec(&mut cx)?\n        .into_iter()\n        .map(|value| {\n            let string: Handle<JsString> = value.downcast_or_throw(&mut cx)?;\n            Ok(string.value(&mut cx))\n        })\n        .collect::<Result<Vec<_>, _>>()?;\n    assert_eq!(property_names, &[\"0\", \"a\", \"whatever\"]);\n\n    cx.export_value(\"rustCreated\", rust_created)?;\n\n    fn add1(mut cx: FunctionContext) -> JsResult<JsNumber> {\n        let x = cx.argument::<JsNumber>(0)?.value(&mut cx);\n        Ok(cx.number(x + 1.0))\n    }\n\n    cx.export_function(\"add1\", add1)?;\n\n    cx.export_function(\"return_js_string\", return_js_string)?;\n    cx.export_function(\"return_js_string_utf16\", return_js_string_utf16)?;\n    cx.export_function(\"return_length_utf8\", return_length_utf8)?;\n    cx.export_function(\"return_length_utf16\", return_length_utf16)?;\n    cx.export_function(\"run_string_as_script\", run_string_as_script)?;\n\n    cx.export_function(\"return_js_number\", return_js_number)?;\n    cx.export_function(\"return_large_js_number\", return_large_js_number)?;\n    cx.export_function(\"return_negative_js_number\", return_negative_js_number)?;\n    cx.export_function(\"return_float_js_number\", return_float_js_number)?;\n    cx.export_function(\n        \"return_negative_float_js_number\",\n        return_negative_float_js_number,\n    )?;\n    cx.export_function(\"accept_and_return_js_number\", accept_and_return_js_number)?;\n    cx.export_function(\n        \"accept_and_return_large_js_number\",\n        accept_and_return_large_js_number,\n    )?;\n    cx.export_function(\n        \"accept_and_return_float_js_number\",\n        accept_and_return_float_js_number,\n    )?;\n    cx.export_function(\n        \"accept_and_return_negative_js_number\",\n        accept_and_return_negative_js_number,\n    )?;\n\n    cx.export_function(\"return_js_function\", return_js_function)?;\n    cx.export_function(\"call_js_function\", call_js_function)?;\n    cx.export_function(\n        \"call_js_function_idiomatically\",\n        call_js_function_idiomatically,\n    )?;\n    cx.export_function(\"call_js_function_with_bind\", call_js_function_with_bind)?;\n    cx.export_function(\n        \"call_js_function_with_bind_and_args_with\",\n        call_js_function_with_bind_and_args_with,\n    )?;\n    cx.export_function(\n        \"call_js_function_with_bind_and_args_and_with\",\n        call_js_function_with_bind_and_args_and_with,\n    )?;\n    cx.export_function(\"call_parse_int_with_bind\", call_parse_int_with_bind)?;\n    cx.export_function(\n        \"call_js_function_with_bind_and_exec\",\n        call_js_function_with_bind_and_exec,\n    )?;\n    cx.export_function(\n        \"call_js_constructor_with_bind\",\n        call_js_constructor_with_bind,\n    )?;\n    cx.export_function(\"bind_js_function_to_object\", bind_js_function_to_object)?;\n    cx.export_function(\"bind_js_function_to_number\", bind_js_function_to_number)?;\n    cx.export_function(\n        \"call_js_function_with_zero_args\",\n        call_js_function_with_zero_args,\n    )?;\n    cx.export_function(\n        \"call_js_function_with_one_arg\",\n        call_js_function_with_one_arg,\n    )?;\n    cx.export_function(\n        \"call_js_function_with_two_args\",\n        call_js_function_with_two_args,\n    )?;\n    cx.export_function(\n        \"call_js_function_with_three_args\",\n        call_js_function_with_three_args,\n    )?;\n    cx.export_function(\n        \"call_js_function_with_four_args\",\n        call_js_function_with_four_args,\n    )?;\n    cx.export_function(\n        \"call_js_function_with_custom_this\",\n        call_js_function_with_custom_this,\n    )?;\n    cx.export_function(\n        \"call_js_function_with_implicit_this\",\n        call_js_function_with_implicit_this,\n    )?;\n    cx.export_function(\n        \"exec_js_function_with_implicit_this\",\n        exec_js_function_with_implicit_this,\n    )?;\n    cx.export_function(\n        \"call_js_function_with_heterogeneous_tuple\",\n        call_js_function_with_heterogeneous_tuple,\n    )?;\n    cx.export_function(\"construct_js_function\", construct_js_function)?;\n    cx.export_function(\n        \"construct_js_function_idiomatically\",\n        construct_js_function_idiomatically,\n    )?;\n    cx.export_function(\n        \"construct_js_function_with_overloaded_result\",\n        construct_js_function_with_overloaded_result,\n    )?;\n    cx.export_function(\"num_arguments\", num_arguments)?;\n    cx.export_function(\"return_this\", return_this)?;\n    cx.export_function(\"require_object_this\", require_object_this)?;\n    cx.export_function(\"is_argument_zero_some\", is_argument_zero_some)?;\n    cx.export_function(\"require_argument_zero_string\", require_argument_zero_string)?;\n    cx.export_function(\"check_string_and_number\", check_string_and_number)?;\n    cx.export_function(\"execute_scoped\", execute_scoped)?;\n    cx.export_function(\"compute_scoped\", compute_scoped)?;\n    cx.export_function(\"recompute_scoped\", recompute_scoped)?;\n\n    cx.export_function(\"return_js_array\", return_js_array)?;\n    cx.export_function(\"return_js_array_with_number\", return_js_array_with_number)?;\n    cx.export_function(\"return_js_array_with_string\", return_js_array_with_string)?;\n    cx.export_function(\"read_js_array\", read_js_array)?;\n\n    cx.export_function(\"to_string\", to_string)?;\n\n    cx.export_function(\"return_js_global_object\", return_js_global_object)?;\n    cx.export_function(\"return_js_object\", return_js_object)?;\n    cx.export_function(\"return_js_object_with_number\", return_js_object_with_number)?;\n    cx.export_function(\"return_js_object_with_string\", return_js_object_with_string)?;\n    cx.export_function(\n        \"return_js_object_with_mixed_content\",\n        return_js_object_with_mixed_content,\n    )?;\n    cx.export_function(\"freeze_js_object\", freeze_js_object)?;\n    cx.export_function(\"seal_js_object\", seal_js_object)?;\n\n    cx.export_function(\"return_array_buffer\", return_array_buffer)?;\n    cx.export_function(\n        \"return_array_buffer_from_slice\",\n        return_array_buffer_from_slice,\n    )?;\n    cx.export_function(\"read_array_buffer_with_lock\", read_array_buffer_with_lock)?;\n    cx.export_function(\n        \"read_array_buffer_with_borrow\",\n        read_array_buffer_with_borrow,\n    )?;\n    cx.export_function(\"write_array_buffer_with_lock\", write_array_buffer_with_lock)?;\n    cx.export_function(\n        \"write_array_buffer_with_borrow_mut\",\n        write_array_buffer_with_borrow_mut,\n    )?;\n    cx.export_function(\"read_typed_array_with_borrow\", read_typed_array_with_borrow)?;\n    cx.export_function(\n        \"write_typed_array_with_borrow_mut\",\n        write_typed_array_with_borrow_mut,\n    )?;\n    cx.export_function(\"read_u8_typed_array\", read_u8_typed_array)?;\n    cx.export_function(\"copy_typed_array\", copy_typed_array)?;\n    cx.export_function(\"return_uninitialized_buffer\", return_uninitialized_buffer)?;\n    cx.export_function(\"return_buffer\", return_buffer)?;\n    cx.export_function(\"return_external_buffer\", return_external_buffer)?;\n    cx.export_function(\"return_external_array_buffer\", return_external_array_buffer)?;\n    cx.export_function(\n        \"return_int8array_from_arraybuffer\",\n        return_int8array_from_arraybuffer,\n    )?;\n    cx.export_function(\n        \"return_int16array_from_arraybuffer\",\n        return_int16array_from_arraybuffer,\n    )?;\n    cx.export_function(\n        \"return_uint32array_from_arraybuffer\",\n        return_uint32array_from_arraybuffer,\n    )?;\n    cx.export_function(\n        \"return_float64array_from_arraybuffer\",\n        return_float64array_from_arraybuffer,\n    )?;\n    cx.export_function(\n        \"return_biguint64array_from_arraybuffer\",\n        return_biguint64array_from_arraybuffer,\n    )?;\n    cx.export_function(\"return_new_int32array\", return_new_int32array)?;\n    cx.export_function(\"return_int32array_from_slice\", return_int32array_from_slice)?;\n    cx.export_function(\n        \"return_uint32array_from_arraybuffer_region\",\n        return_uint32array_from_arraybuffer_region,\n    )?;\n    cx.export_function(\"get_arraybuffer_byte_length\", get_arraybuffer_byte_length)?;\n    cx.export_function(\"detach_same_handle\", detach_same_handle)?;\n    cx.export_function(\"detach_and_escape\", detach_and_escape)?;\n    cx.export_function(\"detach_and_cast\", detach_and_cast)?;\n    cx.export_function(\"detach_and_unroot\", detach_and_unroot)?;\n    cx.export_function(\"get_typed_array_info\", get_typed_array_info)?;\n    cx.export_function(\"build_f32_region\", build_f32_region)?;\n    cx.export_function(\"build_f64_region\", build_f64_region)?;\n    cx.export_function(\"read_buffer_with_lock\", read_buffer_with_lock)?;\n    cx.export_function(\"read_buffer_with_borrow\", read_buffer_with_borrow)?;\n    cx.export_function(\"write_buffer_with_lock\", write_buffer_with_lock)?;\n    cx.export_function(\"write_buffer_with_borrow_mut\", write_buffer_with_borrow_mut)?;\n    cx.export_function(\"copy_buffer\", copy_buffer)?;\n    cx.export_function(\"copy_buffer_with_borrow\", copy_buffer_with_borrow)?;\n    cx.export_function(\"byte_length\", byte_length)?;\n    cx.export_function(\"call_nullary_method\", call_nullary_method)?;\n    cx.export_function(\"call_unary_method\", call_unary_method)?;\n    cx.export_function(\"call_symbol_method\", call_symbol_method)?;\n    cx.export_function(\"get_property_with_prop\", get_property_with_prop)?;\n    cx.export_function(\"set_property_with_prop\", set_property_with_prop)?;\n    cx.export_function(\"call_methods_with_prop\", call_methods_with_prop)?;\n    cx.export_function(\"call_non_method_with_prop\", call_non_method_with_prop)?;\n\n    cx.export_function(\"create_date\", create_date)?;\n    cx.export_function(\"get_date_value\", get_date_value)?;\n    cx.export_function(\"check_date_is_invalid\", check_date_is_invalid)?;\n    cx.export_function(\"check_date_is_valid\", check_date_is_valid)?;\n    cx.export_function(\"try_new_date\", try_new_date)?;\n    cx.export_function(\"try_new_lossy_date\", try_new_lossy_date)?;\n    cx.export_function(\"nan_dates\", nan_dates)?;\n    cx.export_function(\"create_date_from_value\", create_date_from_value)?;\n    cx.export_function(\"create_and_get_invalid_date\", create_and_get_invalid_date)?;\n\n    cx.export_function(\"is_array\", is_array)?;\n    cx.export_function(\"is_array_buffer\", is_array_buffer)?;\n    cx.export_function(\"is_uint32_array\", is_uint32_array)?;\n    cx.export_function(\"is_boolean\", is_boolean)?;\n    cx.export_function(\"is_buffer\", is_buffer)?;\n    cx.export_function(\"is_error\", is_error)?;\n    cx.export_function(\"is_null\", is_null)?;\n    cx.export_function(\"is_number\", is_number)?;\n    cx.export_function(\"is_object\", is_object)?;\n    cx.export_function(\"is_string\", is_string)?;\n    cx.export_function(\"is_undefined\", is_undefined)?;\n    cx.export_function(\"strict_equals\", strict_equals)?;\n\n    cx.export_function(\"new_error\", new_error)?;\n    cx.export_function(\"new_type_error\", new_type_error)?;\n    cx.export_function(\"new_range_error\", new_range_error)?;\n    cx.export_function(\"throw_error\", throw_error)?;\n    cx.export_function(\"downcast_error\", downcast_error)?;\n\n    cx.export_function(\"panic\", panic)?;\n    cx.export_function(\"panic_after_throw\", panic_after_throw)?;\n\n    cx.export_function(\"throw_and_catch\", throw_and_catch)?;\n    cx.export_function(\"call_and_catch\", call_and_catch)?;\n    cx.export_function(\"get_number_or_default\", get_number_or_default)?;\n    cx.export_function(\"assume_this_is_an_object\", assume_this_is_an_object)?;\n    cx.export_function(\"is_construct\", is_construct)?;\n    cx.export_function(\"caller_with_drop_callback\", caller_with_drop_callback)?;\n\n    cx.export_function(\"count_called\", {\n        let n = std::cell::RefCell::new(0);\n\n        move |mut cx| {\n            *n.borrow_mut() += 1;\n\n            Ok(cx.number(*n.borrow()))\n        }\n    })?;\n\n    fn call_get_own_property_names(mut cx: FunctionContext) -> JsResult<JsArray> {\n        let object = cx.argument::<JsObject>(0)?;\n        object.get_own_property_names(&mut cx)\n    }\n\n    cx.export_function(\"get_own_property_names\", call_get_own_property_names)?;\n\n    cx.export_function(\"person_new\", person_new)?;\n    cx.export_function(\"person_greet\", person_greet)?;\n    cx.export_function(\"ref_person_new\", ref_person_new)?;\n    cx.export_function(\"ref_person_greet\", ref_person_greet)?;\n    cx.export_function(\"ref_person_set_name\", ref_person_set_name)?;\n    cx.export_function(\"ref_person_fail\", ref_person_fail)?;\n    cx.export_function(\"external_unit\", external_unit)?;\n\n    cx.export_function(\"useless_root\", useless_root)?;\n    cx.export_function(\"thread_callback\", thread_callback)?;\n    cx.export_function(\"multi_threaded_callback\", multi_threaded_callback)?;\n    cx.export_function(\"greeter_new\", greeter_new)?;\n    cx.export_function(\"greeter_greet\", greeter_greet)?;\n    cx.export_function(\"leak_channel\", leak_channel)?;\n    cx.export_function(\"drop_global_queue\", drop_global_queue)?;\n    cx.export_function(\"channel_join\", channel_join)?;\n    cx.export_function(\"sum\", sum)?;\n    cx.export_function(\"sum_manual_promise\", sum_manual_promise)?;\n    cx.export_function(\"sum_rust_thread\", sum_rust_thread)?;\n    cx.export_function(\"leak_promise\", leak_promise)?;\n    cx.export_function(\"channel_panic\", channel_panic)?;\n    cx.export_function(\"channel_throw\", channel_throw)?;\n    cx.export_function(\"channel_panic_throw\", channel_panic_throw)?;\n    cx.export_function(\"channel_custom_panic\", channel_custom_panic)?;\n    cx.export_function(\"custom_panic_downcast\", custom_panic_downcast)?;\n    cx.export_function(\"task_panic_execute\", task_panic_execute)?;\n    cx.export_function(\"task_panic_complete\", task_panic_complete)?;\n    cx.export_function(\"task_throw\", task_throw)?;\n    cx.export_function(\"task_panic_throw\", task_panic_throw)?;\n    cx.export_function(\"task_custom_panic\", task_custom_panic)?;\n    cx.export_function(\"task_reject_promise\", task_reject_promise)?;\n    cx.export_function(\"task_panic_execute_promise\", task_panic_execute_promise)?;\n    cx.export_function(\"task_panic_complete_promise\", task_panic_complete_promise)?;\n    cx.export_function(\"task_panic_throw_promise\", task_panic_throw_promise)?;\n    cx.export_function(\"deferred_settle_with_throw\", deferred_settle_with_throw)?;\n    cx.export_function(\"deferred_settle_with_panic\", deferred_settle_with_panic)?;\n    cx.export_function(\n        \"deferred_settle_with_panic_throw\",\n        deferred_settle_with_panic_throw,\n    )?;\n    cx.export_function(\"get_and_replace\", js::workers::get_and_replace)?;\n    cx.export_function(\"get_or_init\", js::workers::get_or_init)?;\n    cx.export_function(\"get_or_init_clone\", js::workers::get_or_init_clone)?;\n    cx.export_function(\"get_or_init_thread_id\", js::workers::get_or_init_thread_id)?;\n    cx.export_function(\"reentrant_try_init\", js::workers::reentrant_try_init)?;\n    cx.export_function(\"get_reentrant_value\", js::workers::get_reentrant_value)?;\n    cx.export_function(\"stash_global_object\", js::workers::stash_global_object)?;\n    cx.export_function(\"unstash_global_object\", js::workers::unstash_global_object)?;\n    cx.export_function(\"reject_after\", js::workers::reject_after)?;\n    cx.export_function(\"box_channels\", js::workers::box_channels)?;\n\n    // Futures\n    cx.export_function(\"lazy_async_add\", js::futures::lazy_async_add)?;\n    cx.export_function(\"lazy_async_sum\", js::futures::lazy_async_sum)?;\n\n    // JsBigInt test suite\n    cx.export_function(\"bigint_suite\", js::bigint::bigint_suite)?;\n\n    // Extractors\n    cx.export_function(\"extract_values\", js::extract::extract_values)?;\n    cx.export_function(\"extract_buffer_sum\", js::extract::extract_buffer_sum)?;\n    cx.export_function(\"extract_json_sum\", js::extract::extract_json_sum)?;\n    cx.export_function(\n        \"extract_single_add_one\",\n        js::extract::extract_single_add_one,\n    )?;\n\n    // Classes\n    let class_constructor = js::class::Message::constructor(&mut cx)?;\n    cx.export_value(\"Message\", class_constructor)?;\n    let point_constructor = js::class::Point::constructor(&mut cx)?;\n    cx.export_value(\"Point\", point_constructor)?;\n    let string_buffer_constructor = js::class::StringBuffer::constructor(&mut cx)?;\n    cx.export_value(\"StringBuffer\", string_buffer_constructor)?;\n    let async_class_constructor = js::class::AsyncClass::constructor(&mut cx)?;\n    cx.export_value(\"AsyncClass\", async_class_constructor)?;\n\n    // Test constructor features\n    let fallible_counter_constructor = js::class::FallibleCounter::constructor(&mut cx)?;\n    cx.export_value(\"FallibleCounter\", fallible_counter_constructor)?;\n    let context_counter_constructor = js::class::ContextCounter::constructor(&mut cx)?;\n    cx.export_value(\"ContextCounter\", context_counter_constructor)?;\n    let json_config_constructor = js::class::JsonConfig::constructor(&mut cx)?;\n    cx.export_value(\"JsonConfig\", json_config_constructor)?;\n    let validated_config_constructor = js::class::ValidatedConfig::constructor(&mut cx)?;\n    cx.export_value(\"ValidatedConfig\", validated_config_constructor)?;\n    let argv_constructor = js::class::Argv::constructor(&mut cx)?;\n    cx.export_value(\"Argv\", argv_constructor)?;\n    let secret_constructor = js::class::Secret::constructor(&mut cx)?;\n    cx.export_value(\"Secret\", secret_constructor)?;\n    let carousel_constructor = js::class::Carousel::constructor(&mut cx)?;\n    cx.export_value(\"Carousel\", carousel_constructor)?;\n    let expando_constructor = js::class::Expando::constructor(&mut cx)?;\n    cx.export_value(\"Expando\", expando_constructor)?;\n\n    Ok(())\n}\n\nfn runtime<'a, C: Context<'a>>(cx: &mut C) -> NeonResult<&'static Runtime> {\n    static RUNTIME: OnceCell<Runtime> = OnceCell::new();\n\n    RUNTIME.get_or_try_init(|| Runtime::new().or_else(|err| cx.throw_error(err.to_string())))\n}\n"
  },
  {
    "path": "test/rust-2024/.gitignore",
    "content": "target\nindex.node\n**/node_modules\n**/.DS_Store\nnpm-debug.log*cargo.log\ncross.log\n"
  },
  {
    "path": "test/rust-2024/Cargo.toml",
    "content": "[package]\nname = \"rust-2024\"\nversion = \"0.1.0\"\ndescription = \"Test Neon with Rust 2024 Edition\"\nauthors = [\"Dave Herman <david.herman@gmail.com>\"]\nlicense = \"MIT\"\nedition = \"2024\"\nexclude = [\"index.node\"]\n\n[lib]\ncrate-type = [\"cdylib\"]\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies.neon]\npath = \"../../crates/neon\"\nfeatures = [\"futures\", \"napi-experimental\", \"external-buffers\", \"serde\", \"tokio\"]\n"
  },
  {
    "path": "test/rust-2024/README.md",
    "content": "# 2024\n\n**2024:** Test Neon with Rust 2024 Edition\n\nThis project was bootstrapped by [create-neon](https://www.npmjs.com/package/create-neon).\n\n## Building 2024\n\nBuilding 2024 requires a [supported version of Node and Rust](https://github.com/neon-bindings/neon#platform-support).\n\nTo run the build, run:\n\n```sh\n$ npm run build\n```\n\nThis command uses the [@neon-rs/cli](https://www.npmjs.com/package/@neon-rs/cli) utility to assemble the binary Node addon from the output of `cargo`.\n\n## Exploring 2024\n\nAfter building 2024, you can explore its exports at the Node console:\n\n```sh\n$ npm i\n$ npm run build\n$ node\n> require('.').hello()\n'hello node'\n```\n\n## Available Scripts\n\nIn the project directory, you can run:\n\n#### `npm install`\n\nInstalls the project, including running `npm run build`.\n\n#### `npm run build`\n\nBuilds the Node addon (`index.node`) from source, generating a release build with `cargo --release`.\n\nAdditional [`cargo build`](https://doc.rust-lang.org/cargo/commands/cargo-build.html) arguments may be passed to `npm run build` and similar commands. For example, to enable a [cargo feature](https://doc.rust-lang.org/cargo/reference/features.html):\n\n```\nnpm run build -- --feature=beetle\n```\n\n#### `npm run debug`\n\nSimilar to `npm run build` but generates a debug build with `cargo`.\n\n#### `npm run cross`\n\nSimilar to `npm run build` but uses [cross-rs](https://github.com/cross-rs/cross) to cross-compile for another platform. Use the [`CARGO_BUILD_TARGET`](https://doc.rust-lang.org/cargo/reference/config.html#buildtarget) environment variable to select the build target.\n\n#### `npm test`\n\nRuns the unit tests by calling `cargo test`. You can learn more about [adding tests to your Rust code](https://doc.rust-lang.org/book/ch11-01-writing-tests.html) from the [Rust book](https://doc.rust-lang.org/book/).\n\n## Project Layout\n\nThe directory structure of this project is:\n\n```\n2024/\n├── Cargo.toml\n├── README.md\n├── src/\n|   └── lib.rs\n├── index.node\n├── package.json\n└── target/\n```\n\n| Entry          | Purpose                                                                                                                                  |\n|----------------|------------------------------------------------------------------------------------------------------------------------------------------|\n| `Cargo.toml`   | The Cargo [manifest file](https://doc.rust-lang.org/cargo/reference/manifest.html), which informs the `cargo` command.                   |\n| `README.md`    | This file.                                                                                                                               |\n| `src/`         | The directory tree containing the Rust source code for the project.                                                                      |\n| `lib.rs`       | Entry point for the Rust source code.                                                                                                          |\n| `index.node`   | The main module, a [Node addon](https://nodejs.org/api/addons.html) generated by the build and pointed to by `\"main\"` in `package.json`. |\n| `package.json` | The npm [manifest file](https://docs.npmjs.com/cli/v7/configuring-npm/package-json), which informs the `npm` command.                    |\n| `target/`      | Binary artifacts generated by the Rust build.                                                                                            |\n\n## Learn More\n\nLearn more about:\n\n- [Neon](https://neon-bindings.com).\n- [Rust](https://www.rust-lang.org).\n- [Node](https://nodejs.org).\n"
  },
  {
    "path": "test/rust-2024/package.json",
    "content": "{\n  \"name\": \"rust-2024\",\n  \"version\": \"0.1.0\",\n  \"description\": \"Test Neon with Rust 2024 Edition\",\n  \"main\": \"index.node\",\n  \"scripts\": {\n    \"test\": \"cargo test\",\n    \"cargo-build\": \"cargo build --message-format=json-render-diagnostics > cargo.log\",\n    \"cross-build\": \"cross build --message-format=json-render-diagnostics > cross.log\",\n    \"postcargo-build\": \"neon dist < cargo.log\",\n    \"postcross-build\": \"neon dist -m /target < cross.log\",\n    \"debug\": \"npm run cargo-build --\",\n    \"build\": \"npm run cargo-build -- --release\",\n    \"cross\": \"npm run cross-build -- --release\"\n  },\n  \"author\": \"Dave Herman <david.herman@gmail.com>\",\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"@neon-rs/cli\": \"0.1.82\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/neon-bindings/neon.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/neon-bindings/neon/issues\"\n  },\n  \"homepage\": \"https://github.com/neon-bindings/neon#readme\"\n}\n"
  },
  {
    "path": "test/rust-2024/src/lib.rs",
    "content": "#[neon::export]\nfn hello() -> String {\n    \"hello node\".to_string()\n}\n"
  },
  {
    "path": "test/ui/Cargo.toml",
    "content": "[package]\nname = \"ui-test\"\nversion = \"0.1.0\"\nedition = \"2021\"\nauthors = [\"The Neon Community\"]\nlicense = \"MIT/Apache-2.0\"\n\n[lib]\ncrate-type = [\"cdylib\"]\n\n[dependencies.neon]\npath = \"../../crates/neon\"\nfeatures = [\"futures\", \"napi-experimental\", \"serde\"]\n\n[dependencies]\nrustversion = \"1.0.17\"\n\n[dev-dependencies]\ntrybuild = \"1\"\n"
  },
  {
    "path": "test/ui/src/lib.rs",
    "content": "#[rustversion::attr(not(stable), ignore)]\n#[test]\nfn ui() {\n    let t = trybuild::TestCases::new();\n\n    t.compile_fail(\"tests/fail/*.rs\");\n    t.pass(\"tests/pass/*.rs\");\n}\n"
  },
  {
    "path": "test/ui/tests/fail/class-async-borrowed-channel.rs",
    "content": "use neon::prelude::*;\n\nstruct Example;\n\n#[neon::class]\nimpl Example {\n    #[neon(async)]\n    fn method(&self, _ch: &Channel) {}\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/class-async-borrowed-channel.stderr",
    "content": "error: Expected `&mut Cx` instead of a `Channel` reference.\n --> tests/fail/class-async-borrowed-channel.rs:8:28\n  |\n8 |     fn method(&self, _ch: &Channel) {}\n  |                            ^^^^^^^\n\nerror[E0277]: the trait bound `Example: Default` is not satisfied\n --> tests/fail/class-async-borrowed-channel.rs:5:1\n  |\n5 | #[neon::class]\n  | ^^^^^^^^^^^^^^ the trait `Default` is not implemented for `Example`\n  |\n  = note: this error originates in the attribute macro `neon::class` (in Nightly builds, run with -Z macro-backtrace for more info)\nhelp: consider annotating `Example` with `#[derive(Default)]`\n  |\n3 + #[derive(Default)]\n4 | struct Example;\n  |\n"
  },
  {
    "path": "test/ui/tests/fail/class-async-context-ref.rs",
    "content": "use neon::prelude::*;\n\nstruct Example;\n\n#[neon::class]\nimpl Example {\n    #[neon(async)]\n    fn method(&self, _cx: &mut FunctionContext) {}\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/class-async-context-ref.stderr",
    "content": "error[E0277]: the trait bound `Example: Default` is not satisfied\n --> tests/fail/class-async-context-ref.rs:5:1\n  |\n5 | #[neon::class]\n  | ^^^^^^^^^^^^^^ the trait `Default` is not implemented for `Example`\n  |\n  = note: this error originates in the attribute macro `neon::class` (in Nightly builds, run with -Z macro-backtrace for more info)\nhelp: consider annotating `Example` with `#[derive(Default)]`\n  |\n3 + #[derive(Default)]\n4 | struct Example;\n  |\n\nerror[E0277]: `()` is not a future\n --> tests/fail/class-async-context-ref.rs:5:1\n  |\n 5 | #[neon::class]\n   | ^^^^^^^^^^^^^^ `()` is not a future\n   |\n   = help: the trait `Future` is not implemented for `()`\nnote: required by a bound in `neon::macro_internal::spawn`\n  --> $WORKSPACE/crates/neon/src/macro_internal/futures.rs\n   |\n 9 | pub fn spawn<'cx, F, S>(cx: &mut Cx<'cx>, fut: F, settle: S) -> JsResult<'cx, JsValue>\n   |        ----- required by a bound in this function\n   | where\n   |     F: Future + Send + 'static,\n   |        ^^^^^^ required by this bound in `spawn`\n   = note: this error originates in the attribute macro `neon::class` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0282]: type annotations needed\n --> tests/fail/class-async-context-ref.rs:5:1\n  |\n5 | #[neon::class]\n  | ^^^^^^^^^^^^^^ cannot infer type\n  |\n  = note: this error originates in the attribute macro `neon::class` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "test/ui/tests/fail/class-async-fn-borrowed-self.rs",
    "content": "#[derive(Clone)]\nstruct Example;\n\n#[neon::class]\nimpl Example {\n    async fn method(&self) {}\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/class-async-fn-borrowed-self.stderr",
    "content": "error: Async functions in classes must take `self` by value, not `&self` or `&mut self`. This is required because async functions capture `self` in the Future, which must be `'static` for spawning.\n --> tests/fail/class-async-fn-borrowed-self.rs:6:21\n  |\n6 |     async fn method(&self) {}\n  |                     ^\n\nerror[E0277]: the trait bound `Example: Default` is not satisfied\n --> tests/fail/class-async-fn-borrowed-self.rs:4:1\n  |\n4 | #[neon::class]\n  | ^^^^^^^^^^^^^^ the trait `Default` is not implemented for `Example`\n  |\n  = note: this error originates in the attribute macro `neon::class` (in Nightly builds, run with -Z macro-backtrace for more info)\nhelp: consider annotating `Example` with `#[derive(Default)]`\n  |\n2 + #[derive(Default)]\n3 | struct Example;\n  |\n"
  },
  {
    "path": "test/ui/tests/fail/class-async-owned-context.rs",
    "content": "use neon::prelude::*;\n\nstruct Example;\n\n#[neon::class]\nimpl Example {\n    #[neon(async)]\n    fn method(&self, _cx: FunctionContext) {}\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/class-async-owned-context.stderr",
    "content": "error: Context parameters must be a `&mut` reference. Try `&mut FunctionContext` or `&mut Cx`.\n --> tests/fail/class-async-owned-context.rs:8:27\n  |\n8 |     fn method(&self, _cx: FunctionContext) {}\n  |                           ^^^^^^^^^^^^^^^\n\nerror[E0277]: the trait bound `Example: Default` is not satisfied\n --> tests/fail/class-async-owned-context.rs:5:1\n  |\n5 | #[neon::class]\n  | ^^^^^^^^^^^^^^ the trait `Default` is not implemented for `Example`\n  |\n  = note: this error originates in the attribute macro `neon::class` (in Nightly builds, run with -Z macro-backtrace for more info)\nhelp: consider annotating `Example` with `#[derive(Default)]`\n  |\n3 + #[derive(Default)]\n4 | struct Example;\n  |\n"
  },
  {
    "path": "test/ui/tests/fail/class-borrowed-channel-sync.rs",
    "content": "use neon::prelude::*;\n\nstruct Example;\n\n#[neon::class]\nimpl Example {\n    fn method(&self, _ch: &Channel) {}\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/class-borrowed-channel-sync.stderr",
    "content": "error: Expected `&mut Cx` instead of a `Channel` reference.\n --> tests/fail/class-borrowed-channel-sync.rs:7:28\n  |\n7 |     fn method(&self, _ch: &Channel) {}\n  |                            ^^^^^^^\n\nerror[E0277]: the trait bound `Example: Default` is not satisfied\n --> tests/fail/class-borrowed-channel-sync.rs:5:1\n  |\n5 | #[neon::class]\n  | ^^^^^^^^^^^^^^ the trait `Default` is not implemented for `Example`\n  |\n  = note: this error originates in the attribute macro `neon::class` (in Nightly builds, run with -Z macro-backtrace for more info)\nhelp: consider annotating `Example` with `#[derive(Default)]`\n  |\n3 + #[derive(Default)]\n4 | struct Example;\n  |\n"
  },
  {
    "path": "test/ui/tests/fail/class-channel-in-sync.rs",
    "content": "use neon::prelude::*;\n\nstruct Example;\n\n#[neon::class]\nimpl Example {\n    fn method(&self, _ch: Channel) {}\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/class-channel-in-sync.stderr",
    "content": "error: Unexpected `Channel` in sync method. Use `&mut FunctionContext` for sync methods, or `Channel` in async/task methods.\n --> tests/fail/class-channel-in-sync.rs:7:27\n  |\n7 |     fn method(&self, _ch: Channel) {}\n  |                           ^^^^^^^\n\nerror[E0277]: the trait bound `Example: Default` is not satisfied\n --> tests/fail/class-channel-in-sync.rs:5:1\n  |\n5 | #[neon::class]\n  | ^^^^^^^^^^^^^^ the trait `Default` is not implemented for `Example`\n  |\n  = note: this error originates in the attribute macro `neon::class` (in Nightly builds, run with -Z macro-backtrace for more info)\nhelp: consider annotating `Example` with `#[derive(Default)]`\n  |\n3 + #[derive(Default)]\n4 | struct Example;\n  |\n"
  },
  {
    "path": "test/ui/tests/fail/class-constructor-self-receiver.rs",
    "content": "struct Example;\n\n#[neon::class]\nimpl Example {\n    fn new(&self) -> Self {\n        Example\n    }\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/class-constructor-self-receiver.stderr",
    "content": "error: Constructor methods cannot have a `self` receiver\n --> tests/fail/class-constructor-self-receiver.rs:5:12\n  |\n5 |     fn new(&self) -> Self {\n  |            ^^^^^\n"
  },
  {
    "path": "test/ui/tests/fail/class-constructor-with-self.rs",
    "content": "struct Example;\n\n#[neon::class]\nimpl Example {\n    fn new(self) -> Self {\n        self\n    }\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/class-constructor-with-self.stderr",
    "content": "error: Constructor methods cannot have a `self` receiver\n --> tests/fail/class-constructor-with-self.rs:5:12\n  |\n5 |     fn new(self) -> Self {\n  |            ^^^^\n"
  },
  {
    "path": "test/ui/tests/fail/class-duplicate-property-names.rs",
    "content": "struct Example;\n\n#[neon::class]\nimpl Example {\n    #[neon(name = \"value\")]\n    const VALUE1: i32 = 42;\n\n    #[neon(name = \"value\")]\n    const VALUE2: i32 = 43;\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/class-duplicate-property-names.stderr",
    "content": "error: duplicate property name 'value' - const property names must be unique in JavaScript\n --> tests/fail/class-duplicate-property-names.rs:8:5\n  |\n8 | /     #[neon(name = \"value\")]\n9 | |     const VALUE2: i32 = 43;\n  | |___________________________^\n"
  },
  {
    "path": "test/ui/tests/fail/class-immutable-context.rs",
    "content": "use neon::prelude::*;\n\nstruct Example;\n\n#[neon::class]\nimpl Example {\n    fn method(&self, _cx: &FunctionContext) {}\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/class-immutable-context.stderr",
    "content": "error: Must be a `&mut` reference.\n --> tests/fail/class-immutable-context.rs:7:27\n  |\n7 |     fn method(&self, _cx: &FunctionContext) {}\n  |                           ^\n\nerror[E0277]: the trait bound `Example: Default` is not satisfied\n --> tests/fail/class-immutable-context.rs:5:1\n  |\n5 | #[neon::class]\n  | ^^^^^^^^^^^^^^ the trait `Default` is not implemented for `Example`\n  |\n  = note: this error originates in the attribute macro `neon::class` (in Nightly builds, run with -Z macro-backtrace for more info)\nhelp: consider annotating `Example` with `#[derive(Default)]`\n  |\n3 + #[derive(Default)]\n4 | struct Example;\n  |\n"
  },
  {
    "path": "test/ui/tests/fail/class-invalid-item-type.rs",
    "content": "struct Example;\n\n#[neon::class]\nimpl Example {\n    type AssocType = i32;\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/class-invalid-item-type.stderr",
    "content": "error: `neon::class` can only contain `const` and `fn` items.\n --> tests/fail/class-invalid-item-type.rs:5:5\n  |\n5 |     type AssocType = i32;\n  |     ^^^^\n"
  },
  {
    "path": "test/ui/tests/fail/class-invalid-property-name.rs",
    "content": "struct Example;\n\n#[neon::class]\nimpl Example {\n    #[neon(name = \"123invalid\")]\n    const VALUE: i32 = 42;\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/class-invalid-property-name.stderr",
    "content": "error: '123invalid' is not a valid JavaScript identifier\n --> tests/fail/class-invalid-property-name.rs:5:19\n  |\n5 |     #[neon(name = \"123invalid\")]\n  |                   ^^^^^^^^^^^^\n"
  },
  {
    "path": "test/ui/tests/fail/class-method-missing-self.rs",
    "content": "struct Example;\n\n#[neon::class]\nimpl Example {\n    fn method() {}\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/class-method-missing-self.stderr",
    "content": "error: Class methods must have a `self` receiver (`&self` or `&mut self`) as their first parameter\n --> tests/fail/class-method-missing-self.rs:5:8\n  |\n5 |     fn method() {}\n  |        ^^^^^^\n\nerror[E0277]: the trait bound `Example: Default` is not satisfied\n --> tests/fail/class-method-missing-self.rs:3:1\n  |\n3 | #[neon::class]\n  | ^^^^^^^^^^^^^^ the trait `Default` is not implemented for `Example`\n  |\n  = note: this error originates in the attribute macro `neon::class` (in Nightly builds, run with -Z macro-backtrace for more info)\nhelp: consider annotating `Example` with `#[derive(Default)]`\n  |\n1 + #[derive(Default)]\n2 | struct Example;\n  |\n"
  },
  {
    "path": "test/ui/tests/fail/class-missing-forced-context.rs",
    "content": "struct Example;\n\n#[neon::class]\nimpl Example {\n    #[neon(context)]\n    fn method(&self) {}\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/class-missing-forced-context.stderr",
    "content": "error: Expected a context argument after `&self` when using `#[neon(context)]`. Add a parameter like `cx: &mut FunctionContext` or remove the `context` attribute.\n --> tests/fail/class-missing-forced-context.rs:6:15\n  |\n6 |     fn method(&self) {}\n  |               ^\n\nerror[E0277]: the trait bound `Example: Default` is not satisfied\n --> tests/fail/class-missing-forced-context.rs:3:1\n  |\n3 | #[neon::class]\n  | ^^^^^^^^^^^^^^ the trait `Default` is not implemented for `Example`\n  |\n  = note: this error originates in the attribute macro `neon::class` (in Nightly builds, run with -Z macro-backtrace for more info)\nhelp: consider annotating `Example` with `#[derive(Default)]`\n  |\n1 + #[derive(Default)]\n2 | struct Example;\n  |\n"
  },
  {
    "path": "test/ui/tests/fail/class-multiple-constructors.rs",
    "content": "struct Example;\n\n#[neon::class]\nimpl Example {\n    fn new() -> Self {\n        Example\n    }\n\n    fn new() -> Self {\n        Example\n    }\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/class-multiple-constructors.stderr",
    "content": "error: Only one `new` constructor is allowed in a class.\n --> tests/fail/class-multiple-constructors.rs:9:5\n  |\n9 |     fn new() -> Self {\n  |     ^^\n"
  },
  {
    "path": "test/ui/tests/fail/class-multiple-finalizers.rs",
    "content": "struct Example;\n\n#[neon::class]\nimpl Example {\n    fn finalize<'a, C: neon::context::Context<'a>>(self, _cx: &mut C) {}\n    fn finalize<'a, C: neon::context::Context<'a>>(self, _cx: &mut C) {}\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/class-multiple-finalizers.stderr",
    "content": "error: Only one `finalize` method is allowed in a class.\n --> tests/fail/class-multiple-finalizers.rs:6:5\n  |\n6 |     fn finalize<'a, C: neon::context::Context<'a>>(self, _cx: &mut C) {}\n  |     ^^\n"
  },
  {
    "path": "test/ui/tests/fail/class-multiple-neon-attrs-const.rs",
    "content": "struct Example;\n\n#[neon::class]\nimpl Example {\n    #[neon(name = \"foo\")]\n    #[neon(json)]\n    const VALUE: i32 = 42;\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/class-multiple-neon-attrs-const.stderr",
    "content": "error: multiple #[neon(...)] attributes on const property are not allowed\n --> tests/fail/class-multiple-neon-attrs-const.rs:6:5\n  |\n6 |     #[neon(json)]\n  |     ^^^^^^^^^^^^^\n"
  },
  {
    "path": "test/ui/tests/fail/class-multiple-neon-attrs-method.rs",
    "content": "struct Example;\n\n#[neon::class]\nimpl Example {\n    #[neon(async)]\n    #[neon(task)]\n    fn method(&self) {}\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/class-multiple-neon-attrs-method.stderr",
    "content": "error: multiple #[neon(...)] attributes on class method are not allowed\n --> tests/fail/class-multiple-neon-attrs-method.rs:6:7\n  |\n6 |     #[neon(task)]\n  |       ^^^^^^^^^^\n"
  },
  {
    "path": "test/ui/tests/fail/class-owned-context.rs",
    "content": "use neon::prelude::*;\n\nstruct Example;\n\n#[neon::class]\nimpl Example {\n    fn method(&self, _cx: FunctionContext) {}\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/class-owned-context.stderr",
    "content": "error: Context parameters must be a `&mut` reference. Try `&mut FunctionContext` or `&mut Cx`.\n --> tests/fail/class-owned-context.rs:7:27\n  |\n7 |     fn method(&self, _cx: FunctionContext) {}\n  |                           ^^^^^^^^^^^^^^^\n\nerror[E0277]: the trait bound `Example: Default` is not satisfied\n --> tests/fail/class-owned-context.rs:5:1\n  |\n5 | #[neon::class]\n  | ^^^^^^^^^^^^^^ the trait `Default` is not implemented for `Example`\n  |\n  = note: this error originates in the attribute macro `neon::class` (in Nightly builds, run with -Z macro-backtrace for more info)\nhelp: consider annotating `Example` with `#[derive(Default)]`\n  |\n3 + #[derive(Default)]\n4 | struct Example;\n  |\n"
  },
  {
    "path": "test/ui/tests/fail/missing-class-clone.rs",
    "content": "struct Point {\n    x: i32,\n    y: i32,\n}\n\n#[neon::class]\nimpl Point {\n    fn new(x: i32, y: i32) -> Self {\n        Point { x, y }\n    }\n\n    fn equals(&self, other: Point) -> bool {\n        self.x == other.x && self.y == other.y\n    }\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/missing-class-clone.stderr",
    "content": "error[E0277]: the trait bound `Point: Clone` is not satisfied\n --> tests/fail/missing-class-clone.rs:6:1\n  |\n  6 | #[neon::class]\n    | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Point`\n    |\n    = help: the following other types implement trait `FromArgs<'cx>`:\n              ()\n              (T1, T2)\n              (T1, T2, T3)\n              (T1, T2, T3, T4)\n              (T1, T2, T3, T4, T5)\n              (T1, T2, T3, T4, T5, T6)\n              (T1, T2, T3, T4, T5, T6, T7)\n              (T1, T2, T3, T4, T5, T6, T7, T8)\n            and $N others\nnote: required for `Point` to implement `TryFromJs<'_>`\n   --> tests/fail/missing-class-clone.rs:6:1\n    |\n  6 | #[neon::class]\n    | ^^^^^^^^^^^^^^ unsatisfied trait bound introduced here\n  7 | impl Point {\n    |      ^^^^^\n    = note: required for `(Point,)` to implement `FromArgs<'_>`\nnote: required by a bound in `FunctionContext::<'cx>::args`\n   --> $WORKSPACE/crates/neon/src/context/mod.rs\n    |\n    |     pub fn args<T>(&mut self) -> NeonResult<T>\n    |            ---- required by a bound in this associated function\n    |     where\n    |         T: FromArgs<'cx>,\n    |            ^^^^^^^^^^^^^ required by this bound in `FunctionContext::<'cx>::args`\n    = note: this error originates in the attribute macro `neon::class` (in Nightly builds, run with -Z macro-backtrace for more info)\nhelp: consider annotating `Point` with `#[derive(Clone)]`\n    |\n  1 + #[derive(Clone)]\n  2 | struct Point {\n    |\n"
  },
  {
    "path": "test/ui/tests/fail/missing-class-default.rs",
    "content": "struct Point {\n    x: i32,\n    y: i32,\n}\n\n#[neon::class]\nimpl Point {\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/missing-class-default.stderr",
    "content": "error[E0277]: the trait bound `Point: Default` is not satisfied\n --> tests/fail/missing-class-default.rs:6:1\n  |\n6 | #[neon::class]\n  | ^^^^^^^^^^^^^^ the trait `Default` is not implemented for `Point`\n  |\n  = note: this error originates in the attribute macro `neon::class` (in Nightly builds, run with -Z macro-backtrace for more info)\nhelp: consider annotating `Point` with `#[derive(Default)]`\n  |\n1 + #[derive(Default)]\n2 | struct Point {\n  |\n"
  },
  {
    "path": "test/ui/tests/fail/missing-context.rs",
    "content": "#[neon::export(context)]\nfn missing_context() {}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/missing-context.stderr",
    "content": "error: Expected a context argument. Try removing the `context` attribute.\n --> tests/fail/missing-context.rs:1:1\n  |\n1 | #[neon::export(context)]\n  | ^^^^^^^^^^^^^^^^^^^^^^^^\n  |\n  = note: this error originates in the attribute macro `neon::export` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "test/ui/tests/fail/need-borrowed-context.rs",
    "content": "#[neon::export]\nfn owned_cx(_cx: Cx) {}\n\n#[neon::export]\nfn owned_function_cx(_cx: FunctionContext) {}\n\n#[neon::export]\nfn ref_cx(_cx: &Cx) {}\n\n#[neon::export]\nfn ref_function_cx(_cx: &FunctionContext) {}\n\n#[neon::export(context)]\nfn forced_cx(_cx: String) {}\n\n#[neon::export(context)]\nfn forced_ref_cx(_cx: &String) {}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/need-borrowed-context.stderr",
    "content": "error: Context must be a `&mut` reference.\n --> tests/fail/need-borrowed-context.rs:2:18\n  |\n2 | fn owned_cx(_cx: Cx) {}\n  |                  ^^\n\nerror: Context must be a `&mut` reference.\n --> tests/fail/need-borrowed-context.rs:5:27\n  |\n5 | fn owned_function_cx(_cx: FunctionContext) {}\n  |                           ^^^^^^^^^^^^^^^\n\nerror: Must be a `&mut` reference.\n --> tests/fail/need-borrowed-context.rs:8:16\n  |\n8 | fn ref_cx(_cx: &Cx) {}\n  |                ^\n\nerror: Must be a `&mut` reference.\n  --> tests/fail/need-borrowed-context.rs:11:25\n   |\n11 | fn ref_function_cx(_cx: &FunctionContext) {}\n   |                         ^\n\nerror: Context must be a `&mut` reference.\n  --> tests/fail/need-borrowed-context.rs:14:19\n   |\n14 | fn forced_cx(_cx: String) {}\n   |                   ^^^^^^\n\nerror: Must be a `&mut` reference.\n  --> tests/fail/need-borrowed-context.rs:17:23\n   |\n17 | fn forced_ref_cx(_cx: &String) {}\n   |                       ^\n"
  },
  {
    "path": "test/ui/tests/fail/unexpected-self.rs",
    "content": "struct Example;\n\nimpl Example {\n    #[neon::export]\n    fn borrow(&self) {}\n\n    #[neon::export]\n    fn borrow_mut(&mut self) {}\n\n    #[neon::export]\n    fn owned(self) {}\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/unexpected-self.stderr",
    "content": "error: Exported functions cannot receive `self`.\n --> tests/fail/unexpected-self.rs:5:15\n  |\n5 |     fn borrow(&self) {}\n  |               ^\n\nerror: Exported functions cannot receive `self`.\n --> tests/fail/unexpected-self.rs:8:19\n  |\n8 |     fn borrow_mut(&mut self) {}\n  |                   ^\n\nerror: Exported functions cannot receive `self`.\n  --> tests/fail/unexpected-self.rs:11:14\n   |\n11 |     fn owned(self) {}\n   |              ^^^^\n"
  },
  {
    "path": "test/ui/tests/fail/unnecessary-attribute.rs",
    "content": "#[neon::export(async)]\nasync fn async_with_async() {}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/unnecessary-attribute.stderr",
    "content": "error: `async` attribute should not be used with an `async fn`\n --> tests/fail/unnecessary-attribute.rs:1:16\n  |\n1 | #[neon::export(async)]\n  |                ^^^^^\n"
  },
  {
    "path": "test/ui/tests/fail/unsupported-property.rs",
    "content": "#[neon::export(foo)]\nstatic STRING: &str = \"\";\n\n#[neon::export(foo)]\nfn unsupported() {}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/unsupported-property.stderr",
    "content": "error: unsupported property\n --> tests/fail/unsupported-property.rs:1:16\n  |\n1 | #[neon::export(foo)]\n  |                ^^^\n\nerror: unsupported property\n --> tests/fail/unsupported-property.rs:4:16\n  |\n4 | #[neon::export(foo)]\n  |                ^^^\n"
  },
  {
    "path": "test/ui/tests/fail/wrong-context.rs",
    "content": "#[neon::export]\nfn sync_channel(_ch: Channel) {}\n\n#[neon::export]\nfn sync_borrow_channel(_ch: &mut Channel) {}\n\n#[neon::export(async)]\nfn async_channel(_ch: Channel) {}\n\n#[neon::export(async)]\nfn async_borrow_channel(_ch: &mut Channel) {}\n\n#[neon::export]\nasync fn async_cx(_cx: Cx) {}\n\n#[neon::export]\nasync fn async_function_context(_cx: FunctionContext) {}\n\n#[neon::export]\nasync fn async_cx_ref(_cx: &Cx) {}\n\n#[neon::export]\nasync fn async_borrow_channel(_cx: &Channel) {}\n\n#[neon::export(context)]\nasync fn async_borrow_forced_channel(_cx: &String) {}\n\n#[neon::export]\nasync fn async_function_context_ref(_cx: &FunctionContext) {}\n\n#[neon::export(task)]\nfn task_function_context(_cx: FunctionContext) {}\n\n#[neon::export(task)]\nfn task_cx_ref(_cx: &Cx) {}\n\n#[neon::export(task)]\nfn task_function_context_ref(_cx: &FunctionContext) {}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/fail/wrong-context.stderr",
    "content": "error: Expected `&mut Cx` instead of `Channel`.\n --> tests/fail/wrong-context.rs:2:22\n  |\n2 | fn sync_channel(_ch: Channel) {}\n  |                      ^^^^^^^\n\nerror: Expected `&mut Cx` instead of a `Channel` reference.\n --> tests/fail/wrong-context.rs:5:34\n  |\n5 | fn sync_borrow_channel(_ch: &mut Channel) {}\n  |                                  ^^^^^^^\n\nerror: Expected `&mut Cx` instead of `Channel`.\n --> tests/fail/wrong-context.rs:8:23\n  |\n8 | fn async_channel(_ch: Channel) {}\n  |                       ^^^^^^^\n\nerror: Expected `&mut Cx` instead of a `Channel` reference.\n  --> tests/fail/wrong-context.rs:11:35\n   |\n11 | fn async_borrow_channel(_ch: &mut Channel) {}\n   |                                   ^^^^^^^\n\nerror: Context is not available in async functions. Try a `Channel` instead.\n  --> tests/fail/wrong-context.rs:14:24\n   |\n14 | async fn async_cx(_cx: Cx) {}\n   |                        ^^\n\nerror: Context is not available in async functions. Try a `Channel` instead.\n  --> tests/fail/wrong-context.rs:17:38\n   |\n17 | async fn async_function_context(_cx: FunctionContext) {}\n   |                                      ^^^^^^^^^^^^^^^\n\nerror: Expected an owned `Channel` instead of a context reference.\n  --> tests/fail/wrong-context.rs:20:29\n   |\n20 | async fn async_cx_ref(_cx: &Cx) {}\n   |                             ^^\n\nerror: Expected an owned `Channel` instead of a reference.\n  --> tests/fail/wrong-context.rs:23:36\n   |\n23 | async fn async_borrow_channel(_cx: &Channel) {}\n   |                                    ^\n\nerror: Expected an owned `Channel` instead of a reference.\n  --> tests/fail/wrong-context.rs:26:43\n   |\n26 | async fn async_borrow_forced_channel(_cx: &String) {}\n   |                                           ^\n\nerror: Expected an owned `Channel` instead of a context reference.\n  --> tests/fail/wrong-context.rs:29:43\n   |\n29 | async fn async_function_context_ref(_cx: &FunctionContext) {}\n   |                                           ^^^^^^^^^^^^^^^\n\nerror: Context is not available in async functions. Try a `Channel` instead.\n  --> tests/fail/wrong-context.rs:32:31\n   |\n32 | fn task_function_context(_cx: FunctionContext) {}\n   |                               ^^^^^^^^^^^^^^^\n\nerror: Expected an owned `Channel` instead of a context reference.\n  --> tests/fail/wrong-context.rs:35:22\n   |\n35 | fn task_cx_ref(_cx: &Cx) {}\n   |                      ^^\n\nerror: Expected an owned `Channel` instead of a context reference.\n  --> tests/fail/wrong-context.rs:38:36\n   |\n38 | fn task_function_context_ref(_cx: &FunctionContext) {}\n   |                                    ^^^^^^^^^^^^^^^\n"
  },
  {
    "path": "test/ui/tests/pass/context-and-this.rs",
    "content": "use std::future::Future;\n\nuse neon::{\n    context::{Context, Cx, FunctionContext},\n    event::Channel,\n    handle::Handle,\n    types::{extract::Boxed, JsString},\n};\n\ntype Ch = Channel;\ntype FnCx<'cx> = FunctionContext<'cx>;\n\n#[neon::export]\nfn sync_nothing() {}\n\n#[neon::export]\nfn sync_function_context(_cx: &mut FunctionContext) {}\n\n#[neon::export]\nfn sync_cx(_cx: &mut Cx) {}\n\n#[neon::export(context)]\nfn sync_cx_forced(_cx: &mut FnCx) {}\n\n#[neon::export]\nfn sync_cx_lifetimes<'cx>(cx: &mut Cx<'cx>) -> Handle<'cx, JsString> {\n    cx.string(\"Hello, World!\")\n}\n\n#[neon::export]\nfn sync_this(this: Vec<u8>) {\n    let _ = this;\n}\n\n#[neon::export(this)]\nfn sync_this_forced(_this: Vec<u8>) {}\n\n#[neon::export]\nfn sync_cx_and_this(_cx: &mut Cx, this: Vec<u8>) {\n    let _ = this;\n}\n\n#[neon::export]\nfn sync_cx_and_this_and_args(_cx: &mut Cx, this: Vec<u8>, _a: String) {\n    let _ = this;\n}\n\n#[neon::export]\nfn boxed_this(Boxed(this): Boxed<String>) {\n    let _ = this;\n}\n\n#[neon::export]\nasync fn async_nothing() {}\n\n#[neon::export]\nasync fn async_channel(_ch: Channel) {}\n\n#[neon::export(context)]\nasync fn async_channel_forced(_ch: Ch) {}\n\n#[neon::export]\nasync fn async_channel_and_arg(_ch: Channel, _a: String) {}\n\n#[neon::export]\nasync fn async_no_channel(_a: String) {}\n\n#[neon::export]\nasync fn async_this(this: Vec<u8>) {\n    let _ = this;\n}\n\n#[neon::export(this)]\nasync fn async_this_forced(_this: Vec<u8>) {}\n\n#[neon::export]\nasync fn async_this_args(this: Vec<u8>, _a: String) {\n    let _ = this;\n}\n\n#[neon::export]\nasync fn async_this_and_channel(_ch: Channel, this: Vec<u8>) {\n    let _ = this;\n}\n\n#[neon::export]\nasync fn async_this_and_channel_args(_ch: Channel, this: Vec<u8>, _a: String, _b: String) {\n    let _ = this;\n}\n\n#[neon::export(task)]\nfn task_nothing() {}\n\n#[neon::export(task)]\nfn task_channel(_ch: Channel) {}\n\n#[neon::export(context, task)]\nfn task_channel_forced(_ch: Ch) {}\n\n#[neon::export(task)]\nfn task_channel_and_arg(_ch: Channel, _a: String) {}\n\n#[neon::export(task)]\nfn task_no_channel(_a: String) {}\n\n#[neon::export(task)]\nfn task_this(this: Vec<u8>) {\n    let _ = this;\n}\n\n#[neon::export(task, this)]\nfn task_this_forced(_this: Vec<u8>) {}\n\n#[neon::export(task)]\nfn task_this_args(this: Vec<u8>, _a: String) {\n    let _ = this;\n}\n\n#[neon::export(task)]\nfn task_this_and_channel(_ch: Channel, this: Vec<u8>) {\n    let _ = this;\n}\n\n#[neon::export(task)]\nfn task_this_and_channel_args(_ch: Channel, this: Vec<u8>, _a: String, _b: String) {\n    let _ = this;\n}\n\n#[neon::export(async)]\nfn impl_async_context(_cx: &mut Cx) -> impl Future<Output = ()> {\n    async {}\n}\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/pass/globals.rs",
    "content": "#[neon::export]\nstatic STATIC_STRING: &str = \"\";\n\n#[neon::export]\nconst CONST_NUMBER: f64 = 42.0;\n\n#[neon::export]\nstatic STATIC_ARR: &[f64] = &[42.0];\n\n#[neon::export(json)]\nstatic ARR_OF_ARR: &[&[f64]] = &[&[42.0]];\n\nfn main() {}\n"
  },
  {
    "path": "test/ui/tests/pass/json.rs",
    "content": "#[neon::export(json)]\nfn wrap_with_json(v: Vec<String>) -> Vec<String> {\n    v\n}\n\nfn main() {}\n"
  }
]