wasm-bindgen-0.2.87/.cargo/config000064400000000000000000000010261046102023000146350ustar 00000000000000# TODO: we shouldn't check this in to git, need to figure out how to avoid doing # that. [target.wasm32-unknown-unknown] runner = 'cargo run -p wasm-bindgen-cli --bin wasm-bindgen-test-runner --' [target.'cfg(all())'] rustflags = [ "-Adead_code", "-Anon_upper_case_globals", "-Aunused_doc_comments", "-Aclippy::large_enum_variant", "-Aclippy::missing_safety_doc", "-Aclippy::new_without_default", "-Aclippy::overly_complex_bool_expr", "-Aclippy::too_many_arguments", "-Aclippy::type_complexity" ] wasm-bindgen-0.2.87/.gitattributes000064400000000000000000000000331046102023000151640ustar 00000000000000*.webidl linguist-vendored wasm-bindgen-0.2.87/.github/actions/setup-geckodriver/action.yml000064400000000000000000000001441046102023000227360ustar 00000000000000name: 'Setup Geckodriver' description: 'Setup Geckodriver' runs: using: node16 main: 'main.js' wasm-bindgen-0.2.87/.github/actions/setup-geckodriver/main.js000064400000000000000000000015161046102023000222240ustar 00000000000000const child_process = require('child_process'); const fs = require('fs'); function set_env(name, val) { fs.appendFileSync(process.env['GITHUB_ENV'], `${name}=${val}\n`) } function fetch(url) { child_process.execFileSync('curl', ['--retry', '5', '-LO', url]) } const version = '0.24.0'; if (process.platform === 'win32') { const file = `geckodriver-v${version}-win64.zip`; fetch(`https://github.com/mozilla/geckodriver/releases/download/v${version}/${file}`); child_process.execFileSync('unzip', [file]); set_env("GECKODRIVER", process.cwd() + '/geckodriver.exe'); } else { const file = `geckodriver-v${version}-linux64.tar.gz`; fetch(`https://github.com/mozilla/geckodriver/releases/download/v${version}/${file}`); child_process.execFileSync('tar', ['xf', file]); set_env("GECKODRIVER", process.cwd() + '/geckodriver'); } wasm-bindgen-0.2.87/.github/workflows/main.yml000064400000000000000000000474611046102023000173550ustar 00000000000000name: CI on: push: branches: [main] tags-ignore: [dev] pull_request: branches: [main] defaults: run: shell: bash # Cancel any in-flight jobs for the same PR/branch so there's only one active # at a time concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true permissions: contents: read # to fetch code (actions/checkout) jobs: # Check Code style quickly by running `rustfmt` over all code rustfmt: name: Rustfmt runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: rustup update --no-self-update stable && rustup default stable - run: rustup component add rustfmt - run: cargo fmt --all -- --check # Run `cargo check` over everything check: name: Check runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: rustup update --no-self-update stable && rustup default stable - run: cargo check --all # Run `cargo clippy` over everything clippy: name: Clippy runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: rustup update --no-self-update stable && rustup default stable - run: rustup target add wasm32-unknown-unknown - run: cargo clippy --no-deps --all-features -p wasm-bindgen-backend -- -D warnings - run: cargo clippy --no-deps --all-features -p wasm-bindgen-cli -- -D warnings - run: cargo clippy --no-deps --all-features -p wasm-bindgen-cli-support -- -D warnings - run: cargo clippy --no-deps --all-features -p example-tests -- -D warnings - run: cargo clippy --no-deps --all-features -p wasm-bindgen-externref-xform -- -D warnings - run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown -p wasm-bindgen-futures -- -D warnings - run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown -p js-sys -- -D warnings - run: cargo clippy --no-deps --all-features -p wasm-bindgen-macro -- -D warnings - run: cargo clippy --no-deps --all-features -p wasm-bindgen-macro-support -- -D warnings - run: cargo clippy --no-deps --all-features -p wasm-bindgen-multi-value-xform -- -D warnings - run: cargo clippy --no-deps --all-features -p wasm-bindgen-shared -- -D warnings - run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown -p wasm-bindgen-test -- -D warnings - run: cargo clippy --no-deps --all-features -p wasm-bindgen-test-macro -- -D warnings - run: cargo clippy --no-deps --all-features -p wasm-bindgen-threads-xform -- -D warnings - run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown -p typescript-tests -- -D warnings - run: cargo clippy --no-deps --all-features -p wasm-bindgen-wasm-conventions -- -D warnings - run: cargo clippy --no-deps --all-features -p wasm-bindgen-wasm-interpreter -- -D warnings - run: cargo clippy --no-deps --all-features -p wasm-bindgen-webidl -- -D warnings - run: cargo clippy --no-deps --all-features -p webidl-tests -- -D warnings - run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown -p web-sys -- -D warnings - run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown -- -D warnings - run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown --tests -- -D warnings - run: cargo clippy --no-deps --all-features --target wasm32-unknown-unknown -p wasm-bindgen-benchmark -- -D warnings - run: for i in examples/*/; do cd "$i"; cargo clippy --no-deps --all-features --target wasm32-unknown-unknown -- -D warnings || exit 1; cd ../..; done test_wasm_bindgen: name: "Run wasm-bindgen crate tests (unix)" runs-on: ubuntu-latest env: WASM_BINDGEN_SPLIT_LINKED_MODULES: 1 steps: - uses: actions/checkout@v3 - run: rustup update --no-self-update stable && rustup default stable - run: rustup target add wasm32-unknown-unknown - uses: actions/setup-node@v3 with: node-version: '16' - uses: ./.github/actions/setup-geckodriver - run: cargo test --target wasm32-unknown-unknown - run: cargo test --target wasm32-unknown-unknown --features serde-serialize - run: cargo test --target wasm32-unknown-unknown --features enable-interning - run: cargo test --target wasm32-unknown-unknown -p wasm-bindgen-futures - run: cargo test --target wasm32-unknown-unknown --test wasm env: WASM_BINDGEN_WEAKREF: 1 - run: cargo test --target wasm32-unknown-unknown --test wasm env: WASM_BINDGEN_WEAKREF: 1 WASM_BINDGEN_NO_DEBUG: 1 - run: cargo test --target wasm32-unknown-unknown --test wasm --features serde-serialize env: WASM_BINDGEN_WEAKREF: 1 - run: cargo test --target wasm32-unknown-unknown env: WASM_BINDGEN_EXTERNREF: 1 NODE_ARGS: --experimental-wasm-reftypes - run: cargo test --target wasm32-unknown-unknown env: WASM_BINDGEN_MULTI_VALUE: 1 test_threads: name: "Run wasm-bindgen crate tests with multithreading enabled" runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: rustup default nightly-2023-05-08 - run: rustup target add wasm32-unknown-unknown - run: rustup component add rust-src # Note: we only run the browser tests here, because wasm-bindgen doesn't support threading in Node yet. - run: | RUSTFLAGS='-C target-feature=+atomics,+bulk-memory,+mutable-globals' \ cargo test --target wasm32-unknown-unknown --test headless -Z build-std=std,panic_abort # I don't know why this is failing so comment this out for now, but ideally # this would be figured out at some point and solved. # test_wasm_bindgen_windows: # name: "Run wasm-bindgen crate tests (Windows)" # runs-on: windows-latest # steps: # - uses: actions/checkout@v3 # - run: rustup update --no-self-update stable && rustup default stable # - run: rustup target add wasm32-unknown-unknown # - uses: actions/setup-node@v3 # with: # node-version: '16' # - uses: ./.github/actions/setup-geckodriver # - run: cargo test --target wasm32-unknown-unknown # env: # RUST_LOG: wasm_bindgen_test_runner # GECKODRIVER_ARGS: --log trace # - run: cargo test --target wasm32-unknown-unknown -p js-sys # - run: cargo test --target wasm32-unknown-unknown -p webidl-tests # env: # WBINDGEN_I_PROMISE_JS_SYNTAX_WORKS_IN_NODE: 1 # - run: cargo build --manifest-path crates/web-sys/Cargo.toml --target wasm32-unknown-unknown --features "Node Window Document" test_native: name: Run native tests runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: rustup update --no-self-update stable && rustup default stable - run: rustup target add wasm32-unknown-unknown - uses: actions/setup-node@v3 with: node-version: '16' - run: cargo test - run: cargo test -p wasm-bindgen-cli-support - run: cargo test -p wasm-bindgen-cli - run: cargo test -p wasm-bindgen-externref-xform - run: cargo test -p wasm-bindgen-macro-support - run: cargo test -p wasm-bindgen-multi-value-xform - run: cargo test -p wasm-bindgen-wasm-interpreter - run: cargo test -p wasm-bindgen-futures - run: cargo test -p wasm-bindgen-shared test_web_sys: name: "Run web-sys crate tests" runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: rustup update --no-self-update stable && rustup default stable - run: rustup target add wasm32-unknown-unknown - uses: actions/setup-node@v3 with: node-version: '16' - uses: ./.github/actions/setup-geckodriver - run: cargo build --manifest-path crates/web-sys/Cargo.toml --target wasm32-unknown-unknown - run: cargo build --manifest-path crates/web-sys/Cargo.toml --target wasm32-unknown-unknown --features Node - run: cargo build --manifest-path crates/web-sys/Cargo.toml --target wasm32-unknown-unknown --features Element - run: cargo build --manifest-path crates/web-sys/Cargo.toml --target wasm32-unknown-unknown --features Window - run: cargo test --manifest-path crates/web-sys/Cargo.toml --target wasm32-unknown-unknown --all-features - run: cargo test --manifest-path crates/web-sys/Cargo.toml --target wasm32-unknown-unknown --all-features env: RUSTFLAGS: --cfg=web_sys_unstable_apis check_web_sys: name: "Verify that web-sys is compiled correctly" runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: rustup update --no-self-update stable && rustup default stable - run: cd crates/web-sys && cargo run --release --package wasm-bindgen-webidl -- webidls src/features ./Cargo.toml - run: git diff --exit-code test_js_sys: name: "Run js-sys crate tests" runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: rustup update --no-self-update stable && rustup default stable - run: rustup target add wasm32-unknown-unknown - uses: actions/setup-node@v3 with: node-version: '16' - uses: ./.github/actions/setup-geckodriver - run: cargo test -p js-sys --target wasm32-unknown-unknown - run: cargo test -p js-sys --target wasm32-unknown-unknown env: RUSTFLAGS: --cfg=js_sys_unstable_apis test_webidl: name: "Run wasm-bindgen-webidl crate tests" runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: rustup update --no-self-update stable && rustup default stable - run: rustup target add wasm32-unknown-unknown - uses: actions/setup-node@v3 with: node-version: '16' - run: cargo test -p wasm-bindgen-webidl - run: cargo test -p webidl-tests --target wasm32-unknown-unknown env: WBINDGEN_I_PROMISE_JS_SYNTAX_WORKS_IN_NODE: 1 - run: cargo test -p webidl-tests --target wasm32-unknown-unknown env: RUSTFLAGS: --cfg=web_sys_unstable_apis test_typescript_output: name: "Test TypeScript output of wasm-bindgen" runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: rustup update --no-self-update stable && rustup default stable - run: rustup target add wasm32-unknown-unknown - uses: actions/setup-node@v3 with: node-version: '16' - run: cd crates/typescript-tests && ./run.sh test_deno: name: "Build and test the deno example" runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: rustup update --no-self-update stable && rustup default stable - run: rustup target add wasm32-unknown-unknown - uses: denoland/setup-deno@v1 with: deno-version: v1.x - run: cd examples/deno && ./build.sh && deno run --allow-read test.ts test_ui: name: Run UI compile-fail tests runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: rustup update --no-self-update 1.69.0 && rustup default 1.69.0 - run: cargo test -p wasm-bindgen-macro - run: cargo test -p wasm-bindgen-test-macro build_examples: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: rustup update --no-self-update stable && rustup default stable - run: rustup target add wasm32-unknown-unknown - run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -f - run: | curl -L https://github.com/WebAssembly/binaryen/releases/download/version_112/binaryen-version_112-x86_64-linux.tar.gz -sSf > binaryen-version_112-x86_64-linux.tar.gz tar -xz -f binaryen-version_112-x86_64-linux.tar.gz binaryen-version_112/bin/wasm2js echo "$PWD/binaryen-version_112/bin" >> $GITHUB_PATH - run: | cargo build -p wasm-bindgen-cli ln -snf `pwd`/target/debug/wasm-bindgen $(dirname `which cargo`)/wasm-bindgen - run: mv _package.json package.json && npm install && rm package.json - run: | for dir in `ls examples | grep -v README | grep -v raytrace | grep -v deno | grep -v wasm-audio-worklet`; do (cd examples/$dir && (npm run build -- --output-path ../../exbuild/$dir || (./build.sh && mkdir -p ../../exbuild/$dir && cp -r ./* ../../exbuild/$dir)) ) || exit 1; done env: RUSTFLAGS: --cfg=web_sys_unstable_apis - uses: actions/upload-artifact@v3 with: name: examples1 path: exbuild build_nightly: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: rustup default nightly-2023-05-08 - run: rustup target add wasm32-unknown-unknown - run: rustup component add rust-src - run: | for dir in raytrace-parallel wasm-audio-worklet; do (cd examples/$dir && ./build.sh && mkdir -p ../../exbuild/$dir && cp -r ./* ../../exbuild/$dir ) || exit 1; done - uses: actions/upload-artifact@v3 with: name: examples2 path: exbuild test_examples: needs: - build_examples - build_nightly runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/download-artifact@v3 with: name: examples1 path: exbuild - uses: actions/download-artifact@v3 with: name: examples2 path: exbuild - run: rustup update --no-self-update stable && rustup default stable - run: cargo test -p example-tests env: EXBUILD: exbuild build_benchmarks: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: rustup update --no-self-update stable && rustup default stable - run: rustup target add wasm32-unknown-unknown - run: cargo build --manifest-path benchmarks/Cargo.toml --release --target wasm32-unknown-unknown - run: cargo run -p wasm-bindgen-cli -- target/wasm32-unknown-unknown/release/wasm_bindgen_benchmark.wasm --out-dir benchmarks/pkg --target web - uses: actions/upload-artifact@v3 with: name: benchmarks path: benchmarks dist_linux_x86_64_musl: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: rustup update --no-self-update stable && rustup default stable - run: rustup target add x86_64-unknown-linux-musl - run: sudo apt update -y && sudo apt install musl-tools -y - run: | cargo build --manifest-path crates/cli/Cargo.toml --target x86_64-unknown-linux-musl --features vendored-openssl --release strip -g target/x86_64-unknown-linux-musl/release/wasm-bindgen strip -g target/x86_64-unknown-linux-musl/release/wasm-bindgen-test-runner strip -g target/x86_64-unknown-linux-musl/release/wasm2es6js - uses: actions/upload-artifact@v3 with: name: dist_linux_x86_64_musl path: "target/x86_64-unknown-linux-musl/release/wasm*" dist_linux_aarch64_gnu: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: rustup update --no-self-update stable && rustup default stable - run: rustup target add aarch64-unknown-linux-gnu - run: sudo apt update -y && sudo apt install gcc-aarch64-linux-gnu -y - run: | cargo build --manifest-path crates/cli/Cargo.toml --target aarch64-unknown-linux-gnu --features vendored-openssl --release env: CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc - uses: actions/upload-artifact@v3 with: name: dist_linux_aarch64_gnu path: "target/aarch64-unknown-linux-gnu/release/wasm*" dist_macos_x86_64: runs-on: macos-latest steps: - uses: actions/checkout@v3 - run: rustup update --no-self-update stable && rustup default stable - run: cargo build --manifest-path crates/cli/Cargo.toml --release env: MACOSX_DEPLOYMENT_TARGET: 10.7 - uses: actions/upload-artifact@v3 with: name: dist_macos_x86_64 path: "target/release/wasm*" dist_macos_aarch64: runs-on: macos-latest steps: - uses: actions/checkout@v3 - run: rustup update --no-self-update stable && rustup default stable - run: rustup target add aarch64-apple-darwin - run: | cargo build --manifest-path crates/cli/Cargo.toml --target aarch64-apple-darwin --release env: MACOSX_DEPLOYMENT_TARGET: 10.7 - uses: actions/upload-artifact@v3 with: name: dist_macos_aarch64 path: "target/aarch64-apple-darwin/release/wasm*" dist_windows: runs-on: windows-latest steps: - uses: actions/checkout@v3 - run: rustup update --no-self-update stable && rustup default stable - run: cargo build --manifest-path crates/cli/Cargo.toml --release env: RUSTFLAGS: -Ctarget-feature=+crt-static - uses: actions/upload-artifact@v3 with: name: dist_windows path: "target/release/wasm*" doc_book: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: | curl -L https://github.com/rust-lang/mdBook/releases/download/v0.4.28/mdbook-v0.4.28-x86_64-unknown-linux-gnu.tar.gz | tar xzf - echo $PWD >> $GITHUB_PATH - run: (cd guide && mdbook build) - uses: actions/upload-artifact@v3 with: name: doc_book path: guide/book/html doc_api: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: rustup update --no-self-update nightly && rustup default nightly - run: cargo doc --no-deps --features 'serde-serialize' - run: cargo doc --no-deps --manifest-path crates/js-sys/Cargo.toml - run: cargo doc --no-deps --manifest-path crates/web-sys/Cargo.toml --all-features env: RUSTDOCFLAGS: --cfg=web_sys_unstable_apis - run: cargo doc --no-deps --manifest-path crates/futures/Cargo.toml - run: tar czvf docs.tar.gz target/doc - uses: actions/upload-artifact@v3 with: name: doc_api path: docs.tar.gz deploy: permissions: contents: write # to push changes in repo (jamesives/github-pages-deploy-action) needs: - doc_api - doc_book - dist_linux_x86_64_musl - dist_linux_aarch64_gnu - dist_macos_x86_64 - dist_macos_aarch64 - dist_windows - build_examples - build_nightly - build_benchmarks runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - run: rustup update --no-self-update nightly && rustup default nightly - uses: actions/download-artifact@v3 with: path: artifacts - run: find artifacts - run: | set -ex mkdir -p gh-release tag=`git describe --tags` mk() { target=$1 src=$2 name=wasm-bindgen-$tag-$target mkdir -p tmp/$name rm -f artifacts/$src/*.d rm -f artifacts/$src/*.pdb cp README.md \ LICENSE-MIT \ LICENSE-APACHE \ artifacts/$src/wasm* \ tmp/$name/ chmod +x tmp/$name/wasm* tar czvf gh-release/$name.tar.gz -C tmp $name } mk x86_64-unknown-linux-musl dist_linux_x86_64_musl mk aarch64-unknown-linux-gnu dist_linux_aarch64_gnu mk x86_64-apple-darwin dist_macos_x86_64 mk aarch64-apple-darwin dist_macos_aarch64 mk x86_64-pc-windows-msvc dist_windows - uses: actions/upload-artifact@v3 with: name: gh-release path: gh-release - run: | mv artifacts/doc_book gh-pages tar xf artifacts/doc_api/docs.tar.gz mv target/doc gh-pages/api mv artifacts/examples1 gh-pages/exbuild mv artifacts/examples2/* gh-pages/exbuild mv artifacts/benchmarks gh-pages/benchmarks tar czf gh-pages.tar.gz gh-pages - uses: actions/upload-artifact@v3 with: name: gh-pages path: gh-pages.tar.gz - uses: JamesIves/github-pages-deploy-action@v4.4.1 with: branch: gh-pages folder: gh-pages single-commit: true if: github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: softprops/action-gh-release@v1 if: startsWith(github.ref, 'refs/tags/') with: files: "gh-release/*.tar.gz" wasm-bindgen-0.2.87/.gitignore000064400000000000000000000002001046102023000142550ustar 00000000000000.idea /target/ **/*.rs.bk Cargo.lock node_modules package-lock.json npm-shrinkwrap.json yarn.lock /publish /publish.exe .vscode wasm-bindgen-0.2.87/CHANGELOG.md000064400000000000000000001756661046102023000141330ustar 00000000000000# `wasm-bindgen` Change Log -------------------------------------------------------------------------------- ## [0.2.87](https://github.com/rustwasm/wasm-bindgen/compare/0.2.86...0.2.87) Released 2023-06-12. ### Added * Implemented `IntoIterator` for `Array`. [#3477](https://github.com/rustwasm/wasm-bindgen/pull/3477) ### Changed * Deprecate `HtmlMenuItemElement` and parts of `HtmlMenuElement`. [#3448](https://github.com/rustwasm/wasm-bindgen/pull/3448) * Stabilize `ResizeObserver`. [#3459](https://github.com/rustwasm/wasm-bindgen/pull/3459) ### Fixed * Take alignment into consideration during (de/re)allocation. [#3463](https://github.com/rustwasm/wasm-bindgen/pull/3463) -------------------------------------------------------------------------------- ## 0.2.86 Released 2023-05-16. [changes](https://github.com/rustwasm/wasm-bindgen/compare/0.2.85...0.2.86) -------------------------------------------------------------------------------- ## 0.2.85 Released 2023-05-09. [changes](https://github.com/rustwasm/wasm-bindgen/compare/0.2.84...0.2.85) -------------------------------------------------------------------------------- ## 0.2.84 Released 2023-02-01. [changes](https://github.com/rustwasm/wasm-bindgen/compare/0.2.83...0.2.84) -------------------------------------------------------------------------------- ## 0.2.83 Released 2022-09-12. [changes](https://github.com/rustwasm/wasm-bindgen/compare/0.2.82...0.2.83) -------------------------------------------------------------------------------- ## 0.2.82 Released 2022-07-25. [changes](https://github.com/rustwasm/wasm-bindgen/compare/0.2.81...0.2.82) -------------------------------------------------------------------------------- ## 0.2.81 Released 2022-06-14. [changes](https://github.com/rustwasm/wasm-bindgen/compare/0.2.80...0.2.81) -------------------------------------------------------------------------------- ## 0.2.80 Released 2022-04-04. [changes](https://github.com/rustwasm/wasm-bindgen/compare/0.2.79...0.2.80) -------------------------------------------------------------------------------- ## 0.2.79 Released 2022-01-19. [changes](https://github.com/rustwasm/wasm-bindgen/compare/0.2.78...0.2.79) -------------------------------------------------------------------------------- ## 0.2.78 Released 2021-09-15. [changes](https://github.com/rustwasm/wasm-bindgen/compare/0.2.77...0.2.78) -------------------------------------------------------------------------------- ## 0.2.77 Released 2021-09-08. [changes](https://github.com/rustwasm/wasm-bindgen/compare/0.2.76...0.2.77) -------------------------------------------------------------------------------- ## 0.2.76 Released 2021-08-19. [changes](https://github.com/rustwasm/wasm-bindgen/compare/0.2.75...0.2.76) -------------------------------------------------------------------------------- ## 0.2.75 Released 2021-08-02. [changes](https://github.com/rustwasm/wasm-bindgen/compare/0.2.74...0.2.75) -------------------------------------------------------------------------------- ## 0.2.74 Released 2021-05-10. [changes](https://github.com/rustwasm/wasm-bindgen/compare/0.2.73...0.2.74) -------------------------------------------------------------------------------- ## 0.2.73 Released 2021-03-29. [changes](https://github.com/rustwasm/wasm-bindgen/compare/0.2.72...0.2.73) -------------------------------------------------------------------------------- ## 0.2.72 Released 2021-03-18. [changes](https://github.com/rustwasm/wasm-bindgen/compare/0.2.71...0.2.72) -------------------------------------------------------------------------------- ## 0.2.71 Released 2021-02-26. [changes](https://github.com/rustwasm/wasm-bindgen/compare/0.2.70...0.2.71) -------------------------------------------------------------------------------- ## 0.2.70 Released 2021-01-25. [changes](https://github.com/rustwasm/wasm-bindgen/compare/0.2.69...0.2.70) -------------------------------------------------------------------------------- ## 0.2.69 Released 2020-11-30. ### Added * Unstable bindings for WebBluetooth have been added. [#2311](https://github.com/rustwasm/wasm-bindgen/pull/2311) * Unstable bindings for WebUSB have been added. [#2345](https://github.com/rustwasm/wasm-bindgen/pull/2345) * Renaming a struct field with `js_name` is now supported. [#2360](https://github.com/rustwasm/wasm-bindgen/pull/2360) * The WebGPU WebIDL has been updated. [#2353](https://github.com/rustwasm/wasm-bindgen/pull/2353) ### Fixed * The ImageCapture APIs of web-sys have been moved to unstable and were fixed. [#2348](https://github.com/rustwasm/wasm-bindgen/pull/2348) * Bindings for `waitAsync` have been updated. [#2362](https://github.com/rustwasm/wasm-bindgen/pull/2362) -------------------------------------------------------------------------------- ## 0.2.68 Released 2020-09-08. ### Added * Add userVisibleOnly property to PushSubscriptionOptionsInit. [#2288](https://github.com/rustwasm/wasm-bindgen/pull/2288) ### Fixed * TypeScript files now import `*.wasm` instead of bare files. [#2283](https://github.com/rustwasm/wasm-bindgen/pull/2283) * Usage of `externref` now appropriately resizes the table by using 2x the previous capacity, fixing a performance issue with lots of externref objects. [#2294](https://github.com/rustwasm/wasm-bindgen/pull/2294) * Compatibility with the latest Firefox WebDriver has been fixed. [#2301](https://github.com/rustwasm/wasm-bindgen/pull/2301) * Non deterministic output with closures has been fixed. [#2304](https://github.com/rustwasm/wasm-bindgen/pull/2304) ### Updated * The WebGPU WebIDL was updated. [#2267](https://github.com/rustwasm/wasm-bindgen/pull/2267) -------------------------------------------------------------------------------- ## 0.2.67 Released 2020-07-28. ### Added * A `--reference-types` flag was added to the CLI. [#2257](https://github.com/rustwasm/wasm-bindgen/pull/2257) ### Fixed * Breakage with `Closure::forget` in 0.2.66 was fixed. [#2258](https://github.com/rustwasm/wasm-bindgen/pull/2258) -------------------------------------------------------------------------------- ## 0.2.66 Released 2020-07-28. ### Added * Reverse mappings from value to name are now available in JS bindings of enums. [#2240](https://github.com/rustwasm/wasm-bindgen/pull/2240) ### Fixed * Functions using a return pointer in threaded programs now correctly load and store return values in a way that doesn't interfere with other threads. [#2249](https://github.com/rustwasm/wasm-bindgen/pull/2249) * Support for weak references has been updated and a `--weak-refs` flag is now available in the CLI for enabling weak references. [#2248](https://github.com/rustwasm/wasm-bindgen/pull/2248) -------------------------------------------------------------------------------- ## 0.2.65 Released 2020-07-15. ### Added * Functions from JS can now be natively imported as `async` and will use promises under the hood. [#2196](https://github.com/rustwasm/wasm-bindgen/pull/2196) ### Changed * Encoding for the reference types proposal has been updated to the latest version of the spec. [#2234](https://github.com/rustwasm/wasm-bindgen/pull/2234) -------------------------------------------------------------------------------- ## 0.2.64 Released 2020-06-29. ### Added * Nested namespaces for imports can now be specified. [#2105](https://github.com/rustwasm/wasm-bindgen/pull/2105) * A `deno` target has been added. [#2176](https://github.com/rustwasm/wasm-bindgen/pull/2176) ### Fixed * Getters/setters that consume the original object have been fixed to invalidate the object correctly. [#2172](https://github.com/rustwasm/wasm-bindgen/pull/2172) * Compatibility with nightly threading in LLVM has been fixed. [#2183](https://github.com/rustwasm/wasm-bindgen/pull/2183) * Trailing space in generated doc comments is now removed. [#2210](https://github.com/rustwasm/wasm-bindgen/pull/2210) -------------------------------------------------------------------------------- ## 0.2.63 Released 2020-05-27. ### Added * A new example about using WebRTC has been added. [#2131](https://github.com/rustwasm/wasm-bindgen/pull/2131) * The `Blob.stream()` method has been added. [#2140](https://github.com/rustwasm/wasm-bindgen/pull/2140) [#2142](https://github.com/rustwasm/wasm-bindgen/pull/2142) ### Changed * The encoding and implementation of WebAssembly reference types has been sync'd with the latest upstream specification. [#2125](https://github.com/rustwasm/wasm-bindgen/pull/2125) ### Fixed * Test functions names will no longer collide with test intrinsic names. [#2123](https://github.com/rustwasm/wasm-bindgen/pull/2123) * Fixed warnings with `#[must_use]` types in generated code. [#2144](https://github.com/rustwasm/wasm-bindgen/pull/2144) * Fixed compatibility with latest Rust nightlies. [#2159](https://github.com/rustwasm/wasm-bindgen/pull/2159) -------------------------------------------------------------------------------- ## 0.2.62 Released 2020-05-01. ### Fixed * Usage of `require` has been fixed with Webpack 5. [#2115](https://github.com/rustwasm/wasm-bindgen/pull/2115) -------------------------------------------------------------------------------- ## 0.2.61 Released 2020-04-29. ### Added * Exported Rust `enum` types can now be renamed with `js_name`. [#2071](https://github.com/rustwasm/wasm-bindgen/pull/2071) * More comments are copied to JS/TS files, and comments should no longer accidentally have escape sequences in them. [#2070](https://github.com/rustwasm/wasm-bindgen/pull/2070) * Experimental bindings for the Clipboard browser APIs have been added. [#2100](https://github.com/rustwasm/wasm-bindgen/pull/2100) ### Changed * WebGPU bindings have been updated. [#2080](https://github.com/rustwasm/wasm-bindgen/pull/2080) * `setBindGroup` methods for WebIDL now take immutable slices instead of mutable slices. [#2087](https://github.com/rustwasm/wasm-bindgen/pull/2087) * JS code generation for `catch` functions has been improved. [#2098](https://github.com/rustwasm/wasm-bindgen/pull/2098) * Usage of NPM dependencies with the `web` target is no longer an error. [#2103](https://github.com/rustwasm/wasm-bindgen/pull/2103) ### Fixed * Combining `js_name` with `getter` and `setter` has now been fixed. [#2074](https://github.com/rustwasm/wasm-bindgen/pull/2074) * Importing global names which conflict with other namespaces should now work correctly. [#2057](https://github.com/rustwasm/wasm-bindgen/pull/2057) * Acquiring the global JS object has been fixed for Firefox extension content scripts. [#2099](https://github.com/rustwasm/wasm-bindgen/pull/2099) * The output of `wasm-bindgen` is now compatible with Webpack 5 and the updated version of the wasm ESM integration specification. [#2110](https://github.com/rustwasm/wasm-bindgen/pull/2099) -------------------------------------------------------------------------------- ## 0.2.60 Released 2020-03-25. ### Added * The `js_sys` types are now more accurately reflected in TypeScript. [#2028](https://github.com/rustwasm/wasm-bindgen/pull/2028) * The timeout in `wasm-bindgen-test-runner`'s timeout can now be configured via `WASM_BINDGEN_TEST_TIMEOUT`. [#2036](https://github.com/rustwasm/wasm-bindgen/pull/2036) * WebIDL for WebXR has been added. [#2000](https://github.com/rustwasm/wasm-bindgen/pull/2000) ### Changed * The WebIDL for WebGPU has been updated. [#2037](https://github.com/rustwasm/wasm-bindgen/pull/2037) -------------------------------------------------------------------------------- ## 0.2.59 Released 2020-03-03. ### Added * The `js_sys::Number` type now has a number of JS-number associated constants on it now. [#1965](https://github.com/rustwasm/wasm-bindgen/pull/1965) * The `getTransform` method on `CanvasRenderingContext2D` has been added. [#1966](https://github.com/rustwasm/wasm-bindgen/pull/1966) * Initial experimental support was added for electron targets with a new `--omit-imports` flag. [#1958](https://github.com/rustwasm/wasm-bindgen/pull/1958) * Optional struct fields are now reflected idiomatically in TypeScript. [#1990](https://github.com/rustwasm/wasm-bindgen/pull/1990) * Typed arrays in `js_sys` now have `get_index` and `set_index` methods. [#2001](https://github.com/rustwasm/wasm-bindgen/pull/2001) * The `web_sys::Blob` type has been updated with `arrayBuffer` and `text` methods. [#2008](https://github.com/rustwasm/wasm-bindgen/pull/2008) * Support for unstable browser interfaces has now been added. By compiling `web_sys` with `--cfg web_sys_unstable_apis` (typically via `RUSTFLAGS`) you'll be able to access all bound WebIDL functions, even those like GPU support on the web, which has now also had its WebIDL updated. [#1997](https://github.com/rustwasm/wasm-bindgen/pull/1997) * The compile time for `web_sys` has been massively reduced by pre-generating Rust code from WebIDL. It is also readable now since it generates `#[wasm_bindgen]` annotations instead of expanded code. [#2012](https://github.com/rustwasm/wasm-bindgen/pull/2012) * A new `typescript_type` attribute can be used to specify the TypeScript type for an `extern` type. [#2012](https://github.com/rustwasm/wasm-bindgen/pull/2012) * It is now possible to use string values with `#[wasm_bindgen]` `enum`s. [#2012](https://github.com/rustwasm/wasm-bindgen/pull/2012) * A new `skip_tyepscript` attribute is recognized to skip generating TypeScript bindings for a function or type. [#2016](https://github.com/rustwasm/wasm-bindgen/pull/2016) ### Changed * More `uniformMatrix*` bindings now are whitelisted take shared slice instead of a mutable slice. [#1957](https://github.com/rustwasm/wasm-bindgen/pull/1957) * Non-`dependency` keys in `package.json` are now ignored instead of error'd about. [#1969](https://github.com/rustwasm/wasm-bindgen/pull/1969) * WebGPU has been removed from `web_sys` since it was outdated and didn't work anywhere anyway. [#1972](https://github.com/rustwasm/wasm-bindgen/pull/1972) * The JS heap of objects managed by wasm-bindgen has had its definition tightended up a bit. [#1987](https://github.com/rustwasm/wasm-bindgen/pull/1987) * The `self` identifier is no longer used on the `no-modules` target, making it a bit more flexible in more environments. [#1995](https://github.com/rustwasm/wasm-bindgen/pull/1995) * The wasm-loading logic is now more flexible and can take promises as well. [#1996](https://github.com/rustwasm/wasm-bindgen/pull/1996) * JS glue for closures is now deduplicated. [#2002](https://github.com/rustwasm/wasm-bindgen/pull/2002) * The `web_sys` crate now emits more accurate TypeScript definitions using named types instead of `any` everywhere. [#1998](https://github.com/rustwasm/wasm-bindgen/pull/1998) * The `send_with_u8_array` methods in `web_sys` are whitelisted to take shared slices instead of mutable slices. [#2015](https://github.com/rustwasm/wasm-bindgen/pull/2015) -------------------------------------------------------------------------------- ## 0.2.58 Released 2020-01-07. ### Added * When using the `no-modules` output type the initialization path for the wasm file is now optional if it can be inferred from the current JS script. [#1938](https://github.com/rustwasm/wasm-bindgen/pull/1938) ### Fixed * TypeScript for struct methods that have floats has been fixed. [#1945](https://github.com/rustwasm/wasm-bindgen/pull/1945) -------------------------------------------------------------------------------- ## 0.2.57 Released 2020-01-06. ### Fixed * The `js_sys::Promise` type is now marked as `#[must_use]` [#1927](https://github.com/rustwasm/wasm-bindgen/pull/1927) * Duplicate imports of the same name are now handled correctly again. [#1942](https://github.com/rustwasm/wasm-bindgen/pull/1942) -------------------------------------------------------------------------------- ## 0.2.56 Released 2019-12-20. ### Added * Added a `#[wasm_bindgen(inspectable)]` attribute for exported objects to generate `toJSON` and `toString` implementations. [#1876](https://github.com/rustwasm/wasm-bindgen/pull/1876) * Support for the most recent interface types proposal has been implemented. [#1882](https://github.com/rustwasm/wasm-bindgen/pull/1882) * Initial support for async iterators has been added. [#1895](https://github.com/rustwasm/wasm-bindgen/pull/1895) * Support for an `async` start function was added. [#1905](https://github.com/rustwasm/wasm-bindgen/pull/1905) * `Array::iter` and `Array::to_vec` methods were added to js-sys. [#1909](https://github.com/rustwasm/wasm-bindgen/pull/1909) ### Fixed * Another webkit-specific WebIDL construct was fixed in web-sys. [#1865](https://github.com/rustwasm/wasm-bindgen/pull/1865) -------------------------------------------------------------------------------- ## 0.2.55 Released 2019-11-19. ### Fixed * Running `wasm-bindgen` over empty anyref modules now works again. [#1861](https://github.com/rustwasm/wasm-bindgen/pull/1861) * Support for multi-value JS engines has been fixed as a wasm interface types polyfill. [#1863](https://github.com/rustwasm/wasm-bindgen/pull/1863) -------------------------------------------------------------------------------- ## 0.2.54 Released 2019-11-07. ### Added * A safe `to_vec` method has been added for typed arrays. [#1844](https://github.com/rustwasm/wasm-bindgen/pull/1844) * A unsafe method `view_mut_raw` has been added to typed arrays. [#1850](https://github.com/rustwasm/wasm-bindgen/pull/1850) * The `HTMLImageElement` WebIDL has been updated with recent features. [#1842](https://github.com/rustwasm/wasm-bindgen/pull/1842) * Binary crates are now supported and `fn main` will be automatically executed like the `start` function. [#1843](https://github.com/rustwasm/wasm-bindgen/pull/1843) ### Changed * Some JS glue generation has been tweaked to avoid TypeScript warnings. [#1852](https://github.com/rustwasm/wasm-bindgen/pull/1852) -------------------------------------------------------------------------------- ## 0.2.53 Released 2019-10-29. ### Fixed * A bug with the experimental support for multi-value interface types has been fixed. [#1839](https://github.com/rustwasm/wasm-bindgen/pull/1839) -------------------------------------------------------------------------------- ## 0.2.52 Released 2019-10-24. ### Added * The support for wasm-interface-types now uses multi-value by default. [#1805](https://github.com/rustwasm/wasm-bindgen/pull/1805) * The Worklet IDL has been updated. [#1817](https://github.com/rustwasm/wasm-bindgen/pull/1817) * The HTMLInputElement type has selectionStart and selectionEnd properties now. [#1811](https://github.com/rustwasm/wasm-bindgen/pull/1811) * An `unintern` function has been added to remove an interned string from the cache. [#1828](https://github.com/rustwasm/wasm-bindgen/pull/1828) ### Changed * Some WebIDL indexing getters have been corrected to reflect that they can throw and/or return `undefined` [#1789](https://github.com/rustwasm/wasm-bindgen/pull/1789) ### Fixed * A bug with `TextDecoder` and Safari has been fxied [#1789](https://github.com/rustwasm/wasm-bindgen/pull/1789) -------------------------------------------------------------------------------- ## 0.2.51 Released 2019-09-26. ### Added * The `wasm-bindgen-futures` and `wasm-bindgen-test` crates now require Nightly Rust and have a new major version published as a result. These crates now support `async`/`await` by default, and they will be supported in the stable Rust 1.39.0 release. The previous versions of crates will continue to work on stable today. [#1741](https://github.com/rustwasm/wasm-bindgen/pull/1741) * Using `#[wasm_bindgen]` on an `async` function will now work and return a `Promise` on the JS side of things. [#1754](https://github.com/rustwasm/wasm-bindgen/pull/1754) * More helper methods for `js_sys::Array` have been added. [#1749](https://github.com/rustwasm/wasm-bindgen/pull/1749) * Initial support for the WebAssembly multi-value proposal has been added. [#1764](https://github.com/rustwasm/wasm-bindgen/pull/1764) * Constructors for `js_sys::Date` with optional parameters has been added. [#1759](https://github.com/rustwasm/wasm-bindgen/pull/1759) * Headless tests can now be run against a remote webdriver client [#1744](https://github.com/rustwasm/wasm-bindgen/pull/1744) ### Changed * The `passStringToWasm` function has been optimized for size. [#1736](https://github.com/rustwasm/wasm-bindgen/pull/1736) ### Fixed * BOM markers will not be preserved when passing strings to/from wasm. [#1730](https://github.com/rustwasm/wasm-bindgen/pull/1730) * Importing a `static` value which isn't a `JsValue` has been fixed. [#1784](https://github.com/rustwasm/wasm-bindgen/pull/1784) * Converting `undefined` to a Rust value via `into_serde` has been fixed. [#1783](https://github.com/rustwasm/wasm-bindgen/pull/1783) * Routine errors are no longer erroneously logged in debug mode. [#1788](https://github.com/rustwasm/wasm-bindgen/pull/1788) -------------------------------------------------------------------------------- ## 0.2.50 Released 2019-08-19. ### Added * Experimental support with a `WASM_INTERFACE_TYPES=1` environment variable has been added to emit a Wasm Interface Types custom section, making the output of `wasm-bindgen` a single standalone WebAssembly file. [#1725](https://github.com/rustwasm/wasm-bindgen/pull/1725) ### Fixed * Unrelated errors are now no longer accidentally swallowed by the `instantiateStreaming` fallback. [#1723](https://github.com/rustwasm/wasm-bindgen/pull/1723) -------------------------------------------------------------------------------- ## 0.2.49 Released 2019-08-14. ### Added * Add binding for `Element.getElementsByClassName`. [#1665](https://github.com/rustwasm/wasm-bindgen/pull/1665) * `PartialEq` and `Eq` are now implemented for all `web-sys` types. [#1673](https://github.com/rustwasm/wasm-bindgen/pull/1673) * The `wasm-bindgen-futures` crate now has support for futures when the experimental WebAssembly threading feature is enabled. [#1514](https://github.com/rustwasm/wasm-bindgen/pull/1514) * A new `enable-interning` feature is available to intern strings and reduce the cost of transferring strings across the JS/Rust boundary. [#1612](https://github.com/rustwasm/wasm-bindgen/pull/1612) * The `wasm-bindgen` CLI has experimental support for reading native `webidl-bindings` custom sections and generating JS glue. This support is in addition to Rust's own custom sections and allows using `wasm-bindgen` with binaries produced by other than rustc possibly. [#1690](https://github.com/rustwasm/wasm-bindgen/pull/1690) * New environment variables have been added to configure webdriver startup arguments. [#1703](https://github.com/rustwasm/wasm-bindgen/pull/1703) * New `JsValue::{is_truthy,is_falsy}` methods are now available. [#1638](https://github.com/rustwasm/wasm-bindgen/pull/1638) ### Changed * JS import shims are now skipped again when they are unnecessary. [#1654](https://github.com/rustwasm/wasm-bindgen/pull/1654) * WebAssembly output files now directly embed the module/name for imports if supported for the target and the import, reducing JS shims even further. [#1689](https://github.com/rustwasm/wasm-bindgen/pull/1689) ### Fixed * Support for threads have been updated for LLVM 9 and nightly Rust. [#1675](https://github.com/rustwasm/wasm-bindgen/pull/1675) [#1688](https://github.com/rustwasm/wasm-bindgen/pull/1688) * The `anyref` passes in `wasm-bindgen` have seen a number of fixes to improve their correctness and get the full test suite running. [#1692](https://github.com/rustwasm/wasm-bindgen/pull/1692) [#1704](https://github.com/rustwasm/wasm-bindgen/pull/1704) * Support for `futures-preview 0.3.0-alpha.18` has been added to `wasm-bindgen-futures`. [#1716](https://github.com/rustwasm/wasm-bindgen/pull/1716) -------------------------------------------------------------------------------- ## 0.2.48 Released 2019-07-11. ### Added * All typed arrays now implement `From` for the corresponding Rust slice type, providing a safe way to create an instance which copies the data. [#1620](https://github.com/rustwasm/wasm-bindgen/pull/1620) * `Function::bind{2,3,4}` are now available in `js-sys`. [#1633](https://github.com/rustwasm/wasm-bindgen/pull/1633) ### Changed * More WebGL methods have been updated to use shared slices instead of mutable slices. [#1639](https://github.com/rustwasm/wasm-bindgen/pull/1639) * When using the `bundler` target the import of the wasm file now uses the `.wasm` extension to ensure a wasm file is loaded. [#1646](https://github.com/rustwasm/wasm-bindgen/pull/1646) * The old internal `Stack` trait has been removed since it is no longer used. [#1624](https://github.com/rustwasm/wasm-bindgen/pull/1624) ### Fixed * The `js_sys::global()` accessor now attempts other strategies before falling back to a `Function` constructor which can violate some strict CSP settings. [#1650](https://github.com/rustwasm/wasm-bindgen/pull/1649) * Dropping a `JsFuture` no longer logs a benign error to the console. [#1649](https://github.com/rustwasm/wasm-bindgen/pull/1649) * Fixed an assertion which could happen in some modules when generating bindings. [#1617](https://github.com/rustwasm/wasm-bindgen/pull/1617) -------------------------------------------------------------------------------- ## 0.2.47 Released 2019-06-19. ### Changed * The `HtmlHyperlinkElement` should now include more native methods after a small edit to the WebIDL. [#1604](https://github.com/rustwasm/wasm-bindgen/pull/1604) * Duplicate names for getters/setters now have a first-class `wasm-bindgen` error. [#1605](https://github.com/rustwasm/wasm-bindgen/pull/1605) ### Fixed * TypeScript definition of `init` with `--target web` now reflects that the first argument is optional. [#1599](https://github.com/rustwasm/wasm-bindgen/pull/1599) * A panic with the futures 0.3 support has been fixed. [#1598](https://github.com/rustwasm/wasm-bindgen/pull/1598) * More slice types are recognized as becoming immutable in some WebIDL methods. [#1602](https://github.com/rustwasm/wasm-bindgen/pull/1602) * The function table is now no longer too aggressively removed. [#1606](https://github.com/rustwasm/wasm-bindgen/pull/1606) -------------------------------------------------------------------------------- ## 0.2.46 Released 2019-06-14. ### Added * Bindings for `Array#flat` and `Array#flatMap` have been added. [#1573](https://github.com/rustwasm/wasm-bindgen/pull/1573) * All `#[wasm_bindgen]` types now `AsRef` to themselves. [#1583](https://github.com/rustwasm/wasm-bindgen/pull/1583) * When using `--target web` the path passed to `init` is no longer required. [#1579](https://github.com/rustwasm/wasm-bindgen/pull/1579) ### Fixed * Some diagnostics related to compiler errors in `#[wasm_bindgen]` have been improved. [#1550](https://github.com/rustwasm/wasm-bindgen/pull/1550) * The support for weak references has been updated to the current JS proposal. [#1557](https://github.com/rustwasm/wasm-bindgen/pull/1557) * Documentation and feature gating for web-sys dictionaries has improved. [#1572](https://github.com/rustwasm/wasm-bindgen/pull/1572) * Getter and setter TypeScript has been fixed. [#1577](https://github.com/rustwasm/wasm-bindgen/pull/1577) * The `env_logger` crate and its tree of dependencies is no longer required to build `web-sys`. [#1586](https://github.com/rustwasm/wasm-bindgen/pull/1586) -------------------------------------------------------------------------------- ## 0.2.45 Released 2019-05-20. ### Fixed * Using `__wbindgen_cb_forget` on `--target web` has been fixed. [#1544](https://github.com/rustwasm/wasm-bindgen/pull/1544) ### Changed * More whitelists have been added for `web-sys` to use shared slices instead of mutable slices. [#1539](https://github.com/rustwasm/wasm-bindgen/pull/1539) -------------------------------------------------------------------------------- ## 0.2.44 Released 2019-05-16. ### Added * Support for exporting "fields" on JS objects wrapping Rust structs which are hooked up to getters/setters has been added. This is in addition to `pub` struct fields and allows performing more complicated computations in getters/setters. [#1440](https://github.com/rustwasm/wasm-bindgen/pull/1440) * Support for futures 0.3 (and `async` / `await` syntax) has been added to the `wasm-bindgen-futures` crate. [#1507](https://github.com/rustwasm/wasm-bindgen/pull/1507) * Stacks of imported JS functions that throw and aren't marked `catch` are now logged in debug mode. [#1466](https://github.com/rustwasm/wasm-bindgen/pull/1466) * A utility for counting the size of the `anyref` heap has been added. [#1521](https://github.com/rustwasm/wasm-bindgen/pull/1521) * Passing ASCII-only strings to WASM should now be significantly faster. [#1470](https://github.com/rustwasm/wasm-bindgen/pull/1470) * The `selectionStart` and `selectionEnd` APIs of text areas have been enabled. [#1533](https://github.com/rustwasm/wasm-bindgen/pull/1533) ### Changed * Some more methods in `web-sys` now take immutable slices instead of mutable ones. [#1508](https://github.com/rustwasm/wasm-bindgen/pull/1508) * TypeScript bindings for `Option` arguments now use `foo?` where possible. [#1483](https://github.com/rustwasm/wasm-bindgen/pull/1483) ### Fixed * Unnecessary bindings to `__wbindgen_object_drop_ref` have been fixed. [#1504](https://github.com/rustwasm/wasm-bindgen/pull/1504) * Some direct imports have been fixed for `--target web`. [#1503](https://github.com/rustwasm/wasm-bindgen/pull/1503) * Both importing and exporting the same name has been fixed. [#1506](https://github.com/rustwasm/wasm-bindgen/pull/1506) * TypeScript typings for `init` in `--target web` have been fixed. [#1520](https://github.com/rustwasm/wasm-bindgen/pull/1520) * Calling a dropped `Closure` should no longer "segfault" but produce a clear error. [#1530](https://github.com/rustwasm/wasm-bindgen/pull/1530) -------------------------------------------------------------------------------- ## 0.2.43 Released 2019-04-29. ### Added * Support for `isize` and `usize` arrays has been added. [#1448](https://github.com/rustwasm/wasm-bindgen/pull/1448) * Support customizing `dyn_ref` and friends via a new `is_type_of` attribute and apply it to some `js_sys` bindings. [#1405](https://github.com/rustwasm/wasm-bindgen/pull/1405) [#1450](https://github.com/rustwasm/wasm-bindgen/pull/1450) [#1490](https://github.com/rustwasm/wasm-bindgen/pull/1490) * A new `skip` attribute to `#[wasm_bindgen]` has been added to skip fields and methods when generating bindings. [#1410](https://github.com/rustwasm/wasm-bindgen/pull/1410) * More bindings have been added to `web-sys` for interfaces tagged with `[NoInterfaceObject]` in WebIDL. These types always fail `dyn_ref` and friends and must be manually casted into. [#1449](https://github.com/rustwasm/wasm-bindgen/pull/1449) * Added `Debug for JsFuture`. [#1477](https://github.com/rustwasm/wasm-bindgen/pull/1477) * Initial bindings for `Atomics` and `SharedArrayBuffer` have been added to `js_sys`. [#1463](https://github.com/rustwasm/wasm-bindgen/pull/1463) * Bindings for `Object.fromEntries` has been added to `js_sys`. [#1456](https://github.com/rustwasm/wasm-bindgen/pull/1456) * Tuple structs exported to JS now have indexed struct properties. [#1467](https://github.com/rustwasm/wasm-bindgen/pull/1467) * Binding for `new Function(args, body)` has been added to `js_sys`. [#1492](https://github.com/rustwasm/wasm-bindgen/pull/1492) * Bindings for some variadic functions have been added to `js_sys`. [#1491](https://github.com/rustwasm/wasm-bindgen/pull/1491) ### Changed * Many `js-sys` types have received various tweaks and improvements to ensure they're consistent and work similarly to native Rust types. [#1447](https://github.com/rustwasm/wasm-bindgen/pull/1447) [#1444](https://github.com/rustwasm/wasm-bindgen/pull/1444) [#1473](https://github.com/rustwasm/wasm-bindgen/pull/1473) * Dummy types in `js-sys` only used to namespace methods were removed and now modules are used for namespacing instead. [#1451](https://github.com/rustwasm/wasm-bindgen/pull/1451) * Bindings in `web-sys` are formatted by default for ease of usage in IDEs. [#1461](https://github.com/rustwasm/wasm-bindgen/pull/1461) ### Fixed * Documentation for Rust methods now show up in TypeScript as well. [#1472](https://github.com/rustwasm/wasm-bindgen/pull/1472) -------------------------------------------------------------------------------- ## 0.2.42 Released 2019-04-11. ### Fixed * Fixed an issue in Firefox where using `encodeInto` accidentally caused empty strings to keep getting passed to Rust. [#1434](https://github.com/rustwasm/wasm-bindgen/pull/1434) -------------------------------------------------------------------------------- ## 0.2.41 Released 2019-04-10. ### Added * Initial support for transitive NPM dependencies has been added. [#1305](https://github.com/rustwasm/wasm-bindgen/pull/1305) * The `constructor` property of `Object` is now bound in `js-sys`. [#1403](https://github.com/rustwasm/wasm-bindgen/pull/1403) * The `Closure` type now always implements `Debug`. [#1408](https://github.com/rustwasm/wasm-bindgen/pull/1408) * Closures which take one `&T` argument are now supported. More implementations may be added in the future, but for now it's just one argument closures. [#1417](https://github.com/rustwasm/wasm-bindgen/pull/1417) * The TypeScript bindings for `--web` now expose the `init` function. [#1412](https://github.com/rustwasm/wasm-bindgen/pull/1412) * A `js_sys::JsString::is_valid_utf16` method has been added to handle unpaired surrogates in JS strings. Surrounding documentation has also been updated to document this potential pitfall. [#1416](https://github.com/rustwasm/wasm-bindgen/pull/1416) * A `wasm_bindgen::function_table()` function has been added to expose the `WebAssembly.Table` and get access to it in wasm code. [#1431](https://github.com/rustwasm/wasm-bindgen/pull/1431) ### Fixed * Reexporting the `wasm_bindgen` macro in crates has been fixed. [#1359](https://github.com/rustwasm/wasm-bindgen/pull/1359) * Returning `u32` to JS has been fixed where large `u32` values would show up in JS as large negative numbers. [#1401](https://github.com/rustwasm/wasm-bindgen/pull/1401) * Manual instantiation with `WebAssembly.Module` has been fixed. [#1419](https://github.com/rustwasm/wasm-bindgen/pull/1419) * Error message for non-`Copy` public struct fields has been improved. [#1430](https://github.com/rustwasm/wasm-bindgen/pull/1430) ### Changed * Performance of passing strings to Rust in Node.js has been improved. [#1391](https://github.com/rustwasm/wasm-bindgen/pull/1391) * Performance of `js_sys::try_iter` has been improved. [#1393](https://github.com/rustwasm/wasm-bindgen/pull/1393) * Performance of using `TextEncoder#encodeInto` has been improved. [#1414](https://github.com/rustwasm/wasm-bindgen/pull/1414) -------------------------------------------------------------------------------- ## 0.2.40 Released 2019-03-21. ### Added * TypeScript and JS generation will now attempt to preserve argument names in the generated JS where possible. [#1344](https://github.com/rustwasm/wasm-bindgen/pull/1344) * Enable `Option` support for enums defined in WebIDL. [#1350](https://github.com/rustwasm/wasm-bindgen/pull/1350) * Add a `raw_module` attribute to `#[wasm_bindgen]` which is the same as `module` except doesn't attempt to recognize `./`, `../`, `or `/` prefixed paths. [#1353](https://github.com/rustwasm/wasm-bindgen/pull/1353) * The `wasm-bindgen` CLI flags have now all been renamed under a `--target` flag. Instead of `--web` you'll now pass `--target web`, for example. This increases consistency between the `wasm-bindgen` and `wasm-pack` CLI. [#1369](https://github.com/rustwasm/wasm-bindgen/pull/1369) ### Fixed * Definitions for `TypedArray` imports of `js-sys` have been unified with a macro to improve consistency and fix future bugs. [#1371](https://github.com/rustwasm/wasm-bindgen/pull/1371) * Usage of `--no-modules` in CloudFlare workers should now work by default. [#1384](https://github.com/rustwasm/wasm-bindgen/pull/1384) * A use-after-free when a closure is reinvoked after being destroyed on the Rust die has been fixed. [#1385](https://github.com/rustwasm/wasm-bindgen/pull/1385) * A bug causing nondeterministic generation of JS bindings has been fixed. [#1383](https://github.com/rustwasm/wasm-bindgen/pull/1383) -------------------------------------------------------------------------------- ## 0.2.39 Released 2018-03-13. ### Added * Crates can now import locally written JS snippets to get bundled into the final output. See [RFC 6] for more details as well as the PR. [#1295](https://github.com/rustwasm/wasm-bindgen/pull/1295) [RFC 6]: https://github.com/rustwasm/rfcs/pull/6 ### Changed * A typo in the return value of `slice` methods on typed arrays in `js-sys` was corrected. [#1321](https://github.com/rustwasm/wasm-bindgen/pull/1321) * The directory specified by `--out-dir` is now created if it doesn't exist already. [#1330](https://github.com/rustwasm/wasm-bindgen/pull/1330) ### Fixed * A bug where if `nom` was in a crate graph and was compiled with the `verbose-errors` feature has been fixed. Previously the `wasm-bindgen-webidl` crate wouldn't compile, and now it will. [#1338](https://github.com/rustwasm/wasm-bindgen/pull/1338) -------------------------------------------------------------------------------- ## 0.2.38 Released 2019-03-04. ### Added * Support for `Option` in `#[wasm_bindgen]` functions has now been added. [#1275](https://github.com/rustwasm/wasm-bindgen/pull/1275) * Experimental support for the `anyref` type proposal in WebAssembly has now landed and is enabled with `WASM_BINDGEN_ANYREF=1`. [#1002](https://github.com/rustwasm/wasm-bindgen/pull/1002) * Support for the new browser `TextEncode#encodeInto` API has been added. [#1279](https://github.com/rustwasm/wasm-bindgen/pull/1279) * JS doc comments are now added to TypeScript bindings in addition to the JS bindings generated. [#1302](https://github.com/rustwasm/wasm-bindgen/pull/1302) * Initial support for `FnOnce` closures has been added to the `Closure` type. [#1281](https://github.com/rustwasm/wasm-bindgen/pull/1281) ### Fixed * Fixed an internal assert tripping when some modules were compiled with LTO. [#1274](https://github.com/rustwasm/wasm-bindgen/pull/1274) * The `Context` type in the `wasm-bindgen-test` crate had its JS name changed to avoid conflicts with other crates that have a `Context` type being exported. [#1280](https://github.com/rustwasm/wasm-bindgen/pull/1280) * The headless test runner for Safari on macOS High Sierra has been fixed. [#1298](https://github.com/rustwasm/wasm-bindgen/pull/1298) ### Changed * The `wasm-bindgen` CLI tool now emits the `producers` section again with relevant bugs having been fixed in the meantime. The `--remove-producers-section` flag can continue to be used to omit emission of this section. [#1263](https://github.com/rustwasm/wasm-bindgen/pull/1263) -------------------------------------------------------------------------------- ## 0.2.37 Released 2019-02-15. ### Added * The `HtmlMediaElement` type now exposes a `src_object` getter. [#1248](https://github.com/rustwasm/wasm-bindgen/pull/1248). * The `js_sys::Reflect` type now has specializes getter/setters for `u32` and `f64` indices. [#1225](https://github.com/rustwasm/wasm-bindgen/pull/1225). * A `--remove-producers-section` flag has been added to the CLI tool to, well, remove the `producers` section from the final wasm file. [#1256](https://github.com/rustwasm/wasm-bindgen/pull/1256). ### Fixed * The `wasm-bindgen` CLI tool will correctly strip DWARF debug information unless `--keep-debug` is passed. [#1255](https://github.com/rustwasm/wasm-bindgen/pull/1255). ### Changed * The `wasm-bindgen` CLI tool no longer emits the `producers` custom section by default to work around a [webpack bug]. See [#1260](https://github.com/rustwasm/wasm-bindgen/pull/1260). [webpack bug]: https://github.com/webpack/webpack/pull/8786 -------------------------------------------------------------------------------- ## 0.2.36 Released 2019-02-12. ### Fixed * Fixed a bug where using closures and LTO together caused a panic inside the `wasm-bindgen` CLI tool. See [#1244](https://github.com/rustwasm/wasm-bindgen/issues/1244). -------------------------------------------------------------------------------- ## 0.2.35 Released 2019-02-12. ### Changed * `wasm-bindgen` now internally uses the `walrus` crate to perform its transformations of the wasm that rustc/LLVM emits. See [#1237](https://github.com/rustwasm/wasm-bindgen/pull/1237). ### Fixed * When `WebAssembly.instantiateStreaming` fails due to incorrect MIME type, *actually* properly recover. See [#1243](https://github.com/rustwasm/wasm-bindgen/pull/1243). -------------------------------------------------------------------------------- ## 0.2.34 Released 2019-02-11. ### Added * Added support for optional `enum`s. See [#1214](https://github.com/rustwasm/wasm-bindgen/pull/1214). * Added the `UnwrapThrowExt` trait, which can enable smaller code sizes for panics. See [#1219](https://github.com/rustwasm/wasm-bindgen/pull/1219). ### Fixed * Some `WebGlRenderingContext` methods are now whitelisted to use shared slices instead of exclusive slices. See [#1199](https://github.com/rustwasm/wasm-bindgen/pull/1199). * Fixed TypeScript definitions for optional types. See [#1201](https://github.com/rustwasm/wasm-bindgen/pull/1201). * Quiet clippy warnings inside generated code. See [1207](https://github.com/rustwasm/wasm-bindgen/pull/1207). * Fixed using `cfg_attr` and `wasm_bindgen` together like `#[cfg_attr(..., wasm_bindgen)]`. See [1208](https://github.com/rustwasm/wasm-bindgen/pull/1208). * The WebAudio example program was fixed. See [#1215](https://github.com/rustwasm/wasm-bindgen/pull/1215). * Fixed logging HTML in `wasm-bindgen-test`. See [#1233](https://github.com/rustwasm/wasm-bindgen/pull/1233). * When `WebAssembly.instantiateStreaming` fails due to incorrect MIME type, properly recover. See [#1235](https://github.com/rustwasm/wasm-bindgen/pull/1235). -------------------------------------------------------------------------------- ## 0.2.33 Released 2019-01-18. ### Added * Improved the `Debug` output of `JsValue` [#1161](https://github.com/rustwasm/wasm-bindgen/pull/1161) * Bindings for `JSON.stringify` and its optional arguments have been added [#1190](https://github.com/rustwasm/wasm-bindgen/pull/1190) ### Fixed * A bug with windows binaries being released has ben resolved. -------------------------------------------------------------------------------- ## 0.2.32 Released 2019-01-16. ### Added * Added support for Web IDL sequences. This enabled bindings generation for a couple more Web APIs. We generate functions for Web APIs that take sequences to accept any iterable, and for Web APIs that return sequences, a `js_sys::Array` is returned. See [#1152](https://github.com/rustwasm/wasm-bindgen/pull/1152) and [#1038](https://github.com/rustwasm/wasm-bindgen/issues/1038). * The `wasm-bindgen-test` test runner will capture `console.debug`, `console.info`, and `console.warn` log messages and print them to `stdout` now. It already supported `console.log` and `console.error` and continues to support them. See [#1183](https://github.com/rustwasm/wasm-bindgen/issues/1183) and [#1184](https://github.com/rustwasm/wasm-bindgen/pull/1184). * Added additional `--debug`-only assertions in the emitted JS glue for cases where an imported JS function that is not annotated with `#[wasm_bindgen(catch)]` throws an exception. This should help catch some bugs earlier! See [#1179](https://github.com/rustwasm/wasm-bindgen/pull/1179). ### Fixed * Fixed a bug where `#[wasm_bindgen_test]` tests would fail in non-headless Web browsers if they used `console.log`. See [#1167](https://github.com/rustwasm/wasm-bindgen/pull/1167). * Fixed a bug where returning closures from exported functions sometimes resulted in a faulty error. See [#1174](https://github.com/rustwasm/wasm-bindgen/issues/1174) and [#1175](https://github.com/rustwasm/wasm-bindgen/pull/1175). * Sometimes our generated TypeScript interface files had syntax errors in them (missing semicolons). This has been fixed. See [#1181](https://github.com/rustwasm/wasm-bindgen/pull/1181). -------------------------------------------------------------------------------- ## 0.2.31 Released 2019-01-09. ### Added * A new `spawn_local` function has been added to the `wasm-bindgen-futures` crate. [#1148](https://github.com/rustwasm/wasm-bindgen/pull/1148) * Built-in conversions are now available from typed arrays and Rust arrays. [#1147](https://github.com/rustwasm/wasm-bindgen/pull/1147) ### Fixed * Some casing of dictionary properties in WebIDL has been fixed. [#1155](https://github.com/rustwasm/wasm-bindgen/pull/1155) -------------------------------------------------------------------------------- ## 0.2.30 Released 2019-01-07. ### Added * The `wasm-bindgen` CLI now has an `--out-name` argument to name the output module. [#1084](https://github.com/rustwasm/wasm-bindgen/pull/1084) * Support for importing the `default` export has been added. [#1106](https://github.com/rustwasm/wasm-bindgen/pull/1106) ### Changed * All `web-sys` methods are now flagged as `structural`, fixing a few bindings. [#1117](https://github.com/rustwasm/wasm-bindgen/pull/1117) ### Fixed * A small bug with LTO and closures has been fixed. [#1145](https://github.com/rustwasm/wasm-bindgen/pull/1145) -------------------------------------------------------------------------------- ## 0.2.29 Released 2018-12-04. ### Added * Add a `#[wasm_bindgen(start)]` attribute to customize the `start` section of the wasm module. [#1057](https://github.com/rustwasm/wasm-bindgen/pull/1057) * Add support for producing the new "producers" section of wasm binaries [#1041](https://github.com/rustwasm/wasm-bindgen/pull/1041) * Add support a `typescript_custom_section` attribute for producing custom typescript abstractions [#1048](https://github.com/rustwasm/wasm-bindgen/pull/1048) * Generate `*.d.ts` files for wasm files in addition to the JS bindings [#1053](https://github.com/rustwasm/wasm-bindgen/pull/1053) * Add a feature to assert that all attributes in `#[wasm_bindgen]` are used to help catch typos and mistakes [#1055](https://github.com/rustwasm/wasm-bindgen/pull/1055) ### Changed * JS glue generation has received a few small optimizations such as removing shims and removing object allocations [#1033](https://github.com/rustwasm/wasm-bindgen/pull/1033) [#1030](https://github.com/rustwasm/wasm-bindgen/pull/1030) * JS glue now just uses one array of JS objects instead of two [#1069](https://github.com/rustwasm/wasm-bindgen/pull/1069) ### Fixed * Fix a typo in the `--no-modules` generated JS [#1045](https://github.com/rustwasm/wasm-bindgen/pull/1045) -------------------------------------------------------------------------------- ## 0.2.28 Released 2018-11-12. ### Added * The `js_class` support is now supported on exported types to define a different class in JS than is named in Rust [#1012](https://github.com/rustwasm/wasm-bindgen/pull/1012) * More WebIDL bindings are exposed with some internal restructuring to ignore unimplemented types at a different location [#1014](https://github.com/rustwasm/wasm-bindgen/pull/1014) * All imported types now implement `Deref` to their first `extends` attribute (or `JsValue` if one isn't listed). This is intended to greatly improve the ergonomics of `web-sys` bindings by allowing easy access to parent class methods [#1019](https://github.com/rustwasm/wasm-bindgen/pull/1019) * A new attribute, `final`, can be applied to JS imports. This attribute is relatively nuanced and [best explained in documentation][final-dox], but is added since `structural` is now the default [#1019](https://github.com/rustwasm/wasm-bindgen/pull/1019) [final-dox]: https://rustwasm.github.io/wasm-bindgen/reference/attributes/on-js-imports/final.html * A new CLI flag, `--remove-name-section`, can be passed to remove the wasm `name` section which contains the names of functions for debugging (typically not needed in release mode) [#1024](https://github.com/rustwasm/wasm-bindgen/pull/1024) ### Changed * All imported functions are now `structural` by default. This shouldn't change the semantics of imported functions, only how they're invoked in the JS function shims that are generated by `wasm-bindgen`. More discussion can be founed on [RFC 5] and the PR [#1019](https://github.com/rustwasm/wasm-bindgen/pull/1019) [RFC 5]: https://rustwasm.github.io/rfcs/005-structural-and-deref.html * JS glue assertions for moved arguments are now only emitted in debug mode, which is still off by default [#1020](https://github.com/rustwasm/wasm-bindgen/pull/1020) ### Fixed * Typescript generated bindings now correctly reflect `Option` for more types [#1008](https://github.com/rustwasm/wasm-bindgen/pull/1008) * The JS shim code generation has been optimized for `structural` bindings (now the default) to include fewer JS shims and more easily optimizable for JS engines [#1019](https://github.com/rustwasm/wasm-bindgen/pull/1019) * Passing a `WebAssembly.Module` to the `--no-modules` constructor has been fixed [#1025](https://github.com/rustwasm/wasm-bindgen/pull/1025) -------------------------------------------------------------------------------- ## 0.2.27 Released 2018-10-29. ### Fixed * Fixed an internal panic where the gc passes were being too aggressive [#995](https://github.com/rustwasm/wasm-bindgen/pull/995) -------------------------------------------------------------------------------- ## 0.2.26 Released 2018-10-29. ### Added * The `TypedArray.slice` methods have now been bound in `js-sys`. [#956](https://github.com/rustwasm/wasm-bindgen/pull/956) * The `Debug` and `Clone` traits are now implemented for `js_sys::Promise`. [#957](https://github.com/rustwasm/wasm-bindgen/pull/957) * The `js_sys::DataView` type now exposes overloads to specify endianness. [#966](https://github.com/rustwasm/wasm-bindgen/pull/966) * When using `--no-modules` a `WebAssembly.Module` can now be directly passed into the instantiation glue. [#969](https://github.com/rustwasm/wasm-bindgen/pull/969) ### Fixed * The `JsValue` type is no longer considered `Send`. [#955](https://github.com/rustwasm/wasm-bindgen/pull/955) * The generated JS glue is now more robust in the face of missing APIs. [#959](https://github.com/rustwasm/wasm-bindgen/pull/959) * An issue with the latest version of `safaridriver` used to run headless tests has been resolved. [#991](https://github.com/rustwasm/wasm-bindgen/pull/991) -------------------------------------------------------------------------------- ## 0.2.25 Released 2018-10-10. ### Fixed * Using `wasm-bindgen` will no longer unconditionally pull in Rust's default allocator for Wasm (dlmalloc) regardless if you configured a custom global allocator (eg wee_alloc). [#947](https://github.com/rustwasm/wasm-bindgen/pull/947) * Fixed web-sys build on some Windows machines. [#943](https://github.com/rustwasm/wasm-bindgen/issues/943) * Fixed generated ES class bindings to Rust structs that were only referenced through struct fields. [#948](https://github.com/rustwasm/wasm-bindgen/issues/948) -------------------------------------------------------------------------------- ## 0.2.24 Released 2018-10-05. ### Added * Constructors for types in `web-sys` should now have better documentation. * A new `vendor_prefix` attribute in `#[wasm_bindgen]` is supported to bind APIs on the web which may have a vendor prefix (like `webkitAudioContext`). This is then subsequently used to fix `AudioContext` usage in Safari. * The `#[wasm_bindgen(extends = Foo)]` attribute now supports full paths, so you can also say `#[wasm_bindgen(extends = foo::Bar)]` and such. ### Changed * The `Closure` type is now optimized when the underlying closure is a ZST. The type now no longer allocates memory in this situation. * The documentation now has a list of caveats for browser support, including how `TextEncoder` and `TextDecoder` are not implemented in Edge. If you're using webpack there's a listed strategy available, and improvements to the polyfill strategy are always welcome! * The `BaseAudioContext` and `AudioScheduledSourceNode` types in `web-sys` have been deprecated as they don't exist in Safari or Edge. ### Fixed * Fixed the `#[wasm_bindgen_test]`'s error messages in a browser to correctly escape HTML-looking output. * WebIDL Attributes on `Window` are now correctly bound to not go through `Window.prototype` which doesn't exist but instead use a `structural` definition. * Fixed a codegen error when the `BorrowMut` trait was in scope. * Fixed TypeScript generation for constructors of classes, it was accidentally producing a syntactially invalid file! -------------------------------------------------------------------------------- ## 0.2.23 Released 2018-09-26. ### Added * [This is the first release of the `web-sys` crate!](https://rustwasm.github.io/2018/09/26/announcing-web-sys.html) * Added support for unions of interfaces and non-interfaces in the WebIDL frontend. * Added a policy for inclusion of new ECMAScript features in `js-sys`: the feature must be in stage 4 or greater for us to support it. * Added some documentation about size profiling and optimization with `wasm-bindgen` to the guide. * Added the `Clamped` type for generating JavaScript `Uint8ClampedArray`s. * CI is now running on beta! Can't wait for the `rustc` release trains to roll over, so we can run CI on stable too! * Added the `js_sys::try_iter` function, which checks arbitrary JS values for compliance with the JS iteration protocol, and if they are iterable, converts them into an iterator over the JS values that they yield. ### Changed * We now only generate null checks on methods on the JS side when in debug mode. For safety we will always null check on the Rust side, however. * Improved error messages when defining setters that don't start with `set_` and don't use `js_name = ...`. * Improved generated code for classes in a way that avoids an unnecessary allocation with static methods that return `Self` but are not the "main" constructor. * **BREAKING:** `js_sys::Reflect` APIs are all fallible now. This is because reflecting on `Proxy`s whose trap handlers throw an exception can cause any of the reflection APIs to throw. Accordingly, `js_sys` has been bumped from `0.2.X` to `0.3.X`. ### Fixed * The method of ensuring that `__wbindgen_malloc` and `__wbindgen_free` are always emitted in the `.wasm` binary, regardless of seeming reachability is now zero-overhead. -------------------------------------------------------------------------------- ## 0.2.22 Released 2018-09-21 ### Added * The `IntoIterator` trait is now implemented for JS `Iterator` types * A number of variadic methods in `js-sys` have had explicit arities added. * The guide has been improved quite a bit as well as enhanced with more examples * The `js-sys` crate is now complete! Thanks so much to everyone involved to help fill out all the APIs. * Exported Rust functions with `#[wasm_bindgen]` can now return a `Result` where the `Err` payload is raised as an exception in JS. ### Fixed * An issue with running `wasm-bindgen` on crates that have been compiled with LTO has been resolved. -------------------------------------------------------------------------------- ## 0.2.21 Released 2018-09-07 ### Added * Added many more bindings for `WebAssembly` in the `js-sys` crate. ### Fixed * The "names" section of the wasm binary is now correctly preserved by wasm-bindgen. -------------------------------------------------------------------------------- ## 0.2.20 Released 2018-09-06 ### Added * All of `wasm-bindgen` is configured to compile on stable Rust as of the upcoming 1.30.0 release, scheduled for October 25, 2018. * The underlying `JsValue` of a `Closure` type can now be extracted at any time. * Initial and experimental support was added for modules that have shared memory (use atomic instructions). ### Removed * The `--wasm2asm` flag of `wasm2es6js` was removed because the `wasm2asm` tool has been removed from upstream Binaryen. This is replaced with the new `wasm2js` tool from Binaryen. ### Fixed * The "schema" version for wasm-bindgen now changes on all publishes, meaning we can't forget to update it. This means that the crate version and CLI version must exactly match. * The `wasm-bindgen` crate now has a `links` key which forbids multiple versions of `wasm-bindgen` from being linked into a dependency graph, fixing obscure linking errors with a more first-class error message. * Binary releases for Windows has been fixed. -------------------------------------------------------------------------------- ## 0.2.19 (and 0.2.18) Released 2018-08-27. ### Added * Added bindings to `js-sys` for some `WebAssembly` types. * Added bindings to `js-sys` for some `Intl` types. * Added bindings to `js-sys` for some `String` methods. * Added an example of using the WebAudio APIs. * Added an example of using the `fetch` API. * Added more `extends` annotations for types in `js-sys`. * Experimental support for `WeakRef` was added to automatically deallocate Rust objects when gc'd. * Added support for executing `wasm-bindgen` over modules that import their memory. * Added a global `memory()` function in the `wasm-bindgen` crate for accessing the JS object that represent wasm's own memory. ### Removed * Removed `AsMut` implementations for imported objects. ### Fixed * Fixed the `constructor` and `catch` attributes combined on imported types. * Fixed importing the same-named static in two modules. -------------------------------------------------------------------------------- ## 0.2.17 Released 2018-08-16. ### Added * Greatly expanded documentation in the wasm-bindgen guide. * Added bindings to `js-sys` for `Intl.DateTimeFormat` * Added a number of `extends` attributes for types in `js-sys` ### Fixed * Fixed compile on latest nightly with latest `proc-macro2` * Fixed compilation in some scenarios on Windows with paths in `module` paths -------------------------------------------------------------------------------- ## 0.2.16 Released 2018-08-13. ### Added * Added the `wasm_bindgen::JsCast` trait, as described in [RFC #2][rfc-2]. * Added [the `#[wasm_bindgen(extends = ...)]` attribute][extends-attr] to describe inheritance relationships, as described in [RFC #2][rfc-2]. * Added support for receiving `Option<&T>` parameters from JavaScript in exported Rust functions and methods. * Added support for receiving `Option` and other option-wrapped scalars. * Added reference documentation to the guide for every `#[wasm_bindgen]` attribute and how it affects the generated bindings. * Published the `wasm-bindgen-futures` crate for converting between JS `Promise`s and Rust `Future`s. ### Changed * Overhauled the guide's documentation on passing JS closures to Rust, and Rust closures to JS. * Overhauled the guide's documentation on using serde to serialize complex data to `JsValue` and deserialize `JsValue`s back into complex data. * Static methods are now always bound to their JS class, as is required for `Promise`'s static methods. ### Removed * Removed internal usage of `syn`'s `visit-mut` cargo feature, which should result in faster build times. ### Fixed * Various usage errors for the `#[wasm_bindgen]` proc-macro are now properly reported with source span information, rather than `panic!()`s inside the proc-macro. * Fixed a bug where taking a struct by reference and returning a slice resulted in lexical variable redeclaration errors in the generated JS glue. [#662][] * The `#[wasm_bindgen(js_class = "....")]` attribute for binding methods to renamed imported JS classes now properly works with constructors. [rfc-2]: https://rustwasm.github.io/rfcs/002-wasm-bindgen-inheritance-casting.html [extends-attr]: https://rustwasm.github.io/wasm-bindgen/reference/attributes/on-js-imports/extends.html [#662]: https://github.com/rustwasm/wasm-bindgen/pull/662 -------------------------------------------------------------------------------- ## 0.2.15 Released 2018-07-26. ### Fixed * Fixed `wasm-bindgen` CLI version mismatch checks that got broken in the last point release. -------------------------------------------------------------------------------- ## 0.2.14 Released 2018-07-25. ### Fixed * Fixed compilation errors on targets that use Mach-O. [#545](https://github.com/rustwasm/wasm-bindgen/issues/545) -------------------------------------------------------------------------------- ## 0.2.13 Released 2018-07-22. ### Added * Support the `#[wasm_bindgen(js_name = foo)]` attribute on exported functions and methods to allow renaming an export to JS. This allows JS to call it by one name and Rust to call it by another, for example using `camelCase` in JS and `snake_case` in Rust ### Fixed * Compilation with the latest nightly compiler has been fixed (nightlies on and after 2018-07-21) -------------------------------------------------------------------------------- ## 0.2.12 Released 2018-07-19. This release is mostly internal refactorings and minor improvements to the existing crates and functionality, but the bigs news is an upcoming `js-sys` and `web-sys` set of crates. The `js-sys` crate will expose [all global JS bindings][js-all] and the `web-sys` crate will be generated from WebIDL to expose all APIs browsers have. More info on this soon! [js-all]: https://github.com/rustwasm/wasm-bindgen/issues/275 ### Added * Support for `Option` was added where `T` can be a number of slices or imported types. * Comments in Rust are now preserved in generated JS bindings, as well as comments being generated to indicate the types of arguments/return values. * The online documentation has been reorganized [into a book][book]. * The generated JS is now formatted better by default for readability. * A `--keep-debug` flag has been added to the CLI to retain debug sections by default. This happens by default when `--debug` is passed. [book]: https://rustwasm.github.io/wasm-bindgen/ ### Fixed * Compilation with the latest nightly compiler has been fixed (nightlies on and after 2018-07-19) * Declarations of an imported function in multiple crates have been fixed to not conflict. * Compilation with `#![deny(missing_docs)]` has been fixed. -------------------------------------------------------------------------------- ## 0.2.11 Released 2018-05-24. -------------------------------------------------------------------------------- ## 0.2.10 Released 2018-05-17. -------------------------------------------------------------------------------- ## 0.2.9 Released 2018-05-11. wasm-bindgen-0.2.87/CONTRIBUTING.md000064400000000000000000000002241046102023000145240ustar 00000000000000# Contributing See the ["Contributing" section of the `wasm-bindgen` guide](https://rustwasm.github.io/docs/wasm-bindgen/contributing/index.html). wasm-bindgen-0.2.87/Cargo.toml0000644000000041310000000000100115020ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" rust-version = "1.56" name = "wasm-bindgen" version = "0.2.87" authors = ["The wasm-bindgen Developers"] description = """ Easy support for interacting between JS and Rust. """ homepage = "https://rustwasm.github.io/" documentation = "https://docs.rs/wasm-bindgen" readme = "README.md" categories = ["wasm"] license = "MIT/Apache-2.0" repository = "https://github.com/rustwasm/wasm-bindgen" resolver = "2" [package.metadata.docs.rs] features = ["serde-serialize"] [lib] test = false [dependencies.cfg-if] version = "1.0.0" [dependencies.serde] version = "1.0" optional = true [dependencies.serde_json] version = "1.0" optional = true [dependencies.wasm-bindgen-macro] version = "=0.2.87" [features] default = [ "spans", "std", ] enable-interning = ["std"] gg-alloc = ["wasm-bindgen-test/gg-alloc"] serde-serialize = [ "serde", "serde_json", "std", ] spans = ["wasm-bindgen-macro/spans"] std = [] strict-macro = ["wasm-bindgen-macro/strict-macro"] xxx_debug_only_print_generated_code = ["wasm-bindgen-macro/xxx_debug_only_print_generated_code"] [target."cfg(target_arch = \"wasm32\")".dev-dependencies.js-sys] version = "0.3.64" [target."cfg(target_arch = \"wasm32\")".dev-dependencies.serde_derive] version = "1.0" [target."cfg(target_arch = \"wasm32\")".dev-dependencies.wasm-bindgen-futures] version = "=0.4.37" [target."cfg(target_arch = \"wasm32\")".dev-dependencies.wasm-bindgen-test] version = "=0.3.37" [target."cfg(target_arch = \"wasm32\")".dev-dependencies.wasm-bindgen-test-crate-a] version = "0.1" [target."cfg(target_arch = \"wasm32\")".dev-dependencies.wasm-bindgen-test-crate-b] version = "0.1" wasm-bindgen-0.2.87/Cargo.toml.orig000064400000000000000000000060631046102023000151710ustar 00000000000000[package] name = "wasm-bindgen" version = "0.2.87" authors = ["The wasm-bindgen Developers"] license = "MIT/Apache-2.0" readme = "README.md" categories = ["wasm"] repository = "https://github.com/rustwasm/wasm-bindgen" homepage = "https://rustwasm.github.io/" documentation = "https://docs.rs/wasm-bindgen" description = """ Easy support for interacting between JS and Rust. """ edition = "2018" rust-version = "1.56" [package.metadata.docs.rs] features = ["serde-serialize"] [lib] test = false [features] default = ["spans", "std"] spans = ["wasm-bindgen-macro/spans"] std = [] serde-serialize = ["serde", "serde_json", "std"] enable-interning = ["std"] # Whether or not the `#[wasm_bindgen]` macro is strict and generates an error on # all unused attributes strict-macro = ["wasm-bindgen-macro/strict-macro"] # Enables gg-alloc as system allocator when using wasm-bindgen-test to check that large pointers # are handled correctly gg-alloc = ["wasm-bindgen-test/gg-alloc"] # This is only for debugging wasm-bindgen! No stability guarantees, so enable # this at your own peril! xxx_debug_only_print_generated_code = [ "wasm-bindgen-macro/xxx_debug_only_print_generated_code", ] [dependencies] wasm-bindgen-macro = { path = "crates/macro", version = "=0.2.87" } serde = { version = "1.0", optional = true } serde_json = { version = "1.0", optional = true } cfg-if = "1.0.0" [target.'cfg(target_arch = "wasm32")'.dev-dependencies] js-sys = { path = 'crates/js-sys', version = '0.3.64' } wasm-bindgen-test = { path = 'crates/test', version = '=0.3.37' } wasm-bindgen-futures = { path = 'crates/futures', version = '=0.4.37' } serde_derive = "1.0" wasm-bindgen-test-crate-a = { path = 'tests/crates/a', version = '0.1' } wasm-bindgen-test-crate-b = { path = 'tests/crates/b', version = '0.1' } [workspace] members = [ "benchmarks", "crates/cli", "crates/js-sys", "crates/test", "crates/test/sample", "crates/example-tests", "crates/typescript-tests", "crates/web-sys", "crates/webidl", "crates/webidl-tests", "examples/add", "examples/canvas", "examples/char", "examples/closures", "examples/console_log", "examples/deno", "examples/dom", "examples/duck-typed-interfaces", "examples/fetch", "examples/guide-supported-types-examples", "examples/hello_world", "examples/import_js/crate", "examples/julia_set", "examples/paint", "examples/performance", "examples/raytrace-parallel", "examples/request-animation-frame", "examples/todomvc", "examples/wasm-audio-worklet", "examples/wasm-in-wasm", "examples/wasm-in-wasm-imports", "examples/wasm-in-web-worker", "examples/wasm2js", "examples/weather_report", "examples/webaudio", "examples/webgl", "examples/webrtc_datachannel", "examples/websockets", "examples/webxr", "examples/without-a-bundler", "examples/without-a-bundler-no-modules", "examples/synchronous-instantiation", "tests/no-std", ] resolver = "2" [patch.crates-io] wasm-bindgen = { path = '.' } wasm-bindgen-futures = { path = 'crates/futures' } js-sys = { path = 'crates/js-sys' } web-sys = { path = 'crates/web-sys' } wasm-bindgen-0.2.87/LICENSE-APACHE000064400000000000000000000251371046102023000142310ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. wasm-bindgen-0.2.87/LICENSE-MIT000064400000000000000000000020411046102023000137260ustar 00000000000000Copyright (c) 2014 Alex Crichton Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. wasm-bindgen-0.2.87/README.md000064400000000000000000000100671046102023000135600ustar 00000000000000

wasm-bindgen

Facilitating high-level interactions between Wasm modules and JavaScript.

Build Status Crates.io version Download docs.rs docs

Guide | API Docs | Contributing | Chat

Built with 🦀🕸 by The Rust and WebAssembly Working Group
## Example Import JavaScript things into Rust and export Rust things to JavaScript. ```rust use wasm_bindgen::prelude::*; // Import the `window.alert` function from the Web. #[wasm_bindgen] extern "C" { fn alert(s: &str); } // Export a `greet` function from Rust to JavaScript, that alerts a // hello message. #[wasm_bindgen] pub fn greet(name: &str) { alert(&format!("Hello, {}!", name)); } ``` Use exported Rust things from JavaScript with ECMAScript modules! ```js import { greet } from "./hello_world"; greet("World!"); ``` ## Features * **Lightweight.** Only pay for what you use. `wasm-bindgen` only generates bindings and glue for the JavaScript imports you actually use and Rust functionality that you export. For example, importing and using the `document.querySelector` method doesn't cause `Node.prototype.appendChild` or `window.alert` to be included in the bindings as well. * **ECMAScript modules.** Just import WebAssembly modules the same way you would import JavaScript modules. Future compatible with [WebAssembly modules and ECMAScript modules integration][wasm-es-modules]. * **Designed with the ["Web IDL bindings" proposal][webidl-bindings] in mind.** Eventually, there won't be any JavaScript shims between Rust-generated wasm functions and native DOM methods. Because the wasm functions are statically type checked, some of those native methods' dynamic type checks should become unnecessary, promising to unlock even-faster-than-JavaScript DOM access. [wasm-es-modules]: https://github.com/WebAssembly/esm-integration [webidl-bindings]: https://github.com/WebAssembly/proposals/issues/8 ## Guide [**📚 Read the `wasm-bindgen` guide here! 📚**](https://rustwasm.github.io/docs/wasm-bindgen/) You can find general documentation about using Rust and WebAssembly together [here](https://rustwasm.github.io/docs). ## API Docs - [wasm-bindgen](https://docs.rs/wasm-bindgen) - [js-sys](https://docs.rs/js-sys) - [web-sys](https://docs.rs/web-sys) - [wasm-bindgen-futures](https://docs.rs/wasm-bindgen-futures) ## License This project is licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ## Contribution **[See the "Contributing" section of the guide for information on hacking on `wasm-bindgen`!][contributing]** Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. [contributing]: https://rustwasm.github.io/docs/wasm-bindgen/contributing/index.htmlwasm-bindgen-0.2.87/_package.json000064400000000000000000000004631046102023000147250ustar 00000000000000{ "scripts": { "build": "webpack", "serve": "webpack serve" }, "devDependencies": { "@wasm-tool/wasm-pack-plugin": "1.5.0", "html-webpack-plugin": "^5.3.2", "text-encoding": "^0.7.0", "webpack": "^5.49.0", "webpack-cli": "^4.7.2", "webpack-dev-server": "^3.11.2" } } wasm-bindgen-0.2.87/build.rs000064400000000000000000000002121046102023000137350ustar 00000000000000// Empty `build.rs` so that `[package] links = ...` works in `Cargo.toml`. fn main() { println!("cargo:rerun-if-changed=build.rs"); } wasm-bindgen-0.2.87/examples/.gitignore000064400000000000000000000000511046102023000160770ustar 00000000000000package-lock.json pkg dist wasm-pack.log wasm-bindgen-0.2.87/examples/README.md000064400000000000000000000003761046102023000154000ustar 00000000000000# Examples This directory contains a number of Cargo projects that are all examples of how to use `wasm-bindgen` in various contexts. More documentation can be [found online][dox] [dox]: https://rustwasm.github.io/docs/wasm-bindgen/examples/index.html wasm-bindgen-0.2.87/examples/import_js/README.md000064400000000000000000000006361046102023000174050ustar 00000000000000# Importing non-browser JS [View documentation for this example online][dox] or [View compiled example online][compiled] [compiled]: https://rustwasm.github.io/wasm-bindgen/exbuild/import_js/ [dox]: https://rustwasm.github.io/docs/wasm-bindgen/examples/import-js.html You can build the example locally with: ``` $ npm run serve ``` and then visiting http://localhost:8080 in a browser should run the example! wasm-bindgen-0.2.87/examples/import_js/index.html000064400000000000000000000003141046102023000201140ustar 00000000000000

Open up the developer console and you should see "Hello from Rust!"

wasm-bindgen-0.2.87/examples/import_js/index.js000064400000000000000000000002071046102023000175650ustar 00000000000000// For more comments about what's going on here, check out the `hello_world` // example import('./crate/pkg') .catch(console.error); wasm-bindgen-0.2.87/examples/import_js/package.json000064400000000000000000000004641046102023000204130ustar 00000000000000{ "scripts": { "build": "webpack", "serve" : "webpack serve" }, "devDependencies": { "@wasm-tool/wasm-pack-plugin": "1.5.0", "text-encoding": "^0.7.0", "html-webpack-plugin": "^5.3.2", "webpack": "^5.49.0", "webpack-cli": "^4.7.2", "webpack-dev-server": "^3.11.2" } } wasm-bindgen-0.2.87/examples/import_js/webpack.config.js000064400000000000000000000015751046102023000213470ustar 00000000000000const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const webpack = require('webpack'); const WasmPackPlugin = require("@wasm-tool/wasm-pack-plugin"); module.exports = { entry: './index.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'index.js', }, plugins: [ new HtmlWebpackPlugin({ template: 'index.html' }), new WasmPackPlugin({ crateDirectory: path.resolve(__dirname, "crate") }), // Have this example work in Edge which doesn't ship `TextEncoder` or // `TextDecoder` at this time. new webpack.ProvidePlugin({ TextDecoder: ['text-encoding', 'TextDecoder'], TextEncoder: ['text-encoding', 'TextEncoder'] }) ], mode: 'development', experiments: { asyncWebAssembly: true } }; wasm-bindgen-0.2.87/guide/.gitignore000064400000000000000000000000051046102023000153550ustar 00000000000000book wasm-bindgen-0.2.87/guide/book.toml000064400000000000000000000002311046102023000152150ustar 00000000000000[book] authors = ["Nick Fitzgerald"] multilingual = false src = "src" title = "The `wasm-bindgen` Guide" [build] build-dir = "book/html" [output.html] wasm-bindgen-0.2.87/guide/src/SUMMARY.md000064400000000000000000000172121046102023000156430ustar 00000000000000# Summary [Introduction](./introduction.md) -------------------------------------------------------------------------------- - [Examples](./examples/index.md) - [Hello, World!](./examples/hello-world.md) - [Using `console.log`](./examples/console-log.md) - [Small wasm files](./examples/add.md) - [Without a Bundler](./examples/without-a-bundler.md) - [Converting WebAssembly to JS](./examples/wasm2js.md) - [Importing functions from JS](./examples/import-js.md) - [Working with `char`](./examples/char.md) - [js-sys: WebAssembly in WebAssembly](./examples/wasm-in-wasm.md) - [web-sys: DOM hello world](./examples/dom.md) - [web-sys: Closures](./examples/closures.md) - [web-sys: `performance.now`](./examples/performance.md) - [web-sys: using `fetch`](./examples/fetch.md) - [web-sys: `canvas` hello world](./examples/2d-canvas.md) - [web-sys: `canvas` Julia set](./examples/julia.md) - [web-sys: WebAudio](./examples/web-audio.md) - [web-sys: WebGL](./examples/webgl.md) - [web-sys: WebSockets](./examples/websockets.md) - [web-sys: WebRTC DataChannel](./examples/webrtc_datachannel.md) - [web-sys: `requestAnimationFrame`](./examples/request-animation-frame.md) - [web-sys: A Simple Paint Program](./examples/paint.md) - [web-sys: WASM in Web Worker](./examples/wasm-in-web-worker.md) - [Parallel Raytracing](./examples/raytrace.md) - [WASM Audio Worklet](./examples/wasm-audio-worklet.md) - [web-sys: A TODO MVC App](./examples/todomvc.md) - [Reference](./reference/index.md) - [Deployment](./reference/deployment.md) - [JS snippets](./reference/js-snippets.md) - [Static JS Objects](./reference/static-js-objects.md) - [Passing Rust Closures to JS](./reference/passing-rust-closures-to-js.md) - [Receiving JS Closures in Rust](./reference/receiving-js-closures-in-rust.md) - [`Promise`s and `Future`s](./reference/js-promises-and-rust-futures.md) - [Iterating over JS Values](./reference/iterating-over-js-values.md) - [Arbitrary Data with Serde](./reference/arbitrary-data-with-serde.md) - [Accessing Properties of Untyped JS Values](./reference/accessing-properties-of-untyped-js-values.md) - [Working with Duck-Typed Interfaces](./reference/working-with-duck-typed-interfaces.md) - [Command Line Interface](./reference/cli.md) - [Optimizing for Size](./reference/optimize-size.md) - [Supported Rust Targets](./reference/rust-targets.md) - [Supported Browsers](./reference/browser-support.md) - [Support for Weak References](./reference/weak-references.md) - [Support for Reference Types](./reference/reference-types.md) - [Supported Types](./reference/types.md) - [Imported JavaScript Types](./reference/types/imported-js-types.md) - [Exported Rust Types](./reference/types/exported-rust-types.md) - [`JsValue`](./reference/types/jsvalue.md) - [`Box<[JsValue]>`](./reference/types/boxed-jsvalue-slice.md) - [`*const T` and `*mut T`](./reference/types/pointers.md) - [Numbers](./reference/types/numbers.md) - [`bool`](./reference/types/bool.md) - [`char`](./reference/types/char.md) - [`str`](./reference/types/str.md) - [`String`](./reference/types/string.md) - [Number Slices](./reference/types/number-slices.md) - [Boxed Number Slices](./reference/types/boxed-number-slices.md) - [`Result`](./reference/types/result.md) - [`#[wasm_bindgen]` Attributes](./reference/attributes/index.md) - [On JavaScript Imports](./reference/attributes/on-js-imports/index.md) - [`catch`](./reference/attributes/on-js-imports/catch.md) - [`constructor`](./reference/attributes/on-js-imports/constructor.md) - [`extends`](./reference/attributes/on-js-imports/extends.md) - [`getter` and `setter`](./reference/attributes/on-js-imports/getter-and-setter.md) - [`final`](./reference/attributes/on-js-imports/final.md) - [`indexing_getter`, `indexing_setter`, and `indexing_deleter`](./reference/attributes/on-js-imports/indexing-getter-setter-deleter.md) - [`js_class = "Blah"`](./reference/attributes/on-js-imports/js_class.md) - [`js_name`](./reference/attributes/on-js-imports/js_name.md) - [`js_namespace`](./reference/attributes/on-js-imports/js_namespace.md) - [`method`](./reference/attributes/on-js-imports/method.md) - [`module = "blah"`](./reference/attributes/on-js-imports/module.md) - [`raw_module = "blah"`](./reference/attributes/on-js-imports/raw_module.md) - [`static_method_of = Blah`](./reference/attributes/on-js-imports/static_method_of.md) - [`structural`](./reference/attributes/on-js-imports/structural.md) - [`variadic`](./reference/attributes/on-js-imports/variadic.md) - [`vendor_prefix`](./reference/attributes/on-js-imports/vendor_prefix.md) - [On Rust Exports](./reference/attributes/on-rust-exports/index.md) - [`constructor`](./reference/attributes/on-rust-exports/constructor.md) - [`js_name = Blah`](./reference/attributes/on-rust-exports/js_name.md) - [`readonly`](./reference/attributes/on-rust-exports/readonly.md) - [`skip`](./reference/attributes/on-rust-exports/skip.md) - [`skip_jsdoc`](./reference/attributes/on-rust-exports/skip_jsdoc.md) - [`start`](./reference/attributes/on-rust-exports/start.md) - [`main`](./reference/attributes/on-rust-exports/main.md) - [`typescript_custom_section`](./reference/attributes/on-rust-exports/typescript_custom_section.md) - [`getter` and `setter`](./reference/attributes/on-rust-exports/getter-and-setter.md) - [`inspectable`](./reference/attributes/on-rust-exports/inspectable.md) - [`skip_typescript`](./reference/attributes/on-rust-exports/skip_typescript.md) - [`typescript_type`](./reference/attributes/on-rust-exports/typescript_type.md) - [`getter_with_clone`](./reference/attributes/on-rust-exports/getter_with_clone.md) - [`web-sys`](./web-sys/index.md) - [Using `web-sys`](./web-sys/using-web-sys.md) - [Cargo Features](./web-sys/cargo-features.md) - [Function Overloads](./web-sys/function-overloads.md) - [Type Translations](./web-sys/type-translations.md) - [Inheritance](./web-sys/inheritance.md) - [Unstable APIs](./web-sys/unstable-apis.md) - [Testing with `wasm-bindgen-test`](./wasm-bindgen-test/index.md) - [Usage](./wasm-bindgen-test/usage.md) - [Writing Asynchronous Tests](./wasm-bindgen-test/asynchronous-tests.md) - [Testing in Headless Browsers](./wasm-bindgen-test/browsers.md) - [Continuous Integration](./wasm-bindgen-test/continuous-integration.md) - [Contributing to `wasm-bindgen`](./contributing/index.md) - [Testing](./contributing/testing.md) - [Internal Design](./contributing/design/index.md) - [JS Objects in Rust](./contributing/design/js-objects-in-rust.md) - [Exporting a function to JS](./contributing/design/exporting-rust.md) - [Exporting a struct to JS](./contributing/design/exporting-rust-struct.md) - [Importing a function from JS](./contributing/design/importing-js.md) - [Importing a class from JS](./contributing/design/importing-js-struct.md) - [Rust Type conversions](./contributing/design/rust-type-conversions.md) - [Types in `wasm-bindgen`](./contributing/design/describe.md) - [`js-sys`](./contributing/js-sys/index.md) - [Testing](./contributing/js-sys/testing.md) - [Adding More APIs](./contributing/js-sys/adding-more-apis.md) - [`web-sys`](./contributing/web-sys/index.md) - [Overview](./contributing/web-sys/overview.md) - [Testing](./contributing/web-sys/testing.md) - [Logging](./contributing/web-sys/logging.md) - [Supporting More Web APIs](./contributing/web-sys/supporting-more-web-apis.md) - [Publishing](./contributing/publishing.md) - [Team](./contributing/team.md) wasm-bindgen-0.2.87/guide/src/_headers000064400000000000000000000001321046102023000156520ustar 00000000000000/* Cross-Origin-Opener-Policy: same-origin Cross-Origin-Embedder-Policy: require-corp wasm-bindgen-0.2.87/guide/src/contributing/design/describe.md000064400000000000000000000042571046102023000222530ustar 00000000000000# Communicating types to `wasm-bindgen` The last aspect to talk about when converting Rust/JS types amongst one another is how this information is actually communicated. The `#[wasm_bindgen]` macro is running over the syntactical (unresolved) structure of the Rust code and is then responsible for generating information that `wasm-bindgen` the CLI tool later reads. To accomplish this a slightly unconventional approach is taken. Static information about the structure of the Rust code is serialized via JSON (currently) to a custom section of the wasm executable. Other information, like what the types actually are, unfortunately isn't known until later in the compiler due to things like associated type projections and typedefs. It also turns out that we want to convey "rich" types like `FnMut(String, Foo, &JsValue)` to the `wasm-bindgen` CLI, and handling all this is pretty tricky! To solve this issue the `#[wasm_bindgen]` macro generates **executable functions** which "describe the type signature of an import or export". These executable functions are what the `WasmDescribe` trait is all about: ```rust pub trait WasmDescribe { fn describe(); } ``` While deceptively simple this trait is actually quite important. When you write, an export like this: ```rust #[wasm_bindgen] fn greet(a: &str) { // ... } ``` In addition to the shims we talked about above which JS generates the macro *also* generates something like: ``` #[no_mangle] pub extern "C" fn __wbindgen_describe_greet() { ::describe(); } ``` Or in other words it generates invocations of `describe` functions. In doing so the `__wbindgen_describe_greet` shim is a programmatic description of the type layouts of an import/export. These are then executed when `wasm-bindgen` runs! These executions rely on an import called `__wbindgen_describe` which passes one `u32` to the host, and when called multiple times gives a `Vec` effectively. This `Vec` can then be reparsed into an `enum Descriptor` which fully describes a type. All in all this is a bit roundabout but shouldn't have any impact on the generated code or runtime at all. All these descriptor functions are pruned from the emitted wasm file. wasm-bindgen-0.2.87/guide/src/contributing/design/exporting-rust-struct.md000064400000000000000000000115641046102023000250260ustar 00000000000000# Exporting a struct to JS So far we've covered JS objects, importing functions, and exporting functions. This has given us quite a rich base to build on so far, and that's great! We sometimes, though, want to go even further and define a JS `class` in Rust. Or in other words, we want to expose an object with methods from Rust to JS rather than just importing/exporting free functions. The `#[wasm_bindgen]` attribute can annotate both a `struct` and `impl` blocks to allow: ```rust #[wasm_bindgen] pub struct Foo { internal: i32, } #[wasm_bindgen] impl Foo { #[wasm_bindgen(constructor)] pub fn new(val: i32) -> Foo { Foo { internal: val } } pub fn get(&self) -> i32 { self.internal } pub fn set(&mut self, val: i32) { self.internal = val; } } ``` This is a typical Rust `struct` definition for a type with a constructor and a few methods. Annotating the struct with `#[wasm_bindgen]` means that we'll generate necessary trait impls to convert this type to/from the JS boundary. The annotated `impl` block here means that the functions inside will also be made available to JS through generated shims. If we take a look at the generated JS code for this we'll see: ```js import * as wasm from './js_hello_world_bg'; export class Foo { static __construct(ptr) { return new Foo(ptr); } constructor(ptr) { this.ptr = ptr; } free() { const ptr = this.ptr; this.ptr = 0; wasm.__wbg_foo_free(ptr); } static new(arg0) { const ret = wasm.foo_new(arg0); return Foo.__construct(ret) } get() { const ret = wasm.foo_get(this.ptr); return ret; } set(arg0) { const ret = wasm.foo_set(this.ptr, arg0); return ret; } } ``` That's actually not much! We can see here though how we've translated from Rust to JS: * Associated functions in Rust (those without `self`) turn into `static` functions in JS. * Methods in Rust turn into methods in wasm. * Manual memory management is exposed in JS as well. The `free` function is required to be invoked to deallocate resources on the Rust side of things. To be able to use `new Foo()`, you'd need to annotate `new` as `#[wasm_bindgen(constructor)]`. One important aspect to note here, though, is that once `free` is called the JS object is "neutered" in that its internal pointer is nulled out. This means that future usage of this object should trigger a panic in Rust. The real trickery with these bindings ends up happening in Rust, however, so let's take a look at that. ```rust // original input to `#[wasm_bindgen]` omitted ... #[export_name = "foo_new"] pub extern "C" fn __wasm_bindgen_generated_Foo_new(arg0: i32) -> u32 { let ret = Foo::new(arg0); Box::into_raw(Box::new(WasmRefCell::new(ret))) as u32 } #[export_name = "foo_get"] pub extern "C" fn __wasm_bindgen_generated_Foo_get(me: u32) -> i32 { let me = me as *mut WasmRefCell; wasm_bindgen::__rt::assert_not_null(me); let me = unsafe { &*me }; return me.borrow().get(); } #[export_name = "foo_set"] pub extern "C" fn __wasm_bindgen_generated_Foo_set(me: u32, arg1: i32) { let me = me as *mut WasmRefCell; wasm_bindgen::__rt::assert_not_null(me); let me = unsafe { &*me }; me.borrow_mut().set(arg1); } #[no_mangle] pub unsafe extern "C" fn __wbindgen_foo_free(me: u32) { let me = me as *mut WasmRefCell; wasm_bindgen::__rt::assert_not_null(me); (*me).borrow_mut(); // ensure no active borrows drop(Box::from_raw(me)); } ``` As with before this is cleaned up from the actual output but it's the same idea as to what's going on! Here we can see a shim for each function as well as a shim for deallocating an instance of `Foo`. Recall that the only valid wasm types today are numbers, so we're required to shoehorn all of `Foo` into a `u32`, which is currently done via `Box` (like `std::unique_ptr` in C++). Note, though, that there's an extra layer here, `WasmRefCell`. This type is the same as [`RefCell`] and can be mostly glossed over. The purpose for this type, if you're interested though, is to uphold Rust's guarantees about aliasing in a world where aliasing is rampant (JS). Specifically the `&Foo` type means that there can be as much aliasing as you'd like, but crucially `&mut Foo` means that it is the sole pointer to the data (no other `&Foo` to the same instance exists). The [`RefCell`] type in libstd is a way of dynamically enforcing this at runtime (as opposed to compile time where it usually happens). Baking in `WasmRefCell` is the same idea here, adding runtime checks for aliasing which are typically happening at compile time. This is currently a Rust-specific feature which isn't actually in the `wasm-bindgen` tool itself, it's just in the Rust-generated code (aka the `#[wasm_bindgen]` attribute). [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html wasm-bindgen-0.2.87/guide/src/contributing/design/exporting-rust.md000064400000000000000000000102341046102023000234750ustar 00000000000000# Exporting a function to JS Alright now that we've got a good grasp on JS objects and how they're working, let's take a look at another feature of `wasm-bindgen`: exporting functionality with types that are richer than just numbers. The basic idea around exporting functionality with more flavorful types is that the wasm exports won't actually be called directly. Instead the generated `foo.js` module will have shims for all exported functions in the wasm module. The most interesting conversion here happens with strings so let's take a look at that. ```rust #[wasm_bindgen] pub fn greet(a: &str) -> String { format!("Hello, {}!", a) } ``` Here we'd like to define an ES module that looks like ```ts // foo.d.ts export function greet(a: string): string; ``` To see what's going on, let's take a look at the generated shim ```js import * as wasm from './foo_bg'; function passStringToWasm(arg) { const buf = new TextEncoder('utf-8').encode(arg); const len = buf.length; const ptr = wasm.__wbindgen_malloc(len, 1); let array = new Uint8Array(wasm.memory.buffer); array.set(buf, ptr); return [ptr, len]; } function getStringFromWasm(ptr, len) { const mem = new Uint8Array(wasm.memory.buffer); const slice = mem.slice(ptr, ptr + len); const ret = new TextDecoder('utf-8').decode(slice); return ret; } export function greet(arg0) { const [ptr0, len0] = passStringToWasm(arg0); try { const ret = wasm.greet(ptr0, len0); const ptr = wasm.__wbindgen_boxed_str_ptr(ret); const len = wasm.__wbindgen_boxed_str_len(ret); const realRet = getStringFromWasm(ptr, len); wasm.__wbindgen_boxed_str_free(ret); return realRet; } finally { wasm.__wbindgen_free(ptr0, len0, 1); } } ``` Phew, that's quite a lot! We can sort of see though if we look closely what's happening: * Strings are passed to wasm via two arguments, a pointer and a length. Right now we have to copy the string onto the wasm heap which means we'll be using `TextEncoder` to actually do the encoding. Once this is done we use an internal function in `wasm-bindgen` to allocate space for the string to go, and then we'll pass that ptr/length to wasm later on. * Returning strings from wasm is a little tricky as we need to return a ptr/len pair, but wasm currently only supports one return value (multiple return values [is being standardized](https://github.com/WebAssembly/design/issues/1146)). To work around this in the meantime, we're actually returning a pointer to a ptr/len pair, and then using functions to access the various fields. * Some cleanup ends up happening in wasm. The `__wbindgen_boxed_str_free` function is used to free the return value of `greet` after it's been decoded onto the JS heap (using `TextDecoder`). The `__wbindgen_free` is then used to free the space we allocated to pass the string argument once the function call is done. Next let's take a look at the Rust side of things as well. Here we'll be looking at a mostly abbreviated and/or "simplified" in the sense of this is what it compiles down to: ```rust pub extern "C" fn greet(a: &str) -> String { format!("Hello, {}!", a) } #[export_name = "greet"] pub extern "C" fn __wasm_bindgen_generated_greet( arg0_ptr: *const u8, arg0_len: usize, ) -> *mut String { let arg0 = unsafe { let slice = ::std::slice::from_raw_parts(arg0_ptr, arg0_len); ::std::str::from_utf8_unchecked(slice) }; let _ret = greet(arg0); Box::into_raw(Box::new(_ret)) } ``` Here we can see again that our `greet` function is unmodified and has a wrapper to call it. This wrapper will take the ptr/len argument and convert it to a string slice, while the return value is boxed up into just a pointer and is then returned up to was for reading via the `__wbindgen_boxed_str_*` functions. So in general exporting a function involves a shim both in JS and in Rust with each side translating to or from wasm arguments to the native types of each language. The `wasm-bindgen` tool manages hooking up all these shims while the `#[wasm_bindgen]` macro takes care of the Rust shim as well. Most arguments have a relatively clear way to convert them, bit if you've got any questions just let me know! wasm-bindgen-0.2.87/guide/src/contributing/design/importing-js-struct.md000064400000000000000000000144451046102023000244370ustar 00000000000000# Importing a class from JS Just like with functions after we've started exporting we'll also want to import! Now that we've exported a `class` to JS we'll want to also be able to import classes in Rust as well to invoke methods and such. Since JS classes are in general just JS objects the bindings here will look pretty similar to the JS object bindings describe above. As usual though, let's dive into an example! ```rust #[wasm_bindgen(module = "./bar")] extern "C" { type Bar; #[wasm_bindgen(constructor)] fn new(arg: i32) -> Bar; #[wasm_bindgen(js_namespace = Bar)] fn another_function() -> i32; #[wasm_bindgen(method)] fn get(this: &Bar) -> i32; #[wasm_bindgen(method)] fn set(this: &Bar, val: i32); #[wasm_bindgen(method, getter)] fn property(this: &Bar) -> i32; #[wasm_bindgen(method, setter)] fn set_property(this: &Bar, val: i32); } fn run() { let bar = Bar::new(Bar::another_function()); let x = bar.get(); bar.set(x + 3); bar.set_property(bar.property() + 6); } ``` Unlike our previous imports, this one's a bit more chatty! Remember that one of the goals of `wasm-bindgen` is to use native Rust syntax wherever possible, so this is mostly intended to use the `#[wasm_bindgen]` attribute to interpret what's written down in Rust. Now there's a few attribute annotations here, so let's go through one-by-one: * `#[wasm_bindgen(module = "./bar")]` - seen before with imports this is declare where all the subsequent functionality is imported from. For example the `Bar` type is going to be imported from the `./bar` module. * `type Bar` - this is a declaration of JS class as a new type in Rust. This means that a new type `Bar` is generated which is "opaque" but is represented as internally containing a `JsValue`. We'll see more on this later. * `#[wasm_bindgen(constructor)]` - this indicates that the binding's name isn't actually used in JS but rather translates to `new Bar()`. The return value of this function must be a bare type, like `Bar`. * `#[wasm_bindgen(js_namespace = Bar)]` - this attribute indicates that the function declaration is namespaced through the `Bar` class in JS. * `#[wasm_bindgen(static_method_of = SomeJsClass)]` - this attribute is similar to `js_namespace`, but instead of producing a free function, produces a static method of `SomeJsClass`. * `#[wasm_bindgen(method)]` - and finally, this attribute indicates that a method call is going to happen. The first argument must be a JS struct, like `Bar`, and the call in JS looks like `Bar.prototype.set.call(...)`. With all that in mind, let's take a look at the JS generated. ```js import * as wasm from './foo_bg'; import { Bar } from './bar'; // other support functions omitted... export function __wbg_s_Bar_new() { return addHeapObject(new Bar()); } const another_function_shim = Bar.another_function; export function __wbg_s_Bar_another_function() { return another_function_shim(); } const get_shim = Bar.prototype.get; export function __wbg_s_Bar_get(ptr) { return shim.call(getObject(ptr)); } const set_shim = Bar.prototype.set; export function __wbg_s_Bar_set(ptr, arg0) { set_shim.call(getObject(ptr), arg0) } const property_shim = Object.getOwnPropertyDescriptor(Bar.prototype, 'property').get; export function __wbg_s_Bar_property(ptr) { return property_shim.call(getObject(ptr)); } const set_property_shim = Object.getOwnPropertyDescriptor(Bar.prototype, 'property').set; export function __wbg_s_Bar_set_property(ptr, arg0) { set_property_shim.call(getObject(ptr), arg0) } ``` Like when importing functions from JS we can see a bunch of shims are generated for all the relevant functions. The `new` static function has the `#[wasm_bindgen(constructor)]` attribute which means that instead of any particular method it should actually invoke the `new` constructor instead (as we see here). The static function `another_function`, however, is dispatched as `Bar.another_function`. The `get` and `set` functions are methods so they go through `Bar.prototype`, and otherwise their first argument is implicitly the JS object itself which is loaded through `getObject` like we saw earlier. Some real meat starts to show up though on the Rust side of things, so let's take a look: ```rust pub struct Bar { obj: JsValue, } impl Bar { fn new() -> Bar { extern "C" { fn __wbg_s_Bar_new() -> u32; } unsafe { let ret = __wbg_s_Bar_new(); Bar { obj: JsValue::__from_idx(ret) } } } fn another_function() -> i32 { extern "C" { fn __wbg_s_Bar_another_function() -> i32; } unsafe { __wbg_s_Bar_another_function() } } fn get(&self) -> i32 { extern "C" { fn __wbg_s_Bar_get(ptr: u32) -> i32; } unsafe { let ptr = self.obj.__get_idx(); let ret = __wbg_s_Bar_get(ptr); return ret } } fn set(&self, val: i32) { extern "C" { fn __wbg_s_Bar_set(ptr: u32, val: i32); } unsafe { let ptr = self.obj.__get_idx(); __wbg_s_Bar_set(ptr, val); } } fn property(&self) -> i32 { extern "C" { fn __wbg_s_Bar_property(ptr: u32) -> i32; } unsafe { let ptr = self.obj.__get_idx(); let ret = __wbg_s_Bar_property(ptr); return ret } } fn set_property(&self, val: i32) { extern "C" { fn __wbg_s_Bar_set_property(ptr: u32, val: i32); } unsafe { let ptr = self.obj.__get_idx(); __wbg_s_Bar_set_property(ptr, val); } } } impl WasmBoundary for Bar { // ... } impl ToRefWasmBoundary for Bar { // ... } ``` In Rust we're seeing that a new type, `Bar`, is generated for this import of a class. The type `Bar` internally contains a `JsValue` as an instance of `Bar` is meant to represent a JS object stored in our module's stack/slab. This then works mostly the same way that we saw JS objects work in the beginning. When calling `Bar::new` we'll get an index back which is wrapped up in `Bar` (which is itself just a `u32` in memory when stripped down). Each function then passes the index as the first argument and otherwise forwards everything along in Rust. wasm-bindgen-0.2.87/guide/src/contributing/design/importing-js.md000064400000000000000000000047141046102023000231130ustar 00000000000000# Importing a function from JS Now that we've exported some rich functionality to JS it's also time to import some! The goal here is to basically implement JS `import` statements in Rust, with fancy types and all. First up, let's say we invert the function above and instead want to generate greetings in JS but call it from Rust. We might have, for example: ```rust #[wasm_bindgen(module = "./greet")] extern "C" { fn greet(a: &str) -> String; } fn other_code() { let greeting = greet("foo"); // ... } ``` The basic idea of imports is the same as exports in that we'll have shims in both JS and Rust doing the necessary translation. Let's first see the JS shim in action: ```js import * as wasm from './foo_bg'; import { greet } from './greet'; // ... export function __wbg_f_greet(ptr0, len0, wasmretptr) { const [retptr, retlen] = passStringToWasm(greet(getStringFromWasm(ptr0, len0))); (new Uint32Array(wasm.memory.buffer))[wasmretptr / 4] = retlen; return retptr; } ``` The `getStringFromWasm` and `passStringToWasm` are the same as we saw before, and like with `__wbindgen_object_drop_ref` far above we've got this weird export from our module now! The `__wbg_f_greet` function is what's generated by `wasm-bindgen` to actually get imported in the `foo.wasm` module. The generated `foo.js` we see imports from the `./greet` module with the `greet` name (was the function import in Rust said) and then the `__wbg_f_greet` function is shimming that import. There's some tricky ABI business going on here so let's take a look at the generated Rust as well. Like before this is simplified from what's actually generated. ```rust extern "C" fn greet(a: &str) -> String { extern "C" { fn __wbg_f_greet(a_ptr: *const u8, a_len: usize, ret_len: *mut usize) -> *mut u8; } unsafe { let a_ptr = a.as_ptr(); let a_len = a.len(); let mut __ret_strlen = 0; let mut __ret_strlen_ptr = &mut __ret_strlen as *mut usize; let _ret = __wbg_f_greet(a_ptr, a_len, __ret_strlen_ptr); String::from_utf8_unchecked( Vec::from_raw_parts(_ret, __ret_strlen, __ret_strlen) ) } } ``` Here we can see that the `greet` function was generated but it's largely just a shim around the `__wbg_f_greet` function that we're calling. The ptr/len pair for the argument is passed as two arguments and for the return value we're receiving one value (the length) indirectly while directly receiving the returned pointer. wasm-bindgen-0.2.87/guide/src/contributing/design/index.md000064400000000000000000000056371046102023000216050ustar 00000000000000# Design of `wasm-bindgen` This section is intended to be a deep-dive into how `wasm-bindgen` internally works today, specifically for Rust. If you're reading this far in the future it may no longer be up to date, but feel free to open an issue and we can try to answer questions and/or update this! ## Foundation: ES Modules The first thing to know about `wasm-bindgen` is that it's fundamentally built on the idea of ES Modules. In other words this tool takes an opinionated stance that wasm files *should be viewed as ES modules*. This means that you can `import` from a wasm file, use its `export`-ed functionality, etc, from normal JS files. Now unfortunately at the time of this writing the interface of wasm interop isn't very rich. Wasm modules can only call functions or export functions that deal exclusively with `i32`, `i64`, `f32`, and `f64`. Bummer! That's where this project comes in. The goal of `wasm-bindgen` is to enhance the "ABI" of wasm modules with richer types like classes, JS objects, Rust structs, strings, etc. Keep in mind, though, that everything is based on ES Modules! This means that the compiler is actually producing a "broken" wasm file of sorts. The wasm file emitted by rustc, for example, does not have the interface we would like to have. Instead it requires the `wasm-bindgen` tool to postprocess the file, generating a `foo.js` and `foo_bg.wasm` file. The `foo.js` file is the desired interface expressed in JS (classes, types, strings, etc) and the `foo_bg.wasm` module is simply used as an implementation detail (it was lightly modified from the original `foo.wasm` file). As more features are stabilized in WebAssembly over time (like host bindings) the JS file is expected to get smaller and smaller. It's unlikely to ever disappear, but `wasm-bindgen` is designed to follow the WebAssembly spec and proposals closely to optimize JS/Rust as much as possible. ## Foundation #2: Unintrusive in Rust On the more Rust-y side of things the `wasm-bindgen` crate is designed to ideally have as minimal impact on a Rust crate as possible. Ideally a few `#[wasm_bindgen]` attributes are annotated in key locations and otherwise you're off to the races. The attribute strives to both not invent new syntax and work with existing idioms today. For example a library might exposed a function in normal Rust that looks like: ```rust pub fn greet(name: &str) -> String { // ... } ``` And with `#[wasm_bindgen]` all you need to do in exporting it to JS is: ```rust #[wasm_bindgen] pub fn greet(name: &str) -> String { // ... } ``` Additionally the design here with minimal intervention in Rust should allow us to easily take advantage of the upcoming [host bindings][host] proposal. Ideally you'd simply upgrade `wasm-bindgen`-the-crate as well as your toolchain and you're immediately getting raw access to host bindings! (this is still a bit of a ways off though...) [host]: https://github.com/WebAssembly/host-bindings wasm-bindgen-0.2.87/guide/src/contributing/design/js-objects-in-rust.md000064400000000000000000000166331046102023000241360ustar 00000000000000# Polyfill for "JS objects in wasm" One of the main goals of `wasm-bindgen` is to allow working with and passing around JS objects in wasm, but that's not allowed today! While indeed true, that's where the polyfill comes in. The question here is how we shoehorn JS objects into a `u32` for wasm to use. The current strategy for this approach is to maintain a module-local variable in the generated `foo.js` file: a `heap`. ### Temporary JS objects on the "stack" The first slots in the `heap` in `foo.js` are considered a stack. This stack, like typical program execution stacks, grows down. JS objects are pushed on the bottom of the stack, and their index in the stack is the identifier that's passed to wasm. A stack pointer is maintained to figure out where the next item is pushed. JS objects are then only removed from the bottom of the stack as well. Removal is simply storing null then incrementing a counter. Because of the "stack-y" nature of this scheme it only works for when wasm doesn't hold onto a JS object (aka it only gets a "reference" in Rust parlance). Let's take a look at an example. ```rust // foo.rs #[wasm_bindgen] pub fn foo(a: &JsValue) { // ... } ``` Here we're using the special `JsValue` type from the `wasm-bindgen` library itself. Our exported function, `foo`, takes a *reference* to an object. This notably means that it can't persist the object past the lifetime of this function call. Now what we actually want to generate is a JS module that looks like (in TypeScript parlance) ```ts // foo.d.ts export function foo(a: any); ``` and what we actually generate looks something like: ```js // foo.js import * as wasm from './foo_bg'; const heap = new Array(32); heap.push(undefined, null, true, false); let stack_pointer = 32; function addBorrowedObject(obj) { stack_pointer -= 1; heap[stack_pointer] = obj; return stack_pointer; } export function foo(arg0) { const idx0 = addBorrowedObject(arg0); try { wasm.foo(idx0); } finally { heap[stack_pointer++] = undefined; } } ``` Here we can see a few notable points of action: * The wasm file was renamed to `foo_bg.wasm`, and we can see how the JS module generated here is importing from the wasm file. * Next we can see our `heap` module variable which is to store all JS values reference-able from wasm. * Our exported function `foo`, takes an arbitrary argument, `arg0`, which is converted to an index with the `addBorrowedObject` object function. The index is then passed to wasm so wasm can operate with it. * Finally, we have a `finally` which frees the stack slot as it's no longer used, popping the value that was pushed at the start of the function. It's also helpful to dig into the Rust side of things to see what's going on there! Let's take a look at the code that `#[wasm_bindgen]` generates in Rust: ```rust // what the user wrote pub fn foo(a: &JsValue) { // ... } #[export_name = "foo"] pub extern "C" fn __wasm_bindgen_generated_foo(arg0: u32) { let arg0 = unsafe { ManuallyDrop::new(JsValue::__from_idx(arg0)) }; let arg0 = &*arg0; foo(arg0); } ``` And as with the JS, the notable points here are: * The original function, `foo`, is unmodified in the output * A generated function here (with a unique name) is the one that's actually exported from the wasm module * Our generated function takes an integer argument (our index) and then wraps it in a `JsValue`. There's some trickery here that's not worth going into just yet, but we'll see in a bit what's happening under the hood. ### Long-lived JS objects The above strategy is useful when JS objects are only temporarily used in Rust, for example only during one function call. Sometimes, though, objects may have a dynamic lifetime or otherwise need to be stored on Rust's heap. To cope with this there's a second half of management of JS objects, naturally corresponding to the other side of the JS `heap` array. JS Objects passed to wasm that are not references are assumed to have a dynamic lifetime inside of the wasm module. As a result the strict push/pop of the stack won't work and we need more permanent storage for the JS objects. To cope with this we build our own "slab allocator" of sorts. A picture (or code) is worth a thousand words so let's show what happens with an example. ```rust // foo.rs #[wasm_bindgen] pub fn foo(a: JsValue) { // ... } ``` Note that the `&` is missing in front of the `JsValue` we had before, and in Rust parlance this means it's taking ownership of the JS value. The exported ES module interface is the same as before, but the ownership mechanics are slightly different. Let's see the generated JS's slab in action: ```js import * as wasm from './foo_bg'; // imports from wasm file const heap = new Array(32); heap.push(undefined, null, true, false); let heap_next = 36; function addHeapObject(obj) { if (heap_next === heap.length) heap.push(heap.length + 1); const idx = heap_next; heap_next = heap[idx]; heap[idx] = obj; return idx; } export function foo(arg0) { const idx0 = addHeapObject(arg0); wasm.foo(idx0); } export function __wbindgen_object_drop_ref(idx) { heap[idx ] = heap_next; heap_next = idx; } ``` Unlike before we're now calling `addHeapObject` on the argument to `foo` rather than `addBorrowedObject`. This function will use `heap` and `heap_next` as a slab allocator to acquire a slot to store the object, placing a structure there once it's found. Note that this is going on the right-half of the array, unlike the stack which resides on the left half. This discipline mirrors the stack/heap in normal programs, roughly. Another curious aspect of this generated module is the `__wbindgen_object_drop_ref` function. This is one that's actually imported to wasm rather than used in this module! This function is used to signal the end of the lifetime of a `JsValue` in Rust, or in other words when it goes out of scope. Otherwise though this function is largely just a general "slab free" implementation. And finally, let's take a look at the Rust generated again too: ```rust // what the user wrote pub fn foo(a: JsValue) { // ... } #[export_name = "foo"] pub extern "C" fn __wasm_bindgen_generated_foo(arg0: u32) { let arg0 = unsafe { JsValue::__from_idx(arg0) }; foo(arg0); } ``` Ah that looks much more familiar! Not much interesting is happening here, so let's move on to... ### Anatomy of `JsValue` Currently the `JsValue` struct is actually quite simple in Rust, it's: ```rust pub struct JsValue { idx: u32, } // "private" constructors impl Drop for JsValue { fn drop(&mut self) { unsafe { __wbindgen_object_drop_ref(self.idx); } } } ``` Or in other words it's a newtype wrapper around a `u32`, the index that we're passed from wasm. The destructor here is where the `__wbindgen_object_drop_ref` function is called to relinquish our reference count of the JS object, freeing up our slot in the `slab` that we saw above. If you'll recall as well, when we took `&JsValue` above we generated a wrapper of `ManuallyDrop` around the local binding, and that's because we wanted to avoid invoking this destructor when the object comes from the stack. ### Working with `heap` in reality The above explanations are pretty close to what happens today, but in reality there's a few differences especially around handling constant values like `undefined`, `null`, etc. Be sure to check out the actual generated JS and the generation code for the full details! wasm-bindgen-0.2.87/guide/src/contributing/design/rust-type-conversions.md000064400000000000000000000067751046102023000250240ustar 00000000000000# Rust Type conversions Previously we've been seeing mostly abridged versions of type conversions when values enter Rust. Here we'll go into some more depth about how this is implemented. There are two categories of traits for converting values, traits for converting values from Rust to JS and traits for the other way around. ## From Rust to JS First up let's take a look at going from Rust to JS: ```rust pub trait IntoWasmAbi: WasmDescribe { type Abi: WasmAbi; fn into_abi(self) -> Self::Abi; } ``` And that's it! This is actually the only trait needed currently for translating a Rust value to a JS one. There's a few points here: * We'll get to `WasmDescribe` later in this section. * The associated type `Abi` is what will actually be generated as an argument / return type for the `extern "C"` functions used to declare wasm imports/exports. The bound `WasmAbi` is implemented for primitive types like `u32` and `f64`, which can be represented directly as WebAssembly values, as well of a couple of `#[repr(C)]` types like `WasmSlice`: ```rust #[repr(C)] pub struct WasmSlice { pub ptr: u32, pub len: u32, } ``` This struct, which is how things like strings are represented in FFI, isn't a WebAssembly primitive type and so isn't mapped directly to a WebAssembly parameter / return value; instead, the C ABI flattens it out into two arguments or stores it on the stack. * And finally we have the `into_abi` function, returning the `Abi` associated type which will be actually passed to JS. This trait is implemented for all types that can be converted to JS and is unconditionally used during codegen. For example you'll often see `IntoWasmAbi for Foo` but also `IntoWasmAbi for &'a Foo`. The `IntoWasmAbi` trait is used in two locations. First it's used to convert return values of Rust exported functions to JS. Second it's used to convert the Rust arguments of JS functions imported to Rust. ## From JS to Rust Unfortunately the opposite direction from above, going from JS to Rust, is a bit more complicated. Here we've got three traits: ```rust pub trait FromWasmAbi: WasmDescribe { type Abi: WasmAbi; unsafe fn from_abi(js: Self::Abi) -> Self; } pub trait RefFromWasmAbi: WasmDescribe { type Abi: WasmAbi; type Anchor: Deref; unsafe fn ref_from_abi(js: Self::Abi) -> Self::Anchor; } pub trait RefMutFromWasmAbi: WasmDescribe { type Abi: WasmAbi; type Anchor: DerefMut; unsafe fn ref_mut_from_abi(js: Self::Abi) -> Self::Anchor; } ``` The `FromWasmAbi` is relatively straightforward, basically the opposite of `IntoWasmAbi`. It takes the ABI argument (typically the same as `IntoWasmAbi::Abi`) to produce an instance of `Self`. This trait is implemented primarily for types that *don't* have internal lifetimes or are references. The latter two traits here are mostly the same, and are intended for generating references (both shared and mutable references). They look almost the same as `FromWasmAbi` except that they return an `Anchor` type which implements a `Deref` trait rather than `Self`. The `Ref*` traits allow having arguments in functions that are references rather than bare types, for example `&str`, `&JsValue`, or `&[u8]`. The `Anchor` here is required to ensure that the lifetimes don't persist beyond one function call and remain anonymous. The `From*` family of traits are used for converting the Rust arguments in Rust exported functions to JS. They are also used for the return value in JS functions imported into Rust. wasm-bindgen-0.2.87/guide/src/contributing/index.md000064400000000000000000000017521046102023000203260ustar 00000000000000# Contributing to `wasm-bindgen` This section contains instructions on how to get this project up and running for development. You may want to browse the [unpublished guide documentation] for `wasm-bindgen` as well as it may have more up-to-date information. [unpublished documentation]: https://rustwasm.github.io/wasm-bindgen/ ## Prerequisites 1. Rust. [Install Rust]. Once Rust is installed, run ```shell rustup target add wasm32-unknown-unknown ``` [install Rust]: https://www.rust-lang.org/en-US/install.html 2. The tests for this project use Node. Make sure you have node >= 10 installed, as that is when WebAssembly support was introduced. [Install Node]. [Install Node]: https://nodejs.org/en/ ## Code Formatting Although formatting rules are not mandatory, it is encouraged to run `cargo run` (`rustfmt`) with its default rules within a PR to maintain a more organized code base. If necessary, a PR with a single commit that formats the entire project is also welcome.wasm-bindgen-0.2.87/guide/src/contributing/js-sys/adding-more-apis.md000064400000000000000000000024001046102023000235560ustar 00000000000000# Adding Support for More JavaScript Global APIs As of 2018-09-24 we've [added all APIs][issue] in the current ECMAScript standard (yay!). To that end you'll hopefully not find a missing API, but if you do please feel free to file an issue! We currently add new APIs added to ECMAScript that are in [TC39 stage 4][tc39] to this crate. If there's a new API in stage 4, feel free to file an issue as well! ### Instructions for adding an API * [ ] Find the `wasm-bindgen` issue for the API you'd like to add. If this doesn't exist, feel free to open one! Afterwards be sure to comment on the issue to avoid duplication of work. * [ ] Open the [MDN page](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects) for the relevant JS API. * [ ] Open `crates/js-sys/src/lib.rs` in your editor; this is the file where we are implementing the bindings. * [ ] Follow the instructions in the top of `crates/js-sys/src/lib.rs` about how to add new bindings. * [ ] Add a test for the new binding to `crates/js-sys/tests/wasm/MyType.rs` * [ ] Run the [JS global API bindings tests][test] * [ ] Send a pull request! [issue]: https://github.com/rustwasm/wasm-bindgen/issues/275 [tc39]: https://tc39.github.io/process-document/ [test]: testing.html wasm-bindgen-0.2.87/guide/src/contributing/js-sys/index.md000064400000000000000000000040361046102023000215540ustar 00000000000000# `js-sys` The [`js-sys` crate][js-sys] provides raw bindings to all the global APIs guaranteed to exist in every JavaScript environment by the ECMAScript standard, and its source lives at [`wasm-bindgen/crates/js-sys`][src]. With the `js-sys` crate, we can work with `Object`s, `Array`s, `Function`s, `Map`s, `Set`s, etc... without writing the `#[wasm_bindgen]` imports by hand. Documentation for the published version of this crate is available on [docs.rs][docsrs] but you can also check out the [master branch documentation][masterdoc] for the crate. [docsrs]: https://docs.rs/js-sys [masterdoc]: https://rustwasm.github.io/wasm-bindgen/api/js_sys/ [src]: https://github.com/rustwasm/wasm-bindgen/tree/master/crates/js-sys For example, we can invoke JavaScript [`Function`][mdn-function] callbacks and time how long they take to execute with [`Date.now()`][mdn-date-now], and we don't need to write any JS imports ourselves: ```rust use wasm_bindgen::prelude::*; #[wasm_bindgen] pub fn timed(callback: &js_sys::Function) -> f64 { let then = js_sys::Date::now(); callback.apply(JsValue::null(), &js_sys::Array::new()).unwrap(); let now = js_sys::Date::now(); now - then } ``` The `js-sys` crate doesn't contain bindings to any Web APIs like [`document.querySelectorAll`][mdn-qsa]. These will be part of the [`web-sys`][web-sys] crate. [MDN]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects [js-sys]: https://crates.io/crates/js-sys [issue]: https://github.com/rustwasm/wasm-bindgen/issues/275 [mdn-function]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function [mdn-qsa]: https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll [web-sys]: https://crates.io/crates/web-sys [web-sys-contributing]: https://rustwasm.github.io/wasm-bindgen/web-sys.html [web-sys-issues]: https://github.com/rustwasm/wasm-bindgen/issues?q=is%3Aissue+is%3Aopen+label%3Aweb-sys [mdn-date-now]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now wasm-bindgen-0.2.87/guide/src/contributing/js-sys/testing.md000064400000000000000000000006011046102023000221140ustar 00000000000000# Testing You can test the `js-sys` crate by running `cargo test --target wasm32-unknown-unknown` within the `crates/js-sys` directory in the `wasm-bindgen` repository: ```sh cd wasm-bindgen/crates/js-sys cargo test --target wasm32-unknown-unknown ``` These tests are largely executed in Node.js right now via the [`wasm-bindgen-test` framework](../../wasm-bindgen-test/index.html) wasm-bindgen-0.2.87/guide/src/contributing/publishing.md000064400000000000000000000010761046102023000213620ustar 00000000000000# Publishing New `wasm-bindgen` Releases 1. Compile the `publish.rs` script: ``` rustc publish.rs ``` 2. Bump every crate's minor version: ``` # Make sure you are in the root of the wasm-bindgen repo! ./publish bump ``` 3. Send a pull request for the version bump. 4. After the pull request's CI is green and it has been merged, publish to cargo: ``` # Make sure you are in the root of the wasm-bindgen repo! ./publish publish ``` wasm-bindgen-0.2.87/guide/src/contributing/team.md000064400000000000000000000030411046102023000201360ustar 00000000000000# Team `wasm-bindgen` follows the [`rustwasm` organization's governance described here][governance]: * All pull requests (including those made by a team member) must be approved by at least one other team member. * Larger, more nuanced decisions about design, architecture, breaking changes, trade offs, etc are made by team consensus. [governance]: https://github.com/rustwasm/team/blob/master/GOVERNANCE.md#repositories ## Members | [![](https://github.com/alexcrichton.png?size=117)][alexcrichton] | [![](https://github.com/fitzgen.png?size=117)][fitzgen] | [![](https://github.com/spastorino.png?size=117)][spastorino] | [![](https://github.com/ohanar.png?size=117)][ohanar] | [![](https://github.com/jonathan-s.png?size=117)][jonathan-s] | |:---:|:---:|:---:|:---:| | [`alexcrichton`][alexcrichton] | [`fitzgen`][fitzgen] | [`spastorino`][spastorino] | [`ohanar`][ohanar] | [`jonathan-s`][jonathan-s] | | [![](https://github.com/sendilkumarn.png?size=117)][sendilkumarn] | [![](https://github.com/belfz.png?size=117)][belfz] | [![](https://github.com/afdw.png?size=117)][afdw] | | | | [`sendilkumarn`][sendilkumarn] | [`belfz`][belfz] | [`afdw`][afdw] | | | [alexcrichton]: https://github.com/alexcrichton [fitzgen]: https://github.com/fitzgen [spastorino]: https://github.com/spastorino [ohanar]: https://github.com/ohanar [jonathan-s]: https://github.com/jonathan-s [sendilkumarn]: https://github.com/sendilkumarn [belfz]: https://github.com/belfz [afdw]: https://github.com/afdw wasm-bindgen-0.2.87/guide/src/contributing/testing.md000064400000000000000000000022511046102023000206670ustar 00000000000000# Running `wasm-bindgen`'s Tests ## Wasm Tests on Node and Headless Browsers These are the largest test suites, and most common to run in day to day `wasm-bindgen` development. These tests are compiled to Wasm and then run in Node.js or a headless browser via the WebDriver protocol. ```bash cargo test --target wasm32-unknown-unknown ``` See [the `wasm-bindgen-test` crate's `README.md`](https://github.com/rustwasm/wasm-bindgen/blob/master/crates/test/README.md) for details and configuring which headless browser is used. ## Sanity Tests for `wasm-bindgen` on the Native Host Target This small test suite just verifies that exported `wasm-bindgen` methods can still be used on the native host's target. ``` cargo test ``` ## The Web IDL Frontend's Tests ``` cargo test -p webidl-tests --target wasm32-unknown-unknown ``` ## The Macro UI Tests These tests assert that we have reasonable error messages that point to the right source spans when the `#[wasm_bindgen]` proc-macro is misused. ``` cargo test -p ui-tests ``` ## The `js-sys` Tests See [the `js-sys` testing page](js-sys/testing.html). ## The `web-sys` Tests See [the `web-sys` testing page](web-sys/testing.html). wasm-bindgen-0.2.87/guide/src/contributing/web-sys/index.md000064400000000000000000000014261046102023000217150ustar 00000000000000# `web-sys` The `web-sys` crate provides raw bindings to all of the Web's APIs, and its source lives at `wasm-bindgen/crates/web-sys`. The `web-sys` crate is **entirely** mechanically generated inside `build.rs` using `wasm-bindgen`'s WebIDL frontend and the WebIDL interface definitions for Web APIs. This means that `web-sys` isn't always the most ergonomic crate to use, but it's intended to provide verified and correct bindings to the web platform, and then better interfaces can be iterated on crates.io! Documentation for the published version of this crate is available on [docs.rs][docsrs] but you can also check out the [master branch documentation][masterdoc] for the crate. [docsrs]: https://docs.rs/web-sys [masterdoc]: https://rustwasm.github.io/wasm-bindgen/api/web_sys/ wasm-bindgen-0.2.87/guide/src/contributing/web-sys/logging.md000064400000000000000000000013411046102023000222300ustar 00000000000000# Logging The `wasm_bindgen_webidl` crate (used by `web-sys`'s `build.rs`) uses [`env_logger`][env_logger] for logging, which can be enabled by setting the `RUST_LOG=wasm_bindgen_webidl` environment variable while building the `web-sys` crate. Make sure to enable "very verbose" output during `cargo build` to see these logs within `web-sys`'s build script output. ```sh cd crates/web-sys RUST_LOG=wasm_bindgen_webidl cargo build -vv ``` If `wasm_bindgen_webidl` encounters WebIDL constructs that it doesn't know how to translate into `wasm-bindgen` AST items, it will emit warn-level logs. ``` WARN 2018-07-06T18:21:49Z: wasm_bindgen_webidl: Unsupported WebIDL interface: ... ``` [env_logger]: https://crates.io/crates/env_logger wasm-bindgen-0.2.87/guide/src/contributing/web-sys/overview.md000064400000000000000000000023751046102023000224600ustar 00000000000000# `web-sys` Overview The `web-sys` crate has this file and directory layout: ```text . ├── build.rs ├── Cargo.toml ├── README.md ├── src │ └── lib.rs └── webidls └── enabled └── ... ``` ### `webidls/enabled/*.webidl` These are the WebIDL interfaces that we will actually generate bindings for (or at least bindings for *some* of the things defined in these files). ### `build.rs` The `build.rs` invokes `wasm-bindgen`'s WebIDL frontend on all the WebIDL files in `webidls/enabled`. It writes the resulting bindings into the cargo build's out directory. ### `src/lib.rs` The only thing `src/lib.rs` does is include the bindings generated at compile time in `build.rs`. Here is the whole `src/lib.rs` file: ```rust {{#include ../../../../crates/web-sys/src/lib.rs}} ``` ### Cargo features When compiled the crate is almost empty by default, which probably isn't what you want! Due to the very large number of APIs, this crate uses features to enable portions of its API to reduce compile times. The list of features in `Cargo.toml` all correspond to types in the generated functions. Enabling a feature enables that type. All methods should indicate what features need to be activated to use the method. wasm-bindgen-0.2.87/guide/src/contributing/web-sys/supporting-more-web-apis.md000064400000000000000000000025621046102023000254670ustar 00000000000000# Supporting More Web APIs in `web-sys` 1. Ensure that the `.webidl` file describing the interface exists somewhere within the `crates/web-sys/webidls/enabled` directory. First, check to see whether we have the WebIDL definition file for your API: ```sh grep -rn MyWebApi crates/web-sys/webidls ``` * If your interface is defined in a `.webidl` file that is inside the `crates/web-sys/webidls/enabled` directory, skip to step (3). * If your interface isn't defined in any file yet, find the WebIDL definition in the relevant standard and add it as a new `.webidl` file in `crates/web-sys/webidls/enabled`. Make sure that it is a standard Web API! We don't want to add non-standard APIs to this crate. * If your interface is defined in a `.webidl` file within any of the `crates/web-sys/webidls/unavailable_*` directories, you need to move it into `crates/web-sys/webidls/enabled`, e.g.: ```sh cd crates/web-sys git mv webidls/unavailable_enum_ident/MyWebApi.webidl webidls/enabled/MyWebApi.webidl ``` 2. Regenerate the `web-sys` crate auto-generated bindings, which you can do with the following commands: ```sh cd crates/web-sys cargo run --release --package wasm-bindgen-webidl -- webidls src/features ./Cargo.toml ``` You can then use `git diff` to ensure the bindings look correct. wasm-bindgen-0.2.87/guide/src/contributing/web-sys/testing.md000064400000000000000000000007351046102023000222650ustar 00000000000000# Testing You can test the `web-sys` crate by running `cargo test` within the `crates/web-sys` directory in the `wasm-bindgen` repository: ```sh cd wasm-bindgen/crates/web-sys cargo test --target wasm32-unknown-unknown --all-features ``` The Wasm tests all run within a headless browser. See [the `wasm-bindgen-test` crate's `README.md`](https://github.com/rustwasm/wasm-bindgen/blob/master/crates/test/README.md) for details and configuring which headless browser is used. wasm-bindgen-0.2.87/guide/src/examples/2d-canvas.md000064400000000000000000000014511046102023000201000ustar 00000000000000# 2D Canvas [View full source code][code] or [view the compiled example online][online] [online]: https://rustwasm.github.io/wasm-bindgen/exbuild/canvas/ [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/canvas Drawing a smiley face with the 2D canvas API. This is a port of part of [this MDN tutorial](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes#Moving_the_pen) to `web-sys`. ![A smiley face](./2d-canvas.png) ## `Cargo.toml` The `Cargo.toml` enables features necessary to query the DOM and work with 2D canvas. ```toml {{#include ../../../examples/canvas/Cargo.toml}} ``` ## `src/lib.rs` Gets the `` element, creates a 2D rendering context, and draws the smiley face. ```rust {{#include ../../../examples/canvas/src/lib.rs}} ``` wasm-bindgen-0.2.87/guide/src/examples/2d-canvas.png000064400000000000000000000073301046102023000202660ustar 00000000000000‰PNG  IHDR––<qâžIDATxœíÝmLS×ð¢D %` ‚ 0jâ‹a0 M¡A‚ 1IJ6­>^К‚kaa6lªÜk`µZaµZqÿþ}§¯û*,-- VO°`566"55U¨r/ýõ×_GXXôz=ôz=8¥R‰……§«û6:ׯ_¬ž`Á:zô(._¾,T9/~¸r¹ß~ûíkÖ××¹\Nä`ZZußÅjµB¯× VO°`ùúú r<ã…‡‡¿ñ‡»¬··—È–ZußåáÇð÷÷¬ž Ázüø1¶oß.D©—¶âß Åàà äëÚÃËËK°Ó Ö•+W¿¿²÷£_§Ó¡ªªJòuí¡ÓéÐÐÐ H-A‚Ecë1 Öë„ܺ,H°"""ÐÛÛ+D©—îß¿¬ø÷öïßÏë%‰V]{tuu!**JZ‚ËÛÛÛ¡Ãù¹R*•èëë{ëŸwwwC¥R9MÝ•|ÈiìØØxîèí –V«Euu5çñjµZ;0iéïï‡F£á<þâÅ‹‚¾K°`5559tæ7ðñÇóØ‘´:t_ý5çñz½­­­ã±#iÈÎÎÆ78¿víŽ9ÂcG+4X·nÝBtt´Cs|øá‡øþûïyêHüîÞ½k×!#ï¢R©ÐÝÝÍSGöüp[wwwÌÍÍqÏÇeAJ½ü?yò›7oæ±#û,³ÙìÐo‡pæÌÔÖÖòÓˆ]ºt gÏžuh«ÕŠsçÎñÔ‘ý_/g ä‰^ZøÚ‹FëeMT^yâȩ˜ýÒ|œ‡Oó |*Áššš‚———ÃóôööB«ÕòБ¸$''ã›o¾qxž-[¶à·ß~ã¡£÷GíµrƒMMMÏãlOZ'$$ ¾¾Þáy®^½JõýÐÔ‚õôéS¸¹¹ñ2Wss3>ùä^æ¢I­Vó¶:¾qãFüù矼ÌÅÕW÷"''‡—¹‘˜˜ÈË\4$$$𪬬,\¸p—¹¸¢þ²ñ€€Œñ2×—_~ NÇË\BJNNæåò### âe.GPÖ;wÉÛ|===ðððÄR„ÍfƒL&ãåF}™B¡Àwß}ÇÛ|\QÀÿG÷ìì,BBBDý^ÄK—.a÷îݼ¾bÏ[ G‰"X°gÏÞ÷[9sÁÁÁ¢ø¼ìîÝ» txEýUýýýØ·o¯s:B4ÁšŸŸ‡L&ã}Þááa„††"''###¼Ïo¯¡¡!dgg#,,ŒÈÖŸM›6á?þà}^®D,¸yó&± µ´´ ((}ôˆÔx“þþ~:t!!!m}y­V+ø‹.W"ª`@QQ²³³‰ÍßÞÞŽ„„àìÙ³øõ×_y¯1==ÜÜ\øûûC£Ñ8´ós%™™™())!6?W¢ œ8qDkŒáóÏ?GLL ‘ššŠöövNo(Gkk+RRR°sçNÄÄÄàÔ©Sœ|°—˜¦e° 11¥¥¥‚ÔÅ_|µZ ___¸¸¸ $$™™™Ðh4HOO‡Éd‚ÉdBzz:4 ²²²Œµk×ÂÏÏjµ•••œ&}_çÏŸõ÷¤¢ ”””®ÿZZZÂÐÐ:;;QWW‡òòr˜Íf˜Íf”——£®®ä€W?žó‰~Bu°€Ÿ\¤/‹Rb6›EýIµLôÁ^Üs‘¼¡—ŠÌÌLÑÞS½JÁ^ü¶(…ÿ©¤hµZQþö÷6’ ðbËÍÍ < ÝŠ`úûû±iÓ&Ñ­S­DRÁ^ìãÚ»w/Š‹‹i·B\aa!öíÛ'ªu{I.XËŒF# …S>=22…B!š/”¹l°àÞ½{ tªû¬¬,‰ê‹s.$¬eEEEpuuìP1®^½Š7Rßùɧ<{ö ÇÇÖ­[QQQA»»•••aË–-0T÷¨óÍi‚µlzziiiÉd¨ªªÂÌÌ í–^óäÉX­V¸ºº"##ƒÚ#Z$9]°–ÍÏÏ#//žžžˆŠŠBcc#í–píÚ5¨T*lÞ¼çΣò„²Pœ6XÿÕÕÕ…øøx¸¸¸@§ÓÁjµßy¼ØAqñâEèõz¬Y³GŽüÔZVE°–---áúõëÐëõð÷÷‡——t:Š‹‹ÑÕÕÅiË̲ññqtvv¢¸¸Z­Û¶mC@@Ž;†ÖÖVA=ƒU¬WMMM¡¡¡F£QQQ/·Ì„‡‡C©T"66/·Íddd@£Ñ 66J¥r¹üåÖ™ƒÂh4¢¡¡A°Ó‰ÅjUëM–·Ìôõõ¡­­ uuu(++{¹m¦¬¬ uuuhkkC__µ­3bÇ‚ÅÁ‚ÅÁ‚ÅÁ‚ÅÁ‚ÅÁ‚ÅÁ‚ÅÁ‚ÅÁ‚ÅÁ‚ÅÁ‚ÅÁ‚ÅÁ‚ÅÁ‚ÅÁ‚ÅÁ‚ÅÁ‚ÅÁ‚ÅÁ‚ÅÁ‚ÅÁ‚ÅÁ‚ÅÁ‚ÅÁ‚ÅñÍdIŸ ƒœIEND®B`‚ wasm-bindgen-0.2.87/guide/src/examples/add.md000064400000000000000000000033511046102023000170530ustar 00000000000000# Small wasm files [View full source code][code] or [view the compiled example online][online] [online]: https://rustwasm.github.io/wasm-bindgen/exbuild/add/ [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/add One of `wasm-bindgen`'s core goals is a pay-only-for-what-you-use philosophy, so if we don't use much then we shouldn't be paying much! As a result `#[wasm_bindgen]` can generate super-small executables Currently this code... ```rust {{#include ../../../examples/add/src/lib.rs}} ``` generates a 710 byte wasm binary: ``` $ ls -l add_bg.wasm -rw-rw-r-- 1 alex alex 710 Sep 19 17:32 add_bg.wasm ``` If you run [wasm-opt], a C++ tool for optimize WebAssembly, you can make it even smaller too! ``` $ wasm-opt -Os add_bg.wasm -o add.wasm $ ls -l add.wasm -rw-rw-r-- 1 alex alex 172 Sep 19 17:33 add.wasm ``` And sure enough, using the [wasm2wat] tool it's quite small! ``` $ wasm2wat add.wasm (module (type (;0;) (func (param i32 i32) (result i32))) (func (;0;) (type 0) (param i32 i32) (result i32) get_local 1 get_local 0 i32.add) (table (;0;) 1 1 anyfunc) (memory (;0;) 17) (global (;0;) i32 (i32.const 1049118)) (global (;1;) i32 (i32.const 1049118)) (export "memory" (memory 0)) (export "__indirect_function_table" (table 0)) (export "__heap_base" (global 0)) (export "__data_end" (global 1)) (export "add" (func 0)) (data (i32.const 1049096) "invalid malloc request")) ``` Also don't forget to compile in release mode for the smallest binaries! For larger applications you'll likely also want to turn on LTO to generate the smallest binaries: ```toml [profile.release] lto = true ``` [wasm2wat]: https://github.com/webassembly/wabt [wasm-opt]: https://github.com/webassembly/binaryen wasm-bindgen-0.2.87/guide/src/examples/char.md000064400000000000000000000021171046102023000172370ustar 00000000000000# Working with the `char` type [View full source code][code] or [view the compiled example online][online] [online]: https://rustwasm.github.io/wasm-bindgen/exbuild/char/ [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/char The `#[wasm_bindgen]` macro will convert the rust `char` type to a single code-point js `string`, and this example shows how to work with this. Opening this example should display a single counter with a random character for it's `key` and 0 for its `count`. You can click the `+` button to increase a counter's count. By clicking on the "add counter" button you should see a new counter added to the list with a different random character for it's `key`. Under the hood javascript is choosing a random character from an Array of characters and passing that to the rust Counter struct's constructor so the character you are seeing on the page has made the full round trip from js to rust and back to js. ## `src/lib.rs` ```rust {{#include ../../../examples/char/src/lib.rs}} ``` ## `index.js` ```js {{#include ../../../examples/char/index.js}} ``` wasm-bindgen-0.2.87/guide/src/examples/closures.md000064400000000000000000000010511046102023000201550ustar 00000000000000# web-sys: Closures [View full source code][code] or [view the compiled example online][online] [online]: https://rustwasm.github.io/wasm-bindgen/exbuild/closures/ [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/closures One of the features of `#[wasm_bindgen]` is that you can pass closures defined in Rust off to JS. This can be a bit tricky at times, though, so the example here shows how to interact with some standard web APIs with closures. ## `src/lib.rs` ```rust {{#include ../../../examples/closures/src/lib.rs}} ``` wasm-bindgen-0.2.87/guide/src/examples/console-log.md000064400000000000000000000007371046102023000205510ustar 00000000000000# `console.log` [View full source code][code] or [view the compiled example online][online] [online]: https://rustwasm.github.io/wasm-bindgen/exbuild/console_log/ [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/console_log This example shows off how to use `console.log` in a variety of ways, all the way from bare-bones usage to a `println!`-like macro with `web_sys`. ## `src/lib.rs` ```rust {{#include ../../../examples/console_log/src/lib.rs}} ``` wasm-bindgen-0.2.87/guide/src/examples/dom.md000064400000000000000000000013621046102023000171020ustar 00000000000000# web-sys: DOM hello world [View full source code][code] or [view the compiled example online][online] [online]: https://rustwasm.github.io/wasm-bindgen/exbuild/dom/ [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/dom Using `web-sys` we're able to interact with all the standard web platform methods, including those of the DOM! Here we take a look at a simple "Hello, world!" which manufactures a DOM element in Rust, customizes it, and then appends it to the page. ## `Cargo.toml` You can see here how we depend on `web-sys` and activate associated features to enable all the various APIs: ```toml {{#include ../../../examples/dom/Cargo.toml}} ``` ## `src/lib.rs` ```rust {{#include ../../../examples/dom/src/lib.rs}} ``` wasm-bindgen-0.2.87/guide/src/examples/fetch.md000064400000000000000000000011571046102023000174160ustar 00000000000000# The `fetch` API [View full source code][code] or [view the compiled example online][online] [online]: https://rustwasm.github.io/wasm-bindgen/exbuild/fetch/ [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/fetch This example uses the `fetch` API to make an HTTP request to the GitHub API and then parses the resulting JSON. ## `Cargo.toml` The `Cargo.toml` enables a number of features related to the `fetch` API and types used: `Headers`, `Request`, etc. ```toml {{#include ../../../examples/fetch/Cargo.toml}} ``` ## `src/lib.rs` ```rust {{#include ../../../examples/fetch/src/lib.rs}} ``` wasm-bindgen-0.2.87/guide/src/examples/hello-world.md000064400000000000000000000026121046102023000205520ustar 00000000000000# Hello, World! [View full source code][code] or [view the compiled example online][online] [online]: https://rustwasm.github.io/wasm-bindgen/exbuild/hello_world/ [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/hello_world This is the "Hello, world!" example of `#[wasm_bindgen]` showing how to set up a project, export a function to JS, call it from JS, and then call the `alert` function in Rust. ## `Cargo.toml` The `Cargo.toml` lists the `wasm-bindgen` crate as a dependency. Also of note is the `crate-type = ["cdylib"]` which is largely used for wasm final artifacts today. ```toml {{#include ../../../examples/hello_world/Cargo.toml}} ``` ## `src/lib.rs` Here we define our Rust entry point along with calling the `alert` function. ```rust {{#include ../../../examples/hello_world/src/lib.rs}} ``` ## `index.js` Our JS entry point is quite small! ```js {{#include ../../../examples/hello_world/index.js}} ``` ## Webpack-specific files > **Note**: Webpack is required for this example, and if you're interested > in options that don't use a JS bundler [see other examples][wab]. [wab]: without-a-bundler.html And finally here's the Webpack configuration and `package.json` for this project: **webpack.config.js** ```js {{#include ../../../examples/hello_world/webpack.config.js}} ``` **package.json** ```json {{#include ../../../examples/hello_world/package.json}} ``` wasm-bindgen-0.2.87/guide/src/examples/import-js.md000064400000000000000000000015131046102023000202450ustar 00000000000000# Importing non-browser JS [View full source code][code] or [view the compiled example online][online] [online]: https://rustwasm.github.io/wasm-bindgen/exbuild/import_js/ [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/import_js The `#[wasm_bindgen]` attribute can be used on `extern "C" { .. }` blocks to import functionality from JS. This is how the `js-sys` and the `web-sys` crates are built, but you can also use it in your own crate! For example if you're working with this JS file: ```js // defined-in-js.js {{#include ../../../examples/import_js/crate/defined-in-js.js}} ``` you can use it in Rust with: ```rust {{#include ../../../examples/import_js/crate/src/lib.rs}} ``` You can also [explore the full list of ways to configure imports][attr] [attr]: ../reference/attributes/on-js-imports/index.html wasm-bindgen-0.2.87/guide/src/examples/index.md000064400000000000000000000023041046102023000174270ustar 00000000000000# Examples of using `wasm-bindgen`, `js-sys`, and `web-sys` This subsection contains examples of using the `wasm-bindgen`, `js-sys`, and `web-sys` crates. Each example should have more information about what it's doing. These examples all assume familiarity with `wasm-bindgen`, `wasm-pack`, and building a Rust and WebAssembly project. If you're unfamiliar with these check out the [Game of Life tutorial][gol] or [wasm pack tutorials][wpt] to help you get started. The source code for all examples can also be [found online][code] to download and run locally. Most examples are configured with Webpack/`wasm-pack` and can be built with `npm run serve`. Other examples which don't use Webpack are accompanied with instructions or a `build.sh` showing how to build it. Note that most examples currently use Webpack to assemble the final output artifact, but this is not required! You can review the [deployment documentation][deploy] for other options of how to deploy Rust and WebAssembly. [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples [gol]: https://rustwasm.github.io/docs/book/ [deploy]: ../reference/deployment.html [wpt]: https://rustwasm.github.io/docs/wasm-pack/tutorials/index.html wasm-bindgen-0.2.87/guide/src/examples/julia.md000064400000000000000000000011501046102023000174220ustar 00000000000000# Julia Set [View full source code][code] or [view the compiled example online][online] [online]: https://rustwasm.github.io/wasm-bindgen/exbuild/julia_set/ [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/julia_set While not showing off a lot of `web_sys` API surface area, this example shows a neat fractal that you can make! ## `index.js` A small bit of glue is added for this example ```js {{#include ../../../examples/julia_set/index.js}} ``` ## `src/lib.rs` The bulk of the logic is in the generation of the fractal ```rust {{#include ../../../examples/julia_set/src/lib.rs}} ``` wasm-bindgen-0.2.87/guide/src/examples/paint.md000064400000000000000000000012211046102023000174300ustar 00000000000000# Paint Example [View full source code][code] or [view the compiled example online][online] [online]: https://rustwasm.github.io/wasm-bindgen/exbuild/paint/ [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/paint A simple painting program. ## `Cargo.toml` The `Cargo.toml` enables features necessary to work with the DOM, events and 2D canvas. ```toml {{#include ../../../examples/paint/Cargo.toml}} ``` ## `src/lib.rs` Creates the `` element, applies a CSS style to it, adds it to the document, get a 2D rendering context and adds listeners for mouse events. ```rust {{#include ../../../examples/paint/src/lib.rs}} ``` wasm-bindgen-0.2.87/guide/src/examples/performance.md000064400000000000000000000007771046102023000206350ustar 00000000000000# web-sys: `performance.now` [View full source code][code] or [view the compiled example online][online] [online]: https://rustwasm.github.io/wasm-bindgen/exbuild/performance/ [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/performance Want to profile some Rust code in the browser? No problem! You can use the `performance.now()` API and friends to get timing information to see how long things take. ## `src/lib.rs` ```rust {{#include ../../../examples/performance/src/lib.rs}} ``` wasm-bindgen-0.2.87/guide/src/examples/raytrace.md000064400000000000000000000145201046102023000201350ustar 00000000000000# Parallel Raytracing [View full source code][code] or [view the compiled example online][online] [online]: https://wasm-bindgen.netlify.app/exbuild/raytrace-parallel/ [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/raytrace-parallel This is an example of using threads with WebAssembly, Rust, and `wasm-bindgen`, culminating in a parallel raytracer demo. There's a number of moving pieces to this demo and it's unfortunately not the easiest thing to wrangle, but it's hoped that this'll give you a bit of a taste of what it's like to use threads and wasm with Rust on the web. ### Building the demo One of the major gotchas with threaded WebAssembly is that Rust does not ship a precompiled target (e.g. standard library) which has threading support enabled. This means that you'll need to recompile the standard library with the appropriate rustc flags, namely `-C target-feature=+atomics,+bulk-memory,+mutable-globals`. Note that this requires a nightly Rust toolchain. To do this you can use the `RUSTFLAGS` environment variable that Cargo reads: ```sh export RUSTFLAGS='-C target-feature=+atomics,+bulk-memory,+mutable-globals' ``` To recompile the standard library it's recommended to use Cargo's [`-Zbuild-std`](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std) feature: ```sh cargo build --target wasm32-unknown-unknown -Z build-std=panic_abort,std ``` Note that you can also configure this via `.cargo/config.toml`: ```toml [unstable] build-std = ['std', 'panic_abort'] [build] target = "wasm32-unknown-unknown" rustflags = '-Ctarget-feature=+atomics,+bulk-memory,+mutable-globals' ``` After this `cargo build` should produce a WebAssembly file with threading enabled, and the standard library will be appropriately compiled as well. The final step in this is to run `wasm-bindgen` as usual, and `wasm-bindgen` needs no extra configuration to work with threads. You can continue to run it through `wasm-pack`, for example. ### Running the demo Currently it's required to use the `--target no-modules` or `--target web` flag with `wasm-bindgen` to run threaded code. This is because the WebAssembly file imports memory instead of exporting it, so we need to hook initialization of the wasm module at this time to provide the appropriate memory object. This demo uses `--target no-modules`, because Firefox does not support modules in workers. With `--target no-modules` you'll be able to use `importScripts` inside of each web worker to import the shim JS generated by `wasm-bindgen` as well as calling the `wasm_bindgen` initialization function with the shared memory instance from the main thread. The expected usage is that WebAssembly on the main thread will post its memory object to all other threads to get instantiated with. ### Caveats Unfortunately at this time running wasm on the web with threads has a number of caveats, although some are specific to just `wasm-bindgen`. These are some pieces to consider and watch out for, although we're always looking for improvements to be made so if you have an idea please file an issue! * The main thread in a browser cannot block. This means that if you run WebAssembly code on the main thread you can *never* block, meaning you can't do so much as acquire a mutex. This is an extremely difficult limitation to work with on the web, although one workaround is to run wasm exclusively in web workers and run JS on the main thread. It is possible to run the same wasm across all threads, but you need to be extremely vigilant about synchronization with the main thread. * Setting up a threaded environment is a bit wonky and doesn't feel smooth today. For example `--target bundler` is unsupported and very specific shims are required on both the main thread and worker threads. These are possible to work with but are somewhat brittle since there's no standard way to spin up web workers as wasm threads. * There is no standard notion of a "thread". For example the standard library has no viable route to implement the `std::thread` module. As a consequence there is no concept of thread exit and TLS destructors will never run. We do expose a helper, `__wbindgen_thread_destroy`, that deallocates the thread stack and TLS. If you invoke it, it *must* be the last function you invoke from the wasm module for a given thread. * Any thread launched after the first one _might attempt to block_ implicitly in its initialization routine. This is a constraint introduced by the way we set up the space for thread stacks and TLS. This means that if you attempt to run a wasm module in the main thread _after_ you are already running it in a worker, it might fail. * Web Workers executing WebAssembly code cannot receive events from JS. A Web Worker has to fully return back to the browser (and ideally should do so occasionally) to receive JS messages and such. This means that common paradigms like a rayon thread pool do not apply straightforward-ly to the web. The intention of the web is that all long-term blocking happens in the browser itself, not in each thread, but many crates in the ecosystem leveraging threading are not necessarily engineered this way. These caveats are all largely inherited from the web platform itself, and they're important to consider when designing an application for threading. It's highly unlikely that you can pull a crate off the shelf and "just use it" due to these limitations. You'll need to be sure to carefully plan ahead and ensure that gotchas such as these don't cause issues in the future. As mentioned before though we're always trying to actively develop this support so if folks have ideas about how to improve, or if web standards change, we'll try to update this documentation! ### Browser Requirements This demo should work in the latest Firefox and Chrome versions at this time, and other browsers are likely to follow suit. Note that threads and `SharedArrayBuffer` require HTTP headers to be set to work correctly. For more information see the [documentation on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer) under "Security requirements" as well as [Firefox's rollout blog post](https://hacks.mozilla.org/2020/07/safely-reviving-shared-memory/). This means that during local development you'll need to configure your web server appropriately or enable a workaround in your browser. wasm-bindgen-0.2.87/guide/src/examples/request-animation-frame.md000064400000000000000000000015241046102023000230600ustar 00000000000000# `web-sys`: A `requestAnimationFrame` Loop [View full source code][code] or [view the compiled example online][online] [online]: https://rustwasm.github.io/wasm-bindgen/exbuild/request-animation-frame/ [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/request-animation-frame This is an example of a `requestAnimationFrame` loop using the `web-sys` crate! It renders a count of how many times a `requestAnimationFrame` callback has been invoked and then it breaks out of the `requestAnimationFrame` loop after 300 iterations. ## `Cargo.toml` You can see here how we depend on `web-sys` and activate associated features to enable all the various APIs: ```toml {{#include ../../../examples/request-animation-frame/Cargo.toml}} ``` ## `src/lib.rs` ```rust {{#include ../../../examples/request-animation-frame/src/lib.rs}} ``` wasm-bindgen-0.2.87/guide/src/examples/synchronous-instantiation.md000064400000000000000000000027401046102023000236000ustar 00000000000000# Synchronous Instantiation [View full source code][code] [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/synchronous-instantiation This example shows how to synchronously initialize a WebAssembly module as opposed to [asynchronously][without-bundler]. In most cases, the default way of asynchronously initializing a module will suffice. However, there might be use cases where you'd like to lazy load a module on demand and synchronously compile and instantiate it. Note that this only works off the main thread and since compilation and instantiation of large modules can be expensive you should only use this method if it's absolutely required in your use case. Otherwise you should use the [default method][without-bundler]. For this deployment strategy bundlers like Webpack are not required. For more information on deployment see the [dedicated documentation][deployment]. First let's take a look at our tiny lib: ```rust {{#include ../../../examples/synchronous-instantiation/src/lib.rs}} ``` Next, let's have a look at the `index.html`: ```html {{#include ../../../examples/synchronous-instantiation/index.html}} ``` Otherwise the rest of the magic happens in `worker.js`: ```js {{#include ../../../examples/synchronous-instantiation/worker.js}} ``` And that's it! Be sure to read up on the [deployment options][deployment] to see what it means to deploy without a bundler. [deployment]: ../reference/deployment.html [without-bundler]: ./without-a-bundler.html wasm-bindgen-0.2.87/guide/src/examples/todomvc.md000064400000000000000000000021631046102023000177760ustar 00000000000000# TODO MVC using wasm-bingen and web-sys [View full source code][code] or [view the compiled example online][online] [online]: https://rustwasm.github.io/wasm-bindgen/exbuild/todomvc/ [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/todomvc [element]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/todomvc/src/element.rs [scheduler]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/todomvc/src/scheduler.rs [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen) and [web-sys](https://rustwasm.github.io/wasm-bindgen/api/web_sys/) coded [TODO MVC](http://todomvc.com/) The code was rewritten from the [ES6 version](http://todomvc.com/examples/vanilla-es6/). The core differences are: - Having an [Element wrapper][element] that takes care of dyn and into refs in web-sys, - A [Scheduler][scheduler] that allows Controller and View to communicate to each other by emulating something similar to the JS event loop. ## Size The size of the project hasn't undergone much work to make it optimised yet. - ~96kb release build - ~76kb optimised with binaryen - ~28kb brotli compressed wasm-bindgen-0.2.87/guide/src/examples/wasm-audio-worklet.md000064400000000000000000000040741046102023000220610ustar 00000000000000# WASM audio worklet [View full source code][code] or [view the compiled example online][online] [online]: https://wasm-bindgen.netlify.app/exbuild/wasm-audio-worklet/ [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/wasm-audio-worklet This is an example of using threads inside specific worklets with WebAssembly, Rust, and `wasm-bindgen`, culminating in an oscillator demo. This demo should complement the [parallel-raytrace][parallel-raytrace] example by demonstrating an alternative approach using ES modules with on-the-fly module creation. [parallel-raytrace]: https://rustwasm.github.io/docs/wasm-bindgen/examples/raytrace.html ### Building the demo One of the major gotchas with threaded WebAssembly is that Rust does not ship a precompiled target (e.g. standard library) which has threading support enabled. This means that you'll need to recompile the standard library with the appropriate rustc flags, namely `-C target-feature=+atomics,+bulk-memory,+mutable-globals`. Note that this requires a nightly Rust toolchain. See the [more detailed instructions][build] of the parallel-raytrace example. [build]: https://rustwasm.github.io/docs/wasm-bindgen/examples/raytrace.html#building-the-demo ### Caveats This example shares most of its [caveats][caveats] with the parallel-raytrace example. However, it tries to encapsulate worklet creation in a Rust module, so the application developer does not need to maintain custom JS code. [caveats]: https://rustwasm.github.io/docs/wasm-bindgen/examples/raytrace.html#caveats ### Browser Requirements This demo should work in the latest Chrome and Safari versions at this time. Firefox [does not support][firefox-worklet-import] imports in worklet modules, which are difficult to avoid in this example, as `importScripts` is unavailable in worklets. Note that this example requires HTTP headers to be set like in [parallel-raytrace][headers]. [firefox-worklet-import]: https://bugzilla.mozilla.org/show_bug.cgi?id=1572644 [headers]: https://rustwasm.github.io/docs/wasm-bindgen/examples/raytrace.html#browser-requirements wasm-bindgen-0.2.87/guide/src/examples/wasm-in-wasm.md000064400000000000000000000007351046102023000206460ustar 00000000000000# js-sys: WebAssembly in WebAssembly [View full source code][code] or [view the compiled example online][online] [online]: https://rustwasm.github.io/wasm-bindgen/exbuild/wasm-in-wasm/ [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/wasm-in-wasm Using the `js-sys` crate we can get pretty meta and instantiate `WebAssembly` modules from inside `WebAssembly` modules! ## `src/lib.rs` ```rust {{#include ../../../examples/wasm-in-wasm/src/lib.rs}} ``` wasm-bindgen-0.2.87/guide/src/examples/wasm-in-web-worker.md000064400000000000000000000046031046102023000217610ustar 00000000000000# WASM in Web Worker [View full source code][code] [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/wasm-in-web-worker A simple example of parallel execution by spawning a web worker with `web_sys`, loading WASM code in the web worker and interacting between the main thread and the worker. ## Building & compatibility At the time of this writing, only Chrome supports modules in web workers, e.g. Firefox does not. To have compatibility across browsers, the whole example is set up without relying on ES modules as target. Therefore we have to build with `--target no-modules`. The full command can be found in `build.sh`. ## `Cargo.toml` The `Cargo.toml` enables features necessary to work with the DOM, log output to the JS console, creating a worker and reacting to message events. ```toml {{#include ../../../examples/wasm-in-web-worker/Cargo.toml}} ``` ## `src/lib.rs` Creates a struct `NumberEval` with methods to act as stateful object in the worker and function `startup` to be launched in the main thread. Also includes internal helper functions `setup_input_oninput_callback` to attach a `wasm_bindgen::Closure` as callback to the `oninput` event of the input field and `get_on_msg_callback` to create a `wasm_bindgen::Closure` which is triggered when the worker returns a message. ```rust {{#include ../../../examples/wasm-in-web-worker/src/lib.rs}} ``` ## `index.html` Includes the input element `#inputNumber` to type a number into and a HTML element `#resultField` were the result of the evaluation even/odd is written to. Since we require to build with `--target no-modules` to be able to load WASM code in in the worker across browsers, the `index.html` also includes loading both `wasm_in_web_worker.js` and `index.js`. ```html {{#include ../../../examples/wasm-in-web-worker/index.html}} ``` ## `index.js` Loads our WASM file asynchronously and calls the entry point `startup` of the main thread which will create a worker. ```js {{#include ../../../examples/wasm-in-web-worker/index.js}} ``` ## `worker.js` Loads our WASM file by first importing `wasm_bindgen` via `importScripts('./pkg/wasm_in_web_worker.js')` and then awaiting the Promise returned by `wasm_bindgen(...)`. Creates a new object to do the background calculation and bind a method of the object to the `onmessage` callback of the worker. ```js {{#include ../../../examples/wasm-in-web-worker/worker.js}} ``` wasm-bindgen-0.2.87/guide/src/examples/wasm2js.md000064400000000000000000000025401046102023000177100ustar 00000000000000# Converting WebAssembly to JS [View full source code][code] [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/wasm2js Not all browsers have support for `WebAssembly` at this time (although all major ones do). If you'd like to support older browsers, you probably want a method that doesn't involve keeping two codebases in sync! Thankfully there's a tool from [binaryen] called `wasm2js` to convert a wasm file to JS. This JS file, if successfully produced, is equivalent to the wasm file (albeit a little bit larger and slower), and can be loaded into practically any browser. This example is relatively simple (cribbing from the [`console.log` example](console-log.md)): ```rust {{#include ../../../examples/wasm2js/src/lib.rs}} ``` The real magic happens when you actually build the app. Just after `wasm-bindgen` we see here how we execute `wasm2js` in our build script: ```sh {{#include ../../../examples/wasm2js/build.sh}} ``` Note that the `wasm2js` tool is still pretty early days so there's likely to be a number of bugs to run into or work around. If any are encountered though please feel free to report them upstream! Also note that eventually this will ideally be automatically done by your bundler and no action would be needed from you to work in older browsers via `wasm2js`! [binaryen]: https://github.com/WebAssembly/binaryen wasm-bindgen-0.2.87/guide/src/examples/weather_report.md000064400000000000000000000012141046102023000213510ustar 00000000000000# web-sys: Weather report [View full source code][code] or [view the compiled example online][online] [online]: https://rustwasm.github.io/wasm-bindgen/exbuild/weather_report/ [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/weather_report This example makes an HTTP request to [OpenWeather API](https://openweathermap.org/), parses response in JSON and render UI from that JSON. It also shows the usage of `spawn_local` function for handling asynchronous tasks. Please add your api key in *get_response()* before running this application. ## `src/lib.rs` ```rust {{#include ../../../examples/weather_report/src/lib.rs}} ``` wasm-bindgen-0.2.87/guide/src/examples/web-audio.md000064400000000000000000000016411046102023000201770ustar 00000000000000# WebAudio [View full source code][code] or [view the compiled example online][online] [online]: https://rustwasm.github.io/wasm-bindgen/exbuild/webaudio/ [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/webaudio This example creates an [FM oscillator](https://en.wikipedia.org/wiki/Frequency_modulation_synthesis) using the [WebAudio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API) and `web-sys`. ## `Cargo.toml` The `Cargo.toml` enables the types needed to use the relevant bits of the WebAudio API. ```toml {{#include ../../../examples/webaudio/Cargo.toml}} ``` ## `src/lib.rs` The Rust code implements the FM oscillator. ```rust {{#include ../../../examples/webaudio/src/lib.rs}} ``` ## `index.js` A small bit of JavaScript glues the rust module to input widgets and translates events into calls into wasm code. ```js {{#include ../../../examples/webaudio/index.js}} ``` wasm-bindgen-0.2.87/guide/src/examples/webgl.md000064400000000000000000000013221046102023000174170ustar 00000000000000# WebGL Example [View full source code][code] or [view the compiled example online][online] [online]: https://rustwasm.github.io/wasm-bindgen/exbuild/webgl/ [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/webgl This example draws a triangle to the screen using the WebGL API. ## `Cargo.toml` The `Cargo.toml` enables features necessary to obtain and use a WebGL rendering context. ```toml {{#include ../../../examples/webgl/Cargo.toml}} ``` ## `src/lib.rs` This source file handles all of the necessary logic to obtain a rendering context, compile shaders, fill a buffer with vertex coordinates, and draw a triangle to the screen. ```rust {{#include ../../../examples/webgl/src/lib.rs}} ``` wasm-bindgen-0.2.87/guide/src/examples/webrtc_datachannel.md000064400000000000000000000013301046102023000221260ustar 00000000000000# WebRTC DataChannel Example [View full source code][code] or [view the compiled example online][online] [online]: https://rustwasm.github.io/wasm-bindgen/exbuild/webrtc_datachannel/ [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/webrtc_datachannel/ This example creates 2 peer connections and 2 data channels in single browser tab. Send ping/pong between `peer1.dc` and `peer2.dc`. ## `Cargo.toml` The `Cargo.toml` enables features necessary to use WebRTC DataChannel and its negotiation. ```toml {{#include ../../../examples/webrtc_datachannel/Cargo.toml}} ``` ## `src/lib.rs` The Rust code connects WebRTC data channel. ```rust {{#include ../../../examples/webrtc_datachannel/src/lib.rs}} ``` wasm-bindgen-0.2.87/guide/src/examples/websockets.md000064400000000000000000000017011046102023000204710ustar 00000000000000# WebSockets Example [View full source code][code] or [view the compiled example online][online] [online]: https://rustwasm.github.io/wasm-bindgen/exbuild/websockets/ [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/websockets/ This example connects to an echo server on `wss://echo.websocket.org`, sends a `ping` message, and receives the response. ## `Cargo.toml` The `Cargo.toml` enables features necessary to create a `WebSocket` object and to access events such as `MessageEvent` or `ErrorEvent`. ```toml {{#include ../../../examples/websockets/Cargo.toml}} ``` ## `src/lib.rs` This code shows the basic steps required to work with a `WebSocket`. At first it opens the connection, then subscribes to events `onmessage`, `onerror`, `onopen`. After the socket is opened it sends a `ping` message, receives an echoed response and prints it to the browser console. ```rust {{#include ../../../examples/websockets/src/lib.rs}} ``` wasm-bindgen-0.2.87/guide/src/examples/without-a-bundler.md000064400000000000000000000036671046102023000217070ustar 00000000000000# Without a Bundler [View full source code][code] [code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/without-a-bundler This example shows how the `--target web` flag can be used load code in a browser directly. For this deployment strategy bundlers like Webpack are not required. For more information on deployment see the [dedicated documentation][deployment]. First, you'll need to add `web-sys` to your Cargo.toml. ```toml [dependencies.web-sys] version = "0.3.4" features = [ 'Document', 'Element', 'HtmlElement', 'Node', 'Window', ] ``` Then, let's take a look at the code and see how when we're using `--target web` we're not actually losing any functionality! ```rust {{#include ../../../examples/without-a-bundler/src/lib.rs}} ``` Otherwise the rest of the deployment magic happens in `index.html`: ```html {{#include ../../../examples/without-a-bundler/index.html}} ``` And that's it! Be sure to read up on the [deployment options][deployment] to see what it means to deploy without a bundler. [deployment]: ../reference/deployment.html ## Using the older `--target no-modules` [View full source code][code-no-modules] [code-no-modules]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/without-a-bundler-no-modules The older version of using `wasm-bindgen` without a bundler is to use the `--target no-modules` flag to the `wasm-bindgen` CLI. While similar to the newer `--target web`, the `--target no-modules` flag has a few caveats: * It does not support [local JS snippets][snippets] * It does not generate an ES module * It does not support `--split-linked-modules` outside of a document, e.g. inside a worker With that in mind the main difference is how the wasm/JS code is loaded, and here's an example of loading the output of `wasm-pack` for the same module as above. ```html {{#include ../../../examples/without-a-bundler-no-modules/index.html}} ``` [snippets]: ../reference/js-snippets.html wasm-bindgen-0.2.87/guide/src/introduction.md000064400000000000000000000044611046102023000172310ustar 00000000000000# Introduction This book is about `wasm-bindgen`, a Rust library and CLI tool that facilitate high-level interactions between wasm modules and JavaScript. The `wasm-bindgen` tool and crate are only one part of the [Rust and WebAssembly ecosystem][rustwasm]. If you're not familiar already with `wasm-bindgen` it's recommended to start by reading the [Game of Life tutorial][gol]. If you're curious about `wasm-pack`, you can find that [documentation here][wasm-pack]. The `wasm-bindgen` tool is sort of half polyfill for features like the [host bindings proposal][host] and half features for empowering high-level interactions between JS and wasm-compiled code (currently mostly from Rust). More specifically this project allows JS/wasm to communicate with strings, JS objects, classes, etc, as opposed to purely integers and floats. Using `wasm-bindgen` for example you can define a JS class in Rust or take a string from JS or return one. The functionality is growing as well! Currently this tool is Rust-focused but the underlying foundation is language-independent, and it's hoping that over time as this tool stabilizes that it can be used for languages like C/C++! Notable features of this project includes: * Importing JS functionality in to Rust such as [DOM manipulation][dom-ex], [console logging][console-log], or [performance monitoring][perf-ex]. * Exporting Rust functionality to JS such as classes, functions, etc. * Working with rich types like strings, numbers, classes, closures, and objects rather than simply `u32` and floats. * Automatically generating TypeScript bindings for Rust code being consumed by JS. With the addition of [`wasm-pack`][wasm-pack] you can run the gamut from running Rust on the web locally, publishing it as part of a larger application, or even publishing Rust-compiled-to-WebAssembly on NPM! [host]: https://github.com/WebAssembly/host-bindings [dom-ex]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/dom [console-log]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/console_log [perf-ex]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/performance [hello-online]: https://webassembly.studio/?f=gzubao6tg3 [rustwasm]: https://rustwasm.github.io/ [gol]: https://rustwasm.github.io/docs/book/ [wasm-pack]: https://rustwasm.github.io/docs/wasm-pack/ wasm-bindgen-0.2.87/guide/src/reference/accessing-properties-of-untyped-js-values.md000064400000000000000000000041461046102023000265760ustar 00000000000000# Accessing Properties of Untyped JavaScript Values To read and write arbitrary properties from any untyped JavaScript value regardless if it is an `instanceof` some JavaScript class or not, use [the `js_sys::Reflect` APIs][js-sys-reflect]. These APIs are bindings to the [JavaScript builtin `Reflect` object][mdn-reflect] and its methods. You might also benefit from [using duck-typed interfaces](./working-with-duck-typed-interfaces.html) instead of working with untyped values. ## Reading Properties with `js_sys::Reflect::get` [API documentation for `js_sys::Reflect::get`.](https://docs.rs/js-sys/0.3.39/js_sys/Reflect/fn.get.html) A function that returns the value of a property. #### Rust Usage ```rust let value = js_sys::Reflect::get(&target, &property_key)?; ``` #### JavaScript Equivalent ```js let value = target[property_key]; ``` ## Writing Properties with `js_sys::Reflect::set` [API documentation for `js_sys::Reflect::set`.](https://docs.rs/js-sys/0.3.39/js_sys/Reflect/fn.set.html) A function that assigns a value to a property. Returns a boolean that is true if the update was successful. #### Rust Usage ```rust js_sys::Reflect::set(&target, &property_key, &value)?; ``` #### JavaScript Equivalent ```js target[property_key] = value; ``` ## Determining if a Property Exists with `js_sys::Reflect::has` [API documentation for `js_sys::Reflect::has`.](https://docs.rs/js-sys/0.3.39/js_sys/Reflect/fn.has.html) The JavaScript `in` operator as function. Returns a boolean indicating whether an own or inherited property exists on the target. #### Rust Usage ```rust if js_sys::Reflect::has(&target, &property_key)? { // ... } else { // ... } ``` #### JavaScript Equivalent ```js if (property_key in target) { // ... } else { // ... } ``` ## But wait — there's more! See [the `js_sys::Reflect` API documentation][js-sys-reflect] for the full listing of JavaScript value reflection and introspection capabilities. [js-sys-reflect]: https://docs.rs/js-sys/latest/js_sys/Reflect/index.html [mdn-reflect]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect wasm-bindgen-0.2.87/guide/src/reference/arbitrary-data-with-serde.md000064400000000000000000000120771046102023000234270ustar 00000000000000# Serializing and Deserializing Arbitrary Data Into and From `JsValue` with Serde It's possible to pass arbitrary data from Rust to JavaScript by serializing it with [Serde](https://github.com/serde-rs/serde). This can be done through the [`serde-wasm-bindgen`](https://docs.rs/serde-wasm-bindgen) crate. ## Add dependencies To use `serde-wasm-bindgen`, you first have to add it as a dependency in your `Cargo.toml`. You also need the `serde` crate, with the `derive` feature enabled, to allow your types to be serialized and deserialized with Serde. ```toml [dependencies] serde = { version = "1.0", features = ["derive"] } serde-wasm-bindgen = "0.4" ``` ## Derive the `Serialize` and `Deserialize` Traits Add `#[derive(Serialize, Deserialize)]` to your type. All of your type's members must also be supported by Serde, i.e. their types must also implement the `Serialize` and `Deserialize` traits. For example, let's say we'd like to pass this `struct` to JavaScript; doing so is not possible in `wasm-bindgen` normally due to the use of `HashMap`s, arrays, and nested `Vec`s. None of those types are supported for sending across the wasm ABI naively, but all of them implement Serde's `Serialize` and `Deserialize`. Note that we do not need to use the `#[wasm_bindgen]` macro. ```rust use serde::{Serialize, Deserialize}; #[derive(Serialize, Deserialize)] pub struct Example { pub field1: HashMap, pub field2: Vec>, pub field3: [f32; 4], } ``` ## Send it to JavaScript with `serde_wasm_bindgen::to_value` Here's a function that will pass an `Example` to JavaScript by serializing it to `JsValue`: ```rust #[wasm_bindgen] pub fn send_example_to_js() -> JsValue { let mut field1 = HashMap::new(); field1.insert(0, String::from("ex")); let example = Example { field1, field2: vec![vec![1., 2.], vec![3., 4.]], field3: [1., 2., 3., 4.] }; serde_wasm_bindgen::to_value(&example).unwrap() } ``` ## Receive it from JavaScript with `serde_wasm_bindgen::from_value` Here's a function that will receive a `JsValue` parameter from JavaScript and then deserialize an `Example` from it: ```rust #[wasm_bindgen] pub fn receive_example_from_js(val: JsValue) { let example: Example = serde_wasm_bindgen::from_value(val).unwrap(); ... } ``` ## JavaScript Usage In the `JsValue` that JavaScript gets, `field1` will be a `Map`, `field2` will be a JavaScript `Array` whose members are `Array`s of numbers, and `field3` will be an `Array` of numbers. ```js import { send_example_to_js, receive_example_from_js } from "example"; // Get the example object from wasm. let example = send_example_to_js(); // Add another "Vec" element to the end of the "Vec>" example.field2.push([5, 6]); // Send the example object back to wasm. receive_example_from_js(example); ``` ## An alternative approach - using JSON `serde-wasm-bindgen` works by directly manipulating JavaScript values. This requires a lot of calls back and forth between Rust and JavaScript, which can sometimes be slow. An alternative way of doing this is to serialize values to JSON, and then parse them on the other end. Browsers' JSON implementations are usually quite fast, and so this approach can outstrip `serde-wasm-bindgen`'s performance in some cases. But this approach supports only types that can be serialized as JSON, leaving out some important types that `serde-wasm-bindgen` supports such as `Map`, `Set`, and array buffers. That's not to say that using JSON is always faster, though - the JSON approach can be anywhere from 2x to 0.2x the speed of `serde-wasm-bindgen`, depending on the JS runtime and the values being passed. It also leads to larger code size than `serde-wasm-bindgen`. So, make sure to profile each for your own use cases. This approach is implemented in [`gloo_utils::format::JsValueSerdeExt`]: ```toml # Cargo.toml [dependencies] gloo-utils = { version = "0.1", features = ["serde"] } ``` ```rust use gloo_utils::format::JsValueSerdeExt; #[wasm_bindgen] pub fn send_example_to_js() -> JsValue { let mut field1 = HashMap::new(); field1.insert(0, String::from("ex")); let example = Example { field1, field2: vec![vec![1., 2.], vec![3., 4.]], field3: [1., 2., 3., 4.] }; JsValue::from_serde(&example).unwrap() } #[wasm_bindgen] pub fn receive_example_from_js(val: JsValue) { let example: Example = val.into_serde().unwrap(); ... } ``` [`gloo_utils::format::JsValueSerdeExt`]: https://docs.rs/gloo-utils/latest/gloo_utils/format/trait.JsValueSerdeExt.html ## History In previous versions of `wasm-bindgen`, `gloo-utils`'s JSON-based Serde support (`JsValue::from_serde` and `JsValue::into_serde`) was built into `wasm-bindgen` itself. However, this required a dependency on `serde_json`, which had a problem: with certain features of `serde_json` and other crates enabled, `serde_json` would end up with a circular dependency on `wasm-bindgen`, which is illegal in Rust and caused people's code to fail to compile. So, these methods were extracted out into `gloo-utils` with an extension trait and the originals were deprecated. wasm-bindgen-0.2.87/guide/src/reference/attributes/index.md000064400000000000000000000004551046102023000217420ustar 00000000000000# `#[wasm_bindgen]` Attributes The `#[wasm_bindgen]` macro supports a good amount of configuration for controlling precisely how exports are exported, how imports are imported, and what the generated JavaScript glue ends up looking like. This section is an exhaustive reference of the possibilities! wasm-bindgen-0.2.87/guide/src/reference/attributes/on-js-imports/catch.md000064400000000000000000000020641046102023000244340ustar 00000000000000# `catch` The `catch` attribute allows catching a JavaScript exception. This can be attached to any imported function or method, and the function must return a `Result` where the `Err` payload is a `JsValue`: ```rust #[wasm_bindgen] extern "C" { // `catch` on a standalone function. #[wasm_bindgen(catch)] fn foo() -> Result<(), JsValue>; // `catch` on a method. type Zoidberg; #[wasm_bindgen(catch, method)] fn woop_woop_woop(this: &Zoidberg) -> Result; } ``` If calling the imported function throws an exception, then `Err` will be returned with the exception that was raised. Otherwise, `Ok` is returned with the result of the function. > By default `wasm-bindgen` will take no action when wasm calls a JS function > which ends up throwing an exception. The wasm spec right now doesn't support > stack unwinding and as a result Rust code **will not execute destructors**. > This can unfortunately cause memory leaks in Rust right now, but as soon as > wasm implements catching exceptions we'll be sure to add support as well! wasm-bindgen-0.2.87/guide/src/reference/attributes/on-js-imports/constructor.md000064400000000000000000000011701046102023000257340ustar 00000000000000# `constructor` The `constructor` attribute is used to indicate that the function being bound should actually translate to calling the `new` operator in JavaScript. The final argument must be a type that's imported from JavaScript, and it's what will get used in the generated glue: ```rust #[wasm_bindgen] extern "C" { type Shoes; #[wasm_bindgen(constructor)] fn new() -> Shoes; } ``` This will attach a `new` static method to the `Shoes` type, and in JavaScript when this method is called, it will be equivalent to `new Shoes()`. ```rust // Become a cobbler; construct `new Shoes()` let shoes = Shoes::new(); ``` wasm-bindgen-0.2.87/guide/src/reference/attributes/on-js-imports/extends.md000064400000000000000000000020211046102023000250150ustar 00000000000000# `extends = Class` The `extends` attribute can be used to say that an imported type extends (in the JS class hierarchy sense) another type. This will generate `AsRef`, `AsMut`, and `From` impls for converting a type into another given that we statically know the inheritance hierarchy: ```rust #[wasm_bindgen] extern "C" { type Foo; #[wasm_bindgen(extends = Foo)] type Bar; } let x: &Bar = ...; let y: &Foo = x.as_ref(); // zero cost cast ``` The trait implementations generated for the above block are: ```rust impl From for Foo { ... } impl AsRef for Bar { ... } impl AsMut for Bar { ... } ``` The `extends = ...` attribute can be specified multiple times for longer inheritance chains, and `AsRef` and such impls will be generated for each of the types. ```rust #[wasm_bindgen] extern "C" { type Foo; #[wasm_bindgen(extends = Foo)] type Bar; #[wasm_bindgen(extends = Foo, extends = Bar)] type Baz; } let x: &Baz = ...; let y1: &Bar = x.as_ref(); let y2: &Foo = y1.as_ref(); ``` wasm-bindgen-0.2.87/guide/src/reference/attributes/on-js-imports/final.md000064400000000000000000000132431046102023000244440ustar 00000000000000# `final` The `final` attribute is the converse of the [`structural` attribute](structural.html). It configures how `wasm-bindgen` will generate JS imports to call the imported function. Notably a function imported by `final` never changes after it was imported, whereas a function imported by default (or with `structural`) is subject to runtime lookup rules such as walking the prototype chain of an object. Note that `final` is not suitable for accessing data descriptor properties of JS objects; to accomplish this, use the `structural` attribute. [host-bindings]: https://github.com/WebAssembly/host-bindings [reference-types]: https://github.com/WebAssembly/reference-types The `final` attribute is intended to be purely related to performance. It ideally has no user-visible effect, and `structural` imports (the default) should be able to transparently switch to `final` eventually. The eventual performance aspect is that with the [host bindings proposal][host-bindings] then `wasm-bindgen` will need to generate far fewer JS function shims to import than it does today. For example, consider this import today: ```rust #[wasm_bindgen] extern "C" { type Foo; #[wasm_bindgen(method)] fn bar(this: &Foo, argument: &str) -> JsValue; } ``` **Without the `final` attribute** the generated JS looks like this: ```js // without `final` export function __wbg_bar_a81456386e6b526f(arg0, arg1, arg2) { let varg1 = getStringFromWasm(arg1, arg2); return addHeapObject(getObject(arg0).bar(varg1)); } ``` We can see here that this JS function shim is required, but it's all relatively self-contained. It does, however, execute the `bar` method in a duck-type-y fashion in the sense that it never validates `getObject(arg0)` is of type `Foo` to actually call the `Foo.prototype.bar` method. If we instead, however, write this: ```rust #[wasm_bindgen] extern "C" { type Foo; #[wasm_bindgen(method, final)] // note the change here fn bar(this: &Foo, argument: &str) -> JsValue; } ``` it generates this JS glue (roughly): ```js const __wbg_bar_target = Foo.prototype.bar; export function __wbg_bar_a81456386e6b526f(arg0, arg1, arg2) { let varg1 = getStringFromWasm(arg1, arg2); return addHeapObject(__wbg_bar_target.call(getObject(arg0), varg1)); } ``` The difference here is pretty subtle, but we can see how the function being called is hoisted out of the generated shim and is bound to always be `Foo.prototype.bar`. This then uses the `Function.call` method to invoke that function with `getObject(arg0)` as the receiver. But wait, there's still a JS function shim here even with `final`! That's true, and this is simply a fact of future WebAssembly proposals not being implemented yet. The semantics, though, match the future [host bindings proposal][host-bindings] because the method being called is determined exactly once, and it's located on the prototype chain rather than being resolved at runtime when the function is called. ## Interaction with future proposals If you're curious to see how our JS function shim will be eliminated entirely, let's take a look at the generated bindings. We're starting off with this: ```js const __wbg_bar_target = Foo.prototype.bar; export function __wbg_bar_a81456386e6b526f(arg0, arg1, arg2) { let varg1 = getStringFromWasm(arg1, arg2); return addHeapObject(__wbg_bar_target.call(getObject(arg0), varg1)); } ``` ... and once the [reference types proposal][reference-types] is implemented then we won't need some of these pesky functions. That'll transform our generated JS shim to look like: ```js const __wbg_bar_target = Foo.prototype.bar; export function __wbg_bar_a81456386e6b526f(arg0, arg1, arg2) { let varg1 = getStringFromWasm(arg1, arg2); return __wbg_bar_target.call(arg0, varg1); } ``` Getting better! Next up we need the host bindings proposal. Note that the proposal is undergoing some changes right now so it's tough to link to reference documentation, but it suffices to say that it'll empower us with at least two different features. First, host bindings promises to provide the concept of "argument conversions". The `arg1` and `arg2` values here are actually a pointer and a length to a utf-8 encoded string, and with host bindings we'll be able to annotate that this import should take those two arguments and convert them to a JS string (that is, the *host* should do this, the WebAssembly engine). Using that feature we can further trim this down to: ```js const __wbg_bar_target = Foo.prototype.bar; export function __wbg_bar_a81456386e6b526f(arg0, varg1) { return __wbg_bar_target.call(arg0, varg1); } ``` And finally, the second promise of the host bindings proposal is that we can flag a function call to indicate the first argument is the `this` binding of the function call. Today the `this` value of all called imported functions is `undefined`, and this flag (configured with host bindings) will indicate the first argument here is actually the `this`. With that in mind we can further transform this to: ```js export const __wbg_bar_a81456386e6b526f = Foo.prototype.bar; ``` and voila! We, with [reference types][reference-types] and [host bindings][host-bindings], now have no JS function shim at all necessary to call the imported function. Additionally future wasm proposals to the ES module system may also mean that don't even need the `export const ...` here too. It's also worth pointing out that with all these wasm proposals implemented the default way to import the `bar` function (aka `structural`) would generate a JS function shim that looks like: ```js export function __wbg_bar_a81456386e6b526f(varg1) { return this.bar(varg1); } ``` where this import is still subject to runtime prototype chain lookups and such. wasm-bindgen-0.2.87/guide/src/reference/attributes/on-js-imports/getter-and-setter.md000064400000000000000000000045501046102023000267120ustar 00000000000000# `getter` and `setter` These two attributes can be combined with `method` to indicate that this is a getter or setter method. A `getter`-tagged function by default accesses the JavaScript property with the same name as the getter function. A `setter`'s function name is currently required to start with `set_` and the property it accesses is the suffix after `set\_`. Consider the following JavaScript class that has a getter and setter for the `white_russians` property: ```js class TheDude { get white_russians() { ... } set white_russians(val) { ... } } ``` We would import this with the following `#[wasm_bindgen]` attributes: ```rust #[wasm_bindgen] extern "C" { type TheDude; #[wasm_bindgen(method, getter)] fn white_russians(this: &TheDude) -> u32; #[wasm_bindgen(method, setter)] fn set_white_russians(this: &TheDude, val: u32); } ``` Here we're importing the `TheDude` type and defining the ability to access each object's `white_russians` property. The first function here is a getter and will be available in Rust as `the_dude.white_russians()`, and the latter is the setter which is accessible as `the_dude.set_white_russians(2)`. Note that both functions have a `this` argument as they're tagged with `method`. Finally, you can also pass an argument to the `getter` and `setter` properties to configure what property is accessed. When the property is explicitly specified then there is no restriction on the method name. For example the below is equivalent to the above: ```rust #[wasm_bindgen] extern "C" { type TheDude; #[wasm_bindgen(method, getter = white_russians)] fn my_custom_getter_name(this: &TheDude) -> u32; #[wasm_bindgen(method, setter = white_russians)] fn my_custom_setter_name(this: &TheDude, val: u32); } ``` Heads up! `getter` and `setter` functions are found on the constructor's prototype chain once at load time, cached, and then the cached accessor is invoked on each access. If you need to dynamically walk the prototype chain on every access, add the `structural` attribute! ```js // This is the default function Rust will invoke on `the_dude.white_russians()`: const white_russians = Object.getOwnPropertyDescriptor( TheDude.prototype, "white_russians" ).get; // This is what you get by adding `structural`: const white_russians = function(the_dude) { return the_dude.white_russians; }; ``` wasm-bindgen-0.2.87/guide/src/reference/attributes/on-js-imports/index.md000064400000000000000000000003231046102023000244550ustar 00000000000000# `#[wasm_bindgen]` on JavaScript Imports This section enumerates the attributes available for customizing bindings for JavaScript functions and classes imported into Rust within an `extern "C" { ... }` block. wasm-bindgen-0.2.87/guide/src/reference/attributes/on-js-imports/indexing-getter-setter-deleter.md000064400000000000000000000044441046102023000314010ustar 00000000000000# `indexing_getter`, `indexing_setter`, and `indexing_deleter` These three attributes indicate that a method is an dynamically intercepted getter, setter, or deleter on the receiver object itself, rather than a direct access of the receiver's properties. It is equivalent calling the Proxy handler for the `obj[prop]` operation with some dynamic `prop` variable in JavaScript, rather than a normal static property access like `obj.prop` on a normal JavaScript `Object`. This is useful for binding to `Proxy`s and some builtin DOM types that dynamically intercept property accesses. * `indexing_getter` corresponds to `obj[prop]` operation in JavaScript. The function annotated must have a `this` receiver parameter, a single parameter that is used for indexing into the receiver (`prop`), and a return type. * `indexing_setter` corresponds to the `obj[prop] = val` operation in JavaScript. The function annotated must have a `this` receiver parameter, a parameter for indexing into the receiver (`prop`), and a value parameter (`val`). * `indexing_deleter` corresponds to `delete obj[prop]` operation in JavaScript. The function annotated must have a `this` receiver and a single parameter for indexing into the receiver (`prop`). These must always be used in conjunction with the `structural` and `method` flags. For example, consider this JavaScript snippet that uses `Proxy`: ```js const foo = new Proxy({}, { get(obj, prop) { return prop in obj ? obj[prop] : prop.length; }, set(obj, prop, value) { obj[prop] = value; }, deleteProperty(obj, prop) { delete obj[prop]; }, }); foo.ten; // 3 foo.ten = 10; foo.ten; // 10 delete foo.ten; foo.ten; // 3 ``` To bind that in `wasm-bindgen` in Rust, we would use the `indexing_*` attributes on methods: ```rust #[wasm_bindgen] extern "C" { type Foo; static foo: Foo; #[wasm_bindgen(method, structural, indexing_getter)] fn get(this: &Foo, prop: &str) -> u32; #[wasm_bindgen(method, structural, indexing_setter)] fn set(this: &Foo, prop: &str, val: u32); #[wasm_bindgen(method, structural, indexing_deleter)] fn delete(this: &Foo, prop: &str); } assert_eq!(foo.get("ten"), 3); foo.set("ten", 10); assert_eq!(foo.get("ten"), 10); foo.delete("ten"); assert_eq!(foo.get("ten"), 3); ``` wasm-bindgen-0.2.87/guide/src/reference/attributes/on-js-imports/js_class.md000064400000000000000000000012421046102023000251500ustar 00000000000000# `js_class = "Blah"` The `js_class` attribute can be used in conjunction with the `method` attribute to bind methods of imported JavaScript classes that have been renamed on the Rust side. ```rust #[wasm_bindgen] extern "C" { // We don't want to import JS strings as `String`, since Rust already has a // `String` type in its prelude, so rename it as `JsString`. #[wasm_bindgen(js_name = String)] type JsString; // This is a method on the JavaScript "String" class, so specify that with // the `js_class` attribute. #[wasm_bindgen(method, js_class = "String", js_name = charAt)] fn char_at(this: &JsString, index: u32) -> JsString; } ``` wasm-bindgen-0.2.87/guide/src/reference/attributes/on-js-imports/js_name.md000064400000000000000000000043771046102023000247770ustar 00000000000000# `js_name = blah` The `js_name` attribute can be used to bind to a different function in JavaScript than the identifier that's defined in Rust. Most often, this is used to convert a camel-cased JavaScript identifier into a snake-cased Rust identifier: ```rust #[wasm_bindgen] extern "C" { #[wasm_bindgen(js_name = jsOftenUsesCamelCase)] fn js_often_uses_camel_case() -> u32; } ``` Sometimes, it is used to bind to JavaScript identifiers that are not valid Rust identifiers, in which case `js_name = "some string"` is used instead of `js_name = ident`: ```rust #[wasm_bindgen] extern "C" { #[wasm_bindgen(js_name = "$$$")] fn cash_money() -> u32; } ``` However, you can also use `js_name` to define multiple signatures for polymorphic JavaScript functions: ```rust #[wasm_bindgen] extern "C" { #[wasm_bindgen(js_namespace = console, js_name = log)] fn console_log_str(s: &str); #[wasm_bindgen(js_namespace = console, js_name = log)] fn console_log_u32(n: u32); #[wasm_bindgen(js_namespace = console, js_name = log)] fn console_log_many(a: u32, b: &JsValue); } ``` All of these functions will call `console.log` in JavaScript, but each identifier will have only one signature in Rust. Note that if you use `js_name` when importing a type you'll also need to use the [`js_class` attribute][jsclass] when defining methods on the type: ```rust #[wasm_bindgen] extern "C" { #[wasm_bindgen(js_name = String)] type JsString; #[wasm_bindgen(method, getter, js_class = "String")] pub fn length(this: &JsString) -> u32; } ``` The `js_name` attribute can also be used in situations where a JavaScript module uses `export default`. In this case, setting the `js_name` attribute to "default" on the `type` declaration, and the [`js_class` attribute][jsclass] to "default" on any methods on the exported object will generate the correct imports. For example, a module that would be imported directly in JavaScript: ```javascript import Foo from "bar"; let f = new Foo(); ``` Could be accessed using this definition in Rust: ```rust #[wasm_bindgen(module = "bar")] extern "C" { #[wasm_bindgen(js_name = default)] type Foo; #[wasm_bindgen(constructor, js_class = default)] pub fn new() -> Foo; } ``` [jsclass]: js_class.html wasm-bindgen-0.2.87/guide/src/reference/attributes/on-js-imports/js_namespace.md000064400000000000000000000034661046102023000260110ustar 00000000000000# `js_namespace = blah` This attribute indicates that the JavaScript type is accessed through the given namespace. For example, the `WebAssembly.Module` APIs are all accessed through the `WebAssembly` namespace. `js_namespace` can be applied to any import (function or type) and whenever the generated JavaScript attempts to reference a name (like a class or function name) it'll be accessed through this namespace. ```rust #[wasm_bindgen] extern "C" { #[wasm_bindgen(js_namespace = console)] fn log(s: &str); type Foo; #[wasm_bindgen(constructor, js_namespace = Bar)] fn new() -> Foo; } log("hello, console!"); Foo::new(); ``` This is an example of how to bind namespaced items in Rust. The `log` and `Foo::new` functions will be available in the Rust module and will be invoked as `console.log` and `new Bar.Foo` in JavaScript. It is also possible to access the JavaScript object under the nested namespace. `js_namespace` also accepts the array of the string to specify the namespace. ```rust #[wasm_bindgen] extern "C" { #[wasm_bindgen(js_namespace = ["window", "document"])] fn write(s: &str); } write("hello, document!"); ``` This example shows how to bind `window.document.write` in Rust. If all items in the `extern "C" { … }` block have the same `js_namespace = …`: ```rust #[wasm_bindgen] extern "C" { #[wasm_bindgen(js_namespace = Math)] fn random() -> f64; #[wasm_bindgen(js_namespace = Math)] fn log(a: f64) -> f64; // ... } ``` Then that macro argument can also be moved to the outer block: ```rust #[wasm_bindgen(js_namespace = Math)] extern "C" { #[wasm_bindgen] fn random() -> f64; #[wasm_bindgen] fn log(a: f64) -> f64; // ... } ``` `js_namespace = …` on an individual item takes precedence over the outer block's `js_namespace = …`. wasm-bindgen-0.2.87/guide/src/reference/attributes/on-js-imports/method.md000064400000000000000000000010611046102023000246260ustar 00000000000000# `method` The `method` attribute allows you to describe methods of imported JavaScript objects. It is applied on a function that has `this` as its first parameter, which is a shared reference to an imported JavaScript type. ```rust #[wasm_bindgen] extern "C" { type Set; #[wasm_bindgen(method)] fn has(this: &Set, element: &JsValue) -> bool; } ``` This generates a `has` method on `Set` in Rust, which invokes the `Set.prototype.has` method in JavaScript. ```rust let set: Set = ...; let elem: JsValue = ...; if set.has(&elem) { ... } ``` wasm-bindgen-0.2.87/guide/src/reference/attributes/on-js-imports/module.md000064400000000000000000000014731046102023000246420ustar 00000000000000# `module = "blah"` The `module` attributes configures the module from which items are imported. For example, ```rust #[wasm_bindgen(module = "wu/tang/clan")] extern "C" { type ThirtySixChambers; } ``` generates JavaScript import glue like: ```js import { ThirtySixChambers } from "wu/tang/clan"; ``` If a `module` attribute is not present, then the global scope is used instead. For example, ```rust #[wasm_bindgen] extern "C" { fn illmatic() -> u32; } ``` generates JavaScript import glue like: ```js let illmatic = this.illmatic; ``` Note that if the string specified with `module` starts with `./`, `../`, or `/` then it's interpreted as a path to a [local JS snippet](../../js-snippets.html). If this doesn't work for your use case you might be interested in the [`raw_module` attribute](raw_module.html) wasm-bindgen-0.2.87/guide/src/reference/attributes/on-js-imports/no_deref.md000064400000000000000000000010321046102023000251250ustar 00000000000000# `no_deref` The `no_deref` attribute can be used to say that no `Deref` impl should be generated for an imported type. If this attribute is not present, a `Deref` impl will be generated with a `Target` of the type's first `extends` attribute, or `Target = JsValue` if there are no `extends` attributes. ```rust #[wasm_bindgen] extern "C" { type Foo; #[wasm_bindgen(method)] fn baz(this: &Foo) #[wasm_bindgen(extends = Foo, no_deref)] type Bar; } fn do_stuff(bar: &Bar) { bar.baz() // Does not compile } ``` wasm-bindgen-0.2.87/guide/src/reference/attributes/on-js-imports/raw_module.md000064400000000000000000000013361046102023000255110ustar 00000000000000# `raw_module = "blah"` This attribute performs exactly the same purpose as the [`module` attribute](module.html) on JS imports, but it does not attempt to interpret paths starting with `./`, `../`, or `/` as JS snippets. For example: ```rust #[wasm_bindgen(raw_module = "./some/js/file.js")] extern "C" { fn the_function(); } ``` Note that if you use this attribute with a relative or absolute path, it's likely up to the final bundler or project to assign meaning to that path. This typically means that the JS file or module will be resolved relative to the final location of the wasm file itself. That means that `raw_module` is likely unsuitable for libraries on crates.io, but may be usable within end-user applications. wasm-bindgen-0.2.87/guide/src/reference/attributes/on-js-imports/static_method_of.md000064400000000000000000000015731046102023000266710ustar 00000000000000# `static_method_of = Blah` The `static_method_of` attribute allows one to specify that an imported function is a static method of the given imported JavaScript class. For example, to bind to JavaScript's `Date.now()` static method, one would use this attribute: ```rust #[wasm_bindgen] extern "C" { type Date; #[wasm_bindgen(static_method_of = Date)] pub fn now() -> f64; } ``` The `now` function becomes a static method of the imported type in the Rust bindings as well: ```rust let instant = Date::now(); ``` This is similar to the `js_namespace` attribute, but the usage from within Rust is different since the method also becomes a static method of the imported type. Additionally this attribute also specifies that the `this` parameter when invoking the method is expected to be the JS class, e.g. always invoked as `Date.now()` instead of `const x = Date.now; x()`. wasm-bindgen-0.2.87/guide/src/reference/attributes/on-js-imports/structural.md000064400000000000000000000030611046102023000255600ustar 00000000000000# `structural` > **Note**: As of [RFC 5] this attribute is the default for all imported > functions. This attribute is largely ignored today and is only retained for > backwards compatibility and learning purposes. > > The inverse of this attribute, [the `final` > attribute](final.html) is more functionally interesting than > `structural` (as `structural` is simply the default) [RFC 5]: https://rustwasm.github.io/rfcs/005-structural-and-deref.html The `structural` flag can be added to `method` annotations, indicating that the method being accessed (or property with getters/setters) should be accessed in a structural, duck-type-y fashion. Rather than walking the constructor's prototype chain once at load time and caching the property result, the prototype chain is dynamically walked on every access. ```rust #[wasm_bindgen] extern "C" { type Duck; #[wasm_bindgen(method, structural)] fn quack(this: &Duck); #[wasm_bindgen(method, getter, structural)] fn is_swimming(this: &Duck) -> bool; } ``` The constructor for the type here, `Duck`, is not required to exist in JavaScript (it's not referenced). Instead `wasm-bindgen` will generate shims that will access the passed in JavaScript value's `quack` method or its `is_swimming` property. ```js // Without `structural`, get the method directly off the prototype at load time: const Duck_prototype_quack = Duck.prototype.quack; function quack(duck) { Duck_prototype_quack.call(duck); } // With `structural`, walk the prototype chain on every access: function quack(duck) { duck.quack(); } ``` wasm-bindgen-0.2.87/guide/src/reference/attributes/on-js-imports/typescript_type.md000064400000000000000000000005701046102023000266210ustar 00000000000000# `typescript_type = "Blah"` The `typescript_type` attribute is used to specify the TypeScript type for an imported type. This type will be used in the generated `.d.ts`. Right now only identifiers are supported, but eventually we'd like to support all TypeScript types. ```rust #[wasm_bindgen] extern "C" { #[wasm_bindgen(typescript_type = "Foo")] type Foo; } ``` wasm-bindgen-0.2.87/guide/src/reference/attributes/on-js-imports/variadic.md000064400000000000000000000025111046102023000251310ustar 00000000000000# Variadic Parameters In javascript, both the types of function arguments, and the number of function arguments are dynamic. For example ```js function sum(...rest) { let i; // the old way let old_way = 0; for (i=0; i i32; } ``` when we call this function, the last argument will be expanded as the javascript expects. To export a rust function to javascript with a variadic argument, we will use the same bindgen variadic attribute and assume that the last argument will be the variadic array. For example the following rust function: ```rust #[wasm_bindgen(variadic)] pub fn variadic_function(arr: &JsValue) -> JsValue { arr.into() } ``` will generate the following TS interface ```ts export function variadic_function(...arr: any): any; ``` wasm-bindgen-0.2.87/guide/src/reference/attributes/on-js-imports/vendor_prefix.md000064400000000000000000000014701046102023000262240ustar 00000000000000# Vendor-prefixed APIs On the web new APIs often have vendor prefixes while they're in an experimental state. For example the `AudioContext` API is known as `webkitAudioContext` in Safari at the time of this writing. The `vendor_prefix` attribute indicates these alternative names, which are used if the normal name isn't defined. For example to use `AudioContext` you might do: ```rust #[wasm_bindgen] extern "C" { #[wasm_bindgen(vendor_prefix = webkit)] type AudioContext; // methods on `AudioContext` ... } ``` Whenever `AudioContext` is used it'll use `AudioContext` if the global namespace defines it or alternatively it'll fall back to `webkitAudioContext`. Note that `vendor_prefix` cannot be used with `module = "..."` or `js_namespace = ...`, so it's basically limited to web-platform APIs today. wasm-bindgen-0.2.87/guide/src/reference/attributes/on-rust-exports/constructor.md000064400000000000000000000011261046102023000263250ustar 00000000000000# `constructor` When attached to a Rust "constructor" it will make the generated JavaScript bindings callable as `new Foo()`. For example, consider this exported Rust type and `constructor` annotation: ```rust #[wasm_bindgen] pub struct Foo { contents: u32, } #[wasm_bindgen] impl Foo { #[wasm_bindgen(constructor)] pub fn new() -> Foo { Foo { contents: 0 } } pub fn get_contents(&self) -> u32 { self.contents } } ``` This can be used in JavaScript as: ```js import { Foo } from './my_module'; const f = new Foo(); console.log(f.get_contents()); ``` wasm-bindgen-0.2.87/guide/src/reference/attributes/on-rust-exports/getter-and-setter.md000064400000000000000000000027731046102023000273070ustar 00000000000000# `getter` and `setter` The `getter` and `setter` attributes can be used in Rust `impl` blocks to define properties in JS that act like getters and setters of a field. For example: ```rust #[wasm_bindgen] pub struct Baz { field: i32, } #[wasm_bindgen] impl Baz { #[wasm_bindgen(constructor)] pub fn new(field: i32) -> Baz { Baz { field } } #[wasm_bindgen(getter)] pub fn field(&self) -> i32 { self.field } #[wasm_bindgen(setter)] pub fn set_field(&mut self, field: i32) { self.field = field; } } ``` Can be combined in `JavaScript` like in this snippet: ```js const obj = new Baz(3); assert.equal(obj.field, 3); obj.field = 4; assert.equal(obj.field, 4); ``` You can also configure the name of the property that is exported in JS like so: ```rust #[wasm_bindgen] impl Baz { #[wasm_bindgen(getter = anotherName)] pub fn field(&self) -> i32 { self.field } #[wasm_bindgen(setter = anotherName)] pub fn set_field(&mut self, field: i32) { self.field = field; } } ``` Getters are expected to take no arguments other than `&self` and return the field's type. Setters are expected to take one argument other than `&mut self` (or `&self`) and return no values. The name for a `getter` is by default inferred from the function name it's attached to. The default name for a `setter` is the function's name minus the `set_` prefix, and if `set_` isn't a prefix of the function it's an error to not provide the name explicitly. wasm-bindgen-0.2.87/guide/src/reference/attributes/on-rust-exports/getter_with_clone.md000064400000000000000000000007661046102023000274560ustar 00000000000000# `getter_with_clone` By default, Rust exports exposed to JavaScript will generate getters that require fields to implement `Copy`. The `getter_with_clone` attribute can be used to generate getters that require `Clone` instead. This attribute can be applied per struct or per field. For example: ```rust #[wasm_bindgen] pub struct Foo { #[wasm_bindgen(getter_with_clone)] pub bar: String, } #[wasm_bindgen(getter_with_clone)] pub struct Foo { pub bar: String, pub baz: String, } ``` wasm-bindgen-0.2.87/guide/src/reference/attributes/on-rust-exports/index.md000064400000000000000000000002501046102023000250440ustar 00000000000000# `#[wasm_bindgen]` on Rust Exports This section enumerates the attributes available for customizing bindings for Rust functions and `struct`s exported to JavaScript. wasm-bindgen-0.2.87/guide/src/reference/attributes/on-rust-exports/inspectable.md000064400000000000000000000034661046102023000262420ustar 00000000000000# `inspectable` By default, structs exported from Rust become JavaScript classes with a single `ptr` property. All other properties are implemented as getters, which are not displayed when calling `toJSON`. The `inspectable` attribute can be used on Rust structs to provide a `toJSON` and `toString` implementation that display all readable fields. For example: ```rust #[wasm_bindgen(inspectable)] pub struct Baz { pub field: i32, private: i32, } #[wasm_bindgen] impl Baz { #[wasm_bindgen(constructor)] pub fn new(field: i32) -> Baz { Baz { field, private: 13 } } } ``` Provides the following behavior as in this JavaScript snippet: ```js const obj = new Baz(3); assert.deepStrictEqual(obj.toJSON(), { field: 3 }); obj.field = 4; assert.strictEqual(obj.toString(), '{"field":4}'); ``` One or both of these implementations can be overridden as desired. Note that the generated `toString` calls `toJSON` internally, so overriding `toJSON` will affect its output as a side effect. ```rust #[wasm_bindgen] impl Baz { #[wasm_bindgen(js_name = toJSON)] pub fn to_json(&self) -> i32 { self.field } #[wasm_bindgen(js_name = toString)] pub fn to_string(&self) -> String { format!("Baz: {}", self.field) } } ``` Note that the output of `console.log` will remain unchanged and display only the `ptr` field in browsers. It is recommended to call `toJSON` or `JSON.stringify` in these situations to aid with logging or debugging. Node.js does not suffer from this limitation, see the section below. ## `inspectable` Classes in Node.js When the `nodejs` target is used, an additional `[util.inspect.custom]` implementation is provided which calls `toJSON` internally. This method is used for `console.log` and similar functions to display all readable fields of the Rust struct. wasm-bindgen-0.2.87/guide/src/reference/attributes/on-rust-exports/js_class.md000064400000000000000000000012301046102023000255350ustar 00000000000000# `js_class = Blah` The `js_class` attribute is used to indicate that all the methods inside an `impl` block should be attached to the specified JS class instead of inferring it from the self type in the `impl` block. The `js_class` attribute is most frequently paired with [the `js_name` attribute](js_name.html) on structs: ```rust #[wasm_bindgen(js_name = Foo)] pub struct JsFoo { /* ... */ } #[wasm_bindgen(js_class = Foo)] impl JsFoo { #[wasm_bindgen(constructor)] pub fn new() -> JsFoo { /* ... */ } pub fn foo(&self) { /* ... */ } } ``` which is accessed like: ```rust import { Foo } from './my_module'; const x = new Foo(); x.foo(); ``` wasm-bindgen-0.2.87/guide/src/reference/attributes/on-rust-exports/js_name.md000064400000000000000000000017571046102023000253660ustar 00000000000000# `js_name = Blah` The `js_name` attribute can be used to export a different name in JS than what something is named in Rust. It can be applied to both exported Rust functions and types. For example, this is often used to convert between Rust's snake-cased identifiers into JavaScript's camel-cased identifiers: ```rust #[wasm_bindgen(js_name = doTheThing)] pub fn do_the_thing() -> u32 { 42 } ``` This can be used in JavaScript as: ```js import { doTheThing } from './my_module'; const x = doTheThing(); console.log(x); ``` Like imports, `js_name` can also be used to rename types exported to JS: ```rust #[wasm_bindgen(js_name = Foo)] pub struct JsFoo { // .. } ``` to be accessed like: ```js import { Foo } from './my_module'; // ... ``` Note that attaching methods to the JS class `Foo` should be done via the [`js_class` attribute](js_class.html): ```rust #[wasm_bindgen(js_name = Foo)] pub struct JsFoo { /* ... */ } #[wasm_bindgen(js_class = Foo)] impl JsFoo { // ... } ``` wasm-bindgen-0.2.87/guide/src/reference/attributes/on-rust-exports/main.md000064400000000000000000000017521046102023000246710ustar 00000000000000# `main` When attached to the `main` function this attribute will adjust it to properly throw errors if they can be. ```rust #[wasm_bindgen(main)] fn main() -> Result<(), JsValue> { Err(JsValue::from("this error message will be thrown")) } ``` The attribute also allows using `async fn main()` in Cargo binaries. ```rust #[wasm_bindgen(main)] async fn main() { // ... future.await; } ``` This attribute is only intended to be used on the `main` function of binaries or examples. Unlike `#[wasm_bindgen(start)]`, it will not cause an arbitrary function to be executed on start in a library. The return type support is modeled after [`Termination`]. `()` and `Infallible` are supported, but [`Termination`] itself is not. In order, wasm-bindgen will first detect a `Result<(), impl Into>` and will throw proper `JsValue`s, `Result<(), impl Debug>` will convert an error to a string and throw that. [`Termination`]: https://doc.rust-lang.org/std/process/trait.Termination.html wasm-bindgen-0.2.87/guide/src/reference/attributes/on-rust-exports/readonly.md000064400000000000000000000014371046102023000255620ustar 00000000000000# `readonly` When attached to a `pub` struct field this indicates that it's read-only from JavaScript, and a setter will not be generated and exported to JavaScript. ```rust #[wasm_bindgen] pub fn make_foo() -> Foo { Foo { first: 10, second: 20, } } #[wasm_bindgen] pub struct Foo { pub first: u32, #[wasm_bindgen(readonly)] pub second: u32, } ``` Here the `first` field will be both readable and writable from JS, but the `second` field will be a `readonly` field in JS where the setter isn't implemented and attempting to set it will throw an exception. ```js import { make_foo } from "./my_module"; const foo = make_foo(); // Can both get and set `first`. foo.first = 99; console.log(foo.first); // Can only get `second`. console.log(foo.second); ``` wasm-bindgen-0.2.87/guide/src/reference/attributes/on-rust-exports/skip.md000064400000000000000000000016651046102023000247160ustar 00000000000000# `skip` When attached to a `pub` struct field this indicates that field will not be exposed to JavaScript, and neither getter nor setter will be generated in ES6 class. ```rust use wasm_bindgen::prelude::*; #[wasm_bindgen] pub struct Foo { pub bar: u32, #[wasm_bindgen(skip)] pub baz: u32, } #[wasm_bindgen] impl Foo { pub fn new() -> Self { Foo { bar: 1, baz: 2 } } } ``` Here the `bar` field will be both readable and writable from JS, but the `baz` field will be `undefined` in JS. ```js import('./pkg/').then(rust => { let foo = rust.Foo.new(); // bar is accessible by getter console.log(foo.bar); // field marked with `skip` is undefined console.log(foo.baz); // you can shadow it foo.baz = 45; // so accessing by getter will return `45` // but it won't affect real value in rust memory console.log(foo.baz); }); ``` wasm-bindgen-0.2.87/guide/src/reference/attributes/on-rust-exports/skip_jsdoc.md000064400000000000000000000021371046102023000260730ustar 00000000000000# `skip_jsdoc` When attached to a function or a method, prevents `wasm-bindgen` from auto-generating JSDoc-style doc comments. By default, `wasm-bindgen` adds `@param` and `@returns` annotations to doc comments in the generated JS files. A `skip_jsdoc` annotation prevents this, allowing you to supply your own doc comments. The following rust uses `skip_jsdoc` to omit one of the auto-generated doc comments. ```rust use wasm_bindgen::prelude::*; /// Autogenerated docs. #[wasm_bindgen] pub fn foo(arg: u32) -> u32 { arg + 1 } /// Manually written docs. /// /// @param {number} arg - A descriptive description. /// @returns {number} Something a bit bigger. #[wasm_bindgen(skip_jsdoc)] pub fn bar(arg: u32) -> u32 { arg + 2 } ``` The `wasm-bindgen`-generated JS interface of the above code will look something like this: ```js /** * Autogenerated docs. * * @param {number} arg * @returns {number} */ export function foo(arg) { /* ... */ } /** * Manually written docs. * * @param {number} arg - A descriptive description. * @returns {number} Something a bit bigger. */ export function bar(arg) { /* ... */ } ``` wasm-bindgen-0.2.87/guide/src/reference/attributes/on-rust-exports/skip_typescript.md000064400000000000000000000017401046102023000271760ustar 00000000000000# `skip_typescript` By default, Rust exports exposed to JavaScript will generate TypeScript definitions (unless `--no-typescript` is used). The `skip_typescript` attribute can be used to disable type generation per function, enum, struct, or field. For example: ```rust #[wasm_bindgen(skip_typescript)] pub enum MyHiddenEnum { One, Two, Three } #[wasm_bindgen] pub struct MyPoint { pub x: u32, #[wasm_bindgen(skip_typescript)] pub y: u32, } #[wasm_bindgen] impl MyPoint { #[wasm_bindgen(skip_typescript)] pub fn stringify(&self) -> String { format!("({}, {})", self.x, self.y) } } ``` Will generate the following `.d.ts` file: ```ts /* tslint:disable */ /* eslint-disable */ export class MyPoint { free(): void; x: number; } ``` When combined with [the `typescript_custom_section` attribute](typescript_custom_section.html), this can be used to manually specify more specific function types instead of using the generated definitions. wasm-bindgen-0.2.87/guide/src/reference/attributes/on-rust-exports/start.md000064400000000000000000000022771046102023000251050ustar 00000000000000# `start` When attached to a `pub` function this attribute will configure the `start` section of the wasm executable to be emitted, executing the tagged function as soon as the wasm module is instantiated. ```rust #[wasm_bindgen(start)] fn main() { // executed automatically ... } ``` The `start` section of the wasm executable will be configured to execute the `main` function here as soon as it can. Note that due to various practical limitations today the start section of the executable may not literally point to `main`, but the `main` function here should be started up automatically when the wasm module is loaded. There's a few caveats to be aware of when using the `start` attribute: * The `start` function must take no arguments and must either return `()` or `Result<(), JsValue>` * Only one `start` function can be placed into a module, including its dependencies. If more than one is specified then `wasm-bindgen` will fail when the CLI is run. It's recommended that only applications use this attribute. * The `start` function will not be executed when testing. * Note that the `start` function is relatively new, so if you find any bugs with it, please feel free to report an issue! wasm-bindgen-0.2.87/guide/src/reference/attributes/on-rust-exports/typescript_custom_section.md000064400000000000000000000020751046102023000312700ustar 00000000000000# `typescript_custom_section` When added to a `const` `&'static str`, it will append the contents of the string to the `.d.ts` file exported by `wasm-bindgen-cli` (when the `--typescript` flag is enabled). ```rust #[wasm_bindgen(typescript_custom_section)] const TS_APPEND_CONTENT: &'static str = r#" export type Coords = { "latitude": number, "longitude": number, }; "#; ``` The primary target for this feature is for code generation. For example, you can author a macro that allows you to export a TypeScript definition alongside the definition of a struct or Rust type. ```rust #[derive(MyTypescriptExport)] struct Coords { latitude: u32, longitude: u32, } ``` The proc_derive_macro "MyTypescriptExport" can export its own `#[wasm_bindgen(typescript_custom_section)]` section, which would then be picked up by wasm-bindgen-cli. This would be equivalent to the contents of the TS_APPEND_CONTENT string in the first example. This feature allows plain data objects to be typechecked in Rust and in TypeScript by outputting a type definition generated at compile time. wasm-bindgen-0.2.87/guide/src/reference/attributes/on-rust-exports/typescript_type.md000064400000000000000000000022301046102023000272040ustar 00000000000000# typescript_type The `typescript_type` allows us to use typescript declarations in `typescript_custom_section` as arguments for rust functions! For example: ```rust #[wasm_bindgen(typescript_custom_section)] const ITEXT_STYLE: &'static str = r#" interface ITextStyle { bold: boolean; italic: boolean; size: number; } "#; #[wasm_bindgen] extern "C" { #[wasm_bindgen(typescript_type = "ITextStyle")] pub type ITextStyle; } #[wasm_bindgen] #[derive(Default)] pub struct TextStyle { pub bold: bool, pub italic: bool, pub size: i32, } #[wasm_bindgen] impl TextStyle { #[wasm_bindgen(constructor)] pub fn new(i: ITextStyle) -> TextStyle { let _js_value: JsValue = i.into(); // parse JsValue TextStyle::default() } pub fn optional_new(_i: Option) -> TextStyle { // parse JsValue TextStyle::default() } } ``` We can write our `typescript` code like: ```ts import { ITextStyle, TextStyle } from "./my_awesome_module"; const style: TextStyle = new TextStyle({ bold: true, italic: true, size: 42, }); const optional_style: TextStyle = TextStyle.optional_new(); ``` wasm-bindgen-0.2.87/guide/src/reference/browser-support.md000064400000000000000000000024401046102023000216360ustar 00000000000000# Supported Browsers The output of `wasm-bindgen` includes a JS file, and as a result it's good to know what browsers that file is expected to be used in! By default the output uses ES modules with Wasm imports which isn't implemented in browsers today, but when using a bundler (like Webpack) or `--target web` you should be able to produce output suitable for all browsers. Firefox, Chrome, Safari, and Edge browsers are all supported by `wasm-bindgen`. If you find a problem in one of these browsers please [report it] as we'd like to fix the bug! If you find a bug in another browser we would also like to be aware of it! ## Caveats * **IE 11** - `wasm-bindgen` by default requires support for `WebAssembly`, but no version of IE currently supports `WebAssembly`. You can support IE by [compiling wasm files to JS using `wasm2js`][w2js] (you can [see an example of doing this too](../examples/wasm2js.html)). Note that at this time no bundler will do this by default, but we'd love to document plugins which do this if you are aware of one! If you find other incompatibilities please report them to us! We'd love to either keep this list up-to-date or fix the underlying bugs :) [report it]: https://github.com/rustwasm/wasm-bindgen/issues/new [w2js]: https://github.com/WebAssembly/binaryen wasm-bindgen-0.2.87/guide/src/reference/cli.md000064400000000000000000000107551046102023000172200ustar 00000000000000# The `wasm-bindgen` Command Line Interface The `wasm-bindgen` command line tool has a number of options available to it to tweak the JavaScript that is generated. The most up-to-date set of flags can always be listed via `wasm-bindgen --help`. ## Installation ``` cargo install -f wasm-bindgen-cli ``` ## Usage ``` wasm-bindgen [options] ./target/wasm32-unknown-unknown/release/crate.wasm ``` ## Options ### `--out-dir DIR` The target directory to emit the JavaScript bindings, TypeScript definitions, processed `.wasm` binary, etc... ### `--target` This flag indicates what flavor of output what `wasm-bindgen` should generate. For example it could generate code to be loaded in a bundler like Webpack, a native web page, or Node.js. For a full list of options to pass this flag, see the section on [deployment] [deployment]: deployment.html ### `--no-modules-global VAR` When `--target no-modules` is used this flag can indicate what the name of the global to assign generated bindings to. For more information about this see the section on [deployment] ### `--typescript` Output a TypeScript declaration file for the generated JavaScript bindings. This is on by default. ### `--no-typescript` By default, a `*.d.ts` TypeScript declaration file is generated for the generated JavaScript bindings, but this flag will disable that. ### `--omit-imports` When the `module` attribute is used with the `wasm-bindgen` macro, the code generator will emit corresponding `import` or `require` statements in the header section of the generated javascript. This flag causes those import statements to be omitted. This is necessary for some use cases, such as generating javascript which is intended to be used with Electron (with node integration disabled), where the imports are instead handled through a separate preload script. ### `--debug` Generates a bit more JS and wasm in "debug mode" to help catch programmer errors, but this output isn't intended to be shipped to production. ### `--no-demangle` When post-processing the `.wasm` binary, do not demangle Rust symbols in the "names" custom section. ### `--keep-lld-exports` When post-processing the `.wasm` binary, do not remove exports that are synthesized by Rust's linker, LLD. ### `--keep-debug` When post-processing the `.wasm` binary, do not strip DWARF debug info custom sections. ### `--browser` When generating bundler-compatible code (see the section on [deployment]) this indicates that the bundled code is always intended to go into a browser so a few checks for Node.js can be elided. ### `--weak-refs` Enables usage of the [TC39 Weak References proposal](https://github.com/tc39/proposal-weakrefs), ensuring that all Rust memory is eventually deallocated regardless of whether you're calling `free` or not. This is off-by-default while we're waiting for support to percolate into all major browsers. For more information see the [documentation about weak references](./weak-references.md). ### `--reference-types` Enables usage of the [WebAssembly References Types proposal](https://github.com/webassembly/reference-types) proposal, meaning that the WebAssembly binary will use `externref` when importing and exporting functions that work with `JsValue`. For more information see the [documentation about reference types](./reference-types.md). ### `--omit-default-module-path` Don't add WebAssembly fallback imports in generated JavaScript. ### `--split-linked-modules` Controls whether wasm-bindgen will split linked modules out into their own files. Enabling this is recommended, because it allows lazy-loading the linked modules and setting a stricter Content Security Policy. wasm-bindgen uses the `new URL('…', import.meta.url)` syntax to resolve the links to such split out files. This breaks with most bundlers, since the bundler doesn't know to include the linked module in its output. That's why this option is disabled by default. Webpack 5 is an exception, which has special treatment for that syntax. For other bundlers, you'll need to take extra steps to get it to work, likely by using a plugin. Alternatively, you can leave the syntax as is and instead manually configure the bundler to copy all files in `snippets/` to the output directory, preserving their paths relative to whichever bundled file ends up containing the JS shim. On the no-modules target, `link_to!` won't work if used outside of a document, e.g. inside a worker. This is because it's impossible to figure out what the URL of the linked module is without a reference point like `import.meta.url`. wasm-bindgen-0.2.87/guide/src/reference/deployment.md000064400000000000000000000103351046102023000206230ustar 00000000000000# Deploying Rust and WebAssembly At this point in time deploying Rust and WebAssembly to the web or other locations unfortunately isn't a trivial task to do. This page hopes to serve as documentation for the various known options, and as always PRs are welcome to update this if it's out of date! The methods of deployment and integration here are primarily tied to the `--target` flag. | Value | Summary | |-----------------|------------------------------------------------------------| | [`bundler`] | Suitable for loading in bundlers like Webpack | | [`web`] | Directly loadable in a web browser | | [`nodejs`] | Loadable via `require` as a Node.js module | | [`deno`] | Loadable using imports from Deno modules | | [`no-modules`] | Like `web`, but older and doesn't use ES modules | [`bundler`]: #bundlers [`web`]: #without-a-bundler [`no-modules`]: #without-a-bundler [`nodejs`]: #nodejs [`deno`]: #deno ## Bundlers **`--target bundler`** The default output of `wasm-bindgen`, or the `bundler` target, assumes a model where the wasm module itself is natively an ES module. This model, however, is not natively implemented in any JS implementation at this time. As a result, to consume the default output of `wasm-bindgen` you will need a bundler of some form. > **Note**: the choice of this default output was done to reflect the trends of > the JS ecosystem. While tools other than bundlers don't support wasm files as > native ES modules today they're all very much likely to in the future! Currently the only known bundler known to be fully compatible with `wasm-bindgen` is [webpack]. Most [examples] use webpack, and you can check out the [hello world example online] to see the details of webpack configuration necessary. [webpack]: https://webpack.js.org/ [examples]: ../examples/index.html [hello world example online]: ../examples/hello-world.html ## Without a Bundler **`--target web` or `--target no-modules`** If you're not using a bundler but you're still running code in a web browser, `wasm-bindgen` still supports this! For this use case you'll want to use the `--target web` flag. You can check out a [full example][nomex] in the documentation, but the highlights of this output are: * When compiling you'll pass `--target web` to `wasm-bindgen` * The output can natively be included on a web page, and doesn't require any further postprocessing. The output is included as an ES module. * The `--target web` mode is not able to use NPM dependencies. * You'll want to review the [browser requirements] for `wasm-bindgen` because no polyfills will be available. [nomex]: ../examples/without-a-bundler.html [rfc1]: https://github.com/rustwasm/rfcs/pull/6 [rfc2]: https://github.com/rustwasm/rfcs/pull/8 [browser requirements]: browser-support.html The CLI also supports an output mode called `--target no-modules` which is similar to the `web` target in that it requires manual initialization of the wasm and is intended to be included in web pages without any further postprocessing. See the [without a bundler example][nomex] for some more information about `--target no-modules`. ## Node.js **`--target nodejs`** If you're deploying WebAssembly into Node.js (perhaps as an alternative to a native module), then you'll want to pass the `--target nodejs` flag to `wasm-bindgen`. Like the "without a bundler" strategy, this method of deployment does not require any further postprocessing. The generated JS shims can be `require`'d just like any other Node module (even the `*_bg` wasm file can be `require`'d as it has a JS shim generated as well). Note that this method requires a version of Node.js with WebAssembly support, which is currently Node 8 and above. ## Deno **`--target deno`** To deploy WebAssembly to Deno, use the `--target deno` flag. To then import your module inside deno, use ```ts // @deno-types="./out/crate_name.d.ts" import { yourFunction } from "./out/crate_name.js"; ``` ## NPM If you'd like to deploy compiled WebAssembly to NPM, then the tool for the job is [`wasm-pack`]. More information on this coming soon! [`wasm-pack`]: https://rustwasm.github.io/docs/wasm-pack/ wasm-bindgen-0.2.87/guide/src/reference/index.md000064400000000000000000000006061046102023000175520ustar 00000000000000# Reference This section contains reference material for using `wasm-bindgen`. It is not intended to be read start to finish. Instead, it aims to quickly answer questions like: * Is type X supported as a parameter in a Rust function exported to JavaScript? * What was that CLI flag to disable ECMAScript modules output, and instead attach the JavaScript bindings directly to `window`? wasm-bindgen-0.2.87/guide/src/reference/iterating-over-js-values.md000064400000000000000000000065301046102023000233130ustar 00000000000000# Iterating over JavaScript Values ## Methods That Return `js_sys::Iterator` Some JavaScript collections have methods for iterating over their values or keys: * [`Map::values`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Map.html#method.values) * [`Set::keys`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Set.html#method.keys) * etc... These methods return [`js_sys::Iterator`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Iterator.html), which is the Rust representation of a JavaScript object that has a `next` method that either returns the next item in the iteration, notes that iteration has completed, or throws an error. That is, `js_sys::Iterator` represents an object that implements [the duck-typed JavaScript iteration protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols). `js_sys::Iterator` can be converted into a Rust iterator either by reference (into [`js_sys::Iter<'a>`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Iter.html)) or by value (into [`js_sys::IntoIter`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.IntoIter.html)). The Rust iterator will yield items of type `Result`. If it yields an `Ok(...)`, then the JS iterator protocol returned an element. If it yields an `Err(...)`, then the JS iterator protocol threw an exception. ```rust use wasm_bindgen::prelude::*; #[wasm_bindgen] pub fn count_strings_in_set(set: &js_sys::Set) -> u32 { let mut count = 0; // Call `keys` to get an iterator over the set's elements. Because this is // in a `for ... in ...` loop, Rust will automatically call its // `IntoIterator` trait implementation to convert it into a Rust iterator. for x in set.keys() { // We know the built-in iterator for set elements won't throw // exceptions, so just unwrap the element. If this was an untrusted // iterator, we might want to explicitly handle the case where it throws // an exception instead of returning a `{ value, done }` object. let x = x.unwrap(); // If `x` is a string, increment our count of strings in the set! if x.is_string() { count += 1; } } count } ``` ## Iterating Over Any JavaScript Object that Implements the Iterator Protocol You could manually test for whether an object implements JS's duck-typed iterator protocol, and if so, convert it into a `js_sys::Iterator` that you can finally iterate over. You don't need to do this by-hand, however, since we bundled this up as [the `js_sys::try_iter` function!](https://rustwasm.github.io/wasm-bindgen/api/js_sys/fn.try_iter.html) For example, we can write a function that collects the numbers from any JS iterable and returns them as an `Array`: ```rust use wasm_bindgen::prelude::*; #[wasm_bindgen] pub fn collect_numbers(some_iterable: &JsValue) -> Result { let nums = js_sys::Array::new(); let iterator = js_sys::try_iter(some_iterable)?.ok_or_else(|| { "need to pass iterable JS values!" })?; for x in iterator { // If the iterator's `next` method throws an error, propagate it // up to the caller. let x = x?; // If `x` is a number, add it to our array of numbers! if x.as_f64().is_some() { nums.push(&x); } } Ok(nums) } ``` wasm-bindgen-0.2.87/guide/src/reference/js-promises-and-rust-futures.md000064400000000000000000000104651046102023000241500ustar 00000000000000# Working with a JS `Promise` and a Rust `Future` Many APIs on the web work with a `Promise`, such as an `async` function in JS. Naturally you'll probably want to interoperate with them from Rust! To do that you can use the `wasm-bindgen-futures` crate as well as Rust `async` functions. The first thing you might encounter is the need for working with a `Promise`. For this you'll want to use [`js_sys::Promise`]. Once you've got one of those values you can convert that value to `wasm_bindgen_futures::JsFuture`. This type implements the `std::future::Future` trait which allows naturally using it in an `async` function. For example: [`js_sys::Promise`]: https://docs.rs/js-sys/*/js_sys/struct.Promise.html ```rust async fn get_from_js() -> Result { let promise = js_sys::Promise::resolve(&42.into()); let result = wasm_bindgen_futures::JsFuture::from(promise).await?; Ok(result) } ``` Here we can see how converting a `Promise` to Rust creates a `impl Future>`. This corresponds to `then` and `catch` in JS where a successful promise becomes `Ok` and an erroneous promise becomes `Err`. You can also import a JS async function directly with a `extern "C"` block, and the promise will be converted to a future automatically. For now the return type must be `JsValue` or no return at all: ```rust #[wasm_bindgen] extern "C" { async fn async_func_1() -> JsValue; async fn async_func_2(); } ``` The `async` can be combined with the `catch` attribute to manage errors from the JS promise: ```rust #[wasm_bindgen] extern "C" { #[wasm_bindgen(catch)] async fn async_func_3() -> Result; #[wasm_bindgen(catch)] async fn async_func_4() -> Result<(), JsValue>; } ``` Next up you'll probably want to export a Rust function to JS that returns a promise. To do this you can use an `async` function and `#[wasm_bindgen]`: ```rust #[wasm_bindgen] pub async fn foo() { // ... } ``` When invoked from JS the `foo` function here will return a `Promise`, so you can import this as: ```js import { foo } from "my-module"; async function shim() { const result = await foo(); // ... } ``` ## Return values of `async fn` When using an `async fn` in Rust and exporting it to JS there's some restrictions on the return type. The return value of an exported Rust function will eventually become `Result` where `Ok` turns into a successfully resolved promise and `Err` is equivalent to throwing an exception. The following types are supported as return types from an `async fn`: * `()` - turns into a successful `undefined` in JS * `T: Into` - turns into a successful JS value * `Result<(), E: Into>` - if `Ok(())` turns into a successful `undefined` and otherwise turns into a failed promise with `E` converted to a JS value * `Result, E: Into>` - like the previous case except both data payloads are converted into a `JsValue`. Note that many types implement being converted into a `JsValue`, such as all imported types via `#[wasm_bindgen]` (aka those in `js-sys` or `web-sys`), primitives like `u32`, and all exported `#[wasm_bindgen]` types. In general, you should be able to write code without having too many explicit conversions, and the macro should take care of the rest! ## Using `wasm-bindgen-futures` The `wasm-bindgen-futures` crate bridges the gap between JavaScript `Promise`s and Rust `Future`s. Its `JsFuture` type provides conversion from a JavaScript `Promise` into a Rust `Future`, and its `future_to_promise` function converts a Rust `Future` into a JavaScript `Promise` and schedules it to be driven to completion. Learn more: * [`wasm_bindgen_futures` on crates.io][crate] * [`wasm-bindgen-futures` API documentation and example usage][docs] [crate]: https://crates.io/crates/wasm-bindgen-futures [docs]: https://rustwasm.github.io/wasm-bindgen/api/wasm_bindgen_futures/ ## Compatibility with versions of `Future` The current crate on crates.io, `wasm-bindgen-futures 0.4.*`, supports `std::future::Future` and `async`/`await` in Rust. This typically requires Rust 1.39.0+ (as of this writing on 2019-09-05 it's the nightly channel of Rust). If you're using the `Future` trait from the `futures` `0.1.*` crate then you'll want to use the `0.3.*` track of `wasm-bindgen-futures` on crates.io. wasm-bindgen-0.2.87/guide/src/reference/js-snippets.md000064400000000000000000000056101046102023000207220ustar 00000000000000# JS Snippets Often when developing a crate you want to run on the web you'll want to include some JS code here and there. While [`js-sys`](https://docs.rs/js-sys) and [`web-sys`](https://docs.rs/web-sys) cover many needs they don't cover everything, so `wasm-bindgen` supports the ability to write JS code next to your Rust code and have it included in the final output artifact. To include a local JS file, you'll use the `#[wasm_bindgen(module)]` macro: ```rust #[wasm_bindgen(module = "/js/foo.js")] extern "C" { fn add(a: u32, b: u32) -> u32; } ``` This declaration indicates that all the functions contained in the `extern` block are imported from the file `/js/foo.js`, where the root is relative to the crate root (where `Cargo.toml` is located). The `/js/foo.js` file will make its way to the final output when `wasm-bindgen` executes, so you can use the `module` annotation in a library without having to worry users of your library! The JS file itself must be written with ES module syntax: ```js export function add(a, b) { return a + b; } ``` A full design of this feature can be found in [RFC 6] as well if you're interested! [RFC 6]: https://github.com/rustwasm/rfcs/pull/6 ### Using `inline_js` In addition to `module = "..."` if you're a macro author you also have the ability to use the `inline_js` attribute: ```rust #[wasm_bindgen(inline_js = "export function add(a, b) { return a + b; }")] extern "C" { fn add(a: u32, b: u32) -> u32; } ``` Using `inline_js` indicates that the JS module is specified inline in the attribute itself, and no files are loaded from the filesystem. They have the same limitations and caveats as when using `module`, but can sometimes be easier to generate for macros themselves. It's not recommended for hand-written code to make use of `inline_js` but instead to leverage `module` where possible. ### Caveats While quite useful local JS snippets currently suffer from a few caveats which are important to be aware of. Many of these are temporary though! * Currently `import` statements are not supported in the JS file. This is a restriction we may lift in the future once we settle on a good way to support this. For now, though, js snippets must be standalone modules and can't import from anything else. * Only `--target web` and the default bundler output mode are supported. To support `--target nodejs` we'd need to translate ES module syntax to CommonJS (this is planned to be done, just hasn't been done yet). Additionally to support `--target no-modules` we'd have to similarly translate from ES modules to something else. * Paths in `module = "..."` must currently start with `/`, or be rooted at the crate root. It is intended to eventually support relative paths like `./` and `../`, but it's currently believed that this requires more support in the Rust `proc_macro` crate. As above, more detail about caveats can be found in [RFC 6]. wasm-bindgen-0.2.87/guide/src/reference/optimize-size.md000064400000000000000000000047751046102023000212660ustar 00000000000000# Optimizing for Size with `wasm-bindgen` The Rust and WebAssembly Working Group's [Game of Life tutorial][gol] has an excellent section on [shrinking wasm code size][size], but there's a few `wasm-bindgen`-specific items to mention as well! First and foremost, `wasm-bindgen` is designed to be lightweight and a "pay only for what you use" mentality. If you suspect that `wasm-bindgen` is bloating your program that is a bug and we'd like to know about it! Please feel free to [file an issue][issue], even if it's a question! ### What to profile With `wasm-bindgen` there's a few different files to be measuring the size of. The first of which is the output of the compiler itself, typically at `target/wasm32-unknown-unknown/release/foo.wasm`. **This file is not optimized for size and you should not measure it.** The output of the compiler when linking with `wasm-bindgen` is by design larger than it needs to be, the `wasm-bindgen` CLI tool will automatically strip all unneeded functionality out of the binary. This leaves us with two primary generated files to measure the size of: * **Generated wasm** - after running the `wasm-bindgen` CLI tool you'll get a file in `--out-dir` that looks like `foo_bg.wasm`. This file is the final fully-finished artifact from `wasm-bindgen`, and it reflects the size of the app you'll be publishing. All the optimizations [mentioned in the code size tutorial][size] will help reduce the size of this binary, so feel free to go crazy! * **Generated JS** - the other file after running `wasm-bindgen` is a `foo.js` file which is what's actually imported by other JS code. This file is already generated to be as small as possible (not including unneeded functionality). The JS, however, is not uglified or minified, but rather still human readable and debuggable. It's expected that you'll run an uglifier or bundler of the JS output to minimize it further in your application. If you spot a way we could reduce the output JS size further (or make it more amenable to bundler minification), please let us know! ### Example As an example, the `wasm-bindgen` repository [contains an example][example] about generating small wasm binaries and shows off how to generate a small wasm file for adding two numbers. [gol]: https://rustwasm.github.io/book/game-of-life/introduction.html [size]: https://rustwasm.github.io/book/game-of-life/code-size.html [issue]: https://github.com/rustwasm/wasm-bindgen/issues/new [example]: https://rustwasm.github.io/docs/wasm-bindgen/examples/add.html wasm-bindgen-0.2.87/guide/src/reference/passing-rust-closures-to-js.md000064400000000000000000000065551046102023000240020ustar 00000000000000# Passing Rust Closures to Imported JavaScript Functions The `#[wasm_bindgen]` attribute supports Rust closures being passed to JavaScript in two variants: 1. Stack-lifetime closures that should not be invoked by JavaScript again after the imported JavaScript function that the closure was passed to returns. 2. Heap-allocated closures that can be invoked any number of times, but must be explicitly deallocated when finished. ## Stack-Lifetime Closures Closures with a stack lifetime are passed to JavaScript as either `&dyn Fn` or `&mut dyn FnMut` trait objects: ```rust // Import JS functions that take closures #[wasm_bindgen] extern "C" { fn takes_immutable_closure(f: &dyn Fn()); fn takes_mutable_closure(f: &mut dyn FnMut()); } // Usage takes_immutable_closure(&|| { // ... }); let mut times_called = 0; takes_mutable_closure(&mut || { times_called += 1; }); ``` **Once these imported functions return, the closures that were given to them will become invalidated, and any future attempts to call those closures from JavaScript will raise an exception.** Closures also support arguments and return values like exports do, for example: ```rust #[wasm_bindgen] extern "C" { fn takes_closure_that_takes_int_and_returns_string(x: &dyn Fn(u32) -> String); } takes_closure_that_takes_int_and_returns_string(&|x: u32| -> String { format!("x is {}", x) }); ``` ## Heap-Allocated Closures Sometimes the discipline of stack-lifetime closures is not desired. For example, you'd like to schedule a closure to be run on the next turn of the event loop in JavaScript through `setTimeout`. For this, you want the imported function to return but the JavaScript closure still needs to be valid! For this scenario, you need the `Closure` type, which is defined in the `wasm_bindgen` crate, exported in `wasm_bindgen::prelude`, and represents a "long lived" closure. The `Closure` type is currently behind a feature which needs to be enabled: ```toml [dependencies] wasm-bindgen = {version = "^0.2", features = ["nightly"]} ``` The validity of the JavaScript closure is tied to the lifetime of the `Closure` in Rust. **Once a `Closure` is dropped, it will deallocate its internal memory and invalidate the corresponding JavaScript function so that any further attempts to invoke it raise an exception.** Like stack closures a `Closure` supports both `Fn` and `FnMut` closures, as well as arguments and returns. ```rust #[wasm_bindgen] extern "C" { fn setInterval(closure: &Closure, millis: u32) -> f64; fn cancelInterval(token: f64); #[wasm_bindgen(js_namespace = console)] fn log(s: &str); } #[wasm_bindgen] pub struct Interval { closure: Closure, token: f64, } impl Interval { pub fn new(millis: u32, f: F) -> Interval where F: FnMut() { // Construct a new closure. let closure = Closure::new(f); // Pass the closure to JS, to run every n milliseconds. let token = setInterval(&closure, millis); Interval { closure, token } } } // When the Interval is destroyed, cancel its `setInterval` timer. impl Drop for Interval { fn drop(&mut self) { cancelInterval(self.token); } } // Keep logging "hello" every second until the resulting `Interval` is dropped. #[wasm_bindgen] pub fn hello() -> Interval { Interval::new(1_000, || log("hello")) } ``` wasm-bindgen-0.2.87/guide/src/reference/receiving-js-closures-in-rust.md000064400000000000000000000015231046102023000242630ustar 00000000000000# Receiving JavaScript Closures in Exported Rust Functions You can use the `js-sys` crate to access JavaScript's `Function` type, and invoke that function via `Function.prototype.apply` and `Function.prototype.call`. For example, we can wrap a `Vec` in a new type, export it to JavaScript, and invoke a JavaScript closure on each member of the `Vec`: ```rust use wasm_bindgen::prelude::*; #[wasm_bindgen] pub struct VecU32 { xs: Vec, } #[wasm_bindgen] impl VecU32 { pub fn each(&self, f: &js_sys::Function) { let this = JsValue::null(); for &x in &self.xs { let x = JsValue::from(x); let _ = f.call1(&this, &x); } } } ``` Since Rust has no function overloading, the `call#` method also requires a number representing the amount of arguments passed to the JavaScript closure. wasm-bindgen-0.2.87/guide/src/reference/reference-types.md000064400000000000000000000033551046102023000215470ustar 00000000000000# Support for Reference Types WebAssembly recently has gained support for a new value type called `externref`. Proposed in the [WebAssembly reference types repo](https://github.com/webassembly/reference-types) this feature of WebAssembly is hoped to enable more efficient communication between the host (JS) and the wasm module. This feature removes the need for much of the JS glue generated by `wasm-bindgen` because it can natively call APIs with JS values. For example, this Rust function: ```rust #[wasm_bindgen] pub fn takes_js_value(a: &JsValue) { // ... } ``` generates this JS glue *without* reference types support: ```js const heap = new Array(32).fill(undefined); heap.push(undefined, null, true, false); let stack_pointer = 32; function addBorrowedObject(obj) { if (stack_pointer == 1) throw new Error('out of js stack'); heap[--stack_pointer] = obj; return stack_pointer; } export function takes_js_value(a) { try { wasm.takes_js_value(addBorrowedObject(a)); } finally { heap[stack_pointer++] = undefined; } } ``` We can see here how under the hood the JS is managing a table of JS values which are passed to the wasm binary, so wasm actually only works in indices. If we pass the `--reference-types` flag to the CLI, however, the generated JS looks like: ```js export function takes_js_value(a) { wasm.takes_js_value(a); } ``` And that's it! The WebAssembly binary takes the JS value directly and manages it internally. Currently this feature is supported in Firefox 79+ and Chrome. Support in other browsers is likely coming soon! In Node.js this feature is behind the `--experimental-wasm-anyref` flag, although the support does not currently align with the upstream specification as of 14.6.0. wasm-bindgen-0.2.87/guide/src/reference/rust-targets.md000064400000000000000000000037121046102023000211100ustar 00000000000000# Supported Rust Targets > **Note**: This section is about Rust target triples, not targets like node/web > workers/browsers. More information on that coming soon! The `wasm-bindgen` project is designed to target the `wasm32-unknown-unknown` target in Rust. This target is a "bare bones" target for Rust which emits WebAssembly as output. The standard library is largely inert as modules like `std::fs` and `std::net` will simply return errors. ## Non-wasm targets Note that `wasm-bindgen` also aims to compile on all targets. This means that it should be safe, if you like, to use `#[wasm_bindgen]` even when compiling for Windows (for example). For example: ```rust #[wasm_bindgen] pub fn add(a: u32, b: u32) -> u32 { a + b } #[cfg(not(target_arch = "wasm32"))] fn main() { println!("1 + 2 = {}", add(1, 2)); } ``` This program will compile and work on all platforms, not just `wasm32-unknown-unknown`. Note that imported functions with `#[wasm_bindgen]` will unconditionally panic on non-wasm targets. For example: ```rust #[wasm_bindgen] extern "C" { #[wasm_bindgen(js_namespace = console)] fn log(s: &str); } fn main() { log("hello!"); } ``` This program will unconditionally panic on all platforms other than `wasm32-unknown-unknown`. For better compile times, however, you likely want to only use `#[wasm_bindgen]` on the `wasm32-unknown-unknown` target. You can have a target-specific dependency like so: ```toml [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen = "0.2" ``` And in your code you can use: ```rust #[cfg(target_arch = "wasm32")] #[wasm_bindgen] pub fn only_on_the_wasm_target() { // ... } ``` ## Other Web Targets The `wasm-bindgen` target does not support the `wasm32-unknown-emscripten` nor the `asmjs-unknown-emscripten` targets. There are currently no plans to support these targets either. All annotations work like other platforms on the targets, retaining exported functions and causing all imports to panic. wasm-bindgen-0.2.87/guide/src/reference/static-js-objects.md000064400000000000000000000026631046102023000220000ustar 00000000000000# Use of `static` to Access JS Objects JavaScript modules will often export arbitrary static objects for use with their provided interfaces. These objects can be accessed from Rust by declaring a named `static` in the `extern` block. `wasm-bindgen` will bind a `JsStatic` for these objects, which can be cloned into a `JsValue`. For example, given the following JavaScript: ```js let COLORS = { red: 'rgb(255, 0, 0)', green: 'rgb(0, 255, 0)', blue: 'rgb(0, 0, 255)', }; ``` `static` can aid in the access of this object from Rust: ```rust #[wasm_bindgen] extern "C" { static COLORS; } fn get_colors() -> JsValue { COLORS.clone() } ``` Since `COLORS` is effectively a JavaScript namespace, we can use the same mechanism to refer directly to namespaces exported from JavaScript modules, and even to exported classes: ```js let namespace = { // Members of namespace... }; class SomeType { // Definition of SomeType... }; export { SomeType, namespace }; ``` The binding for this module: ```rust #[wasm_bindgen(module = "/js/some-rollup.js")] extern "C" { // Likewise with the namespace--this refers to the object directly. #[wasm_bindgen(js_name = namespace)] static NAMESPACE: JsValue; // Refer to SomeType's class #[wasm_bindgen(js_name = SomeType)] static SOME_TYPE: JsValue; // Other bindings for SomeType type SomeType; #[wasm_bindgen(constructor)] fn new() -> SomeType; } ``` wasm-bindgen-0.2.87/guide/src/reference/types/bool.md000064400000000000000000000007631046102023000205460ustar 00000000000000# `bool` | `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | |:---:|:---:|:---:|:---:|:---:|:---:|:---:| | Yes | No | No | Yes | Yes | Yes | A JavaScript boolean value | ## Example Rust Usage ```rust {{#include ../../../../examples/guide-supported-types-examples/src/bool.rs}} ``` ## Example JavaScript Usage ```js {{#include ../../../../examples/guide-supported-types-examples/bool.js}} ``` wasm-bindgen-0.2.87/guide/src/reference/types/boxed-jsvalue-slice.md000064400000000000000000000012331046102023000234510ustar 00000000000000# `Box<[JsValue]>` | `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | |:---:|:---:|:---:|:---:|:---:|:---:|:---:| | Yes | No | No | Yes | Yes | Yes | A JavaScript `Array` object | Boxed slices of imported JS types and exported Rust types are also supported. `Vec` is supported wherever `Box<[T]>` is. ## Example Rust Usage ```rust {{#include ../../../../examples/guide-supported-types-examples/src/boxed_js_value_slice.rs}} ``` ## Example JavaScript Usage ```js {{#include ../../../../examples/guide-supported-types-examples/boxed_js_value_slice.js}} ``` wasm-bindgen-0.2.87/guide/src/reference/types/boxed-number-slices.md000064400000000000000000000017231046102023000234570ustar 00000000000000# Boxed Number Slices: `Box<[u8]>`, `Box<[i8]>`, `Box<[u16]>`, `Box<[i16]>`, `Box<[u32]>`, `Box<[i32]>`, `Box<[u64]>`, `Box<[i64]>`, `Box<[f32]>`, and `Box<[f64]>` | `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | |:---:|:---:|:---:|:---:|:---:|:---:|:---:| | Yes | No | No | Yes | Yes | Yes | A JavaScript `TypedArray` of the appropriate type (`Int32Array`, `Uint8Array`, etc...) | Note that the contents of the slice are copied into the JavaScript `TypedArray` from the Wasm linear memory when returning a boxed slice to JavaScript, and vice versa when receiving a JavaScript `TypedArray` as a boxed slice in Rust. ## Example Rust Usage ```rust {{#include ../../../../examples/guide-supported-types-examples/src/boxed_number_slices.rs}} ``` ## Example JavaScript Usage ```js {{#include ../../../../examples/guide-supported-types-examples/boxed_number_slices.js}} ``` wasm-bindgen-0.2.87/guide/src/reference/types/char.md000064400000000000000000000007601046102023000205250ustar 00000000000000# `char` | `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | |:---:|:---:|:---:|:---:|:---:|:---:|:---:| | Yes | No | No | Yes | No | No | A JavaScript string value | ## Example Rust Usage ```rust {{#include ../../../../examples/guide-supported-types-examples/src/char.rs}} ``` ## Example JavaScript Usage ```js {{#include ../../../../examples/guide-supported-types-examples/char.js}} ``` wasm-bindgen-0.2.87/guide/src/reference/types/exported-rust-types.md000064400000000000000000000016641046102023000236030ustar 00000000000000# Exported `struct Whatever` Rust Types | `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | |:---:|:---:|:---:|:---:|:---:|:---:|:---:| | Yes | Yes | Yes | Yes | Yes | Yes | Instances of a `wasm-bindgen`-generated JavaScript `class Whatever { ... }` | > **Note**: Public fields implementing Copy have automatically generated getters/setters. > To generate getters/setters for non-Copy public fields, use #[wasm_bindgen(getter_with_clone)] for the struct > or [implement getters/setters manually](https://rustwasm.github.io/wasm-bindgen/reference/attributes/on-rust-exports/getter-and-setter.html). ## Example Rust Usage ```rust {{#include ../../../../examples/guide-supported-types-examples/src/exported_types.rs}} ``` ## Example JavaScript Usage ```js {{#include ../../../../examples/guide-supported-types-examples/exported_types.js}} ``` wasm-bindgen-0.2.87/guide/src/reference/types/imported-js-types.md000064400000000000000000000011371046102023000232060ustar 00000000000000# Imported `extern Whatever;` JavaScript Types | `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | |:---:|:---:|:---:|:---:|:---:|:---:|:---:| | Yes | Yes | No | Yes | Yes | Yes | Instances of the extern `Whatever` JavaScript class / prototype constructor | ## Example Rust Usage ```rust {{#include ../../../../examples/guide-supported-types-examples/src/imported_types.rs}} ``` ## Example JavaScript Usage ```js {{#include ../../../../examples/guide-supported-types-examples/imported_types.js}} ``` wasm-bindgen-0.2.87/guide/src/reference/types/jsvalue.md000064400000000000000000000007671046102023000212700ustar 00000000000000# `JsValue` | `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | |:---:|:---:|:---:|:---:|:---:|:---:|:---:| | Yes | Yes | No | Yes | No | No | Any JavaScript value | ## Example Rust Usage ```rust {{#include ../../../../examples/guide-supported-types-examples/src/js_value.rs}} ``` ## Example JavaScript Usage ```js {{#include ../../../../examples/guide-supported-types-examples/js_value.js}} ``` wasm-bindgen-0.2.87/guide/src/reference/types/number-slices.md000064400000000000000000000013141046102023000223540ustar 00000000000000# Number Slices: `[u8]`, `[i8]`, `[u16]`, `[i16]`, `[u32]`, `[i32]`, `[u64]`, `[i64]`, `[f32]`, and `[f64]` | `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option<&T>` parameter | `Option` return value | JavaScript representation | |:---:|:---:|:---:|:---:|:---:|:---:|:---:| | No | Yes | Yes | No | No | No | A JavaScript `TypedArray` view of the Wasm memory for the boxed slice of the appropriate type (`Int32Array`, `Uint8Array`, etc) | ## Example Rust Usage ```rust {{#include ../../../../examples/guide-supported-types-examples/src/number_slices.rs}} ``` ## Example JavaScript Usage ```js {{#include ../../../../examples/guide-supported-types-examples/number_slices.js}} ``` wasm-bindgen-0.2.87/guide/src/reference/types/numbers.md000064400000000000000000000011231046102023000212550ustar 00000000000000# Numbers: `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, `isize`, `usize`, `f32`, and `f64` | `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | |:---:|:---:|:---:|:---:|:---:|:---:|:---:| | Yes | No | No | Yes | Yes | Yes | A JavaScript number value | ## Example Rust Usage ```rust {{#include ../../../../examples/guide-supported-types-examples/src/numbers.rs}} ``` ## Example JavaScript Usage ```js {{#include ../../../../examples/guide-supported-types-examples/numbers.js}} ``` wasm-bindgen-0.2.87/guide/src/reference/types/pointers.md000064400000000000000000000010111046102023000214410ustar 00000000000000# `*const T` and `*mut T` | `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | |:---:|:---:|:---:|:---:|:---:|:---:|:---:| | Yes | No | No | Yes | No | No | A JavaScript number value | ## Example Rust Usage ```rust {{#include ../../../../examples/guide-supported-types-examples/src/pointers.rs}} ``` ## Example JavaScript Usage ```js {{#include ../../../../examples/guide-supported-types-examples/pointers.js}} ``` wasm-bindgen-0.2.87/guide/src/reference/types/result.md000064400000000000000000000021351046102023000211240ustar 00000000000000# `Result` | `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | |:---:|:---:|:---:|:---:|:---:|:---:|:---:| | No | No | No | Yes | No | No | Same as `T`, or an exception | The `Result` type can be returned from functions exported to JS as well as closures in Rust. The `Ok` type must be able to be converted to JS, and the `Err` type must implement `Into`. Whenever `Ok(val)` is encountered it's converted to JS and handed off, and whenever `Err(error)` is encountered an exception is thrown in JS with `error`. You can use `Result` to enable handling of JS exceptions with `?` in Rust, naturally propagating it upwards to the wasm boundary. Furthermore you can also return custom types in Rust so long as they're all convertible to `JsValue`. Note that if you import a JS function with `Result` you need `#[wasm_bindgen(catch)]` to be annotated on the import (unlike exported functions, which require no extra annotation). This may not be necessary in the future though and it may work "as is"!. wasm-bindgen-0.2.87/guide/src/reference/types/str.md000064400000000000000000000041621046102023000204200ustar 00000000000000# `str` | `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | |:---:|:---:|:---:|:---:|:---:|:---:|:---:| | No | Yes | No | No | No | No | JavaScript string value | Copies the string's contents back and forth between the JavaScript garbage-collected heap and the Wasm linear memory with `TextDecoder` and `TextEncoder`. If you don't want to perform this copy, and would rather work with handles to JavaScript string values, use the `js_sys::JsString` type. ## Example Rust Usage ```rust {{#include ../../../../examples/guide-supported-types-examples/src/str.rs}} ``` ## Example JavaScript Usage ```js {{#include ../../../../examples/guide-supported-types-examples/str.js}} ``` ## UTF-16 vs UTF-8 Strings in JavaScript are encoded as UTF-16, but with one major exception: they can contain unpaired surrogates. For some Unicode characters UTF-16 uses two 16-bit values. These are called "surrogate pairs" because they always come in pairs. In JavaScript, it is possible for these surrogate pairs to be missing the other half, creating an "unpaired surrogate". When passing a string from JavaScript to Rust, it uses the `TextEncoder` API to convert from UTF-16 to UTF-8. This is normally perfectly fine... unless there are unpaired surrogates. In that case it will replace the unpaired surrogates with U+FFFD (�, the replacement character). That means the string in Rust is now different from the string in JavaScript! If you want to guarantee that the Rust string is the same as the JavaScript string, you should instead use `js_sys::JsString` (which keeps the string in JavaScript and doesn't copy it into Rust). If you want to access the raw value of a JS string, you can use `JsString::iter`, which returns an `Iterator`. This perfectly preserves everything (including unpaired surrogates), but it does not do any encoding (so you have to do that yourself!). If you simply want to ignore strings which contain unpaired surrogates, you can use `JsString::is_valid_utf16` to test whether the string contains unpaired surrogates or not. wasm-bindgen-0.2.87/guide/src/reference/types/string.md000064400000000000000000000014501046102023000211130ustar 00000000000000# `String` | `T` parameter | `&T` parameter | `&mut T` parameter | `T` return value | `Option` parameter | `Option` return value | JavaScript representation | |:---:|:---:|:---:|:---:|:---:|:---:|:---:| | Yes | No | No | Yes | Yes | Yes | JavaScript string value | Copies the string's contents back and forth between the JavaScript garbage-collected heap and the Wasm linear memory with `TextDecoder` and `TextEncoder` > **Note**: Be sure to check out the [documentation for `str`](str.html) to > learn about some caveats when working with strings between JS and Rust. ## Example Rust Usage ```rust {{#include ../../../../examples/guide-supported-types-examples/src/string.rs}} ``` ## Example JavaScript Usage ```js {{#include ../../../../examples/guide-supported-types-examples/string.js}} ``` wasm-bindgen-0.2.87/guide/src/reference/types.md000064400000000000000000000003461046102023000176100ustar 00000000000000# Supported Rust Types and their JavaScript Representations This section provides an overview of all the types that `wasm-bindgen` can send and receive across the WebAssembly ABI boundary, and how they translate into JavaScript. wasm-bindgen-0.2.87/guide/src/reference/weak-references.md000064400000000000000000000021751046102023000215140ustar 00000000000000# Support for Weak References By default wasm-bindgen does not use the [TC39 weak references proposal](https://github.com/tc39/proposal-weakrefs). This proposal just advanced to stage 4 at the time of this writing, but it will still stake some time for support to percolate into all the major browsers. Without weak references your JS integration may be susceptible to memory leaks in Rust, for example: * You could forget to call `.free()` on a JS object, leaving the Rust memory allocated. * Rust closures converted to JS values (the `Closure` type) may not be executed and cleaned up. * Rust closures have `Closure::{into_js_value,forget}` methods which explicitly do not free the underlying memory. These issues are all solved with the weak references proposal in JS. The `--weak-refs` flag to the `wasm-bindgen` CLI will enable usage of `FinalizationRegistry` to ensure that all memory is cleaned up, regardless of whether it's explicitly deallocated or not. Note that explicit deallocation is always a possibility and supported, but if it's not called then memory will still be automatically deallocated with the `--weak-refs` flag. wasm-bindgen-0.2.87/guide/src/reference/working-with-duck-typed-interfaces.md000064400000000000000000000012121046102023000252560ustar 00000000000000# Working with Duck-Typed Interfaces Liberal use of [the `structural` attribute](./attributes/on-js-imports/structural.html) on imported methods, getters, and setters allows you to define duck-typed interfaces. A duck-typed interface is one where many different JavaScript objects that don't share the same base class in their prototype chain and therefore are not `instanceof` the same base can be used the same way. ## Defining a Duck-Typed Interface in Rust ```rust {{#include ../../../examples/duck-typed-interfaces/src/lib.rs}} ``` ## JavaScript Usage ```js {{#include ../../../examples/duck-typed-interfaces/duck-typed-interfaces.js}} ``` wasm-bindgen-0.2.87/guide/src/wasm-bindgen-test/asynchronous-tests.md000064400000000000000000000025751046102023000237370ustar 00000000000000# Writing Asynchronous Tests Not all tests can execute immediately and some may need to do "blocking" work like fetching resources and/or other bits and pieces. To accommodate this asynchronous tests are also supported through the `futures` and `wasm-bindgen-futures` crates. Writing an asynchronous test is pretty simple, just use an `async` function! You'll also likely want to use the `wasm-bindgen-futures` crate to convert JS promises to Rust futures. ```rust use wasm_bindgen::prelude::*; use wasm_bindgen_futures::JsFuture; #[wasm_bindgen_test] async fn my_async_test() { // Create a promise that is ready on the next tick of the micro task queue. let promise = js_sys::Promise::resolve(&JsValue::from(42)); // Convert that promise into a future and make the test wait on it. let x = JsFuture::from(promise).await.unwrap(); assert_eq!(x, 42); } ``` ## Rust compiler compatibility Note that `async` functions are only supported in stable from Rust 1.39.0 and beyond. If you're using the `futures` crate from crates.io in its 0.1 version then you'll want to use the `0.3.*` version of `wasm-bindgen-futures` and the `0.2.8` version of `wasm-bindgen-test`. In those modes you'll also need to use `#[wasm_bindgen_test(async)]` instead of using an `async` function. In general we'd recommend using the nightly version with `async` since the user experience is much improved! wasm-bindgen-0.2.87/guide/src/wasm-bindgen-test/browsers.md000064400000000000000000000122251046102023000217030ustar 00000000000000# Testing in Headless Browsers ## Configure Your Test Crate Add this to the root of your test crate, e.g. `$MY_CRATE/tests/web.rs`: ```rust use wasm_bindgen_test::wasm_bindgen_test_configure; wasm_bindgen_test_configure!(run_in_browser); ``` Or if you need to run your tests inside a web worker, you can also configured it using the `wasm_bindgen_test_configure` macro as following snippet. ```rust use wasm_bindgen_test::wasm_bindgen_test_configure; wasm_bindgen_test_configure!(run_in_worker); ``` Note that although a particular test crate must target either headless browsers or Node.js, you can have test suites for both Node.js and browsers for your project by using multiple test crates. For example: ``` $MY_CRATE/ `-- tests |-- node.rs # The tests in this suite use the default Node.js. |-- worker.rs # The tests in this suite are configured for workers. `-- web.rs # The tests in this suite are configured for browsers. ``` ## Configuring Which Browser is Used To control which browser is used for headless testing, use the appropriate flag with `wasm-pack test`: * `wasm-pack test --chrome` — Run the tests in Chrome. This machine must have Chrome installed. * `wasm-pack test --firefox` — Run the tests in Firefox. This machine must have Firefox installed. * `wasm-pack test --safari` — Run the tests in Safari. This machine must have Safari installed. If multiple browser flags are passed, the tests will be run under each browser. ## Running the Tests in the Headless Browser Once the tests are configured to run in a headless browser, just run `wasm-pack test` with the appropriate browser flags and `--headless`: ```bash wasm-pack test --headless --chrome --firefox --safari ``` ## Configuring Headless Browser capabilities Add the file `webdriver.json` to the root of your crate. Each browser has own section for capabilities. For example: ```json { "moz:firefoxOptions": { "prefs": { "media.navigator.streams.fake": true, "media.navigator.permission.disabled": true }, "args": [] }, "goog:chromeOptions": { "args": [ "--use-fake-device-for-media-stream", "--use-fake-ui-for-media-stream" ] } } ``` Full list supported capabilities can be found: * for Chrome - [here](https://peter.sh/experiments/chromium-command-line-switches/) * for Firefox - [here](https://developer.mozilla.org/en-US/docs/Web/WebDriver/Capabilities/firefoxOptions) Note that the `headless` argument is always enabled for both browsers. You have to enable the special preference `dom.workers.modules.enabled` for firefox when running the tests in Web Workers without using `WASM_BINDGEN_USE_NO_MODULE` variable. Because firefox supported ECMAScript modules in last release (2023-03-14) behind a special preference. ### Debugging Headless Browser Tests Omitting the `--headless` flag will disable headless mode, and allow you to debug failing tests in your browser's devtools. -------------------------------------------------------------------------------- ## Appendix: Testing in headless browsers without `wasm-pack` **âš ï¸ The recommended way to use `wasm-bindgen-test` is with `wasm-pack`, since it will handle installing the test runner, installing a WebDriver client for your browser, and informing `cargo` how to use the custom test runner.** However, you can also manage those tasks yourself, if you wish. ### Configuring Which Browser is Used If one of the following environment variables is set, then the corresponding WebDriver and browser will be used. If none of these environment variables are set, then the `$PATH` is searched for a suitable WebDriver implementation. #### `GECKODRIVER=path/to/geckodriver` Use Firefox for headless browser testing, and `geckodriver` as its WebDriver. The `firefox` binary must be on your `$PATH`. [Get `geckodriver` here](https://github.com/mozilla/geckodriver/releases) #### `CHROMEDRIVER=path/to/chromedriver` Use Chrome for headless browser testing, and `chromedriver` as its WebDriver. The `chrome` binary must be on your `$PATH`. [Get `chromedriver` here](http://chromedriver.chromium.org/downloads) #### `SAFARIDRIVER=path/to/safaridriver` Use Safari for headless browser testing, and `safaridriver` as its WebDriver. This is installed by default on Mac OS. It should be able to find your Safari installation by default. ### Running the Tests in the Remote Headless Browser Tests can be run on a remote webdriver. To do this, the above environment variables must be set as URL to the remote webdriver. For example: ``` CHROMEDRIVER_REMOTE=http://remote.host/ ``` ### Running the Tests in the Headless Browser Once the tests are configured to run in a headless browser and the appropriate environment variables are set, executing the tests for headless browsers is the same as executing them for Node.js: ```bash cargo test --target wasm32-unknown-unknown ``` #### Debugging Headless Browser Tests Set the `NO_HEADLESS=1` environment variable and the browser tests will not run headless. Instead, the tests will start a local server that you can visit in your Web browser of choices, and headless testing should not be used. You can then use your browser's devtools to debug. wasm-bindgen-0.2.87/guide/src/wasm-bindgen-test/continuous-integration.md000064400000000000000000000034501046102023000245640ustar 00000000000000# Setting Up Continuous Integration with `wasm-bindgen-test` This page contains example configurations for running `wasm-bindgen-test`-based tests in various CI services. Is your favorite CI service missing? [Send us a pull request!](https://github.com/rustwasm/wasm-bindgen) ## Travis CI ```yaml language: rust rust : nightly addons: firefox: latest chrome : stable install: - curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh script: # this will test the non wasm targets if your crate has those, otherwise remove this line. # - cargo test - wasm-pack test --firefox --headless - wasm-pack test --chrome --headless ``` ## AppVeyor ```yaml install: - ps: Install-Product node 10 - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe - rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain nightly - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin - rustc -V - cargo -V - rustup target add wasm32-unknown-unknown - cargo install wasm-bindgen-cli build: false test_script: # Test in Chrome. chromedriver is installed by default in appveyor. - set CHROMEDRIVER=C:\Tools\WebDriver\chromedriver.exe - cargo test --target wasm32-unknown-unknown - set CHROMEDRIVER= # Test in Firefox. geckodriver is also installed by default. - set GECKODRIVER=C:\Tools\WebDriver\geckodriver.exe - cargo test --target wasm32-unknown-unknown ``` ## GitHub Actions ```yaml on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Install run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh - run: cargo test - run: wasm-pack test --headless --chrome - run: wasm-pack test --headless --firefox ``` wasm-bindgen-0.2.87/guide/src/wasm-bindgen-test/index.md000064400000000000000000000007741046102023000211520ustar 00000000000000# Testing on `wasm32-unknown-unknown` with `wasm-bindgen-test` The `wasm-bindgen-test` crate is an experimental test harness for Rust programs compiled to wasm using `wasm-bindgen` and the `wasm32-unknown-unknown` target. ## Goals * Write tests for wasm as similar as possible to how you normally would write `#[test]`-style unit tests for native targets. * Run the tests with the usual `cargo test` command but with an explicit wasm target: ``` cargo test --target wasm32-unknown-unknown ``` wasm-bindgen-0.2.87/guide/src/wasm-bindgen-test/usage.md000064400000000000000000000071531046102023000211450ustar 00000000000000# Using `wasm-bindgen-test` ### Add `wasm-bindgen-test` to Your `Cargo.toml`'s `[dev-dependencies]` ```toml [dev-dependencies] wasm-bindgen-test = "0.3.0" ``` Note that the `0.3.0` track of `wasm-bindgen-test` supports Rust 1.39.0+, which is currently the nightly channel (as of 2019-09-05). If you want support for older compilers use the `0.2.*` track of `wasm-bindgen-test`. ## Write Some Tests Create a `$MY_CRATE/tests/wasm.rs` file: ```rust use wasm_bindgen_test::*; #[wasm_bindgen_test] fn pass() { assert_eq!(1, 1); } #[wasm_bindgen_test] fn fail() { assert_eq!(1, 2); } ``` Writing tests is the same as normal Rust `#[test]`s, except we are using the `#[wasm_bindgen_test]` attribute. One other difference is that the tests **must** be in the root of the crate, or within a `pub mod`. Putting them inside a private module will not work. ## Execute Your Tests Run the tests with `wasm-pack test`. By default, the tests are generated to target Node.js, but you can [configure tests to run inside headless browsers](./browsers.html) as well. ```shell $ wasm-pack test --node Finished dev [unoptimized + debuginfo] target(s) in 0.11s Running /home/.../target/wasm32-unknown-unknown/debug/deps/wasm-4a309ffe6ad80503.wasm running 2 tests test wasm::pass ... ok test wasm::fail ... FAILED failures: ---- wasm::fail output ---- error output: panicked at 'assertion failed: `(left == right)` left: `1`, right: `2`', crates/test/tests/wasm.rs:14:5 JS exception that was thrown: RuntimeError: unreachable at __rust_start_panic (wasm-function[1362]:33) at rust_panic (wasm-function[1357]:30) at std::panicking::rust_panic_with_hook::h56e5e464b0e7fc22 (wasm-function[1352]:444) at std::panicking::continue_panic_fmt::had70ba48785b9a8f (wasm-function[1350]:122) at std::panicking::begin_panic_fmt::h991e7d1ca9bf9c0c (wasm-function[1351]:95) at wasm::fail::ha4c23c69dfa0eea9 (wasm-function[88]:477) at core::ops::function::FnOnce::call_once::h633718dad359559a (wasm-function[21]:22) at wasm_bindgen_test::__rt::Context::execute::h2f669104986475eb (wasm-function[13]:291) at __wbg_test_fail_1 (wasm-function[87]:57) at module.exports.__wbg_apply_2ba774592c5223a7 (/home/alex/code/wasm-bindgen/target/wasm32-unknown-unknown/wbg-tmp/wasm-4a309ffe6ad80503.js:61:66) failures: wasm::fail test result: FAILED. 1 passed; 1 failed; 0 ignored error: test failed, to rerun pass '--test wasm' ``` That's it! -------------------------------------------------------------------------------- ## Appendix: Using `wasm-bindgen-test` without `wasm-pack` **âš ï¸ The recommended way to use `wasm-bindgen-test` is with `wasm-pack`, since it will handle installing the test runner, installing a WebDriver client for your browser, and informing `cargo` how to use the custom test runner.** However, you can also manage those tasks yourself, if you wish. In addition to the steps above, you must also do the following. ### Install the Test Runner The test runner comes along with the main `wasm-bindgen` CLI tool. Make sure to replace "X.Y.Z" with the same version of `wasm-bindgen` that you already have in `Cargo.toml`! ```shell cargo install wasm-bindgen-cli --vers "X.Y.Z" ``` ### Configure `.cargo/config` to use the Test Runner Add this to `$MY_CRATE/.cargo/config`: ```toml [target.wasm32-unknown-unknown] runner = 'wasm-bindgen-test-runner' ``` ### Run the Tests Run the tests by passing `--target wasm32-unknown-unknown` to `cargo test`: ``` cargo test --target wasm32-unknown-unknown ``` wasm-bindgen-0.2.87/guide/src/web-sys/cargo-features.md000064400000000000000000000015101046102023000210000ustar 00000000000000# Cargo Features in `web-sys` To keep `web-sys` building as fast as possible, there is a cargo feature for every type defined in `web-sys`. To access that type, you must enable its feature. To access a method, you must enable the feature for its `self` type and the features for each of its argument types. In the [API documentation][], every method lists the features that are required to enable it. For example, [the `WebGlRenderingContext::compile_shader` function][compile_shader] requires these features: * `WebGlRenderingContext`, because that is the method's `self` type * `WebGlShader`, because it takes an argument of that type [API documentation]: https://rustwasm.github.io/wasm-bindgen/api/web_sys [compile_shader]: https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.WebGlRenderingContext.html#method.compile_shader wasm-bindgen-0.2.87/guide/src/web-sys/function-overloads.md000064400000000000000000000024071046102023000217200ustar 00000000000000# Function Overloads Many Web APIs are overloaded to take different types of arguments or to skip arguments completely. `web-sys` contains multiple bindings for these functions that each specialize to a particular overload and set of argument types. For example, [the `fetch` API][mdn-fetch] can be given a URL string, or a `Request` object, and it might also optionally be given a `RequestInit` options object. Therefore, we end up with these `web-sys` functions that all bind to the `window.fetch` function: * [`Window::fetch_with_str`](https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Window.html#method.fetch_with_str) * [`Window::fetch_with_request`](https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Window.html#method.fetch_with_request) * [`Window::fetch_with_str_and_init`](https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Window.html#method.fetch_with_str_and_init) * [`Window::fetch_with_request_and_init`](https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Window.html#method.fetch_with_request_and_init) Note that different overloads can use different interfaces, and therefore can require different sets of cargo features to be enabled. [mdn-fetch]: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch wasm-bindgen-0.2.87/guide/src/web-sys/index.md000064400000000000000000000013261046102023000172050ustar 00000000000000# The `web-sys` Crate [The `web-sys` crate][web-sys] provides raw `wasm-bindgen` imports for all of the Web's APIs. This includes: * `window.fetch` * `Node.prototype.appendChild` * WebGL * WebAudio * and many more! It's sort of like the `libc` crate, but for the Web. It does *not* include the JavaScript APIs that are guaranteed to exist in all standards-compliant ECMAScript environments, such as `Array`, `Date`, and `eval`. Bindings for these APIs can be found in [the `js-sys` crate][js-sys]. ## API Documentation [**Read the `web-sys` API documentation here!**][api] [api]: https://rustwasm.github.io/wasm-bindgen/api/web_sys/ [js-sys]: https://crates.io/crates/js-sys [web-sys]: https://crates.io/crates/web-sys wasm-bindgen-0.2.87/guide/src/web-sys/inheritance.md000064400000000000000000000040621046102023000203670ustar 00000000000000# Inheritance in `web-sys` Inheritance between JS classes is the bread and butter of how the DOM works on the web, and as a result it's quite important for `web-sys` to provide access to this inheritance hierarchy as well! There are few ways you can access the inheritance hierarchy when using `web-sys`. ### Accessing parent classes using `Deref` Like smart pointers in Rust, all types in `web_sys` implement `Deref` to their parent JS class. This means, for example, if you have a `web_sys::Element` you can create a `web_sys::Node` from that implicitly: ```rust let element: &Element = ...; element.append_child(..); // call a method on `Node` method_expecting_a_node(&element); // coerce to `&Node` implicitly let node: &Node = &element; // explicitly coerce to `&Node` ``` Using `Deref` allows ergonomic transitioning up the inheritance hierarchy to the parent class and beyond, giving you access to all the methods using the `.` operator. ### Accessing parent classes using `AsRef` In addition to `Deref`, the `AsRef` trait is implemented for all types in `web_sys` for all types in the inheritance hierarchy. For example for the `HtmlAnchorElement` type you'll find: ```rust impl AsRef for HtmlAnchorElement impl AsRef for HtmlAnchorElement impl AsRef for HtmlAnchorElement impl AsRef for HtmlAnchorElement impl AsRef for HtmlAnchorElement impl AsRef for HtmlAnchorElement ``` You can use `.as_ref()` to explicitly get a reference to any parent class from from a type in `web_sys`. Note that because of the number of `AsRef` implementations you'll likely need to have type inference guidance as well. ### Accessing child clases using `JsCast` Finally the `wasm_bindgen::JsCast` trait can be used to implement all manner of casts between types. It supports static unchecked casts between types as well as dynamic runtime-checked casts (using `instanceof`) between types. More documentation about this can be found [on the trait itself][jscast] [jscast]: https://docs.rs/wasm-bindgen/0.2/wasm_bindgen/trait.JsCast.html wasm-bindgen-0.2.87/guide/src/web-sys/type-translations.md000064400000000000000000000023161046102023000215760ustar 00000000000000# Type Translations in `web-sys` Most of the types specified in [WebIDL (the interface definition language for all Web APIs)][webidl] have relatively straightforward translations into `web-sys`, but it's worth calling out a few in particular: * `BufferSource` and `ArrayBufferView` - these two types show up in a number of APIs that generally deal with a buffer of bytes. We bind them in `web-sys` with two different types, `js_sys::Object` and `&mut [u8]`. Using `js_sys::Object` allows passing in arbitrary JS values which represent a view of bytes (like any typed array object), and `&mut [u8]` allows using a raw slice in Rust. Unfortunately we must pessimistically assume that JS will modify all slices as we don't currently have information of whether they're modified or not. * Callbacks are all represented as `js_sys::Function`. This means that all callbacks going through `web-sys` are a raw JS value. You can work with this by either juggling actual `js_sys::Function` instances or you can create a `Closure`, extract the underlying `JsValue` with `as_ref`, and then use `JsCast::unchecked_ref` to convert it to a `js_sys::Function`. [webidl]: https://heycam.github.io/webidl/ wasm-bindgen-0.2.87/guide/src/web-sys/unstable-apis.md000064400000000000000000000023141046102023000206430ustar 00000000000000# Unstable APIs It's common for browsers to implement parts of a web API while the specification for that API is still being written. The API may require frequent changes as the specification continues to be developed, so the WebIDL is relatively unstable. This causes some challenges for `web-sys` because it means `web-sys` would have to make breaking API changes whenever the WebIDL changes. It also means that previously published `web-sys` versions would be invalid, because the browser API may have been changed to match the updated WebIDL. To avoid frequent breaking changes for unstable APIs, `web-sys` hides all unstable APIs through an attribute that looks like: ```rust #[cfg(web_sys_unstable_apis)] pub struct Foo; ``` By hiding unstable APIs through an attribute, it's necessary for crates to explicitly opt-in to these reduced stability guarantees in order to use these APIs. Specifically, these APIs do not follow semver and may break whenever the WebIDL changes. Crates can opt-in to unstable APIs at compile-time by passing the `cfg` flag `web_sys_unstable_apis`. Typically the `RUSTFLAGS` environment variable is used to do this. For example: ```bash RUSTFLAGS=--cfg=web_sys_unstable_apis cargo run ``` wasm-bindgen-0.2.87/guide/src/web-sys/using-web-sys.md000064400000000000000000000030341046102023000206100ustar 00000000000000# Using `web-sys` ## Add `web-sys` as a dependency to your `Cargo.toml` ```toml [dependencies] wasm-bindgen = "0.2" [dependencies.web-sys] version = "0.3" features = [ ] ``` ## Enable the cargo features for the APIs you're using To keep build times super speedy, [`web-sys` gates each Web interface behind a cargo feature](./cargo-features.html). Find the type or method you want to use in the [API documentation][api]; it will list the features that must be enabled to access that API. For example, if we're looking for [the `window.resizeTo` function][js-resize-to], we would [search for `resizeTo` in the API documentation][search-resize-to]. We would find [the `web_sys::Window::resize_to` function][rust-resize-to], which requires the `Window` feature. To get access to that function, we enable the `Window` feature in `Cargo.toml`: ```toml [dependencies.web-sys] version = "0.3" features = [ "Window" ] ``` ## Call the method! ```rust use wasm_bindgen::prelude::*; use web_sys::Window; #[wasm_bindgen] pub fn make_the_window_small() { // Resize the window to 500px by 500px. let window = web_sys::window().unwrap(); window.resize_to(500, 500) .expect("could not resize the window"); } ``` [api]: https://rustwasm.github.io/wasm-bindgen/api/web_sys/ [js-resize-to]: https://developer.mozilla.org/en-US/docs/Web/API/window/resizeTo [search-resize-to]: https://rustwasm.github.io/wasm-bindgen/api/web_sys/?search=resizeTo [rust-resize-to]: https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Window.html#method.resize_to wasm-bindgen-0.2.87/publish.rs000064400000000000000000000143621046102023000143170ustar 00000000000000//! Helper script to publish the wasm-bindgen suite of crates //! //! Usage: //! //! * First, compile this script //! * Next, set cwd to the root of the wasm-bindgen repository //! * Execute `./publish bump` to bump versions //! * Send a PR //! * Merge when green //! * Execute `./publish publish` to publish crates use std::collections::HashMap; use std::env; use std::fs; use std::io; use std::path::{Path, PathBuf}; use std::process::Command; // note that this list must be topologically sorted by dependencies const CRATES_TO_PUBLISH: &[&str] = &[ "wasm-bindgen-shared", "wasm-bindgen-backend", "wasm-bindgen-macro-support", "wasm-bindgen-macro", "wasm-bindgen-test-macro", "wasm-bindgen-test", "wasm-bindgen-wasm-interpreter", "wasm-bindgen-wasm-conventions", "wasm-bindgen-threads-xform", "wasm-bindgen-multi-value-xform", "wasm-bindgen-externref-xform", "wasm-bindgen-cli-support", "wasm-bindgen-cli", "wasm-bindgen", "wasm-bindgen-futures", "js-sys", "web-sys", ]; const CRATES_TO_AVOID_PUBLISH: &[&str] = &[ // We'll publish these when they're ready one day "wasm-bindgen-typescript", // These are internal crates, unlikely to ever be published "ui-tests", "sample", "webidl-tests", "typescript-tests", "wasm-bindgen-webidl", "example-tests", ]; struct Crate { manifest: PathBuf, name: String, version: String, next_version: String, } fn main() { let mut crates = Vec::new(); crates.push(read_crate("./Cargo.toml".as_ref())); find_crates("crates".as_ref(), &mut crates); find_crates("examples".as_ref(), &mut crates); let pos = CRATES_TO_PUBLISH .iter() .chain(CRATES_TO_AVOID_PUBLISH) .enumerate() .map(|(i, c)| (*c, i)) .collect::>(); crates.sort_by_key(|krate| pos.get(&krate.name[..])); match &env::args().nth(1).expect("must have one argument")[..] { "bump" => { for krate in crates.iter() { bump_version(&krate, &crates); } } "publish" => { for krate in crates.iter() { publish(&krate); } } s => panic!("unknown command: {}", s), } } fn find_crates(dir: &Path, dst: &mut Vec) { if dir.join("Cargo.toml").exists() { let krate = read_crate(&dir.join("Cargo.toml")); if CRATES_TO_PUBLISH .iter() .chain(CRATES_TO_AVOID_PUBLISH) .any(|c| krate.name == *c) { dst.push(krate); } else if dir.iter().any(|s| s == "examples") { dst.push(krate); } else { panic!("failed to find {:?} in whitelist or blacklist", krate.name); } } for entry in dir.read_dir().unwrap() { let entry = entry.unwrap(); if entry.file_type().unwrap().is_dir() { find_crates(&entry.path(), dst); } } } fn read_crate(manifest: &Path) -> Crate { let mut name = None; let mut version = None; for line in fs::read_to_string(manifest).unwrap().lines() { if name.is_none() && line.starts_with("name = \"") { name = Some( line.replace("name = \"", "") .replace("\"", "") .trim() .to_string(), ); } if version.is_none() && line.starts_with("version = \"") { version = Some( line.replace("version = \"", "") .replace("\"", "") .trim() .to_string(), ); } } let name = name.unwrap(); let version = version.unwrap(); let next_version = if CRATES_TO_PUBLISH.contains(&&name[..]) { bump(&version) } else { version.clone() }; Crate { manifest: manifest.to_path_buf(), name, version, next_version, } } fn bump_version(krate: &Crate, crates: &[Crate]) { let contents = fs::read_to_string(&krate.manifest).unwrap(); let mut new_manifest = String::new(); let mut is_deps = false; for line in contents.lines() { let mut rewritten = false; if line.starts_with("version =") { if CRATES_TO_PUBLISH.contains(&&krate.name[..]) { println!( "bump `{}` {} => {}", krate.name, krate.version, krate.next_version ); new_manifest.push_str(&line.replace(&krate.version, &krate.next_version)); rewritten = true; } } is_deps = if line.starts_with("[") { line.contains("dependencies") } else { is_deps }; for other in crates { if !is_deps || !line.starts_with(&format!("{} ", other.name)) { continue; } if !line.contains(&other.version) { if !line.contains("version =") { continue; } panic!( "{:?} has a dep on {} but doesn't list version {}", krate.manifest, other.name, other.version ); } rewritten = true; new_manifest.push_str(&line.replace(&other.version, &other.next_version)); break; } if !rewritten { new_manifest.push_str(line); } new_manifest.push_str("\n"); } fs::write(&krate.manifest, new_manifest).unwrap(); } fn bump(version: &str) -> String { let mut iter = version.split('.').map(|s| s.parse::().unwrap()); let major = iter.next().expect("major version"); let minor = iter.next().expect("minor version"); let patch = iter.next().expect("patch version"); format!("{}.{}.{}", major, minor, patch + 1) } fn publish(krate: &Crate) { if !CRATES_TO_PUBLISH.iter().any(|s| *s == krate.name) { return; } let status = Command::new("cargo") .arg("publish") .current_dir(krate.manifest.parent().unwrap()) .arg("--no-verify") .arg("--allow-dirty") .status() .expect("failed to run cargo"); if !status.success() { println!("FAIL: failed to publish `{}`: {}", krate.name, status); } } wasm-bindgen-0.2.87/releases/friends.sh000075500000000000000000000004671046102023000161000ustar 00000000000000#!/usr/bin/env bash set -eu set -o pipefail cd $(dirname $0) if [[ -z "${1+x}" ]]; then read -p "List friends since which commit/tag? " since echo else since=$1 fi git shortlog -s -n "$since.." \ | cut -f 2- \ | sort -u \ | grep -v bors\-servo \ | xargs -d '\n' -I{} echo "- {}" wasm-bindgen-0.2.87/releases/release-announcement-template.md000064400000000000000000000021171046102023000223440ustar 00000000000000# Announcing `wasm-bindgen` $TODO_VERSION `wasm-bindgen` facilitates high-level interactions between wasm modules and JavaScript. * [GitHub][] * [crates.io][] * [The `wasm-bindgen` Guide][guide] Upgrade to this release by updating your `Cargo.toml`: ```toml wasm-bindgen = "$TODO_VERSION" ``` ## Changelog ## Friends Thanks to everyone who contributed to this release! ## Contributing Want to join us? Check out our [The "Contributing" section of the guide][contributing] and take a look at some of these issues: * [Issues labeled "good first issue"][good-first-issue] * [Issues labeled "help wanted"][help-wanted] [GitHub]: https://github.com/rustwasm/wasm-bindgen [crates.io]: https://crates.io/crates/wasm-bindgen [guide]: https://rustwasm.github.io/wasm-bindgen [contributing]: https://rustwasm.github.io/wasm-bindgen/contributing.md [good-first-issue]: https://github.com/rustwasm/wasm-bindgen/labels/good%20first%20issue [help-wanted]: https://github.com/rustwasm/wasm-bindgen/labels/help%20wanted wasm-bindgen-0.2.87/src/cache/intern.rs000064400000000000000000000061051046102023000157760ustar 00000000000000use cfg_if::cfg_if; cfg_if! { if #[cfg(feature = "enable-interning")] { use std::thread_local; use std::string::String; use std::borrow::ToOwned; use std::cell::RefCell; use std::collections::HashMap; use crate::JsValue; struct Cache { entries: RefCell>, } thread_local! { static CACHE: Cache = Cache { entries: RefCell::new(HashMap::new()), }; } /// This returns the raw index of the cached JsValue, so you must take care /// so that you don't use it after it is freed. pub(crate) fn unsafe_get_str(s: &str) -> Option { CACHE.with(|cache| { let cache = cache.entries.borrow(); cache.get(s).map(|x| x.idx) }) } fn intern_str(key: &str) { CACHE.with(|cache| { let mut cache = cache.entries.borrow_mut(); // Can't use `entry` because `entry` requires a `String` if !cache.contains_key(key) { cache.insert(key.to_owned(), JsValue::from(key)); } }) } fn unintern_str(key: &str) { CACHE.with(|cache| { let mut cache = cache.entries.borrow_mut(); cache.remove(key); }) } } } /// Interns Rust strings so that it's much faster to send them to JS. /// /// Sending strings from Rust to JS is slow, because it has to do a full `O(n)` /// copy and *also* encode from UTF-8 to UTF-16. This must be done every single /// time a string is sent to JS. /// /// If you are sending the same string multiple times, you can call this `intern` /// function, which simply returns its argument unchanged: /// /// ```rust /// # use wasm_bindgen::intern; /// intern("foo") // returns "foo" /// # ; /// ``` /// /// However, if you enable the `"enable-interning"` feature for wasm-bindgen, /// then it will add the string into an internal cache. /// /// When you send that cached string to JS, it will look it up in the cache, /// which completely avoids the `O(n)` copy and encoding. This has a significant /// speed boost (as high as 783%)! /// /// However, there is a small cost to this caching, so you shouldn't cache every /// string. Only cache strings which have a high likelihood of being sent /// to JS multiple times. /// /// Also, keep in mind that this function is a *performance hint*: it's not /// *guaranteed* that the string will be cached, and the caching strategy /// might change at any time, so don't rely upon it. #[inline] pub fn intern(s: &str) -> &str { #[cfg(feature = "enable-interning")] intern_str(s); s } /// Removes a Rust string from the intern cache. /// /// This does the opposite of the [`intern`](fn.intern.html) function. /// /// If the [`intern`](fn.intern.html) function is called again then it will re-intern the string. #[allow(unused_variables)] #[inline] pub fn unintern(s: &str) { #[cfg(feature = "enable-interning")] unintern_str(s); } wasm-bindgen-0.2.87/src/cache/mod.rs000064400000000000000000000000201046102023000152440ustar 00000000000000pub mod intern; wasm-bindgen-0.2.87/src/cast.rs000064400000000000000000000140141046102023000143640ustar 00000000000000use crate::{describe::WasmDescribe, JsValue}; /// A trait for checked and unchecked casting between JS types. /// /// Specified [in an RFC][rfc] this trait is intended to provide support for /// casting JS values between different types of one another. In JS there aren't /// many static types but we've ascribed JS values with static types in Rust, /// yet they often need to be switched to other types temporarily! This trait /// provides both checked and unchecked casting into various kinds of values. /// /// This trait is automatically implemented for any type imported in a /// `#[wasm_bindgen]` `extern` block. /// /// [rfc]: https://github.com/rustwasm/rfcs/blob/master/text/002-wasm-bindgen-inheritance-casting.md pub trait JsCast where Self: AsRef + Into, { /// Test whether this JS value has a type `T`. /// /// This method will dynamically check to see if this JS object can be /// casted to the JS object of type `T`. Usually this uses the `instanceof` /// operator. This also works with primitive types like /// booleans/strings/numbers as well as cross-realm object like `Array` /// which can originate from other iframes. /// /// In general this is intended to be a more robust version of /// `is_instance_of`, but if you want strictly the `instanceof` operator /// it's recommended to use that instead. fn has_type(&self) -> bool where T: JsCast, { T::is_type_of(self.as_ref()) } /// Performs a dynamic cast (checked at runtime) of this value into the /// target type `T`. /// /// This method will return `Err(self)` if `self.has_type::()` /// returns `false`, and otherwise it will return `Ok(T)` manufactured with /// an unchecked cast (verified correct via the `has_type` operation). fn dyn_into(self) -> Result where T: JsCast, { if self.has_type::() { Ok(self.unchecked_into()) } else { Err(self) } } /// Performs a dynamic cast (checked at runtime) of this value into the /// target type `T`. /// /// This method will return `None` if `self.has_type::()` /// returns `false`, and otherwise it will return `Some(&T)` manufactured /// with an unchecked cast (verified correct via the `has_type` operation). fn dyn_ref(&self) -> Option<&T> where T: JsCast, { if self.has_type::() { Some(self.unchecked_ref()) } else { None } } /// Performs a zero-cost unchecked cast into the specified type. /// /// This method will convert the `self` value to the type `T`, where both /// `self` and `T` are simple wrappers around `JsValue`. This method **does /// not check whether `self` is an instance of `T`**. If used incorrectly /// then this method may cause runtime exceptions in both Rust and JS, this /// should be used with caution. fn unchecked_into(self) -> T where T: JsCast, { T::unchecked_from_js(self.into()) } /// Performs a zero-cost unchecked cast into a reference to the specified /// type. /// /// This method will convert the `self` value to the type `T`, where both /// `self` and `T` are simple wrappers around `JsValue`. This method **does /// not check whether `self` is an instance of `T`**. If used incorrectly /// then this method may cause runtime exceptions in both Rust and JS, this /// should be used with caution. /// /// This method, unlike `unchecked_into`, does not consume ownership of /// `self` and instead works over a shared reference. fn unchecked_ref(&self) -> &T where T: JsCast, { T::unchecked_from_js_ref(self.as_ref()) } /// Test whether this JS value is an instance of the type `T`. /// /// This method performs a dynamic check (at runtime) using the JS /// `instanceof` operator. This method returns `self instanceof T`. /// /// Note that `instanceof` does not always work with primitive values or /// across different realms (e.g. iframes). If you're not sure whether you /// specifically need only `instanceof` it's recommended to use `has_type` /// instead. fn is_instance_of(&self) -> bool where T: JsCast, { T::instanceof(self.as_ref()) } /// Performs a dynamic `instanceof` check to see whether the `JsValue` /// provided is an instance of this type. /// /// This is intended to be an internal implementation detail, you likely /// won't need to call this. It's generally called through the /// `is_instance_of` method instead. fn instanceof(val: &JsValue) -> bool; /// Performs a dynamic check to see whether the `JsValue` provided /// is a value of this type. /// /// Unlike `instanceof`, this can be specialised to use a custom check by /// adding a `#[wasm_bindgen(is_type_of = callback)]` attribute to the /// type import declaration. /// /// Other than that, this is intended to be an internal implementation /// detail of `has_type` and you likely won't need to call this. fn is_type_of(val: &JsValue) -> bool { Self::instanceof(val) } /// Performs a zero-cost unchecked conversion from a `JsValue` into an /// instance of `Self` /// /// This is intended to be an internal implementation detail, you likely /// won't need to call this. fn unchecked_from_js(val: JsValue) -> Self; /// Performs a zero-cost unchecked conversion from a `&JsValue` into an /// instance of `&Self`. /// /// Note the safety of this method, which basically means that `Self` must /// be a newtype wrapper around `JsValue`. /// /// This is intended to be an internal implementation detail, you likely /// won't need to call this. fn unchecked_from_js_ref(val: &JsValue) -> &Self; } /// Trait implemented for wrappers around `JsValue`s generated by `#[wasm_bindgen]`. #[doc(hidden)] pub trait JsObject: JsCast + WasmDescribe {} wasm-bindgen-0.2.87/src/closure.rs000064400000000000000000000735611046102023000151220ustar 00000000000000//! Support for long-lived closures in `wasm-bindgen` //! //! This module defines the `Closure` type which is used to pass "owned //! closures" from Rust to JS. Some more details can be found on the `Closure` //! type itself. #![allow(clippy::fn_to_numeric_cast)] use std::fmt; use std::mem::{self, ManuallyDrop}; use std::prelude::v1::*; use crate::convert::*; use crate::describe::*; use crate::throw_str; use crate::JsValue; use crate::UnwrapThrowExt; /// A handle to both a closure in Rust as well as JS closure which will invoke /// the Rust closure. /// /// A `Closure` is the primary way that a `'static` lifetime closure is /// transferred from Rust to JS. `Closure` currently requires that the closures /// it's created with have the `'static` lifetime in Rust for soundness reasons. /// /// This type is a "handle" in the sense that whenever it is dropped it will /// invalidate the JS closure that it refers to. Any usage of the closure in JS /// after the `Closure` has been dropped will raise an exception. It's then up /// to you to arrange for `Closure` to be properly deallocate at an appropriate /// location in your program. /// /// The type parameter on `Closure` is the type of closure that this represents. /// Currently this can only be the `Fn` and `FnMut` traits with up to 7 /// arguments (and an optional return value). /// /// # Examples /// /// Here are a number of examples of using `Closure`. /// /// ## Using the `setInterval` API /// /// Sample usage of `Closure` to invoke the `setInterval` API. /// /// ```rust,no_run /// use wasm_bindgen::prelude::*; /// /// #[wasm_bindgen] /// extern "C" { /// fn setInterval(closure: &Closure, time: u32) -> i32; /// fn clearInterval(id: i32); /// /// #[wasm_bindgen(js_namespace = console)] /// fn log(s: &str); /// } /// /// #[wasm_bindgen] /// pub struct IntervalHandle { /// interval_id: i32, /// _closure: Closure, /// } /// /// impl Drop for IntervalHandle { /// fn drop(&mut self) { /// clearInterval(self.interval_id); /// } /// } /// /// #[wasm_bindgen] /// pub fn run() -> IntervalHandle { /// // First up we use `Closure::new` to wrap up a Rust closure and create /// // a JS closure. /// let cb = Closure::new(|| { /// log("interval elapsed!"); /// }); /// /// // Next we pass this via reference to the `setInterval` function, and /// // `setInterval` gets a handle to the corresponding JS closure. /// let interval_id = setInterval(&cb, 1_000); /// /// // If we were to drop `cb` here it would cause an exception to be raised /// // whenever the interval elapses. Instead we *return* our handle back to JS /// // so JS can decide when to cancel the interval and deallocate the closure. /// IntervalHandle { /// interval_id, /// _closure: cb, /// } /// } /// ``` /// /// ## Casting a `Closure` to a `js_sys::Function` /// /// This is the same `setInterval` example as above, except it is using /// `web_sys` (which uses `js_sys::Function` for callbacks) instead of manually /// writing bindings to `setInterval` and other Web APIs. /// /// ```rust,ignore /// use wasm_bindgen::JsCast; /// /// #[wasm_bindgen] /// pub struct IntervalHandle { /// interval_id: i32, /// _closure: Closure, /// } /// /// impl Drop for IntervalHandle { /// fn drop(&mut self) { /// let window = web_sys::window().unwrap(); /// window.clear_interval_with_handle(self.interval_id); /// } /// } /// /// #[wasm_bindgen] /// pub fn run() -> Result { /// let cb = Closure::new(|| { /// web_sys::console::log_1(&"interval elapsed!".into()); /// }); /// /// let window = web_sys::window().unwrap(); /// let interval_id = window.set_interval_with_callback_and_timeout_and_arguments_0( /// // Note this method call, which uses `as_ref()` to get a `JsValue` /// // from our `Closure` which is then converted to a `&Function` /// // using the `JsCast::unchecked_ref` function. /// cb.as_ref().unchecked_ref(), /// 1_000, /// )?; /// /// // Same as above. /// Ok(IntervalHandle { /// interval_id, /// _closure: cb, /// }) /// } /// ``` /// /// ## Using `FnOnce` and `Closure::once` with `requestAnimationFrame` /// /// Because `requestAnimationFrame` only calls its callback once, we can use /// `FnOnce` and `Closure::once` with it. /// /// ```rust,no_run /// use wasm_bindgen::prelude::*; /// /// #[wasm_bindgen] /// extern "C" { /// fn requestAnimationFrame(closure: &Closure) -> u32; /// fn cancelAnimationFrame(id: u32); /// /// #[wasm_bindgen(js_namespace = console)] /// fn log(s: &str); /// } /// /// #[wasm_bindgen] /// pub struct AnimationFrameHandle { /// animation_id: u32, /// _closure: Closure, /// } /// /// impl Drop for AnimationFrameHandle { /// fn drop(&mut self) { /// cancelAnimationFrame(self.animation_id); /// } /// } /// /// // A type that will log a message when it is dropped. /// struct LogOnDrop(&'static str); /// impl Drop for LogOnDrop { /// fn drop(&mut self) { /// log(self.0); /// } /// } /// /// #[wasm_bindgen] /// pub fn run() -> AnimationFrameHandle { /// // We are using `Closure::once` which takes a `FnOnce`, so the function /// // can drop and/or move things that it closes over. /// let fired = LogOnDrop("animation frame fired or canceled"); /// let cb = Closure::once(move || drop(fired)); /// /// // Schedule the animation frame! /// let animation_id = requestAnimationFrame(&cb); /// /// // Again, return a handle to JS, so that the closure is not dropped /// // immediately and JS can decide whether to cancel the animation frame. /// AnimationFrameHandle { /// animation_id, /// _closure: cb, /// } /// } /// ``` /// /// ## Converting `FnOnce`s directly into JavaScript Functions with `Closure::once_into_js` /// /// If we don't want to allow a `FnOnce` to be eagerly dropped (maybe because we /// just want it to drop after it is called and don't care about cancellation) /// then we can use the `Closure::once_into_js` function. /// /// This is the same `requestAnimationFrame` example as above, but without /// supporting early cancellation. /// /// ``` /// use wasm_bindgen::prelude::*; /// /// #[wasm_bindgen] /// extern "C" { /// // We modify the binding to take an untyped `JsValue` since that is what /// // is returned by `Closure::once_into_js`. /// // /// // If we were using the `web_sys` binding for `requestAnimationFrame`, /// // then the call sites would cast the `JsValue` into a `&js_sys::Function` /// // using `f.unchecked_ref::()`. See the `web_sys` /// // example above for details. /// fn requestAnimationFrame(callback: JsValue); /// /// #[wasm_bindgen(js_namespace = console)] /// fn log(s: &str); /// } /// /// // A type that will log a message when it is dropped. /// struct LogOnDrop(&'static str); /// impl Drop for LogOnDrop { /// fn drop(&mut self) { /// log(self.0); /// } /// } /// /// #[wasm_bindgen] /// pub fn run() { /// // We are using `Closure::once_into_js` which takes a `FnOnce` and /// // converts it into a JavaScript function, which is returned as a /// // `JsValue`. /// let fired = LogOnDrop("animation frame fired"); /// let cb = Closure::once_into_js(move || drop(fired)); /// /// // Schedule the animation frame! /// requestAnimationFrame(cb); /// /// // No need to worry about whether or not we drop a `Closure` /// // here or return some sort of handle to JS! /// } /// ``` pub struct Closure { js: ManuallyDrop, data: ManuallyDrop>, } union FatPtr { ptr: *mut T, fields: (usize, usize), } impl Closure where T: ?Sized + WasmClosure, { /// Creates a new instance of `Closure` from the provided Rust function. /// /// Note that the closure provided here, `F`, has a few requirements /// associated with it: /// /// * It must implement `Fn` or `FnMut` (for `FnOnce` functions see /// `Closure::once` and `Closure::once_into_js`). /// /// * It must be `'static`, aka no stack references (use the `move` /// keyword). /// /// * It can have at most 7 arguments. /// /// * Its arguments and return values are all types that can be shared with /// JS (i.e. have `#[wasm_bindgen]` annotations or are simple numbers, /// etc.) pub fn new(t: F) -> Closure where F: IntoWasmClosure + 'static, { Closure::wrap(Box::new(t).unsize()) } /// A more direct version of `Closure::new` which creates a `Closure` from /// a `Box`/`Box`, which is how it's kept internally. pub fn wrap(mut data: Box) -> Closure { assert_eq!(mem::size_of::<*const T>(), mem::size_of::>()); let (a, b) = unsafe { FatPtr { ptr: &mut *data as *mut T, } .fields }; // Here we need to create a `JsValue` with the data and `T::invoke()` // function pointer. To do that we... take a few unconventional turns. // In essence what happens here is this: // // 1. First up, below we call a function, `breaks_if_inlined`. This // function, as the name implies, does not work if it's inlined. // More on that in a moment. // 2. This function internally calls a special import recognized by the // `wasm-bindgen` CLI tool, `__wbindgen_describe_closure`. This // imported symbol is similar to `__wbindgen_describe` in that it's // not intended to show up in the final binary but it's an // intermediate state for a `wasm-bindgen` binary. // 3. The `__wbindgen_describe_closure` import is namely passed a // descriptor function, monomorphized for each invocation. // // Most of this doesn't actually make sense to happen at runtime! The // real magic happens when `wasm-bindgen` comes along and updates our // generated code. When `wasm-bindgen` runs it performs a few tasks: // // * First, it finds all functions that call // `__wbindgen_describe_closure`. These are all `breaks_if_inlined` // defined below as the symbol isn't called anywhere else. // * Next, `wasm-bindgen` executes the `breaks_if_inlined` // monomorphized functions, passing it dummy arguments. This will // execute the function just enough to invoke the special import, // namely telling us about the function pointer that is the describe // shim. // * This knowledge is then used to actually find the descriptor in the // function table which is then executed to figure out the signature // of the closure. // * Finally, and probably most heinously, the call to // `breaks_if_inlined` is rewritten to call an otherwise globally // imported function. This globally imported function will generate // the `JsValue` for this closure specialized for the signature in // question. // // Later on `wasm-gc` will clean up all the dead code and ensure that // we don't actually call `__wbindgen_describe_closure` at runtime. This // means we will end up not actually calling `breaks_if_inlined` in the // final binary, all calls to that function should be pruned. // // See crates/cli-support/src/js/closures.rs for a more information // about what's going on here. extern "C" fn describe() { inform(CLOSURE); T::describe() } #[inline(never)] unsafe fn breaks_if_inlined(a: usize, b: usize) -> u32 { super::__wbindgen_describe_closure(a as u32, b as u32, describe:: as u32) } let idx = unsafe { breaks_if_inlined::(a, b) }; Closure { js: ManuallyDrop::new(JsValue::_new(idx)), data: ManuallyDrop::new(data), } } /// Release memory management of this closure from Rust to the JS GC. /// /// When a `Closure` is dropped it will release the Rust memory and /// invalidate the associated JS closure, but this isn't always desired. /// Some callbacks are alive for the entire duration of the program or for a /// lifetime dynamically managed by the JS GC. This function can be used /// to drop this `Closure` while keeping the associated JS function still /// valid. /// /// By default this function will leak memory. This can be dangerous if this /// function is called many times in an application because the memory leak /// will overwhelm the page quickly and crash the wasm. /// /// If the browser, however, supports weak references, then this function /// will not leak memory. Instead the Rust memory will be reclaimed when the /// JS closure is GC'd. Weak references are not enabled by default since /// they're still a proposal for the JS standard. They can be enabled with /// `WASM_BINDGEN_WEAKREF=1` when running `wasm-bindgen`, however. pub fn into_js_value(self) -> JsValue { let idx = self.js.idx; mem::forget(self); JsValue::_new(idx) } /// Same as `into_js_value`, but doesn't return a value. pub fn forget(self) { drop(self.into_js_value()); } } // NB: we use a specific `T` for this `Closure` impl block to avoid every // call site having to provide an explicit, turbo-fished type like // `Closure::::once(...)`. impl Closure { /// Create a `Closure` from a function that can only be called once. /// /// Since we have no way of enforcing that JS cannot attempt to call this /// `FnOne(A...) -> R` more than once, this produces a `Closure R>` that will dynamically throw a JavaScript error if called more /// than once. /// /// # Example /// /// ```rust,no_run /// use wasm_bindgen::prelude::*; /// /// // Create an non-`Copy`, owned `String`. /// let mut s = String::from("Hello"); /// /// // Close over `s`. Since `f` returns `s`, it is `FnOnce` and can only be /// // called once. If it was called a second time, it wouldn't have any `s` /// // to work with anymore! /// let f = move || { /// s += ", World!"; /// s /// }; /// /// // Create a `Closure` from `f`. Note that the `Closure`'s type parameter /// // is `FnMut`, even though `f` is `FnOnce`. /// let closure: Closure String> = Closure::once(f); /// ``` pub fn once(fn_once: F) -> Closure where F: 'static + WasmClosureFnOnce, { Closure::wrap(fn_once.into_fn_mut()) } /// Convert a `FnOnce(A...) -> R` into a JavaScript `Function` object. /// /// If the JavaScript function is invoked more than once, it will throw an /// exception. /// /// Unlike `Closure::once`, this does *not* return a `Closure` that can be /// dropped before the function is invoked to deallocate the closure. The /// only way the `FnOnce` is deallocated is by calling the JavaScript /// function. If the JavaScript function is never called then the `FnOnce` /// and everything it closes over will leak. /// /// ```rust,ignore /// use wasm_bindgen::{prelude::*, JsCast}; /// /// let f = Closure::once_into_js(move || { /// // ... /// }); /// /// assert!(f.is_instance_of::()); /// ``` pub fn once_into_js(fn_once: F) -> JsValue where F: 'static + WasmClosureFnOnce, { fn_once.into_js_function() } } /// A trait for converting an `FnOnce(A...) -> R` into a `FnMut(A...) -> R` that /// will throw if ever called more than once. #[doc(hidden)] pub trait WasmClosureFnOnce: 'static { type FnMut: ?Sized + 'static + WasmClosure; fn into_fn_mut(self) -> Box; fn into_js_function(self) -> JsValue; } impl AsRef for Closure { fn as_ref(&self) -> &JsValue { &self.js } } impl WasmDescribe for Closure where T: WasmClosure + ?Sized, { fn describe() { inform(EXTERNREF); } } // `Closure` can only be passed by reference to imports. impl<'a, T> IntoWasmAbi for &'a Closure where T: WasmClosure + ?Sized, { type Abi = u32; fn into_abi(self) -> u32 { (&*self.js).into_abi() } } impl<'a, T> OptionIntoWasmAbi for &'a Closure where T: WasmClosure + ?Sized, { fn none() -> Self::Abi { 0 } } fn _check() { fn _assert() {} _assert::<&Closure>(); _assert::<&Closure>(); _assert::<&Closure String>>(); _assert::<&Closure>(); _assert::<&Closure>(); _assert::<&Closure String>>(); } impl fmt::Debug for Closure where T: ?Sized, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Closure {{ ... }}") } } impl Drop for Closure where T: ?Sized, { fn drop(&mut self) { unsafe { // this will implicitly drop our strong reference in addition to // invalidating all future invocations of the closure if super::__wbindgen_cb_drop(self.js.idx) != 0 { ManuallyDrop::drop(&mut self.data); } } } } /// An internal trait for the `Closure` type. /// /// This trait is not stable and it's not recommended to use this in bounds or /// implement yourself. #[doc(hidden)] pub unsafe trait WasmClosure { fn describe(); } /// An internal trait for the `Closure` type. /// /// This trait is not stable and it's not recommended to use this in bounds or /// implement yourself. #[doc(hidden)] pub trait IntoWasmClosure { fn unsize(self: Box) -> Box; } // The memory safety here in these implementations below is a bit tricky. We // want to be able to drop the `Closure` object from within the invocation of a // `Closure` for cases like promises. That means that while it's running we // might drop the `Closure`, but that shouldn't invalidate the environment yet. // // Instead what we do is to wrap closures in `Rc` variables. The main `Closure` // has a strong reference count which keeps the trait object alive. Each // invocation of a closure then *also* clones this and gets a new reference // count. When the closure returns it will release the reference count. // // This means that if the main `Closure` is dropped while it's being invoked // then destruction is deferred until execution returns. Otherwise it'll // deallocate data immediately. macro_rules! doit { ($( ($($var:ident)*) )*) => ($( unsafe impl<$($var,)* R> WasmClosure for dyn Fn($($var),*) -> R + 'static where $($var: FromWasmAbi + 'static,)* R: ReturnWasmAbi + 'static, { fn describe() { #[allow(non_snake_case)] unsafe extern "C" fn invoke<$($var: FromWasmAbi,)* R: ReturnWasmAbi>( a: usize, b: usize, $($var: <$var as FromWasmAbi>::Abi),* ) -> ::Abi { if a == 0 { throw_str("closure invoked after being dropped"); } // Make sure all stack variables are converted before we // convert `ret` as it may throw (for `Result`, for // example) let ret = { let f: *const dyn Fn($($var),*) -> R = FatPtr { fields: (a, b) }.ptr; $( let $var = <$var as FromWasmAbi>::from_abi($var); )* (*f)($($var),*) }; ret.return_abi() } inform(invoke::<$($var,)* R> as u32); unsafe extern fn destroy<$($var: FromWasmAbi,)* R: ReturnWasmAbi>( a: usize, b: usize, ) { // This can be called by the JS glue in erroneous situations // such as when the closure has already been destroyed. If // that's the case let's not make things worse by // segfaulting and/or asserting, so just ignore null // pointers. if a == 0 { return; } drop(Box::from_raw(FatPtr:: R> { fields: (a, b) }.ptr)); } inform(destroy::<$($var,)* R> as u32); <&Self>::describe(); } } unsafe impl<$($var,)* R> WasmClosure for dyn FnMut($($var),*) -> R + 'static where $($var: FromWasmAbi + 'static,)* R: ReturnWasmAbi + 'static, { fn describe() { #[allow(non_snake_case)] unsafe extern "C" fn invoke<$($var: FromWasmAbi,)* R: ReturnWasmAbi>( a: usize, b: usize, $($var: <$var as FromWasmAbi>::Abi),* ) -> ::Abi { if a == 0 { throw_str("closure invoked recursively or after being dropped"); } // Make sure all stack variables are converted before we // convert `ret` as it may throw (for `Result`, for // example) let ret = { let f: *const dyn FnMut($($var),*) -> R = FatPtr { fields: (a, b) }.ptr; let f = f as *mut dyn FnMut($($var),*) -> R; $( let $var = <$var as FromWasmAbi>::from_abi($var); )* (*f)($($var),*) }; ret.return_abi() } inform(invoke::<$($var,)* R> as u32); unsafe extern fn destroy<$($var: FromWasmAbi,)* R: ReturnWasmAbi>( a: usize, b: usize, ) { // See `Fn()` above for why we simply return if a == 0 { return; } drop(Box::from_raw(FatPtr:: R> { fields: (a, b) }.ptr)); } inform(destroy::<$($var,)* R> as u32); <&mut Self>::describe(); } } #[allow(non_snake_case, unused_parens)] impl WasmClosureFnOnce<($($var),*), R> for T where T: 'static + FnOnce($($var),*) -> R, $($var: FromWasmAbi + 'static,)* R: ReturnWasmAbi + 'static { type FnMut = dyn FnMut($($var),*) -> R; fn into_fn_mut(self) -> Box { let mut me = Some(self); Box::new(move |$($var),*| { let me = me.take().expect_throw("FnOnce called more than once"); me($($var),*) }) } fn into_js_function(self) -> JsValue { use std::rc::Rc; use crate::__rt::WasmRefCell; let mut me = Some(self); let rc1 = Rc::new(WasmRefCell::new(None)); let rc2 = rc1.clone(); let closure = Closure::wrap(Box::new(move |$($var),*| { // Invoke ourself and get the result. let me = me.take().expect_throw("FnOnce called more than once"); let result = me($($var),*); // And then drop the `Rc` holding this function's `Closure` // alive. debug_assert_eq!(Rc::strong_count(&rc2), 1); let option_closure = rc2.borrow_mut().take(); debug_assert!(option_closure.is_some()); drop(option_closure); result }) as Box R>); let js_val = closure.as_ref().clone(); *rc1.borrow_mut() = Some(closure); debug_assert_eq!(Rc::strong_count(&rc1), 2); drop(rc1); js_val } } impl IntoWasmClosure R> for T where T: 'static + FnMut($($var),*) -> R, $($var: FromWasmAbi + 'static,)* R: ReturnWasmAbi + 'static, { fn unsize(self: Box) -> Box R> { self } } impl IntoWasmClosure R> for T where T: 'static + Fn($($var),*) -> R, $($var: FromWasmAbi + 'static,)* R: ReturnWasmAbi + 'static, { fn unsize(self: Box) -> Box R> { self } } )*) } doit! { () (A) (A B) (A B C) (A B C D) (A B C D E) (A B C D E F) (A B C D E F G) (A B C D E F G H) } // Copy the above impls down here for where there's only one argument and it's a // reference. We could add more impls for more kinds of references, but it // becomes a combinatorial explosion quickly. Let's see how far we can get with // just this one! Maybe someone else can figure out voodoo so we don't have to // duplicate. unsafe impl WasmClosure for dyn Fn(&A) -> R where A: RefFromWasmAbi, R: ReturnWasmAbi + 'static, { fn describe() { #[allow(non_snake_case)] unsafe extern "C" fn invoke( a: usize, b: usize, arg: ::Abi, ) -> ::Abi { if a == 0 { throw_str("closure invoked after being dropped"); } // Make sure all stack variables are converted before we // convert `ret` as it may throw (for `Result`, for // example) let ret = { let f: *const dyn Fn(&A) -> R = FatPtr { fields: (a, b) }.ptr; let arg = ::ref_from_abi(arg); (*f)(&*arg) }; ret.return_abi() } inform(invoke:: as u32); unsafe extern "C" fn destroy(a: usize, b: usize) { // See `Fn()` above for why we simply return if a == 0 { return; } drop(Box::from_raw( FatPtr:: R> { fields: (a, b) }.ptr, )); } inform(destroy:: as u32); <&Self>::describe(); } } unsafe impl WasmClosure for dyn FnMut(&A) -> R where A: RefFromWasmAbi, R: ReturnWasmAbi + 'static, { fn describe() { #[allow(non_snake_case)] unsafe extern "C" fn invoke( a: usize, b: usize, arg: ::Abi, ) -> ::Abi { if a == 0 { throw_str("closure invoked recursively or after being dropped"); } // Make sure all stack variables are converted before we // convert `ret` as it may throw (for `Result`, for // example) let ret = { let f: *const dyn FnMut(&A) -> R = FatPtr { fields: (a, b) }.ptr; let f = f as *mut dyn FnMut(&A) -> R; let arg = ::ref_from_abi(arg); (*f)(&*arg) }; ret.return_abi() } inform(invoke:: as u32); unsafe extern "C" fn destroy(a: usize, b: usize) { // See `Fn()` above for why we simply return if a == 0 { return; } drop(Box::from_raw( FatPtr:: R> { fields: (a, b) }.ptr, )); } inform(destroy:: as u32); <&mut Self>::describe(); } } #[allow(non_snake_case)] impl WasmClosureFnOnce<(&A,), R> for T where T: 'static + FnOnce(&A) -> R, A: RefFromWasmAbi + 'static, R: ReturnWasmAbi + 'static, { type FnMut = dyn FnMut(&A) -> R; fn into_fn_mut(self) -> Box { let mut me = Some(self); Box::new(move |arg| { let me = me.take().expect_throw("FnOnce called more than once"); me(arg) }) } fn into_js_function(self) -> JsValue { use crate::__rt::WasmRefCell; use std::rc::Rc; let mut me = Some(self); let rc1 = Rc::new(WasmRefCell::new(None)); let rc2 = rc1.clone(); let closure = Closure::wrap(Box::new(move |arg: &A| { // Invoke ourself and get the result. let me = me.take().expect_throw("FnOnce called more than once"); let result = me(arg); // And then drop the `Rc` holding this function's `Closure` // alive. debug_assert_eq!(Rc::strong_count(&rc2), 1); let option_closure = rc2.borrow_mut().take(); debug_assert!(option_closure.is_some()); drop(option_closure); result }) as Box R>); let js_val = closure.as_ref().clone(); *rc1.borrow_mut() = Some(closure); debug_assert_eq!(Rc::strong_count(&rc1), 2); drop(rc1); js_val } } wasm-bindgen-0.2.87/src/convert/closures.rs000064400000000000000000000153251046102023000167570ustar 00000000000000#![allow(clippy::fn_to_numeric_cast)] use core::mem; use crate::convert::slices::WasmSlice; use crate::convert::RefFromWasmAbi; use crate::convert::{FromWasmAbi, IntoWasmAbi, ReturnWasmAbi}; use crate::describe::{inform, WasmDescribe, FUNCTION}; use crate::throw_str; macro_rules! stack_closures { ($( ($cnt:tt $invoke:ident $invoke_mut:ident $($var:ident)*) )*) => ($( impl<'a, 'b, $($var,)* R> IntoWasmAbi for &'a (dyn Fn($($var),*) -> R + 'b) where $($var: FromWasmAbi,)* R: ReturnWasmAbi { type Abi = WasmSlice; fn into_abi(self) -> WasmSlice { unsafe { let (a, b): (usize, usize) = mem::transmute(self); WasmSlice { ptr: a as u32, len: b as u32 } } } } #[allow(non_snake_case)] unsafe extern "C" fn $invoke<$($var: FromWasmAbi,)* R: ReturnWasmAbi>( a: usize, b: usize, $($var: <$var as FromWasmAbi>::Abi),* ) -> ::Abi { if a == 0 { throw_str("closure invoked after being dropped"); } // Scope all local variables before we call `return_abi` to // ensure they're all destroyed as `return_abi` may throw let ret = { let f: &dyn Fn($($var),*) -> R = mem::transmute((a, b)); $( let $var = <$var as FromWasmAbi>::from_abi($var); )* f($($var),*) }; ret.return_abi() } impl<'a, $($var,)* R> WasmDescribe for dyn Fn($($var),*) -> R + 'a where $($var: FromWasmAbi,)* R: ReturnWasmAbi { fn describe() { inform(FUNCTION); inform($invoke::<$($var,)* R> as u32); inform($cnt); $(<$var as WasmDescribe>::describe();)* ::describe(); ::describe(); } } impl<'a, 'b, $($var,)* R> IntoWasmAbi for &'a mut (dyn FnMut($($var),*) -> R + 'b) where $($var: FromWasmAbi,)* R: ReturnWasmAbi { type Abi = WasmSlice; fn into_abi(self) -> WasmSlice { unsafe { let (a, b): (usize, usize) = mem::transmute(self); WasmSlice { ptr: a as u32, len: b as u32 } } } } #[allow(non_snake_case)] unsafe extern "C" fn $invoke_mut<$($var: FromWasmAbi,)* R: ReturnWasmAbi>( a: usize, b: usize, $($var: <$var as FromWasmAbi>::Abi),* ) -> ::Abi { if a == 0 { throw_str("closure invoked recursively or after being dropped"); } // Scope all local variables before we call `return_abi` to // ensure they're all destroyed as `return_abi` may throw let ret = { let f: &mut dyn FnMut($($var),*) -> R = mem::transmute((a, b)); $( let $var = <$var as FromWasmAbi>::from_abi($var); )* f($($var),*) }; ret.return_abi() } impl<'a, $($var,)* R> WasmDescribe for dyn FnMut($($var),*) -> R + 'a where $($var: FromWasmAbi,)* R: ReturnWasmAbi { fn describe() { inform(FUNCTION); inform($invoke_mut::<$($var,)* R> as u32); inform($cnt); $(<$var as WasmDescribe>::describe();)* ::describe(); ::describe(); } } )*) } stack_closures! { (0 invoke0 invoke0_mut) (1 invoke1 invoke1_mut A) (2 invoke2 invoke2_mut A B) (3 invoke3 invoke3_mut A B C) (4 invoke4 invoke4_mut A B C D) (5 invoke5 invoke5_mut A B C D E) (6 invoke6 invoke6_mut A B C D E F) (7 invoke7 invoke7_mut A B C D E F G) (8 invoke8 invoke8_mut A B C D E F G H) } impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn Fn(&A) -> R + 'b) where A: RefFromWasmAbi, R: ReturnWasmAbi, { type Abi = WasmSlice; fn into_abi(self) -> WasmSlice { unsafe { let (a, b): (usize, usize) = mem::transmute(self); WasmSlice { ptr: a as u32, len: b as u32, } } } } #[allow(non_snake_case)] unsafe extern "C" fn invoke1_ref( a: usize, b: usize, arg: ::Abi, ) -> ::Abi { if a == 0 { throw_str("closure invoked after being dropped"); } // Scope all local variables before we call `return_abi` to // ensure they're all destroyed as `return_abi` may throw let ret = { let f: &dyn Fn(&A) -> R = mem::transmute((a, b)); let arg = ::ref_from_abi(arg); f(&*arg) }; ret.return_abi() } impl<'a, A, R> WasmDescribe for dyn Fn(&A) -> R + 'a where A: RefFromWasmAbi, R: ReturnWasmAbi, { fn describe() { inform(FUNCTION); inform(invoke1_ref:: as u32); inform(1); <&A as WasmDescribe>::describe(); ::describe(); ::describe(); } } impl<'a, 'b, A, R> IntoWasmAbi for &'a mut (dyn FnMut(&A) -> R + 'b) where A: RefFromWasmAbi, R: ReturnWasmAbi, { type Abi = WasmSlice; fn into_abi(self) -> WasmSlice { unsafe { let (a, b): (usize, usize) = mem::transmute(self); WasmSlice { ptr: a as u32, len: b as u32, } } } } #[allow(non_snake_case)] unsafe extern "C" fn invoke1_mut_ref( a: usize, b: usize, arg: ::Abi, ) -> ::Abi { if a == 0 { throw_str("closure invoked recursively or after being dropped"); } // Scope all local variables before we call `return_abi` to // ensure they're all destroyed as `return_abi` may throw let ret = { let f: &mut dyn FnMut(&A) -> R = mem::transmute((a, b)); let arg = ::ref_from_abi(arg); f(&*arg) }; ret.return_abi() } impl<'a, A, R> WasmDescribe for dyn FnMut(&A) -> R + 'a where A: RefFromWasmAbi, R: ReturnWasmAbi, { fn describe() { inform(FUNCTION); inform(invoke1_mut_ref:: as u32); inform(1); <&A as WasmDescribe>::describe(); ::describe(); ::describe(); } } wasm-bindgen-0.2.87/src/convert/impls.rs000064400000000000000000000210251046102023000162360ustar 00000000000000use core::char; use core::mem::{self, ManuallyDrop}; use crate::convert::traits::WasmAbi; use crate::convert::{FromWasmAbi, IntoWasmAbi, LongRefFromWasmAbi, RefFromWasmAbi}; use crate::convert::{OptionFromWasmAbi, OptionIntoWasmAbi, ReturnWasmAbi}; use crate::{Clamped, JsError, JsValue}; unsafe impl WasmAbi for () {} #[repr(C, u32)] pub enum WasmOption { None, Some(T), } unsafe impl WasmAbi for WasmOption {} impl WasmOption { pub fn from_option>(option: Option) -> Self { match option { Some(v) => WasmOption::Some(v.into_abi()), None => WasmOption::None, } } pub unsafe fn into_option>(v: Self) -> Option { match v { WasmOption::Some(v) => Some(T::from_abi(v)), WasmOption::None => None, } } } macro_rules! type_wasm_native { ($($t:tt as $c:tt)*) => ($( impl IntoWasmAbi for $t { type Abi = $c; #[inline] fn into_abi(self) -> $c { self as $c } } impl FromWasmAbi for $t { type Abi = $c; #[inline] unsafe fn from_abi(js: $c) -> Self { js as $t } } impl IntoWasmAbi for Option<$t> { type Abi = WasmOption<$c>; #[inline] fn into_abi(self) -> Self::Abi { WasmOption::from_option(self.map(|v| v as $c)) } } impl FromWasmAbi for Option<$t> { type Abi = WasmOption<$c>; #[inline] unsafe fn from_abi(js: Self::Abi) -> Self { WasmOption::into_option(js).map(|v: $c| v as $t) } } )*) } type_wasm_native!( i32 as i32 isize as i32 u32 as u32 usize as u32 i64 as i64 u64 as u64 f32 as f32 f64 as f64 ); macro_rules! type_abi_as_u32 { ($($t:tt)*) => ($( impl IntoWasmAbi for $t { type Abi = u32; #[inline] fn into_abi(self) -> u32 { self as u32 } } impl FromWasmAbi for $t { type Abi = u32; #[inline] unsafe fn from_abi(js: u32) -> Self { js as $t } } impl OptionIntoWasmAbi for $t { #[inline] fn none() -> u32 { 0x00FF_FFFFu32 } } impl OptionFromWasmAbi for $t { #[inline] fn is_none(js: &u32) -> bool { *js == 0x00FF_FFFFu32 } } )*) } type_abi_as_u32!(i8 u8 i16 u16); impl IntoWasmAbi for bool { type Abi = u32; #[inline] fn into_abi(self) -> u32 { self as u32 } } impl FromWasmAbi for bool { type Abi = u32; #[inline] unsafe fn from_abi(js: u32) -> bool { js != 0 } } impl OptionIntoWasmAbi for bool { #[inline] fn none() -> u32 { 0x00FF_FFFFu32 } } impl OptionFromWasmAbi for bool { #[inline] fn is_none(js: &u32) -> bool { *js == 0x00FF_FFFFu32 } } impl IntoWasmAbi for char { type Abi = u32; #[inline] fn into_abi(self) -> u32 { self as u32 } } impl FromWasmAbi for char { type Abi = u32; #[inline] unsafe fn from_abi(js: u32) -> char { char::from_u32_unchecked(js) } } impl OptionIntoWasmAbi for char { #[inline] fn none() -> u32 { 0x00FF_FFFFu32 } } impl OptionFromWasmAbi for char { #[inline] fn is_none(js: &u32) -> bool { *js == 0x00FF_FFFFu32 } } impl IntoWasmAbi for *const T { type Abi = u32; #[inline] fn into_abi(self) -> u32 { self as u32 } } impl FromWasmAbi for *const T { type Abi = u32; #[inline] unsafe fn from_abi(js: u32) -> *const T { js as *const T } } impl IntoWasmAbi for *mut T { type Abi = u32; #[inline] fn into_abi(self) -> u32 { self as u32 } } impl FromWasmAbi for *mut T { type Abi = u32; #[inline] unsafe fn from_abi(js: u32) -> *mut T { js as *mut T } } impl IntoWasmAbi for JsValue { type Abi = u32; #[inline] fn into_abi(self) -> u32 { let ret = self.idx; mem::forget(self); ret } } impl FromWasmAbi for JsValue { type Abi = u32; #[inline] unsafe fn from_abi(js: u32) -> JsValue { JsValue::_new(js) } } impl<'a> IntoWasmAbi for &'a JsValue { type Abi = u32; #[inline] fn into_abi(self) -> u32 { self.idx } } impl RefFromWasmAbi for JsValue { type Abi = u32; type Anchor = ManuallyDrop; #[inline] unsafe fn ref_from_abi(js: u32) -> Self::Anchor { ManuallyDrop::new(JsValue::_new(js)) } } impl LongRefFromWasmAbi for JsValue { type Abi = u32; type Anchor = JsValue; #[inline] unsafe fn long_ref_from_abi(js: u32) -> Self::Anchor { Self::from_abi(js) } } impl IntoWasmAbi for Option { type Abi = T::Abi; #[inline] fn into_abi(self) -> T::Abi { match self { None => T::none(), Some(me) => me.into_abi(), } } } impl FromWasmAbi for Option { type Abi = T::Abi; #[inline] unsafe fn from_abi(js: T::Abi) -> Self { if T::is_none(&js) { None } else { Some(T::from_abi(js)) } } } impl IntoWasmAbi for Clamped { type Abi = T::Abi; #[inline] fn into_abi(self) -> Self::Abi { self.0.into_abi() } } impl FromWasmAbi for Clamped { type Abi = T::Abi; #[inline] unsafe fn from_abi(js: T::Abi) -> Self { Clamped(T::from_abi(js)) } } impl IntoWasmAbi for () { type Abi = (); #[inline] fn into_abi(self) { self } } /// This is an encoding of a Result. It can only store things that can be decoded by the JS /// bindings. /// /// At the moment, we do not write the exact struct packing layout of everything into the /// glue/descriptions of datatypes, so T cannot be arbitrary. The current requirements of the /// struct unpacker (StructUnpacker), which apply to ResultAbi as a whole, are as follows: /// /// - repr(C), of course /// - u32/i32/f32/f64 fields at the "leaf fields" of the "field tree" /// - layout equivalent to a completely flattened repr(C) struct, constructed by an in order /// traversal of all the leaf fields in it. /// /// This means that you can't embed struct A(u32, f64) as struct B(u32, A); because the "completely /// flattened" struct AB(u32, u32, f64) would miss the 4 byte padding that is actually present /// within B and then as a consequence also miss the 4 byte padding within A that repr(C) inserts. /// /// The enemy is padding. Padding is only required when there is an `f64` field. So the enemy is /// `f64` after anything else, particularly anything arbitrary. There is no smaller sized type, so /// we don't need to worry about 1-byte integers, etc. It's best, therefore, to place your f64s /// first in your structs, that's why we have `abi` first, although here it doesn't matter as the /// other two fields total 8 bytes anyway. /// #[repr(C)] pub struct ResultAbi { /// This field is the same size/align as `T`. abi: ResultAbiUnion, /// Order of args here is such that we can pop() the possible error first, deal with it and /// move on. Later fields are popped off the stack first. err: u32, is_err: u32, } #[repr(C)] pub union ResultAbiUnion { // ManuallyDrop is #[repr(transparent)] ok: std::mem::ManuallyDrop, err: (), } unsafe impl WasmAbi for ResultAbi {} unsafe impl WasmAbi for ResultAbiUnion {} impl> ReturnWasmAbi for Result { type Abi = ResultAbi; #[inline] fn return_abi(self) -> Self::Abi { match self { Ok(v) => { let abi = ResultAbiUnion { ok: std::mem::ManuallyDrop::new(v.into_abi()), }; ResultAbi { abi, is_err: 0, err: 0, } } Err(e) => { let jsval = e.into(); ResultAbi { abi: ResultAbiUnion { err: () }, is_err: 1, err: jsval.into_abi(), } } } } } impl IntoWasmAbi for JsError { type Abi = ::Abi; fn into_abi(self) -> Self::Abi { self.value.into_abi() } } wasm-bindgen-0.2.87/src/convert/mod.rs000064400000000000000000000003541046102023000156730ustar 00000000000000//! This is mostly an internal module, no stability guarantees are provided. Use //! at your own risk. mod closures; mod impls; mod slices; mod traits; pub use self::impls::*; pub use self::slices::WasmSlice; pub use self::traits::*; wasm-bindgen-0.2.87/src/convert/slices.rs000064400000000000000000000233401046102023000163760ustar 00000000000000#[cfg(feature = "std")] use std::prelude::v1::*; use core::ops::{Deref, DerefMut}; use core::str; use crate::__wbindgen_copy_to_typed_array; use crate::cast::JsObject; use crate::convert::OptionIntoWasmAbi; use crate::convert::{ FromWasmAbi, IntoWasmAbi, LongRefFromWasmAbi, RefFromWasmAbi, RefMutFromWasmAbi, WasmAbi, }; use cfg_if::cfg_if; if_std! { use core::mem; use crate::convert::OptionFromWasmAbi; } #[repr(C)] pub struct WasmSlice { pub ptr: u32, pub len: u32, } unsafe impl WasmAbi for WasmSlice {} #[inline] fn null_slice() -> WasmSlice { WasmSlice { ptr: 0, len: 0 } } if_std! { #[repr(C)] pub struct WasmMutSlice { pub slice: WasmSlice, pub idx: u32, } unsafe impl WasmAbi for WasmMutSlice {} /// The representation of a mutable slice passed from JS to Rust. pub struct MutSlice { /// A copy of the data in the JS typed array. contents: Box<[T]>, /// A reference to the original JS typed array. js: JsValue, } impl Drop for MutSlice { fn drop(&mut self) { unsafe { __wbindgen_copy_to_typed_array( self.contents.as_ptr() as *const u8, self.contents.len() * mem::size_of::(), self.js.idx ); } } } impl Deref for MutSlice { type Target = [T]; fn deref(&self) -> &[T] { &self.contents } } impl DerefMut for MutSlice { fn deref_mut(&mut self) -> &mut [T] { &mut self.contents } } } macro_rules! vectors { ($($t:ident)*) => ($( if_std! { impl IntoWasmAbi for Box<[$t]> { type Abi = WasmSlice; #[inline] fn into_abi(self) -> WasmSlice { let ptr = self.as_ptr(); let len = self.len(); mem::forget(self); WasmSlice { ptr: ptr.into_abi(), len: len as u32, } } } impl OptionIntoWasmAbi for Box<[$t]> { #[inline] fn none() -> WasmSlice { null_slice() } } impl FromWasmAbi for Box<[$t]> { type Abi = WasmSlice; #[inline] unsafe fn from_abi(js: WasmSlice) -> Self { let ptr = <*mut $t>::from_abi(js.ptr); let len = js.len as usize; Vec::from_raw_parts(ptr, len, len).into_boxed_slice() } } impl OptionFromWasmAbi for Box<[$t]> { #[inline] fn is_none(slice: &WasmSlice) -> bool { slice.ptr == 0 } } } impl<'a> IntoWasmAbi for &'a [$t] { type Abi = WasmSlice; #[inline] fn into_abi(self) -> WasmSlice { WasmSlice { ptr: self.as_ptr().into_abi(), len: self.len() as u32, } } } impl<'a> OptionIntoWasmAbi for &'a [$t] { #[inline] fn none() -> WasmSlice { null_slice() } } impl<'a> IntoWasmAbi for &'a mut [$t] { type Abi = WasmSlice; #[inline] fn into_abi(self) -> WasmSlice { (&*self).into_abi() } } impl<'a> OptionIntoWasmAbi for &'a mut [$t] { #[inline] fn none() -> WasmSlice { null_slice() } } impl RefFromWasmAbi for [$t] { type Abi = WasmSlice; type Anchor = Box<[$t]>; #[inline] unsafe fn ref_from_abi(js: WasmSlice) -> Box<[$t]> { >::from_abi(js) } } impl RefMutFromWasmAbi for [$t] { type Abi = WasmMutSlice; type Anchor = MutSlice<$t>; #[inline] unsafe fn ref_mut_from_abi(js: WasmMutSlice) -> MutSlice<$t> { let contents = >::from_abi(js.slice); let js = JsValue::from_abi(js.idx); MutSlice { contents, js } } } impl LongRefFromWasmAbi for [$t] { type Abi = WasmSlice; type Anchor = Box<[$t]>; #[inline] unsafe fn long_ref_from_abi(js: WasmSlice) -> Box<[$t]> { Self::ref_from_abi(js) } } )*) } vectors! { u8 i8 u16 i16 u32 i32 u64 i64 usize isize f32 f64 } cfg_if! { if #[cfg(feature = "enable-interning")] { #[inline] fn unsafe_get_cached_str(x: &str) -> Option { // This uses 0 for the ptr as an indication that it is a JsValue and not a str. crate::cache::intern::unsafe_get_str(x).map(|x| WasmSlice { ptr: 0, len: x }) } } else { #[inline] fn unsafe_get_cached_str(_x: &str) -> Option { None } } } if_std! { impl IntoWasmAbi for Vec where Box<[T]>: IntoWasmAbi { type Abi = as IntoWasmAbi>::Abi; #[inline] fn into_abi(self) -> Self::Abi { self.into_boxed_slice().into_abi() } } impl OptionIntoWasmAbi for Vec where Box<[T]>: IntoWasmAbi { #[inline] fn none() -> WasmSlice { null_slice() } } impl FromWasmAbi for Vec where Box<[T]>: FromWasmAbi { type Abi = as FromWasmAbi>::Abi; #[inline] unsafe fn from_abi(js: Self::Abi) -> Self { >::from_abi(js).into() } } impl OptionFromWasmAbi for Vec where Box<[T]>: FromWasmAbi { #[inline] fn is_none(abi: &WasmSlice) -> bool { abi.ptr == 0 } } impl IntoWasmAbi for String { type Abi = as IntoWasmAbi>::Abi; #[inline] fn into_abi(self) -> Self::Abi { // This is safe because the JsValue is immediately looked up in the heap and // then returned, so use-after-free cannot occur. unsafe_get_cached_str(&self).unwrap_or_else(|| self.into_bytes().into_abi()) } } impl OptionIntoWasmAbi for String { #[inline] fn none() -> Self::Abi { null_slice() } } impl FromWasmAbi for String { type Abi = as FromWasmAbi>::Abi; #[inline] unsafe fn from_abi(js: Self::Abi) -> Self { String::from_utf8_unchecked(>::from_abi(js)) } } impl OptionFromWasmAbi for String { #[inline] fn is_none(slice: &WasmSlice) -> bool { slice.ptr == 0 } } } impl<'a> IntoWasmAbi for &'a str { type Abi = <&'a [u8] as IntoWasmAbi>::Abi; #[inline] fn into_abi(self) -> Self::Abi { // This is safe because the JsValue is immediately looked up in the heap and // then returned, so use-after-free cannot occur. unsafe_get_cached_str(self).unwrap_or_else(|| self.as_bytes().into_abi()) } } impl<'a> OptionIntoWasmAbi for &'a str { #[inline] fn none() -> Self::Abi { null_slice() } } impl RefFromWasmAbi for str { type Abi = <[u8] as RefFromWasmAbi>::Abi; type Anchor = Box; #[inline] unsafe fn ref_from_abi(js: Self::Abi) -> Self::Anchor { mem::transmute::, Box>(>::from_abi(js)) } } impl LongRefFromWasmAbi for str { type Abi = <[u8] as RefFromWasmAbi>::Abi; type Anchor = Box; #[inline] unsafe fn long_ref_from_abi(js: Self::Abi) -> Self::Anchor { Self::ref_from_abi(js) } } if_std! { use crate::JsValue; impl IntoWasmAbi for Box<[JsValue]> { type Abi = WasmSlice; #[inline] fn into_abi(self) -> WasmSlice { let ptr = self.as_ptr(); let len = self.len(); mem::forget(self); WasmSlice { ptr: ptr.into_abi(), len: len as u32, } } } impl OptionIntoWasmAbi for Box<[JsValue]> { #[inline] fn none() -> WasmSlice { null_slice() } } impl FromWasmAbi for Box<[JsValue]> { type Abi = WasmSlice; #[inline] unsafe fn from_abi(js: WasmSlice) -> Self { let ptr = <*mut JsValue>::from_abi(js.ptr); let len = js.len as usize; Vec::from_raw_parts(ptr, len, len).into_boxed_slice() } } impl OptionFromWasmAbi for Box<[JsValue]> { #[inline] fn is_none(slice: &WasmSlice) -> bool { slice.ptr == 0 } } impl IntoWasmAbi for Box<[T]> where T: JsObject { type Abi = WasmSlice; #[inline] fn into_abi(self) -> WasmSlice { let ptr = self.as_ptr(); let len = self.len(); mem::forget(self); WasmSlice { ptr: ptr.into_abi(), len: len as u32, } } } impl OptionIntoWasmAbi for Box<[T]> where T: JsObject { #[inline] fn none() -> WasmSlice { null_slice() } } impl FromWasmAbi for Box<[T]> where T: JsObject { type Abi = WasmSlice; #[inline] unsafe fn from_abi(js: WasmSlice) -> Self { let ptr = <*mut JsValue>::from_abi(js.ptr); let len = js.len as usize; let vec: Vec = Vec::from_raw_parts(ptr, len, len).drain(..).map(|js_value| T::unchecked_from_js(js_value)).collect(); vec.into_boxed_slice() } } impl OptionFromWasmAbi for Box<[T]> where T: JsObject { #[inline] fn is_none(slice: &WasmSlice) -> bool { slice.ptr == 0 } } } wasm-bindgen-0.2.87/src/convert/traits.rs000064400000000000000000000132771046102023000164320ustar 00000000000000use core::borrow::Borrow; use core::ops::{Deref, DerefMut}; use crate::describe::*; /// A trait for anything that can be converted into a type that can cross the /// wasm ABI directly, eg `u32` or `f64`. /// /// This is the opposite operation as `FromWasmAbi` and `Ref[Mut]FromWasmAbi`. pub trait IntoWasmAbi: WasmDescribe { /// The wasm ABI type that this converts into when crossing the ABI /// boundary. type Abi: WasmAbi; /// Convert `self` into `Self::Abi` so that it can be sent across the wasm /// ABI boundary. fn into_abi(self) -> Self::Abi; } /// A trait for anything that can be recovered by-value from the wasm ABI /// boundary, eg a Rust `u8` can be recovered from the wasm ABI `u32` type. /// /// This is the by-value variant of the opposite operation as `IntoWasmAbi`. pub trait FromWasmAbi: WasmDescribe { /// The wasm ABI type that this converts from when coming back out from the /// ABI boundary. type Abi: WasmAbi; /// Recover a `Self` from `Self::Abi`. /// /// # Safety /// /// This is only safe to call when -- and implementations may assume that -- /// the supplied `Self::Abi` was previously generated by a call to `::into_abi()` or the moral equivalent in JS. unsafe fn from_abi(js: Self::Abi) -> Self; } /// A trait for anything that can be recovered as some sort of shared reference /// from the wasm ABI boundary. /// /// This is the shared reference variant of the opposite operation as /// `IntoWasmAbi`. pub trait RefFromWasmAbi: WasmDescribe { /// The wasm ABI type references to `Self` are recovered from. type Abi: WasmAbi; /// The type that holds the reference to `Self` for the duration of the /// invocation of the function that has an `&Self` parameter. This is /// required to ensure that the lifetimes don't persist beyond one function /// call, and so that they remain anonymous. type Anchor: Deref; /// Recover a `Self::Anchor` from `Self::Abi`. /// /// # Safety /// /// Same as `FromWasmAbi::from_abi`. unsafe fn ref_from_abi(js: Self::Abi) -> Self::Anchor; } /// A version of the `RefFromWasmAbi` trait with the additional requirement /// that the reference must remain valid as long as the anchor isn't dropped. /// /// This isn't the case for `JsValue`'s `RefFromWasmAbi` implementation. To /// avoid having to allocate a spot for the `JsValue` on the `JsValue` heap, /// the `JsValue` is instead pushed onto the `JsValue` stack, and popped off /// again after the function that the reference was passed to returns. So, /// `JsValue` has a different `LongRefFromWasmAbi` implementation that behaves /// the same as `FromWasmAbi`, putting the value on the heap. /// /// This is needed for async functions, where the reference needs to be valid /// for the whole length of the `Future`, rather than the initial synchronous /// call. /// /// 'long ref' is short for 'long-lived reference'. pub trait LongRefFromWasmAbi: WasmDescribe { /// Same as `RefFromWasmAbi::Abi` type Abi: WasmAbi; /// Same as `RefFromWasmAbi::Anchor` type Anchor: Borrow; /// Same as `RefFromWasmAbi::ref_from_abi` unsafe fn long_ref_from_abi(js: Self::Abi) -> Self::Anchor; } /// Dual of the `RefFromWasmAbi` trait, except for mutable references. pub trait RefMutFromWasmAbi: WasmDescribe { /// Same as `RefFromWasmAbi::Abi` type Abi: WasmAbi; /// Same as `RefFromWasmAbi::Anchor` type Anchor: DerefMut; /// Same as `RefFromWasmAbi::ref_from_abi` unsafe fn ref_mut_from_abi(js: Self::Abi) -> Self::Anchor; } /// Indicates that this type can be passed to JS as `Option`. /// /// This trait is used when implementing `IntoWasmAbi for Option`. pub trait OptionIntoWasmAbi: IntoWasmAbi { /// Returns an ABI instance indicating "none", which JS will interpret as /// the `None` branch of this option. /// /// It should be guaranteed that the `IntoWasmAbi` can never produce the ABI /// value returned here. fn none() -> Self::Abi; } /// Indicates that this type can be received from JS as `Option`. /// /// This trait is used when implementing `FromWasmAbi for Option`. pub trait OptionFromWasmAbi: FromWasmAbi { /// Tests whether the argument is a "none" instance. If so it will be /// deserialized as `None`, and otherwise it will be passed to /// `FromWasmAbi`. fn is_none(abi: &Self::Abi) -> bool; } /// An unsafe trait which represents types that are ABI-safe to pass via wasm /// arguments. /// /// # Safety /// /// This is an unsafe trait to implement as there's no guarantee the type is /// actually safe to transfer across the was boundary, it's up to you to /// guarantee this, so codegen works correctly. pub unsafe trait WasmAbi {} unsafe impl WasmAbi for u32 {} unsafe impl WasmAbi for i32 {} unsafe impl WasmAbi for u64 {} unsafe impl WasmAbi for i64 {} unsafe impl WasmAbi for f32 {} unsafe impl WasmAbi for f64 {} /// A trait representing how to interpret the return value of a function for /// the wasm ABI. /// /// This is very similar to the `IntoWasmAbi` trait and in fact has a blanket /// implementation for all implementors of the `IntoWasmAbi`. The primary use /// case of this trait is to enable functions to return `Result`, interpreting /// an error as "rethrow this to JS" pub trait ReturnWasmAbi: WasmDescribe { /// Same as `IntoWasmAbi::Abi` type Abi: WasmAbi; /// Same as `IntoWasmAbi::into_abi`, except that it may throw and never /// return in the case of `Err`. fn return_abi(self) -> Self::Abi; } impl ReturnWasmAbi for T { type Abi = T::Abi; #[inline] fn return_abi(self) -> Self::Abi { self.into_abi() } } wasm-bindgen-0.2.87/src/describe.rs000064400000000000000000000063131046102023000152150ustar 00000000000000//! This is an internal module, no stability guarantees are provided. Use at //! your own risk. #![doc(hidden)] use crate::{Clamped, JsError, JsValue}; use cfg_if::cfg_if; macro_rules! tys { ($($a:ident)*) => (tys! { @ ($($a)*) 0 }); (@ () $v:expr) => {}; (@ ($a:ident $($b:ident)*) $v:expr) => { pub const $a: u32 = $v; tys!(@ ($($b)*) $v+1); } } // NB: this list must be kept in sync with `crates/cli-support/src/descriptor.rs` tys! { I8 U8 I16 U16 I32 U32 I64 U64 F32 F64 BOOLEAN FUNCTION CLOSURE CACHED_STRING STRING REF REFMUT LONGREF SLICE VECTOR EXTERNREF NAMED_EXTERNREF ENUM RUST_STRUCT CHAR OPTIONAL RESULT UNIT CLAMPED } #[inline(always)] // see the wasm-interpreter crate pub fn inform(a: u32) { unsafe { super::__wbindgen_describe(a) } } pub trait WasmDescribe { fn describe(); } macro_rules! simple { ($($t:ident => $d:ident)*) => ($( impl WasmDescribe for $t { fn describe() { inform($d) } } )*) } simple! { i8 => I8 u8 => U8 i16 => I16 u16 => U16 i32 => I32 u32 => U32 i64 => I64 u64 => U64 isize => I32 usize => U32 f32 => F32 f64 => F64 bool => BOOLEAN char => CHAR JsValue => EXTERNREF } cfg_if! { if #[cfg(feature = "enable-interning")] { simple! { str => CACHED_STRING } } else { simple! { str => STRING } } } impl WasmDescribe for *const T { fn describe() { inform(I32) } } impl WasmDescribe for *mut T { fn describe() { inform(I32) } } impl WasmDescribe for [T] { fn describe() { inform(SLICE); T::describe(); } } impl<'a, T: WasmDescribe + ?Sized> WasmDescribe for &'a T { fn describe() { inform(REF); T::describe(); } } impl<'a, T: WasmDescribe + ?Sized> WasmDescribe for &'a mut T { fn describe() { inform(REFMUT); T::describe(); } } if_std! { use std::prelude::v1::*; cfg_if! { if #[cfg(feature = "enable-interning")] { simple! { String => CACHED_STRING } } else { simple! { String => STRING } } } impl WasmDescribe for Box<[T]> { fn describe() { inform(VECTOR); T::describe(); } } impl WasmDescribe for Vec where Box<[T]>: WasmDescribe { fn describe() { >::describe(); } } } impl WasmDescribe for Option { fn describe() { inform(OPTIONAL); T::describe(); } } impl WasmDescribe for () { fn describe() { inform(UNIT) } } impl> WasmDescribe for Result { fn describe() { inform(RESULT); T::describe(); } } impl WasmDescribe for Clamped { fn describe() { inform(CLAMPED); T::describe(); } } impl WasmDescribe for JsError { fn describe() { JsValue::describe(); } } wasm-bindgen-0.2.87/src/externref.rs000064400000000000000000000134501046102023000154370ustar 00000000000000use crate::JsValue; use std::alloc::{self, Layout}; use std::cell::Cell; use std::mem; use std::ptr; use std::slice; use std::vec::Vec; use std::cmp::max; externs! { #[link(wasm_import_module = "__wbindgen_externref_xform__")] extern "C" { fn __wbindgen_externref_table_grow(delta: usize) -> i32; fn __wbindgen_externref_table_set_null(idx: usize) -> (); } } pub struct Slab { data: Vec, head: usize, base: usize, } impl Slab { fn new() -> Slab { Slab { data: Vec::new(), head: 0, base: 0, } } fn alloc(&mut self) -> usize { let ret = self.head; if ret == self.data.len() { let curr_len = self.data.len(); if curr_len == self.data.capacity() { let extra = max(128, curr_len); let r = unsafe { __wbindgen_externref_table_grow(extra) }; if r == -1 { internal_error("table grow failure") } if self.base == 0 { self.base = r as usize; } else if self.base + self.data.len() != r as usize { internal_error("someone else allocated table entries?") } // poor man's `try_reserve_exact` until that's stable unsafe { let new_cap = self.data.capacity() + extra; let size = mem::size_of::() * new_cap; let align = mem::align_of::(); let layout = match Layout::from_size_align(size, align) { Ok(l) => l, Err(_) => internal_error("size/align layout failure"), }; let ptr = alloc::alloc(layout) as *mut usize; if ptr.is_null() { internal_error("allocation failure"); } ptr::copy_nonoverlapping(self.data.as_ptr(), ptr, self.data.len()); let new_vec = Vec::from_raw_parts(ptr, self.data.len(), new_cap); let mut old = mem::replace(&mut self.data, new_vec); old.set_len(0); } } // custom condition to ensure `push` below doesn't call `reserve` in // optimized builds which pulls in lots of panic infrastructure if self.data.len() >= self.data.capacity() { internal_error("push should be infallible now") } self.data.push(ret + 1); } // usage of `get_mut` thwarts panicking infrastructure in optimized // builds match self.data.get_mut(ret) { Some(slot) => self.head = *slot, None => internal_error("ret out of bounds"), } ret + self.base } fn dealloc(&mut self, slot: usize) { if slot < self.base { internal_error("free reserved slot"); } let slot = slot - self.base; // usage of `get_mut` thwarts panicking infrastructure in optimized // builds match self.data.get_mut(slot) { Some(ptr) => { *ptr = self.head; self.head = slot; } None => internal_error("slot out of bounds"), } } fn live_count(&self) -> u32 { let mut free_count = 0; let mut next = self.head; while next < self.data.len() { debug_assert!((free_count as usize) < self.data.len()); free_count += 1; match self.data.get(next) { Some(n) => next = *n, None => internal_error("slot out of bounds"), }; } self.data.len() as u32 - free_count } } fn internal_error(msg: &str) -> ! { if cfg!(debug_assertions) { super::throw_str(msg) } else { std::process::abort() } } // Management of `externref` is always thread local since an `externref` value // can't cross threads in wasm. Indices as a result are always thread-local. std::thread_local!(pub static HEAP_SLAB: Cell = Cell::new(Slab::new())); #[no_mangle] pub extern "C" fn __externref_table_alloc() -> usize { HEAP_SLAB .try_with(|slot| { let mut slab = slot.replace(Slab::new()); let ret = slab.alloc(); slot.replace(slab); ret }) .unwrap_or_else(|_| internal_error("tls access failure")) } #[no_mangle] pub extern "C" fn __externref_table_dealloc(idx: usize) { if idx < super::JSIDX_RESERVED as usize { return; } // clear this value from the table so while the table slot is un-allocated // we don't keep around a strong reference to a potentially large object unsafe { __wbindgen_externref_table_set_null(idx); } HEAP_SLAB .try_with(|slot| { let mut slab = slot.replace(Slab::new()); slab.dealloc(idx); slot.replace(slab); }) .unwrap_or_else(|_| internal_error("tls access failure")) } #[no_mangle] pub unsafe extern "C" fn __externref_drop_slice(ptr: *mut JsValue, len: usize) { for slot in slice::from_raw_parts_mut(ptr, len) { __externref_table_dealloc(slot.idx as usize); } } // Implementation of `__wbindgen_externref_heap_live_count` for when we are using // `externref` instead of the JS `heap`. #[no_mangle] pub unsafe extern "C" fn __externref_heap_live_count() -> u32 { HEAP_SLAB .try_with(|slot| { let slab = slot.replace(Slab::new()); let count = slab.live_count(); slot.replace(slab); count }) .unwrap_or_else(|_| internal_error("tls access failure")) } // see comment in module above this in `link_mem_intrinsics` #[inline(never)] pub fn link_intrinsics() {} wasm-bindgen-0.2.87/src/lib.rs000064400000000000000000001624001046102023000142030ustar 00000000000000//! Runtime support for the `wasm-bindgen` tool //! //! This crate contains the runtime support necessary for `wasm-bindgen` the //! attribute and tool. Crates pull in the `#[wasm_bindgen]` attribute through //! this crate and this crate also provides JS bindings through the `JsValue` //! interface. #![no_std] #![allow(coherence_leak_check)] #![doc(html_root_url = "https://docs.rs/wasm-bindgen/0.2")] use core::convert::TryFrom; use core::fmt; use core::marker; use core::mem; use core::ops::{ Add, BitAnd, BitOr, BitXor, Deref, DerefMut, Div, Mul, Neg, Not, Rem, Shl, Shr, Sub, }; use core::u32; use crate::convert::{FromWasmAbi, WasmSlice}; macro_rules! if_std { ($($i:item)*) => ($( #[cfg(feature = "std")] $i )*) } macro_rules! externs { ($(#[$attr:meta])* extern "C" { $(fn $name:ident($($args:tt)*) -> $ret:ty;)* }) => ( #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] $(#[$attr])* extern "C" { $(fn $name($($args)*) -> $ret;)* } $( #[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))] #[allow(unused_variables)] unsafe extern fn $name($($args)*) -> $ret { panic!("function not implemented on non-wasm32 targets") } )* ) } /// A module which is typically glob imported. /// /// ``` /// use wasm_bindgen::prelude::*; /// ``` pub mod prelude { pub use crate::JsCast; pub use crate::JsValue; pub use crate::UnwrapThrowExt; #[doc(hidden)] pub use wasm_bindgen_macro::__wasm_bindgen_class_marker; pub use wasm_bindgen_macro::wasm_bindgen; if_std! { pub use crate::closure::Closure; } pub use crate::JsError; } pub use wasm_bindgen_macro::link_to; pub mod convert; pub mod describe; mod cast; pub use crate::cast::{JsCast, JsObject}; use convert::WasmOption; if_std! { extern crate std; use std::prelude::v1::*; pub mod closure; mod externref; mod cache; pub use cache::intern::{intern, unintern}; } /// Representation of an object owned by JS. /// /// A `JsValue` doesn't actually live in Rust right now but actually in a table /// owned by the `wasm-bindgen` generated JS glue code. Eventually the ownership /// will transfer into wasm directly and this will likely become more efficient, /// but for now it may be slightly slow. pub struct JsValue { idx: u32, _marker: marker::PhantomData<*mut u8>, // not at all threadsafe } const JSIDX_OFFSET: u32 = 128; // keep in sync with js/mod.rs const JSIDX_UNDEFINED: u32 = JSIDX_OFFSET; const JSIDX_NULL: u32 = JSIDX_OFFSET + 1; const JSIDX_TRUE: u32 = JSIDX_OFFSET + 2; const JSIDX_FALSE: u32 = JSIDX_OFFSET + 3; const JSIDX_RESERVED: u32 = JSIDX_OFFSET + 4; impl JsValue { /// The `null` JS value constant. pub const NULL: JsValue = JsValue::_new(JSIDX_NULL); /// The `undefined` JS value constant. pub const UNDEFINED: JsValue = JsValue::_new(JSIDX_UNDEFINED); /// The `true` JS value constant. pub const TRUE: JsValue = JsValue::_new(JSIDX_TRUE); /// The `false` JS value constant. pub const FALSE: JsValue = JsValue::_new(JSIDX_FALSE); #[inline] const fn _new(idx: u32) -> JsValue { JsValue { idx, _marker: marker::PhantomData, } } /// Creates a new JS value which is a string. /// /// The utf-8 string provided is copied to the JS heap and the string will /// be owned by the JS garbage collector. #[allow(clippy::should_implement_trait)] // cannot fix without breaking change #[inline] pub fn from_str(s: &str) -> JsValue { unsafe { JsValue::_new(__wbindgen_string_new(s.as_ptr(), s.len())) } } /// Creates a new JS value which is a number. /// /// This function creates a JS value representing a number (a heap /// allocated number) and returns a handle to the JS version of it. #[inline] pub fn from_f64(n: f64) -> JsValue { unsafe { JsValue::_new(__wbindgen_number_new(n)) } } /// Creates a new JS value which is a bigint from a string representing a number. /// /// This function creates a JS value representing a bigint (a heap /// allocated large integer) and returns a handle to the JS version of it. #[inline] pub fn bigint_from_str(s: &str) -> JsValue { unsafe { JsValue::_new(__wbindgen_bigint_from_str(s.as_ptr(), s.len())) } } /// Creates a new JS value which is a boolean. /// /// This function creates a JS object representing a boolean (a heap /// allocated boolean) and returns a handle to the JS version of it. #[inline] pub const fn from_bool(b: bool) -> JsValue { if b { JsValue::TRUE } else { JsValue::FALSE } } /// Creates a new JS value representing `undefined`. #[inline] pub const fn undefined() -> JsValue { JsValue::UNDEFINED } /// Creates a new JS value representing `null`. #[inline] pub const fn null() -> JsValue { JsValue::NULL } /// Creates a new JS symbol with the optional description specified. /// /// This function will invoke the `Symbol` constructor in JS and return the /// JS object corresponding to the symbol created. pub fn symbol(description: Option<&str>) -> JsValue { unsafe { match description { Some(description) => JsValue::_new(__wbindgen_symbol_named_new( description.as_ptr(), description.len(), )), None => JsValue::_new(__wbindgen_symbol_anonymous_new()), } } } /// Creates a new `JsValue` from the JSON serialization of the object `t` /// provided. /// /// **This function is deprecated**, due to [creating a dependency cycle in /// some circumstances][dep-cycle-issue]. Use [`serde-wasm-bindgen`] or /// [`gloo_utils::format::JsValueSerdeExt`] instead. /// /// [dep-cycle-issue]: https://github.com/rustwasm/wasm-bindgen/issues/2770 /// [`serde-wasm-bindgen`]: https://docs.rs/serde-wasm-bindgen /// [`gloo_utils::format::JsValueSerdeExt`]: https://docs.rs/gloo-utils/latest/gloo_utils/format/trait.JsValueSerdeExt.html /// /// This function will serialize the provided value `t` to a JSON string, /// send the JSON string to JS, parse it into a JS object, and then return /// a handle to the JS object. This is unlikely to be super speedy so it's /// not recommended for large payloads, but it's a nice to have in some /// situations! /// /// Usage of this API requires activating the `serde-serialize` feature of /// the `wasm-bindgen` crate. /// /// # Errors /// /// Returns any error encountered when serializing `T` into JSON. #[cfg(feature = "serde-serialize")] #[deprecated = "causes dependency cycles, use `serde-wasm-bindgen` or `gloo_utils::format::JsValueSerdeExt` instead"] pub fn from_serde(t: &T) -> serde_json::Result where T: serde::ser::Serialize + ?Sized, { let s = serde_json::to_string(t)?; unsafe { Ok(JsValue::_new(__wbindgen_json_parse(s.as_ptr(), s.len()))) } } /// Invokes `JSON.stringify` on this value and then parses the resulting /// JSON into an arbitrary Rust value. /// /// **This function is deprecated**, due to [creating a dependency cycle in /// some circumstances][dep-cycle-issue]. Use [`serde-wasm-bindgen`] or /// [`gloo_utils::format::JsValueSerdeExt`] instead. /// /// [dep-cycle-issue]: https://github.com/rustwasm/wasm-bindgen/issues/2770 /// [`serde-wasm-bindgen`]: https://docs.rs/serde-wasm-bindgen /// [`gloo_utils::format::JsValueSerdeExt`]: https://docs.rs/gloo-utils/latest/gloo_utils/format/trait.JsValueSerdeExt.html /// /// This function will first call `JSON.stringify` on the `JsValue` itself. /// The resulting string is then passed into Rust which then parses it as /// JSON into the resulting value. /// /// Usage of this API requires activating the `serde-serialize` feature of /// the `wasm-bindgen` crate. /// /// # Errors /// /// Returns any error encountered when parsing the JSON into a `T`. #[cfg(feature = "serde-serialize")] #[deprecated = "causes dependency cycles, use `serde-wasm-bindgen` or `gloo_utils::format::JsValueSerdeExt` instead"] pub fn into_serde(&self) -> serde_json::Result where T: for<'a> serde::de::Deserialize<'a>, { unsafe { let ret = __wbindgen_json_serialize(self.idx); let s = String::from_abi(ret); serde_json::from_str(&s) } } /// Returns the `f64` value of this JS value if it's an instance of a /// number. /// /// If this JS value is not an instance of a number then this returns /// `None`. #[inline] pub fn as_f64(&self) -> Option { unsafe { FromWasmAbi::from_abi(__wbindgen_number_get(self.idx)) } } /// Tests whether this JS value is a JS string. #[inline] pub fn is_string(&self) -> bool { unsafe { __wbindgen_is_string(self.idx) == 1 } } /// If this JS value is a string value, this function copies the JS string /// value into wasm linear memory, encoded as UTF-8, and returns it as a /// Rust `String`. /// /// To avoid the copying and re-encoding, consider the /// `JsString::try_from()` function from [js-sys](https://docs.rs/js-sys) /// instead. /// /// If this JS value is not an instance of a string or if it's not valid /// utf-8 then this returns `None`. /// /// # UTF-16 vs UTF-8 /// /// JavaScript strings in general are encoded as UTF-16, but Rust strings /// are encoded as UTF-8. This can cause the Rust string to look a bit /// different than the JS string sometimes. For more details see the /// [documentation about the `str` type][caveats] which contains a few /// caveats about the encodings. /// /// [caveats]: https://rustwasm.github.io/docs/wasm-bindgen/reference/types/str.html #[cfg(feature = "std")] #[inline] pub fn as_string(&self) -> Option { unsafe { FromWasmAbi::from_abi(__wbindgen_string_get(self.idx)) } } /// Returns the `bool` value of this JS value if it's an instance of a /// boolean. /// /// If this JS value is not an instance of a boolean then this returns /// `None`. #[inline] pub fn as_bool(&self) -> Option { unsafe { match __wbindgen_boolean_get(self.idx) { 0 => Some(false), 1 => Some(true), _ => None, } } } /// Tests whether this JS value is `null` #[inline] pub fn is_null(&self) -> bool { unsafe { __wbindgen_is_null(self.idx) == 1 } } /// Tests whether this JS value is `undefined` #[inline] pub fn is_undefined(&self) -> bool { unsafe { __wbindgen_is_undefined(self.idx) == 1 } } /// Tests whether the type of this JS value is `symbol` #[inline] pub fn is_symbol(&self) -> bool { unsafe { __wbindgen_is_symbol(self.idx) == 1 } } /// Tests whether `typeof self == "object" && self !== null`. #[inline] pub fn is_object(&self) -> bool { unsafe { __wbindgen_is_object(self.idx) == 1 } } /// Tests whether this JS value is an instance of Array. #[inline] pub fn is_array(&self) -> bool { unsafe { __wbindgen_is_array(self.idx) == 1 } } /// Tests whether the type of this JS value is `function`. #[inline] pub fn is_function(&self) -> bool { unsafe { __wbindgen_is_function(self.idx) == 1 } } /// Tests whether the type of this JS value is `bigint`. #[inline] pub fn is_bigint(&self) -> bool { unsafe { __wbindgen_is_bigint(self.idx) == 1 } } /// Applies the unary `typeof` JS operator on a `JsValue`. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof) #[inline] pub fn js_typeof(&self) -> JsValue { unsafe { JsValue::_new(__wbindgen_typeof(self.idx)) } } /// Applies the binary `in` JS operator on the two `JsValue`s. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in) #[inline] pub fn js_in(&self, obj: &JsValue) -> bool { unsafe { __wbindgen_in(self.idx, obj.idx) == 1 } } /// Tests whether the value is ["truthy"]. /// /// ["truthy"]: https://developer.mozilla.org/en-US/docs/Glossary/Truthy #[inline] pub fn is_truthy(&self) -> bool { !self.is_falsy() } /// Tests whether the value is ["falsy"]. /// /// ["falsy"]: https://developer.mozilla.org/en-US/docs/Glossary/Falsy #[inline] pub fn is_falsy(&self) -> bool { unsafe { __wbindgen_is_falsy(self.idx) == 1 } } /// Get a string representation of the JavaScript object for debugging. #[cfg(feature = "std")] fn as_debug_string(&self) -> String { unsafe { let mut ret = [0; 2]; __wbindgen_debug_string(&mut ret, self.idx); let data = Vec::from_raw_parts(ret[0] as *mut u8, ret[1], ret[1]); String::from_utf8_unchecked(data) } } /// Compare two `JsValue`s for equality, using the `==` operator in JS. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Equality) #[inline] pub fn loose_eq(&self, other: &Self) -> bool { unsafe { __wbindgen_jsval_loose_eq(self.idx, other.idx) != 0 } } /// Applies the unary `~` JS operator on a `JsValue`. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_NOT) #[inline] pub fn bit_not(&self) -> JsValue { unsafe { JsValue::_new(__wbindgen_bit_not(self.idx)) } } /// Applies the binary `>>>` JS operator on the two `JsValue`s. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unsigned_right_shift) #[inline] pub fn unsigned_shr(&self, rhs: &Self) -> u32 { unsafe { __wbindgen_unsigned_shr(self.idx, rhs.idx) } } /// Applies the binary `/` JS operator on two `JsValue`s, catching and returning any `RangeError` thrown. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Division) #[inline] pub fn checked_div(&self, rhs: &Self) -> Self { unsafe { JsValue::_new(__wbindgen_checked_div(self.idx, rhs.idx)) } } /// Applies the binary `**` JS operator on the two `JsValue`s. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Exponentiation) #[inline] pub fn pow(&self, rhs: &Self) -> Self { unsafe { JsValue::_new(__wbindgen_pow(self.idx, rhs.idx)) } } /// Applies the binary `<` JS operator on the two `JsValue`s. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Less_than) #[inline] pub fn lt(&self, other: &Self) -> bool { unsafe { __wbindgen_lt(self.idx, other.idx) == 1 } } /// Applies the binary `<=` JS operator on the two `JsValue`s. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Less_than_or_equal) #[inline] pub fn le(&self, other: &Self) -> bool { unsafe { __wbindgen_le(self.idx, other.idx) == 1 } } /// Applies the binary `>=` JS operator on the two `JsValue`s. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Greater_than_or_equal) #[inline] pub fn ge(&self, other: &Self) -> bool { unsafe { __wbindgen_ge(self.idx, other.idx) == 1 } } /// Applies the binary `>` JS operator on the two `JsValue`s. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Greater_than) #[inline] pub fn gt(&self, other: &Self) -> bool { unsafe { __wbindgen_gt(self.idx, other.idx) == 1 } } /// Applies the unary `+` JS operator on a `JsValue`. Can throw. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unary_plus) #[inline] pub fn unchecked_into_f64(&self) -> f64 { unsafe { __wbindgen_as_number(self.idx) } } } impl PartialEq for JsValue { /// Compares two `JsValue`s for equality, using the `===` operator in JS. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Strict_equality) #[inline] fn eq(&self, other: &Self) -> bool { unsafe { __wbindgen_jsval_eq(self.idx, other.idx) != 0 } } } impl PartialEq for JsValue { #[inline] fn eq(&self, other: &bool) -> bool { self.as_bool() == Some(*other) } } impl PartialEq for JsValue { #[inline] fn eq(&self, other: &str) -> bool { *self == JsValue::from_str(other) } } impl<'a> PartialEq<&'a str> for JsValue { #[inline] fn eq(&self, other: &&'a str) -> bool { >::eq(self, other) } } if_std! { impl PartialEq for JsValue { #[inline] fn eq(&self, other: &String) -> bool { >::eq(self, other) } } impl<'a> PartialEq<&'a String> for JsValue { #[inline] fn eq(&self, other: &&'a String) -> bool { >::eq(self, other) } } } macro_rules! forward_deref_unop { (impl $imp:ident, $method:ident for $t:ty) => { impl $imp for $t { type Output = <&'static $t as $imp>::Output; #[inline] fn $method(self) -> <&'static $t as $imp>::Output { $imp::$method(&self) } } }; } macro_rules! forward_deref_binop { (impl $imp:ident, $method:ident for $t:ty) => { impl<'a> $imp<$t> for &'a $t { type Output = <&'static $t as $imp<&'static $t>>::Output; #[inline] fn $method(self, other: $t) -> <&'static $t as $imp<&'static $t>>::Output { $imp::$method(self, &other) } } impl $imp<&$t> for $t { type Output = <&'static $t as $imp<&'static $t>>::Output; #[inline] fn $method(self, other: &$t) -> <&'static $t as $imp<&'static $t>>::Output { $imp::$method(&self, other) } } impl $imp<$t> for $t { type Output = <&'static $t as $imp<&'static $t>>::Output; #[inline] fn $method(self, other: $t) -> <&'static $t as $imp<&'static $t>>::Output { $imp::$method(&self, &other) } } }; } impl Not for &JsValue { type Output = bool; /// Applies the `!` JS operator on a `JsValue`. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_NOT) #[inline] fn not(self) -> Self::Output { JsValue::is_falsy(self) } } forward_deref_unop!(impl Not, not for JsValue); impl TryFrom for f64 { type Error = JsValue; /// Applies the unary `+` JS operator on a `JsValue`. /// Returns the numeric result on success, or the JS error value on error. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unary_plus) #[inline] fn try_from(val: JsValue) -> Result { f64::try_from(&val) } } impl TryFrom<&JsValue> for f64 { type Error = JsValue; /// Applies the unary `+` JS operator on a `JsValue`. /// Returns the numeric result on success, or the JS error value on error. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unary_plus) #[inline] fn try_from(val: &JsValue) -> Result { let jsval = unsafe { JsValue::_new(__wbindgen_try_into_number(val.idx)) }; match jsval.as_f64() { Some(num) => Ok(num), None => Err(jsval), } } } impl Neg for &JsValue { type Output = JsValue; /// Applies the unary `-` JS operator on a `JsValue`. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unary_negation) #[inline] fn neg(self) -> Self::Output { unsafe { JsValue::_new(__wbindgen_neg(self.idx)) } } } forward_deref_unop!(impl Neg, neg for JsValue); impl BitAnd for &JsValue { type Output = JsValue; /// Applies the binary `&` JS operator on two `JsValue`s. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_AND) #[inline] fn bitand(self, rhs: Self) -> Self::Output { unsafe { JsValue::_new(__wbindgen_bit_and(self.idx, rhs.idx)) } } } forward_deref_binop!(impl BitAnd, bitand for JsValue); impl BitOr for &JsValue { type Output = JsValue; /// Applies the binary `|` JS operator on two `JsValue`s. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_OR) #[inline] fn bitor(self, rhs: Self) -> Self::Output { unsafe { JsValue::_new(__wbindgen_bit_or(self.idx, rhs.idx)) } } } forward_deref_binop!(impl BitOr, bitor for JsValue); impl BitXor for &JsValue { type Output = JsValue; /// Applies the binary `^` JS operator on two `JsValue`s. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_XOR) #[inline] fn bitxor(self, rhs: Self) -> Self::Output { unsafe { JsValue::_new(__wbindgen_bit_xor(self.idx, rhs.idx)) } } } forward_deref_binop!(impl BitXor, bitxor for JsValue); impl Shl for &JsValue { type Output = JsValue; /// Applies the binary `<<` JS operator on two `JsValue`s. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Left_shift) #[inline] fn shl(self, rhs: Self) -> Self::Output { unsafe { JsValue::_new(__wbindgen_shl(self.idx, rhs.idx)) } } } forward_deref_binop!(impl Shl, shl for JsValue); impl Shr for &JsValue { type Output = JsValue; /// Applies the binary `>>` JS operator on two `JsValue`s. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Right_shift) #[inline] fn shr(self, rhs: Self) -> Self::Output { unsafe { JsValue::_new(__wbindgen_shr(self.idx, rhs.idx)) } } } forward_deref_binop!(impl Shr, shr for JsValue); impl Add for &JsValue { type Output = JsValue; /// Applies the binary `+` JS operator on two `JsValue`s. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Addition) #[inline] fn add(self, rhs: Self) -> Self::Output { unsafe { JsValue::_new(__wbindgen_add(self.idx, rhs.idx)) } } } forward_deref_binop!(impl Add, add for JsValue); impl Sub for &JsValue { type Output = JsValue; /// Applies the binary `-` JS operator on two `JsValue`s. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Subtraction) #[inline] fn sub(self, rhs: Self) -> Self::Output { unsafe { JsValue::_new(__wbindgen_sub(self.idx, rhs.idx)) } } } forward_deref_binop!(impl Sub, sub for JsValue); impl Div for &JsValue { type Output = JsValue; /// Applies the binary `/` JS operator on two `JsValue`s. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Division) #[inline] fn div(self, rhs: Self) -> Self::Output { unsafe { JsValue::_new(__wbindgen_div(self.idx, rhs.idx)) } } } forward_deref_binop!(impl Div, div for JsValue); impl Mul for &JsValue { type Output = JsValue; /// Applies the binary `*` JS operator on two `JsValue`s. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Multiplication) #[inline] fn mul(self, rhs: Self) -> Self::Output { unsafe { JsValue::_new(__wbindgen_mul(self.idx, rhs.idx)) } } } forward_deref_binop!(impl Mul, mul for JsValue); impl Rem for &JsValue { type Output = JsValue; /// Applies the binary `%` JS operator on two `JsValue`s. /// /// [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Remainder) #[inline] fn rem(self, rhs: Self) -> Self::Output { unsafe { JsValue::_new(__wbindgen_rem(self.idx, rhs.idx)) } } } forward_deref_binop!(impl Rem, rem for JsValue); impl<'a> From<&'a str> for JsValue { #[inline] fn from(s: &'a str) -> JsValue { JsValue::from_str(s) } } impl From<*mut T> for JsValue { #[inline] fn from(s: *mut T) -> JsValue { JsValue::from(s as usize) } } impl From<*const T> for JsValue { #[inline] fn from(s: *const T) -> JsValue { JsValue::from(s as usize) } } if_std! { impl<'a> From<&'a String> for JsValue { #[inline] fn from(s: &'a String) -> JsValue { JsValue::from_str(s) } } impl From for JsValue { #[inline] fn from(s: String) -> JsValue { JsValue::from_str(&s) } } } impl From for JsValue { #[inline] fn from(s: bool) -> JsValue { JsValue::from_bool(s) } } impl<'a, T> From<&'a T> for JsValue where T: JsCast, { #[inline] fn from(s: &'a T) -> JsValue { s.as_ref().clone() } } impl From> for JsValue where JsValue: From, { #[inline] fn from(s: Option) -> JsValue { match s { Some(s) => s.into(), None => JsValue::undefined(), } } } impl JsCast for JsValue { // everything is a `JsValue`! #[inline] fn instanceof(_val: &JsValue) -> bool { true } #[inline] fn unchecked_from_js(val: JsValue) -> Self { val } #[inline] fn unchecked_from_js_ref(val: &JsValue) -> &Self { val } } impl AsRef for JsValue { #[inline] fn as_ref(&self) -> &JsValue { self } } macro_rules! numbers { ($($n:ident)*) => ($( impl PartialEq<$n> for JsValue { #[inline] fn eq(&self, other: &$n) -> bool { self.as_f64() == Some(f64::from(*other)) } } impl From<$n> for JsValue { #[inline] fn from(n: $n) -> JsValue { JsValue::from_f64(n.into()) } } )*) } numbers! { i8 u8 i16 u16 i32 u32 f32 f64 } macro_rules! big_numbers { (|$arg:ident|, $($n:ident = $handle:expr,)*) => ($( impl PartialEq<$n> for JsValue { #[inline] fn eq(&self, other: &$n) -> bool { self == &JsValue::from(*other) } } impl From<$n> for JsValue { #[inline] fn from($arg: $n) -> JsValue { unsafe { JsValue::_new($handle) } } } )*) } fn bigint_get_as_i64(v: &JsValue) -> Option { unsafe { Option::from_abi(__wbindgen_bigint_get_as_i64(v.idx)) } } macro_rules! try_from_for_num64 { ($ty:ty) => { impl TryFrom for $ty { type Error = JsValue; #[inline] fn try_from(v: JsValue) -> Result { bigint_get_as_i64(&v) // Reinterpret bits; ABI-wise this is safe to do and allows us to avoid // having separate intrinsics per signed/unsigned types. .map(|as_i64| as_i64 as Self) // Double-check that we didn't truncate the bigint to 64 bits. .filter(|as_self| v == *as_self) // Not a bigint or not in range. .ok_or(v) } } }; } try_from_for_num64!(i64); try_from_for_num64!(u64); macro_rules! try_from_for_num128 { ($ty:ty, $hi_ty:ty) => { impl TryFrom for $ty { type Error = JsValue; #[inline] fn try_from(v: JsValue) -> Result { // Truncate the bigint to 64 bits, this will give us the lower part. let lo = match bigint_get_as_i64(&v) { // The lower part must be interpreted as unsigned in both i128 and u128. Some(lo) => lo as u64, // Not a bigint. None => return Err(v), }; // Now we know it's a bigint, so we can safely use `>> 64n` without // worrying about a JS exception on type mismatch. let hi = v >> JsValue::from(64_u64); // The high part is the one we want checked against a 64-bit range. // If it fits, then our original number is in the 128-bit range. let hi = <$hi_ty>::try_from(hi)?; Ok(Self::from(hi) << 64 | Self::from(lo)) } } }; } try_from_for_num128!(i128, i64); try_from_for_num128!(u128, u64); big_numbers! { |n|, i64 = __wbindgen_bigint_from_i64(n), u64 = __wbindgen_bigint_from_u64(n), i128 = __wbindgen_bigint_from_i128((n >> 64) as i64, n as u64), u128 = __wbindgen_bigint_from_u128((n >> 64) as u64, n as u64), } // `usize` and `isize` have to be treated a bit specially, because we know that // they're 32-bit but the compiler conservatively assumes they might be bigger. // So, we have to manually forward to the `u32`/`i32` versions. impl PartialEq for JsValue { #[inline] fn eq(&self, other: &usize) -> bool { *self == (*other as u32) } } impl From for JsValue { #[inline] fn from(n: usize) -> Self { Self::from(n as u32) } } impl PartialEq for JsValue { #[inline] fn eq(&self, other: &isize) -> bool { *self == (*other as i32) } } impl From for JsValue { #[inline] fn from(n: isize) -> Self { Self::from(n as i32) } } externs! { #[link(wasm_import_module = "__wbindgen_placeholder__")] extern "C" { fn __wbindgen_object_clone_ref(idx: u32) -> u32; fn __wbindgen_object_drop_ref(idx: u32) -> (); fn __wbindgen_string_new(ptr: *const u8, len: usize) -> u32; fn __wbindgen_number_new(f: f64) -> u32; fn __wbindgen_bigint_from_str(ptr: *const u8, len: usize) -> u32; fn __wbindgen_bigint_from_i64(n: i64) -> u32; fn __wbindgen_bigint_from_u64(n: u64) -> u32; fn __wbindgen_bigint_from_i128(hi: i64, lo: u64) -> u32; fn __wbindgen_bigint_from_u128(hi: u64, lo: u64) -> u32; fn __wbindgen_symbol_named_new(ptr: *const u8, len: usize) -> u32; fn __wbindgen_symbol_anonymous_new() -> u32; fn __wbindgen_externref_heap_live_count() -> u32; fn __wbindgen_is_null(idx: u32) -> u32; fn __wbindgen_is_undefined(idx: u32) -> u32; fn __wbindgen_is_symbol(idx: u32) -> u32; fn __wbindgen_is_object(idx: u32) -> u32; fn __wbindgen_is_array(idx: u32) -> u32; fn __wbindgen_is_function(idx: u32) -> u32; fn __wbindgen_is_string(idx: u32) -> u32; fn __wbindgen_is_bigint(idx: u32) -> u32; fn __wbindgen_typeof(idx: u32) -> u32; fn __wbindgen_in(prop: u32, obj: u32) -> u32; fn __wbindgen_is_falsy(idx: u32) -> u32; fn __wbindgen_as_number(idx: u32) -> f64; fn __wbindgen_try_into_number(idx: u32) -> u32; fn __wbindgen_neg(idx: u32) -> u32; fn __wbindgen_bit_and(a: u32, b: u32) -> u32; fn __wbindgen_bit_or(a: u32, b: u32) -> u32; fn __wbindgen_bit_xor(a: u32, b: u32) -> u32; fn __wbindgen_bit_not(idx: u32) -> u32; fn __wbindgen_shl(a: u32, b: u32) -> u32; fn __wbindgen_shr(a: u32, b: u32) -> u32; fn __wbindgen_unsigned_shr(a: u32, b: u32) -> u32; fn __wbindgen_add(a: u32, b: u32) -> u32; fn __wbindgen_sub(a: u32, b: u32) -> u32; fn __wbindgen_div(a: u32, b: u32) -> u32; fn __wbindgen_checked_div(a: u32, b: u32) -> u32; fn __wbindgen_mul(a: u32, b: u32) -> u32; fn __wbindgen_rem(a: u32, b: u32) -> u32; fn __wbindgen_pow(a: u32, b: u32) -> u32; fn __wbindgen_lt(a: u32, b: u32) -> u32; fn __wbindgen_le(a: u32, b: u32) -> u32; fn __wbindgen_ge(a: u32, b: u32) -> u32; fn __wbindgen_gt(a: u32, b: u32) -> u32; fn __wbindgen_number_get(idx: u32) -> WasmOption; fn __wbindgen_boolean_get(idx: u32) -> u32; fn __wbindgen_string_get(idx: u32) -> WasmSlice; fn __wbindgen_bigint_get_as_i64(idx: u32) -> WasmOption; fn __wbindgen_debug_string(ret: *mut [usize; 2], idx: u32) -> (); fn __wbindgen_throw(a: *const u8, b: usize) -> !; fn __wbindgen_rethrow(a: u32) -> !; fn __wbindgen_error_new(a: *const u8, b: usize) -> u32; fn __wbindgen_cb_drop(idx: u32) -> u32; fn __wbindgen_describe(v: u32) -> (); fn __wbindgen_describe_closure(a: u32, b: u32, c: u32) -> u32; fn __wbindgen_json_parse(ptr: *const u8, len: usize) -> u32; fn __wbindgen_json_serialize(idx: u32) -> WasmSlice; fn __wbindgen_jsval_eq(a: u32, b: u32) -> u32; fn __wbindgen_jsval_loose_eq(a: u32, b: u32) -> u32; fn __wbindgen_copy_to_typed_array(ptr: *const u8, len: usize, idx: u32) -> (); fn __wbindgen_not(idx: u32) -> u32; fn __wbindgen_exports() -> u32; fn __wbindgen_memory() -> u32; fn __wbindgen_module() -> u32; fn __wbindgen_function_table() -> u32; } } impl Clone for JsValue { #[inline] fn clone(&self) -> JsValue { unsafe { let idx = __wbindgen_object_clone_ref(self.idx); JsValue::_new(idx) } } } #[cfg(feature = "std")] impl fmt::Debug for JsValue { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "JsValue({})", self.as_debug_string()) } } #[cfg(not(feature = "std"))] impl fmt::Debug for JsValue { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("JsValue") } } impl Drop for JsValue { #[inline] fn drop(&mut self) { unsafe { // We definitely should never drop anything in the stack area debug_assert!(self.idx >= JSIDX_OFFSET, "free of stack slot {}", self.idx); // Otherwise if we're not dropping one of our reserved values, // actually call the intrinsic. See #1054 for eventually removing // this branch. if self.idx >= JSIDX_RESERVED { __wbindgen_object_drop_ref(self.idx); } } } } impl Default for JsValue { fn default() -> Self { Self::UNDEFINED } } /// Wrapper type for imported statics. /// /// This type is used whenever a `static` is imported from a JS module, for /// example this import: /// /// ```ignore /// #[wasm_bindgen] /// extern "C" { /// static console: JsValue; /// } /// ``` /// /// will generate in Rust a value that looks like: /// /// ```ignore /// static console: JsStatic = ...; /// ``` /// /// This type implements `Deref` to the inner type so it's typically used as if /// it were `&T`. #[cfg(feature = "std")] pub struct JsStatic { #[doc(hidden)] pub __inner: &'static std::thread::LocalKey, } #[cfg(feature = "std")] impl Deref for JsStatic { type Target = T; fn deref(&self) -> &T { // We know that our tls key is never overwritten after initialization, // so it should be safe (on that axis at least) to hand out a reference // that lives longer than the closure below. // // FIXME: this is not sound if we ever implement thread exit hooks on // wasm, as the pointer will eventually be invalidated but you can get // `&'static T` from this interface. We... probably need to deprecate // and/or remove this interface nowadays. unsafe { self.__inner.with(|ptr| &*(ptr as *const T)) } } } #[cold] #[inline(never)] #[deprecated(note = "renamed to `throw_str`")] #[doc(hidden)] pub fn throw(s: &str) -> ! { throw_str(s) } /// Throws a JS exception. /// /// This function will throw a JS exception with the message provided. The /// function will not return as the wasm stack will be popped when the exception /// is thrown. /// /// Note that it is very easy to leak memory with this function because this /// function, unlike `panic!` on other platforms, **will not run destructors**. /// It's recommended to return a `Result` where possible to avoid the worry of /// leaks. #[cold] #[inline(never)] pub fn throw_str(s: &str) -> ! { unsafe { __wbindgen_throw(s.as_ptr(), s.len()); } } /// Rethrow a JS exception /// /// This function will throw a JS exception with the JS value provided. This /// function will not return and the wasm stack will be popped until the point /// of entry of wasm itself. /// /// Note that it is very easy to leak memory with this function because this /// function, unlike `panic!` on other platforms, **will not run destructors**. /// It's recommended to return a `Result` where possible to avoid the worry of /// leaks. #[cold] #[inline(never)] pub fn throw_val(s: JsValue) -> ! { unsafe { let idx = s.idx; mem::forget(s); __wbindgen_rethrow(idx); } } /// Get the count of live `externref`s / `JsValue`s in `wasm-bindgen`'s heap. /// /// ## Usage /// /// This is intended for debugging and writing tests. /// /// To write a test that asserts against unnecessarily keeping `anref`s / /// `JsValue`s alive: /// /// * get an initial live count, /// /// * perform some series of operations or function calls that should clean up /// after themselves, and should not keep holding onto `externref`s / `JsValue`s /// after completion, /// /// * get the final live count, /// /// * and assert that the initial and final counts are the same. /// /// ## What is Counted /// /// Note that this only counts the *owned* `externref`s / `JsValue`s that end up in /// `wasm-bindgen`'s heap. It does not count borrowed `externref`s / `JsValue`s /// that are on its stack. /// /// For example, these `JsValue`s are accounted for: /// /// ```ignore /// #[wasm_bindgen] /// pub fn my_function(this_is_counted: JsValue) { /// let also_counted = JsValue::from_str("hi"); /// assert!(wasm_bindgen::externref_heap_live_count() >= 2); /// } /// ``` /// /// While this borrowed `JsValue` ends up on the stack, not the heap, and /// therefore is not accounted for: /// /// ```ignore /// #[wasm_bindgen] /// pub fn my_other_function(this_is_not_counted: &JsValue) { /// // ... /// } /// ``` pub fn externref_heap_live_count() -> u32 { unsafe { __wbindgen_externref_heap_live_count() } } #[doc(hidden)] pub fn anyref_heap_live_count() -> u32 { externref_heap_live_count() } /// An extension trait for `Option` and `Result` for unwrapping the `T` /// value, or throwing a JS error if it is not available. /// /// These methods should have a smaller code size footprint than the normal /// `Option::unwrap` and `Option::expect` methods, but they are specific to /// working with wasm and JS. /// /// On non-wasm32 targets, defaults to the normal unwrap/expect calls. /// /// # Example /// /// ``` /// use wasm_bindgen::prelude::*; /// /// // If the value is `Option::Some` or `Result::Ok`, then we just get the /// // contained `T` value. /// let x = Some(42); /// assert_eq!(x.unwrap_throw(), 42); /// /// let y: Option = None; /// /// // This call would throw an error to JS! /// // /// // y.unwrap_throw() /// // /// // And this call would throw an error to JS with a custom error message! /// // /// // y.expect_throw("woopsie daisy!") /// ``` pub trait UnwrapThrowExt: Sized { /// Unwrap this `Option` or `Result`, but instead of panicking on failure, /// throw an exception to JavaScript. #[cfg_attr(debug_assertions, track_caller)] fn unwrap_throw(self) -> T { if cfg!(all(debug_assertions, feature = "std")) { let loc = core::panic::Location::caller(); let msg = std::format!( "`unwrap_throw` failed ({}:{}:{})", loc.file(), loc.line(), loc.column() ); self.expect_throw(&msg) } else { self.expect_throw("`unwrap_throw` failed") } } /// Unwrap this container's `T` value, or throw an error to JS with the /// given message if the `T` value is unavailable (e.g. an `Option` is /// `None`). #[cfg_attr(debug_assertions, track_caller)] fn expect_throw(self, message: &str) -> T; } impl UnwrapThrowExt for Option { #[cfg_attr(debug_assertions, track_caller)] fn expect_throw(self, message: &str) -> T { if cfg!(all(target_arch = "wasm32", not(target_os = "emscripten"))) { match self { Some(val) => val, None => throw_str(message), } } else { self.expect(message) } } } impl UnwrapThrowExt for Result where E: core::fmt::Debug, { #[cfg_attr(debug_assertions, track_caller)] fn expect_throw(self, message: &str) -> T { if cfg!(all(target_arch = "wasm32", not(target_os = "emscripten"))) { match self { Ok(val) => val, Err(_) => throw_str(message), } } else { self.expect(message) } } } /// Returns a handle to this wasm instance's `WebAssembly.Module` /// /// Note that this is only available when the final wasm app is built with /// `--target no-modules`, it's not recommended to rely on this API yet! This is /// largely just an experimental addition to enable threading demos. Using this /// may prevent your wasm module from building down the road. #[doc(hidden)] pub fn module() -> JsValue { unsafe { JsValue::_new(__wbindgen_module()) } } /// Returns a handle to this wasm instance's `WebAssembly.Instance.prototype.exports` pub fn exports() -> JsValue { unsafe { JsValue::_new(__wbindgen_exports()) } } /// Returns a handle to this wasm instance's `WebAssembly.Memory` pub fn memory() -> JsValue { unsafe { JsValue::_new(__wbindgen_memory()) } } /// Returns a handle to this wasm instance's `WebAssembly.Table` which is the /// indirect function table used by Rust pub fn function_table() -> JsValue { unsafe { JsValue::_new(__wbindgen_function_table()) } } #[doc(hidden)] pub mod __rt { use crate::JsValue; use core::borrow::{Borrow, BorrowMut}; use core::cell::{Cell, UnsafeCell}; use core::convert::Infallible; use core::ops::{Deref, DerefMut}; pub extern crate core; #[cfg(feature = "std")] pub extern crate std; #[macro_export] #[doc(hidden)] #[cfg(feature = "std")] macro_rules! __wbindgen_if_not_std { ($($i:item)*) => {}; } #[macro_export] #[doc(hidden)] #[cfg(not(feature = "std"))] macro_rules! __wbindgen_if_not_std { ($($i:item)*) => ($($i)*) } #[inline] pub fn assert_not_null(s: *mut T) { if s.is_null() { throw_null(); } } #[cold] #[inline(never)] fn throw_null() -> ! { super::throw_str("null pointer passed to rust"); } /// A vendored version of `RefCell` from the standard library. /// /// Now why, you may ask, would we do that? Surely `RefCell` in libstd is /// quite good. And you're right, it is indeed quite good! Functionally /// nothing more is needed from `RefCell` in the standard library but for /// now this crate is also sort of optimizing for compiled code size. /// /// One major factor to larger binaries in Rust is when a panic happens. /// Panicking in the standard library involves a fair bit of machinery /// (formatting, panic hooks, synchronization, etc). It's all worthwhile if /// you need it but for something like `WasmRefCell` here we don't actually /// need all that! /// /// This is just a wrapper around all Rust objects passed to JS intended to /// guard accidental reentrancy, so this vendored version is intended solely /// to not panic in libstd. Instead when it "panics" it calls our `throw` /// function in this crate which raises an error in JS. pub struct WasmRefCell { borrow: Cell, value: UnsafeCell, } impl WasmRefCell { pub fn new(value: T) -> WasmRefCell where T: Sized, { WasmRefCell { value: UnsafeCell::new(value), borrow: Cell::new(0), } } pub fn get_mut(&mut self) -> &mut T { unsafe { &mut *self.value.get() } } pub fn borrow(&self) -> Ref { unsafe { if self.borrow.get() == usize::max_value() { borrow_fail(); } self.borrow.set(self.borrow.get() + 1); Ref { value: &*self.value.get(), borrow: &self.borrow, } } } pub fn borrow_mut(&self) -> RefMut { unsafe { if self.borrow.get() != 0 { borrow_fail(); } self.borrow.set(usize::max_value()); RefMut { value: &mut *self.value.get(), borrow: &self.borrow, } } } pub fn into_inner(self) -> T where T: Sized, { self.value.into_inner() } } pub struct Ref<'b, T: ?Sized + 'b> { value: &'b T, borrow: &'b Cell, } impl<'b, T: ?Sized> Deref for Ref<'b, T> { type Target = T; #[inline] fn deref(&self) -> &T { self.value } } impl<'b, T: ?Sized> Borrow for Ref<'b, T> { #[inline] fn borrow(&self) -> &T { self.value } } impl<'b, T: ?Sized> Drop for Ref<'b, T> { fn drop(&mut self) { self.borrow.set(self.borrow.get() - 1); } } pub struct RefMut<'b, T: ?Sized + 'b> { value: &'b mut T, borrow: &'b Cell, } impl<'b, T: ?Sized> Deref for RefMut<'b, T> { type Target = T; #[inline] fn deref(&self) -> &T { self.value } } impl<'b, T: ?Sized> DerefMut for RefMut<'b, T> { #[inline] fn deref_mut(&mut self) -> &mut T { self.value } } impl<'b, T: ?Sized> Borrow for RefMut<'b, T> { #[inline] fn borrow(&self) -> &T { self.value } } impl<'b, T: ?Sized> BorrowMut for RefMut<'b, T> { #[inline] fn borrow_mut(&mut self) -> &mut T { self.value } } impl<'b, T: ?Sized> Drop for RefMut<'b, T> { fn drop(&mut self) { self.borrow.set(0); } } fn borrow_fail() -> ! { super::throw_str( "recursive use of an object detected which would lead to \ unsafe aliasing in rust", ); } if_std! { use std::alloc::{alloc, dealloc, realloc, Layout}; #[no_mangle] pub extern "C" fn __wbindgen_malloc(size: usize, align: usize) -> *mut u8 { if let Ok(layout) = Layout::from_size_align(size, align) { unsafe { if layout.size() > 0 { let ptr = alloc(layout); if !ptr.is_null() { return ptr } } else { return align as *mut u8 } } } malloc_failure(); } #[no_mangle] pub unsafe extern "C" fn __wbindgen_realloc(ptr: *mut u8, old_size: usize, new_size: usize, align: usize) -> *mut u8 { debug_assert!(old_size > 0); debug_assert!(new_size > 0); if let Ok(layout) = Layout::from_size_align(old_size, align) { let ptr = realloc(ptr, layout, new_size); if !ptr.is_null() { return ptr } } malloc_failure(); } #[cold] fn malloc_failure() -> ! { if cfg!(debug_assertions) { super::throw_str("invalid malloc request") } else { std::process::abort(); } } #[no_mangle] pub unsafe extern "C" fn __wbindgen_free(ptr: *mut u8, size: usize, align: usize) { // This happens for zero-length slices, and in that case `ptr` is // likely bogus so don't actually send this to the system allocator if size == 0 { return } let layout = Layout::from_size_align_unchecked(size, align); dealloc(ptr, layout); } } /// This is a curious function necessary to get wasm-bindgen working today, /// and it's a bit of an unfortunate hack. /// /// The general problem is that somehow we need the above two symbols to /// exist in the final output binary (__wbindgen_malloc and /// __wbindgen_free). These symbols may be called by JS for various /// bindings, so we for sure need to make sure they're exported. /// /// The problem arises, though, when what if no Rust code uses the symbols? /// For all intents and purposes it looks to LLVM and the linker like the /// above two symbols are dead code, so they're completely discarded! /// /// Specifically what happens is this: /// /// * The above two symbols are generated into some object file inside of /// libwasm_bindgen.rlib /// * The linker, LLD, will not load this object file unless *some* symbol /// is loaded from the object. In this case, if the Rust code never calls /// __wbindgen_malloc or __wbindgen_free then the symbols never get linked /// in. /// * Later when `wasm-bindgen` attempts to use the symbols they don't /// exist, causing an error. /// /// This function is a weird hack for this problem. We inject a call to this /// function in all generated code. Usage of this function should then /// ensure that the above two intrinsics are translated. /// /// Due to how rustc creates object files this function (and anything inside /// it) will be placed into the same object file as the two intrinsics /// above. That means if this function is called and referenced we'll pull /// in the object file and link the intrinsics. /// /// Ideas for how to improve this are most welcome! pub fn link_mem_intrinsics() { crate::externref::link_intrinsics(); } static mut GLOBAL_EXNDATA: [u32; 2] = [0; 2]; #[no_mangle] pub unsafe extern "C" fn __wbindgen_exn_store(idx: u32) { debug_assert_eq!(GLOBAL_EXNDATA[0], 0); GLOBAL_EXNDATA[0] = 1; GLOBAL_EXNDATA[1] = idx; } pub fn take_last_exception() -> Result<(), super::JsValue> { unsafe { let ret = if GLOBAL_EXNDATA[0] == 1 { Err(super::JsValue::_new(GLOBAL_EXNDATA[1])) } else { Ok(()) }; GLOBAL_EXNDATA[0] = 0; GLOBAL_EXNDATA[1] = 0; ret } } /// An internal helper trait for usage in `#[wasm_bindgen]` on `async` /// functions to convert the return value of the function to /// `Result` which is what we'll return to JS (where an /// error is a failed future). pub trait IntoJsResult { fn into_js_result(self) -> Result; } impl IntoJsResult for () { fn into_js_result(self) -> Result { Ok(JsValue::undefined()) } } impl> IntoJsResult for T { fn into_js_result(self) -> Result { Ok(self.into()) } } impl, E: Into> IntoJsResult for Result { fn into_js_result(self) -> Result { match self { Ok(e) => Ok(e.into()), Err(e) => Err(e.into()), } } } impl> IntoJsResult for Result<(), E> { fn into_js_result(self) -> Result { match self { Ok(()) => Ok(JsValue::undefined()), Err(e) => Err(e.into()), } } } /// An internal helper trait for usage in `#[wasm_bindgen(start)]` /// functions to throw the error (if it is `Err`). pub trait Start { fn start(self); } impl Start for () { #[inline] fn start(self) {} } impl> Start for Result<(), E> { #[inline] fn start(self) { if let Err(e) = self { crate::throw_val(e.into()); } } } /// An internal helper struct for usage in `#[wasm_bindgen(main)]` /// functions to throw the error (if it is `Err`). pub struct MainWrapper(pub Option); pub trait Main { fn __wasm_bindgen_main(&mut self); } impl Main for &mut &mut MainWrapper<()> { #[inline] fn __wasm_bindgen_main(&mut self) {} } impl Main for &mut &mut MainWrapper { #[inline] fn __wasm_bindgen_main(&mut self) {} } impl> Main for &mut &mut MainWrapper> { #[inline] fn __wasm_bindgen_main(&mut self) { if let Err(e) = self.0.take().unwrap() { crate::throw_val(e.into()); } } } impl Main for &mut MainWrapper> { #[inline] fn __wasm_bindgen_main(&mut self) { if let Err(e) = self.0.take().unwrap() { crate::throw_str(&std::format!("{:?}", e)); } } } } /// A wrapper type around slices and vectors for binding the `Uint8ClampedArray` /// array in JS. /// /// If you need to invoke a JS API which must take `Uint8ClampedArray` array, /// then you can define it as taking one of these types: /// /// * `Clamped<&[u8]>` /// * `Clamped<&mut [u8]>` /// * `Clamped>` /// /// All of these types will show up as `Uint8ClampedArray` in JS and will have /// different forms of ownership in Rust. #[derive(Copy, Clone, PartialEq, Debug, Eq)] pub struct Clamped(pub T); impl Deref for Clamped { type Target = T; fn deref(&self) -> &T { &self.0 } } impl DerefMut for Clamped { fn deref_mut(&mut self) -> &mut T { &mut self.0 } } /// Convenience type for use on exported `fn() -> Result` functions, where you wish to /// throw a JavaScript `Error` object. /// /// You can get wasm_bindgen to throw basic errors by simply returning /// `Err(JsError::new("message"))` from such a function. /// /// For more complex error handling, `JsError` implements `From where T: std::error::Error` by /// converting it to a string, so you can use it with `?`. Many Rust error types already do this, /// and you can use [`thiserror`](https://crates.io/crates/thiserror) to derive Display /// implementations easily or use any number of boxed error types that implement it already. /// /// /// To allow JavaScript code to catch only your errors, you may wish to add a subclass of `Error` /// in a JS module, and then implement `Into` directly on a type and instantiate that /// subclass. In that case, you would not need `JsError` at all. /// /// ### Basic example /// /// ```rust,no_run /// use wasm_bindgen::prelude::*; /// /// #[wasm_bindgen] /// pub fn throwing_function() -> Result<(), JsError> { /// Err(JsError::new("message")) /// } /// ``` /// /// ### Complex Example /// /// ```rust,no_run /// use wasm_bindgen::prelude::*; /// /// #[derive(Debug, Clone)] /// enum MyErrorType { /// SomeError, /// } /// /// use core::fmt; /// impl std::error::Error for MyErrorType {} /// impl fmt::Display for MyErrorType { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// write!(f, "display implementation becomes the error message") /// } /// } /// /// fn internal_api() -> Result<(), MyErrorType> { /// Err(MyErrorType::SomeError) /// } /// /// #[wasm_bindgen] /// pub fn throwing_function() -> Result<(), JsError> { /// internal_api()?; /// Ok(()) /// } /// /// ``` #[derive(Clone)] pub struct JsError { value: JsValue, } impl JsError { /// Construct a JavaScript `Error` object with a string message #[inline] pub fn new(s: &str) -> JsError { Self { value: unsafe { JsValue::_new(crate::__wbindgen_error_new(s.as_ptr(), s.len())) }, } } } if_std! { impl From for JsError where E: std::error::Error, { fn from(error: E) -> Self { JsError::new(&error.to_string()) } } } impl From for JsValue { fn from(error: JsError) -> Self { error.value } } wasm-bindgen-0.2.87/tests/headless/externref_heap_live_count.rs000064400000000000000000000012341046102023000230230ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; // This test is in the headless suite so that we can test the `externref` table // implementation of `externref_heap_live_count` (as opposed to the JS `heap` // implementation) in Firefox. #[wasm_bindgen_test] fn test_externref_heap_live_count() { let initial = wasm_bindgen::externref_heap_live_count(); let after_alloc = { let _vals: Vec<_> = (0..10).map(JsValue::from).collect(); wasm_bindgen::externref_heap_live_count() }; let after_dealloc = wasm_bindgen::externref_heap_live_count(); assert_eq!(initial, after_dealloc); assert_eq!(initial + 10, after_alloc); } wasm-bindgen-0.2.87/tests/headless/main.js000064400000000000000000000000561046102023000165120ustar 00000000000000export function import_export_same_name() { } wasm-bindgen-0.2.87/tests/headless/main.rs000064400000000000000000000024051046102023000165220ustar 00000000000000#![cfg(target_arch = "wasm32")] extern crate wasm_bindgen; extern crate wasm_bindgen_test; use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; wasm_bindgen_test_configure!(run_in_browser); #[wasm_bindgen] pub struct ConsumeRetString; #[wasm_bindgen] impl ConsumeRetString { // https://github.com/rustwasm/wasm-bindgen/issues/329#issuecomment-411082013 // // This used to cause two `const ptr = ...` declarations, which is invalid // JS. pub fn consume(self) -> String { String::new() } } #[wasm_bindgen_test] fn works() { ConsumeRetString.consume(); } #[wasm_bindgen] extern "C" { #[wasm_bindgen(js_namespace = console)] pub fn log(s: &str); } #[wasm_bindgen_test] fn can_log_html_strings() { log(""); } #[wasm_bindgen] pub fn import_export_same_name() { #[wasm_bindgen(module = "/tests/headless/main.js")] extern "C" { fn import_export_same_name(); } import_export_same_name(); } pub mod externref_heap_live_count; pub mod modules; pub mod snippets; pub mod strings; #[wasm_bindgen_test] fn closures_work() { let x = Closure::wrap(Box::new(|| {}) as Box); drop(x); let x = Closure::wrap(Box::new(|| {}) as Box); x.forget(); } wasm-bindgen-0.2.87/tests/headless/modules.js000064400000000000000000000000531046102023000172330ustar 00000000000000export function get_five() { return 5; } wasm-bindgen-0.2.87/tests/headless/modules.rs000064400000000000000000000003521046102023000172450ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(raw_module = "./tests/headless/modules.js")] extern "C" { fn get_five() -> u32; } #[wasm_bindgen_test] fn test_get_five() { assert_eq!(get_five(), 5); } wasm-bindgen-0.2.87/tests/headless/snippets.rs000064400000000000000000000025241046102023000174450ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "/tests/headless/snippets1.js")] extern "C" { fn get_two() -> u32; #[wasm_bindgen(js_name = get_stateful)] fn get_stateful1() -> u32; } #[wasm_bindgen(module = "/tests/headless/snippets1.js")] extern "C" { #[wasm_bindgen(js_name = get_stateful)] fn get_stateful2() -> u32; } #[wasm_bindgen_test] fn test_get_two() { assert_eq!(get_two(), 2); } #[wasm_bindgen_test] fn stateful_deduplicated() { assert_eq!(get_stateful1(), 1); assert_eq!(get_stateful2(), 2); assert_eq!(get_stateful1(), 3); assert_eq!(get_stateful2(), 4); } #[wasm_bindgen(inline_js = "export function get_three() { return 3; }")] extern "C" { fn get_three() -> u32; } #[wasm_bindgen_test] fn test_get_three() { assert_eq!(get_three(), 3); } #[wasm_bindgen(inline_js = "let a = 0; export function get() { a += 1; return a; }")] extern "C" { #[wasm_bindgen(js_name = get)] fn duplicate1() -> u32; } #[wasm_bindgen(inline_js = "let a = 0; export function get() { a += 1; return a; }")] extern "C" { #[wasm_bindgen(js_name = get)] fn duplicate2() -> u32; } #[wasm_bindgen_test] fn duplicate_inline_not_unified() { assert_eq!(duplicate1(), 1); assert_eq!(duplicate2(), 1); assert_eq!(duplicate1(), 2); assert_eq!(duplicate2(), 2); } wasm-bindgen-0.2.87/tests/headless/snippets1.js000064400000000000000000000001571046102023000175160ustar 00000000000000export function get_two() { return 2; } let a = 0; export function get_stateful() { a += 1; return a; } wasm-bindgen-0.2.87/tests/headless/strings.js000064400000000000000000000006111046102023000172540ustar 00000000000000export function test_string_roundtrip(f) { const test = expected => { const actual = f(expected); if (actual === expected) return; throw new Error(`string roundtrip "${actual}" != "${expected}"`); }; test(''); test('a'); test('💖'); test('a longer string'); test('a longer 💖 string'); test('\uFEFFbar'); } export function identity(s) { return s; } wasm-bindgen-0.2.87/tests/headless/strings.rs000064400000000000000000000006171046102023000172720ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "/tests/headless/strings.js")] extern "C" { fn test_string_roundtrip(c: &Closure String>); fn identity(s: &str) -> String; } #[wasm_bindgen_test] fn string_roundtrip() { test_string_roundtrip(&Closure::wrap(Box::new(|s| s))); assert_eq!("\u{feff}bar", &identity("\u{feff}bar")); } wasm-bindgen-0.2.87/tests/must_use.rs000064400000000000000000000003561046102023000156550ustar 00000000000000//! This test validates that the generated bindings don't cause linting warnings //! when used with structs annotated with `#[must_use]`. #![deny(unused)] use wasm_bindgen::prelude::*; #[wasm_bindgen] #[must_use] pub struct MustUse {} wasm-bindgen-0.2.87/tests/non_wasm.rs000064400000000000000000000012021046102023000156210ustar 00000000000000extern crate wasm_bindgen; use wasm_bindgen::prelude::*; #[wasm_bindgen] pub struct A { x: u32, } #[wasm_bindgen] impl A { pub fn new() -> A { A { x: 3 } } pub fn foo(&self) { assert_eq!(self.x, 3); } } #[wasm_bindgen] pub fn foo(x: bool) { A::new().foo(); if x { bar("test"); baz(JsValue::from(3)); } } #[wasm_bindgen] extern "C" { fn some_import(); static A: JsValue; } #[wasm_bindgen] pub fn bar(_: &str) -> JsValue { some_import(); A.clone() } #[wasm_bindgen] pub fn baz(_: JsValue) {} #[test] fn test_foo() { foo(false); A::new().foo(); } wasm-bindgen-0.2.87/tests/std-crate-no-std-dep.rs000064400000000000000000000010411046102023000176370ustar 00000000000000//! This is a test that we can define items in a `#![no_std]` crate when //! `wasm-bindgen` is compiled itself with the `std` feature and everything //! works out just fine. #![no_std] extern crate wasm_bindgen; use wasm_bindgen::prelude::*; #[wasm_bindgen] extern "C" { fn test(a: &str); type Js; #[wasm_bindgen(constructor)] fn new() -> Js; #[wasm_bindgen(method, structural)] fn init(this: &Js); } #[wasm_bindgen] pub struct A {} #[wasm_bindgen] impl A { pub fn foo(&self) {} pub fn bar(&mut self) {} } wasm-bindgen-0.2.87/tests/unwrap_throw.rs000064400000000000000000000006531046102023000165500ustar 00000000000000extern crate wasm_bindgen; use wasm_bindgen::prelude::*; #[test] fn unwrap_throw_ok() { assert_eq!(Some(42).unwrap_throw(), 42); let x: Result = Ok(42); assert_eq!(x.unwrap_throw(), 42); } #[test] #[should_panic] fn unwrap_throw_none() { let x: Option = None; x.unwrap_throw(); } #[test] #[should_panic] fn unwrap_throw_err() { let x: Result = Err(()); x.unwrap_throw(); } wasm-bindgen-0.2.87/tests/wasm/api.js000064400000000000000000000045601046102023000155220ustar 00000000000000const wasm = require('wasm-bindgen-test.js'); const assert = require('assert'); exports.assert_null = x => { assert.strictEqual(x, null); }; exports.js_works = () => { assert.strictEqual(wasm.api_foo(), 'foo'); assert.strictEqual(wasm.api_bar('a'), 'a'); assert.strictEqual(wasm.api_baz(), 1); wasm.api_baz2(2, 'a'); assert.strictEqual(wasm.api_js_null(), null); assert.strictEqual(wasm.api_js_undefined(), undefined); wasm.api_test_is_null_undefined(null, undefined, 1.0); assert.strictEqual(wasm.api_get_true(), true); assert.strictEqual(wasm.api_get_false(), false); wasm.api_test_bool(true, false, 1.0); assert.strictEqual(typeof (wasm.api_mk_symbol()), 'symbol'); assert.strictEqual(typeof (wasm.api_mk_symbol2('a')), 'symbol'); assert.strictEqual(Symbol.keyFor(wasm.api_mk_symbol()), undefined); assert.strictEqual(Symbol.keyFor(wasm.api_mk_symbol2('b')), undefined); wasm.api_assert_symbols(Symbol(), 'a'); wasm.api_acquire_string('foo', null); assert.strictEqual(wasm.api_acquire_string2(''), ''); assert.strictEqual(wasm.api_acquire_string2('a'), 'a'); let arr = [1, 2, 3, 4, {}, ['a', 'b', 'c']] wasm.api_completely_variadic(...arr).forEach((element, index) => { assert.strictEqual(element, arr[index]); }); assert.strictEqual( wasm.api_completely_variadic().length, 0 ); wasm.api_variadic_with_prefixed_params([], {}, ...arr).forEach((element, index) => { assert.strictEqual(element, arr[index]); }); }; exports.js_eq_works = () => { assert.strictEqual(wasm.eq_test('a', 'a'), true); assert.strictEqual(wasm.eq_test('a', 'b'), false); assert.strictEqual(wasm.eq_test(NaN, NaN), false); assert.strictEqual(wasm.eq_test({ a: 'a' }, { a: 'a' }), false); assert.strictEqual(wasm.eq_test1(NaN), false); let x = { a: 'a' }; assert.strictEqual(wasm.eq_test(x, x), true); assert.strictEqual(wasm.eq_test1(x), true); }; exports.debug_values = () => ([ null, undefined, 0, 1.0, true, [1, 2, 3], "string", { test: "object" }, [1.0, [2.0, 3.0]], () => (null), new Set(), ]); exports.assert_function_table = (x, i) => { const rawWasm = require('wasm-bindgen-test.js').__wasm; assert.ok(x instanceof WebAssembly.Table); assert.strictEqual(x.get(i), rawWasm.function_table_lookup); }; wasm-bindgen-0.2.87/tests/wasm/api.rs000064400000000000000000000103011046102023000155200ustar 00000000000000use js_sys::{Uint8Array, WebAssembly}; use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/api.js")] extern "C" { fn js_works(); fn js_eq_works(); fn assert_null(v: JsValue); fn debug_values() -> JsValue; fn assert_function_table(a: JsValue, b: usize); } #[wasm_bindgen_test] fn works() { js_works(); } #[wasm_bindgen] pub fn api_foo() -> JsValue { JsValue::from("foo") } #[wasm_bindgen] pub fn api_bar(s: &str) -> JsValue { JsValue::from(s) } #[wasm_bindgen] pub fn api_baz() -> JsValue { JsValue::from(1.0) } #[wasm_bindgen] pub fn api_baz2(a: &JsValue, b: &JsValue) { assert_eq!(a.as_f64(), Some(2.0)); assert_eq!(b.as_f64(), None); } #[wasm_bindgen] pub fn api_js_null() -> JsValue { JsValue::null() } #[wasm_bindgen] pub fn api_js_undefined() -> JsValue { JsValue::undefined() } #[wasm_bindgen] pub fn api_test_is_null_undefined(a: &JsValue, b: &JsValue, c: &JsValue) { assert!(a.is_null()); assert!(!a.is_undefined()); assert!(!b.is_null()); assert!(b.is_undefined()); assert!(!c.is_null()); assert!(!c.is_undefined()); } #[wasm_bindgen] pub fn api_get_true() -> JsValue { JsValue::from(true) } #[wasm_bindgen] pub fn api_get_false() -> JsValue { JsValue::from(false) } #[wasm_bindgen] pub fn api_test_bool(a: &JsValue, b: &JsValue, c: &JsValue) { assert_eq!(a.as_bool(), Some(true)); assert_eq!(format!("{:?}", a), "JsValue(true)"); assert_eq!(b.as_bool(), Some(false)); assert_eq!(c.as_bool(), None); } #[wasm_bindgen] pub fn api_mk_symbol() -> JsValue { let a = JsValue::symbol(None); assert!(a.is_symbol()); assert_eq!(format!("{:?}", a), "JsValue(Symbol)"); a } #[wasm_bindgen] pub fn api_mk_symbol2(s: &str) -> JsValue { let a = JsValue::symbol(Some(s)); assert!(a.is_symbol()); a } #[wasm_bindgen] pub fn api_assert_symbols(a: &JsValue, b: &JsValue) { assert!(a.is_symbol()); assert!(!b.is_symbol()); } #[wasm_bindgen] pub fn api_acquire_string(a: &JsValue, b: &JsValue) { assert_eq!(a.as_string().unwrap(), "foo"); assert_eq!(format!("{:?}", a), "JsValue(\"foo\")"); assert_eq!(b.as_string(), None); } #[wasm_bindgen] pub fn api_acquire_string2(a: &JsValue) -> String { a.as_string().unwrap_or("wrong".to_string()) } #[wasm_bindgen_test] fn eq_works() { js_eq_works(); } #[wasm_bindgen] pub fn eq_test(a: &JsValue, b: &JsValue) -> bool { a == b } #[wasm_bindgen] #[allow(clippy::eq_op)] pub fn eq_test1(a: &JsValue) -> bool { a == a } #[wasm_bindgen(variadic)] pub fn api_completely_variadic(args: &JsValue) -> JsValue { args.into() } #[wasm_bindgen(variadic)] pub fn api_variadic_with_prefixed_params( _first: &JsValue, _second: &JsValue, args: &JsValue, ) -> JsValue { args.into() } #[wasm_bindgen_test] fn null_keeps_working() { assert_null(JsValue::null()); assert_null(JsValue::null()); } #[wasm_bindgen_test] fn memory_accessor_appears_to_work() { let data = 3u32; let ptr = &data as *const u32 as u32; let my_mem = wasm_bindgen::memory(); let mem = my_mem.dyn_into::().unwrap(); let buf = mem.buffer(); let slice = Uint8Array::new(&buf); let mut v = Vec::new(); slice .subarray(ptr, ptr + 4) .for_each(&mut |val, _, _| v.push(val)); assert_eq!(v, [3, 0, 0, 0]); } #[wasm_bindgen_test] fn debug_output() { let test_iter = debug_values() .dyn_into::() .unwrap() .values() .into_iter(); let expecteds = vec![ "JsValue(null)", "JsValue(undefined)", "JsValue(0)", "JsValue(1)", "JsValue(true)", "JsValue([1, 2, 3])", "JsValue(\"string\")", "JsValue(Object({\"test\":\"object\"}))", "JsValue([1, [2, 3]])", "JsValue(Function)", "JsValue(Set)", ]; for (test, expected) in test_iter.zip(expecteds) { assert_eq!(format!("{:?}", test.unwrap()), expected); } } #[wasm_bindgen_test] fn function_table_is() { assert_function_table( wasm_bindgen::function_table(), function_table_lookup as usize, ); } #[no_mangle] pub extern "C" fn function_table_lookup() {} wasm-bindgen-0.2.87/tests/wasm/arg_names.js000064400000000000000000000010741046102023000167020ustar 00000000000000const wasm = require('wasm-bindgen-test.js'); const assert = require('assert'); const ARGUMENT_NAMES = /([^\s,]+)/g; const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; // https://stackoverflow.com/q/1007981/210304 function getArgNames(func) { let fnStr = func.toString().replace(STRIP_COMMENTS, ''); let result = fnStr.slice(fnStr.indexOf('(')+1, fnStr.indexOf(')')).match(ARGUMENT_NAMES); return result === null ? [] : result; } exports.js_arg_names = () => { assert.deepEqual(getArgNames(wasm.fn_with_many_args), ['_a', '_b', '_c', '_d']); }; wasm-bindgen-0.2.87/tests/wasm/arg_names.rs000064400000000000000000000004461046102023000167140ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/arg_names.js")] extern "C" { fn js_arg_names(); } #[wasm_bindgen] pub fn fn_with_many_args(_a: i32, _b: i32, _c: i32, _d: i32) {} #[wasm_bindgen_test] fn rust_arg_names() { js_arg_names(); } wasm-bindgen-0.2.87/tests/wasm/bigint.js000064400000000000000000000042341046102023000162230ustar 00000000000000const wasm = require('wasm-bindgen-test.js'); const assert = require('assert'); exports.i64_js_identity = a => a; exports.u64_js_identity = a => a; exports.js_works = () => { assert.strictEqual(wasm.zero(), BigInt('0')); assert.strictEqual(wasm.one(), BigInt('1')); assert.strictEqual(wasm.neg_one(), BigInt('-1')); assert.strictEqual(wasm.i32_min(), BigInt('-2147483648')); assert.strictEqual(wasm.u32_max(), BigInt('4294967295')); assert.strictEqual(wasm.i64_min(), BigInt('-9223372036854775808')); assert.strictEqual(wasm.u64_max(), BigInt('18446744073709551615')); const i64_min = BigInt('-9223372036854775808'); const u64_max = BigInt('18446744073709551615'); const identityTestI64Values = [ BigInt('0'), BigInt('1'), BigInt('-1'), i64_min, ]; for (const value of identityTestI64Values) { assert.strictEqual(wasm.i64_rust_identity(value), value); assert.strictEqual(wasm.i64_jsvalue_identity(value), value); } const identityTestU64Values = [ BigInt('0'), BigInt('1'), u64_max, ]; for (const value of identityTestU64Values) { assert.strictEqual(wasm.u64_rust_identity(value), value); assert.strictEqual(wasm.u64_jsvalue_identity(value), value); } assert.strictEqual(wasm.u64_rust_identity(BigInt('1') << BigInt('64')), BigInt('0')); assert.strictEqual(wasm.i128_min_jsvalue(), BigInt('-170141183460469231731687303715884105728')); assert.strictEqual(wasm.u128_max_jsvalue(), BigInt('340282366920938463463374607431768211455')); assert.deepStrictEqual(wasm.u64_slice([]), new BigUint64Array()); assert.deepStrictEqual(wasm.i64_slice([]), new BigInt64Array()); const arr1 = new BigUint64Array([BigInt('1'), BigInt('2')]); assert.deepStrictEqual(wasm.u64_slice([BigInt('1'), BigInt('2')]), arr1); const arr2 = new BigInt64Array([BigInt('1'), BigInt('2')]); assert.deepStrictEqual(wasm.i64_slice([BigInt('1'), BigInt('2')]), arr2); assert.deepStrictEqual(wasm.i64_slice([i64_min]), new BigInt64Array([i64_min])); assert.deepStrictEqual(wasm.u64_slice([u64_max]), new BigUint64Array([u64_max])); }; wasm-bindgen-0.2.87/tests/wasm/bigint.rs000064400000000000000000000045721046102023000162400ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/bigint.js")] extern "C" { fn i64_js_identity(a: i64) -> i64; fn u64_js_identity(a: u64) -> u64; fn js_works(); } #[wasm_bindgen] pub fn zero() -> u64 { 0 } #[wasm_bindgen] pub fn one() -> u64 { 1 } #[wasm_bindgen] pub fn neg_one() -> i64 { -1 } #[wasm_bindgen] pub fn i32_min() -> i64 { i32::min_value() as i64 } #[wasm_bindgen] pub fn u32_max() -> u64 { u32::max_value() as u64 } #[wasm_bindgen] pub fn i64_min() -> i64 { i64::min_value() } #[wasm_bindgen] pub fn u64_max() -> u64 { u64::max_value() } #[wasm_bindgen] pub fn i64_rust_identity(a: i64) -> i64 { i64_js_identity(a) } #[wasm_bindgen] pub fn u64_rust_identity(a: u64) -> u64 { u64_js_identity(a) } #[wasm_bindgen] pub fn i64_jsvalue_identity(a: i64) -> JsValue { JsValue::from(a) } #[wasm_bindgen] pub fn u64_jsvalue_identity(a: u64) -> JsValue { JsValue::from(a) } #[wasm_bindgen] pub fn i128_min_jsvalue() -> JsValue { JsValue::from(i128::min_value()) } #[wasm_bindgen] pub fn u128_max_jsvalue() -> JsValue { JsValue::from(u128::max_value()) } #[wasm_bindgen] pub fn i64_slice(a: &[i64]) -> Vec { a.to_vec() } #[wasm_bindgen] pub fn u64_slice(a: &[u64]) -> Vec { a.to_vec() } #[wasm_bindgen_test] fn works() { js_works(); } mod try_from_works { use super::*; use crate::JsValue; use core::convert::TryFrom; macro_rules! test_type_boundaries { ($($ty:ident)*) => { $( #[wasm_bindgen_test] fn $ty() { // Not a bigint. assert!($ty::try_from(JsValue::NULL).is_err()); assert!($ty::try_from(JsValue::from_f64(0.0)).is_err()); // Within range. assert_eq!($ty::try_from(JsValue::from($ty::MIN)), Ok($ty::MIN)); // Too small. assert!($ty::try_from(JsValue::from($ty::MIN) - JsValue::from(1_i64)).is_err()); // Within range. assert_eq!($ty::try_from(JsValue::from($ty::MAX)), Ok($ty::MAX)); // Too large. assert!($ty::try_from(JsValue::from($ty::MAX) + JsValue::from(1_i64)).is_err()); } )* }; } test_type_boundaries!(i64 u64 i128 u128); } wasm-bindgen-0.2.87/tests/wasm/char.js000064400000000000000000000011661046102023000156650ustar 00000000000000const wasm = require('wasm-bindgen-test.js'); const assert = require('assert'); exports.js_identity = a => a; exports.js_works = () => { assert.strictEqual(wasm.letter(), 'a'); assert.strictEqual(wasm.face(), '😀'); assert.strictEqual(wasm.rust_identity('Õ‚'), 'Õ‚'); assert.strictEqual(wasm.rust_identity('Ò'), 'Ò'); assert.strictEqual(wasm.rust_identity('Δ'), 'Δ'); assert.strictEqual(wasm.rust_identity('䉨'), '䉨'); assert.strictEqual(wasm.rust_js_identity('a'), 'a'); assert.strictEqual(wasm.rust_js_identity('㊻'), '㊻'); wasm.rust_letter('a'); wasm.rust_face('😀'); }; wasm-bindgen-0.2.87/tests/wasm/char.rs000064400000000000000000000011641046102023000156730ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/char.js")] extern "C" { fn js_identity(c: char) -> char; fn js_works(); } #[wasm_bindgen] pub fn rust_identity(c: char) -> char { c } #[wasm_bindgen] pub fn rust_js_identity(c: char) -> char { js_identity(c) } #[wasm_bindgen] pub fn letter() -> char { 'a' } #[wasm_bindgen] pub fn face() -> char { '😀' } #[wasm_bindgen] pub fn rust_letter(a: char) { assert_eq!(a, 'a'); } #[wasm_bindgen] pub fn rust_face(p: char) { assert_eq!(p, '😀'); } #[wasm_bindgen_test] fn works() { js_works(); } wasm-bindgen-0.2.87/tests/wasm/classes.js000064400000000000000000000166731046102023000164160ustar 00000000000000const wasm = require('wasm-bindgen-test.js'); const assert = require('assert'); exports.js_simple = () => { const r = new wasm.ClassesSimple(); assert.strictEqual(r.add(0), 0); assert.strictEqual(r.add(1), 1); assert.strictEqual(r.add(1), 2); r.add(2); assert.strictEqual(r.consume(), 4); assert.throws(() => r.free(), /null pointer passed to rust/); const r2 = wasm.ClassesSimple.with_contents(10); assert.strictEqual(r2.add(1), 11); assert.strictEqual(r2.add(2), 13); assert.strictEqual(r2.add(3), 16); r2.free(); const r3 = new wasm.ClassesSimple(); assert.strictEqual(r3.add(42), 42); r3.free(); }; exports.js_strings = () => { const r = wasm.ClassesStrings1.new(); r.set(3); let bar = r.bar('baz'); r.free(); assert.strictEqual(bar.name(), 'foo-baz-3'); bar.free(); }; exports.js_exceptions = () => { // this test only works when `--debug` is passed to `wasm-bindgen` (or the // equivalent thereof) if (require('process').env.WASM_BINDGEN_NO_DEBUG) return; assert.throws(() => new wasm.ClassesExceptions1(), /cannot invoke `new` directly/); let a = wasm.ClassesExceptions1.new(); a.free(); assert.throws(() => a.free(), /null pointer passed to rust/); let b = wasm.ClassesExceptions1.new(); b.foo(b); assert.throws(() => b.bar(b), /recursive use of an object/); // TODO: throws because it tries to borrow_mut, but the throw_str from the previous line doesn't clean up the // RefMut so the object is left in a broken state. // We still try to call free here so the object is removed from the FinalizationRegistry when weak refs are enabled. assert.throws(() => b.free(), /recursive use of an object/); let c = wasm.ClassesExceptions1.new(); let d = wasm.ClassesExceptions2.new(); assert.throws(() => c.foo(d), /expected instance of ClassesExceptions1/); d.free(); c.free(); }; exports.js_pass_one_to_another = () => { let a = wasm.ClassesPassA.new(); let b = wasm.ClassesPassB.new(); a.foo(b); a.bar(b); a.free(); }; exports.take_class = foo => { assert.strictEqual(foo.inner(), 13); foo.free(); assert.throws(() => foo.free(), /null pointer passed to rust/); }; exports.js_constructors = () => { const foo = new wasm.ConstructorsFoo(1); assert.strictEqual(foo.get_number(), 1); foo.free(); assert.strictEqual(wasm.ConstructorsBar.new, undefined); const foo2 = new wasm.ConstructorsFoo(2); assert.strictEqual(foo2.get_number(), 2); foo2.free(); const bar = new wasm.ConstructorsBar(3, 4); assert.strictEqual(bar.get_sum(), 7); bar.free(); assert.strictEqual(wasm.ConstructorsBar.other_name, undefined); const bar2 = new wasm.ConstructorsBar(5, 6); assert.strictEqual(bar2.get_sum(), 11); bar2.free(); assert.strictEqual(wasm.cross_item_construction().get_sum(), 15); }; exports.js_empty_structs = () => { wasm.OtherEmpty.return_a_value(); }; exports.js_public_fields = () => { const a = wasm.PublicFields.new(); assert.strictEqual(a.a, 0); a.a = 3; assert.strictEqual(a.a, 3); assert.strictEqual(a.b, 0); a.b = 7; assert.strictEqual(a.b, 7); assert.strictEqual(a.c, 0); a.c = 8; assert.strictEqual(a.c, 8); assert.strictEqual(a.d, 0); a.d = 3.3; assert.strictEqual(a.d, 3); assert.strictEqual(a.skipped, undefined); }; exports.js_getter_with_clone = () => { const a = wasm.GetterWithCloneStruct.new(); assert.strictEqual(a.a, ''); a.a = 'foo'; assert.strictEqual(a.a, 'foo'); const b = wasm.GetterWithCloneStructField.new(); assert.strictEqual(b.a, ''); b.a = 'foo'; assert.strictEqual(b.a, 'foo'); }; exports.js_using_self = () => { wasm.UseSelf.new().free(); }; exports.js_readonly_fields = () => { const a = wasm.Readonly.new(); assert.strictEqual(a.a, 0); a.a = 3; assert.strictEqual(a.a, 0); a.free(); }; exports.js_double_consume = () => { const r = new wasm.DoubleConsume(); assert.throws(() => r.consume(r)); }; exports.js_js_rename = () => { (new wasm.JsRename()).bar(); wasm.classes_foo(); }; exports.js_access_fields = () => { assert.ok((new wasm.AccessFieldFoo()).bar instanceof wasm.AccessFieldBar); assert.ok((new wasm.AccessField0())[0] instanceof wasm.AccessFieldBar); }; exports.js_renamed_export = () => { const x = new wasm.JsRenamedExport(); assert.ok(x.x === 3); x.foo(); x.bar(x); }; exports.js_renamed_field = () => { const x = new wasm.RenamedField(); assert.ok(x.bar === 3); x.foo(); } exports.js_conditional_bindings = () => { const x = new wasm.ConditionalBindings(); x.free(); }; exports.js_assert_none = x => { assert.strictEqual(x, undefined); }; exports.js_assert_some = x => { assert.ok(x instanceof wasm.OptionClass); }; exports.js_return_none1 = () => null; exports.js_return_none2 = () => undefined; exports.js_return_some = x => x; exports.js_test_option_classes = () => { assert.strictEqual(wasm.option_class_none(), undefined); wasm.option_class_assert_none(undefined); wasm.option_class_assert_none(null); const c = wasm.option_class_some(); assert.ok(c instanceof wasm.OptionClass); wasm.option_class_assert_some(c); }; /** * Invokes `console.log`, but logs to a string rather than stdout * @param {any} data Data to pass to `console.log` * @returns {string} Output from `console.log`, without color or trailing newlines */ const console_log_to_string = data => { // Store the original stdout.write and create a console that logs without color const original_write = process.stdout.write; const colorless_console = new console.Console({ stdout: process.stdout, colorMode: false }); let output = ''; // Change stdout.write to append to our string, then restore the original function process.stdout.write = chunk => output += chunk.trim(); colorless_console.log(data); process.stdout.write = original_write; return output; }; exports.js_test_inspectable_classes = () => { const inspectable = wasm.Inspectable.new(); const not_inspectable = wasm.NotInspectable.new(); // Inspectable classes have a toJSON and toString implementation generated assert.deepStrictEqual(inspectable.toJSON(), { a: inspectable.a }); assert.strictEqual(inspectable.toString(), `{"a":${inspectable.a}}`); // Inspectable classes in Node.js have improved console.log formatting as well assert(console_log_to_string(inspectable).endsWith(`{ a: ${inspectable.a} }`)); // Non-inspectable classes do not have a toJSON or toString generated assert.strictEqual(not_inspectable.toJSON, undefined); assert.strictEqual(not_inspectable.toString(), '[object Object]'); // Non-inspectable classes in Node.js have no special console.log formatting assert.strictEqual(console_log_to_string(not_inspectable), `NotInspectable { __wbg_ptr: ${not_inspectable.__wbg_ptr} }`); inspectable.free(); not_inspectable.free(); }; exports.js_test_inspectable_classes_can_override_generated_methods = () => { const overridden_inspectable = wasm.OverriddenInspectable.new(); // Inspectable classes can have the generated toJSON and toString overwritten assert.strictEqual(overridden_inspectable.a, 0); assert.deepStrictEqual(overridden_inspectable.toJSON(), 'JSON was overwritten'); assert.strictEqual(overridden_inspectable.toString(), 'string was overwritten'); overridden_inspectable.free(); }; wasm-bindgen-0.2.87/tests/wasm/classes.rs000064400000000000000000000261571046102023000164240ustar 00000000000000#[allow(unused_imports)] // test for #919 use std::borrow::BorrowMut; use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/classes.js")] extern "C" { fn js_simple(); fn js_strings(); fn js_exceptions(); fn js_pass_one_to_another(); fn take_class(foo: ClassesIntoJs); #[wasm_bindgen(js_name = take_class)] fn take_class_as_jsvalue(foo: JsValue); fn js_constructors(); fn js_empty_structs(); fn js_public_fields(); fn js_getter_with_clone(); fn js_using_self(); fn js_readonly_fields(); fn js_double_consume(); fn js_js_rename(); fn js_access_fields(); fn js_renamed_export(); fn js_renamed_field(); fn js_conditional_bindings(); fn js_assert_none(a: Option); fn js_assert_some(a: Option); fn js_return_none1() -> Option; fn js_return_none2() -> Option; fn js_return_some(a: OptionClass) -> Option; fn js_test_option_classes(); fn js_test_inspectable_classes(); fn js_test_inspectable_classes_can_override_generated_methods(); } #[wasm_bindgen_test] fn simple() { js_simple(); } #[wasm_bindgen] pub struct ClassesSimple { contents: u32, } #[wasm_bindgen] impl ClassesSimple { #[wasm_bindgen(constructor)] pub fn new() -> ClassesSimple { ClassesSimple::with_contents(0) } pub fn with_contents(a: u32) -> ClassesSimple { ClassesSimple { contents: a } } pub fn add(&mut self, amt: u32) -> u32 { self.contents += amt; self.contents } pub fn consume(self) -> u32 { self.contents } } #[wasm_bindgen_test] fn strings() { js_strings() } #[wasm_bindgen] pub struct ClassesStrings1 { name: u32, } #[wasm_bindgen] pub struct ClassesStrings2 { contents: String, } #[wasm_bindgen] impl ClassesStrings1 { pub fn new() -> ClassesStrings1 { ClassesStrings1 { name: 0 } } pub fn set(&mut self, amt: u32) { self.name = amt; } pub fn bar(&self, mix: &str) -> ClassesStrings2 { ClassesStrings2 { contents: format!("foo-{}-{}", mix, self.name), } } } #[wasm_bindgen] impl ClassesStrings2 { pub fn name(&self) -> String { self.contents.clone() } } #[wasm_bindgen_test] fn exceptions() { js_exceptions(); } #[wasm_bindgen] pub struct ClassesExceptions1 {} #[wasm_bindgen] impl ClassesExceptions1 { pub fn new() -> ClassesExceptions1 { ClassesExceptions1 {} } pub fn foo(&self, _: &ClassesExceptions1) {} pub fn bar(&mut self, _: &mut ClassesExceptions1) {} } #[wasm_bindgen] pub struct ClassesExceptions2 {} #[wasm_bindgen] impl ClassesExceptions2 { pub fn new() -> ClassesExceptions2 { ClassesExceptions2 {} } } #[wasm_bindgen_test] fn pass_one_to_another() { js_pass_one_to_another(); } #[wasm_bindgen] pub struct ClassesPassA {} #[wasm_bindgen] impl ClassesPassA { pub fn new() -> ClassesPassA { ClassesPassA {} } pub fn foo(&self, _other: &ClassesPassB) {} pub fn bar(&self, _other: ClassesPassB) {} } #[wasm_bindgen] pub struct ClassesPassB {} #[wasm_bindgen] impl ClassesPassB { pub fn new() -> ClassesPassB { ClassesPassB {} } } #[wasm_bindgen_test] fn pass_into_js() { take_class(ClassesIntoJs(13)); } #[wasm_bindgen] pub struct ClassesIntoJs(i32); #[wasm_bindgen] impl ClassesIntoJs { pub fn inner(&self) -> i32 { self.0 } } #[wasm_bindgen] pub struct Issue27Context {} #[wasm_bindgen] impl Issue27Context { pub fn parse(&self, _expr: &str) -> Issue27Expr { panic!() } pub fn eval(&self, _expr: &Issue27Expr) -> f64 { panic!() } pub fn set(&mut self, _var: &str, _val: f64) { panic!() } } #[wasm_bindgen] pub struct Issue27Expr {} #[wasm_bindgen_test] fn pass_into_js_as_js_class() { take_class_as_jsvalue(ClassesIntoJs(13).into()); } #[wasm_bindgen_test] fn constructors() { js_constructors(); } #[wasm_bindgen] pub fn cross_item_construction() -> ConstructorsBar { ConstructorsBar::other_name(7, 8) } #[wasm_bindgen] pub struct ConstructorsFoo { number: u32, } #[wasm_bindgen] impl ConstructorsFoo { #[wasm_bindgen(constructor)] pub fn new(number: u32) -> ConstructorsFoo { ConstructorsFoo { number } } pub fn get_number(&self) -> u32 { self.number } } #[wasm_bindgen] pub struct ConstructorsBar { number: u32, number2: u32, } #[wasm_bindgen] impl ConstructorsBar { #[wasm_bindgen(constructor)] pub fn other_name(number: u32, number2: u32) -> ConstructorsBar { ConstructorsBar { number, number2 } } pub fn get_sum(&self) -> u32 { self.number + self.number2 } } #[wasm_bindgen_test] fn empty_structs() { js_empty_structs(); } #[wasm_bindgen] pub struct MissingClass {} #[wasm_bindgen] pub struct OtherEmpty {} #[wasm_bindgen] impl OtherEmpty { pub fn return_a_value() -> MissingClass { MissingClass {} } } #[wasm_bindgen_test] fn public_fields() { js_public_fields(); } #[wasm_bindgen] #[derive(Default)] pub struct PublicFields { pub a: u32, pub b: f32, pub c: f64, pub d: i32, #[wasm_bindgen(skip)] pub skipped: u32, } #[wasm_bindgen] impl PublicFields { pub fn new() -> PublicFields { PublicFields::default() } } #[wasm_bindgen_test] fn getter_with_clone() { js_getter_with_clone(); } #[wasm_bindgen(getter_with_clone)] #[derive(Default)] pub struct GetterWithCloneStruct { pub a: String, } #[wasm_bindgen] impl GetterWithCloneStruct { pub fn new() -> GetterWithCloneStruct { GetterWithCloneStruct::default() } } #[wasm_bindgen] #[derive(Default)] pub struct GetterWithCloneStructField { #[wasm_bindgen(getter_with_clone)] pub a: String, } #[wasm_bindgen] impl GetterWithCloneStructField { pub fn new() -> GetterWithCloneStructField { GetterWithCloneStructField::default() } } #[wasm_bindgen_test] fn using_self() { js_using_self(); } #[wasm_bindgen] pub struct UseSelf {} #[wasm_bindgen] impl UseSelf { pub fn new() -> Self { UseSelf {} } } #[wasm_bindgen_test] fn readonly_fields() { js_readonly_fields(); } #[wasm_bindgen] #[derive(Default)] pub struct Readonly { #[wasm_bindgen(readonly)] pub a: u32, } #[wasm_bindgen] impl Readonly { pub fn new() -> Readonly { Readonly::default() } } #[wasm_bindgen_test] fn double_consume() { js_double_consume(); } #[wasm_bindgen] pub struct DoubleConsume {} #[wasm_bindgen] impl DoubleConsume { #[wasm_bindgen(constructor)] pub fn new() -> DoubleConsume { DoubleConsume {} } pub fn consume(self, other: DoubleConsume) { drop(other); } } #[wasm_bindgen_test] fn rename_function_for_js() { js_js_rename(); foo(); } #[wasm_bindgen] pub struct JsRename {} #[wasm_bindgen] impl JsRename { #[wasm_bindgen(constructor)] pub fn new() -> JsRename { let f = JsRename {}; f.foo(); f } #[wasm_bindgen(js_name = bar)] pub fn foo(&self) {} } #[wasm_bindgen(js_name = classes_foo)] pub fn foo() {} #[wasm_bindgen] pub struct AccessFieldFoo { pub bar: AccessFieldBar, } #[wasm_bindgen] pub struct AccessField0(pub AccessFieldBar); #[wasm_bindgen] #[derive(Copy, Clone)] pub struct AccessFieldBar { _value: u32, } #[wasm_bindgen] impl AccessFieldFoo { #[wasm_bindgen(constructor)] pub fn new() -> AccessFieldFoo { AccessFieldFoo { bar: AccessFieldBar { _value: 2 }, } } } #[wasm_bindgen] impl AccessField0 { #[wasm_bindgen(constructor)] pub fn new() -> AccessField0 { AccessField0(AccessFieldBar { _value: 2 }) } } #[wasm_bindgen_test] fn access_fields() { js_access_fields(); } #[wasm_bindgen(js_name = JsRenamedExport)] pub struct RenamedExport { pub x: u32, } #[wasm_bindgen(js_class = JsRenamedExport)] impl RenamedExport { #[wasm_bindgen(constructor)] pub fn new() -> RenamedExport { RenamedExport { x: 3 } } pub fn foo(&self) {} pub fn bar(&self, other: &RenamedExport) { drop(other); } } #[wasm_bindgen_test] fn renamed_export() { js_renamed_export(); } #[wasm_bindgen] pub struct RenamedField { #[wasm_bindgen(js_name = bar)] pub foo: u32, } #[wasm_bindgen(js_class = RenamedField)] impl RenamedField { #[wasm_bindgen(constructor)] pub fn new() -> RenamedField { RenamedField { foo: 3 } } pub fn foo(&self) {} } #[wasm_bindgen_test] fn renamed_field() { js_renamed_field(); } #[cfg_attr(target_arch = "wasm32", wasm_bindgen)] pub struct ConditionalBindings {} #[cfg_attr(target_arch = "wasm32", wasm_bindgen)] impl ConditionalBindings { #[cfg_attr(target_arch = "wasm32", wasm_bindgen(constructor))] pub fn new() -> ConditionalBindings { ConditionalBindings {} } } #[wasm_bindgen_test] fn conditional_bindings() { js_conditional_bindings(); } #[wasm_bindgen] pub struct OptionClass(u32); #[wasm_bindgen_test] fn option_class() { js_assert_none(None); js_assert_some(Some(OptionClass(1))); assert!(js_return_none1().is_none()); assert!(js_return_none2().is_none()); assert_eq!(js_return_some(OptionClass(2)).unwrap().0, 2); js_test_option_classes(); } #[wasm_bindgen] pub fn option_class_none() -> Option { None } #[wasm_bindgen] pub fn option_class_some() -> Option { Some(OptionClass(3)) } #[wasm_bindgen] pub fn option_class_assert_none(x: Option) { assert!(x.is_none()); } #[wasm_bindgen] pub fn option_class_assert_some(x: Option) { assert_eq!(x.unwrap().0, 3); } mod works_in_module { use wasm_bindgen::prelude::wasm_bindgen; #[wasm_bindgen] pub struct WorksInModule(u32); #[wasm_bindgen] impl WorksInModule { #[wasm_bindgen(constructor)] pub fn new() -> WorksInModule { WorksInModule(1) } pub fn foo(&self) {} } } #[wasm_bindgen_test] fn inspectable_classes() { js_test_inspectable_classes(); } #[wasm_bindgen(inspectable)] #[derive(Default)] pub struct Inspectable { pub a: u32, // This private field will not be exposed unless a getter is provided for it #[allow(dead_code)] private: u32, } #[wasm_bindgen] impl Inspectable { pub fn new() -> Self { Self::default() } } #[wasm_bindgen] #[derive(Default)] pub struct NotInspectable { pub a: u32, } #[wasm_bindgen] impl NotInspectable { pub fn new() -> Self { Self::default() } } #[wasm_bindgen_test] fn inspectable_classes_can_override_generated_methods() { js_test_inspectable_classes_can_override_generated_methods(); } #[wasm_bindgen(inspectable)] #[derive(Default)] pub struct OverriddenInspectable { pub a: u32, } #[wasm_bindgen] impl OverriddenInspectable { pub fn new() -> Self { Self::default() } #[wasm_bindgen(js_name = toJSON)] pub fn js_to_json(&self) -> String { String::from("JSON was overwritten") } #[wasm_bindgen(js_name = toString)] pub fn js_to_string(&self) -> String { String::from("string was overwritten") } } wasm-bindgen-0.2.87/tests/wasm/closures.js000064400000000000000000000055721046102023000166140ustar 00000000000000const assert = require('assert'); const wasm = require('wasm-bindgen-test'); exports.works_call = a => { a(); }; exports.works_thread = a => a(2); let CANNOT_REUSE_CACHE = null; exports.cannot_reuse_call = a => { CANNOT_REUSE_CACHE = a; }; exports.cannot_reuse_call_again = () => { CANNOT_REUSE_CACHE(); }; exports.long_lived_call1 = a => { a(); }; exports.long_lived_call2 = a => a(2); exports.many_arity_call1 = a => { a(); }; exports.many_arity_call2 = a => { a(1); }; exports.many_arity_call3 = a => { a(1, 2); }; exports.many_arity_call4 = a => { a(1, 2, 3); }; exports.many_arity_call5 = a => { a(1, 2, 3, 4); }; exports.many_arity_call6 = a => { a(1, 2, 3, 4, 5); }; exports.many_arity_call7 = a => { a(1, 2, 3, 4, 5, 6); }; exports.many_arity_call8 = a => { a(1, 2, 3, 4, 5, 6, 7); }; exports.many_arity_call9 = a => { a(1, 2, 3, 4, 5, 6, 7, 8); }; exports.option_call1 = a => { if (a) { a(); } }; exports.option_call2 = a => { if (a) { return a(2); } }; exports.option_call3 = a => a == undefined; let LONG_LIVED_DROPPING_CACHE = null; exports.long_lived_dropping_cache = a => { LONG_LIVED_DROPPING_CACHE = a; }; exports.long_lived_dropping_call = () => { LONG_LIVED_DROPPING_CACHE(); }; let LONG_LIVED_OPTION_DROPPING_CACHE = null; exports.long_lived_option_dropping_cache = a => { if (a) { LONG_LIVED_OPTION_DROPPING_CACHE = a; return true; } else { return false; } } exports.long_lived_option_dropping_call = () => { LONG_LIVED_OPTION_DROPPING_CACHE(); } let LONG_FNMUT_RECURSIVE_CACHE = null; exports.long_fnmut_recursive_cache = a => { LONG_FNMUT_RECURSIVE_CACHE = a; }; exports.long_fnmut_recursive_call = () => { LONG_FNMUT_RECURSIVE_CACHE(); }; exports.fnmut_call = a => { a(); }; exports.fnmut_thread = a => a(2); let FNMUT_BAD_F = null; exports.fnmut_bad_call = a => { FNMUT_BAD_F = a; a(); }; exports.fnmut_bad_again = x => { if (x) { FNMUT_BAD_F(); } }; exports.string_arguments_call = a => { a('foo'); }; exports.string_ret_call = a => { assert.strictEqual(a('foo'), 'foobar'); }; let DROP_DURING_CALL = null; exports.drop_during_call_save = f => { DROP_DURING_CALL = f; }; exports.drop_during_call_call = () => DROP_DURING_CALL(); exports.js_test_closure_returner = () => { wasm.closure_returner().someKey(); }; exports.calling_it_throws = a => { try { a(); return false; } catch(_) { return true; } }; exports.call_val = f => f(); exports.pass_reference_first_arg_twice = (a, b, c) => { b(a); c(a); a.free(); }; exports.call_destroyed = f => { assert.throws(f, /closure invoked.*after being dropped/); }; let FORGOTTEN_CLOSURE = null; exports.js_store_forgotten_closure = f => { FORGOTTEN_CLOSURE = f; }; exports.js_call_forgotten_closure = () => { FORGOTTEN_CLOSURE(); }; wasm-bindgen-0.2.87/tests/wasm/closures.rs000064400000000000000000000446061046102023000166250ustar 00000000000000use js_sys::Number; use std::cell::{Cell, RefCell}; use std::rc::Rc; use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/closures.js")] extern "C" { fn works_call(a: &dyn Fn()); fn works_thread(a: &dyn Fn(u32) -> u32) -> u32; fn cannot_reuse_call(a: &dyn Fn()); #[wasm_bindgen(catch)] fn cannot_reuse_call_again() -> Result<(), JsValue>; fn long_lived_call1(a: &Closure); fn long_lived_call2(a: &Closure u32>) -> u32; fn many_arity_call1(a: &Closure); fn many_arity_call2(a: &Closure); fn many_arity_call3(a: &Closure); fn many_arity_call4(a: &Closure); fn many_arity_call5(a: &Closure); fn many_arity_call6(a: &Closure); fn many_arity_call7(a: &Closure); fn many_arity_call8(a: &Closure); fn many_arity_call9(a: &Closure); #[wasm_bindgen(js_name = many_arity_call1)] fn many_arity_call_mut1(a: &Closure); #[wasm_bindgen(js_name = many_arity_call2)] fn many_arity_call_mut2(a: &Closure); #[wasm_bindgen(js_name = many_arity_call3)] fn many_arity_call_mut3(a: &Closure); #[wasm_bindgen(js_name = many_arity_call4)] fn many_arity_call_mut4(a: &Closure); #[wasm_bindgen(js_name = many_arity_call5)] fn many_arity_call_mut5(a: &Closure); #[wasm_bindgen(js_name = many_arity_call6)] fn many_arity_call_mut6(a: &Closure); #[wasm_bindgen(js_name = many_arity_call7)] fn many_arity_call_mut7(a: &Closure); #[wasm_bindgen(js_name = many_arity_call8)] fn many_arity_call_mut8(a: &Closure); #[wasm_bindgen(js_name = many_arity_call9)] fn many_arity_call_mut9(a: &Closure); fn option_call1(a: Option<&Closure>); fn option_call2(a: Option<&Closure u32>>) -> u32; fn option_call3(a: Option<&Closure>) -> bool; #[wasm_bindgen(js_name = many_arity_call1)] fn many_arity_stack1(a: &dyn Fn()); #[wasm_bindgen(js_name = many_arity_call2)] fn many_arity_stack2(a: &dyn Fn(u32)); #[wasm_bindgen(js_name = many_arity_call3)] fn many_arity_stack3(a: &dyn Fn(u32, u32)); #[wasm_bindgen(js_name = many_arity_call4)] fn many_arity_stack4(a: &dyn Fn(u32, u32, u32)); #[wasm_bindgen(js_name = many_arity_call5)] fn many_arity_stack5(a: &dyn Fn(u32, u32, u32, u32)); #[wasm_bindgen(js_name = many_arity_call6)] fn many_arity_stack6(a: &dyn Fn(u32, u32, u32, u32, u32)); #[wasm_bindgen(js_name = many_arity_call7)] fn many_arity_stack7(a: &dyn Fn(u32, u32, u32, u32, u32, u32)); #[wasm_bindgen(js_name = many_arity_call8)] fn many_arity_stack8(a: &dyn Fn(u32, u32, u32, u32, u32, u32, u32)); #[wasm_bindgen(js_name = many_arity_call9)] fn many_arity_stack9(a: &dyn Fn(u32, u32, u32, u32, u32, u32, u32, u32)); fn long_lived_dropping_cache(a: &Closure); #[wasm_bindgen(catch)] fn long_lived_dropping_call() -> Result<(), JsValue>; fn long_lived_option_dropping_cache(a: Option<&Closure>) -> bool; #[wasm_bindgen(catch)] fn long_lived_option_dropping_call() -> Result<(), JsValue>; fn long_fnmut_recursive_cache(a: &Closure); #[wasm_bindgen(catch)] fn long_fnmut_recursive_call() -> Result<(), JsValue>; fn fnmut_call(a: &mut dyn FnMut()); fn fnmut_thread(a: &mut dyn FnMut(u32) -> u32) -> u32; fn fnmut_bad_call(a: &mut dyn FnMut()); #[wasm_bindgen(catch)] fn fnmut_bad_again(a: bool) -> Result<(), JsValue>; fn string_arguments_call(a: &mut dyn FnMut(String)); fn string_ret_call(a: &mut dyn FnMut(String) -> String); fn drop_during_call_save(a: &Closure); fn drop_during_call_call(); fn js_test_closure_returner(); fn calling_it_throws(a: &Closure) -> bool; fn call_val(f: &JsValue); #[wasm_bindgen(js_name = calling_it_throws)] fn call_val_throws(f: &JsValue) -> bool; fn pass_reference_first_arg_twice( a: RefFirstArgument, b: &Closure, c: &Closure, ); #[wasm_bindgen(js_name = pass_reference_first_arg_twice)] fn pass_reference_first_arg_twice2( a: RefFirstArgument, b: &mut dyn FnMut(&RefFirstArgument), c: &mut dyn FnMut(&RefFirstArgument), ); fn call_destroyed(a: &JsValue); fn js_store_forgotten_closure(closure: &Closure); fn js_call_forgotten_closure(); #[wasm_bindgen(js_name = many_arity_call2)] fn externref_call(a: &Closure); #[wasm_bindgen(js_name = many_arity_call2)] fn named_externref_call(a: &Closure); } #[wasm_bindgen_test] fn works() { let a = Cell::new(false); works_call(&|| a.set(true)); assert!(a.get()); assert_eq!(works_thread(&|a| a + 1), 3); } #[wasm_bindgen_test] fn cannot_reuse() { cannot_reuse_call(&|| {}); assert!(cannot_reuse_call_again().is_err()); } #[wasm_bindgen_test] fn debug() { let closure = Closure::wrap(Box::new(|| {}) as Box); assert_eq!(&format!("{:?}", closure), "Closure { ... }"); } #[wasm_bindgen_test] fn long_lived() { let hit = Rc::new(Cell::new(false)); let hit2 = hit.clone(); let a = Closure::new(move || hit2.set(true)); assert!(!hit.get()); long_lived_call1(&a); assert!(hit.get()); let hit = Rc::new(Cell::new(false)); { let hit = hit.clone(); let a = Closure::new(move |x| { hit.set(true); x + 3 }); assert_eq!(long_lived_call2(&a), 5); } assert!(hit.get()); } #[wasm_bindgen_test] fn many_arity() { many_arity_call1(&Closure::new(|| {})); many_arity_call2(&Closure::new(|a| assert_eq!(a, 1))); many_arity_call3(&Closure::new(|a, b| assert_eq!((a, b), (1, 2)))); many_arity_call4(&Closure::new(|a, b, c| assert_eq!((a, b, c), (1, 2, 3)))); many_arity_call5(&Closure::new(|a, b, c, d| { assert_eq!((a, b, c, d), (1, 2, 3, 4)) })); many_arity_call6(&Closure::new(|a, b, c, d, e| { assert_eq!((a, b, c, d, e), (1, 2, 3, 4, 5)) })); many_arity_call7(&Closure::new(|a, b, c, d, e, f| { assert_eq!((a, b, c, d, e, f), (1, 2, 3, 4, 5, 6)) })); many_arity_call8(&Closure::new(|a, b, c, d, e, f, g| { assert_eq!((a, b, c, d, e, f, g), (1, 2, 3, 4, 5, 6, 7)) })); many_arity_call9(&Closure::new(|a, b, c, d, e, f, g, h| { assert_eq!((a, b, c, d, e, f, g, h), (1, 2, 3, 4, 5, 6, 7, 8)) })); let s = String::new(); many_arity_call_mut1(&Closure::once(move || drop(s))); let s = String::new(); many_arity_call_mut2(&Closure::once(move |a| { drop(s); assert_eq!(a, 1); })); let s = String::new(); many_arity_call_mut3(&Closure::once(move |a, b| { drop(s); assert_eq!((a, b), (1, 2)); })); let s = String::new(); many_arity_call_mut4(&Closure::once(move |a, b, c| { drop(s); assert_eq!((a, b, c), (1, 2, 3)); })); let s = String::new(); many_arity_call_mut5(&Closure::once(move |a, b, c, d| { drop(s); assert_eq!((a, b, c, d), (1, 2, 3, 4)); })); let s = String::new(); many_arity_call_mut6(&Closure::once(move |a, b, c, d, e| { drop(s); assert_eq!((a, b, c, d, e), (1, 2, 3, 4, 5)); })); let s = String::new(); many_arity_call_mut7(&Closure::once(move |a, b, c, d, e, f| { drop(s); assert_eq!((a, b, c, d, e, f), (1, 2, 3, 4, 5, 6)); })); let s = String::new(); many_arity_call_mut8(&Closure::once(move |a, b, c, d, e, f, g| { drop(s); assert_eq!((a, b, c, d, e, f, g), (1, 2, 3, 4, 5, 6, 7)); })); let s = String::new(); many_arity_call_mut9(&Closure::once(move |a, b, c, d, e, f, g, h| { drop(s); assert_eq!((a, b, c, d, e, f, g, h), (1, 2, 3, 4, 5, 6, 7, 8)); })); many_arity_stack1(&(|| {})); many_arity_stack2(&(|a| assert_eq!(a, 1))); many_arity_stack3(&(|a, b| assert_eq!((a, b), (1, 2)))); many_arity_stack4(&(|a, b, c| assert_eq!((a, b, c), (1, 2, 3)))); many_arity_stack5(&(|a, b, c, d| assert_eq!((a, b, c, d), (1, 2, 3, 4)))); many_arity_stack6(&(|a, b, c, d, e| assert_eq!((a, b, c, d, e), (1, 2, 3, 4, 5)))); many_arity_stack7(&(|a, b, c, d, e, f| assert_eq!((a, b, c, d, e, f), (1, 2, 3, 4, 5, 6)))); many_arity_stack8( &(|a, b, c, d, e, f, g| assert_eq!((a, b, c, d, e, f, g), (1, 2, 3, 4, 5, 6, 7))), ); many_arity_stack9( &(|a, b, c, d, e, f, g, h| assert_eq!((a, b, c, d, e, f, g, h), (1, 2, 3, 4, 5, 6, 7, 8))), ); } #[wasm_bindgen_test] fn option() { let hit = Rc::new(Cell::new(false)); let hit2 = hit.clone(); let a = Closure::new(move || hit2.set(true)); assert!(!hit.get()); option_call1(Some(&a)); assert!(hit.get()); let hit = Rc::new(Cell::new(false)); { let hit = hit.clone(); let a = Closure::new(move |x| { hit.set(true); x + 3 }); assert_eq!(option_call2(Some(&a)), 5); } assert!(hit.get()); assert!(option_call3(None)); } struct Dropper(Rc>); impl Drop for Dropper { fn drop(&mut self) { assert!(!self.0.get()); self.0.set(true); } } #[wasm_bindgen_test] fn call_fn_once_twice() { let dropped = Rc::new(Cell::new(false)); let dropper = Dropper(dropped.clone()); let called = Rc::new(Cell::new(false)); let c = Closure::once({ let called = called.clone(); move || { assert!(!called.get()); called.set(true); drop(dropper); } }); many_arity_call_mut1(&c); assert!(called.get()); assert!(dropped.get()); assert!(calling_it_throws(&c)); } #[wasm_bindgen_test] fn once_into_js() { let dropped = Rc::new(Cell::new(false)); let dropper = Dropper(dropped.clone()); let called = Rc::new(Cell::new(false)); let f = Closure::once_into_js({ let called = called.clone(); move || { assert!(!called.get()); called.set(true); drop(dropper); } }); call_val(&f); assert!(called.get()); assert!(dropped.get()); assert!(call_val_throws(&f)); } #[wasm_bindgen_test] fn long_lived_dropping() { let hit = Rc::new(Cell::new(false)); let hit2 = hit.clone(); let a = Closure::new(move || hit2.set(true)); long_lived_dropping_cache(&a); assert!(!hit.get()); assert!(long_lived_dropping_call().is_ok()); assert!(hit.get()); drop(a); assert!(long_lived_dropping_call().is_err()); } #[wasm_bindgen_test] fn long_lived_option_dropping() { let hit = Rc::new(Cell::new(false)); let hit2 = hit.clone(); let a = Closure::new(move || hit2.set(true)); assert!(!long_lived_option_dropping_cache(None)); assert!(long_lived_option_dropping_cache(Some(&a))); assert!(!hit.get()); assert!(long_lived_option_dropping_call().is_ok()); assert!(hit.get()); drop(a); assert!(long_lived_option_dropping_call().is_err()); } #[wasm_bindgen_test] fn long_fnmut_recursive() { let a = Closure::new(|| { assert!(long_fnmut_recursive_call().is_err()); }); long_fnmut_recursive_cache(&a); assert!(long_fnmut_recursive_call().is_ok()); } #[wasm_bindgen_test] fn fnmut() { let mut a = false; fnmut_call(&mut || a = true); assert!(a); let mut x = false; assert_eq!( fnmut_thread(&mut |a| { x = true; a + 1 }), 3 ); assert!(x); } #[wasm_bindgen_test] fn fnmut_bad() { let mut x = true; let mut hits = 0; fnmut_bad_call(&mut || { hits += 1; if fnmut_bad_again(hits == 1).is_err() { return; } x = false; }); assert_eq!(hits, 1); assert!(x); assert!(fnmut_bad_again(true).is_err()); } #[wasm_bindgen_test] fn string_arguments() { let mut x = false; string_arguments_call(&mut |s| { assert_eq!(s, "foo"); x = true; }); assert!(x); } #[wasm_bindgen_test] fn string_ret() { let mut x = false; string_ret_call(&mut |mut s| { assert_eq!(s, "foo"); s.push_str("bar"); x = true; s }); assert!(x); } #[wasm_bindgen_test] fn drop_drops() { static mut HIT: bool = false; struct A; impl Drop for A { fn drop(&mut self) { unsafe { HIT = true; } } } let a = A; let x: Closure = Closure::new(move || drop(&a)); drop(x); unsafe { assert!(HIT); } } #[wasm_bindgen_test] fn drop_during_call_ok() { static mut HIT: bool = false; struct A; impl Drop for A { fn drop(&mut self) { unsafe { HIT = true; } } } let rc = Rc::new(RefCell::new(None)); let rc2 = rc.clone(); let x = 3; let a = A; let x: Closure = Closure::new(move || { // "drop ourselves" drop(rc2.borrow_mut().take().unwrap()); // `A` should not have been destroyed as a result unsafe { assert!(!HIT); } // allocate some heap memory to try to paper over our `3` drop(String::from("1234567890")); // make sure our closure memory is still valid assert_eq!(x, 3); // make sure `A` is bound to our closure environment. drop(&a); unsafe { assert!(!HIT); } }); drop_during_call_save(&x); *rc.borrow_mut() = Some(x); drop(rc); unsafe { assert!(!HIT); } drop_during_call_call(); unsafe { assert!(HIT); } } #[wasm_bindgen_test] fn test_closure_returner() { type ClosureType = dyn FnMut() -> BadStruct; use js_sys::{Object, Reflect}; js_test_closure_returner(); #[wasm_bindgen] pub struct ClosureHandle(Closure); #[wasm_bindgen] pub struct BadStruct {} #[wasm_bindgen] pub fn closure_returner() -> Result { let o = Object::new(); let some_fn = Closure::wrap(Box::new(move || BadStruct {}) as Box); Reflect::set( &o, &JsValue::from("someKey"), some_fn.as_ref().unchecked_ref(), ) .unwrap(); Reflect::set( &o, &JsValue::from("handle"), &JsValue::from(ClosureHandle(some_fn)), ) .unwrap(); Ok(o) } } #[wasm_bindgen] pub struct RefFirstArgument { contents: u32, } #[wasm_bindgen_test] fn reference_as_first_argument_builds_at_all() { #[wasm_bindgen] extern "C" { fn ref_first_arg1(a: &dyn Fn(&JsValue)); fn ref_first_arg2(a: &mut dyn FnMut(&JsValue)); fn ref_first_arg3(a: &Closure); fn ref_first_arg4(a: &Closure); fn ref_first_custom1(a: &dyn Fn(&RefFirstArgument)); fn ref_first_custom2(a: &mut dyn FnMut(&RefFirstArgument)); fn ref_first_custom3(a: &Closure); fn ref_first_custom4(a: &Closure); } Closure::wrap(Box::new(|_: &JsValue| ()) as Box); Closure::wrap(Box::new(|_: &JsValue| ()) as Box); Closure::once(|_: &JsValue| ()); Closure::once_into_js(|_: &JsValue| ()); Closure::wrap(Box::new(|_: &RefFirstArgument| ()) as Box); Closure::wrap(Box::new(|_: &RefFirstArgument| ()) as Box); Closure::once(|_: &RefFirstArgument| ()); Closure::once_into_js(|_: &RefFirstArgument| ()); } #[wasm_bindgen_test] fn reference_as_first_argument_works() { let a = Rc::new(Cell::new(0)); let b = { let a = a.clone(); Closure::once(move |x: &RefFirstArgument| { assert_eq!(a.get(), 0); assert_eq!(x.contents, 3); a.set(a.get() + 1); }) }; let c = { let a = a.clone(); Closure::once(move |x: &RefFirstArgument| { assert_eq!(a.get(), 1); assert_eq!(x.contents, 3); a.set(a.get() + 1); }) }; pass_reference_first_arg_twice(RefFirstArgument { contents: 3 }, &b, &c); assert_eq!(a.get(), 2); } #[wasm_bindgen_test] fn reference_as_first_argument_works2() { let a = Cell::new(0); pass_reference_first_arg_twice2( RefFirstArgument { contents: 3 }, &mut |x: &RefFirstArgument| { assert_eq!(a.get(), 0); assert_eq!(x.contents, 3); a.set(a.get() + 1); }, &mut |x: &RefFirstArgument| { assert_eq!(a.get(), 1); assert_eq!(x.contents, 3); a.set(a.get() + 1); }, ); assert_eq!(a.get(), 2); } #[wasm_bindgen_test] fn call_destroyed_doesnt_segfault() { struct A(i32, i32); impl Drop for A { fn drop(&mut self) { assert_eq!(self.0, self.1); } } let a = A(1, 1); let a = Closure::wrap(Box::new(move || drop(&a)) as Box); let b = a.as_ref().clone(); drop(a); call_destroyed(&b); let a = A(2, 2); let a = Closure::wrap(Box::new(move || drop(&a)) as Box); let b = a.as_ref().clone(); drop(a); call_destroyed(&b); let a = A(1, 1); let a = Closure::wrap(Box::new(move |_: &JsValue| drop(&a)) as Box); let b = a.as_ref().clone(); drop(a); call_destroyed(&b); let a = A(2, 2); let a = Closure::wrap(Box::new(move |_: &JsValue| drop(&a)) as Box); let b = a.as_ref().clone(); drop(a); call_destroyed(&b); } #[wasm_bindgen_test] fn forget_works() { let a = Closure::wrap(Box::new(|| {}) as Box); js_store_forgotten_closure(&a); a.forget(); js_call_forgotten_closure(); } #[wasm_bindgen_test] fn named_externref_no_duplicate_adapter() { externref_call(&Closure::new(|a| assert_eq!(a, 1))); named_externref_call(&Closure::new(|a| assert_eq!(a, 1))); } wasm-bindgen-0.2.87/tests/wasm/comments.js000064400000000000000000000017201046102023000165710ustar 00000000000000const fs = require('fs'); const assert = require('assert'); exports.assert_comments_exist = function() { const bindings_file = require.resolve('wasm-bindgen-test'); const contents = fs.readFileSync(bindings_file); assert.ok(contents.includes("* annotated function âœ”ï¸ \" \\ ' {")); assert.ok(contents.includes("* annotated struct type")); assert.ok(contents.includes("* annotated struct field b")); assert.ok(contents.includes("* annotated struct field c")); assert.ok(contents.includes("* annotated struct constructor")); assert.ok(contents.includes("* annotated struct method")); assert.ok(contents.includes("* annotated struct getter")); assert.ok(contents.includes("* annotated struct setter")); assert.ok(contents.includes("* annotated struct static method")); assert.ok(contents.includes("* annotated enum type")); assert.ok(contents.includes("* annotated enum variant 1")); assert.ok(contents.includes("* annotated enum variant 2")); }; wasm-bindgen-0.2.87/tests/wasm/comments.rs000064400000000000000000000025331046102023000166040ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/comments.js")] extern "C" { fn assert_comments_exist(); } /// annotated function âœ”ï¸ " \ ' { #[wasm_bindgen] pub fn annotated() -> String { String::new() } /// annotated struct type #[wasm_bindgen] pub struct Annotated { a: String, /// annotated struct field b pub b: u32, /// annotated struct field c #[wasm_bindgen(readonly)] pub c: u32, d: u32, } #[wasm_bindgen] impl Annotated { /// annotated struct constructor #[wasm_bindgen(constructor)] pub fn new() -> Self { Self { a: String::new(), b: 0, c: 0, d: 0, } } /// annotated struct method pub fn get_a(&self) -> String { self.a.clone() } /// annotated struct getter #[wasm_bindgen(getter)] pub fn d(&self) -> u32 { self.d } /// annotated struct setter #[wasm_bindgen(setter)] pub fn set_d(&mut self, value: u32) { self.d = value } /// annotated struct static method pub fn static_method() {} } /// annotated enum type #[wasm_bindgen] pub enum AnnotatedEnum { /// annotated enum variant 1 Variant1, /// annotated enum variant 2 Variant2, } #[wasm_bindgen_test] fn works() { assert_comments_exist(); } wasm-bindgen-0.2.87/tests/wasm/duplicate_deps.js000064400000000000000000000004271046102023000177340ustar 00000000000000const assert = require('assert'); let next = null; exports.assert_next_undefined = function() { next = undefined; }; exports.assert_next_ten = function() { next = 10; }; exports.foo = function(a) { console.log(a, next); assert.strictEqual(a, next); next = null; }; wasm-bindgen-0.2.87/tests/wasm/duplicate_deps.rs000064400000000000000000000005721046102023000177450ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; use wasm_bindgen_test_crate_a as a; use wasm_bindgen_test_crate_b as b; #[wasm_bindgen(module = "tests/wasm/duplicate_deps.js")] extern "C" { fn assert_next_undefined(); fn assert_next_ten(); } #[wasm_bindgen_test] fn works() { assert_next_undefined(); a::test(); assert_next_ten(); b::test(); } wasm-bindgen-0.2.87/tests/wasm/duplicates.rs000064400000000000000000000027351046102023000171200ustar 00000000000000use wasm_bindgen_test::*; pub mod same_function_different_locations_a { use wasm_bindgen::prelude::*; #[wasm_bindgen(module = "tests/wasm/duplicates_a.js")] extern "C" { pub fn foo(); pub static bar: JsValue; } } pub mod same_function_different_locations_b { use wasm_bindgen::prelude::*; #[wasm_bindgen(module = "tests/wasm/duplicates_a.js")] extern "C" { pub fn foo(); pub static bar: JsValue; } } #[wasm_bindgen_test] fn same_function_different_locations() { same_function_different_locations_a::foo(); same_function_different_locations_b::foo(); assert_eq!(*same_function_different_locations_a::bar, 3); assert_eq!(*same_function_different_locations_a::bar, 3); } pub mod same_function_different_modules_a { use wasm_bindgen::prelude::*; #[wasm_bindgen(module = "tests/wasm/duplicates_b.js")] extern "C" { pub fn foo() -> bool; pub static bar: JsValue; } } pub mod same_function_different_modules_b { use wasm_bindgen::prelude::*; #[wasm_bindgen(module = "tests/wasm/duplicates_c.js")] extern "C" { pub fn foo() -> bool; pub static bar: JsValue; } } #[wasm_bindgen_test] fn same_function_different_modules() { assert!(same_function_different_modules_a::foo()); assert!(!same_function_different_modules_b::foo()); assert_eq!(*same_function_different_modules_a::bar, 4); assert_eq!(*same_function_different_modules_b::bar, 5); } wasm-bindgen-0.2.87/tests/wasm/duplicates_a.js000064400000000000000000000000511046102023000173750ustar 00000000000000exports.foo = () => {}; exports.bar = 3; wasm-bindgen-0.2.87/tests/wasm/duplicates_b.js000064400000000000000000000000531046102023000174000ustar 00000000000000exports.foo = () => true; exports.bar = 4; wasm-bindgen-0.2.87/tests/wasm/duplicates_c.js000064400000000000000000000000541046102023000174020ustar 00000000000000exports.foo = () => false; exports.bar = 5; wasm-bindgen-0.2.87/tests/wasm/enums.js000064400000000000000000000027021046102023000160740ustar 00000000000000const wasm = require('wasm-bindgen-test.js'); const assert = require('assert'); exports.js_c_style_enum = () => { assert.strictEqual(wasm.Color.Green, 0); assert.strictEqual(wasm.Color.Yellow, 1); assert.strictEqual(wasm.Color.Red, 2); assert.strictEqual(wasm.Color[0], 'Green'); assert.strictEqual(wasm.Color[1], 'Yellow'); assert.strictEqual(wasm.Color[2], 'Red'); assert.strictEqual(Object.keys(wasm.Color).length, 6); assert.strictEqual(wasm.enum_cycle(wasm.Color.Green), wasm.Color.Yellow); }; exports.js_c_style_enum_with_custom_values = () => { assert.strictEqual(wasm.ColorWithCustomValues.Green, 21); assert.strictEqual(wasm.ColorWithCustomValues.Yellow, 34); assert.strictEqual(wasm.ColorWithCustomValues.Red, 2); assert.strictEqual(wasm.ColorWithCustomValues[21], 'Green'); assert.strictEqual(wasm.ColorWithCustomValues[34], 'Yellow'); assert.strictEqual(wasm.ColorWithCustomValues[2], 'Red'); assert.strictEqual(Object.keys(wasm.ColorWithCustomValues).length, 6); assert.strictEqual(wasm.enum_with_custom_values_cycle(wasm.ColorWithCustomValues.Green), wasm.ColorWithCustomValues.Yellow); }; exports.js_handle_optional_enums = x => wasm.handle_optional_enums(x); exports.js_expect_enum = (a, b) => { assert.strictEqual(a, b); }; exports.js_expect_enum_none = a => { assert.strictEqual(a, undefined); }; exports.js_renamed_enum = b => { assert.strictEqual(wasm.JsRenamedEnum.B, b); }; wasm-bindgen-0.2.87/tests/wasm/enums.rs000064400000000000000000000043441046102023000161100ustar 00000000000000use self::inner::ColorWithCustomValues; use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/enums.js")] extern "C" { fn js_c_style_enum(); fn js_c_style_enum_with_custom_values(); fn js_handle_optional_enums(x: Option) -> Option; fn js_expect_enum(x: Color, y: Option); fn js_expect_enum_none(x: Option); fn js_renamed_enum(b: RenamedEnum); } #[wasm_bindgen] #[derive(PartialEq, Debug)] pub enum Color { Green, Yellow, Red, } pub mod inner { use wasm_bindgen::prelude::*; #[wasm_bindgen] pub enum ColorWithCustomValues { Green = 21, Yellow = 34, Red = 2, } } #[wasm_bindgen(js_name = JsRenamedEnum)] #[derive(Copy, Clone)] pub enum RenamedEnum { A = 10, B = 20, } #[wasm_bindgen] pub fn enum_cycle(color: Color) -> Color { match color { Color::Green => Color::Yellow, Color::Yellow => Color::Red, Color::Red => Color::Green, } } #[wasm_bindgen] pub fn enum_with_custom_values_cycle(color: ColorWithCustomValues) -> ColorWithCustomValues { match color { ColorWithCustomValues::Green => ColorWithCustomValues::Yellow, ColorWithCustomValues::Yellow => ColorWithCustomValues::Red, ColorWithCustomValues::Red => ColorWithCustomValues::Green, } } #[wasm_bindgen_test] fn c_style_enum() { js_c_style_enum(); } #[wasm_bindgen_test] fn c_style_enum_with_custom_values() { js_c_style_enum_with_custom_values(); } #[wasm_bindgen] pub fn handle_optional_enums(x: Option) -> Option { x } #[wasm_bindgen_test] fn test_optional_enums() { use self::Color::*; assert_eq!(js_handle_optional_enums(None), None); assert_eq!(js_handle_optional_enums(Some(Green)), Some(Green)); assert_eq!(js_handle_optional_enums(Some(Yellow)), Some(Yellow)); assert_eq!(js_handle_optional_enums(Some(Red)), Some(Red)); } #[wasm_bindgen_test] fn test_optional_enum_values() { use self::Color::*; js_expect_enum(Green, Some(Green)); js_expect_enum(Yellow, Some(Yellow)); js_expect_enum(Red, Some(Red)); js_expect_enum_none(None); } #[wasm_bindgen_test] fn test_renamed_enum() { js_renamed_enum(RenamedEnum::B); } wasm-bindgen-0.2.87/tests/wasm/final.js000064400000000000000000000005061046102023000160360ustar 00000000000000const assert = require('assert'); exports.MyType = class { static foo(y) { assert.equal(y, 'x'); return y + 'y'; } constructor(x) { assert.equal(x, 2); this._a = 1; } bar(x) { assert.equal(x, true); return 3.2; } get a() { return this._a; } set a(v) { this._a = v; } }; wasm-bindgen-0.2.87/tests/wasm/final.rs000064400000000000000000000016521046102023000160510ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen] extern "C" { type Math; #[wasm_bindgen(static_method_of = Math, final)] fn log(f: f32) -> f32; } #[wasm_bindgen(module = "tests/wasm/final.js")] extern "C" { type MyType; #[wasm_bindgen(constructor, final)] fn new(x: u32) -> MyType; #[wasm_bindgen(static_method_of = MyType, final)] fn foo(a: &str) -> String; #[wasm_bindgen(method, final)] fn bar(this: &MyType, arg: bool) -> f32; #[wasm_bindgen(method, getter, final)] fn a(this: &MyType) -> u32; #[wasm_bindgen(method, setter, final)] fn set_a(this: &MyType, a: u32); } #[wasm_bindgen_test] fn simple() { assert_eq!(Math::log(1.0), 0.0); } #[wasm_bindgen_test] fn classes() { assert_eq!(MyType::foo("x"), "xy"); let x = MyType::new(2); assert_eq!(x.bar(true), 3.2); assert_eq!(x.a(), 1); x.set_a(3); assert_eq!(x.a(), 3); } wasm-bindgen-0.2.87/tests/wasm/futures.js000064400000000000000000000031321046102023000164400ustar 00000000000000const assert = require('assert'); const wasm = require('wasm-bindgen-test'); exports.call_exports = async function() { await wasm.async_do_nothing(); assert.strictEqual(1, await wasm.async_return_1()); assert.strictEqual(2, await wasm.async_return_2()); await wasm.async_nothing_again(); assert.strictEqual(3, await wasm.async_return_3()); assert.strictEqual(4, await wasm.async_return_4()); assert.strictEqual(5, (await wasm.async_return_5()).val); assert.strictEqual(6, (await wasm.async_return_6()).val); await assert.rejects(wasm.async_throw_7(), /7/); await assert.rejects(wasm.async_throw_custom(), /\[object Object\]/); await assert.rejects(wasm.async_throw_message(), /async message/); await assert.rejects(wasm.async_throw_jserror(), /async message/); await assert.rejects(wasm.async_throw_custom_error(), /custom error/); assert.strictEqual("Hi, Jim!", await wasm.async_take_reference("Jim")); const foo = await new wasm.AsyncStruct(); assert.strictEqual(42, await foo.method()); await wasm.async_take_js_reference(42); const buffer = new Int32Array([1, 2, 3, 4]); await wasm.async_take_mut_slice(buffer); assert.deepStrictEqual(buffer, new Int32Array([42, 42, 42, 42])); }; exports.call_promise = async function() { return "ok"; } exports.call_promise_ok = async function() { return "ok"; } exports.call_promise_err = async function() { throw "error"; } exports.call_promise_unit = async function() { console.log("asdfasdf"); } exports.call_promise_ok_unit = async function() { } exports.call_promise_err_unit = async function() { throw "error"; } wasm-bindgen-0.2.87/tests/wasm/futures.rs000064400000000000000000000072251046102023000164570ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[rustfmt::skip] #[wasm_bindgen(module = "tests/wasm/futures.js")] extern "C" { #[wasm_bindgen(catch)] async fn call_exports() -> Result; async fn call_promise() -> JsValue; #[wasm_bindgen(catch)] async fn call_promise_ok() -> Result; #[wasm_bindgen(catch)] async fn call_promise_err() -> Result; #[wasm_bindgen] async fn call_promise_unit(); #[wasm_bindgen(catch)] async fn call_promise_ok_unit() -> Result<(), JsValue>; #[wasm_bindgen(catch)] async fn call_promise_err_unit() -> Result<(), JsValue>; } #[wasm_bindgen_test] async fn smoke() { call_exports().await.unwrap(); } #[wasm_bindgen] pub async fn async_do_nothing() {} #[wasm_bindgen] pub async fn async_return_1() -> JsValue { 1.into() } #[wasm_bindgen] pub async fn async_return_2() -> u32 { 2 } #[wasm_bindgen] pub async fn async_nothing_again() -> Result<(), JsValue> { Ok(()) } #[wasm_bindgen] pub async fn async_return_3() -> Result { Ok(3) } #[wasm_bindgen] pub async fn async_return_4() -> Result { Ok(4.into()) } #[wasm_bindgen] pub struct AsyncCustomReturn { pub val: u32, } #[wasm_bindgen] pub async fn async_return_5() -> AsyncCustomReturn { AsyncCustomReturn { val: 5 } } #[wasm_bindgen] pub async fn async_return_6() -> Result { Ok(AsyncCustomReturn { val: 6 }) } #[wasm_bindgen] pub async fn async_throw_7() -> Result { Err(7.into()) } #[wasm_bindgen] pub async fn async_throw_custom() -> Result { Err(AsyncCustomReturn { val: 8 }.into()) } #[wasm_bindgen] pub async fn async_throw_message() -> Result<(), JsValue> { Err(js_sys::Error::new("async message").into()) } #[wasm_bindgen] pub async fn async_throw_jserror() -> Result { Err(JsError::new("async message")) } pub struct AsyncCustomError { pub val: JsValue, } impl From for JsValue { fn from(e: AsyncCustomError) -> Self { e.val } } #[wasm_bindgen] pub async fn async_throw_custom_error() -> Result { Err(AsyncCustomError { val: JsValue::from("custom error"), }) } #[wasm_bindgen] pub async fn async_take_reference(x: &str) -> String { format!("Hi, {x}!") } #[wasm_bindgen] pub struct AsyncStruct; #[wasm_bindgen] impl AsyncStruct { #[wasm_bindgen(constructor)] pub async fn new() -> AsyncStruct { AsyncStruct } pub async fn method(&self) -> u32 { 42 } } #[wasm_bindgen] pub async fn async_take_js_reference(x: &JsValue) { assert_eq!(*x, 42); } #[wasm_bindgen] pub async fn async_take_mut_slice(x: &mut [i32]) { x.fill(42); } #[wasm_bindgen_test] async fn test_promise() { assert_eq!(call_promise().await.as_string(), Some(String::from("ok"))) } #[wasm_bindgen_test] async fn test_promise_ok() { assert_eq!( call_promise_ok().await.map(|j| j.as_string()), Ok(Some(String::from("ok"))) ) } #[wasm_bindgen_test] async fn test_promise_err() { assert_eq!( call_promise_err().await.map_err(|j| j.as_string()), Err(Some(String::from("error"))) ) } #[wasm_bindgen_test] async fn test_promise_unit() { call_promise_unit().await } #[wasm_bindgen_test] async fn test_promise_ok_unit() { call_promise_ok_unit().await.unwrap() } #[wasm_bindgen_test] async fn test_promise_err_unit() { assert_eq!( call_promise_err_unit().await.map_err(|j| j.as_string()), Err::<(), _>(Some(String::from("error"))) ) } wasm-bindgen-0.2.87/tests/wasm/getters_and_setters.js000064400000000000000000000076001046102023000210170ustar 00000000000000const wasm = require('wasm-bindgen-test.js'); const assert = require('assert'); exports._1_js = (rules) => { assert.equal(rules.field, 1); rules.field *= 2; return rules; } exports._2_js = (rules) => { let value = rules.no_js_name__no_getter_with_name__no_getter_without_name(); assert.equal(value, 2); rules.set_no_js_name__no_setter_with_name__no_setter_without_name(value * 2); return rules; } exports._3_js = (rules) => { let value = rules.no_js_name__no_getter_with_name__getter_without_name; assert.equal(value, 3); rules.no_js_name__no_setter_with_name__setter_without_name = value * 2; return rules; } exports._4_js = (rules) => { let value = rules.new_no_js_name__getter_with_name__getter_without_name; assert.equal(value, 4); rules.new_no_js_name__setter_with_name__setter_without_name = value * 2; return rules; } exports._5_js = (rules) => { let value = rules.new_js_name__no_getter_with_name__no_getter_without_name(); assert.equal(value, 5); rules.new_js_name__no_setter_with_name__no_setter_without_name(value * 2); return rules; } exports._6_js = (rules) => { let value = rules.new_js_name__no_getter_with_name__getter_without_name; assert.equal(value, 6); rules.new_js_name__no_setter_with_name__setter_without_name = value * 2; return rules; } exports._7_js = (rules) => { let value = rules.new_js_name__getter_with_name__no_getter_without_name_for_field; assert.equal(value, 7); rules.new_js_name__setter_with_name__no_setter_without_name_for_field = value * 2; return rules; } exports._8_js = (rules) => { let value = rules.new_js_name__no_getter_setter_with_name__getter_setter_without_name__same_getter_setter_name; assert.equal(value, 8); rules.new_js_name__no_getter_setter_with_name__getter_setter_without_name__same_getter_setter_name = value * 2; return rules; } exports._9_js = (rules) => { let value = rules.new_js_name__no_getter_setter_with_name__getter_setter_without_name__same_getter_setter_name__same_getter_setter_origin_name; assert.equal(value, 9); rules.new_js_name__no_getter_setter_with_name__getter_setter_without_name__same_getter_setter_name__same_getter_setter_origin_name = value * 2; return rules; } exports._10_js = (rules) => { let value = rules.new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_field__same_getter_setter_name; assert.equal(value, 10); rules.new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_field__same_getter_setter_name = value * 2; return rules; } exports._11_js = (rules) => { let value = rules.new_js_name__getter_with_name__no_getter_without_name_for_field__same_getter_setter_name; assert.equal(value, 11); rules.new_js_name__setter_with_name__no_setter_without_name_for_field__same_getter_setter_name = value * 2; return rules; } exports._12_js = (rules) => { let value = rules.new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_field__same_getter_setter_name__same_getter_setter_origin_name; assert.equal(value, 12); rules.new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_field__same_getter_setter_name__same_getter_setter_origin_name = value * 2; return rules; } exports._13_js = (rules) => { let value = rules.new_js_name__getter_with_name__no_getter_without_name_for_field__same_getter_setter_name__same_getter_setter_origin_name; assert.equal(value, 13); rules.new_js_name__setter_with_name__no_setter_without_name_for_field__same_getter_setter_name__same_getter_setter_origin_name = value * 2; return rules; } exports.test_getter_compute = x => { assert.equal(x.foo, 3) }; exports.test_setter_compute = x => { x.foo = 97; }; exports.test_statics = x => { assert.equal(x.field, 3); assert.equal(wasm.Statics.field, 4); x.field = 13; wasm.Statics.field = 14; } wasm-bindgen-0.2.87/tests/wasm/getters_and_setters.rs000064400000000000000000000271421046102023000210320ustar 00000000000000use std::cell::Cell; use std::rc::Rc; use std::sync::atomic::{AtomicU32, Ordering}; use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/getters_and_setters.js")] extern "C" { fn _1_js(rules: Rules) -> Rules; fn _2_js(rules: Rules) -> Rules; fn _3_js(rules: Rules) -> Rules; fn _4_js(rules: Rules) -> Rules; fn _5_js(rules: Rules) -> Rules; fn _6_js(rules: Rules) -> Rules; fn _7_js(rules: Rules) -> Rules; fn _8_js(rules: Rules) -> Rules; fn _9_js(rules: Rules) -> Rules; fn _10_js(rules: Rules) -> Rules; fn _11_js(rules: Rules) -> Rules; fn _12_js(rules: Rules) -> Rules; fn _13_js(rules: Rules) -> Rules; fn test_getter_compute(x: GetterCompute); fn test_setter_compute(x: SetterCompute); fn test_statics(x: Statics); } // Each getter/setter combination is derived // from https://github.com/rustwasm/wasm-bindgen/pull/1440#issuecomment-487113564 #[wasm_bindgen] pub struct Rules { pub field: i32, } #[wasm_bindgen] #[allow(non_snake_case)] impl Rules { #[wasm_bindgen] pub fn no_js_name__no_getter_with_name__no_getter_without_name(&self) -> i32 { self.field } #[wasm_bindgen] pub fn set_no_js_name__no_setter_with_name__no_setter_without_name(&mut self, field: i32) { self.field = field; } #[wasm_bindgen(getter)] pub fn no_js_name__no_getter_with_name__getter_without_name(&self) -> i32 { self.field } #[wasm_bindgen(setter)] pub fn set_no_js_name__no_setter_with_name__setter_without_name(&mut self, field: i32) { self.field = field; } #[wasm_bindgen(getter = new_no_js_name__getter_with_name__getter_without_name)] pub fn no_js_name__getter_with_name__getter_without_name(&self) -> i32 { self.field } #[wasm_bindgen(setter = new_no_js_name__setter_with_name__setter_without_name)] pub fn set_no_js_name__setter_with_name__setter_without_name(&mut self, field: i32) { self.field = field; } #[wasm_bindgen(js_name = new_js_name__no_getter_with_name__no_getter_without_name)] pub fn js_name__no_getter_with_name__no_getter_without_name(&self) -> i32 { self.field } #[wasm_bindgen(js_name = new_js_name__no_setter_with_name__no_setter_without_name)] pub fn set_js_name__no_setter_with_name__no_setter_without_name(&mut self, field: i32) { self.field = field; } #[wasm_bindgen(getter, js_name = new_js_name__no_getter_with_name__getter_without_name)] pub fn js_name__no_getter_with_name__getter_without_name(&self) -> i32 { self.field } #[wasm_bindgen(js_name = new_js_name__no_setter_with_name__setter_without_name, setter)] pub fn set_js_name__no_setter_with_name__setter_without_name(&mut self, field: i32) { self.field = field; } #[wasm_bindgen( getter = new_js_name__getter_with_name__no_getter_without_name_for_field, js_name = new_js_name__getter_with_name__no_getter_without_name_for_method )] pub fn js_name__getter_with_name__no_getter_without_name(&self) -> i32 { self.field } #[wasm_bindgen( js_name = new_js_name__setter_with_name__no_setter_without_name_for_method, setter = new_js_name__setter_with_name__no_setter_without_name_for_field )] pub fn set_js_name__setter_with_name__no_setter_without_name_for_field(&mut self, field: i32) { self.field = field; } #[wasm_bindgen(getter, js_name = new_js_name__no_getter_setter_with_name__getter_setter_without_name__same_getter_setter_name)] pub fn js_name__no_getter_with_name__getter_without_name__same_getter_setter_name( &self, ) -> i32 { self.field } #[wasm_bindgen(js_name = new_js_name__no_getter_setter_with_name__getter_setter_without_name__same_getter_setter_name, setter)] pub fn set_js_name__no_setter_with_name__setter_without_name__same_getter_setter_name( &mut self, field: i32, ) { self.field = field; } #[wasm_bindgen(getter, js_name = new_js_name__no_getter_setter_with_name__getter_setter_without_name__same_getter_setter_name__same_getter_setter_origin_name)] pub fn js_name__no_getter_setter_with_name__getter_setter_without_name__same_getter_setter_name__same_getter_setter_origin_name( &self, ) -> i32 { self.field } #[wasm_bindgen(js_name = new_js_name__no_getter_setter_with_name__getter_setter_without_name__same_getter_setter_name__same_getter_setter_origin_name, setter)] pub fn set_js_name__no_getter_setter_with_name__getter_setter_without_name__same_getter_setter_name__same_getter_setter_origin_name( &mut self, field: i32, ) { self.field = field; } #[wasm_bindgen( getter = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_field__same_getter_setter_name, js_name = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_method__same_getter_setter_name)] pub fn js_name__getter_with_name__no_getter_without_name__same_getter_setter_name( &self, ) -> i32 { self.field } #[wasm_bindgen( js_name = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_method__same_getter_setter_name, setter = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_field__same_getter_setter_name)] pub fn set_js_name__setter_with_name__no_setter_without_name__same_getter_setter_name( &mut self, field: i32, ) { self.field = field; } #[wasm_bindgen( getter = new_js_name__getter_with_name__no_getter_without_name_for_field__same_getter_setter_name, js_name = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_method__same_getter_setter_name__no_same_field_name)] pub fn js_name__getter_with_name__no_getter_without_name__same_getter_setter_name__no_same_field_name( &self, ) -> i32 { self.field } #[wasm_bindgen( js_name = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_method__same_getter_setter_name__no_same_field_name, setter = new_js_name__setter_with_name__no_setter_without_name_for_field__same_getter_setter_name)] pub fn set_js_name__setter_with_name__no_setter_without_name__same_getter_setter_name__no_same_field_name( &mut self, field: i32, ) { self.field = field; } #[wasm_bindgen( getter = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_field__same_getter_setter_name__same_getter_setter_origin_name, js_name = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_method__same_getter_setter_name__same_getter_setter_origin_name)] pub fn js_name__getter_setter_with_name__no_getter_setter_without_name__same_getter_setter_name__same_getter_setter_origin_name( &self, ) -> i32 { self.field } #[wasm_bindgen( js_name = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_method__same_getter_setter_name__same_getter_setter_origin_name, setter = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_field__same_getter_setter_name__same_getter_setter_origin_name)] pub fn set_js_name__getter_setter_with_name__no_getter_setter_without_name__same_getter_setter_name__same_getter_setter_origin_name( &mut self, field: i32, ) { self.field = field; } #[wasm_bindgen( getter = new_js_name__getter_with_name__no_getter_without_name_for_field__same_getter_setter_name__same_getter_setter_origin_name, js_name = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_method__same_getter_setter_name__same_getter_setter_origin_name__no_same_field_name)] pub fn js_name__getter_setter_with_name__no_getter_setter_without_name__same_getter_setter_name__same_getter_setter_origin_name__no_same_field_name( &self, ) -> i32 { self.field } #[wasm_bindgen( js_name = new_js_name__getter_setter_with_name__no_getter_setter_without_name_for_method__same_getter_setter_name__same_getter_setter_origin_name__no_same_field_name, setter = new_js_name__setter_with_name__no_setter_without_name_for_field__same_getter_setter_name__same_getter_setter_origin_name)] pub fn set_js_name__getter_setter_with_name__no_getter_setter_without_name__same_getter_setter_name__same_getter_setter_origin_name__no_same_field_name( &mut self, field: i32, ) { self.field = field; } } #[wasm_bindgen_test] fn _1_rust() { let rules = _1_js(Rules { field: 1 }); assert_eq!(rules.field, 2); } #[wasm_bindgen_test] fn _2_rust() { let rules = _2_js(Rules { field: 2 }); assert_eq!(rules.field, 4); } #[wasm_bindgen_test] fn _3_rust() { let rules = _3_js(Rules { field: 3 }); assert_eq!(rules.field, 6); } #[wasm_bindgen_test] fn _4_rust() { let rules = _4_js(Rules { field: 4 }); assert_eq!(rules.field, 8); } #[wasm_bindgen_test] fn _5_rust() { let rules = _5_js(Rules { field: 5 }); assert_eq!(rules.field, 10); } #[wasm_bindgen_test] fn _6_rust() { let rules = _6_js(Rules { field: 6 }); assert_eq!(rules.field, 12); } #[wasm_bindgen_test] fn _7_rust() { let rules = _7_js(Rules { field: 7 }); assert_eq!(rules.field, 14); } #[wasm_bindgen_test] fn _8_rust() { let rules = _8_js(Rules { field: 8 }); assert_eq!(rules.field, 16); } #[wasm_bindgen_test] fn _9_rust() { let rules = _9_js(Rules { field: 9 }); assert_eq!(rules.field, 18); } #[wasm_bindgen_test] fn _10_rust() { let rules = _10_js(Rules { field: 10 }); assert_eq!(rules.field, 20); } #[wasm_bindgen_test] fn _11_rust() { let rules = _11_js(Rules { field: 11 }); assert_eq!(rules.field, 22); } #[wasm_bindgen_test] fn _12_rust() { let rules = _12_js(Rules { field: 12 }); assert_eq!(rules.field, 24); } #[wasm_bindgen_test] fn _13_rust() { let rules = _13_js(Rules { field: 13 }); assert_eq!(rules.field, 26); } #[wasm_bindgen] struct GetterCompute; #[wasm_bindgen] impl GetterCompute { #[wasm_bindgen(getter)] pub fn foo(&self) -> u32 { 3 } } #[wasm_bindgen_test] fn getter_compute() { test_getter_compute(GetterCompute); } #[wasm_bindgen] struct SetterCompute(Rc>); #[wasm_bindgen] impl SetterCompute { #[wasm_bindgen(setter)] pub fn set_foo(&self, x: u32) { self.0.set(x + 3); } } #[wasm_bindgen_test] fn setter_compute() { let r = Rc::new(Cell::new(3)); test_setter_compute(SetterCompute(r.clone())); assert_eq!(r.get(), 100); } static FIELD: AtomicU32 = AtomicU32::new(3); static STATIC_FIELD: AtomicU32 = AtomicU32::new(4); #[wasm_bindgen] struct Statics; #[wasm_bindgen] impl Statics { #[wasm_bindgen(getter = field)] // Make sure that this still works if we make this mutable for no reason pub fn getter(&mut self) -> u32 { FIELD.load(Ordering::Relaxed) } #[wasm_bindgen(setter = field)] // Make sure that this still works if we make this consume the type for no reason pub fn setter(self, x: u32) { FIELD.store(x, Ordering::Relaxed) } // Define a static field with the same name to make sure that works. #[wasm_bindgen(getter = field)] pub fn static_getter() -> u32 { STATIC_FIELD.load(Ordering::Relaxed) } #[wasm_bindgen(setter = field)] pub fn static_setter(x: u32) { STATIC_FIELD.store(x, Ordering::Relaxed) } } #[wasm_bindgen_test] fn statics() { test_statics(Statics); assert_eq!(FIELD.load(Ordering::Relaxed), 13); assert_eq!(STATIC_FIELD.load(Ordering::Relaxed), 14); } wasm-bindgen-0.2.87/tests/wasm/import_class.js000064400000000000000000000063031046102023000174450ustar 00000000000000const assert = require('assert'); const wasm = require('wasm-bindgen-test'); exports.math_log = Math.log; exports.StaticFunction = class { static bar() { return 2; } }; class Construct { static create() { const ret = new Construct(); ret.internal_string = 'this'; return ret; } get_internal_string() { return this.internal_string; } append_to_internal_string(s) { this.internal_string += s; } assert_internal_string(s) { assert.strictEqual(this.internal_string, s); } ["kebab-case"]() { return 42; } get ["kebab-case-val"]() { return 42; } set ["kebab-case-val"](val) {} static ["static-kebab-case"]() { return 42; } static get ["static-kebab-case-val"]() { return 42; } static set ["static-kebab-case-val"](val) {} } Construct.internal_string = ''; exports.Construct = Construct; class NewConstructor { constructor(field) { this.field = field; } get() { return this.field + 1; } } exports.NewConstructors = NewConstructor; exports.default = NewConstructor; let switch_called = false; class SwitchMethods { constructor() { } static a() { switch_called = true; } b() { switch_called = true; } } exports.SwitchMethods = SwitchMethods; exports.switch_methods_called = function() { const tmp = switch_called; switch_called = false; return tmp; }; exports.switch_methods_a = function() { SwitchMethods.a = function() {}; }; exports.switch_methods_b = function() { SwitchMethods.prototype.b = function() {}; }; exports.Properties = class { constructor() { this.num = 1; } get a() { return this.num; } set a(val) { this.num = val; } }; exports.RenameProperties = class { constructor() { this.num = 1; } get a() { return this.num; } set a(val) { this.num = val; } }; class Options { } exports.Options = Options; exports.take_none = function(val) { assert.strictEqual(val, undefined); }; exports.take_some = function(val) { assert.strictEqual(val === undefined, false); }; exports.return_null = function() { return null; }; exports.return_undefined = function() { return undefined; }; exports.return_some = function() { return new Options(); }; exports.run_rust_option_tests = function() { wasm.rust_take_none(); wasm.rust_take_none(null) wasm.rust_take_none(undefined); wasm.rust_take_some(new Options()); assert.strictEqual(wasm.rust_return_none(), undefined); assert.strictEqual(wasm.rust_return_none(), undefined); assert.strictEqual(wasm.rust_return_some() === undefined, false); }; exports.CatchConstructors = class { constructor(x) { if (x == 0) { throw new Error('bad!'); } } }; exports.StaticStructural = class { static static_structural(x) { return x + 3; } }; class InnerClass { static inner_static_function(x) { return x + 5; } static create_inner_instance() { const ret = new InnerClass(); ret.internal_int = 3; return ret; } get_internal_int() { return this.internal_int; } append_to_internal_int(i) { this.internal_int += i; } assert_internal_int(i) { assert.strictEqual(this.internal_int, i); } } exports.nestedNamespace = { InnerClass: InnerClass } wasm-bindgen-0.2.87/tests/wasm/import_class.rs000064400000000000000000000170121046102023000174540ustar 00000000000000//! dox #![deny(missing_docs)] // test that documenting public bindings is enough #![allow(clippy::redundant_clone)] // test specifically with cloned objects use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/import_class.js")] extern "C" { fn math_log(f: f64) -> f64; #[wasm_bindgen(js_namespace = StaticFunction)] fn bar() -> u32; #[derive(Clone)] type Construct; #[wasm_bindgen(js_namespace = Construct)] fn create() -> Construct; #[wasm_bindgen(method)] fn get_internal_string(this: &Construct) -> String; #[wasm_bindgen(method)] fn append_to_internal_string(this: &Construct, s: &str); #[wasm_bindgen(method)] fn assert_internal_string(this: &Construct, s: &str); #[wasm_bindgen(method, js_name = "kebab-case")] fn kebab_case(this: &Construct) -> u32; #[wasm_bindgen(method, getter, js_name = "kebab-case-val")] fn kebab_case_val(this: &Construct) -> u32; #[wasm_bindgen(method, setter, js_name = "kebab-case-val")] fn set_kebab_case_val(this: &Construct, val: u32); #[wasm_bindgen(static_method_of = Construct, js_name = "static-kebab-case")] fn static_kebab_case() -> u32; #[wasm_bindgen(static_method_of = Construct, getter, js_name = "static-kebab-case-val")] fn static_kebab_case_val() -> u32; #[wasm_bindgen(static_method_of = Construct, setter, js_name = "static-kebab-case-val")] fn set_static_kebab_case_val(val: u32); type NewConstructors; #[wasm_bindgen(constructor)] fn new(arg: i32) -> NewConstructors; #[wasm_bindgen(method)] fn get(this: &NewConstructors) -> i32; #[wasm_bindgen(js_name = default)] type RenamedTypes; #[wasm_bindgen(constructor, js_class = default)] fn new(arg: i32) -> RenamedTypes; #[wasm_bindgen(method, js_class = default)] fn get(this: &RenamedTypes) -> i32; fn switch_methods_a(); fn switch_methods_b(); type SwitchMethods; #[wasm_bindgen(constructor)] #[wasm_bindgen(final)] fn new() -> SwitchMethods; #[wasm_bindgen(js_namespace = SwitchMethods, final)] fn a(); fn switch_methods_called() -> bool; #[wasm_bindgen(method, final)] fn b(this: &SwitchMethods); type Properties; #[wasm_bindgen(constructor)] fn new() -> Properties; #[wasm_bindgen(getter, method)] fn a(this: &Properties) -> i32; #[wasm_bindgen(setter, method)] fn set_a(this: &Properties, a: i32); type RenameProperties; #[wasm_bindgen(constructor)] fn new() -> RenameProperties; #[wasm_bindgen(getter = a, method)] fn test(this: &RenameProperties) -> i32; #[wasm_bindgen(getter, method, js_name = a)] fn test2(this: &RenameProperties) -> i32; #[wasm_bindgen(setter = a, method)] fn another(this: &RenameProperties, a: i32); #[wasm_bindgen(setter, method, js_name = a)] fn another2(this: &RenameProperties, a: i32); /// dox pub type AssertImportDenyDocsWorks; /// dox #[wasm_bindgen(constructor)] pub fn new() -> AssertImportDenyDocsWorks; /// dox #[wasm_bindgen(getter = a, method)] pub fn test(this: &AssertImportDenyDocsWorks) -> i32; /// dox pub fn foo(); pub type Options; #[wasm_bindgen(constructor)] fn new() -> Options; fn take_none(val: Option); fn take_some(val: Option); fn return_null() -> Option; fn return_undefined() -> Option; fn return_some() -> Option; fn run_rust_option_tests(); type CatchConstructors; #[wasm_bindgen(constructor, catch)] fn new(x: u32) -> Result; type StaticStructural; #[wasm_bindgen(static_method_of = StaticStructural, structural)] fn static_structural(a: u32) -> u32; #[derive(Clone)] type InnerClass; #[wasm_bindgen(js_namespace = ["nestedNamespace", "InnerClass"])] fn inner_static_function(a: u32) -> u32; #[wasm_bindgen(js_namespace = ["nestedNamespace", "InnerClass"])] fn create_inner_instance() -> InnerClass; #[wasm_bindgen(method)] fn get_internal_int(this: &InnerClass) -> u32; #[wasm_bindgen(method)] fn append_to_internal_int(this: &InnerClass, i: u32); #[wasm_bindgen(method)] fn assert_internal_int(this: &InnerClass, i: u32); } #[wasm_bindgen(js_namespace = Math)] extern "C" { #[wasm_bindgen] fn random() -> f64; #[wasm_bindgen] fn log(a: f64) -> f64; } #[wasm_bindgen_test] fn simple() { random(); assert_eq!(log(1.0), math_log(1.0)); } #[wasm_bindgen_test] fn import_class() { assert_eq!(bar(), 2); } #[wasm_bindgen_test] fn construct() { let f = Construct::create(); assert_eq!(f.get_internal_string(), "this"); assert_eq!(f.clone().get_internal_string(), "this"); f.append_to_internal_string(" foo"); f.assert_internal_string("this foo"); assert_eq!(f.kebab_case(), 42); f.set_kebab_case_val(0); // our setter does nothing so this is 42 anyway assert_eq!(f.kebab_case_val(), 42); assert_eq!(Construct::static_kebab_case(), 42); Construct::set_static_kebab_case_val(0); assert_eq!(Construct::static_kebab_case_val(), 42); } #[wasm_bindgen_test] fn new_constructors() { let f = NewConstructors::new(1); assert_eq!(f.get(), 2); } #[wasm_bindgen_test] fn rename_type() { let f = RenamedTypes::new(1); assert_eq!(f.get(), 2); } #[wasm_bindgen_test] fn switch_methods() { assert!(!switch_methods_called()); SwitchMethods::a(); assert!(switch_methods_called()); switch_methods_a(); assert!(!switch_methods_called()); SwitchMethods::a(); assert!(switch_methods_called()); assert!(!switch_methods_called()); SwitchMethods::new().b(); assert!(switch_methods_called()); switch_methods_b(); assert!(!switch_methods_called()); SwitchMethods::new().b(); assert!(!switch_methods_called()); } #[wasm_bindgen_test] fn properties() { let a = Properties::new(); assert_eq!(a.a(), 1); a.set_a(2); assert_eq!(a.a(), 2); } #[wasm_bindgen_test] fn rename_setter_getter() { let x: fn() -> RenameProperties = RenameProperties::new; let a = x(); assert_eq!(a.test(), 1); a.another(2); assert_eq!(a.test(), 2); a.another2(3); assert_eq!(a.test2(), 3); } /// dox #[wasm_bindgen] pub struct AssertDenyDocsWorks { /// dox pub a: u32, _b: i64, } /// dox #[wasm_bindgen] pub fn assert_deny_docs_works() {} #[wasm_bindgen_test] fn options() { take_none(None); take_some(Some(Options::new())); assert!(return_null().is_none()); assert!(return_undefined().is_none()); assert!(return_some().is_some()); run_rust_option_tests(); } /// doc #[wasm_bindgen] pub fn rust_take_none(a: Option) { assert!(a.is_none()); } /// doc #[wasm_bindgen] pub fn rust_take_some(a: Option) { assert!(a.is_some()); } /// doc #[wasm_bindgen] pub fn rust_return_none() -> Option { None } /// doc #[wasm_bindgen] pub fn rust_return_some() -> Option { Some(Options::new()) } #[wasm_bindgen_test] fn catch_constructors() { assert!(CatchConstructors::new(0).is_err()); assert!(CatchConstructors::new(1).is_ok()); } #[wasm_bindgen_test] fn static_structural() { assert_eq!(StaticStructural::static_structural(30), 33); } #[wasm_bindgen_test] fn nested_namespace() { assert_eq!(InnerClass::inner_static_function(15), 20); let f = InnerClass::create_inner_instance(); assert_eq!(f.get_internal_int(), 3); assert_eq!(f.clone().get_internal_int(), 3); f.append_to_internal_int(5); f.assert_internal_int(8); } wasm-bindgen-0.2.87/tests/wasm/imports.js000064400000000000000000000064011046102023000164420ustar 00000000000000const assert = require('assert'); const wasm = require('wasm-bindgen-test'); const fs = require('fs'); let ARG = null; let ANOTHER_ARG = null; let SYM = Symbol('a'); exports.simple_foo = function(s) { assert.strictEqual(ARG, null); assert.strictEqual(s, "foo"); ARG = s; }; exports.simple_another = function(s) { assert.strictEqual(ANOTHER_ARG, null); assert.strictEqual(s, 21); ANOTHER_ARG = s; return 35; }; exports.simple_take_and_return_bool = function(s) { return s; }; exports.simple_return_object = function() { return SYM; }; exports.test_simple = function() { assert.strictEqual(ARG, null); wasm.simple_take_str("foo"); assert.strictEqual(ARG, "foo"); assert.strictEqual(ANOTHER_ARG, null); assert.strictEqual(wasm.simple_another_thunk(21), 35); assert.strictEqual(ANOTHER_ARG, 21); assert.strictEqual(wasm.simple_bool_thunk(true), true); assert.strictEqual(wasm.simple_bool_thunk(false), false); assert.strictEqual(wasm.simple_get_the_object(), SYM); }; exports.return_string = function() { return 'bar'; }; exports.take_and_ret_string = function(a) { return a + 'b'; }; exports.exceptions_throw = function() { throw new Error('error!'); }; exports.exceptions_throw2 = function() { throw new Error('error2'); }; exports.test_exception_propagates = function() { assert.throws(wasm.exceptions_propagate, /error!/); }; exports.assert_valid_error = function(obj) { assert.strictEqual(obj instanceof Error, true); assert.strictEqual(obj.message, 'error2'); }; exports.IMPORT = 1.0; exports.return_three = function() { return 3; }; exports.underscore = function(x) {}; exports.pub = function() { return 2; }; exports.bar = { foo: 3 }; let CUSTOM_TYPE = null; exports.take_custom_type = function(f) { CUSTOM_TYPE = f; return f; }; exports.custom_type_return_2 = function() { return 2; }; exports.touch_custom_type = function() { assert.throws(() => CUSTOM_TYPE.touch(), /Attempt to use a moved value|null pointer passed to rust/); }; exports.interpret_2_as_custom_type = function() { assert.throws(wasm.interpret_2_as_custom_type, /expected instance of CustomType/); }; exports.baz$ = function() {}; exports.$foo = 1.0; exports.assert_dead_import_not_generated = function() { const filename = require.resolve("wasm-bindgen-test"); const bindings = fs.readFileSync(filename); assert.ok(!bindings.includes("unused_import")); }; exports.import_inside_function_works = function() {}; exports.import_inside_private_module = function() {}; exports.should_call_undefined_functions = () => false; exports.STATIC_STRING = 'x'; class StaticMethodCheck { static static_method_of_right_this() { assert.ok(this === StaticMethodCheck); } } exports.StaticMethodCheck = StaticMethodCheck; exports.receive_undefined = val => { assert.strictEqual(val, undefined); }; const VAL = {}; exports.receive_some = val => { assert.strictEqual(val, VAL); }; exports.get_some_val = () => VAL; exports.Math = { func_from_module_math: (a) => a * 2 } exports.Number = { func_from_module_number: () => 3.0 } exports.same_name_from_import = (a) => a * 3; exports.same_js_namespace_from_module = { func_from_module_1_same_js_namespace: (a) => a * 5 } exports["kebab-case"] = () => 42; exports["\"string'literal\nbreakers\r"] = () => 42; wasm-bindgen-0.2.87/tests/wasm/imports.rs000064400000000000000000000200201046102023000164430ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/imports.js")] extern "C" { fn test_simple(); fn simple_foo(s: &str); fn simple_another(a: u32) -> i32; fn simple_take_and_return_bool(a: bool) -> bool; fn simple_return_object() -> JsValue; #[allow(dead_code)] fn missing_symbol(s: &str); fn return_string() -> String; fn take_and_ret_string(s: String) -> String; #[wasm_bindgen(js_name = take_and_ret_string)] fn take_and_ret_string2(s: &str) -> String; fn exceptions_throw(); #[wasm_bindgen(catch)] fn exceptions_throw2() -> Result<(), JsValue>; fn test_exception_propagates(); fn assert_valid_error(val: JsValue); static IMPORT: JsValue; #[wasm_bindgen(js_name = return_three)] fn rust_name_for_return_three() -> u32; fn underscore(_: u8); #[wasm_bindgen(js_name = pub)] fn js_function_named_rust_keyword() -> u32; #[allow(non_camel_case_types)] type bar; #[wasm_bindgen(js_namespace = bar, js_name = foo)] static FOO: JsValue; fn take_custom_type(f: CustomType) -> CustomType; fn touch_custom_type(); fn custom_type_return_2() -> CustomType; #[wasm_bindgen(js_name = interpret_2_as_custom_type)] fn js_interpret_2_as_custom_type(); #[wasm_bindgen(js_name = "baz$")] fn renamed_with_dollar_sign(); #[wasm_bindgen(js_name = "$foo")] static RENAMED: JsValue; fn unused_import(); fn assert_dead_import_not_generated(); fn should_call_undefined_functions() -> bool; type StaticMethodCheck; #[wasm_bindgen(static_method_of = StaticMethodCheck)] fn static_method_of_right_this(); static STATIC_STRING: String; #[derive(Clone)] type PassOutOptionUndefined; fn get_some_val() -> PassOutOptionUndefined; #[wasm_bindgen(js_name = "receive_undefined")] fn receive_undefined_ref(arg: Option<&PassOutOptionUndefined>); #[wasm_bindgen(js_name = "receive_undefined")] fn receive_undefined_owned(arg: Option); #[wasm_bindgen(js_name = "receive_some")] fn receive_some_ref(arg: Option<&PassOutOptionUndefined>); #[wasm_bindgen(js_name = "receive_some")] fn receive_some_owned(arg: Option); #[wasm_bindgen(js_namespace = Math)] fn func_from_module_math(a: i32) -> i32; #[wasm_bindgen(js_namespace = Number)] fn func_from_module_number() -> f64; #[wasm_bindgen(js_name = "same_name_from_import")] fn same_name_from_import_1(s: i32) -> i32; #[wasm_bindgen(js_namespace = same_js_namespace_from_module)] fn func_from_module_1_same_js_namespace(s: i32) -> i32; #[wasm_bindgen(js_name = "kebab-case")] fn kebab_case() -> u32; #[wasm_bindgen(js_name = "\"string'literal\nbreakers\r")] fn string_literal_breakers() -> u32; } #[wasm_bindgen(module = "tests/wasm/imports_2.js")] extern "C" { #[wasm_bindgen(js_name = "same_name_from_import")] fn same_name_from_import_2(s: i32) -> i32; #[wasm_bindgen(js_namespace = same_js_namespace_from_module)] fn func_from_module_2_same_js_namespace(s: i32) -> i32; } #[wasm_bindgen] extern "C" { fn parseInt(a: &str) -> u32; #[wasm_bindgen(js_namespace = Math, js_name = "sqrt")] fn func_from_global_math(s: f64) -> f64; type Number; #[wasm_bindgen(getter, static_method_of = Number, js_name = "NAN")] fn static_getter_from_global_number() -> f64; } #[wasm_bindgen_test] fn simple() { test_simple(); } #[wasm_bindgen] pub fn simple_take_str(s: &str) { simple_foo(s); } #[wasm_bindgen] pub fn simple_another_thunk(a: u32) -> i32 { simple_another(a) } #[wasm_bindgen] pub fn simple_bool_thunk(a: bool) -> bool { simple_take_and_return_bool(a) } #[wasm_bindgen] pub fn simple_get_the_object() -> JsValue { simple_return_object() } #[wasm_bindgen_test] fn string_ret() { assert_eq!(return_string(), "bar"); } #[wasm_bindgen_test] fn strings() { assert_eq!(take_and_ret_string(String::from("a")), "ab"); assert_eq!(take_and_ret_string2("b"), "bb"); } #[wasm_bindgen_test] fn exceptions() { test_exception_propagates(); assert!(exceptions_throw2().is_err()); } #[wasm_bindgen] pub fn exceptions_propagate() { exceptions_throw(); } #[wasm_bindgen_test] fn exn_caught() { assert_valid_error(exceptions_throw2().unwrap_err()); } #[wasm_bindgen_test] fn free_imports() { assert_eq!(parseInt("3"), 3); } #[wasm_bindgen_test] fn import_a_field() { assert_eq!(IMPORT.as_f64(), Some(1.0)); } #[wasm_bindgen_test] fn rename() { assert_eq!(rust_name_for_return_three(), 3); } #[wasm_bindgen_test] fn underscore_pattern() { underscore(2); } #[wasm_bindgen_test] fn rust_keyword() { assert_eq!(js_function_named_rust_keyword(), 2); } #[wasm_bindgen_test] fn rust_keyword2() { assert_eq!(FOO.as_f64(), Some(3.0)); } #[wasm_bindgen_test] fn custom_type() { take_custom_type(CustomType(())); touch_custom_type(); js_interpret_2_as_custom_type(); } #[wasm_bindgen] pub fn interpret_2_as_custom_type() { custom_type_return_2(); } #[wasm_bindgen] pub struct CustomType(()); #[wasm_bindgen] impl CustomType { pub fn touch(&self) { panic!() } } #[wasm_bindgen_test] fn rename_with_string() { renamed_with_dollar_sign(); } #[wasm_bindgen_test] fn rename_static_with_string() { assert_eq!(RENAMED.as_f64(), Some(1.0)); } #[wasm_bindgen_test] fn dead_imports_not_generated() { assert_dead_import_not_generated(); } #[wasm_bindgen_test] fn import_inside_function_works() { #[wasm_bindgen(module = "tests/wasm/imports.js")] extern "C" { fn import_inside_function_works(); } import_inside_function_works(); } #[wasm_bindgen_test] fn private_module_imports_work() { private::foo(); } mod private { use wasm_bindgen::prelude::*; pub fn foo() { #[wasm_bindgen(module = "tests/wasm/imports.js")] extern "C" { fn import_inside_private_module(); } import_inside_private_module(); } } #[wasm_bindgen] extern "C" { fn something_not_defined_in_the_environment(); type TypeThatIsNotDefined; #[wasm_bindgen(constructor)] fn new() -> TypeThatIsNotDefined; #[wasm_bindgen(method)] fn method(this: &TypeThatIsNotDefined); #[wasm_bindgen(method, getter)] fn property(this: &TypeThatIsNotDefined) -> u32; #[wasm_bindgen(method, setter)] fn set_property(this: &TypeThatIsNotDefined, val: u32); } #[wasm_bindgen_test] fn undefined_function_is_ok() { if !should_call_undefined_functions() { return; } something_not_defined_in_the_environment(); let x = TypeThatIsNotDefined::new(); x.method(); x.set_property(x.property()); } #[wasm_bindgen_test] fn static_string_ok() { assert_eq!(*STATIC_STRING, "x"); } #[wasm_bindgen_test] fn static_method_of_has_right_this() { StaticMethodCheck::static_method_of_right_this(); } #[wasm_bindgen_test] fn pass_out_options_as_undefined() { receive_undefined_ref(None); receive_undefined_ref(None); receive_undefined_owned(None); receive_undefined_owned(None); let v = get_some_val(); receive_some_ref(Some(&v)); receive_some_ref(Some(&v)); receive_some_owned(Some(v.clone())); receive_some_owned(Some(v)); } #[wasm_bindgen_test] fn func_from_global_and_module_same_js_namespace() { assert_eq!(func_from_global_math(4.0), 2.0); assert_eq!(func_from_module_math(2), 4); } #[wasm_bindgen_test] fn getter_from_global_and_module_same_name() { assert!(Number::static_getter_from_global_number().is_nan()); assert_eq!(func_from_module_number(), 3.0); } #[wasm_bindgen_test] fn func_from_two_modules_same_js_name() { assert_eq!(same_name_from_import_1(1), 3); assert_eq!(same_name_from_import_2(1), 4); } #[wasm_bindgen_test] fn func_from_two_modules_same_js_namespace() { assert_eq!(func_from_module_1_same_js_namespace(2), 10); assert_eq!(func_from_module_2_same_js_namespace(2), 12); } #[wasm_bindgen_test] fn invalid_idents() { assert_eq!(kebab_case(), 42); assert_eq!(string_literal_breakers(), 42); } wasm-bindgen-0.2.87/tests/wasm/imports_2.js000064400000000000000000000002171046102023000166620ustar 00000000000000exports.same_name_from_import = (a) => a * 4; exports.same_js_namespace_from_module = { func_from_module_2_same_js_namespace: (a) => a * 6 }wasm-bindgen-0.2.87/tests/wasm/intrinsics.rs000064400000000000000000000066661046102023000171570ustar 00000000000000//! Tests that some of our more obscure intrinsics work properly. use std::convert::TryFrom; use std::fmt::Debug; use js_sys::{Array, Object, RangeError, Reflect}; use wasm_bindgen::{JsCast, JsValue}; use wasm_bindgen_test::wasm_bindgen_test; // Shorter `JsValue::from(i32)`. fn int(x: i32) -> JsValue { JsValue::from(x) } #[wasm_bindgen_test] fn bitwise() { assert_eq!(int(0b1110) & int(0b0111), 0b0110); assert_eq!(int(0b1000) | int(0b0010), 0b1010); assert_eq!(int(0b1110) ^ int(0b0100), 0b1010); assert_eq!(int(0x00ffffff).bit_not(), 0xff000000u32 as i32); assert_eq!(int(0b0001) << int(2), 0b0100); assert_eq!(int(0b1000) >> int(2), 0b0010); assert_eq!(int(-0b1000) >> int(2), -0b0010); // Note that bit-wise, this is the same as the above `-0b1000`. assert_eq!( JsValue::from(0xfffffff8u32).unsigned_shr(&int(2)), 0x3ffffffe ); } #[wasm_bindgen_test] fn arithmetic() { assert_eq!(-int(12), -12); assert_eq!(int(1) + int(2), 3); assert_eq!(int(1) - int(2), -1); assert_eq!(int(10) / int(5), 2); assert_eq!(int(42).checked_div(&int(6)), 7); // Note that this doesn't throw for regular numbers, since they just give // `NaN` for invalid results. assert!(JsValue::bigint_from_str("0") .checked_div(&JsValue::bigint_from_str("0")) .dyn_into::() .is_ok()); assert_eq!(int(12) * int(34), 408); assert_eq!(int(17) % int(10), 7); assert_eq!(int(2).pow(&int(8)), 256) } #[wasm_bindgen_test] fn cmp() { assert!(int(2).lt(&int(3))); assert!(!int(2).lt(&int(2))); assert!(int(2).le(&int(3))); assert!(int(2).le(&int(2))); assert!(int(3).ge(&int(2))); assert!(int(3).ge(&int(3))); assert!(int(3).gt(&int(2))); assert!(!int(3).gt(&int(3))); assert!(int(2) == int(2)); assert!(int(2) != int(3)); assert!(int(2) != JsValue::from_str("2")); assert!(int(2).loose_eq(&JsValue::from_str("2"))); } #[wasm_bindgen_test] fn types() { assert!( Reflect::get(&js_sys::global(), &JsValue::from_str("Number")) .unwrap() .is_function() ); assert!(JsValue::UNDEFINED.is_undefined()); assert!(JsValue::NULL.is_null()); assert!(Object::new().is_object()); assert!(Array::new().is_array()); assert!(JsValue::symbol(None).is_symbol()); assert!(JsValue::from_str("hi").is_string()); assert!(JsValue::bigint_from_str("5").is_bigint()); assert_eq!(int(5).js_typeof(), "number"); assert_eq!(JsValue::bigint_from_str("5").js_typeof(), "bigint"); assert_eq!(JsValue::NULL.js_typeof(), "object"); } #[wasm_bindgen_test] fn misc() { assert!(JsValue::from_str("Number").js_in(&js_sys::global())); assert!(!JsValue::from_str("frob").js_in(&js_sys::global())); assert_eq!(int(5).unchecked_into_f64(), 5.0); assert_eq!(JsValue::from_str("5").unchecked_into_f64(), 5.0); assert_eq!(f64::try_from(int(5)), Ok(5.0)); assert_eq!(f64::try_from(JsValue::from_str("5")), Ok(5.0)); assert!(f64::try_from(JsValue::from_str("hi")).unwrap().is_nan()); assert!(f64::try_from(JsValue::symbol(None)).is_err()); } fn debug(x: impl Debug) -> String { format!("{x:?}") } #[wasm_bindgen_test] fn debug_string() { assert_eq!(debug(int(5)), "JsValue(5)"); assert_eq!(debug(JsValue::TRUE), "JsValue(true)"); assert_eq!(debug(JsValue::symbol(None)), "JsValue(Symbol)"); assert_eq!(debug(JsValue::from_str("hi")), "JsValue(\"hi\")"); } wasm-bindgen-0.2.87/tests/wasm/js_keywords.js000064400000000000000000000012641046102023000173120ustar 00000000000000const wasm = require("wasm-bindgen-test.js"); const assert = require("assert"); exports.js_keywords_compile = () => { assert.strictEqual(wasm._throw(1), 1); assert.strictEqual(wasm._class(1, 2), false); assert.strictEqual(wasm.classy(3), 3); let obj = new wasm.Class("class"); assert.strictEqual(wasm.Class.void("string"), "string"); assert.strictEqual(obj.catch, "class"); assert.strictEqual(obj.instanceof("Class"), "class is instance of Class"); }; exports.test_keyword_1_as_fn_name = (x) => { return wasm._throw(x); }; exports.test_keyword_2_as_fn_name = (x, y) => { return wasm._class(x, y); }; exports.test_keyword_as_fn_arg = (x) => { return wasm.classy(x); }; wasm-bindgen-0.2.87/tests/wasm/js_keywords.rs000064400000000000000000000023571046102023000173260ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/js_keywords.js")] extern "C" { fn js_keywords_compile(); fn test_keyword_1_as_fn_name(x: u8) -> u8; fn test_keyword_2_as_fn_name(x: u8, y: u8) -> bool; fn test_keyword_as_fn_arg(x: u8) -> u8; } #[wasm_bindgen] pub fn throw(class: u8) -> u8 { class } #[wasm_bindgen(js_name = class)] pub fn fn_parsed_to_keyword(instanceof: u8, catch: u8) -> bool { instanceof > catch } #[wasm_bindgen(js_name = classy)] pub fn arg_is_keyword(class: u8) -> u8 { class } #[wasm_bindgen] pub struct Class { name: String, } #[wasm_bindgen] impl Class { #[wasm_bindgen(constructor)] pub fn new(void: String) -> Self { Class { name: void } } pub fn instanceof(&self, class: String) -> String { format!("{} is instance of {}", self.name.clone(), class) } #[wasm_bindgen(getter)] pub fn catch(&self) -> String { self.name.clone() } pub fn void(void: String) -> String { void } } #[wasm_bindgen_test] fn compile() { js_keywords_compile(); assert_eq!(test_keyword_1_as_fn_name(1), 1); assert!(!test_keyword_2_as_fn_name(1, 2)); assert_eq!(test_keyword_as_fn_arg(1), 1); } wasm-bindgen-0.2.87/tests/wasm/js_objects.js000064400000000000000000000045521046102023000170770ustar 00000000000000const wasm = require('wasm-bindgen-test.js'); const assert = require('assert'); let SIMPLE_ARG = null; exports.simple_foo = s => { assert.strictEqual(SIMPLE_ARG, null); SIMPLE_ARG = s; }; exports.js_simple = () => { assert.strictEqual(SIMPLE_ARG, null); let sym = Symbol('test'); wasm.simple_bar(sym); assert.strictEqual(SIMPLE_ARG, sym); }; let OWNED_ARG = null; exports.owned_foo = s => { assert.strictEqual(OWNED_ARG, null); OWNED_ARG = s; }; exports.js_owned = () => { assert.strictEqual(OWNED_ARG, null); let sym = Symbol('test'); wasm.owned_bar(sym); assert.strictEqual(OWNED_ARG, sym); }; let CLONE_ARG = Symbol('test'); exports.clone_foo1 = s => { assert.strictEqual(s, CLONE_ARG); }; exports.clone_foo2 = s => { assert.strictEqual(s, CLONE_ARG); }; exports.clone_foo3 = s => { assert.strictEqual(s, CLONE_ARG); }; exports.clone_foo4 = s => { assert.strictEqual(s, CLONE_ARG); }; exports.clone_foo5 = s => { assert.strictEqual(s, CLONE_ARG); }; exports.js_clone = () => { wasm.clone_bar(CLONE_ARG); }; let PROMOTE_ARG = Symbol('test'); exports.promote_foo1 = s => { assert.strictEqual(s, PROMOTE_ARG); }; exports.promote_foo2 = s => { assert.strictEqual(s, PROMOTE_ARG); }; exports.promote_foo3 = s => { assert.strictEqual(s, PROMOTE_ARG); }; exports.promote_foo4 = s => { assert.strictEqual(s, PROMOTE_ARG); }; exports.js_promote = () => { wasm.promote_bar(PROMOTE_ARG); }; exports.returning_vector_foo = () => { return {'foo': 'bar'}; }; exports.js_returning_vector = () => { assert.strictEqual(wasm.returning_vector_bar().length, 10); }; exports.js_another_vector_return = () => { assert.deepStrictEqual(wasm.another_vector_return_get_array(), [1, 2, 3, 4, 5, 6]); }; exports.returning_vector_string_foo = () => { return "This is the mostest awesomest string that can possibly exist."; }; exports.js_returning_vector_string = () => { assert.strictEqual(wasm.returning_vector_string_bar().length, 10); }; exports.js_another_vector_string_return = () => { assert.deepStrictEqual(wasm.another_vector_string_return_get_array(), ["1", "2", "3", "4", "5", "6"]); }; exports.verify_serde = function(a) { assert.deepStrictEqual(a, { a: 0, b: 'foo', c: null, d: { a: 1 } }); return { a: 2, b: 'bar', c: { a: 3 }, d: { a: 4 }, } }; wasm-bindgen-0.2.87/tests/wasm/js_objects.rs000064400000000000000000000072551046102023000171120ustar 00000000000000use js_sys::JsString; use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/js_objects.js")] extern "C" { fn simple_foo(s: &JsValue); fn js_simple(); fn owned_foo(s: JsValue); fn js_owned(); fn clone_foo1(s: JsValue); fn clone_foo2(s: &JsValue); fn clone_foo3(s: JsValue); fn clone_foo4(s: &JsValue); fn clone_foo5(s: JsValue); fn js_clone(); fn promote_foo1(s: &JsValue); fn promote_foo2(s: JsValue); fn promote_foo3(s: &JsValue); fn promote_foo4(s: JsValue); fn js_promote(); fn returning_vector_foo() -> JsValue; fn js_returning_vector(); fn js_another_vector_return(); fn returning_vector_string_foo() -> JsString; fn js_returning_vector_string(); fn js_another_vector_string_return(); fn verify_serde(val: JsValue) -> JsValue; } #[wasm_bindgen] pub fn simple_bar(s: &JsValue) { simple_foo(s); } #[wasm_bindgen_test] fn simple() { js_simple(); } #[wasm_bindgen] pub fn owned_bar(s: JsValue) { owned_foo(s); } #[wasm_bindgen_test] fn owned() { js_owned(); } #[wasm_bindgen] pub fn clone_bar(s: JsValue) { clone_foo1(s.clone()); clone_foo2(&s); clone_foo3(s.clone()); clone_foo4(&s); clone_foo5(s); } #[wasm_bindgen_test] fn clone() { js_clone(); } #[wasm_bindgen] pub fn promote_bar(s: &JsValue) { promote_foo1(s); promote_foo2(s.clone()); promote_foo3(s); promote_foo4(s.clone()); } #[wasm_bindgen_test] fn promote() { js_promote(); } #[wasm_bindgen] pub fn returning_vector_bar() -> Vec { let mut res = Vec::new(); for _ in 0..10 { res.push(returning_vector_foo()) } res } #[wasm_bindgen_test] fn returning_vector() { js_returning_vector(); } #[wasm_bindgen] pub fn another_vector_return_get_array() -> Vec { vec![ JsValue::from(1), JsValue::from(2), JsValue::from(3), JsValue::from(4), JsValue::from(5), JsValue::from(6), ] } #[wasm_bindgen_test] fn another_vector_return() { js_another_vector_return(); } #[wasm_bindgen] pub fn returning_vector_string_bar() -> Vec { let mut res = Vec::new(); for _ in 0..10 { res.push(returning_vector_string_foo()) } res } #[wasm_bindgen_test] fn returning_vector_string() { js_returning_vector_string(); } #[wasm_bindgen] pub fn another_vector_string_return_get_array() -> Vec { vec![ "1".into(), "2".into(), "3".into(), "4".into(), "5".into(), "6".into(), ] } #[wasm_bindgen_test] fn another_vector_string_return() { js_another_vector_string_return(); } #[cfg(feature = "serde-serialize")] #[wasm_bindgen_test] #[allow(deprecated)] fn serde() { #[derive(Deserialize, Serialize)] pub struct SerdeFoo { a: u32, b: String, c: Option, d: SerdeBar, } #[derive(Deserialize, Serialize)] pub struct SerdeBar { a: u32, } let js = JsValue::from_serde("foo").unwrap(); assert_eq!(js.as_string(), Some("foo".to_string())); let ret = verify_serde( JsValue::from_serde(&SerdeFoo { a: 0, b: "foo".to_string(), c: None, d: SerdeBar { a: 1 }, }) .unwrap(), ); let result = ret.into_serde::().unwrap(); assert_eq!(result.a, 2); assert_eq!(result.b, "bar"); assert!(result.c.is_some()); assert_eq!(result.c.as_ref().unwrap().a, 3); assert_eq!(result.d.a, 4); assert_eq!(JsValue::from("bar").into_serde::().unwrap(), "bar"); assert_eq!(JsValue::undefined().into_serde::().ok(), None); } wasm-bindgen-0.2.87/tests/wasm/jscast.js000064400000000000000000000006111046102023000162310ustar 00000000000000class JsCast1 { constructor() { this.val = 1; } myval() { return this.val; } } class JsCast2 { } class JsCast3 extends JsCast1 { constructor() { super(); this.val = 3; } } class JsCast4 extends JsCast3 { constructor() { super(); this.val = 4; } } exports.JsCast1 = JsCast1; exports.JsCast2 = JsCast2; exports.JsCast3 = JsCast3; exports.JsCast4 = JsCast4; wasm-bindgen-0.2.87/tests/wasm/jscast.rs000064400000000000000000000044251046102023000162500ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/jscast.js")] extern "C" { type JsCast1; #[wasm_bindgen(constructor)] fn new() -> JsCast1; #[wasm_bindgen(method)] fn myval(this: &JsCast1) -> u32; type JsCast2; #[wasm_bindgen(constructor)] fn new() -> JsCast2; #[wasm_bindgen(extends = JsCast1)] type JsCast3; #[wasm_bindgen(constructor)] fn new() -> JsCast3; #[wasm_bindgen(extends = crate::jscast::JsCast1, extends = JsCast3)] type JsCast4; #[wasm_bindgen(constructor)] fn new() -> JsCast4; } #[wasm_bindgen_test] fn instanceof_works() { let a = JsCast1::new(); let b = JsCast2::new(); let c = JsCast3::new(); assert!(a.is_instance_of::()); assert!(!a.is_instance_of::()); assert!(!a.is_instance_of::()); assert!(!b.is_instance_of::()); assert!(b.is_instance_of::()); assert!(!b.is_instance_of::()); assert!(c.is_instance_of::()); assert!(!c.is_instance_of::()); assert!(c.is_instance_of::()); } #[wasm_bindgen_test] fn casting() { let a = JsCast1::new(); let b = JsCast2::new(); let c = JsCast3::new(); assert!(a.dyn_ref::().is_some()); assert!(a.dyn_ref::().is_none()); assert!(a.dyn_ref::().is_none()); assert!(b.dyn_ref::().is_none()); assert!(b.dyn_ref::().is_some()); assert!(b.dyn_ref::().is_none()); assert!(c.dyn_ref::().is_some()); assert!(c.dyn_ref::().is_none()); assert!(c.dyn_ref::().is_some()); } #[wasm_bindgen_test] fn method_calling() { let a = JsCast1::new(); let b = JsCast3::new(); assert_eq!(a.myval(), 1); assert_eq!(b.dyn_ref::().unwrap().myval(), 3); assert_eq!(b.unchecked_ref::().myval(), 3); let c: &JsCast1 = b.as_ref(); assert_eq!(c.myval(), 3); } #[wasm_bindgen_test] fn multiple_layers_of_inheritance() { let a = JsCast4::new(); assert!(a.is_instance_of::()); assert!(a.is_instance_of::()); assert!(a.is_instance_of::()); let _: &JsCast3 = a.as_ref(); let b: &JsCast1 = a.as_ref(); assert_eq!(b.myval(), 4); } wasm-bindgen-0.2.87/tests/wasm/link_to.js000064400000000000000000000002051046102023000164000ustar 00000000000000const fs = require('fs'); const url = require('url'); exports.read_file = (str) => fs.readFileSync(url.fileURLToPath(str), "utf8"); wasm-bindgen-0.2.87/tests/wasm/link_to.rs000064400000000000000000000017341046102023000164200ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "/tests/wasm/link_to.js")] extern "C" { #[wasm_bindgen(catch)] fn read_file(url: &str) -> Result; } #[wasm_bindgen_test] fn test_module() { let link = wasm_bindgen::link_to!(module = "/tests/wasm/linked_module.js"); assert_eq!(read_file(&link).unwrap(), "// linked module\n"); } #[wasm_bindgen_test] fn test_raw_module() { let link = wasm_bindgen::link_to!(raw_module = "./not-found.js"); assert!(read_file(&link).is_err()); } #[wasm_bindgen_test] fn test_inline_js() { // Test two invocations to ensure that snippet indices from different // Program structs are offset correctly. let link1 = wasm_bindgen::link_to!(inline_js = "// inline js 1\n"); let link2 = wasm_bindgen::link_to!(inline_js = "// inline js 2\n"); assert_eq!(read_file(&link1).unwrap(), "// inline js 1\n"); assert_eq!(read_file(&link2).unwrap(), "// inline js 2\n"); } wasm-bindgen-0.2.87/tests/wasm/linked_module.js000064400000000000000000000000211046102023000175500ustar 00000000000000// linked module wasm-bindgen-0.2.87/tests/wasm/main.rs000064400000000000000000000023051046102023000157000ustar 00000000000000#![cfg(target_arch = "wasm32")] #![allow(renamed_and_removed_lints)] // clippy::drop_ref will be renamed to drop_ref #![allow(clippy::drop_ref, clippy::drop_non_drop)] extern crate js_sys; extern crate wasm_bindgen; extern crate wasm_bindgen_test; extern crate wasm_bindgen_test_crate_a; extern crate wasm_bindgen_test_crate_b; #[cfg(feature = "serde-serialize")] #[macro_use] extern crate serde_derive; use wasm_bindgen::prelude::*; pub mod api; pub mod arg_names; pub mod bigint; pub mod char; pub mod classes; pub mod closures; pub mod comments; pub mod duplicate_deps; pub mod duplicates; pub mod enums; #[path = "final.rs"] pub mod final_; pub mod futures; pub mod getters_and_setters; pub mod import_class; pub mod imports; pub mod intrinsics; pub mod js_keywords; pub mod js_objects; pub mod jscast; pub mod link_to; pub mod math; pub mod no_shims; pub mod node; pub mod option; pub mod optional_primitives; pub mod owned; pub mod result; pub mod result_jserror; pub mod rethrow; pub mod simple; pub mod slice; pub mod structural; pub mod truthy_falsy; pub mod usize; pub mod validate_prt; pub mod variadic; pub mod vendor_prefix; // should not be executed #[wasm_bindgen(start)] fn start() { panic!(); } wasm-bindgen-0.2.87/tests/wasm/math.js000064400000000000000000000027201046102023000156760ustar 00000000000000const wasm = require('wasm-bindgen-test.js'); const assert = require('assert'); exports.js_auto_bind_math = () => { wasm.math(1.0, 2.0); }; exports.roundtrip = x => x; exports.test_js_roundtrip = () => { assert.strictEqual(wasm.rust_roundtrip_i8(0), 0); assert.strictEqual(wasm.rust_roundtrip_i8(0x80), -128); assert.strictEqual(wasm.rust_roundtrip_i8(0x7f), 127); assert.strictEqual(wasm.rust_roundtrip_i16(0), 0); assert.strictEqual(wasm.rust_roundtrip_i16(0x8000), -32768); assert.strictEqual(wasm.rust_roundtrip_i16(0x7fff), 32767); assert.strictEqual(wasm.rust_roundtrip_i32(0), 0); assert.strictEqual(wasm.rust_roundtrip_i32(0x80000000), -2147483648); assert.strictEqual(wasm.rust_roundtrip_i32(0x7fffffff), 2147483647); assert.strictEqual(wasm.rust_roundtrip_u8(0), 0); assert.strictEqual(wasm.rust_roundtrip_u8(0x80), 128); assert.strictEqual(wasm.rust_roundtrip_u8(0x7f), 127); assert.strictEqual(wasm.rust_roundtrip_u8(0xff), 255); assert.strictEqual(wasm.rust_roundtrip_u16(0), 0); assert.strictEqual(wasm.rust_roundtrip_u16(0x8000), 32768); assert.strictEqual(wasm.rust_roundtrip_u16(0x7fff), 32767); assert.strictEqual(wasm.rust_roundtrip_u16(0xffff), 65535); assert.strictEqual(wasm.rust_roundtrip_u32(0), 0); assert.strictEqual(wasm.rust_roundtrip_u32(0x80000000), 2147483648); assert.strictEqual(wasm.rust_roundtrip_u32(0x7fffffff), 2147483647); assert.strictEqual(wasm.rust_roundtrip_u32(0xffffffff), 4294967295); }; wasm-bindgen-0.2.87/tests/wasm/math.rs000064400000000000000000000073761046102023000157220ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/math.js")] extern "C" { fn js_auto_bind_math(); // There's an identity function called `roundtrip` in the module and we bind // that one function with multiple different signatures here. Note that the // return value is always `f64` to faithfully capture what was sent to JS // (what we're interested in) because all JS numbers fit in `f64` anyway. // This is testing what happens when we pass numbers to JS and what it sees. #[wasm_bindgen(assert_no_shim, js_name = roundtrip)] fn roundtrip_i8(a: i8) -> f64; #[wasm_bindgen(assert_no_shim, js_name = roundtrip)] fn roundtrip_i16(a: i16) -> f64; #[wasm_bindgen(assert_no_shim, js_name = roundtrip)] fn roundtrip_i32(a: i32) -> f64; #[wasm_bindgen(assert_no_shim, js_name = roundtrip)] fn roundtrip_u8(a: u8) -> f64; #[wasm_bindgen(assert_no_shim, js_name = roundtrip)] fn roundtrip_u16(a: u16) -> f64; #[wasm_bindgen(js_name = roundtrip)] fn roundtrip_u32(a: u32) -> f64; fn test_js_roundtrip(); } #[wasm_bindgen] pub fn math(a: f32, b: f64) -> f64 { b.acos() + b.asin() + b.atan() + b.atan2(b) + b.cbrt() + b.cosh() + b.exp_m1() + b.ln_1p() + b.sinh() + b.tan() + b.tanh() + b.hypot(b) + b.cos() + b.exp() + b.exp2() + b.mul_add(b, b) + b.ln() + b.log(b) + b.log10() + b.log2() + b.powi(8) + b.powf(b) + b.round() + b.sin() + b.abs() + b.signum() + b.floor() + b.ceil() + b.trunc() + b.sqrt() + (b % (a as f64)) + ((a.cos() + a.exp() + a.exp2() + a.mul_add(a, a) + a.ln() + a.log(a) + a.log10() + a.log2() + a.powi(8) + a.powf(a) + a.round() + a.sin() + a.abs() + a.signum() + a.floor() + a.ceil() + a.trunc() + a.sqrt() + (a % (b as f32))) as f64) + (b + 2.0f64.powf(a as f64)) } #[wasm_bindgen_test] fn auto_bind_math() { js_auto_bind_math(); } macro_rules! t_roundtrip { ($f:ident($e:expr)) => { assert_eq!($f($e), $e as f64) }; } #[wasm_bindgen_test] fn limits_correct() { t_roundtrip!(roundtrip_i8(i8::min_value())); t_roundtrip!(roundtrip_i8(0)); t_roundtrip!(roundtrip_i8(i8::max_value())); t_roundtrip!(roundtrip_i16(i16::min_value())); t_roundtrip!(roundtrip_i16(0)); t_roundtrip!(roundtrip_i16(i16::max_value())); t_roundtrip!(roundtrip_i32(i32::min_value())); t_roundtrip!(roundtrip_i32(0)); t_roundtrip!(roundtrip_i32(i32::max_value())); t_roundtrip!(roundtrip_u8(u8::min_value())); t_roundtrip!(roundtrip_u8(0)); t_roundtrip!(roundtrip_u8(u8::max_value())); t_roundtrip!(roundtrip_u16(u16::min_value())); t_roundtrip!(roundtrip_u16(0)); t_roundtrip!(roundtrip_u16(u16::max_value())); t_roundtrip!(roundtrip_u32(u32::min_value())); t_roundtrip!(roundtrip_u32(0)); t_roundtrip!(roundtrip_u32(u32::max_value())); test_js_roundtrip(); #[wasm_bindgen] pub fn rust_roundtrip_i8(a: i8) -> i8 { a } #[wasm_bindgen] pub fn rust_roundtrip_i16(a: i16) -> i16 { a } #[wasm_bindgen] pub fn rust_roundtrip_i32(a: i32) -> i32 { a } #[wasm_bindgen] pub fn rust_roundtrip_u8(a: u8) -> u8 { a } #[wasm_bindgen] pub fn rust_roundtrip_u16(a: u16) -> u16 { a } #[wasm_bindgen] pub fn rust_roundtrip_u32(a: u32) -> u32 { a } } wasm-bindgen-0.2.87/tests/wasm/no_shims.rs000064400000000000000000000110031046102023000165660ustar 00000000000000//! A collection of tests to exercise imports where we don't need to generate a //! JS shim to convert arguments/returns even when Web IDL bindings is not //! implemented. use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(inline_js = " function assert_eq(a, b) { if (a !== b) { throw new Error(`assert_eq failed: ${a} != ${b}`); } } module.exports.trivial = function () {}; module.exports.incoming_bool = function () { return true; }; module.exports.incoming_u8 = function () { return 255; }; module.exports.incoming_i8 = function () { return -127; }; module.exports.incoming_u16 = function () { return 65535; }; module.exports.incoming_i16 = function () { return 32767; }; module.exports.incoming_u32 = function () { return 4294967295; }; module.exports.incoming_i32 = function () { return 0; }; module.exports.incoming_f32 = function () { return 1.5; }; module.exports.incoming_f64 = function () { return Math.PI; }; module.exports.outgoing_u8 = function (k) { assert_eq(k, 255); }; module.exports.outgoing_i8 = function (i) { assert_eq(i, -127); }; module.exports.outgoing_u16 = function (l) { assert_eq(l, 65535); }; module.exports.outgoing_i16 = function (j) { assert_eq(j, 32767); }; module.exports.outgoing_i32 = function (x) { assert_eq(x, 0); }; module.exports.outgoing_f32 = function (y) { assert_eq(y, 1.5); }; module.exports.outgoing_f64 = function (pi) { assert_eq(pi, Math.PI); }; module.exports.many = function (x, y, pi) { assert_eq(x, 0); assert_eq(y, 1.5); assert_eq(pi, Math.PI); return 42; }; module.exports.works_when_externref_support_is_enabled = function (v) { assert_eq(v, 'hello'); return v; }; module.exports.MyNamespace = {}; module.exports.MyNamespace.incoming_namespaced = function () { return 13.37; }; module.exports.MyNamespace.outgoing_namespaced = function (w) { assert_eq(13.37, w); }; ")] extern "C" { #[wasm_bindgen(assert_no_shim)] fn trivial(); #[wasm_bindgen(assert_no_shim)] fn incoming_bool() -> bool; #[wasm_bindgen(assert_no_shim)] fn incoming_u8() -> u8; #[wasm_bindgen(assert_no_shim)] fn incoming_i8() -> i8; #[wasm_bindgen(assert_no_shim)] fn incoming_u16() -> u16; #[wasm_bindgen(assert_no_shim)] fn incoming_i16() -> i16; #[wasm_bindgen(assert_no_shim)] fn incoming_u32() -> u32; #[wasm_bindgen(assert_no_shim)] fn incoming_i32() -> i32; #[wasm_bindgen(assert_no_shim)] fn incoming_f32() -> f32; #[wasm_bindgen(assert_no_shim)] fn incoming_f64() -> f64; #[wasm_bindgen(assert_no_shim)] fn outgoing_u8(k: u8); #[wasm_bindgen(assert_no_shim)] fn outgoing_i8(i: i8); #[wasm_bindgen(assert_no_shim)] fn outgoing_u16(l: u16); #[wasm_bindgen(assert_no_shim)] fn outgoing_i16(j: i16); #[wasm_bindgen(assert_no_shim)] fn outgoing_i32(x: i32); #[wasm_bindgen(assert_no_shim)] fn outgoing_f32(y: f32); #[wasm_bindgen(assert_no_shim)] fn outgoing_f64(z: f64); #[wasm_bindgen(assert_no_shim)] fn many(x: i32, y: f32, z: f64) -> i32; #[wasm_bindgen(assert_no_shim, js_namespace = MyNamespace)] fn incoming_namespaced() -> f64; #[wasm_bindgen(assert_no_shim, js_namespace = MyNamespace)] fn outgoing_namespaced(x: f64); // Note that this should only skip the JS shim if we have externref support // enabled. // // #[wasm_bindgen(assert_no_shim)] fn works_when_externref_support_is_enabled(v: JsValue) -> JsValue; } #[wasm_bindgen_test] fn no_shims() { trivial(); let k = incoming_u8(); assert_eq!(k, 255); outgoing_u8(k); let l = incoming_u16(); assert_eq!(l, 65535); outgoing_u16(l); let m = incoming_u32(); assert_eq!(m, 4294967295); let i = incoming_i8(); assert_eq!(i, -127); outgoing_i8(i); let j = incoming_i16(); assert_eq!(j, 32767); outgoing_i16(j); let x = incoming_i32(); assert_eq!(x, 0); outgoing_i32(x); let y = incoming_f32(); assert_eq!(y, 1.5); outgoing_f32(y); let pi = incoming_f64(); assert_eq!(pi, std::f64::consts::PI); outgoing_f64(pi); let z = many(x, y, pi); assert_eq!(z, 42); let w = incoming_namespaced(); assert_eq!(w, 13.37); outgoing_namespaced(w); let b = incoming_bool(); assert!(b); let v = JsValue::from("hello"); let vv = works_when_externref_support_is_enabled(v.clone()); assert_eq!(v, vv); } wasm-bindgen-0.2.87/tests/wasm/node.js000064400000000000000000000017131046102023000156730ustar 00000000000000const assert = require('assert'); const wasm = require('wasm-bindgen-test'); var called = false; exports.hit = function() { called = true; }; exports.FOO = 1.0; exports.test_works = function() { assert.strictEqual(called, true); var r = wasm.Foo.new(); assert.strictEqual(r.add(0), 0); assert.strictEqual(r.add(1), 1); assert.strictEqual(r.add(2), 3); r.free(); var r2 = wasm.Foo.with_contents(10); assert.strictEqual(r2.add(0), 10); assert.strictEqual(r2.add(1), 11); assert.strictEqual(r2.add(2), 13); r2.free(); assert.strictEqual(wasm.Color.Green, 0); assert.strictEqual(wasm.Color.Yellow, 1); assert.strictEqual(wasm.Color.Red, 2); assert.strictEqual(wasm.Color[0], 'Green'); assert.strictEqual(wasm.Color[1], 'Yellow'); assert.strictEqual(wasm.Color[2], 'Red'); assert.strictEqual(Object.keys(wasm.Color).length, 6); assert.strictEqual(wasm.cycle(wasm.Color.Green), wasm.Color.Yellow); wasm.node_math(1.0, 2.0); }; wasm-bindgen-0.2.87/tests/wasm/node.rs000064400000000000000000000037661046102023000157150ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/node.js")] extern "C" { fn test_works(); static FOO: JsValue; fn hit(); } #[wasm_bindgen_test] fn works() { hit(); assert_eq!(FOO.as_f64(), Some(1.0)); test_works(); } #[wasm_bindgen] pub struct Foo { contents: u32, } #[wasm_bindgen] impl Foo { pub fn new() -> Foo { Foo::with_contents(0) } pub fn with_contents(a: u32) -> Foo { Foo { contents: a } } pub fn add(&mut self, amt: u32) -> u32 { self.contents += amt; self.contents } } #[wasm_bindgen] pub enum Color { Green, Yellow, Red, } #[wasm_bindgen] pub fn cycle(color: Color) -> Color { match color { Color::Green => Color::Yellow, Color::Yellow => Color::Red, Color::Red => Color::Green, } } #[wasm_bindgen] pub fn node_math(a: f32, b: f64) -> f64 { b.acos() + b.asin() + b.atan() + b.atan2(b) + b.cbrt() + b.cosh() + b.exp_m1() + b.ln_1p() + b.sinh() + b.tan() + b.tanh() + b.hypot(b) + b.cos() + b.exp() + b.exp2() + b.mul_add(b, b) + b.ln() + b.log(b) + b.log10() + b.log2() + b.powi(8) + b.powf(b) + b.round() + b.sin() + b.abs() + b.signum() + b.floor() + b.ceil() + b.trunc() + b.sqrt() + (b % (a as f64)) + ((a.cos() + a.exp() + a.exp2() + a.mul_add(a, a) + a.ln() + a.log(a) + a.log10() + a.log2() + a.powi(8) + a.powf(a) + a.round() + a.sin() + a.abs() + a.signum() + a.floor() + a.ceil() + a.trunc() + a.sqrt() + (a % (b as f32))) as f64) + (b + 2.0f64.powf(a as f64)) } wasm-bindgen-0.2.87/tests/wasm/option.js000064400000000000000000000014511046102023000162550ustar 00000000000000const wasm = require('wasm-bindgen-test.js'); const assert = require('assert'); class MyType { } exports.MyType = MyType; exports.take_none_byval = x => { assert.strictEqual(x, undefined); }; exports.take_some_byval = x => { assert.ok(x !== null && x !== undefined); assert.ok(x instanceof MyType); }; exports.return_undef_byval = () => undefined; exports.return_null_byval = () => null; exports.return_some_byval = () => new MyType(); exports.test_option_values = () => { wasm.rust_take_none_byval(null); wasm.rust_take_none_byval(undefined); wasm.rust_take_some_byval(new MyType()); assert.strictEqual(wasm.rust_return_none_byval(), undefined); const x = wasm.rust_return_some_byval(); assert.ok(x !== null && x !== undefined); assert.ok(x instanceof MyType); }; wasm-bindgen-0.2.87/tests/wasm/option.rs000064400000000000000000000026351046102023000162720ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/option.js")] extern "C" { pub type MyType; #[wasm_bindgen(constructor)] fn new() -> MyType; fn take_none_byval(t: Option); fn take_some_byval(t: Option); fn return_undef_byval() -> Option; fn return_null_byval() -> Option; fn return_some_byval() -> Option; fn test_option_values(); #[wasm_bindgen(js_name = take_none_byval)] fn take_none_byref(t: Option<&MyType>); #[wasm_bindgen(js_name = take_some_byval)] fn take_some_byref(t: Option<&MyType>); } #[wasm_bindgen_test] fn import_by_value() { take_none_byval(None); take_some_byval(Some(MyType::new())); assert!(return_null_byval().is_none()); assert!(return_undef_byval().is_none()); assert!(return_some_byval().is_some()); } #[wasm_bindgen_test] fn export_by_value() { test_option_values(); } #[wasm_bindgen] pub fn rust_take_none_byval(t: Option) { assert!(t.is_none()); } #[wasm_bindgen] pub fn rust_take_some_byval(t: Option) { assert!(t.is_some()); } #[wasm_bindgen] pub fn rust_return_none_byval() -> Option { None } #[wasm_bindgen] pub fn rust_return_some_byval() -> Option { Some(MyType::new()) } #[wasm_bindgen_test] fn import_by_ref() { take_none_byref(None); take_some_byref(Some(&MyType::new())); } wasm-bindgen-0.2.87/tests/wasm/optional_primitives.js000064400000000000000000000150551046102023000210520ustar 00000000000000const wasm = require('wasm-bindgen-test.js'); const assert = require('assert'); exports.optional_i32_js_identity = a => a; exports.optional_u32_js_identity = a => a; exports.optional_isize_js_identity = a => a; exports.optional_usize_js_identity = a => a; exports.optional_f32_js_identity = a => a; exports.optional_f64_js_identity = a => a; exports.optional_i8_js_identity = a => a; exports.optional_u8_js_identity = a => a; exports.optional_i16_js_identity = a => a; exports.optional_u16_js_identity = a => a; exports.optional_i64_js_identity = a => a; exports.optional_u64_js_identity = a => a; exports.optional_bool_js_identity = a => a; exports.optional_char_js_identity = a => a; exports.js_works = () => { assert.strictEqual(wasm.optional_i32_identity(wasm.optional_i32_none()), undefined); assert.strictEqual(wasm.optional_i32_identity(wasm.optional_i32_zero()), 0); assert.strictEqual(wasm.optional_i32_identity(wasm.optional_i32_one()), 1); assert.strictEqual(wasm.optional_i32_identity(wasm.optional_i32_neg_one()), -1); assert.strictEqual(wasm.optional_i32_identity(wasm.optional_i32_min()), -2147483648); assert.strictEqual(wasm.optional_i32_identity(wasm.optional_i32_max()), 2147483647); assert.strictEqual(wasm.optional_u32_identity(wasm.optional_u32_none()), undefined); assert.strictEqual(wasm.optional_u32_identity(wasm.optional_u32_zero()), 0); assert.strictEqual(wasm.optional_u32_identity(wasm.optional_u32_one()), 1); assert.strictEqual(wasm.optional_u32_identity(wasm.optional_u32_min()), 0); assert.strictEqual(wasm.optional_u32_identity(wasm.optional_u32_max()), 4294967295); assert.strictEqual(wasm.optional_isize_identity(wasm.optional_isize_none()), undefined); assert.strictEqual(wasm.optional_isize_identity(wasm.optional_isize_zero()), 0); assert.strictEqual(wasm.optional_isize_identity(wasm.optional_isize_one()), 1); assert.strictEqual(wasm.optional_isize_identity(wasm.optional_isize_neg_one()), -1); assert.strictEqual(wasm.optional_isize_identity(wasm.optional_isize_min()), -2147483648); assert.strictEqual(wasm.optional_isize_identity(wasm.optional_isize_max()), 2147483647); assert.strictEqual(wasm.optional_usize_identity(wasm.optional_usize_none()), undefined); assert.strictEqual(wasm.optional_usize_identity(wasm.optional_usize_zero()), 0); assert.strictEqual(wasm.optional_usize_identity(wasm.optional_usize_one()), 1); assert.strictEqual(wasm.optional_usize_identity(wasm.optional_usize_min()), 0); assert.strictEqual(wasm.optional_usize_identity(wasm.optional_usize_max()), 4294967295); assert.strictEqual(wasm.optional_f32_identity(wasm.optional_f32_none()), undefined); assert.strictEqual(wasm.optional_f32_identity(wasm.optional_f32_zero()), 0); assert.strictEqual(wasm.optional_f32_identity(wasm.optional_f32_one()), 1); assert.strictEqual(wasm.optional_f32_identity(wasm.optional_f32_neg_one()), -1); assert.strictEqual(wasm.optional_f64_identity(wasm.optional_f64_none()), undefined); assert.strictEqual(wasm.optional_f64_identity(wasm.optional_f64_zero()), 0); assert.strictEqual(wasm.optional_f64_identity(wasm.optional_f64_one()), 1); assert.strictEqual(wasm.optional_f64_identity(wasm.optional_f64_neg_one()), -1); assert.strictEqual(wasm.optional_i8_identity(wasm.optional_i8_none()), undefined); assert.strictEqual(wasm.optional_i8_identity(wasm.optional_i8_zero()), 0); assert.strictEqual(wasm.optional_i8_identity(wasm.optional_i8_one()), 1); assert.strictEqual(wasm.optional_i8_identity(wasm.optional_i8_neg_one()), -1); assert.strictEqual(wasm.optional_i8_identity(wasm.optional_i8_min()), -128); assert.strictEqual(wasm.optional_i8_identity(wasm.optional_i8_max()), 127); assert.strictEqual(wasm.optional_u8_identity(wasm.optional_u8_none()), undefined); assert.strictEqual(wasm.optional_u8_identity(wasm.optional_u8_zero()), 0); assert.strictEqual(wasm.optional_u8_identity(wasm.optional_u8_one()), 1); assert.strictEqual(wasm.optional_u8_identity(wasm.optional_u8_min()), 0); assert.strictEqual(wasm.optional_u8_identity(wasm.optional_u8_max()), 255); assert.strictEqual(wasm.optional_i16_identity(wasm.optional_i16_none()), undefined); assert.strictEqual(wasm.optional_i16_identity(wasm.optional_i16_zero()), 0); assert.strictEqual(wasm.optional_i16_identity(wasm.optional_i16_one()), 1); assert.strictEqual(wasm.optional_i16_identity(wasm.optional_i16_neg_one()), -1); assert.strictEqual(wasm.optional_i16_identity(wasm.optional_i16_min()), -32768); assert.strictEqual(wasm.optional_i16_identity(wasm.optional_i16_max()), 32767); assert.strictEqual(wasm.optional_u16_identity(wasm.optional_u16_none()), undefined); assert.strictEqual(wasm.optional_u16_identity(wasm.optional_u16_zero()), 0); assert.strictEqual(wasm.optional_u16_identity(wasm.optional_u16_one()), 1); assert.strictEqual(wasm.optional_u16_identity(wasm.optional_u16_min()), 0); assert.strictEqual(wasm.optional_u16_identity(wasm.optional_u16_max()), 65535); assert.strictEqual(wasm.optional_i64_identity(wasm.optional_i64_none()), undefined); assert.strictEqual(wasm.optional_i64_identity(wasm.optional_i64_zero()), BigInt('0')); assert.strictEqual(wasm.optional_i64_identity(wasm.optional_i64_one()), BigInt('1')); assert.strictEqual(wasm.optional_i64_identity(wasm.optional_i64_neg_one()), BigInt('-1')); assert.strictEqual(wasm.optional_i64_identity(wasm.optional_i64_min()), BigInt('-9223372036854775808')); assert.strictEqual(wasm.optional_i64_identity(wasm.optional_i64_max()), BigInt('9223372036854775807')); assert.strictEqual(wasm.optional_u64_identity(wasm.optional_u64_none()), undefined); assert.strictEqual(wasm.optional_u64_identity(wasm.optional_u64_zero()), BigInt('0')); assert.strictEqual(wasm.optional_u64_identity(wasm.optional_u64_one()), BigInt('1')); assert.strictEqual(wasm.optional_u64_identity(wasm.optional_u64_min()), BigInt('0')); assert.strictEqual(wasm.optional_u64_identity(wasm.optional_u64_max()), BigInt('18446744073709551615')); assert.strictEqual(wasm.optional_bool_identity(wasm.optional_bool_none()), undefined); assert.strictEqual(wasm.optional_bool_identity(wasm.optional_bool_false()), false); assert.strictEqual(wasm.optional_bool_identity(wasm.optional_bool_true()), true); assert.strictEqual(wasm.optional_char_identity(wasm.optional_char_none()), undefined); assert.strictEqual(wasm.optional_char_identity(wasm.optional_char_letter()), 'a'); assert.strictEqual(wasm.optional_char_identity(wasm.optional_char_face()), '😀'); }; wasm-bindgen-0.2.87/tests/wasm/optional_primitives.rs000064400000000000000000000200271046102023000210550ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/optional_primitives.js")] extern "C" { fn optional_i32_js_identity(a: Option) -> Option; fn optional_u32_js_identity(a: Option) -> Option; fn optional_isize_js_identity(a: Option) -> Option; fn optional_usize_js_identity(a: Option) -> Option; fn optional_f32_js_identity(a: Option) -> Option; fn optional_f64_js_identity(a: Option) -> Option; fn optional_i8_js_identity(a: Option) -> Option; fn optional_u8_js_identity(a: Option) -> Option; fn optional_i16_js_identity(a: Option) -> Option; fn optional_u16_js_identity(a: Option) -> Option; fn optional_i64_js_identity(a: Option) -> Option; fn optional_u64_js_identity(a: Option) -> Option; fn optional_bool_js_identity(a: Option) -> Option; fn optional_char_js_identity(a: Option) -> Option; fn js_works(); } #[wasm_bindgen] pub fn optional_i32_none() -> Option { None } #[wasm_bindgen] pub fn optional_i32_zero() -> Option { Some(0) } #[wasm_bindgen] pub fn optional_i32_one() -> Option { Some(1) } #[wasm_bindgen] pub fn optional_i32_neg_one() -> Option { Some(-1) } #[wasm_bindgen] pub fn optional_i32_min() -> Option { Some(i32::min_value()) } #[wasm_bindgen] pub fn optional_i32_max() -> Option { Some(i32::max_value()) } #[wasm_bindgen] pub fn optional_i32_identity(a: Option) -> Option { optional_i32_js_identity(a) } #[wasm_bindgen] pub fn optional_u32_none() -> Option { None } #[wasm_bindgen] pub fn optional_u32_zero() -> Option { Some(0) } #[wasm_bindgen] pub fn optional_u32_one() -> Option { Some(1) } #[wasm_bindgen] pub fn optional_u32_min() -> Option { Some(u32::min_value()) } #[wasm_bindgen] pub fn optional_u32_max() -> Option { Some(u32::max_value()) } #[wasm_bindgen] pub fn optional_u32_identity(a: Option) -> Option { optional_u32_js_identity(a) } #[wasm_bindgen] pub fn optional_isize_none() -> Option { None } #[wasm_bindgen] pub fn optional_isize_zero() -> Option { Some(0) } #[wasm_bindgen] pub fn optional_isize_one() -> Option { Some(1) } #[wasm_bindgen] pub fn optional_isize_neg_one() -> Option { Some(-1) } #[wasm_bindgen] pub fn optional_isize_min() -> Option { Some(isize::min_value()) } #[wasm_bindgen] pub fn optional_isize_max() -> Option { Some(isize::max_value()) } #[wasm_bindgen] pub fn optional_isize_identity(a: Option) -> Option { optional_isize_js_identity(a) } #[wasm_bindgen] pub fn optional_usize_none() -> Option { None } #[wasm_bindgen] pub fn optional_usize_zero() -> Option { Some(0) } #[wasm_bindgen] pub fn optional_usize_one() -> Option { Some(1) } #[wasm_bindgen] pub fn optional_usize_min() -> Option { Some(usize::min_value()) } #[wasm_bindgen] pub fn optional_usize_max() -> Option { Some(usize::max_value()) } #[wasm_bindgen] pub fn optional_usize_identity(a: Option) -> Option { optional_usize_js_identity(a) } #[wasm_bindgen] pub fn optional_f32_none() -> Option { None } #[wasm_bindgen] pub fn optional_f32_zero() -> Option { Some(0f32) } #[wasm_bindgen] pub fn optional_f32_one() -> Option { Some(1f32) } #[wasm_bindgen] pub fn optional_f32_neg_one() -> Option { Some(-1f32) } #[wasm_bindgen] pub fn optional_f32_identity(a: Option) -> Option { optional_f32_js_identity(a) } #[wasm_bindgen] pub fn optional_f64_none() -> Option { None } #[wasm_bindgen] pub fn optional_f64_zero() -> Option { Some(0f64) } #[wasm_bindgen] pub fn optional_f64_one() -> Option { Some(1f64) } #[wasm_bindgen] pub fn optional_f64_neg_one() -> Option { Some(-1f64) } #[wasm_bindgen] pub fn optional_f64_identity(a: Option) -> Option { optional_f64_js_identity(a) } #[wasm_bindgen] pub fn optional_i8_none() -> Option { None } #[wasm_bindgen] pub fn optional_i8_zero() -> Option { Some(0) } #[wasm_bindgen] pub fn optional_i8_one() -> Option { Some(1) } #[wasm_bindgen] pub fn optional_i8_neg_one() -> Option { Some(-1) } #[wasm_bindgen] pub fn optional_i8_min() -> Option { Some(i8::min_value()) } #[wasm_bindgen] pub fn optional_i8_max() -> Option { Some(i8::max_value()) } #[wasm_bindgen] pub fn optional_i8_identity(a: Option) -> Option { optional_i8_js_identity(a) } #[wasm_bindgen] pub fn optional_u8_none() -> Option { None } #[wasm_bindgen] pub fn optional_u8_zero() -> Option { Some(0) } #[wasm_bindgen] pub fn optional_u8_one() -> Option { Some(1) } #[wasm_bindgen] pub fn optional_u8_min() -> Option { Some(u8::min_value()) } #[wasm_bindgen] pub fn optional_u8_max() -> Option { Some(u8::max_value()) } #[wasm_bindgen] pub fn optional_u8_identity(a: Option) -> Option { optional_u8_js_identity(a) } #[wasm_bindgen] pub fn optional_i16_none() -> Option { None } #[wasm_bindgen] pub fn optional_i16_zero() -> Option { Some(0) } #[wasm_bindgen] pub fn optional_i16_one() -> Option { Some(1) } #[wasm_bindgen] pub fn optional_i16_neg_one() -> Option { Some(-1) } #[wasm_bindgen] pub fn optional_i16_min() -> Option { Some(i16::min_value()) } #[wasm_bindgen] pub fn optional_i16_max() -> Option { Some(i16::max_value()) } #[wasm_bindgen] pub fn optional_i16_identity(a: Option) -> Option { optional_i16_js_identity(a) } #[wasm_bindgen] pub fn optional_u16_none() -> Option { None } #[wasm_bindgen] pub fn optional_u16_zero() -> Option { Some(0) } #[wasm_bindgen] pub fn optional_u16_one() -> Option { Some(1) } #[wasm_bindgen] pub fn optional_u16_min() -> Option { Some(u16::min_value()) } #[wasm_bindgen] pub fn optional_u16_max() -> Option { Some(u16::max_value()) } #[wasm_bindgen] pub fn optional_u16_identity(a: Option) -> Option { optional_u16_js_identity(a) } #[wasm_bindgen] pub fn optional_i64_none() -> Option { None } #[wasm_bindgen] pub fn optional_i64_zero() -> Option { Some(0) } #[wasm_bindgen] pub fn optional_i64_one() -> Option { Some(1) } #[wasm_bindgen] pub fn optional_i64_neg_one() -> Option { Some(-1) } #[wasm_bindgen] pub fn optional_i64_min() -> Option { Some(i64::min_value()) } #[wasm_bindgen] pub fn optional_i64_max() -> Option { Some(i64::max_value()) } #[wasm_bindgen] pub fn optional_i64_identity(a: Option) -> Option { optional_i64_js_identity(a) } #[wasm_bindgen] pub fn optional_u64_none() -> Option { None } #[wasm_bindgen] pub fn optional_u64_zero() -> Option { Some(0) } #[wasm_bindgen] pub fn optional_u64_one() -> Option { Some(1) } #[wasm_bindgen] pub fn optional_u64_min() -> Option { Some(u64::min_value()) } #[wasm_bindgen] pub fn optional_u64_max() -> Option { Some(u64::max_value()) } #[wasm_bindgen] pub fn optional_u64_identity(a: Option) -> Option { optional_u64_js_identity(a) } #[wasm_bindgen] pub fn optional_bool_none() -> Option { None } #[wasm_bindgen] pub fn optional_bool_false() -> Option { Some(false) } #[wasm_bindgen] pub fn optional_bool_true() -> Option { Some(true) } #[wasm_bindgen] pub fn optional_bool_identity(a: Option) -> Option { optional_bool_js_identity(a) } #[wasm_bindgen] pub fn optional_char_none() -> Option { None } #[wasm_bindgen] pub fn optional_char_letter() -> Option { Some('a') } #[wasm_bindgen] pub fn optional_char_face() -> Option { Some('😀') } #[wasm_bindgen] pub fn optional_char_identity(a: Option) -> Option { optional_char_js_identity(a) } #[wasm_bindgen_test] fn works() { js_works(); } wasm-bindgen-0.2.87/tests/wasm/owned.js000064400000000000000000000004661046102023000160660ustar 00000000000000const wasm = require("wasm-bindgen-test.js"); exports.create_garbage = async function () { for (let i = 0; i < 100; i++) { new wasm.OwnedValue(1).add(new wasm.OwnedValue(2)).n(); } if ("gc" in global) { global.gc(); } else { console.warn("test runner doesn't expose GC function"); } }; wasm-bindgen-0.2.87/tests/wasm/owned.rs000064400000000000000000000012141046102023000160660ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen] pub struct OwnedValue { pub n: f64, } #[wasm_bindgen] impl OwnedValue { #[wasm_bindgen(constructor)] pub fn new(n: f64) -> Self { Self { n } } #[allow(clippy::should_implement_trait)] // traits unsupported by wasm_bindgen pub fn add(self, other: OwnedValue) -> Self { Self { n: self.n + other.n, } } pub fn n(self) -> f64 { self.n } } #[wasm_bindgen(module = "tests/wasm/owned.js")] extern "C" { fn create_garbage(); } #[wasm_bindgen_test] fn test_create_garbage() { create_garbage() } wasm-bindgen-0.2.87/tests/wasm/result.js000064400000000000000000000060151046102023000162640ustar 00000000000000const wasm = require('wasm-bindgen-test.js'); const assert = require('assert'); exports.error_new = function(message) { return new Error(message) } exports.call_ok = function() { assert.doesNotThrow(() => { let five = wasm.return_my_ok(); assert.strictEqual(five, 5); }) } exports.call_err = function() { assert.throws(() => wasm.return_my_err(), { message: "MyError::Variant" }); } function check_inflight(struct) { assert.strictEqual(struct.is_inflight(), false); } exports.all_struct_methods = function() { let struct; assert.throws(() => wasm.Struct.new_err(), { message: "MyError::Variant" }); assert.doesNotThrow(() => { struct = wasm.Struct.new(); }); check_inflight(struct); assert.doesNotThrow(() => { let five = struct.return_ok(); assert.strictEqual(five, 5); }); check_inflight(struct); assert.throws(() => struct.return_err(), { message: "MyError::Variant" }); check_inflight(struct); } exports.call_return_string = function() { assert.doesNotThrow(() => { let ok = wasm.return_string(); assert.strictEqual(ok, "string here"); }) } exports.call_jsvalue_ok = function() { assert.doesNotThrow(() => { let five = wasm.return_jsvalue_ok(); assert.strictEqual(five, 5); }) } exports.call_jsvalue_err = function() { try { wasm.return_jsvalue_err(); assert.fail("should have thrown"); } catch (e) { assert.strictEqual(e, -1); } } exports.call_string_ok = function() { assert.doesNotThrow(() => { let ok = wasm.return_string_ok(); assert.strictEqual(ok, "Ok"); }) } exports.call_string_err = function() { // the behaviour of Result is so finicky that it's not obvious // how to to reproduce reliably but also pass the test suite. assert.throws(() => e = wasm.return_string_err(), e => { // one thing we can do (uncomment to test) // is to throw an error in here. // throw new Error("should not cause a SIGBUS in Node") return e === "Er"; }); } exports.call_enum_ok = function() { assert.doesNotThrow(() => { let ok = wasm.return_enum_ok(); assert.strictEqual(ok, 2); }) } exports.call_enum_err = function() { assert.throws(() => { wasm.return_enum_err(); }, { message: "MyError::Variant" }) } exports.call_unit = function() { assert.doesNotThrow(() => { wasm.return_unit_ok(); }); assert.throws(() => { wasm.return_unit_err(); }, { message: "MyError::Variant" }); } exports.call_option = function() { assert.doesNotThrow(() => { let o = wasm.return_option_ok_some(); assert.strictEqual(o, 10.0); }); assert.doesNotThrow(() => { let o = wasm.return_option_ok_none(); assert.strictEqual(o, undefined); }); assert.throws(() => { wasm.return_option_err(); }, { message: "MyError::Variant" }); } wasm-bindgen-0.2.87/tests/wasm/result.rs000064400000000000000000000102601046102023000162710ustar 00000000000000use std::fmt; use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[derive(Clone, Debug)] pub enum MyError { Variant, InflightShouldBeFalse, } // shouldn't technically need this, surely impl std::error::Error for MyError {} impl fmt::Display for MyError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "MyError::{:?}", self) } } #[wasm_bindgen(module = "tests/wasm/result.js")] extern "C" { fn error_new(message: &str) -> JsValue; } impl From for JsValue { fn from(e: MyError) -> Self { error_new(&format!("{}", e)) } } macro_rules! call_test { ($test_fn:ident, $js_fn:ident) => { #[wasm_bindgen_test] fn $test_fn() { #[wasm_bindgen(module = "tests/wasm/result.js")] extern "C" { fn $js_fn(); } $js_fn(); } }; } #[wasm_bindgen] pub fn return_my_err() -> Result { let e = Err(MyError::Variant)?; Ok(e) } call_test!(test_err, call_err); #[wasm_bindgen] pub fn return_my_ok() -> Result { Ok(5) } call_test!(test_ok, call_ok); #[wasm_bindgen] pub struct Struct { inflight: bool, } call_test!(test_struct, all_struct_methods); struct ResetOnDrop<'a> { flag: &'a mut bool, } impl<'a> Drop for ResetOnDrop<'a> { fn drop(&mut self) { *self.flag = false; } } impl<'a> ResetOnDrop<'a> { fn new(flag: &'a mut bool) -> Result { if *flag { return Err(MyError::InflightShouldBeFalse); } Ok(Self { flag }) } } #[wasm_bindgen] impl Struct { #[wasm_bindgen] pub fn new() -> Result { Ok(Struct { inflight: false }) } #[wasm_bindgen] pub fn new_err() -> Result { Err(MyError::Variant) } #[wasm_bindgen] pub fn return_ok(&mut self) -> Result { let _guard = ResetOnDrop::new(&mut self.inflight)?; Ok(5) } #[wasm_bindgen] pub fn return_err(&mut self) -> Result { let guard = ResetOnDrop::new(&mut self.inflight)?; let err = Err(MyError::Variant); let nope = err?; // we are checking both for the flag being reset (from js, via is_inflight) // and for the running of drop code drop(guard); Ok(nope) } #[wasm_bindgen] pub fn is_inflight(&self) -> bool { self.inflight } } // check some more Ok types #[wasm_bindgen] pub fn return_string() -> Result { Ok("string here".into()) } call_test!(test_return_string, call_return_string); // now we check that jsvalue works, as it did before #[wasm_bindgen] pub fn return_jsvalue_ok() -> Result { Ok(5) } call_test!(test_jsvalue_ok, call_jsvalue_ok); #[wasm_bindgen] pub fn return_jsvalue_err() -> Result { Err(JsValue::from(-1i32)) } call_test!(test_jsvalue_err, call_jsvalue_err); // test strings (they have a deferred free, in a finally block: tricky) #[wasm_bindgen] pub fn return_string_ok() -> Result { Ok("Ok".into()) } call_test!(test_string_ok, call_string_ok); #[wasm_bindgen] pub fn return_string_err() -> Result { Err("Er".into()) } call_test!(test_string_err, call_string_err); // test enums #[wasm_bindgen] pub enum MyEnum { One = 1, Two = 2, } #[wasm_bindgen] pub fn return_enum_ok() -> Result { Ok(MyEnum::Two) } call_test!(test_enum_ok, call_enum_ok); #[wasm_bindgen] pub fn return_enum_err() -> Result { Err(MyError::Variant) } call_test!(test_enum_err, call_enum_err); // T = Unit #[wasm_bindgen] pub fn return_unit_ok() -> Result<(), MyError> { Ok(()) } #[wasm_bindgen] pub fn return_unit_err() -> Result<(), MyError> { Err(MyError::Variant) } call_test!(test_unit, call_unit); // T = Option #[wasm_bindgen] pub fn return_option_ok_some() -> Result, MyError> { Ok(Some(10f64)) } #[wasm_bindgen] pub fn return_option_ok_none() -> Result, MyError> { Ok(None) } #[wasm_bindgen] pub fn return_option_err() -> Result, MyError> { Err(MyError::Variant) } call_test!(test_option, call_option); wasm-bindgen-0.2.87/tests/wasm/result_jserror.js000064400000000000000000000024551046102023000200360ustar 00000000000000const wasm = require('wasm-bindgen-test.js'); const assert = require('assert'); exports.call_ok = function() { assert.doesNotThrow(() => { let five = wasm.return_ok(); assert.strictEqual(five, 5); }) } exports.call_err = function() { assert.throws(() => wasm.return_err(), { message: "MyError::Variant" }); } exports.call_make_an_error = function() { assert.doesNotThrow(() => { let e = wasm.make_an_error() assert.strictEqual(e.message, "un-thrown error"); }); } function check_inflight(struct) { assert.strictEqual(struct.is_inflight(), false); } exports.all_struct_methods = function() { let struct; assert.throws(() => wasm.MyStruct.new_err(), { message: "MyError::Variant" }); assert.doesNotThrow(() => { struct = wasm.MyStruct.new(); }); check_inflight(struct); assert.doesNotThrow(() => { let five = struct.return_ok(); assert.strictEqual(five, 5); }); check_inflight(struct); assert.throws(() => struct.return_err(), { message: "MyError::Variant" }); check_inflight(struct); } exports.call_return_string = function() { assert.doesNotThrow(() => { let ok = wasm.jserror_return_string(); assert.strictEqual(ok, "string here"); }) } wasm-bindgen-0.2.87/tests/wasm/result_jserror.rs000064400000000000000000000051111046102023000200360ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen::JsError; use wasm_bindgen_test::*; use std::fmt; #[derive(Clone, Debug)] enum MyError { Variant, InflightShouldBeFalse, } // shouldn't technically need this, surely impl std::error::Error for MyError {} impl fmt::Display for MyError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "MyError::{:?}", self) } } macro_rules! call_test { ($test_fn:ident, $js_fn:ident) => { #[wasm_bindgen_test] fn $test_fn() { #[wasm_bindgen(module = "tests/wasm/result_jserror.js")] extern "C" { fn $js_fn(); } $js_fn(); } }; } #[wasm_bindgen] pub fn return_err() -> Result { let e = Err(MyError::Variant)?; Ok(e) } call_test!(test_err, call_err); #[wasm_bindgen] pub fn return_ok() -> Result { Ok(5) } call_test!(test_ok, call_ok); #[wasm_bindgen] pub fn make_an_error() -> JsError { JsError::new("un-thrown error") } call_test!(test_make_an_error, call_make_an_error); #[wasm_bindgen] pub struct MyStruct { inflight: bool, } call_test!(test_struct, all_struct_methods); struct ResetOnDrop<'a> { flag: &'a mut bool, } impl<'a> Drop for ResetOnDrop<'a> { fn drop(&mut self) { *self.flag = false; } } impl<'a> ResetOnDrop<'a> { fn new(flag: &'a mut bool) -> Result { if *flag { return Err(MyError::InflightShouldBeFalse); } Ok(Self { flag }) } } #[wasm_bindgen] impl MyStruct { #[wasm_bindgen] pub fn new() -> Result { Ok(MyStruct { inflight: false }) } #[wasm_bindgen] pub fn new_err() -> Result { Err(MyError::Variant.into()) } #[wasm_bindgen] pub fn return_ok(&mut self) -> Result { let _guard = ResetOnDrop::new(&mut self.inflight)?; Ok(5) } #[wasm_bindgen] pub fn return_err(&mut self) -> Result { let guard = ResetOnDrop::new(&mut self.inflight)?; let err = Err(MyError::Variant); let nope = err?; // we are checking both for the flag being reset (from js, via is_inflight) // and for the running of drop code drop(guard); Ok(nope) } #[wasm_bindgen] pub fn is_inflight(&self) -> bool { self.inflight } } // check some more Ok types #[wasm_bindgen] pub fn jserror_return_string() -> Result { Ok("string here".into()) } call_test!(test_return_string, call_return_string); wasm-bindgen-0.2.87/tests/wasm/rethrow.js000064400000000000000000000003771046102023000164450ustar 00000000000000const wasm = require('wasm-bindgen-test.js'); const assert = require('assert'); exports.call_throw_one = function() { try { wasm.throw_one(); } catch (e) { assert.strictEqual(e, 1); } }; exports.call_ok = function() { wasm.nothrow(); }; wasm-bindgen-0.2.87/tests/wasm/rethrow.rs000064400000000000000000000006651046102023000164550ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/rethrow.js")] extern "C" { fn call_throw_one(); fn call_ok(); } #[wasm_bindgen_test] fn err_works() { call_throw_one(); } #[wasm_bindgen] pub fn throw_one() -> Result { Err(1.into()) } #[wasm_bindgen_test] fn ok_works() { call_ok(); } #[wasm_bindgen] pub fn nothrow() -> Result { Ok(1) } wasm-bindgen-0.2.87/tests/wasm/should_panic.rs000064400000000000000000000004661046102023000174320ustar 00000000000000#[wasm_bindgen_test] #[should_panic] fn should_panic() { panic!() } #[wasm_bindgen_test] #[should_panic = "error message"] fn should_panic_string() { panic!("error message") } #[wasm_bindgen_test] #[should_panic(expected = "error message")] fn should_panic_expected() { panic!("error message") } wasm-bindgen-0.2.87/tests/wasm/simple.js000064400000000000000000000057031046102023000162420ustar 00000000000000const assert = require('assert'); const wasm = require('wasm-bindgen-test'); exports.test_add = function() { assert.strictEqual(wasm.simple_add(1, 2), 3); assert.strictEqual(wasm.simple_add(2, 3), 5); assert.strictEqual(wasm.simple_add3(2), 5); assert.strictEqual(wasm.simple_get2(true), 2); assert.strictEqual(wasm.simple_return_and_take_bool(true, false), false); }; exports.test_string_arguments = function() { wasm.simple_assert_foo("foo"); wasm.simple_assert_foo_and_bar("foo2", "bar"); }; exports.test_return_a_string = function() { assert.strictEqual(wasm.simple_clone("foo"), "foo"); assert.strictEqual(wasm.simple_clone("another"), "another"); assert.strictEqual(wasm.simple_concat("a", "b", 3), "a b 3"); assert.strictEqual(wasm.simple_concat("c", "d", -2), "c d -2"); }; exports.test_wrong_types = function() { // this test only works when `--debug` is passed to `wasm-bindgen` (or the // equivalent thereof) if (require('process').env.WASM_BINDGEN_NO_DEBUG) return; assert.throws(() => wasm.simple_int('a'), /expected a number argument/); assert.throws(() => wasm.simple_str(3), /expected a string argument/); }; exports.test_other_exports_still_available = function() { require('wasm-bindgen-test').__wasm.foo(3); }; exports.test_jsvalue_typeof = function() { assert.ok(wasm.is_object({})); assert.ok(!wasm.is_object(42)); assert.ok(wasm.is_function(function() {})); assert.ok(!wasm.is_function(42)); assert.ok(wasm.is_string("2b or !2b")); assert.ok(!wasm.is_string(42)); }; exports.optional_str_none = function(x) { assert.strictEqual(x, undefined); }; exports.optional_str_some = function(x) { assert.strictEqual(x, 'x'); }; exports.optional_slice_none = function(x) { assert.strictEqual(x, undefined); }; exports.optional_slice_some = function(x) { assert.strictEqual(x.length, 3); assert.strictEqual(x[0], 1); assert.strictEqual(x[1], 2); assert.strictEqual(x[2], 3); } exports.optional_string_none = function(x) { assert.strictEqual(x, undefined); }; exports.optional_string_some = function(x) { assert.strictEqual(x, 'abcd'); }; exports.optional_string_some_empty = function(x) { assert.strictEqual(x, ''); }; exports.return_string_none = function() {}; exports.return_string_some = function() { return 'foo'; }; exports.test_rust_optional = function() { wasm.take_optional_str_none(); wasm.take_optional_str_none(null); wasm.take_optional_str_none(undefined); wasm.take_optional_str_some('hello'); assert.strictEqual(wasm.return_optional_str_none(), undefined); assert.strictEqual(wasm.return_optional_str_some(), 'world'); }; exports.RenamedInRust = class {}; exports.new_renamed = () => new exports.RenamedInRust; exports.import_export_same_name = () => {}; exports.test_string_roundtrip = () => { const test = s => { assert.strictEqual(wasm.do_string_roundtrip(s), s); }; test(''); test('a'); test('💖'); test('a longer string'); test('a longer 💖 string'); }; wasm-bindgen-0.2.87/tests/wasm/simple.rs000064400000000000000000000116451046102023000162540ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen::{intern, unintern}; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/simple.js")] extern "C" { fn test_add(); fn test_string_arguments(); fn test_return_a_string(); fn test_wrong_types(); fn test_other_exports_still_available(); fn test_jsvalue_typeof(); fn optional_str_none(a: Option<&str>); fn optional_str_some(a: Option<&str>); fn optional_slice_none(a: Option<&[u8]>); fn optional_slice_some(a: Option<&[u8]>); fn optional_string_none(a: Option); fn optional_string_some(a: Option); fn optional_string_some_empty(a: Option); fn return_string_none() -> Option; fn return_string_some() -> Option; fn test_rust_optional(); #[wasm_bindgen(js_name = import_export_same_name)] fn js_import_export_same_name(); #[wasm_bindgen(js_name = RenamedInRust)] type Renamed; fn new_renamed() -> Renamed; fn test_string_roundtrip(); } #[wasm_bindgen_test] fn add() { test_add(); } #[wasm_bindgen] pub fn simple_add(a: u32, b: u32) -> u32 { a + b } #[wasm_bindgen] pub fn simple_add3(a: u32) -> u32 { a + 3 } #[wasm_bindgen] pub fn simple_get2(_b: bool) -> u32 { 2 } #[wasm_bindgen] pub fn simple_return_and_take_bool(a: bool, b: bool) -> bool { a && b } #[wasm_bindgen] pub unsafe fn simple_raw_pointers_work(a: *mut u32, b: *const u8) -> *const u32 { (*a) = (*b) as u32; a } #[wasm_bindgen_test] fn string_arguments() { test_string_arguments(); } #[wasm_bindgen] pub fn simple_assert_foo_and_bar(a: &str, b: &str) { assert_eq!(a, "foo2"); assert_eq!(b, "bar"); } #[wasm_bindgen] pub fn simple_assert_foo(a: &str) { assert_eq!(a, "foo"); } #[wasm_bindgen_test] fn return_a_string() { test_return_a_string(); } #[wasm_bindgen] pub fn simple_clone(a: &str) -> String { a.to_string() } #[wasm_bindgen] pub fn simple_concat(a: &str, b: &str, c: i8) -> String { format!("{} {} {}", a, b, c) } #[wasm_bindgen_test] fn wrong_types() { test_wrong_types(); } #[wasm_bindgen] pub fn simple_int(_a: u32) {} #[wasm_bindgen] pub fn simple_str(_a: &str) {} #[wasm_bindgen_test] fn other_exports() { test_other_exports_still_available(); } #[no_mangle] pub extern "C" fn foo(_a: u32) {} #[wasm_bindgen_test] fn jsvalue_typeof() { test_jsvalue_typeof(); } #[wasm_bindgen] pub fn is_object(val: &JsValue) -> bool { val.is_object() } #[wasm_bindgen] pub fn is_function(val: &JsValue) -> bool { val.is_function() } #[wasm_bindgen] pub fn is_string(val: &JsValue) -> bool { val.is_string() } #[wasm_bindgen] extern "C" { #[derive(Clone)] type Array; #[wasm_bindgen(constructor)] fn new() -> Array; #[wasm_bindgen(method, catch)] fn standardized_method_this_js_runtime_doesnt_implement_yet( this: &Array, ) -> Result<(), JsValue>; } #[wasm_bindgen_test] fn binding_to_unimplemented_apis_doesnt_break_everything() { let array = Array::new(); let res = array.standardized_method_this_js_runtime_doesnt_implement_yet(); assert!(res.is_err()); } #[wasm_bindgen_test] fn optional_slices() { optional_str_none(None); optional_str_some(Some("x")); optional_str_some(Some(intern("x"))); unintern("x"); optional_str_some(Some("x")); optional_slice_none(None); optional_slice_some(Some(&[1, 2, 3])); optional_string_none(None); optional_string_some_empty(Some(String::new())); optional_string_some(Some("abcd".to_string())); assert_eq!(return_string_none(), None); assert_eq!(return_string_some(), Some("foo".to_string())); test_rust_optional(); } #[wasm_bindgen] pub fn take_optional_str_none(x: Option) { assert!(x.is_none()) } #[wasm_bindgen] pub fn take_optional_str_some(x: Option) { assert_eq!(x, Some(String::from("hello"))); } #[wasm_bindgen] pub fn return_optional_str_none() -> Option { None } #[wasm_bindgen] pub fn return_optional_str_some() -> Option { Some("world".to_string()) } #[wasm_bindgen_test] fn renaming_imports_and_instanceof() { let null = JsValue::NULL; assert!(!null.is_instance_of::()); let arr: JsValue = Array::new().into(); assert!(!arr.is_instance_of::()); let renamed: JsValue = new_renamed().into(); assert!(renamed.is_instance_of::()); } #[wasm_bindgen] pub fn import_export_same_name() { js_import_export_same_name(); } #[wasm_bindgen_test] fn string_roundtrip() { test_string_roundtrip(); } #[wasm_bindgen] pub fn do_string_roundtrip(s: String) -> String { s } #[wasm_bindgen_test] #[allow(clippy::redundant_clone)] // clone to increase heap live count fn externref_heap_live_count() { let x = wasm_bindgen::externref_heap_live_count(); let y = JsValue::null().clone(); assert!(wasm_bindgen::externref_heap_live_count() > x); drop(y); assert_eq!(x, wasm_bindgen::externref_heap_live_count()); } wasm-bindgen-0.2.87/tests/wasm/slice.js000064400000000000000000000136271046102023000160540ustar 00000000000000const wasm = require('wasm-bindgen-test.js'); const assert = require('assert'); exports.js_export = () => { const i8 = new Int8Array(2); i8[0] = 1; i8[1] = 2; assert.deepStrictEqual(wasm.export_i8(i8), i8); const u8 = new Uint8Array(2); u8[0] = 1; u8[1] = 2; assert.deepStrictEqual(wasm.export_u8(u8), u8); const i16 = new Int16Array(2); i16[0] = 1; i16[1] = 2; assert.deepStrictEqual(wasm.export_i16(i16), i16); const u16 = new Uint16Array(2); u16[0] = 1; u16[1] = 2; assert.deepStrictEqual(wasm.export_u16(u16), u16); const i32 = new Int32Array(2); i32[0] = 1; i32[1] = 2; assert.deepStrictEqual(wasm.export_i32(i32), i32); assert.deepStrictEqual(wasm.export_isize(i32), i32); const u32 = new Uint32Array(2); u32[0] = 1; u32[1] = 2; assert.deepStrictEqual(wasm.export_u32(u32), u32); assert.deepStrictEqual(wasm.export_usize(u32), u32); const f32 = new Float32Array(2); f32[0] = 1; f32[1] = 2; assert.deepStrictEqual(wasm.export_f32(f32), f32); const f64 = new Float64Array(2); f64[0] = 1; f64[1] = 2; assert.deepStrictEqual(wasm.export_f64(f64), f64); }; const test_import = (a, b, c) => { assert.strictEqual(a.length, 2); assert.strictEqual(a[0], 1); assert.strictEqual(a[1], 2); assert.strictEqual(b.length, 2); assert.strictEqual(b[0], 1); assert.strictEqual(b[1], 2); assert.strictEqual(c, undefined); return a; }; exports.import_js_i8 = test_import; exports.import_js_u8 = test_import; exports.import_js_i16 = test_import; exports.import_js_u16 = test_import; exports.import_js_i32 = test_import; exports.import_js_isize = test_import; exports.import_js_u32 = test_import; exports.import_js_usize = test_import; exports.import_js_f32 = test_import; exports.import_js_f64 = test_import; exports.js_import = () => { const i8 = new Int8Array(2); i8[0] = 1; i8[1] = 2; assert.deepStrictEqual(wasm.import_rust_i8(i8), i8); const u8 = new Uint8Array(2); u8[0] = 1; u8[1] = 2; assert.deepStrictEqual(wasm.import_rust_u8(u8), u8); const i16 = new Int16Array(2); i16[0] = 1; i16[1] = 2; assert.deepStrictEqual(wasm.import_rust_i16(i16), i16); const u16 = new Uint16Array(2); u16[0] = 1; u16[1] = 2; assert.deepStrictEqual(wasm.import_rust_u16(u16), u16); const i32 = new Int32Array(2); i32[0] = 1; i32[1] = 2; assert.deepStrictEqual(wasm.import_rust_i32(i32), i32); assert.deepStrictEqual(wasm.import_rust_isize(i32), i32); const u32 = new Uint32Array(2); u32[0] = 1; u32[1] = 2; assert.deepStrictEqual(wasm.import_rust_u32(u32), u32); assert.deepStrictEqual(wasm.import_rust_usize(u32), u32); const f32 = new Float32Array(2); f32[0] = 1; f32[1] = 2; assert.deepStrictEqual(wasm.import_rust_f32(f32), f32); const f64 = new Float64Array(2); f64[0] = 1; f64[1] = 2; assert.deepStrictEqual(wasm.import_rust_f64(f64), f64); }; exports.js_pass_array = () => { wasm.pass_array_rust_i8([1, 2]); wasm.pass_array_rust_u8([1, 2]); wasm.pass_array_rust_i16([1, 2]); wasm.pass_array_rust_u16([1, 2]); wasm.pass_array_rust_i32([1, 2]); wasm.pass_array_rust_u32([1, 2]); wasm.pass_array_rust_isize([1, 2]); wasm.pass_array_rust_usize([1, 2]); wasm.pass_array_rust_f32([1, 2]); wasm.pass_array_rust_f64([1, 2]); }; const import_mut_foo = (a, b, c) => { assert.strictEqual(a.length, 3); assert.strictEqual(a[0], 1); assert.strictEqual(a[1], 2); a[0] = 4; a[1] = 5; assert.strictEqual(b.length, 3); assert.strictEqual(b[0], 4); assert.strictEqual(b[1], 5); assert.strictEqual(b[2], 6); b[0] = 8; b[1] = 7; assert.strictEqual(c, undefined); }; exports.import_mut_js_i8 = import_mut_foo; exports.import_mut_js_u8 = import_mut_foo; exports.import_mut_js_i16 = import_mut_foo; exports.import_mut_js_u16 = import_mut_foo; exports.import_mut_js_i32 = import_mut_foo; exports.import_mut_js_u32 = import_mut_foo; exports.import_mut_js_isize = import_mut_foo; exports.import_mut_js_usize = import_mut_foo; exports.import_mut_js_f32 = import_mut_foo; exports.import_mut_js_f64 = import_mut_foo; const export_mut_run = (a, rust) => { assert.strictEqual(a.length, 3); a[0] = 1; a[1] = 2; a[2] = 3; console.log(a); rust(a); console.log(a); assert.strictEqual(a.length, 3); assert.strictEqual(a[0], 4); assert.strictEqual(a[1], 5); assert.strictEqual(a[2], 3); }; exports.js_export_mut = () => { export_mut_run(new Int8Array(3), wasm.export_mut_i8); export_mut_run(new Uint8Array(3), wasm.export_mut_u8); export_mut_run(new Int16Array(3), wasm.export_mut_i16); export_mut_run(new Uint16Array(3), wasm.export_mut_u16); export_mut_run(new Int32Array(3), wasm.export_mut_i32); export_mut_run(new Uint32Array(3), wasm.export_mut_u32); export_mut_run(new Int32Array(3), wasm.export_mut_isize); export_mut_run(new Uint32Array(3), wasm.export_mut_usize); export_mut_run(new Float32Array(3), wasm.export_mut_f32); export_mut_run(new Float64Array(3), wasm.export_mut_f64); }; exports.js_return_vec = () => { const app = wasm.return_vec_web_main(); for (let i = 0; i < 10; i++) { app.tick(); const bad = wasm.return_vec_broken_vec(); console.log('Received from rust:', i, bad); assert.strictEqual(bad[0], 1); assert.strictEqual(bad[1], 2); assert.strictEqual(bad[2], 3); assert.strictEqual(bad[3], 4); assert.strictEqual(bad[4], 5); assert.strictEqual(bad[5], 6); assert.strictEqual(bad[6], 7); assert.strictEqual(bad[7], 8); assert.strictEqual(bad[8], 9); } }; exports.js_clamped = (a, offset) => { assert.ok(a instanceof Uint8ClampedArray); assert.equal(a.length, 3); assert.equal(a[0], offset + 0); assert.equal(a[1], offset + 1); assert.equal(a[2], offset + 2); }; wasm-bindgen-0.2.87/tests/wasm/slice.rs000064400000000000000000000132771046102023000160650ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen::Clamped; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/slice.js")] extern "C" { fn js_export(); fn js_import(); fn js_pass_array(); fn js_export_mut(); fn js_return_vec(); fn js_clamped(val: Clamped<&[u8]>, offset: u8); #[wasm_bindgen(js_name = js_clamped)] fn js_clamped2(val: Clamped>, offset: u8); #[wasm_bindgen(js_name = js_clamped)] fn js_clamped3(val: Clamped<&mut [u8]>, offset: u8); } macro_rules! export_macro { ($(($i:ident, $n:ident))*) => ($( #[wasm_bindgen] pub fn $n(a: &[$i]) -> Vec<$i> { assert_eq!(a.len(), 2); assert_eq!(a[0], 1 as $i); assert_eq!(a[1], 2 as $i); a.to_vec() } )*) } export_macro! { (i8, export_i8) (u8, export_u8) (i16, export_i16) (u16, export_u16) (i32, export_i32) (u32, export_u32) (isize, export_isize) (usize, export_usize) (f32, export_f32) (f64, export_f64) } #[wasm_bindgen_test] fn export() { js_export(); } macro_rules! import_macro { ($(($rust:ident, $js:ident, $i:ident))*) => ($( #[wasm_bindgen(module = "tests/wasm/slice.js")] extern "C" { fn $js(a: &[$i], b: Option<&[$i]>, c: Option<&[$i]>) -> Vec<$i>; } #[wasm_bindgen] pub fn $rust(a: &[$i]) -> Vec<$i> { assert_eq!(a.len(), 2); assert_eq!(a[0], 1 as $i); assert_eq!(a[1], 2 as $i); $js(a, Some(a), None) } )*) } import_macro! { (import_rust_i8, import_js_i8, i8) (import_rust_u8, import_js_u8, u8) (import_rust_i16, import_js_i16, i16) (import_rust_u16, import_js_u16, u16) (import_rust_i32, import_js_i32, i32) (import_rust_u32, import_js_u32, u32) (import_rust_isize, import_js_isize, isize) (import_rust_usize, import_js_usize, usize) (import_rust_f32, import_js_f32, f32) (import_rust_f64, import_js_f64, f64) } #[wasm_bindgen_test] fn import() { js_import(); } macro_rules! pass_array_marco { ($(($rust:ident, $i:ident))*) => ($( #[wasm_bindgen] pub fn $rust(a: &[$i]) { assert_eq!(a.len(), 2); assert_eq!(a[0], 1 as $i); assert_eq!(a[1], 2 as $i); } )*) } pass_array_marco! { (pass_array_rust_i8, i8) (pass_array_rust_u8, u8) (pass_array_rust_i16, i16) (pass_array_rust_u16, u16) (pass_array_rust_i32, i32) (pass_array_rust_u32, u32) (pass_array_rust_isize, isize) (pass_array_rust_usize, usize) (pass_array_rust_f32, f32) (pass_array_rust_f64, f64) } #[wasm_bindgen_test] fn pass_array() { js_pass_array(); } macro_rules! import_mut_macro { ($(($rust:ident, $js:ident, $i:ident))*) => ( $( #[wasm_bindgen(module = "tests/wasm/slice.js")] extern "C" { fn $js(a: &mut [$i], b: Option<&mut [$i]>, c: Option<&mut [$i]>); } fn $rust() { let mut buf1 = [ 1 as $i, 2 as $i, 3 as $i, ]; let mut buf2 = [ 4 as $i, 5 as $i, 6 as $i, ]; $js(&mut buf1, Some(&mut buf2), None); assert_eq!(buf1[0], 4 as $i); assert_eq!(buf1[1], 5 as $i); assert_eq!(buf1[2], 3 as $i); assert_eq!(buf2[0], 8 as $i); assert_eq!(buf2[1], 7 as $i); assert_eq!(buf2[2], 6 as $i); } )* #[wasm_bindgen_test] fn import_mut() { $($rust();)* } ) } import_mut_macro! { (import_mut_rust_i8, import_mut_js_i8, i8) (import_mut_rust_u8, import_mut_js_u8, u8) (import_mut_rust_i16, import_mut_js_i16, i16) (import_mut_rust_u16, import_mut_js_u16, u16) (import_mut_rust_i32, import_mut_js_i32, i32) (import_mut_rust_u32, import_mut_js_u32, u32) (import_mut_rust_f32, import_mut_js_f32, f32) (import_mut_rust_f64, import_mut_js_f64, f64) } macro_rules! export_mut_macro { ($(($i:ident, $n:ident))*) => ($( #[wasm_bindgen] pub fn $n(a: &mut [$i]) { assert_eq!(a.len(), 3); assert_eq!(a[0], 1 as $i); assert_eq!(a[1], 2 as $i); assert_eq!(a[2], 3 as $i); a[0] = 4 as $i; a[1] = 5 as $i; } )*) } export_mut_macro! { (i8, export_mut_i8) (u8, export_mut_u8) (i16, export_mut_i16) (u16, export_mut_u16) (i32, export_mut_i32) (u32, export_mut_u32) (isize, export_mut_isize) (usize, export_mut_usize) (f32, export_mut_f32) (f64, export_mut_f64) } #[wasm_bindgen_test] fn export_mut() { js_export_mut(); } #[wasm_bindgen] pub fn return_vec_broken_vec() -> Vec { vec![1, 2, 3, 4, 5, 6, 7, 8, 9] } #[wasm_bindgen] pub fn return_vec_web_main() -> ReturnVecApplication { ReturnVecApplication::new() } #[wasm_bindgen] pub struct ReturnVecApplication { thing: Vec, } #[wasm_bindgen] impl ReturnVecApplication { #[allow(clippy::vec_init_then_push)] pub fn new() -> ReturnVecApplication { let mut thing = vec![]; thing.push(0); thing.push(0); thing.push(0); thing.push(0); thing.push(0); ReturnVecApplication { thing } } pub fn tick(&mut self) { self.thing = self.thing.clone(); } } #[wasm_bindgen_test] fn return_vec() { js_return_vec(); } #[wasm_bindgen_test] fn take_clamped() { js_clamped(Clamped(&[1, 2, 3]), 1); js_clamped2(Clamped(vec![4, 5, 6]), 4); js_clamped3(Clamped(&mut [7, 8, 9]), 7); } wasm-bindgen-0.2.87/tests/wasm/structural.js000064400000000000000000000004121046102023000171510ustar 00000000000000const wasm = require('wasm-bindgen-test.js'); const assert = require('assert'); exports.js_works = () => { let called = false; wasm.run({ bar() { called = true; }, baz: 1, }); assert.strictEqual(called, true); }; wasm-bindgen-0.2.87/tests/wasm/structural.rs000064400000000000000000000012171046102023000171650ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/structural.js")] extern "C" { fn js_works(); } #[wasm_bindgen] extern "C" { pub type StructuralFoo; #[wasm_bindgen(method, structural)] fn bar(this: &StructuralFoo); #[wasm_bindgen(method, getter, structural)] fn baz(this: &StructuralFoo) -> u32; #[wasm_bindgen(method, setter, structural)] fn set_baz(this: &StructuralFoo, val: u32); } #[wasm_bindgen] pub fn run(a: &StructuralFoo) { a.bar(); assert_eq!(a.baz(), 1); a.set_baz(2); assert_eq!(a.baz(), 2); } #[wasm_bindgen_test] fn works() { js_works(); } wasm-bindgen-0.2.87/tests/wasm/truthy_falsy.rs000064400000000000000000000016171046102023000175160ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen_test] fn test_is_truthy() { assert!(!JsValue::from(0).is_truthy()); assert!(!JsValue::from("".to_string()).is_truthy()); assert!(!JsValue::from(false).is_truthy()); assert!(!JsValue::NULL.is_truthy()); assert!(!JsValue::UNDEFINED.is_truthy()); assert!(JsValue::from(10).is_truthy()); assert!(JsValue::from("null".to_string()).is_truthy()); assert!(JsValue::from(true).is_truthy()); } #[wasm_bindgen_test] fn test_is_falsy() { assert!(JsValue::from(0).is_falsy()); assert!(JsValue::from("".to_string()).is_falsy()); assert!(JsValue::from(false).is_falsy()); assert!(JsValue::NULL.is_falsy()); assert!(JsValue::UNDEFINED.is_falsy()); assert!(!JsValue::from(10).is_falsy()); assert!(!JsValue::from("null".to_string()).is_falsy()); assert!(!JsValue::from(true).is_falsy()); } wasm-bindgen-0.2.87/tests/wasm/usize.js000064400000000000000000000032451046102023000161070ustar 00000000000000const wasm = require('wasm-bindgen-test.js'); const assert = require('assert'); exports.isize_js_identity = a => a; exports.usize_js_identity = a => a; exports.js_works = async () => { assert.strictEqual(wasm.usize_zero(), 0); assert.strictEqual(wasm.usize_one(), 1); assert.strictEqual(wasm.isize_neg_one(), -1); assert.strictEqual(wasm.isize_i32_min(), -2147483648); assert.strictEqual(wasm.isize_min(), -2147483648); assert.strictEqual(wasm.usize_u32_max(), 4294967295); assert.strictEqual(wasm.usize_max(), 4294967295); assert.strictEqual(wasm.isize_rust_identity(0), 0); assert.strictEqual(wasm.isize_rust_identity(1), 1); assert.strictEqual(wasm.isize_rust_identity(-1), -1); assert.strictEqual(wasm.usize_rust_identity(0), 0); assert.strictEqual(wasm.usize_rust_identity(1), 1); const usize_max = 4294967295; const isize_min = -2147483648; assert.strictEqual(wasm.isize_rust_identity(isize_min), isize_min); assert.strictEqual(wasm.usize_rust_identity(usize_max), usize_max); assert.deepStrictEqual(wasm.usize_slice([]), new Uint32Array()); assert.deepStrictEqual(wasm.isize_slice([]), new Int32Array()); const arr1 = new Uint32Array([1, 2]); assert.deepStrictEqual(wasm.usize_slice([1, 2]), arr1); const arr2 = new Int32Array([1, 2]); assert.deepStrictEqual(wasm.isize_slice([1, 2]), arr2); assert.deepStrictEqual(wasm.isize_slice([isize_min]), new Int32Array([isize_min])); assert.deepStrictEqual(wasm.usize_slice([usize_max]), new Uint32Array([usize_max])); assert.deepStrictEqual(await wasm.async_usize_one(), 1); assert.deepStrictEqual(await wasm.async_isize_neg_one(), -1); }; wasm-bindgen-0.2.87/tests/wasm/usize.rs000064400000000000000000000023421046102023000161140ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/usize.js")] extern "C" { fn isize_js_identity(a: isize) -> isize; fn usize_js_identity(a: usize) -> usize; fn js_works(); } #[wasm_bindgen] pub fn usize_zero() -> usize { 0 } #[wasm_bindgen] pub fn usize_one() -> usize { 1 } #[wasm_bindgen] pub fn isize_neg_one() -> isize { -1 } #[wasm_bindgen] pub fn isize_i32_min() -> isize { i32::min_value() as isize } #[wasm_bindgen] pub fn usize_u32_max() -> usize { u32::max_value() as usize } #[wasm_bindgen] pub fn isize_min() -> isize { isize::min_value() } #[wasm_bindgen] pub fn usize_max() -> usize { usize::max_value() } #[wasm_bindgen] pub fn isize_rust_identity(a: isize) -> isize { isize_js_identity(a) } #[wasm_bindgen] pub fn usize_rust_identity(a: usize) -> usize { usize_js_identity(a) } #[wasm_bindgen] pub fn isize_slice(a: &[isize]) -> Vec { a.to_vec() } #[wasm_bindgen] pub fn usize_slice(a: &[usize]) -> Vec { a.to_vec() } #[wasm_bindgen] pub async fn async_usize_one() -> usize { 1 } #[wasm_bindgen] pub async fn async_isize_neg_one() -> isize { -1 } #[wasm_bindgen_test] fn works() { js_works(); } wasm-bindgen-0.2.87/tests/wasm/validate_prt.js000064400000000000000000000023521046102023000174240ustar 00000000000000const wasm = require('wasm-bindgen-test.js'); const assert = require('assert'); // NB: `wasm-pack` uses the presence of checks for moved values as a way to test // whether it is correctly enabling `--debug` when configured to do so, so don't // change this expected debug output without also updating `wasm-pack`'s tests. const assertMovedPtrThrows = process.env.WASM_BINDGEN_NO_DEBUG == null ? f => assert.throws(f, /Attempt to use a moved value/) : f => assert.throws(f, /null pointer passed to rust/); const useMoved = () => { const apple = new wasm.Fruit('apple'); apple.name(); wasm.eat(apple); assertMovedPtrThrows(() => apple.name()); }; const moveMoved = () => { const pear = new wasm.Fruit('pear'); pear.name(); wasm.eat(pear); assertMovedPtrThrows(() => wasm.eat(pear)); }; const methodMoved = () => { const quince = new wasm.Fruit('quince'); quince.name(); quince.rot(); assertMovedPtrThrows(() => quince.rot()); }; exports.js_works = () => { useMoved(); moveMoved(); methodMoved(); const a = new wasm.Fruit('a'); a.prop; assertMovedPtrThrows(() => a.prop); const b = new wasm.Fruit('a'); b.prop = 3; assertMovedPtrThrows(() => { b.prop = 4; }); }; wasm-bindgen-0.2.87/tests/wasm/validate_prt.rs000064400000000000000000000012641046102023000174350ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/validate_prt.js")] extern "C" { fn js_works(); } #[wasm_bindgen] pub struct Fruit { name: String, } #[wasm_bindgen] impl Fruit { pub fn name(&self) -> String { self.name.clone() } #[wasm_bindgen(constructor)] pub fn new(name: String) -> Self { Fruit { name } } pub fn rot(self) { drop(self); } #[wasm_bindgen(getter)] pub fn prop(self) -> u32 { 0 } #[wasm_bindgen(setter)] pub fn set_prop(self, _val: u32) {} } #[wasm_bindgen] pub fn eat(_: Fruit) {} #[wasm_bindgen_test] fn works() { js_works(); } wasm-bindgen-0.2.87/tests/wasm/variadic.js000064400000000000000000000031431046102023000165270ustar 00000000000000const assert = require('assert'); // a function for testing numbers function variadic_sum(...args) { let answer = 0; for(var i=0; i u8; #[wasm_bindgen(variadic)] fn variadic_sum_u16(first: u16, second: u16, rest: &[u16]) -> u16; #[wasm_bindgen(variadic)] fn variadic_sum_u32(first: u32, second: u32, rest: &[u32]) -> u32; #[wasm_bindgen(variadic)] fn variadic_sum_u64(first: u64, second: u64, rest: &[u64]) -> u64; //#[wasm_bindgen(variadic)] //fn variadic_sum_usize(first: usize, second: usize, rest: &[usize]) -> usize; #[wasm_bindgen(variadic)] fn variadic_sum_i8(first: i8, second: i8, rest: &[i8]) -> i8; #[wasm_bindgen(variadic)] fn variadic_sum_i16(first: i16, second: i16, rest: &[i16]) -> i16; #[wasm_bindgen(variadic)] fn variadic_sum_i32(first: i32, second: i32, rest: &[i32]) -> i32; #[wasm_bindgen(variadic)] fn variadic_sum_i64(first: i64, second: i64, rest: &[i64]) -> i64; //#[wasm_bindgen(variadic)] //fn variadic_sum_isize(first: isize, second: isize, rest: &[isize]) -> isize; #[wasm_bindgen(variadic)] fn variadic_sum_f32(first: f32, second: f32, rest: &[f32]) -> f32; #[wasm_bindgen(variadic)] fn variadic_sum_f64(first: f64, second: f64, rest: &[f64]) -> f64; //#[wasm_bindgen(variadic)] //fn variadic_sum_opt(first: Option, second: Option, rest: &[Option]) -> u32; //#[wasm_bindgen(variadic)] //fn variadic_concat_str(first: &str, second: &str, rest: &[&str]) -> String; //#[wasm_bindgen(variadic)] //fn variadic_concat_string(first: String, // second: String, // rest: Vec) -> String; #[wasm_bindgen(variadic)] fn variadic_sum_rest_vec(first: u8, second: u8, rest: Vec) -> u8; //#[wasm_bindgen(variadic)] //fn variadic_compare_pairs(first: JsValue, second: JsValue, rest: &[JsValue]); //TODO imported type } // ints macro_rules! variadic_test_int { ($fn_name:ident, $extern_name:ident) => { #[wasm_bindgen_test] fn $fn_name() { assert_eq!($extern_name(1, 2, &[]), 3); assert_eq!($extern_name(1, 2, &[3]), 6); assert_eq!($extern_name(1, 2, &[3, 4]), 10); } }; } // The 64 tests throw js `Cannot mix BigInt and other types, use explicit conversions` variadic_test_int!(u8, variadic_sum_u8); variadic_test_int!(u16, variadic_sum_u16); variadic_test_int!(u32, variadic_sum_u32); //variadic_test_int!(u64, variadic_sum_u64); //variadic_test_int!(usize, variadic_sum_usize); variadic_test_int!(i8, variadic_sum_i8); variadic_test_int!(i16, variadic_sum_i16); variadic_test_int!(i32, variadic_sum_i32); //variadic_test_int!(i64, variadic_sum_i64); //variadic_test_int!(isize, variadic_sum_isize); // floats macro_rules! variadic_test_float { ($fn_name:ident, $extern_name:ident) => { #[wasm_bindgen_test] fn $fn_name() { assert_eq!($extern_name(1., 2., &[]), 3.); assert_eq!($extern_name(1., 2., &[3.]), 6.); assert_eq!($extern_name(1., 2., &[3., 4.]), 10.); } }; } variadic_test_float!(f32, variadic_sum_f32); variadic_test_float!(f64, variadic_sum_f64); // strings // `the trait `wasm_bindgen::convert::IntoWasmAbi` is not implemented for `&[&str]` /* #[wasm_bindgen_test] fn str() { assert_eq!(variadic_concat_str("a ", "test", &[]), "a test"); assert_eq!(variadic_concat_str("a", "nother ", &["test"]), "another test"); assert_eq!(variadic_concat_str("yet ", "a", &["nother ", "test"]), "yet another test"); } #[wasm_bindgen_test] fn string() { assert_eq!(variadic_concat_string("a ".into(), "test".into(), vec![]), "a test"); assert_eq!(variadic_concat_string("a".into(), "nother ".into(), vec!["test".into()]), "another test"); assert_eq!(variadic_concat_string("yet ".into(), "a".into(), vec!["nother ".into(), "test".into()]), "yet another test"); } */ // options /* #[wasm_bindgen_test] fn opt() { assert_eq!(variadic_sum_opt(Some(1), None, &[]), 1); assert_eq!(variadic_sum_opt(Some(1), None, &[Some(2)]), 3); assert_eq!(variadic_sum_opt(Some(1), None, &[None, Some(2)]), 3); } */ // vec not slice #[wasm_bindgen_test] fn rest_vec() { assert_eq!(variadic_sum_rest_vec(1, 2, vec![]), 3); assert_eq!(variadic_sum_rest_vec(1, 2, vec![3]), 6); assert_eq!(variadic_sum_rest_vec(1, 2, vec![3, 4]), 10); } // JsValue //#[wasm_bindgen_test] //fn jsvalue() { // variadic_compare_pairs_jsvalue(true, true, vec![]); // variadic_compare_pairs_jsvalue(false, false, vec![3, 3]); //} wasm-bindgen-0.2.87/tests/wasm/vendor_prefix.js000064400000000000000000000003301046102023000176120ustar 00000000000000exports.import_me = function() {}; global.webkitMySpecialApi = class { foo() { return 123; } }; global.MySpecialApi2 = class { foo() { return 124; } }; global.bMySpecialApi3 = class { foo() { return 125; } }; wasm-bindgen-0.2.87/tests/wasm/vendor_prefix.rs000064400000000000000000000024701046102023000176310ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(module = "tests/wasm/vendor_prefix.js")] extern "C" { fn import_me(x: &str); } #[wasm_bindgen] extern "C" { #[wasm_bindgen(vendor_prefix = webkit)] type MySpecialApi; #[wasm_bindgen(constructor)] fn new() -> MySpecialApi; #[wasm_bindgen(method)] fn foo(this: &MySpecialApi) -> u32; #[wasm_bindgen(vendor_prefix = webkit)] type MySpecialApi2; #[wasm_bindgen(constructor)] fn new() -> MySpecialApi2; #[wasm_bindgen(method)] fn foo(this: &MySpecialApi2) -> u32; #[wasm_bindgen(vendor_prefix = a, vendor_prefix = b)] type MySpecialApi3; #[wasm_bindgen(constructor)] fn new() -> MySpecialApi3; #[wasm_bindgen(method)] fn foo(this: &MySpecialApi3) -> u32; // This API does not exist at all; // test that Rust gets a chance to catch the error (#2437) #[wasm_bindgen(vendor_prefix = a, vendor_prefix = b)] type MyMissingApi; #[wasm_bindgen(constructor, catch)] fn new() -> Result; } #[wasm_bindgen_test] pub fn polyfill_works() { import_me("foo"); assert_eq!(MySpecialApi::new().foo(), 123); assert_eq!(MySpecialApi2::new().foo(), 124); assert_eq!(MySpecialApi3::new().foo(), 125); assert!(MyMissingApi::new().is_err()); } wasm-bindgen-0.2.87/tests/worker/main.rs000064400000000000000000000005231046102023000162420ustar 00000000000000#![cfg(target_arch = "wasm32")] extern crate js_sys; extern crate wasm_bindgen; extern crate wasm_bindgen_test; use wasm_bindgen::prelude::*; use wasm_bindgen_test::wasm_bindgen_test_configure; wasm_bindgen_test_configure!(run_in_worker); pub mod modules; // should not be executed #[wasm_bindgen(start)] fn start() { panic!(); } wasm-bindgen-0.2.87/tests/worker/modules.js000064400000000000000000000000531046102023000167540ustar 00000000000000export function get_five() { return 5; } wasm-bindgen-0.2.87/tests/worker/modules.rs000064400000000000000000000003501046102023000167640ustar 00000000000000use wasm_bindgen::prelude::*; use wasm_bindgen_test::*; #[wasm_bindgen(raw_module = "./tests/worker/modules.js")] extern "C" { fn get_five() -> u32; } #[wasm_bindgen_test] fn test_get_five() { assert_eq!(get_five(), 5); } wasm-bindgen-0.2.87/webdriver.json000064400000000000000000000001631046102023000151610ustar 00000000000000{ "moz:firefoxOptions": { "prefs": { "dom.workers.modules.enabled": true }, "args": [] } }