The last write accidentally wasn't accounted for in the returned length
of the string and we unfortunately don't have any test coverage of
`encodeInto` since it requires Firefox nightly right now (and doesn't
work in Node yet).
Closes#1436
This commit adds an intrinsics to the `wasm_bindgen` crate which
accesses the `WebAssembly.Table` which is the function table of the
module. Eventually the thinking is that a module would import its own
function table via native wasm functionality (via `anyref` and such),
but until that's implemented let's add a binding for it ourselves!
Closes#1427
Because of some incorrect use of `js.push_str(..)`, we could sometimes emit code
before the ES modules imports, which is syntactically invalid:
const __exports = {};
import { Thing } from '...'; // Syntax error!
This has been fixed by making sure that the correct `imports` or `imports_post`
string is built up. We now also assert that the `js` string is empty at the
location where we add imports if we're using ES modules.
This commit fixes the `init` function when passed a
`WebAssembly.Module`. Upon closer reading of the [spec] we see there's
two possible return values from `WebAssembly.instantiate`. If passed a
`Module`, it will return only the `Instance`. If passed a buffer source,
though, it'll return an object with the module/instance.
The fix here is to check the result value is an `Instance`, and if so
assume the input must have been a module so it's paired up in the
output.
Closes#1418
[spec]: http://webassembly.github.io/spec/js-api/index.html#webassembly-namespace
Instead of doubling the size on each iteration, use precise upper limit (3 * JS length) if the string turned out not to be ASCII-only. This results in maximum of 1 reallocation instead of O(log N).
Some dummy examples of what this would change:
- 1000 of ASCII chars: no change, allocates 1000 bytes and bails out.
- 1000 ASCII chars + 1 '😃': before allocated 1000 bytes and reallocated to 2000; now allocates 1000 bytes and reallocates to 1006.
- 1000 of '😃' chars: before allocated 1000 bytes, reallocated to 2000, finally reallocated again to 4000; now allocates 1000 bytes and reallocates to 4000 right away.
Related issue: #1313
All numbers in WebAssembly are signed and then each operation on them
may optionally have an unsigned version. This means that when we pass
large signed numbers to JS they actually show up as large negative
numbers even though JS numbers can faithfully represent the type.
This is fixed by adding `>>>0` in a few locations in the generated
bindings to coerce the JS value into an unsigned value.
Closes#1388
Aside from visual deduplication, this actually fixes a bug in js2rust.rs where it didn't call `expose_is_like_none` but used `isLikeNone` inside of `arg.get_64()` branch.
Most of the CLI crates were already in the 2018 edition, and it turns
out that one of the macro crates was already in the 2018 edition so we
may as well move everything to the 2018 edition!
Always nice to remove those `extern crate` statements nowadays!
This commit also does a `cargo fmt --all` to make sure we're conforming
with style again.
Node.js doesn't currently implement `TextEncoder::encodeInto`. I've raised an upstream issue to add it - https://github.com/nodejs/node/issues/26904 - but it's likely to take some time and will be available only in new releases.
In the meanwhile, it's worth noting that Node.js already has `Buffer::write` which has pretty similar semantics, but doesn't require creating an intermediate view using `.subarray` and instead accepts pointer and length directly.
Also, Node.js has `Buffer::byteLength` helper which allows to efficiently retrieve an encoded byte length of a string upfront, and so allows us to avoid a loop with reallocations.
This change takes leverage of these methods by generating an additional Buffer-based view into the WASM memory and using it for string operations.
I'm seeing up to 35% increase in performance in string-heavy library benchmarks.
We have very few tests today so this starts to add the basics of a test
suite which compiles Cargo projects on-the-fly which will hopefully help
us bolster the amount of assertions we can make about the output.
This commit implements [RFC 8], which enables transitive and transparent
dependencies on NPM. The `module` attribute, when seen and not part of a
local JS snippet, triggers detection of a `package.json` next to
`Cargo.toml`. If found it will cause the `wasm-bindgen` CLI tool to load
and parse the `package.json` within each crate and then create a merged
`package.json` at the end.
[RFC 8]: https://github.com/rustwasm/rfcs/pull/8
This commit fixes an erroneous use-after-free which can happen in
erroneous situations in JS. It's intended that if you invoke a closure
after its environment has been destroyed that you'll immediately get an
error from Rust saying so. The JS binding generation for mutable
closures, however, accidentally did not protect against this.
Each closure has an internal reference count which is incremented while
being invoked and decremented when the invocation finishes and also when
the `Closure` in Rust is dropped. That means there's two branches where
the reference count reaches zero and the internal pointer stored in JS
needs to be set to zero. Only one, however, actually set the pointer to
zero!
This means that if a closure was destroyed while it was being invoked it
would not correctly set its internal pointer to zero. A further
invocation of the closure would then pass as seemingly valid pointer
into Rust, causing a use-after-free.
A test isn't included here specifically for this because our CI has
started failing left-and-right over this test, so this commit will
hopefully just make our CI green!
We've always wanted this to be the deterministic, but usage of `HashMap`
for example can accidentally lead to non-determinism. Looks like one was
forgotten and the bindings were nondeterministic by accident as a
result!
This commit deprecates the `--web`, `--no-modules`, and `--nodejs` flags
in favor of one `--target` flag. The motivation for this commit is to be
consistent between `wasm-bindgen` and `wasm-pack` so documentation for
one is applicable for the other (so we don't have to document everywhere
what the translation is between flags). Additionally this should make it
a bit easier to add new targets (if necessary) in the future as it won't
add to the proliferation of flags.
For now the old flags (like `--web`) continue to be accepted, but
they'll be removed during the next set of breaking changes for
`wasm-bindgen`.
This allows subverting the checks and resolution performed by the
`module` attribute added as part of [RFC 6] and has been discussed in #1343.
Closes#1343
[RFC 6]: https://github.com/rustwasm/rfcs/pull/6
This commit reverts part of the implementation of [RFC 6]. That RFC
specified that the `--browser` flag was going to be repurposed for the
new "natively loadable as ES module output", but unfortunately the
breakage is far broader than initially expected. It turns out that
`wasm-pack` passes `--browser` by default which means that a change to
break `--browser` would break all historical versions of `wasm-pack`
which is a bit much for now.
To solve this the `--browser` flag is going back to what it represents
on the current released version of `wasm-bindgen` (optimize away some
node.js checks in a few places for bundler-style output) and a new
`--web` flag is being introduced as the new deployment strategy.
[RFC 6]: https://github.com/rustwasm/rfcs/pull/6Closes#1318
This commit is an implementation of [RFC 6] which enables crates to
inline local JS snippets into the final output artifact of
`wasm-bindgen`. This is accompanied with a few minor breaking changes
which are intended to be relatively minor in practice:
* The `module` attribute disallows paths starting with `./` and `../`.
It requires paths starting with `/` to actually exist on the filesystem.
* The `--browser` flag no longer emits bundler-compatible code, but
rather emits an ES module that can be natively loaded into a browser.
Otherwise be sure to check out [the RFC][RFC 6] for more details, and
otherwise this should implement at least the MVP version of the RFC!
Notably at this time JS snippets with `--nodejs` or `--no-modules` are
not supported and will unconditionally generate an error.
[RFC 6]: https://github.com/rustwasm/rfcs/pull/6Closes#1311