wasm-bindgen-0.2.104/.cargo_vcs_info.json 0000644 00000000136 00000000001 0013553 0 ustar {
"git": {
"sha1": "4ea9d98ce6448028743534ecc5584af28446fd2e"
},
"path_in_vcs": ""
} wasm-bindgen-0.2.104/Cargo.lock 0000644 00000011662 00000000001 0011534 0 ustar # This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "bumpalo"
version = "3.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
[[package]]
name = "cfg-if"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
[[package]]
name = "itoa"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "log"
version = "0.4.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
[[package]]
name = "memchr"
version = "2.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "proc-macro2"
version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustversion"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "ryu"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
name = "serde"
version = "1.0.226"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dca6411025b24b60bfa7ec1fe1f8e710ac09782dca409ee8237ba74b51295fd"
dependencies = [
"serde_core",
]
[[package]]
name = "serde_core"
version = "1.0.226"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba2ba63999edb9dac981fb34b3e5c0d111a69b0924e253ed29d83f7c99e966a4"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.226"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8db53ae22f34573731bafa1db20f04027b2d25e02d8205921b569171699cdb33"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.145"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
"serde_core",
]
[[package]]
name = "syn"
version = "2.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
[[package]]
name = "wasm-bindgen"
version = "0.2.104"
dependencies = [
"cfg-if",
"once_cell",
"paste",
"rustversion",
"serde",
"serde_derive",
"serde_json",
"wasm-bindgen-macro",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19"
dependencies = [
"bumpalo",
"log",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1"
dependencies = [
"unicode-ident",
]
wasm-bindgen-0.2.104/Cargo.toml 0000644 00000004602 00000000001 0011553 0 ustar # 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 = "2021"
rust-version = "1.57"
name = "wasm-bindgen"
version = "0.2.104"
authors = ["The wasm-bindgen Developers"]
build = "build.rs"
include = [
"/build.rs",
"/LICENSE-*",
"/src",
]
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = """
Easy support for interacting between JS and Rust.
"""
homepage = "https://wasm-bindgen.github.io/wasm-bindgen"
documentation = "https://docs.rs/wasm-bindgen"
readme = "README.md"
categories = ["wasm"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/wasm-bindgen/wasm-bindgen"
[package.metadata.docs.rs]
features = ["serde-serialize"]
[features]
default = ["std"]
enable-interning = ["std"]
gg-alloc = []
msrv = []
rustversion = []
serde-serialize = [
"serde",
"serde_json",
"std",
]
spans = []
std = []
strict-macro = ["wasm-bindgen-macro/strict-macro"]
xxx_debug_only_print_generated_code = []
[lib]
name = "wasm_bindgen"
path = "src/lib.rs"
test = false
[dependencies.cfg-if]
version = "1.0.0"
[dependencies.once_cell]
version = "1.12"
default-features = false
[dependencies.serde]
version = "1.0"
optional = true
[dependencies.serde_json]
version = "1.0"
optional = true
[dependencies.wasm-bindgen-macro]
version = "=0.2.104"
[dependencies.wasm-bindgen-shared]
version = "=0.2.104"
[dev-dependencies.once_cell]
version = "1"
[build-dependencies.rustversion-compat]
version = "1.0"
package = "rustversion"
[target.'cfg(target_arch = "wasm32")'.dev-dependencies.paste]
version = "1"
[target.'cfg(target_arch = "wasm32")'.dev-dependencies.serde_derive]
version = "1.0"
[lints.clippy]
large_enum_variant = "allow"
new_without_default = "allow"
overly_complex_bool_expr = "allow"
too_many_arguments = "allow"
type_complexity = "allow"
[lints.rust.unexpected_cfgs]
level = "warn"
priority = 0
check-cfg = [
"cfg(wasm_bindgen_unstable_test_coverage)",
"cfg(xxx_debug_only_print_generated_code)",
]
wasm-bindgen-0.2.104/Cargo.toml.orig 0000644 0000000 0000000 00000007260 10461020230 0015237 0 ustar 0000000 0000000 [package]
authors = ["The wasm-bindgen Developers"]
categories = ["wasm"]
description = """
Easy support for interacting between JS and Rust.
"""
documentation = "https://docs.rs/wasm-bindgen"
edition = "2021"
homepage = "https://wasm-bindgen.github.io/wasm-bindgen"
include = ["/build.rs", "/LICENSE-*", "/src"]
license = "MIT OR Apache-2.0"
name = "wasm-bindgen"
readme = "README.md"
repository = "https://github.com/wasm-bindgen/wasm-bindgen"
rust-version = "1.57"
version = "0.2.104"
[package.metadata.docs.rs]
features = ["serde-serialize"]
[lib]
test = false
[features]
default = ["std"]
enable-interning = ["std"]
serde-serialize = ["serde", "serde_json", "std"]
spans = []
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"]
# INTERNAL ONLY: 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"]
# Deprecated crate features
msrv = []
rustversion = []
xxx_debug_only_print_generated_code = []
[dependencies]
cfg-if = "1.0.0"
once_cell = { version = "1.12", default-features = false }
serde = { version = "1.0", optional = true }
serde_json = { version = "1.0", optional = true }
wasm-bindgen-macro = { path = "crates/macro", version = "=0.2.104" }
wasm-bindgen-shared = { path = "crates/shared", version = "=0.2.104" }
[build-dependencies]
# In older MSRVs, dependencies and crate features can't have the same name.
rustversion-compat = { package = "rustversion", version = "1.0" }
[dev-dependencies]
once_cell = "1"
wasm-bindgen-test = { path = 'crates/test' }
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
js-sys = { path = 'crates/js-sys' }
paste = "1"
serde_derive = "1.0"
wasm-bindgen-futures = { path = 'crates/futures' }
wasm-bindgen-test-crate-a = { path = 'tests/crates/a' }
wasm-bindgen-test-crate-b = { path = 'tests/crates/b' }
[lints]
workspace = true
[workspace.lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = [
'cfg(wasm_bindgen_unstable_test_coverage)',
'cfg(xxx_debug_only_print_generated_code)',
] }
[workspace.lints.clippy]
large_enum_variant = "allow"
new_without_default = "allow"
overly_complex_bool_expr = "allow"
too_many_arguments = "allow"
type_complexity = "allow"
[workspace]
exclude = ["crates/msrv/resolver", "crates/msrv/lib", "crates/msrv/cli"]
members = [
"benchmarks",
"crates/cli",
"crates/js-sys",
"crates/test",
"crates/test/sample",
"crates/typescript-tests",
"crates/web-sys",
"crates/webidl",
"crates/webidl-tests",
"examples/add",
"examples/canvas",
"examples/char",
"examples/closures",
"examples/console_log",
"examples/nodejs_and_deno",
"examples/dom",
"examples/duck-typed-interfaces",
"examples/explicit-resource-management",
"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/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]
js-sys = { path = 'crates/js-sys' }
wasm-bindgen = { path = '.' }
wasm-bindgen-futures = { path = 'crates/futures' }
web-sys = { path = 'crates/web-sys' }
wasm-bindgen-0.2.104/LICENSE-APACHE 0000644 0000000 0000000 00000025137 10461020230 0014277 0 ustar 0000000 0000000 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.104/LICENSE-MIT 0000644 0000000 0000000 00000002041 10461020230 0013774 0 ustar 0000000 0000000 Copyright (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.104/README.md 0000644 0000000 0000000 00000011232 10461020230 0013621 0 ustar 0000000 0000000
wasm-bindgen
Facilitating high-level interactions between Wasm modules and JavaScript.
## Install `wasm-bindgen-cli`
You can install it using `cargo install`:
```
cargo install wasm-bindgen-cli
```
Or, you can download it from the
[release page](https://github.com/wasm-bindgen/wasm-bindgen/releases).
If you have [`cargo-binstall`](https://crates.io/crates/cargo-binstall) installed,
then you can install the pre-built artifacts by running:
```
cargo binstall wasm-bindgen-cli
```
## 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://wasm-bindgen.github.io/wasm-bindgen/)
## 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)
## MSRV Policy
Libraries that are released on [crates.io](https://crates.io) have a MSRV of v1.57. Changes to the MSRV will be accompanied by a minor version bump.
CLI tools and their corresponding support libraries have a MSRV of v1.82. Changes to the MSRV will be accompanied by a patch version bump.
## 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://wasm-bindgen.github.io/wasm-bindgen/contributing/index.html
wasm-bindgen-0.2.104/build.rs 0000644 0000000 0000000 00000002551 10461020230 0014013 0 ustar 0000000 0000000 // Required so that `[package] links = ...` works in `Cargo.toml`.
use rustversion_compat as rustversion;
use std::env;
macro_rules! deprecated_crate_feature {
($name:literal) => {
#[cfg(feature = $name)]
{
println!("cargo:warning=The `{}` feature is deprecated and will be removed in the next major version.", $name);
}
};
}
fn main() {
println!("cargo:rerun-if-changed=build.rs");
deprecated_crate_feature!("msrv");
deprecated_crate_feature!("rustversion");
deprecated_crate_feature!("xxx_debug_only_print_generated_code");
println!("cargo:rustc-check-cfg=cfg(wbg_diagnostic)");
if rustversion::cfg!(since(1.78)) {
println!("cargo:rustc-cfg=wbg_diagnostic");
}
let target_arch = env::var_os("CARGO_CFG_TARGET_ARCH").unwrap();
let target_os = env::var_os("CARGO_CFG_TARGET_OS").unwrap();
let target_features = env::var("CARGO_CFG_TARGET_FEATURE").unwrap_or_default();
let target_features: Vec<_> = target_features.split(',').map(str::trim).collect();
println!("cargo:rustc-check-cfg=cfg(wbg_reference_types)");
if target_features.contains(&"reference-types")
|| (target_arch == "wasm32"
&& target_os == "unknown"
&& rustversion::cfg!(all(since(1.82), before(1.84))))
{
println!("cargo:rustc-cfg=wbg_reference_types");
}
}
wasm-bindgen-0.2.104/src/cache/intern.rs 0000644 0000000 0000000 00000006441 10461020230 0016047 0 ustar 0000000 0000000 use 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 entries = &cache.entries;
// Can't use `entry` because `entry` requires a `String`
if !entries.borrow().contains_key(key) {
// Note: we must not hold the borrow while we create the `JsValue`,
// because it will try to look up the value in the cache first.
let value = JsValue::from(key);
entries.borrow_mut().insert(key.to_owned(), value);
}
})
}
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.104/src/cache/mod.rs 0000644 0000000 0000000 00000000020 10461020230 0015312 0 ustar 0000000 0000000 pub mod intern;
wasm-bindgen-0.2.104/src/cast.rs 0000644 0000000 0000000 00000013540 10461020230 0014435 0 ustar 0000000 0000000 use crate::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;
}
wasm-bindgen-0.2.104/src/closure.rs 0000644 0000000 0000000 00000037560 10461020230 0015167 0 ustar 0000000 0000000 //! 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 alloc::boxed::Box;
use alloc::string::String;
use core::fmt;
use core::mem::{self, ManuallyDrop};
use crate::convert::*;
use crate::describe::*;
use crate::JsValue;
/// 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: OwnedClosure,
}
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(data: Box) -> Closure {
let data = OwnedClosure {
inner: ManuallyDrop::new(data),
};
Self {
js: ManuallyDrop::new(crate::__rt::wbg_cast(&data)),
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.
///
/// If the platform supports weak references, the Rust memory will be
/// reclaimed when the JS closure is GC'd. If weak references is not
/// supported, 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.
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());
}
/// 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);
/// ```
///
/// Note: the `A` and `R` type parameters are here just for backward compat
/// and will be removed in the future.
pub fn once(fn_once: F) -> Self
where
F: 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::());
/// ```
///
/// Note: the `A` and `R` type parameters are here just for backward compat
/// and will be removed in the future.
pub fn once_into_js(fn_once: F) -> JsValue
where
F: 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 {
fn into_fn_mut(self) -> Box;
fn into_js_function(self) -> JsValue;
}
impl AsRef for Closure {
fn as_ref(&self) -> &JsValue {
&self.js
}
}
/// Internal representation of the actual owned closure which we send to the JS
/// in the constructor to convert it into a JavaScript value.
#[repr(transparent)]
struct OwnedClosure {
inner: ManuallyDrop>,
}
impl WasmDescribe for &OwnedClosure
where
T: WasmClosure + ?Sized,
{
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(CLOSURE);
unsafe extern "C" fn destroy(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(mem::transmute_copy::<_, Box>(&(a, b)));
}
inform(destroy:: as usize as u32);
inform(T::IS_MUT as u32);
T::describe();
}
}
impl IntoWasmAbi for &OwnedClosure
where
T: WasmClosure + ?Sized,
{
type Abi = WasmSlice;
fn into_abi(self) -> WasmSlice {
let (a, b): (usize, usize) = unsafe { mem::transmute_copy(self) };
WasmSlice {
ptr: a as u32,
len: b as u32,
}
}
}
impl WasmDescribe for Closure
where
T: WasmClosure + ?Sized,
{
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(EXTERNREF);
}
}
// `Closure` can only be passed by reference to imports.
impl IntoWasmAbi for &Closure
where
T: WasmClosure + ?Sized,
{
type Abi = u32;
fn into_abi(self) -> u32 {
(&*self.js).into_abi()
}
}
impl OptionIntoWasmAbi for &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) {
// this will implicitly drop our strong reference in addition to
// invalidating all future invocations of the closure
if super::__wbindgen_cb_drop(&self.js) {
unsafe {
ManuallyDrop::drop(&mut self.data.inner);
}
}
}
}
/// 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: WasmDescribe {
const IS_MUT: bool;
}
/// 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;
}
wasm-bindgen-0.2.104/src/convert/closures.rs 0000644 0000000 0000000 00000017552 10461020230 0017031 0 ustar 0000000 0000000 use alloc::boxed::Box;
use core::mem;
use crate::closure::{Closure, IntoWasmClosure, WasmClosure, WasmClosureFnOnce};
use crate::convert::slices::WasmSlice;
use crate::convert::RefFromWasmAbi;
use crate::convert::{FromWasmAbi, IntoWasmAbi, ReturnWasmAbi, WasmAbi, WasmRet};
use crate::describe::{inform, WasmDescribe, FUNCTION};
use crate::throw_str;
use crate::JsValue;
use crate::UnwrapThrowExt;
macro_rules! closures {
// A counter helper to count number of arguments.
(@count_one $ty:ty) => (1);
(@describe ( $($ty:ty),* )) => {
// Needs to be a constant so that interpreter doesn't crash on
// unsupported operations in debug mode.
const ARG_COUNT: u32 = 0 $(+ closures!(@count_one $ty))*;
inform(ARG_COUNT);
$(<$ty>::describe();)*
};
// This silly helper is because by default Rust infers `|var_with_ref_type| ...` closure
// as `impl Fn(&'outer_lifetime A)` instead of `impl for<'temp_lifetime> Fn(&'temp_lifetime A)`
// while `|var_with_ref_type: &A|` makes it use the higher-order generic as expected.
(@closure ($($ty:ty),*) $($var:ident)* $body:block) => (move |$($var: $ty),*| $body);
(@impl_for_fn $is_mut:literal [$($mut:ident)?] $Fn:ident $FnArgs:tt $FromWasmAbi:ident $($var_expr:expr => $var:ident $arg1:ident $arg2:ident $arg3:ident $arg4:ident)*) => (const _: () = {
impl<$($var,)* R> IntoWasmAbi for &'_ $($mut)? (dyn $Fn $FnArgs -> R + '_)
where
Self: WasmDescribe,
{
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,
$(
$arg1: <$var::Abi as WasmAbi>::Prim1,
$arg2: <$var::Abi as WasmAbi>::Prim2,
$arg3: <$var::Abi as WasmAbi>::Prim3,
$arg4: <$var::Abi as WasmAbi>::Prim4,
)*
) -> WasmRet {
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 $Fn $FnArgs -> R = mem::transmute((a, b));
$(
let $var = $var::Abi::join($arg1, $arg2, $arg3, $arg4);
)*
f($($var_expr),*)
};
ret.return_abi().into()
}
#[allow(clippy::fn_to_numeric_cast)]
impl<$($var,)* R> WasmDescribe for dyn $Fn $FnArgs -> R + '_
where
$($var: $FromWasmAbi,)*
R: ReturnWasmAbi,
{
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(FUNCTION);
inform(invoke::<$($var,)* R> as usize as u32);
closures!(@describe $FnArgs);
R::describe();
R::describe();
}
}
unsafe impl<$($var,)* R> WasmClosure for dyn $Fn $FnArgs -> R + '_
where
Self: WasmDescribe,
{
const IS_MUT: bool = $is_mut;
}
impl IntoWasmClosure R> for T
where
T: 'static + $Fn $FnArgs -> R,
{
fn unsize(self: Box) -> Box R> { self }
}
};);
(@impl_for_args $FnArgs:tt $FromWasmAbi:ident $($var_expr:expr => $var:ident $arg1:ident $arg2:ident $arg3:ident $arg4:ident)*) => {
closures!(@impl_for_fn false [] Fn $FnArgs $FromWasmAbi $($var_expr => $var $arg1 $arg2 $arg3 $arg4)*);
closures!(@impl_for_fn true [mut] FnMut $FnArgs $FromWasmAbi $($var_expr => $var $arg1 $arg2 $arg3 $arg4)*);
// 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.
#[allow(non_snake_case, unused_parens)]
impl WasmClosureFnOnce R, $FnArgs, R> for T
where
T: 'static + FnOnce $FnArgs -> R,
$($var: $FromWasmAbi + 'static,)*
R: ReturnWasmAbi + 'static,
{
fn into_fn_mut(self) -> Box R> {
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 alloc::rc::Rc;
use crate::__rt::WasmRefCell;
let rc1 = Rc::new(WasmRefCell::new(None));
let rc2 = rc1.clone();
let closure = Closure::once(closures!(@closure $FnArgs $($var)* {
let result = self($($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
}));
let js_val = closure.as_ref().clone();
*rc1.borrow_mut() = Some(closure);
debug_assert_eq!(Rc::strong_count(&rc1), 2);
drop(rc1);
js_val
}
}
};
($( ($($var:ident $arg1:ident $arg2:ident $arg3:ident $arg4:ident)*) )*) => ($(
closures!(@impl_for_args ($($var),*) FromWasmAbi $($var::from_abi($var) => $var $arg1 $arg2 $arg3 $arg4)*);
)*);
}
closures! {
()
(A a1 a2 a3 a4)
(A a1 a2 a3 a4 B b1 b2 b3 b4)
(A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4)
(A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4 D d1 d2 d3 d4)
(A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4 D d1 d2 d3 d4 E e1 e2 e3 e4)
(A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4 D d1 d2 d3 d4 E e1 e2 e3 e4 F f1 f2 f3 f4)
(A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4 D d1 d2 d3 d4 E e1 e2 e3 e4 F f1 f2 f3 f4 G g1 g2 g3 g4)
(A a1 a2 a3 a4 B b1 b2 b3 b4 C c1 c2 c3 c4 D d1 d2 d3 d4 E e1 e2 e3 e4 F f1 f2 f3 f4 G g1 g2 g3 g4 H h1 h2 h3 h4)
}
// 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.
// We need to allow coherence leak check just for these traits because we're providing separate implementation for `Fn(&A)` variants when `Fn(A)` one already exists.
#[allow(coherence_leak_check)]
const _: () = {
closures!(@impl_for_args (&A) RefFromWasmAbi &*A::ref_from_abi(A) => A a1 a2 a3 a4);
};
wasm-bindgen-0.2.104/src/convert/impls.rs 0000644 0000000 0000000 00000034037 10461020230 0016313 0 ustar 0000000 0000000 use alloc::boxed::Box;
use alloc::vec::Vec;
use core::char;
use core::fmt::Debug;
use core::mem::{self, ManuallyDrop};
use core::ptr::NonNull;
use crate::convert::traits::{WasmAbi, WasmPrimitive};
use crate::convert::TryFromJsValue;
use crate::convert::{FromWasmAbi, IntoWasmAbi, LongRefFromWasmAbi, RefFromWasmAbi};
use crate::convert::{OptionFromWasmAbi, OptionIntoWasmAbi, ReturnWasmAbi};
use crate::{Clamped, JsError, JsValue, UnwrapThrowExt};
// Primitive types can always be passed over the ABI.
impl WasmAbi for T {
type Prim1 = Self;
type Prim2 = ();
type Prim3 = ();
type Prim4 = ();
#[inline]
fn split(self) -> (Self, (), (), ()) {
(self, (), (), ())
}
#[inline]
fn join(prim: Self, _: (), _: (), _: ()) -> Self {
prim
}
}
impl WasmAbi for i128 {
type Prim1 = u64;
type Prim2 = u64;
type Prim3 = ();
type Prim4 = ();
#[inline]
fn split(self) -> (u64, u64, (), ()) {
let low = self as u64;
let high = (self >> 64) as u64;
(low, high, (), ())
}
#[inline]
fn join(low: u64, high: u64, _: (), _: ()) -> Self {
((high as u128) << 64 | low as u128) as i128
}
}
impl WasmAbi for u128 {
type Prim1 = u64;
type Prim2 = u64;
type Prim3 = ();
type Prim4 = ();
#[inline]
fn split(self) -> (u64, u64, (), ()) {
let low = self as u64;
let high = (self >> 64) as u64;
(low, high, (), ())
}
#[inline]
fn join(low: u64, high: u64, _: (), _: ()) -> Self {
(high as u128) << 64 | low as u128
}
}
impl> WasmAbi for Option {
/// Whether this `Option` is a `Some` value.
type Prim1 = u32;
type Prim2 = T::Prim1;
type Prim3 = T::Prim2;
type Prim4 = T::Prim3;
#[inline]
fn split(self) -> (u32, T::Prim1, T::Prim2, T::Prim3) {
match self {
None => (
0,
Default::default(),
Default::default(),
Default::default(),
),
Some(value) => {
let (prim1, prim2, prim3, ()) = value.split();
(1, prim1, prim2, prim3)
}
}
}
#[inline]
fn join(is_some: u32, prim1: T::Prim1, prim2: T::Prim2, prim3: T::Prim3) -> Self {
if is_some == 0 {
None
} else {
Some(T::join(prim1, prim2, prim3, ()))
}
}
}
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 = Option<$c>;
#[inline]
fn into_abi(self) -> Self::Abi {
self.map(|v| v as $c)
}
}
impl FromWasmAbi for Option<$t> {
type Abi = Option<$c>;
#[inline]
unsafe fn from_abi(js: Self::Abi) -> Self {
js.map(|v: $c| v as $t)
}
}
)*)
}
type_wasm_native!(
i64 as i64
u64 as u64
i128 as i128
u128 as u128
f64 as f64
);
/// The sentinel value is 2^32 + 1 for 32-bit primitive types.
///
/// 2^32 + 1 is used, because it's the smallest positive integer that cannot be
/// represented by any 32-bit primitive. While any value >= 2^32 works as a
/// sentinel value for 32-bit integers, it's a bit more tricky for `f32`. `f32`
/// can represent all powers of 2 up to 2^127 exactly. And between 2^32 and 2^33,
/// `f32` can represent all integers 2^32+512*k exactly.
const F64_ABI_OPTION_SENTINEL: f64 = 4294967297_f64;
macro_rules! type_wasm_native_f64_option {
($($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 = f64;
#[inline]
fn into_abi(self) -> Self::Abi {
self.map(|v| v as $c as f64).unwrap_or(F64_ABI_OPTION_SENTINEL)
}
}
impl FromWasmAbi for Option<$t> {
type Abi = f64;
#[inline]
unsafe fn from_abi(js: Self::Abi) -> Self {
if js == F64_ABI_OPTION_SENTINEL {
None
} else {
Some(js as $c as $t)
}
}
}
)*)
}
type_wasm_native_f64_option!(
i32 as i32
isize as i32
u32 as u32
usize as u32
f32 as f32
);
/// The sentinel value is 0xFF_FFFF for primitives with less than 32 bits.
///
/// This value is used, so all small primitive types (`bool`, `i8`, `u8`,
/// `i16`, `u16`, `char`) can use the same JS glue code. `char::MAX` is
/// 0x10_FFFF btw.
const U32_ABI_OPTION_SENTINEL: u32 = 0x00FF_FFFFu32;
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 { U32_ABI_OPTION_SENTINEL }
}
impl OptionFromWasmAbi for $t {
#[inline]
fn is_none(js: &u32) -> bool { *js == U32_ABI_OPTION_SENTINEL }
}
)*)
}
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 {
U32_ABI_OPTION_SENTINEL
}
}
impl OptionFromWasmAbi for bool {
#[inline]
fn is_none(js: &u32) -> bool {
*js == U32_ABI_OPTION_SENTINEL
}
}
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 {
// SAFETY: Checked in bindings.
char::from_u32_unchecked(js)
}
}
impl OptionIntoWasmAbi for char {
#[inline]
fn none() -> u32 {
U32_ABI_OPTION_SENTINEL
}
}
impl OptionFromWasmAbi for char {
#[inline]
fn is_none(js: &u32) -> bool {
*js == U32_ABI_OPTION_SENTINEL
}
}
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 Option<*const T> {
type Abi = f64;
#[inline]
fn into_abi(self) -> f64 {
self.map(|ptr| ptr as u32 as f64)
.unwrap_or(F64_ABI_OPTION_SENTINEL)
}
}
impl FromWasmAbi for Option<*const T> {
type Abi = f64;
#[inline]
unsafe fn from_abi(js: f64) -> Option<*const T> {
if js == F64_ABI_OPTION_SENTINEL {
None
} else {
Some(js as u32 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 Option<*mut T> {
type Abi = f64;
#[inline]
fn into_abi(self) -> f64 {
self.map(|ptr| ptr as u32 as f64)
.unwrap_or(F64_ABI_OPTION_SENTINEL)
}
}
impl FromWasmAbi for Option<*mut T> {
type Abi = f64;
#[inline]
unsafe fn from_abi(js: f64) -> Option<*mut T> {
if js == F64_ABI_OPTION_SENTINEL {
None
} else {
Some(js as u32 as *mut T)
}
}
}
impl IntoWasmAbi for NonNull {
type Abi = u32;
#[inline]
fn into_abi(self) -> u32 {
self.as_ptr() as u32
}
}
impl OptionIntoWasmAbi for NonNull {
#[inline]
fn none() -> u32 {
0
}
}
impl FromWasmAbi for NonNull {
type Abi = u32;
#[inline]
unsafe fn from_abi(js: Self::Abi) -> Self {
// SAFETY: Checked in bindings.
NonNull::new_unchecked(js as *mut T)
}
}
impl OptionFromWasmAbi for NonNull {
#[inline]
fn is_none(js: &u32) -> bool {
*js == 0
}
}
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 IntoWasmAbi for &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
}
}
impl> WasmAbi for Result {
type Prim1 = T::Prim1;
type Prim2 = T::Prim2;
// The order of primitives here is such that we can pop() the possible error
// first, deal with it and move on. Later primitives are popped off the
// stack first.
/// If this `Result` is an `Err`, the error value.
type Prim3 = u32;
/// Whether this `Result` is an `Err`.
type Prim4 = u32;
#[inline]
fn split(self) -> (T::Prim1, T::Prim2, u32, u32) {
match self {
Ok(value) => {
let (prim1, prim2, (), ()) = value.split();
(prim1, prim2, 0, 0)
}
Err(err) => (Default::default(), Default::default(), err, 1),
}
}
#[inline]
fn join(prim1: T::Prim1, prim2: T::Prim2, err: u32, is_err: u32) -> Self {
if is_err == 0 {
Ok(T::join(prim1, prim2, (), ()))
} else {
Err(err)
}
}
}
impl ReturnWasmAbi for Result
where
T: IntoWasmAbi,
E: Into,
T::Abi: WasmAbi,
{
type Abi = Result;
#[inline]
fn return_abi(self) -> Self::Abi {
match self {
Ok(v) => Ok(v.into_abi()),
Err(e) => {
let jsval = e.into();
Err(jsval.into_abi())
}
}
}
}
impl IntoWasmAbi for JsError {
type Abi = ::Abi;
fn into_abi(self) -> Self::Abi {
self.value.into_abi()
}
}
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
// Note: this can't take `&[T]` because the `Into` impl needs
// ownership of `T`.
pub fn js_value_vector_into_abi>(
vector: Box<[T]>,
) -> as IntoWasmAbi>::Abi {
let js_vals: Box<[JsValue]> = vector.into_vec().into_iter().map(|x| x.into()).collect();
js_vals.into_abi()
}
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
pub unsafe fn js_value_vector_from_abi(
js: as FromWasmAbi>::Abi,
) -> Box<[T]>
where
T::Error: Debug,
{
let js_vals = as FromWasmAbi>::from_abi(js);
let mut result = Vec::with_capacity(js_vals.len());
for value in js_vals {
// We push elements one-by-one instead of using `collect` in order to improve
// error messages. When using `collect`, this `expect_throw` is buried in a
// giant chain of internal iterator functions, which results in the actual
// function that takes this `Vec` falling off the end of the call stack.
// So instead, make sure to call it directly within this function.
//
// This is only a problem in debug mode. Since this is the browser's error stack
// we're talking about, it can only see functions that actually make it to the
// final Wasm binary (i.e., not inlined functions). All of those internal
// iterator functions get inlined in release mode, and so they don't show up.
result.push(
T::try_from_js_value(value).expect_throw("array contains a value of the wrong type"),
);
}
result.into_boxed_slice()
}
wasm-bindgen-0.2.104/src/convert/mod.rs 0000644 0000000 0000000 00000000446 10461020230 0015743 0 ustar 0000000 0000000 //! # ⚠️ Unstable
//!
//! This is an internal module, no stability guarantees are provided. Use at
//! your own risk.
#![allow(clippy::missing_safety_doc)]
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.104/src/convert/slices.rs 0000644 0000000 0000000 00000025642 10461020230 0016453 0 ustar 0000000 0000000 use alloc::boxed::Box;
use alloc::string::String;
use alloc::vec::Vec;
use core::mem::{self, MaybeUninit};
use core::ops::{Deref, DerefMut};
use core::str;
use crate::convert::{js_value_vector_from_abi, js_value_vector_into_abi};
use crate::convert::{
FromWasmAbi, IntoWasmAbi, LongRefFromWasmAbi, OptionFromWasmAbi, OptionIntoWasmAbi,
RefFromWasmAbi, RefMutFromWasmAbi, VectorFromWasmAbi, VectorIntoWasmAbi, WasmAbi,
};
use crate::describe::*;
use crate::JsValue;
use crate::{JsCast, __wbindgen_copy_to_typed_array};
use cfg_if::cfg_if;
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
// note: `WasmAbi` types do not need to be FFI-safe themselves, it's just more
// convenient to directly write `WasmSlice` in some of the manually-written FFI
// functions in `lib.rs` rather than `WasmRet`.
#[repr(C)]
pub struct WasmSlice {
pub ptr: u32,
pub len: u32,
}
impl WasmAbi for WasmSlice {
/// `self.ptr`
type Prim1 = u32;
/// `self.len`
type Prim2 = u32;
type Prim3 = ();
type Prim4 = ();
#[inline]
fn split(self) -> (u32, u32, (), ()) {
(self.ptr, self.len, (), ())
}
#[inline]
fn join(ptr: u32, len: u32, _: (), _: ()) -> Self {
Self { ptr, len }
}
}
#[inline]
fn null_slice() -> WasmSlice {
WasmSlice { ptr: 0, len: 0 }
}
pub struct WasmMutSlice {
pub slice: WasmSlice,
pub idx: u32,
}
impl WasmAbi for WasmMutSlice {
/// `self.slice.ptr`
type Prim1 = u32;
/// `self.slice.len`
type Prim2 = u32;
/// `self.idx`
type Prim3 = u32;
type Prim4 = ();
#[inline]
fn split(self) -> (u32, u32, u32, ()) {
(self.slice.ptr, self.slice.len, self.idx, ())
}
#[inline]
fn join(ptr: u32, len: u32, idx: u32, _: ()) -> Self {
Self {
slice: WasmSlice { ptr, len },
idx,
}
}
}
/// 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) {
let byte_slice = unsafe {
core::slice::from_raw_parts(
self.contents.as_ptr() as *const u8,
self.contents.len() * mem::size_of::(),
)
};
__wbindgen_copy_to_typed_array(byte_slice, &self.js);
}
}
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:ty)*) => ($(
vectors_internal!($t);
vectors_internal!(MaybeUninit<$t>);
)*)
}
macro_rules! vectors_internal {
($t:ty) => {
impl WasmDescribeVector for $t {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe_vector() {
inform(VECTOR);
<$t>::describe();
}
}
impl VectorIntoWasmAbi for $t {
type Abi = WasmSlice;
#[inline]
fn vector_into_abi(vector: Box<[$t]>) -> WasmSlice {
let ptr = vector.as_ptr();
let len = vector.len();
mem::forget(vector);
WasmSlice {
ptr: ptr.into_abi(),
len: len as u32,
}
}
}
impl VectorFromWasmAbi for $t {
type Abi = WasmSlice;
#[inline]
unsafe fn vector_from_abi(js: WasmSlice) -> Box<[$t]> {
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<'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
}
impl WasmDescribeVector for String {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe_vector() {
inform(VECTOR);
inform(NAMED_EXTERNREF);
// Trying to use an actual loop for this breaks the Wasm interpreter.
inform(6);
inform('s' as u32);
inform('t' as u32);
inform('r' as u32);
inform('i' as u32);
inform('n' as u32);
inform('g' as u32);
}
}
impl VectorIntoWasmAbi for String {
type Abi = as IntoWasmAbi>::Abi;
fn vector_into_abi(vector: Box<[Self]>) -> Self::Abi {
js_value_vector_into_abi(vector)
}
}
impl VectorFromWasmAbi for String {
type Abi = as FromWasmAbi>::Abi;
unsafe fn vector_from_abi(js: Self::Abi) -> Box<[Self]> {
js_value_vector_from_abi(js)
}
}
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
}
}
}
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 OptionIntoWasmAbi for &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)
}
}
impl IntoWasmAbi for Box<[T]> {
type Abi = ::Abi;
fn into_abi(self) -> Self::Abi {
T::vector_into_abi(self)
}
}
impl OptionIntoWasmAbi for Box<[T]>
where
Self: IntoWasmAbi,
{
fn none() -> WasmSlice {
null_slice()
}
}
impl FromWasmAbi for Box<[T]> {
type Abi = ::Abi;
unsafe fn from_abi(js: Self::Abi) -> Self {
T::vector_from_abi(js)
}
}
impl OptionFromWasmAbi for Box<[T]>
where
Self: FromWasmAbi,
{
fn is_none(slice: &WasmSlice) -> bool {
slice.ptr == 0
}
}
impl VectorFromWasmAbi for T {
type Abi = WasmSlice;
#[inline]
unsafe fn vector_from_abi(js: WasmSlice) -> Box<[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 VectorIntoWasmAbi for T {
type Abi = WasmSlice;
#[inline]
fn vector_into_abi(vector: Box<[T]>) -> WasmSlice {
let ptr = vector.as_ptr();
let len = vector.len();
mem::forget(vector);
WasmSlice {
ptr: ptr.into_abi(),
len: len as u32,
}
}
}
wasm-bindgen-0.2.104/src/convert/traits.rs 0000644 0000000 0000000 00000030415 10461020230 0016471 0 ustar 0000000 0000000 use core::borrow::Borrow;
use core::ops::{Deref, DerefMut};
use crate::describe::*;
use crate::JsValue;
/// 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`.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
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`.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
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`.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
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'.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
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.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
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`.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
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`.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
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;
}
/// A trait for any type which maps to a Wasm primitive type when used in FFI
/// (`i32`, `i64`, `f32`, or `f64`).
///
/// This is with the exception of `()` (and other zero-sized types), which are
/// also allowed because they're ignored: no arguments actually get added.
///
/// # Safety
///
/// This is an unsafe trait to implement as there's no guarantee the type
/// actually maps to a primitive type.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
pub unsafe trait WasmPrimitive: Default {}
unsafe impl WasmPrimitive for u32 {}
unsafe impl WasmPrimitive for i32 {}
unsafe impl WasmPrimitive for u64 {}
unsafe impl WasmPrimitive for i64 {}
unsafe impl WasmPrimitive for f32 {}
unsafe impl WasmPrimitive for f64 {}
unsafe impl WasmPrimitive for () {}
/// A trait which represents types that can be passed across the Wasm ABI
/// boundary, by being split into multiple Wasm primitive types.
///
/// Up to 4 primitives are supported; if you don't want to use all of them, you
/// can set the rest to `()`, which will cause them to be ignored.
///
/// You need to be careful how many primitives you use, however:
/// `Result` uses up 2 primitives to store the error, and so it
/// doesn't work if `T` uses more than 2 primitives.
///
/// So, if you're adding support for a type that needs 3 or more primitives and
/// is able to be returned, you have to add another primitive here.
///
/// There's already one type that uses 3 primitives: `&mut [T]`. However, it
/// can't be returned anyway, so it doesn't matter that
/// `Result<&mut [T], JsValue>` wouldn't work.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
pub trait WasmAbi {
type Prim1: WasmPrimitive;
type Prim2: WasmPrimitive;
type Prim3: WasmPrimitive;
type Prim4: WasmPrimitive;
/// Splits this type up into primitives to be sent over the ABI.
fn split(self) -> (Self::Prim1, Self::Prim2, Self::Prim3, Self::Prim4);
/// Reconstructs this type from primitives received over the ABI.
fn join(prim1: Self::Prim1, prim2: Self::Prim2, prim3: Self::Prim3, prim4: Self::Prim4)
-> Self;
}
/// 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"
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
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()
}
}
use alloc::boxed::Box;
use core::marker::Sized;
/// Trait for element types to implement IntoWasmAbi for vectors of
/// themselves.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
pub trait VectorIntoWasmAbi: WasmDescribeVector + Sized {
type Abi: WasmAbi;
fn vector_into_abi(vector: Box<[Self]>) -> Self::Abi;
}
/// Trait for element types to implement FromWasmAbi for vectors of
/// themselves.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
pub trait VectorFromWasmAbi: WasmDescribeVector + Sized {
type Abi: WasmAbi;
unsafe fn vector_from_abi(js: Self::Abi) -> Box<[Self]>;
}
/// A repr(C) struct containing all of the primitives of a `WasmAbi` type, in
/// order.
///
/// This is used as the return type of imported/exported functions. `WasmAbi`
/// types aren't guaranteed to be FFI-safe, so we can't return them directly:
/// instead we return this.
///
/// If all but one of the primitives is `()`, this corresponds to returning the
/// remaining primitive directly, otherwise a return pointer is used.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
#[repr(C)]
pub struct WasmRet {
prim1: T::Prim1,
prim2: T::Prim2,
prim3: T::Prim3,
prim4: T::Prim4,
}
impl From for WasmRet {
fn from(value: T) -> Self {
let (prim1, prim2, prim3, prim4) = value.split();
Self {
prim1,
prim2,
prim3,
prim4,
}
}
}
// Ideally this'd just be an `Into` implementation, but unfortunately that
// doesn't work because of the orphan rule.
impl WasmRet {
/// Joins the components of this `WasmRet` back into the type they represent.
pub fn join(self) -> T {
T::join(self.prim1, self.prim2, self.prim3, self.prim4)
}
}
/// [`TryFromJsValue`] is a trait for converting a JavaScript value ([`JsValue`])
/// into a Rust type. It is used by the [`wasm_bindgen`](wasm_bindgen_macro::wasm_bindgen)
/// proc-macro to allow conversion to user types.
///
/// Types implementing this trait must specify their conversion logic from
/// [`JsValue`] to the Rust type, handling any potential errors that may occur
/// during the conversion process.
///
/// # ⚠️ Unstable
///
/// This is part of the internal [`convert`](crate::convert) module, **no
/// stability guarantees** are provided. Use at your own risk. See its
/// documentation for more details.
pub trait TryFromJsValue: Sized {
/// The type returned in the event of a conversion error.
type Error;
/// Performs the conversion.
fn try_from_js_value(value: JsValue) -> Result;
}
wasm-bindgen-0.2.104/src/describe.rs 0000644 0000000 0000000 00000010405 10461020230 0015260 0 ustar 0000000 0000000 //! This is an internal module, no stability guarantees are provided. Use at
//! your own risk.
#![doc(hidden)]
use alloc::boxed::Box;
use alloc::string::String;
use alloc::vec::Vec;
use core::{mem::MaybeUninit, ptr::NonNull};
use crate::{Clamped, JsCast, JsError, JsValue};
use cfg_if::cfg_if;
pub use wasm_bindgen_shared::tys::*;
#[inline(always)] // see the wasm-interpreter module
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
pub fn inform(a: u32) {
unsafe { super::__wbindgen_describe(a) }
}
pub trait WasmDescribe {
fn describe();
}
/// Trait for element types to implement WasmDescribe for vectors of
/// themselves.
pub trait WasmDescribeVector {
fn describe_vector();
}
macro_rules! simple {
($($t:ident => $d:ident)*) => ($(
impl WasmDescribe for $t {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() { inform($d) }
}
)*)
}
simple! {
i8 => I8
u8 => U8
i16 => I16
u16 => U16
i32 => I32
u32 => U32
i64 => I64
u64 => U64
i128 => I128
u128 => U128
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 {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(U32)
}
}
impl WasmDescribe for *mut T {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(U32)
}
}
impl WasmDescribe for NonNull {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(NONNULL)
}
}
impl WasmDescribe for [T] {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(SLICE);
T::describe();
}
}
impl WasmDescribe for &T {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(REF);
T::describe();
}
}
impl WasmDescribe for &mut T {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(REFMUT);
T::describe();
}
}
cfg_if! {
if #[cfg(feature = "enable-interning")] {
simple! {
String => CACHED_STRING
}
} else {
simple! {
String => STRING
}
}
}
impl WasmDescribeVector for T {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe_vector() {
inform(VECTOR);
T::describe();
}
}
impl WasmDescribe for Box<[T]> {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
T::describe_vector();
}
}
impl WasmDescribe for Vec
where
Box<[T]>: WasmDescribe,
{
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
>::describe();
}
}
impl WasmDescribe for Option {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(OPTIONAL);
T::describe();
}
}
impl WasmDescribe for () {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(UNIT)
}
}
impl> WasmDescribe for Result {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(RESULT);
T::describe();
}
}
impl WasmDescribe for MaybeUninit {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
T::describe();
}
}
impl WasmDescribe for Clamped {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
inform(CLAMPED);
T::describe();
}
}
impl WasmDescribe for JsError {
#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
fn describe() {
JsValue::describe();
}
}
wasm-bindgen-0.2.104/src/externref.rs 0000644 0000000 0000000 00000011117 10461020230 0015503 0 ustar 0000000 0000000 use crate::JsValue;
use alloc::slice;
use alloc::vec::Vec;
use core::cell::RefCell;
use core::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) -> ();
}
}
struct Slab {
data: Vec,
head: usize,
base: usize,
}
impl Slab {
const fn new() -> Self {
Self {
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?")
}
if self.data.try_reserve_exact(extra).is_err() {
internal_error("allocation failure");
}
}
// 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) -> ! {
cfg_if::cfg_if! {
if #[cfg(debug_assertions)] {
super::throw_str(_msg)
} else if #[cfg(feature = "std")] {
std::process::abort();
} else if #[cfg(all(
target_arch = "wasm32",
any(target_os = "unknown", target_os = "none")
))] {
core::arch::wasm32::unreachable();
} else {
unreachable!()
}
}
}
// 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.
#[cfg_attr(target_feature = "atomics", thread_local)]
static HEAP_SLAB: crate::__rt::ThreadLocalWrapper> =
crate::__rt::ThreadLocalWrapper(RefCell::new(Slab::new()));
#[no_mangle]
pub extern "C" fn __externref_table_alloc() -> usize {
HEAP_SLAB.0.borrow_mut().alloc()
}
#[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.0.borrow_mut().dealloc(idx)
}
#[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`.
pub fn __wbindgen_externref_heap_live_count() -> u32 {
HEAP_SLAB.0.borrow_mut().live_count()
}
wasm-bindgen-0.2.104/src/lib.rs 0000644 0000000 0000000 00000145712 10461020230 0014260 0 ustar 0000000 0000000 //! 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.
//!
//! ## Features
//!
//! ### `enable-interning`
//!
//! Enables the internal cache for [`wasm_bindgen::intern`].
//!
//! This feature currently enables the `std` feature, meaning that it is not
//! compatible with `no_std` environments.
//!
//! ### `std` (default)
//!
//! Enabling this feature will make the crate depend on the Rust standard library.
//!
//! Disable this feature to use this crate in `no_std` environments.
//!
//! ### `strict-macro`
//!
//! All warnings the `#[wasm_bindgen]` macro emits are turned into hard errors.
//! This mainly affects unused attribute options.
//!
//! ### Deprecated features
//!
//! #### `serde-serialize`
//!
//! **Deprecated:** Use the [`serde-wasm-bindgen`](https://docs.rs/serde-wasm-bindgen/latest/serde_wasm_bindgen/) crate instead.
//!
//! Enables the `JsValue::from_serde` and `JsValue::into_serde` methods for
//! serializing and deserializing Rust types to and from JavaScript.
//!
//! #### `spans`
//!
//! **Deprecated:** This feature became a no-op in wasm-bindgen v0.2.20 (Sep 7, 2018).
#![no_std]
#![cfg_attr(wasm_bindgen_unstable_test_coverage, feature(coverage_attribute))]
#![cfg_attr(target_feature = "atomics", feature(thread_local))]
#![cfg_attr(
any(target_feature = "atomics", wasm_bindgen_unstable_test_coverage),
feature(allow_internal_unstable),
allow(internal_features)
)]
#![doc(html_root_url = "https://docs.rs/wasm-bindgen/0.2")]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
use alloc::boxed::Box;
use alloc::string::String;
use alloc::vec::Vec;
use core::convert::TryFrom;
use core::marker::PhantomData;
use core::ops::{
Add, BitAnd, BitOr, BitXor, Deref, DerefMut, Div, Mul, Neg, Not, Rem, Shl, Shr, Sub,
};
use core::ptr::NonNull;
use crate::convert::{TryFromJsValue, VectorIntoWasmAbi};
const _: () = {
/// Dummy empty function provided in order to detect linker-injected functions like `__wasm_call_ctors` and others that should be skipped by the wasm-bindgen interpreter.
///
/// ## About `__wasm_call_ctors`
///
/// There are several ways `__wasm_call_ctors` is introduced by the linker:
///
/// * Using `#[link_section = ".init_array"]`;
/// * Linking with a C library that uses `__attribute__((constructor))`.
///
/// The Wasm linker will insert a call to the `__wasm_call_ctors` function at the beginning of every
/// function that your module exports if it regards a module as having "command-style linkage".
/// Specifically, it regards a module as having "command-style linkage" if:
///
/// * it is not relocatable;
/// * it is not a position-independent executable;
/// * and it does not call `__wasm_call_ctors`, directly or indirectly, from any
/// exported function.
#[no_mangle]
pub extern "C" fn __wbindgen_skip_interpret_calls() {}
};
macro_rules! externs {
($(#[$attr:meta])* extern "C" { $(fn $name:ident($($args:tt)*) -> $ret:ty;)* }) => (
#[cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))]
$(#[$attr])*
extern "C" {
$(fn $name($($args)*) -> $ret;)*
}
$(
#[cfg(not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"))))]
#[allow(unused_variables)]
unsafe extern "C" 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::closure::Closure;
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;
pub use crate::JsError;
}
pub use wasm_bindgen_macro::link_to;
pub mod closure;
pub mod convert;
pub mod describe;
mod link;
#[cfg(wbg_reference_types)]
mod externref;
#[cfg(wbg_reference_types)]
use externref::__wbindgen_externref_heap_live_count;
mod cast;
pub use crate::cast::JsCast;
mod cache;
pub use cache::intern::{intern, unintern};
#[doc(hidden)]
#[path = "rt/mod.rs"]
pub mod __rt;
use __rt::wbg_cast;
/// 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: 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: 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 {
wbg_cast(s)
}
/// 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 {
wbg_cast(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 {
__wbindgen_bigint_from_str(s)
}
/// 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 {
__wbindgen_symbol_new(description)
}
/// 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/wasm-bindgen/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)?;
Ok(__wbindgen_json_parse(s))
}
/// 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/wasm-bindgen/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>,
{
let s = __wbindgen_json_serialize(self);
// Turns out `JSON.stringify(undefined) === undefined`, so if
// we're passed `undefined` reinterpret it as `null` for JSON
// purposes.
serde_json::from_str(s.as_deref().unwrap_or("null"))
}
/// 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 {
__wbindgen_number_get(self)
}
/// Tests whether this JS value is a JS string.
#[inline]
pub fn is_string(&self) -> bool {
__wbindgen_is_string(self)
}
/// 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://wasm-bindgen.github.io/wasm-bindgen/reference/types/str.html
#[inline]
pub fn as_string(&self) -> Option {
__wbindgen_string_get(self)
}
/// 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 {
__wbindgen_boolean_get(self)
}
/// Tests whether this JS value is `null`
#[inline]
pub fn is_null(&self) -> bool {
__wbindgen_is_null(self)
}
/// Tests whether this JS value is `undefined`
#[inline]
pub fn is_undefined(&self) -> bool {
__wbindgen_is_undefined(self)
}
/// Tests whether the type of this JS value is `symbol`
#[inline]
pub fn is_symbol(&self) -> bool {
__wbindgen_is_symbol(self)
}
/// Tests whether `typeof self == "object" && self !== null`.
#[inline]
pub fn is_object(&self) -> bool {
__wbindgen_is_object(self)
}
/// Tests whether this JS value is an instance of Array.
#[inline]
pub fn is_array(&self) -> bool {
__wbindgen_is_array(self)
}
/// Tests whether the type of this JS value is `function`.
#[inline]
pub fn is_function(&self) -> bool {
__wbindgen_is_function(self)
}
/// Tests whether the type of this JS value is `bigint`.
#[inline]
pub fn is_bigint(&self) -> bool {
__wbindgen_is_bigint(self)
}
/// 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 {
__wbindgen_typeof(self)
}
/// 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 {
__wbindgen_in(self, obj)
}
/// 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 {
__wbindgen_is_falsy(self)
}
/// Get a string representation of the JavaScript object for debugging.
fn as_debug_string(&self) -> String {
__wbindgen_debug_string(self)
}
/// 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 {
__wbindgen_jsval_loose_eq(self, other)
}
/// 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 {
__wbindgen_bit_not(self)
}
/// 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 {
__wbindgen_unsigned_shr(self, rhs)
}
/// 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 {
__wbindgen_checked_div(self, rhs)
}
/// 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 {
__wbindgen_pow(self, rhs)
}
/// 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 {
__wbindgen_lt(self, other)
}
/// 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 {
__wbindgen_le(self, other)
}
/// 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 {
__wbindgen_ge(self, other)
}
/// 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 {
__wbindgen_gt(self, other)
}
/// 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 {
// Can't use `wbg_cast` here because it expects that the value already has a correct type
// and will fail with an assertion error in debug mode.
__wbindgen_as_number(self)
}
}
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 {
__wbindgen_jsval_eq(self, other)
}
}
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)
}
}
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 = __wbindgen_try_into_number(val);
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 {
__wbindgen_neg(self)
}
}
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 {
__wbindgen_bit_and(self, rhs)
}
}
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 {
__wbindgen_bit_or(self, rhs)
}
}
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 {
__wbindgen_bit_xor(self, rhs)
}
}
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 {
__wbindgen_shl(self, rhs)
}
}
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 {
__wbindgen_shr(self, rhs)
}
}
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 {
__wbindgen_add(self, rhs)
}
}
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 {
__wbindgen_sub(self, rhs)
}
}
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 {
__wbindgen_div(self, rhs)
}
}
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 {
__wbindgen_mul(self, rhs)
}
}
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 {
__wbindgen_rem(self, rhs)
}
}
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)
}
}
impl From> for JsValue {
#[inline]
fn from(s: NonNull) -> JsValue {
JsValue::from(s.as_ptr() as usize)
}
}
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 TryFrom for String {
type Error = JsValue;
fn try_from(value: JsValue) -> Result {
match value.as_string() {
Some(s) => Ok(s),
None => Err(value),
}
}
}
impl TryFromJsValue for String {
type Error = JsValue;
fn try_from_js_value(value: JsValue) -> Result {
match value.as_string() {
Some(s) => Ok(s),
None => Err(value),
}
}
}
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