* Create JavaScript array without using `new` keyword.
At present [this line of code](https://github.com/rustwasm/wasm-bindgen/blob/master/crates/cli-support/src/js/mod.rs#L747) creates the heap using JavaScript's new keyword.
```
//Line 747
self.global(&format!("const heap = new Array({});", INITIAL_HEAP_OFFSET));
self.global("heap.fill(undefined);");
```
Assuming that the `INITIAL_HEAP_OFFSET` is always 32 (because it is set as a constant in the Rust code), below is the equivalent of what this code will produce; an Array Object with 32 items which are all undefined.
```
const heap = new Array(32);
//(32) [empty × 32]
//Where
var zero_element = heap[0];
//undefined
var one_element = heap[1];
//undefined
```
I believe that this is the desired outcome for the program. All good.
### Suggestion to consider
I am always reminded **not** to use the `new` keyword. Mainly by reading or listening to JavaScript ["The Good Parts"](https://youtu.be/XFTOG895C7c?t=1654).
For example if the `INITIAL_HEAP_OFFSET` was ever anything but one number, the heap would be created in a different way. For example if two numbers are passed in, then an array of size 2 would be created; where both items in the array are individual numbers.
```
const heap = new Array(32, 32);
var zero_element = heap[0];
var one_element = heap[1];
//32
//32
```
I know that this is highly unlikely, due to the fact that the `INITIAL_HEAP_OFFSET` is set as a `const` in the Rust. But thought that I would put out the following suggestion for consideration anyway. This comes from a place of just wanting to contribute in a way that could make this already awesome program a little better. :)
### Suggested update
The heap array could be created using the following code
```
const heap = [];
heap.length = INITIAL_HEAP_OFFSET;
heap[0]
heap[1]
//undefined
//undefined
```
This would create a JavaScript Array of length `INITIAL_HEAP_OFFSET`, where are items are `undefined`
The new code generates (in raw JavaScript)
```
const heap = [];
heap.length = 32;
```
Which produces
```
(32) [empty × 32]
```
In the same way that the original code does.
* Add closing parenthesis to close out self.global
* Adding files which were altered by the BLESS=1 system variable. Essentially updating generated files that are used for testing.
* Adding code generated wat file, by way of running tests using BLESS=1
* Adding table.wat that was generated by running the tests with BLESS=1 set
* Update code that creates heap array line 747 mod.rs
* Updating files that are automatically generated when using BLESS=1
The main gc pass of unused items in wasm-bindgen was accidentally
removing the function table because we weren't properly rooting it in
the auxiliary section which has a few ways that imports can reference
the function table via intrinsics and closures.
Closes#1967
This commit updates how TypeScript signature are generated from adapters
in wasm-bindgen. A richer set of `AdapterType` types are now stored
which record information about optional types and such. These direct
`AdapterType` values are then used to calculate the TypeScript
signature, rather than following the instructions in an adapter function
(which only works anyway for wasm-bindgen generated adapters).
This should be more robust since it reads the actual true signature of
the adapter to generate the TypeScript signature, rather than attempting
to ad-hoc-ly infer it from the various instructions, which was already
broken.
A number of refactorings were involved here, but the main pieces are:
* The `AdapterType` type is a bit more rich now to describe more
Rust-like types.
* The `TypescriptArg` structure is now gone and instead return values
are directly inferred from type signatures of adapters.
* The `typescript_{required,optional}` methods are no longer needed.
* The return of `JsBuilder::process` was enhanced to return more values,
rather than storing some return values on the structure itself.
Closes#1926
The wasm-bindgen nightly test suite started failing recently and a
bisection shows that rust-lang/rust#67363 is the cause of this issue.
The problem happening here is that after that Rust PR duplicate imports
from the same name/module in different parts of a Rust program may now
show up as duplicate imports rather than being coalesced into one
import. This was tripping up `wasm-bindgen` which, when translating from
the wasm module to wasm-bindgen's IR, is unfortunately very
string-based.
The fix here was to detect these duplicate imports and map them all to
the same item, removing the duplicate imports.
Closes#1929
This commit adds a test suite for consuming interface types modules as
input and producing a JS polyfill output. The tests are relatively
simple today and don't exercise a ton of functionality, but they should
hopefully cover the breadth of at least some basics of what wasm
interface types supports today.
A few small fixes were applied along the way, such as:
* Don't require modules to have a stack pointer
* Allow passing `*.wat`, `*.wit`, or `*.wasm` files as input to
`wasm-bindgen` instead of always requiring `*.wasm`.
* Add tests for the interface types output of wasm-bindgen
This commit expands the test suite with assertions about the output of
the interface types pass in wasm-bindgen. The goal here is to actually
assert that we produce the right output and have a suite of reference
files to show how the interface types output is changing over time.
The `reference` test suite added in the previous PR has been updated to
work for interface types as well, generating `*.wit` file assertions
which are printed via the `wit-printer` crate on crates.io.
Along the way a number of bugs were fixed with the interface types
output, such as:
* Non-determinism in output caused by iteration of a `HashMap`
* Avoiding JS generation entirely in interface types mode, ensuring that
we don't export extraneous intrinsics that aren't otherwise needed.
* Fixing location of the stack pointer for modules where it's GC'd out.
It's now rooted in the aux section of wasm-bindgen so it's available
to later passes, like the multi-value pass.
* Interface types emission now works in debug mode, meaning the
`--release` flag is no longer required. This previously did not work
because the `__wbindgen_throw` intrinsic was required in debug mode.
This comes about because of the `malloc_failure` and `internal_error`
functions in the anyref pass. The purpose of these functions is to
signal fatal runtime errors, if any, in a way that's usable to the
user. For wasm interface types though we can replace calls to these
functions with `unreachable` to avoid needing to import the
intrinsic. This has the accidental side effect of making
`wasm_bindgen::throw_str` "just work" with wasm interface types by
aborting the program, but that's not actually entirely intended. It's
hoped that a split of a `wasm-bindgen-core` crate would solve this
issue for the future.
* Run the wasm interface types validator in tests
* Add more gc roots for adapter gc
* Improve stack pointer detection
The stack pointer is never initialized to zero, but some other mutable
globals are (TLS, thread ID, etc), so let's filter those out.
* Add reference output tests for JS operations
This commit starts adding a test suite which checks in, to the
repository, test assertions for both the JS and wasm file outputs of a
Rust crate compiled with `#[wasm_bindgen]`. These aren't intended to be
exhaustive or large scale tests, but rather micro-tests to help observe
the changes in `wasm-bindgen`'s output over time.
The motivation for this commit is basically overhauling how all the GC
passes work in `wasm-bindgen` today. The reorganization is also included
in this commit as well.
Previously `wasm-bindgen` would, in an ad-hoc fashion, run the GC passes
of `walrus` in a bunch of places to ensure that less "garbage" was seen
by future passes. This not only was a source of slowdown but it also was
pretty brittle since `wasm-bindgen` kept breaking if extra iteams leaked
through.
The strategy taken in this commit is to have one precise location for a
GC pass, and everything goes through there. This is achieved by:
* All internal exports are removed immediately when generating the
nonstandard wasm interface types section. Internal exports,
intrinsics, and runtime support are all referenced by the various
instructions and/or sections that use them. This means that we now
have precise tracking of what an adapter uses.
* This in turn enables us to implement the `add_gc_roots` function for
`walrus` custom sections, which in turn allows walrus GC passes to do
what `unexport_unused_intrinsics` did before. That function is now no
longer necessary, but effectively works the same way. All intrinsics
are unexported at the beginning and then they're selectively
re-imported and re-exported through the JS glue generation pass as
necessary and defined by the bindings.
* Passes like the `anyref` pass are now much more precise about the
intrinsics that they work with. The `anyref` pass also deletes any
internal intrinsics found and also does some rewriting of the adapters
aftewards now to hook up calls to the heap count import to the heap
count intrinsic in the wasm module.
* Fix handling of __wbindgen_realloc
The final user of the `require_internal_export` function was
`__wbindgen_realloc`. This usage has now been removed by updating how we
handle usage of the `realloc` function.
The wasm interface types standard doesn't have a `realloc` function
slot, nor do I think it ever will. This means that as a polyfill for
wasm interface types we'll always have to support the lack of `realloc`.
For direct Rust to JS, however, we can still optionally handle
`realloc`. This is all handled with a few internal changes.
* Custom `StringToMemory` instructions now exist. These have an extra
`realloc` slot to store an intrinsic, if found.
* Our custom instructions are lowered to the standard instructions when
generating an interface types section.
* The `realloc` function, if present, is passed as an argument like the
malloc function when passing strings to wasm. If it's not present we
use a slower fallback, but if it's present we use the faster
implementation.
This should mean that there's little-to-no impact on existing users of
`wasm-bindgen`, but this should continue to still work for wasm
interface types polyfills and such. Additionally the GC passes now work
in that they don't delete `__wbindgen_realloc` which we later try to
reference.
* Add an empty test for the anyref pass
* Precisely track I32FromOptionAnyref's dependencies
This depends on the anyref table and a function to allocate an index if
the anyref pass is running, so be sure to track that in the instruction
itself for GC rooting.
* Trim extraneous exports from nop anyref module
Or if you're otherwise not using anyref slices, don't force some
intrinsics to exist.
* Remove globals from reference tests
Looks like these values adjust in slight but insignificant ways over
time
* Update the anyref xform tests
This commit is a pretty large scale rewrite of the internals of wasm-bindgen. No user-facing changes are expected as a result of this PR, but due to the scale of changes here it's likely inevitable that at least something will break. I'm hoping to get more testing in though before landing!
The purpose of this PR is to update wasm-bindgen to the current state of the interface types proposal. The wasm-bindgen tool was last updated when it was still called "WebIDL bindings" so it's been awhile! All support is now based on https://github.com/bytecodealliance/wasm-interface-types which defines parsers/binary format/writers/etc for wasm-interface types.
This is a pretty massive PR and unfortunately can't really be split up any more afaik. I don't really expect realistic review of all the code here (or commits), but some high-level changes are:
* Interface types now consists of a set of "adapter functions". The IR in wasm-bindgen is modeled the same way not.
* Each adapter function has a list of instructions, and these instructions work at a higher level than wasm itself, for example with strings.
* The wasm-bindgen tool has a suite of instructions which are specific to it and not present in the standard. (like before with webidl bindings)
* The anyref/multi-value transformations are now greatly simplified. They're simply "optimization passes" over adapter functions, removing instructions that are otherwise present. This way we don't have to juggle so much all over the place, and instructions always have the same meaning.
* Add support for #[wasm_bindgen(inspectable)]
This annotation generates a `toJSON` and `toString` implementation for
generated JavaScript classes which display all readable properties
available via the class or its getters
This is useful because wasm-bindgen classes currently serialize to
display one value named `ptr`, which does not model the properties of
the struct in Rust
This annotation addresses rustwasm/wasm-bindgen#1857
* Support console.log for inspectable attr in Nodejs
`#[wasm_bindgen(inspectable)]` now generates an implementation of
`[util.inspect.custom]` for the Node.js target only. This implementation
causes `console.log` and friends to yield the same class-style output,
but with all readable fields of the Rust struct displayed
* Reduce duplication in generated methods
Generated `toString` and `[util.inspect.custom]` methods now call
`toJSON` to reduce duplication
* Store module name in variable
This commit adds support to wasm-bindgen to run over interface
types-enabled modules that use multi-value returns and returns are
loaded from the returned array rather than from memory.
Using Typescript I have this warning:
`./pkg/index.js
Line 52:22: Expected '!==' and instead saw '!=' eqeqeq
Search for the keywords to learn more about each warning.
To ignore, add // eslint-disable-next-line to the line before.
`
I guess this should solve the warning.
Thank you for all the work.
* autodiscover an exported `main` if possible
this allows for first-class support of binary crates
* wrap `main` to zero out arguments and suppress return value
* add test for bin crate support
* process only the export of the generated main wrapper
* skip most of `export` since only one line of that is needed
This commit switches all of `wasm-bindgen` from the `failure` crate to
`anyhow`. The `anyhow` crate should serve all the purposes that we
previously used `failure` for but has a few advantages:
* It's based on the standard `Error` trait rather than a custom `Fail`
trait, improving ecosystem compatibility.
* We don't need a `#[derive(Fail)]`, which means that's less code to
compile for `wasm-bindgen`. This notably helps the compile time of
`web-sys` itself.
* Using `Result<()>` in `fn main` with `anyhow::Error` produces
human-readable output, so we can use that natively.
* Reduce indentation in interface types processing
Just a small stylistic change
* Update `webidl_ty` field in multi-value transform
When we're emitting a bindings section we need to be sure to update the
listed type of the binding in addition to the actual binding
expressions. This should help remove the stray return pointer being
listed there by accident!
This came up during #1760 where `Promise.resolve` must be invoked with
`this` as the `Promise` object, but we were erroneously importing it in
such a way that it didn't have a shim and `this` was `undefined`.
The threads transform is implicitly enabled nowadays when the memory
looks like it's shared, so ensure that's taken into account in the
`is_enabled` check.
Turns out that `JSON.stringify(undefined)` doesn't actually return a
string, it returns `undefined`! If we're requested to serialize
`undefined` into JSON instead just interpret it as `null` which should
have the expected semantics of serving as a placeholder for `None`.
Closes#1778
To benefit users in debug mode we log any unexpected exceptions to help
diagnose any issues that might arise. It turns out, though, we log this
for *every* exception happening for *every* import, including imports
like `__wbindgen_throw` which are explicitly intended to throw an
exception. This can cause distracting debug logs to get emitted to the
console, so let's squelch the debug logging for known imports that we
shouldn't log for, such as intrinsics.
Closes#1785
This hasn't ever actually worked in `wasm-bindgen` but there's been
enough refactorings since the initial implementation that it's actually
quite trivial to implement now!
Closes#1777
This tiny crate provides utilities for working with Wasm codegen
conventions (typically established by LLVM or lld) such as getting the shadow
stack pointer.
It also de-duplicates all the places in the codebase where we were implementing
these conventions in one-off ways.