First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
use crate::descriptor::VectorKind;
|
2019-06-10 07:09:51 -07:00
|
|
|
use crate::intrinsic::Intrinsic;
|
2019-12-03 11:16:44 -06:00
|
|
|
use crate::wit::{Adapter, AdapterId, AdapterJsImportKind, AuxValue};
|
|
|
|
use crate::wit::{AdapterKind, Instruction, InstructionData};
|
|
|
|
use crate::wit::{AuxEnum, AuxExport, AuxExportKind, AuxImport, AuxStruct};
|
|
|
|
use crate::wit::{JsImport, JsImportName, NonstandardWitSection, WasmBindgenAux};
|
2020-03-03 00:39:36 +01:00
|
|
|
use crate::{reset_indentation, Bindgen, EncodeInto, OutputMode, PLACEHOLDER_MODULE};
|
2019-12-03 11:16:44 -06:00
|
|
|
use anyhow::{anyhow, bail, Context as _, Error};
|
|
|
|
use std::borrow::Cow;
|
Support emitting direct imports in wasm files
Support was previously (re-)added in #1654 for importing direct JS
values into a WebAssembly module by completely skipping JS shim
generation. This commit takes that PR one step further by *also*
embedding a direct import in the wasm file, where supported. The wasm
file currently largely just imports from the JS shim file that we
generate, but this allows it to directly improt from ES modules where
supported and where possible. Note that like #1654 this only happens
when the function signature doesn't actually require any conversions to
happen in JS (such as handling closures).
For imports from ES modules, local snippets, or inline JS they'll all
have their import directives directly embedded into the final
WebAssembly binary without any shims necessary to hook it all up. For
imports from the global namespace or possibly vendor-prefixed items
these still unconditionally require an import shim to be generated
because there's no way to describe that import in an ES-friendly way
(yet).
There's a few consequences of this commit which are also worth noting:
* The logic in `wasm-bindgen` where it gracefully handles (to some
degree) not-defined items now only is guaranteed to be applied to the
global namespace. If you import from a module, it'll be an
instantiation time error rather than today's runtime error when the
import is called.
* Handling imports in the wasm module not registered with
`#[wasm_bindgen]` has become more strict. Previously these imports
were basically ignored, leaving them up for interpretation depending
on the output format. The changes for each output target are:
* `bundler` - not much has changed here. Previously these ignored
imports would have been treated as ES module imports, and after this
commit there might just be some more of these imports for bundlers
to resolve.
* `web` - previously the ignored imports would likely cause
instantiation failures because the import object never actually
included a binding for other imports. After this commit though the
JS glue which instantiates the module now interprets all
unrecognized wasm module imports as ES module imports, emitting an
`import` directive. This matches what we want for the direct import
functionality, and is also largely what we want for modules in
general.
* `nodejs` - previously ignored imports were handled in the
translation shim for Node to generate `require` statements, so they
were actually "correctly handled" sort of with module imports. The
handling of this hasn't changed, and reflects what we want for
direct imports of values where loading a wasm module in Node ends up
translating the module field of each import to a `require`.
* `no-modules` - this is very similar to the `web` target where
previously this didn't really work one way or the other because we'd
never fill in more fields of the import object when instantiating
the module. After this PR though this is a hard-error to have
unrecognized imports from `#[wasm_bindgen]` with the `no-modules`
output type, because we don't know how to handle the imports.
Note that this touches on #1584 and will likely break the current use
case being mentioned there. I think though that this tightening up of
how we handle imports is what we'll want in the long run where
everything is interpreted as modules, and we'll need to figure out
best how wasi fits into this.
This commit is unlikely to have any real major immediate effects. The
goal here is to continue to inch us towards a world where there's less
and less JS glue necessary and `wasm-bindgen` is just a polyfill for web
standards that otherwise all already exist.
Also note that there's no explicitly added tests for this since this is
largely just a refactoring of an internal implementation detail of
`wasm-bindgen`, but the main `wasm` test suite has many instances of
this path being taken, for example having imports like:
(import "tests/wasm/duplicates_a.js" "foo" (func $__wbg_foo_969c253238f136f0 (type 1)))
(import "tests/wasm/duplicates_b.js" "foo" (func $__wbg_foo_027958cb2e320a94 (type 0)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "trivial" (func $__wbg_trivial_75e27c84882af23b (type 1)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "incoming_bool" (func $__wbg_incomingbool_0f2d9f55f73a256f (type 0)))
2019-07-31 11:35:36 -07:00
|
|
|
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
|
2019-12-03 11:16:44 -06:00
|
|
|
use std::fmt;
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
use std::fs;
|
|
|
|
use std::path::{Path, PathBuf};
|
2019-12-03 09:28:42 -08:00
|
|
|
use walrus::{FunctionId, ImportId, MemoryId, Module, TableId};
|
2019-06-10 07:09:51 -07:00
|
|
|
|
|
|
|
mod binding;
|
2018-04-14 09:13:07 -07:00
|
|
|
|
2018-02-06 15:52:44 -08:00
|
|
|
pub struct Context<'a> {
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
globals: String,
|
|
|
|
imports_post: String,
|
|
|
|
typescript: String,
|
2019-12-03 11:16:44 -06:00
|
|
|
exposed_globals: Option<HashSet<Cow<'static, str>>>,
|
|
|
|
next_export_idx: usize,
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
config: &'a Bindgen,
|
2018-01-29 21:20:38 -08:00
|
|
|
pub module: &'a mut Module,
|
2019-12-03 11:16:44 -06:00
|
|
|
aux: &'a WasmBindgenAux,
|
|
|
|
wit: &'a NonstandardWitSection,
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
|
|
|
|
/// A map representing the `import` statements we'll be generating in the JS
|
|
|
|
/// glue. The key is the module we're importing from and the value is the
|
|
|
|
/// list of identifier we're importing from the module, with optional
|
|
|
|
/// renames for each identifier.
|
|
|
|
js_imports: HashMap<String, Vec<(String, Option<String>)>>,
|
2018-07-30 10:50:43 -07:00
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
/// A map of each wasm import and what JS to hook up to it.
|
|
|
|
wasm_import_definitions: HashMap<ImportId, String>,
|
|
|
|
|
|
|
|
/// A map from an import to the name we've locally imported it as.
|
|
|
|
imported_names: HashMap<JsImportName, String>,
|
2018-07-30 10:50:43 -07:00
|
|
|
|
2019-05-01 13:53:31 -07:00
|
|
|
/// A set of all defined identifiers through either exports or imports to
|
|
|
|
/// the number of times they've been used, used to generate new
|
|
|
|
/// identifiers.
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
defined_identifiers: HashMap<String, usize>,
|
|
|
|
|
|
|
|
exported_classes: Option<BTreeMap<String, ExportedClass>>,
|
2019-02-28 11:37:08 -08:00
|
|
|
|
|
|
|
/// A map of the name of npm dependencies we've loaded so far to the path
|
|
|
|
/// they're defined in as well as their version specification.
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
pub npm_dependencies: HashMap<String, (PathBuf, String)>,
|
2019-12-03 11:16:44 -06:00
|
|
|
|
|
|
|
/// A mapping of a index for memories as we see them. Used in function
|
|
|
|
/// names.
|
|
|
|
memory_indices: HashMap<MemoryId, usize>,
|
|
|
|
table_indices: HashMap<TableId, usize>,
|
2018-02-07 16:41:33 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Default)]
|
|
|
|
pub struct ExportedClass {
|
2018-06-15 11:20:56 -05:00
|
|
|
comments: String,
|
2018-04-20 10:56:10 -07:00
|
|
|
contents: String,
|
|
|
|
typescript: String,
|
2018-09-21 15:45:31 -07:00
|
|
|
has_constructor: bool,
|
|
|
|
wrap_needed: bool,
|
2019-11-26 10:39:57 -08:00
|
|
|
/// Whether to generate helper methods for inspecting the class
|
|
|
|
is_inspectable: bool,
|
|
|
|
/// All readable properties of the class
|
|
|
|
readable_properties: Vec<String>,
|
2020-04-13 20:51:32 +02:00
|
|
|
/// Map from field name to type as a string, docs plus whether it has a setter
|
2020-02-18 23:15:37 +08:00
|
|
|
/// and it is optional
|
2020-04-13 20:51:32 +02:00
|
|
|
typescript_fields: HashMap<String, (String, String, bool, bool)>,
|
2018-01-29 21:20:38 -08:00
|
|
|
}
|
|
|
|
|
2018-11-29 18:15:36 -08:00
|
|
|
const INITIAL_HEAP_VALUES: &[&str] = &["undefined", "null", "true", "false"];
|
|
|
|
// Must be kept in sync with `src/lib.rs` of the `wasm-bindgen` crate
|
|
|
|
const INITIAL_HEAP_OFFSET: usize = 32;
|
2018-07-19 14:44:23 -05:00
|
|
|
|
2018-02-06 15:52:44 -08:00
|
|
|
impl<'a> Context<'a> {
|
2019-12-03 11:16:44 -06:00
|
|
|
pub fn new(
|
|
|
|
module: &'a mut Module,
|
|
|
|
config: &'a Bindgen,
|
|
|
|
wit: &'a NonstandardWitSection,
|
|
|
|
aux: &'a WasmBindgenAux,
|
|
|
|
) -> Result<Context<'a>, Error> {
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
Ok(Context {
|
|
|
|
globals: String::new(),
|
|
|
|
imports_post: String::new(),
|
2019-12-12 03:24:49 +09:00
|
|
|
typescript: "/* tslint:disable */\n/* eslint-disable */\n".to_string(),
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
exposed_globals: Some(Default::default()),
|
|
|
|
imported_names: Default::default(),
|
|
|
|
js_imports: Default::default(),
|
|
|
|
defined_identifiers: Default::default(),
|
|
|
|
wasm_import_definitions: Default::default(),
|
|
|
|
exported_classes: Some(Default::default()),
|
|
|
|
config,
|
|
|
|
module,
|
|
|
|
npm_dependencies: Default::default(),
|
2019-12-03 11:16:44 -06:00
|
|
|
next_export_idx: 0,
|
|
|
|
wit,
|
|
|
|
aux,
|
|
|
|
memory_indices: Default::default(),
|
|
|
|
table_indices: Default::default(),
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn should_write_global(&mut self, name: impl Into<Cow<'static, str>>) -> bool {
|
|
|
|
self.exposed_globals.as_mut().unwrap().insert(name.into())
|
2019-01-14 13:09:05 -08:00
|
|
|
}
|
|
|
|
|
2019-05-01 13:53:31 -07:00
|
|
|
fn export(
|
|
|
|
&mut self,
|
|
|
|
export_name: &str,
|
|
|
|
contents: &str,
|
2020-03-03 10:34:28 -05:00
|
|
|
comments: Option<&str>,
|
2019-05-01 13:53:31 -07:00
|
|
|
) -> Result<(), Error> {
|
2020-04-15 21:28:29 +08:00
|
|
|
let definition_name = self.generate_identifier(export_name);
|
2019-05-01 13:53:31 -07:00
|
|
|
if contents.starts_with("class") && definition_name != export_name {
|
|
|
|
bail!("cannot shadow already defined class `{}`", export_name);
|
|
|
|
}
|
|
|
|
|
2018-04-03 13:12:28 -07:00
|
|
|
let contents = contents.trim();
|
2020-03-03 10:34:28 -05:00
|
|
|
if let Some(c) = comments {
|
2018-06-15 11:20:56 -05:00
|
|
|
self.globals.push_str(c);
|
|
|
|
}
|
2019-02-25 11:11:30 -08:00
|
|
|
let global = match self.config.mode {
|
|
|
|
OutputMode::Node {
|
|
|
|
experimental_modules: false,
|
|
|
|
} => {
|
|
|
|
if contents.starts_with("class") {
|
2019-05-01 13:53:31 -07:00
|
|
|
format!("{}\nmodule.exports.{1} = {1};\n", contents, export_name)
|
2019-02-25 11:11:30 -08:00
|
|
|
} else {
|
2019-05-01 13:53:31 -07:00
|
|
|
format!("module.exports.{} = {};\n", export_name, contents)
|
2019-02-25 11:11:30 -08:00
|
|
|
}
|
2018-05-06 18:00:14 +02:00
|
|
|
}
|
2019-02-25 11:11:30 -08:00
|
|
|
OutputMode::NoModules { .. } => {
|
|
|
|
if contents.starts_with("class") {
|
2019-05-01 13:53:31 -07:00
|
|
|
format!("{}\n__exports.{1} = {1};\n", contents, export_name)
|
2019-02-25 11:11:30 -08:00
|
|
|
} else {
|
2019-05-01 13:53:31 -07:00
|
|
|
format!("__exports.{} = {};\n", export_name, contents)
|
2019-02-25 11:11:30 -08:00
|
|
|
}
|
2018-05-06 18:00:14 +02:00
|
|
|
}
|
2019-03-07 07:33:40 -08:00
|
|
|
OutputMode::Bundler { .. }
|
2019-02-25 11:11:30 -08:00
|
|
|
| OutputMode::Node {
|
|
|
|
experimental_modules: true,
|
2019-05-30 08:50:19 -07:00
|
|
|
}
|
|
|
|
| OutputMode::Web => {
|
2019-02-25 11:11:30 -08:00
|
|
|
if contents.starts_with("function") {
|
2019-05-01 13:53:31 -07:00
|
|
|
let body = &contents[8..];
|
|
|
|
if export_name == definition_name {
|
|
|
|
format!("export function {}{}\n", export_name, body)
|
|
|
|
} else {
|
|
|
|
format!(
|
|
|
|
"function {}{}\nexport {{ {} as {} }};\n",
|
|
|
|
definition_name, body, definition_name, export_name,
|
|
|
|
)
|
|
|
|
}
|
2019-02-25 11:11:30 -08:00
|
|
|
} else if contents.starts_with("class") {
|
2019-05-01 13:53:31 -07:00
|
|
|
assert_eq!(export_name, definition_name);
|
2019-02-25 11:11:30 -08:00
|
|
|
format!("export {}\n", contents)
|
|
|
|
} else {
|
2019-05-01 13:53:31 -07:00
|
|
|
assert_eq!(export_name, definition_name);
|
|
|
|
format!("export const {} = {};\n", export_name, contents)
|
2019-02-25 11:11:30 -08:00
|
|
|
}
|
|
|
|
}
|
2018-04-03 13:12:28 -07:00
|
|
|
};
|
2018-04-14 09:37:49 -07:00
|
|
|
self.global(&global);
|
2019-05-01 13:53:31 -07:00
|
|
|
Ok(())
|
2018-04-03 13:12:28 -07:00
|
|
|
}
|
|
|
|
|
2020-04-29 17:55:28 +02:00
|
|
|
pub fn finalize(
|
|
|
|
&mut self,
|
|
|
|
module_name: &str,
|
|
|
|
) -> Result<(String, String, Option<String>), Error> {
|
2019-03-05 14:40:05 -08:00
|
|
|
// Finalize all bindings for JS classes. This is where we'll generate JS
|
|
|
|
// glue for all classes as well as finish up a few final imports like
|
|
|
|
// `__wrap` and such.
|
|
|
|
self.write_classes()?;
|
|
|
|
|
2019-06-04 09:18:48 -07:00
|
|
|
// Initialization is just flat out tricky and not something we
|
|
|
|
// understand super well. To try to handle various issues that have come
|
|
|
|
// up we always remove the `start` function if one is present. The JS
|
|
|
|
// bindings glue then manually calls the start function (if it was
|
|
|
|
// previously present).
|
2019-08-01 11:56:57 -07:00
|
|
|
let needs_manual_start = self.unstart_start_function();
|
2019-03-05 14:40:05 -08:00
|
|
|
|
|
|
|
// Cause any future calls to `should_write_global` to panic, making sure
|
|
|
|
// we don't ask for items which we can no longer emit.
|
|
|
|
drop(self.exposed_globals.take().unwrap());
|
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
self.finalize_js(module_name, needs_manual_start)
|
2019-03-05 14:40:05 -08:00
|
|
|
}
|
|
|
|
|
2020-03-03 00:39:36 +01:00
|
|
|
fn generate_node_imports(&self) -> String {
|
|
|
|
let mut imports = BTreeSet::new();
|
|
|
|
for import in self.module.imports.iter() {
|
|
|
|
imports.insert(&import.module);
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut shim = String::new();
|
|
|
|
|
|
|
|
shim.push_str("let imports = {};\n");
|
|
|
|
|
|
|
|
if self.config.mode.nodejs_experimental_modules() {
|
|
|
|
for (i, module) in imports.iter().enumerate() {
|
|
|
|
if module.as_str() != PLACEHOLDER_MODULE {
|
|
|
|
shim.push_str(&format!("import * as import{} from '{}';\n", i, module));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i, module) in imports.iter().enumerate() {
|
|
|
|
if module.as_str() == PLACEHOLDER_MODULE {
|
|
|
|
shim.push_str(&format!(
|
|
|
|
"imports['{0}'] = module.exports;\n",
|
|
|
|
PLACEHOLDER_MODULE
|
|
|
|
));
|
|
|
|
} else {
|
|
|
|
if self.config.mode.nodejs_experimental_modules() {
|
|
|
|
shim.push_str(&format!("imports['{}'] = import{};\n", module, i));
|
|
|
|
} else {
|
|
|
|
shim.push_str(&format!("imports['{0}'] = require('{0}');\n", module));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
reset_indentation(&shim)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn generate_node_wasm_loading(&self, path: &Path) -> String {
|
|
|
|
let mut shim = String::new();
|
|
|
|
|
|
|
|
if self.config.mode.nodejs_experimental_modules() {
|
|
|
|
// On windows skip the leading `/` which comes out when we parse a
|
|
|
|
// url to use `C:\...` instead of `\C:\...`
|
|
|
|
shim.push_str(&format!(
|
|
|
|
"
|
|
|
|
import * as path from 'path';
|
|
|
|
import * as fs from 'fs';
|
|
|
|
import * as url from 'url';
|
|
|
|
import * as process from 'process';
|
|
|
|
|
|
|
|
let file = path.dirname(url.parse(import.meta.url).pathname);
|
|
|
|
if (process.platform === 'win32') {{
|
|
|
|
file = file.substring(1);
|
|
|
|
}}
|
|
|
|
const bytes = fs.readFileSync(path.join(file, '{}'));
|
|
|
|
",
|
|
|
|
path.file_name().unwrap().to_str().unwrap()
|
|
|
|
));
|
|
|
|
} else {
|
|
|
|
shim.push_str(&format!(
|
|
|
|
"
|
|
|
|
const path = require('path').join(__dirname, '{}');
|
|
|
|
const bytes = require('fs').readFileSync(path);
|
|
|
|
",
|
|
|
|
path.file_name().unwrap().to_str().unwrap()
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
shim.push_str(
|
|
|
|
"
|
|
|
|
const wasmModule = new WebAssembly.Module(bytes);
|
|
|
|
const wasmInstance = new WebAssembly.Instance(wasmModule, imports);
|
|
|
|
wasm = wasmInstance.exports;
|
|
|
|
module.exports.__wasm = wasm;
|
|
|
|
",
|
|
|
|
);
|
|
|
|
|
|
|
|
reset_indentation(&shim)
|
|
|
|
}
|
|
|
|
|
2019-03-05 14:40:05 -08:00
|
|
|
/// Performs the task of actually generating the final JS module, be it
|
2019-03-19 11:25:13 -07:00
|
|
|
/// `--target no-modules`, `--target web`, or for bundlers. This is the very
|
|
|
|
/// last step performed in `finalize`.
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
fn finalize_js(
|
|
|
|
&mut self,
|
|
|
|
module_name: &str,
|
|
|
|
needs_manual_start: bool,
|
2020-04-29 17:55:28 +02:00
|
|
|
) -> Result<(String, String, Option<String>), Error> {
|
2019-04-01 19:45:53 -03:00
|
|
|
let mut ts = self.typescript.clone();
|
2019-03-05 14:40:05 -08:00
|
|
|
let mut js = String::new();
|
2020-04-29 17:55:28 +02:00
|
|
|
let mut start = None;
|
2020-02-10 23:18:55 +01:00
|
|
|
|
|
|
|
if let OutputMode::NoModules { global } = &self.config.mode {
|
|
|
|
js.push_str(&format!("let {};\n(function() {{\n", global));
|
2019-03-05 14:40:05 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Depending on the output mode, generate necessary glue to actually
|
|
|
|
// import the wasm file in one way or another.
|
2019-04-01 19:45:53 -03:00
|
|
|
let mut init = (String::new(), String::new());
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
let mut footer = String::new();
|
|
|
|
let mut imports = self.js_import_header()?;
|
2019-03-05 14:40:05 -08:00
|
|
|
match &self.config.mode {
|
2019-03-19 11:25:13 -07:00
|
|
|
// In `--target no-modules` mode we need to both expose a name on
|
|
|
|
// the global object as well as generate our own custom start
|
|
|
|
// function.
|
2019-03-05 14:40:05 -08:00
|
|
|
OutputMode::NoModules { global } => {
|
|
|
|
js.push_str("const __exports = {};\n");
|
|
|
|
js.push_str("let wasm;\n");
|
Support emitting direct imports in wasm files
Support was previously (re-)added in #1654 for importing direct JS
values into a WebAssembly module by completely skipping JS shim
generation. This commit takes that PR one step further by *also*
embedding a direct import in the wasm file, where supported. The wasm
file currently largely just imports from the JS shim file that we
generate, but this allows it to directly improt from ES modules where
supported and where possible. Note that like #1654 this only happens
when the function signature doesn't actually require any conversions to
happen in JS (such as handling closures).
For imports from ES modules, local snippets, or inline JS they'll all
have their import directives directly embedded into the final
WebAssembly binary without any shims necessary to hook it all up. For
imports from the global namespace or possibly vendor-prefixed items
these still unconditionally require an import shim to be generated
because there's no way to describe that import in an ES-friendly way
(yet).
There's a few consequences of this commit which are also worth noting:
* The logic in `wasm-bindgen` where it gracefully handles (to some
degree) not-defined items now only is guaranteed to be applied to the
global namespace. If you import from a module, it'll be an
instantiation time error rather than today's runtime error when the
import is called.
* Handling imports in the wasm module not registered with
`#[wasm_bindgen]` has become more strict. Previously these imports
were basically ignored, leaving them up for interpretation depending
on the output format. The changes for each output target are:
* `bundler` - not much has changed here. Previously these ignored
imports would have been treated as ES module imports, and after this
commit there might just be some more of these imports for bundlers
to resolve.
* `web` - previously the ignored imports would likely cause
instantiation failures because the import object never actually
included a binding for other imports. After this commit though the
JS glue which instantiates the module now interprets all
unrecognized wasm module imports as ES module imports, emitting an
`import` directive. This matches what we want for the direct import
functionality, and is also largely what we want for modules in
general.
* `nodejs` - previously ignored imports were handled in the
translation shim for Node to generate `require` statements, so they
were actually "correctly handled" sort of with module imports. The
handling of this hasn't changed, and reflects what we want for
direct imports of values where loading a wasm module in Node ends up
translating the module field of each import to a `require`.
* `no-modules` - this is very similar to the `web` target where
previously this didn't really work one way or the other because we'd
never fill in more fields of the import object when instantiating
the module. After this PR though this is a hard-error to have
unrecognized imports from `#[wasm_bindgen]` with the `no-modules`
output type, because we don't know how to handle the imports.
Note that this touches on #1584 and will likely break the current use
case being mentioned there. I think though that this tightening up of
how we handle imports is what we'll want in the long run where
everything is interpreted as modules, and we'll need to figure out
best how wasi fits into this.
This commit is unlikely to have any real major immediate effects. The
goal here is to continue to inch us towards a world where there's less
and less JS glue necessary and `wasm-bindgen` is just a polyfill for web
standards that otherwise all already exist.
Also note that there's no explicitly added tests for this since this is
largely just a refactoring of an internal implementation detail of
`wasm-bindgen`, but the main `wasm` test suite has many instances of
this path being taken, for example having imports like:
(import "tests/wasm/duplicates_a.js" "foo" (func $__wbg_foo_969c253238f136f0 (type 1)))
(import "tests/wasm/duplicates_b.js" "foo" (func $__wbg_foo_027958cb2e320a94 (type 0)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "trivial" (func $__wbg_trivial_75e27c84882af23b (type 1)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "incoming_bool" (func $__wbg_incomingbool_0f2d9f55f73a256f (type 0)))
2019-07-31 11:35:36 -07:00
|
|
|
init = self.gen_init(needs_manual_start, None)?;
|
2020-03-02 11:44:14 -06:00
|
|
|
footer.push_str(&format!("{} = Object.assign(init, __exports);\n", global));
|
2019-03-05 14:40:05 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// With normal CommonJS node we need to defer requiring the wasm
|
|
|
|
// until the end so most of our own exports are hooked up
|
|
|
|
OutputMode::Node {
|
|
|
|
experimental_modules: false,
|
|
|
|
} => {
|
2020-03-03 00:39:36 +01:00
|
|
|
js.push_str(&self.generate_node_imports());
|
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
js.push_str("let wasm;\n");
|
|
|
|
|
Add tests for the interface types output of wasm-bindgen (#1898)
* 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.
2019-12-04 15:19:48 -06:00
|
|
|
for (id, js) in crate::sorted_iter(&self.wasm_import_definitions) {
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
let import = self.module.imports.get_mut(*id);
|
|
|
|
footer.push_str("\nmodule.exports.");
|
|
|
|
footer.push_str(&import.name);
|
|
|
|
footer.push_str(" = ");
|
|
|
|
footer.push_str(js.trim());
|
|
|
|
footer.push_str(";\n");
|
|
|
|
}
|
|
|
|
|
2020-03-03 00:39:36 +01:00
|
|
|
footer.push_str(
|
|
|
|
&self.generate_node_wasm_loading(&Path::new(&format!(
|
|
|
|
"./{}_bg.wasm",
|
|
|
|
module_name
|
|
|
|
))),
|
|
|
|
);
|
|
|
|
|
2019-03-05 14:40:05 -08:00
|
|
|
if needs_manual_start {
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
footer.push_str("wasm.__wbindgen_start();\n");
|
2019-03-05 14:40:05 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// With Bundlers and modern ES6 support in Node we can simply import
|
|
|
|
// the wasm file as if it were an ES module and let the
|
|
|
|
// bundler/runtime take care of it.
|
2019-03-07 07:33:40 -08:00
|
|
|
OutputMode::Bundler { .. }
|
2019-03-05 14:40:05 -08:00
|
|
|
| OutputMode::Node {
|
|
|
|
experimental_modules: true,
|
|
|
|
} => {
|
2019-07-10 14:45:33 -07:00
|
|
|
imports.push_str(&format!(
|
|
|
|
"import * as wasm from './{}_bg.wasm';\n",
|
|
|
|
module_name
|
|
|
|
));
|
Add tests for the interface types output of wasm-bindgen (#1898)
* 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.
2019-12-04 15:19:48 -06:00
|
|
|
for (id, js) in crate::sorted_iter(&self.wasm_import_definitions) {
|
2019-05-30 08:47:16 -07:00
|
|
|
let import = self.module.imports.get_mut(*id);
|
2020-04-29 17:55:28 +02:00
|
|
|
import.module = format!("./{}_bg.js", module_name);
|
2019-05-30 08:47:16 -07:00
|
|
|
footer.push_str("\nexport const ");
|
|
|
|
footer.push_str(&import.name);
|
|
|
|
footer.push_str(" = ");
|
|
|
|
footer.push_str(js.trim());
|
|
|
|
footer.push_str(";\n");
|
|
|
|
}
|
|
|
|
if needs_manual_start {
|
2020-04-29 17:55:28 +02:00
|
|
|
start = Some("\nwasm.__wbindgen_start();\n".to_string());
|
2019-03-05 14:40:05 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// With a browser-native output we're generating an ES module, but
|
|
|
|
// browsers don't support natively importing wasm right now so we
|
2019-03-19 11:25:13 -07:00
|
|
|
// expose the same initialization function as `--target no-modules`
|
|
|
|
// as the default export of the module.
|
2019-03-07 07:33:40 -08:00
|
|
|
OutputMode::Web => {
|
2019-03-05 14:40:05 -08:00
|
|
|
self.imports_post.push_str("let wasm;\n");
|
Support emitting direct imports in wasm files
Support was previously (re-)added in #1654 for importing direct JS
values into a WebAssembly module by completely skipping JS shim
generation. This commit takes that PR one step further by *also*
embedding a direct import in the wasm file, where supported. The wasm
file currently largely just imports from the JS shim file that we
generate, but this allows it to directly improt from ES modules where
supported and where possible. Note that like #1654 this only happens
when the function signature doesn't actually require any conversions to
happen in JS (such as handling closures).
For imports from ES modules, local snippets, or inline JS they'll all
have their import directives directly embedded into the final
WebAssembly binary without any shims necessary to hook it all up. For
imports from the global namespace or possibly vendor-prefixed items
these still unconditionally require an import shim to be generated
because there's no way to describe that import in an ES-friendly way
(yet).
There's a few consequences of this commit which are also worth noting:
* The logic in `wasm-bindgen` where it gracefully handles (to some
degree) not-defined items now only is guaranteed to be applied to the
global namespace. If you import from a module, it'll be an
instantiation time error rather than today's runtime error when the
import is called.
* Handling imports in the wasm module not registered with
`#[wasm_bindgen]` has become more strict. Previously these imports
were basically ignored, leaving them up for interpretation depending
on the output format. The changes for each output target are:
* `bundler` - not much has changed here. Previously these ignored
imports would have been treated as ES module imports, and after this
commit there might just be some more of these imports for bundlers
to resolve.
* `web` - previously the ignored imports would likely cause
instantiation failures because the import object never actually
included a binding for other imports. After this commit though the
JS glue which instantiates the module now interprets all
unrecognized wasm module imports as ES module imports, emitting an
`import` directive. This matches what we want for the direct import
functionality, and is also largely what we want for modules in
general.
* `nodejs` - previously ignored imports were handled in the
translation shim for Node to generate `require` statements, so they
were actually "correctly handled" sort of with module imports. The
handling of this hasn't changed, and reflects what we want for
direct imports of values where loading a wasm module in Node ends up
translating the module field of each import to a `require`.
* `no-modules` - this is very similar to the `web` target where
previously this didn't really work one way or the other because we'd
never fill in more fields of the import object when instantiating
the module. After this PR though this is a hard-error to have
unrecognized imports from `#[wasm_bindgen]` with the `no-modules`
output type, because we don't know how to handle the imports.
Note that this touches on #1584 and will likely break the current use
case being mentioned there. I think though that this tightening up of
how we handle imports is what we'll want in the long run where
everything is interpreted as modules, and we'll need to figure out
best how wasi fits into this.
This commit is unlikely to have any real major immediate effects. The
goal here is to continue to inch us towards a world where there's less
and less JS glue necessary and `wasm-bindgen` is just a polyfill for web
standards that otherwise all already exist.
Also note that there's no explicitly added tests for this since this is
largely just a refactoring of an internal implementation detail of
`wasm-bindgen`, but the main `wasm` test suite has many instances of
this path being taken, for example having imports like:
(import "tests/wasm/duplicates_a.js" "foo" (func $__wbg_foo_969c253238f136f0 (type 1)))
(import "tests/wasm/duplicates_b.js" "foo" (func $__wbg_foo_027958cb2e320a94 (type 0)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "trivial" (func $__wbg_trivial_75e27c84882af23b (type 1)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "incoming_bool" (func $__wbg_incomingbool_0f2d9f55f73a256f (type 0)))
2019-07-31 11:35:36 -07:00
|
|
|
init = self.gen_init(needs_manual_start, Some(&mut imports))?;
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
footer.push_str("export default init;\n");
|
2019-03-05 14:40:05 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-01 19:45:53 -03:00
|
|
|
let (init_js, init_ts) = init;
|
|
|
|
|
|
|
|
ts.push_str(&init_ts);
|
|
|
|
|
2019-03-05 14:40:05 -08:00
|
|
|
// Emit all the JS for importing all our functionality
|
2019-04-04 15:53:43 -07:00
|
|
|
assert!(
|
|
|
|
!self.config.mode.uses_es_modules() || js.is_empty(),
|
|
|
|
"ES modules require imports to be at the start of the file"
|
|
|
|
);
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
js.push_str(&imports);
|
2019-03-05 14:40:05 -08:00
|
|
|
js.push_str("\n");
|
|
|
|
js.push_str(&self.imports_post);
|
|
|
|
js.push_str("\n");
|
|
|
|
|
|
|
|
// Emit all our exports from this module
|
|
|
|
js.push_str(&self.globals);
|
|
|
|
js.push_str("\n");
|
|
|
|
|
|
|
|
// Generate the initialization glue, if there was any
|
2019-04-01 19:45:53 -03:00
|
|
|
js.push_str(&init_js);
|
2019-03-05 14:40:05 -08:00
|
|
|
js.push_str("\n");
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
js.push_str(&footer);
|
2019-03-05 14:40:05 -08:00
|
|
|
js.push_str("\n");
|
|
|
|
if self.config.mode.no_modules() {
|
|
|
|
js.push_str("})();\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
while js.contains("\n\n\n") {
|
|
|
|
js = js.replace("\n\n\n", "\n\n");
|
|
|
|
}
|
|
|
|
|
2020-04-29 17:55:28 +02:00
|
|
|
Ok((js, ts, start))
|
2019-03-05 14:40:05 -08:00
|
|
|
}
|
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
fn js_import_header(&self) -> Result<String, Error> {
|
|
|
|
let mut imports = String::new();
|
2020-02-12 10:52:59 -07:00
|
|
|
|
|
|
|
if self.config.omit_imports {
|
2020-03-02 11:44:14 -06:00
|
|
|
return Ok(imports);
|
2020-02-12 10:52:59 -07:00
|
|
|
}
|
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
match &self.config.mode {
|
|
|
|
OutputMode::NoModules { .. } => {
|
|
|
|
for (module, _items) in self.js_imports.iter() {
|
|
|
|
bail!(
|
|
|
|
"importing from `{}` isn't supported with `--target no-modules`",
|
|
|
|
module
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
OutputMode::Node {
|
|
|
|
experimental_modules: false,
|
|
|
|
} => {
|
Add tests for the interface types output of wasm-bindgen (#1898)
* 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.
2019-12-04 15:19:48 -06:00
|
|
|
for (module, items) in crate::sorted_iter(&self.js_imports) {
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
imports.push_str("const { ");
|
|
|
|
for (i, (item, rename)) in items.iter().enumerate() {
|
|
|
|
if i > 0 {
|
|
|
|
imports.push_str(", ");
|
2019-01-10 23:37:12 +00:00
|
|
|
}
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
imports.push_str(item);
|
|
|
|
if let Some(other) = rename {
|
|
|
|
imports.push_str(": ");
|
|
|
|
imports.push_str(other)
|
2019-01-10 23:37:12 +00:00
|
|
|
}
|
2018-10-18 08:43:36 -07:00
|
|
|
}
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
imports.push_str(" } = require(String.raw`");
|
|
|
|
imports.push_str(module);
|
|
|
|
imports.push_str("`);\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
OutputMode::Bundler { .. }
|
|
|
|
| OutputMode::Node {
|
|
|
|
experimental_modules: true,
|
|
|
|
}
|
|
|
|
| OutputMode::Web => {
|
Add tests for the interface types output of wasm-bindgen (#1898)
* 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.
2019-12-04 15:19:48 -06:00
|
|
|
for (module, items) in crate::sorted_iter(&self.js_imports) {
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
imports.push_str("import { ");
|
|
|
|
for (i, (item, rename)) in items.iter().enumerate() {
|
|
|
|
if i > 0 {
|
|
|
|
imports.push_str(", ");
|
2019-01-16 10:46:26 +00:00
|
|
|
}
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
imports.push_str(item);
|
|
|
|
if let Some(other) = rename {
|
|
|
|
imports.push_str(" as ");
|
|
|
|
imports.push_str(other)
|
2018-10-18 08:43:36 -07:00
|
|
|
}
|
|
|
|
}
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
imports.push_str(" } from '");
|
|
|
|
imports.push_str(module);
|
|
|
|
imports.push_str("';\n");
|
2018-10-18 08:43:36 -07:00
|
|
|
}
|
2018-10-04 20:00:23 -07:00
|
|
|
}
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
}
|
|
|
|
Ok(imports)
|
2019-02-25 11:11:30 -08:00
|
|
|
}
|
|
|
|
|
2020-03-04 06:20:58 +01:00
|
|
|
fn ts_for_init_fn(
|
|
|
|
&self,
|
|
|
|
has_memory: bool,
|
|
|
|
has_module_or_path_optional: bool,
|
|
|
|
) -> Result<String, Error> {
|
2020-03-04 05:23:05 +01:00
|
|
|
let output = crate::wasm2es6js::interface(&self.module)?;
|
|
|
|
|
2019-04-01 19:45:53 -03:00
|
|
|
let (memory_doc, memory_param) = if has_memory {
|
|
|
|
(
|
|
|
|
"* @param {WebAssembly.Memory} maybe_memory\n",
|
|
|
|
", maybe_memory: WebAssembly.Memory",
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
("", "")
|
|
|
|
};
|
2019-06-16 21:34:31 +10:00
|
|
|
let arg_optional = if has_module_or_path_optional { "?" } else { "" };
|
2020-03-04 05:23:05 +01:00
|
|
|
Ok(format!(
|
2019-04-01 19:45:53 -03:00
|
|
|
"\n\
|
2020-03-04 05:23:05 +01:00
|
|
|
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;\n\
|
|
|
|
\n\
|
|
|
|
export interface InitOutput {{\n\
|
|
|
|
{output}}}\n\
|
|
|
|
\n\
|
2019-04-01 19:45:53 -03:00
|
|
|
/**\n\
|
2020-03-04 05:23:05 +01:00
|
|
|
* If `module_or_path` is {{RequestInfo}} or {{URL}}, makes a request and\n\
|
2019-04-01 19:45:53 -03:00
|
|
|
* for everything else, calls `WebAssembly.instantiate` directly.\n\
|
|
|
|
*\n\
|
2020-03-04 05:23:05 +01:00
|
|
|
* @param {{InitInput | Promise<InitInput>}} module_or_path\n\
|
2019-04-01 19:45:53 -03:00
|
|
|
{}\
|
|
|
|
*\n\
|
2020-03-04 05:23:05 +01:00
|
|
|
* @returns {{Promise<InitOutput>}}\n\
|
2019-04-01 19:45:53 -03:00
|
|
|
*/\n\
|
2019-05-09 11:01:45 -07:00
|
|
|
export default function init \
|
2020-03-04 05:23:05 +01:00
|
|
|
(module_or_path{}: InitInput | Promise<InitInput>{}): Promise<InitOutput>;
|
2019-04-01 19:45:53 -03:00
|
|
|
",
|
2020-03-04 05:23:05 +01:00
|
|
|
memory_doc, arg_optional, memory_param,
|
|
|
|
output = output,
|
|
|
|
))
|
2019-04-01 19:45:53 -03:00
|
|
|
}
|
|
|
|
|
Support emitting direct imports in wasm files
Support was previously (re-)added in #1654 for importing direct JS
values into a WebAssembly module by completely skipping JS shim
generation. This commit takes that PR one step further by *also*
embedding a direct import in the wasm file, where supported. The wasm
file currently largely just imports from the JS shim file that we
generate, but this allows it to directly improt from ES modules where
supported and where possible. Note that like #1654 this only happens
when the function signature doesn't actually require any conversions to
happen in JS (such as handling closures).
For imports from ES modules, local snippets, or inline JS they'll all
have their import directives directly embedded into the final
WebAssembly binary without any shims necessary to hook it all up. For
imports from the global namespace or possibly vendor-prefixed items
these still unconditionally require an import shim to be generated
because there's no way to describe that import in an ES-friendly way
(yet).
There's a few consequences of this commit which are also worth noting:
* The logic in `wasm-bindgen` where it gracefully handles (to some
degree) not-defined items now only is guaranteed to be applied to the
global namespace. If you import from a module, it'll be an
instantiation time error rather than today's runtime error when the
import is called.
* Handling imports in the wasm module not registered with
`#[wasm_bindgen]` has become more strict. Previously these imports
were basically ignored, leaving them up for interpretation depending
on the output format. The changes for each output target are:
* `bundler` - not much has changed here. Previously these ignored
imports would have been treated as ES module imports, and after this
commit there might just be some more of these imports for bundlers
to resolve.
* `web` - previously the ignored imports would likely cause
instantiation failures because the import object never actually
included a binding for other imports. After this commit though the
JS glue which instantiates the module now interprets all
unrecognized wasm module imports as ES module imports, emitting an
`import` directive. This matches what we want for the direct import
functionality, and is also largely what we want for modules in
general.
* `nodejs` - previously ignored imports were handled in the
translation shim for Node to generate `require` statements, so they
were actually "correctly handled" sort of with module imports. The
handling of this hasn't changed, and reflects what we want for
direct imports of values where loading a wasm module in Node ends up
translating the module field of each import to a `require`.
* `no-modules` - this is very similar to the `web` target where
previously this didn't really work one way or the other because we'd
never fill in more fields of the import object when instantiating
the module. After this PR though this is a hard-error to have
unrecognized imports from `#[wasm_bindgen]` with the `no-modules`
output type, because we don't know how to handle the imports.
Note that this touches on #1584 and will likely break the current use
case being mentioned there. I think though that this tightening up of
how we handle imports is what we'll want in the long run where
everything is interpreted as modules, and we'll need to figure out
best how wasi fits into this.
This commit is unlikely to have any real major immediate effects. The
goal here is to continue to inch us towards a world where there's less
and less JS glue necessary and `wasm-bindgen` is just a polyfill for web
standards that otherwise all already exist.
Also note that there's no explicitly added tests for this since this is
largely just a refactoring of an internal implementation detail of
`wasm-bindgen`, but the main `wasm` test suite has many instances of
this path being taken, for example having imports like:
(import "tests/wasm/duplicates_a.js" "foo" (func $__wbg_foo_969c253238f136f0 (type 1)))
(import "tests/wasm/duplicates_b.js" "foo" (func $__wbg_foo_027958cb2e320a94 (type 0)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "trivial" (func $__wbg_trivial_75e27c84882af23b (type 1)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "incoming_bool" (func $__wbg_incomingbool_0f2d9f55f73a256f (type 0)))
2019-07-31 11:35:36 -07:00
|
|
|
fn gen_init(
|
|
|
|
&mut self,
|
|
|
|
needs_manual_start: bool,
|
|
|
|
mut imports: Option<&mut String>,
|
|
|
|
) -> Result<(String, String), Error> {
|
2019-06-04 08:56:34 -07:00
|
|
|
let module_name = "wbg";
|
2019-12-03 11:16:44 -06:00
|
|
|
let mut init_memory_arg = "";
|
|
|
|
let mut init_memory1 = String::new();
|
|
|
|
let mut init_memory2 = String::new();
|
|
|
|
let mut has_memory = false;
|
|
|
|
if let Some(mem) = self.module.memories.iter().next() {
|
|
|
|
if let Some(id) = mem.import {
|
|
|
|
self.module.imports.get_mut(id).module = module_name.to_string();
|
|
|
|
let mut memory = String::from("new WebAssembly.Memory({");
|
|
|
|
memory.push_str(&format!("initial:{}", mem.initial));
|
|
|
|
if let Some(max) = mem.maximum {
|
|
|
|
memory.push_str(&format!(",maximum:{}", max));
|
|
|
|
}
|
|
|
|
if mem.shared {
|
|
|
|
memory.push_str(",shared:true");
|
|
|
|
}
|
|
|
|
memory.push_str("})");
|
|
|
|
self.imports_post.push_str("let memory;\n");
|
|
|
|
init_memory1 = format!("memory = imports.{}.memory = maybe_memory;", module_name);
|
|
|
|
init_memory2 = format!("memory = imports.{}.memory = {};", module_name, memory);
|
|
|
|
init_memory_arg = ", maybe_memory";
|
|
|
|
has_memory = true;
|
|
|
|
}
|
|
|
|
}
|
2019-06-08 01:27:35 +03:00
|
|
|
|
|
|
|
let default_module_path = match self.config.mode {
|
2019-11-21 09:30:08 -06:00
|
|
|
OutputMode::Web => {
|
|
|
|
"\
|
2020-02-11 17:58:42 +01:00
|
|
|
if (typeof input === 'undefined') {
|
|
|
|
input = import.meta.url.replace(/\\.js$/, '_bg.wasm');
|
2019-11-21 09:30:08 -06:00
|
|
|
}"
|
|
|
|
}
|
2020-01-06 21:55:45 +01:00
|
|
|
OutputMode::NoModules { .. } => {
|
|
|
|
"\
|
2020-02-11 17:58:42 +01:00
|
|
|
if (typeof input === 'undefined') {
|
2020-01-06 21:55:45 +01:00
|
|
|
let src;
|
2020-03-10 15:13:50 +01:00
|
|
|
if (typeof document === 'undefined') {
|
2020-02-10 23:18:55 +01:00
|
|
|
src = location.href;
|
2020-01-06 21:55:45 +01:00
|
|
|
} else {
|
2020-02-10 23:18:55 +01:00
|
|
|
src = document.currentScript.src;
|
2020-01-06 21:55:45 +01:00
|
|
|
}
|
2020-02-11 17:58:42 +01:00
|
|
|
input = src.replace(/\\.js$/, '_bg.wasm');
|
2020-01-06 21:55:45 +01:00
|
|
|
}"
|
|
|
|
}
|
2019-06-08 01:27:35 +03:00
|
|
|
_ => "",
|
|
|
|
};
|
|
|
|
|
2020-03-04 05:23:05 +01:00
|
|
|
let ts = self.ts_for_init_fn(has_memory, !default_module_path.is_empty())?;
|
2019-05-01 11:54:06 -07:00
|
|
|
|
2019-05-30 08:47:16 -07:00
|
|
|
// Initialize the `imports` object for all import definitions that we're
|
|
|
|
// directed to wire up.
|
|
|
|
let mut imports_init = String::new();
|
|
|
|
if self.wasm_import_definitions.len() > 0 {
|
|
|
|
imports_init.push_str("imports.");
|
|
|
|
imports_init.push_str(module_name);
|
|
|
|
imports_init.push_str(" = {};\n");
|
|
|
|
}
|
Add tests for the interface types output of wasm-bindgen (#1898)
* 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.
2019-12-04 15:19:48 -06:00
|
|
|
for (id, js) in crate::sorted_iter(&self.wasm_import_definitions) {
|
2019-05-30 08:47:16 -07:00
|
|
|
let import = self.module.imports.get_mut(*id);
|
|
|
|
import.module = module_name.to_string();
|
|
|
|
imports_init.push_str("imports.");
|
|
|
|
imports_init.push_str(module_name);
|
|
|
|
imports_init.push_str(".");
|
|
|
|
imports_init.push_str(&import.name);
|
|
|
|
imports_init.push_str(" = ");
|
|
|
|
imports_init.push_str(js.trim());
|
|
|
|
imports_init.push_str(";\n");
|
|
|
|
}
|
2019-05-01 11:54:06 -07:00
|
|
|
|
Support emitting direct imports in wasm files
Support was previously (re-)added in #1654 for importing direct JS
values into a WebAssembly module by completely skipping JS shim
generation. This commit takes that PR one step further by *also*
embedding a direct import in the wasm file, where supported. The wasm
file currently largely just imports from the JS shim file that we
generate, but this allows it to directly improt from ES modules where
supported and where possible. Note that like #1654 this only happens
when the function signature doesn't actually require any conversions to
happen in JS (such as handling closures).
For imports from ES modules, local snippets, or inline JS they'll all
have their import directives directly embedded into the final
WebAssembly binary without any shims necessary to hook it all up. For
imports from the global namespace or possibly vendor-prefixed items
these still unconditionally require an import shim to be generated
because there's no way to describe that import in an ES-friendly way
(yet).
There's a few consequences of this commit which are also worth noting:
* The logic in `wasm-bindgen` where it gracefully handles (to some
degree) not-defined items now only is guaranteed to be applied to the
global namespace. If you import from a module, it'll be an
instantiation time error rather than today's runtime error when the
import is called.
* Handling imports in the wasm module not registered with
`#[wasm_bindgen]` has become more strict. Previously these imports
were basically ignored, leaving them up for interpretation depending
on the output format. The changes for each output target are:
* `bundler` - not much has changed here. Previously these ignored
imports would have been treated as ES module imports, and after this
commit there might just be some more of these imports for bundlers
to resolve.
* `web` - previously the ignored imports would likely cause
instantiation failures because the import object never actually
included a binding for other imports. After this commit though the
JS glue which instantiates the module now interprets all
unrecognized wasm module imports as ES module imports, emitting an
`import` directive. This matches what we want for the direct import
functionality, and is also largely what we want for modules in
general.
* `nodejs` - previously ignored imports were handled in the
translation shim for Node to generate `require` statements, so they
were actually "correctly handled" sort of with module imports. The
handling of this hasn't changed, and reflects what we want for
direct imports of values where loading a wasm module in Node ends up
translating the module field of each import to a `require`.
* `no-modules` - this is very similar to the `web` target where
previously this didn't really work one way or the other because we'd
never fill in more fields of the import object when instantiating
the module. After this PR though this is a hard-error to have
unrecognized imports from `#[wasm_bindgen]` with the `no-modules`
output type, because we don't know how to handle the imports.
Note that this touches on #1584 and will likely break the current use
case being mentioned there. I think though that this tightening up of
how we handle imports is what we'll want in the long run where
everything is interpreted as modules, and we'll need to figure out
best how wasi fits into this.
This commit is unlikely to have any real major immediate effects. The
goal here is to continue to inch us towards a world where there's less
and less JS glue necessary and `wasm-bindgen` is just a polyfill for web
standards that otherwise all already exist.
Also note that there's no explicitly added tests for this since this is
largely just a refactoring of an internal implementation detail of
`wasm-bindgen`, but the main `wasm` test suite has many instances of
this path being taken, for example having imports like:
(import "tests/wasm/duplicates_a.js" "foo" (func $__wbg_foo_969c253238f136f0 (type 1)))
(import "tests/wasm/duplicates_b.js" "foo" (func $__wbg_foo_027958cb2e320a94 (type 0)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "trivial" (func $__wbg_trivial_75e27c84882af23b (type 1)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "incoming_bool" (func $__wbg_incomingbool_0f2d9f55f73a256f (type 0)))
2019-07-31 11:35:36 -07:00
|
|
|
let extra_modules = self
|
|
|
|
.module
|
|
|
|
.imports
|
|
|
|
.iter()
|
|
|
|
.filter(|i| !self.wasm_import_definitions.contains_key(&i.id()))
|
|
|
|
.filter(|i| {
|
|
|
|
// Importing memory is handled specially in this area, so don't
|
|
|
|
// consider this a candidate for importing from extra modules.
|
|
|
|
match i.kind {
|
|
|
|
walrus::ImportKind::Memory(_) => false,
|
|
|
|
_ => true,
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.map(|i| &i.module)
|
|
|
|
.collect::<BTreeSet<_>>();
|
|
|
|
for (i, extra) in extra_modules.iter().enumerate() {
|
|
|
|
let imports = match &mut imports {
|
|
|
|
Some(list) => list,
|
2019-08-01 11:56:57 -07:00
|
|
|
None => bail!(
|
|
|
|
"cannot import from modules (`{}`) with `--no-modules`",
|
|
|
|
extra
|
|
|
|
),
|
Support emitting direct imports in wasm files
Support was previously (re-)added in #1654 for importing direct JS
values into a WebAssembly module by completely skipping JS shim
generation. This commit takes that PR one step further by *also*
embedding a direct import in the wasm file, where supported. The wasm
file currently largely just imports from the JS shim file that we
generate, but this allows it to directly improt from ES modules where
supported and where possible. Note that like #1654 this only happens
when the function signature doesn't actually require any conversions to
happen in JS (such as handling closures).
For imports from ES modules, local snippets, or inline JS they'll all
have their import directives directly embedded into the final
WebAssembly binary without any shims necessary to hook it all up. For
imports from the global namespace or possibly vendor-prefixed items
these still unconditionally require an import shim to be generated
because there's no way to describe that import in an ES-friendly way
(yet).
There's a few consequences of this commit which are also worth noting:
* The logic in `wasm-bindgen` where it gracefully handles (to some
degree) not-defined items now only is guaranteed to be applied to the
global namespace. If you import from a module, it'll be an
instantiation time error rather than today's runtime error when the
import is called.
* Handling imports in the wasm module not registered with
`#[wasm_bindgen]` has become more strict. Previously these imports
were basically ignored, leaving them up for interpretation depending
on the output format. The changes for each output target are:
* `bundler` - not much has changed here. Previously these ignored
imports would have been treated as ES module imports, and after this
commit there might just be some more of these imports for bundlers
to resolve.
* `web` - previously the ignored imports would likely cause
instantiation failures because the import object never actually
included a binding for other imports. After this commit though the
JS glue which instantiates the module now interprets all
unrecognized wasm module imports as ES module imports, emitting an
`import` directive. This matches what we want for the direct import
functionality, and is also largely what we want for modules in
general.
* `nodejs` - previously ignored imports were handled in the
translation shim for Node to generate `require` statements, so they
were actually "correctly handled" sort of with module imports. The
handling of this hasn't changed, and reflects what we want for
direct imports of values where loading a wasm module in Node ends up
translating the module field of each import to a `require`.
* `no-modules` - this is very similar to the `web` target where
previously this didn't really work one way or the other because we'd
never fill in more fields of the import object when instantiating
the module. After this PR though this is a hard-error to have
unrecognized imports from `#[wasm_bindgen]` with the `no-modules`
output type, because we don't know how to handle the imports.
Note that this touches on #1584 and will likely break the current use
case being mentioned there. I think though that this tightening up of
how we handle imports is what we'll want in the long run where
everything is interpreted as modules, and we'll need to figure out
best how wasi fits into this.
This commit is unlikely to have any real major immediate effects. The
goal here is to continue to inch us towards a world where there's less
and less JS glue necessary and `wasm-bindgen` is just a polyfill for web
standards that otherwise all already exist.
Also note that there's no explicitly added tests for this since this is
largely just a refactoring of an internal implementation detail of
`wasm-bindgen`, but the main `wasm` test suite has many instances of
this path being taken, for example having imports like:
(import "tests/wasm/duplicates_a.js" "foo" (func $__wbg_foo_969c253238f136f0 (type 1)))
(import "tests/wasm/duplicates_b.js" "foo" (func $__wbg_foo_027958cb2e320a94 (type 0)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "trivial" (func $__wbg_trivial_75e27c84882af23b (type 1)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "incoming_bool" (func $__wbg_incomingbool_0f2d9f55f73a256f (type 0)))
2019-07-31 11:35:36 -07:00
|
|
|
};
|
|
|
|
imports.push_str(&format!("import * as __wbg_star{} from '{}';\n", i, extra));
|
|
|
|
imports_init.push_str(&format!("imports['{}'] = __wbg_star{};\n", extra, i));
|
|
|
|
}
|
|
|
|
|
2019-04-01 19:45:53 -03:00
|
|
|
let js = format!(
|
2019-02-25 11:11:30 -08:00
|
|
|
"\
|
2020-02-20 17:33:40 +00:00
|
|
|
async function load(module, imports{init_memory_arg}) {{
|
2020-02-11 17:58:42 +01:00
|
|
|
if (typeof Response === 'function' && module instanceof Response) {{
|
2019-02-25 11:11:30 -08:00
|
|
|
{init_memory2}
|
|
|
|
if (typeof WebAssembly.instantiateStreaming === 'function') {{
|
2020-02-11 17:58:42 +01:00
|
|
|
try {{
|
|
|
|
return await WebAssembly.instantiateStreaming(module, imports);
|
|
|
|
|
|
|
|
}} catch (e) {{
|
|
|
|
if (module.headers.get('Content-Type') != 'application/wasm') {{
|
|
|
|
console.warn(\"`WebAssembly.instantiateStreaming` failed \
|
|
|
|
because your server does not serve wasm with \
|
|
|
|
`application/wasm` MIME type. Falling back to \
|
|
|
|
`WebAssembly.instantiate` which is slower. Original \
|
|
|
|
error:\\n\", e);
|
|
|
|
|
|
|
|
}} else {{
|
|
|
|
throw e;
|
|
|
|
}}
|
|
|
|
}}
|
2019-02-25 11:11:30 -08:00
|
|
|
}}
|
2020-02-11 17:58:42 +01:00
|
|
|
|
|
|
|
const bytes = await module.arrayBuffer();
|
|
|
|
return await WebAssembly.instantiate(bytes, imports);
|
|
|
|
|
2019-03-21 16:39:03 -05:00
|
|
|
}} else {{
|
|
|
|
{init_memory1}
|
2020-02-11 17:58:42 +01:00
|
|
|
const instance = await WebAssembly.instantiate(module, imports);
|
|
|
|
|
|
|
|
if (instance instanceof WebAssembly.Instance) {{
|
|
|
|
return {{ instance, module }};
|
|
|
|
|
|
|
|
}} else {{
|
|
|
|
return instance;
|
|
|
|
}}
|
|
|
|
}}
|
|
|
|
}}
|
|
|
|
|
|
|
|
async function init(input{init_memory_arg}) {{
|
|
|
|
{default_module_path}
|
|
|
|
const imports = {{}};
|
|
|
|
{imports_init}
|
|
|
|
|
|
|
|
if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {{
|
|
|
|
input = fetch(input);
|
2019-02-25 11:11:30 -08:00
|
|
|
}}
|
2020-02-11 17:58:42 +01:00
|
|
|
|
2020-02-20 17:33:40 +00:00
|
|
|
const {{ instance, module }} = await load(await input, imports{init_memory_arg});
|
2020-02-11 17:58:42 +01:00
|
|
|
|
|
|
|
wasm = instance.exports;
|
|
|
|
init.__wbindgen_wasm_module = module;
|
|
|
|
{start}
|
|
|
|
return wasm;
|
2019-02-25 11:11:30 -08:00
|
|
|
}}
|
|
|
|
",
|
2019-04-01 19:45:53 -03:00
|
|
|
init_memory_arg = init_memory_arg,
|
2019-06-08 01:27:35 +03:00
|
|
|
default_module_path = default_module_path,
|
2019-02-25 11:11:30 -08:00
|
|
|
init_memory1 = init_memory1,
|
|
|
|
init_memory2 = init_memory2,
|
|
|
|
start = if needs_manual_start {
|
|
|
|
"wasm.__wbindgen_start();"
|
|
|
|
} else {
|
|
|
|
""
|
|
|
|
},
|
2019-05-01 11:54:06 -07:00
|
|
|
imports_init = imports_init,
|
2019-04-01 19:45:53 -03:00
|
|
|
);
|
|
|
|
|
Support emitting direct imports in wasm files
Support was previously (re-)added in #1654 for importing direct JS
values into a WebAssembly module by completely skipping JS shim
generation. This commit takes that PR one step further by *also*
embedding a direct import in the wasm file, where supported. The wasm
file currently largely just imports from the JS shim file that we
generate, but this allows it to directly improt from ES modules where
supported and where possible. Note that like #1654 this only happens
when the function signature doesn't actually require any conversions to
happen in JS (such as handling closures).
For imports from ES modules, local snippets, or inline JS they'll all
have their import directives directly embedded into the final
WebAssembly binary without any shims necessary to hook it all up. For
imports from the global namespace or possibly vendor-prefixed items
these still unconditionally require an import shim to be generated
because there's no way to describe that import in an ES-friendly way
(yet).
There's a few consequences of this commit which are also worth noting:
* The logic in `wasm-bindgen` where it gracefully handles (to some
degree) not-defined items now only is guaranteed to be applied to the
global namespace. If you import from a module, it'll be an
instantiation time error rather than today's runtime error when the
import is called.
* Handling imports in the wasm module not registered with
`#[wasm_bindgen]` has become more strict. Previously these imports
were basically ignored, leaving them up for interpretation depending
on the output format. The changes for each output target are:
* `bundler` - not much has changed here. Previously these ignored
imports would have been treated as ES module imports, and after this
commit there might just be some more of these imports for bundlers
to resolve.
* `web` - previously the ignored imports would likely cause
instantiation failures because the import object never actually
included a binding for other imports. After this commit though the
JS glue which instantiates the module now interprets all
unrecognized wasm module imports as ES module imports, emitting an
`import` directive. This matches what we want for the direct import
functionality, and is also largely what we want for modules in
general.
* `nodejs` - previously ignored imports were handled in the
translation shim for Node to generate `require` statements, so they
were actually "correctly handled" sort of with module imports. The
handling of this hasn't changed, and reflects what we want for
direct imports of values where loading a wasm module in Node ends up
translating the module field of each import to a `require`.
* `no-modules` - this is very similar to the `web` target where
previously this didn't really work one way or the other because we'd
never fill in more fields of the import object when instantiating
the module. After this PR though this is a hard-error to have
unrecognized imports from `#[wasm_bindgen]` with the `no-modules`
output type, because we don't know how to handle the imports.
Note that this touches on #1584 and will likely break the current use
case being mentioned there. I think though that this tightening up of
how we handle imports is what we'll want in the long run where
everything is interpreted as modules, and we'll need to figure out
best how wasi fits into this.
This commit is unlikely to have any real major immediate effects. The
goal here is to continue to inch us towards a world where there's less
and less JS glue necessary and `wasm-bindgen` is just a polyfill for web
standards that otherwise all already exist.
Also note that there's no explicitly added tests for this since this is
largely just a refactoring of an internal implementation detail of
`wasm-bindgen`, but the main `wasm` test suite has many instances of
this path being taken, for example having imports like:
(import "tests/wasm/duplicates_a.js" "foo" (func $__wbg_foo_969c253238f136f0 (type 1)))
(import "tests/wasm/duplicates_b.js" "foo" (func $__wbg_foo_027958cb2e320a94 (type 0)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "trivial" (func $__wbg_trivial_75e27c84882af23b (type 1)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "incoming_bool" (func $__wbg_incomingbool_0f2d9f55f73a256f (type 0)))
2019-07-31 11:35:36 -07:00
|
|
|
Ok((js, ts))
|
2018-01-29 21:20:38 -08:00
|
|
|
}
|
|
|
|
|
2018-04-25 11:42:22 -07:00
|
|
|
fn write_classes(&mut self) -> Result<(), Error> {
|
2019-01-14 13:11:07 -08:00
|
|
|
for (class, exports) in self.exported_classes.take().unwrap() {
|
2018-04-25 11:42:22 -07:00
|
|
|
self.write_class(&class, &exports)?;
|
2018-04-19 16:49:46 -07:00
|
|
|
}
|
2018-04-25 11:42:22 -07:00
|
|
|
Ok(())
|
2018-04-19 16:49:46 -07:00
|
|
|
}
|
2018-04-15 01:29:09 +02:00
|
|
|
|
2018-04-25 11:42:22 -07:00
|
|
|
fn write_class(&mut self, name: &str, class: &ExportedClass) -> Result<(), Error> {
|
2018-04-19 16:49:46 -07:00
|
|
|
let mut dst = format!("class {} {{\n", name);
|
|
|
|
let mut ts_dst = format!("export {}", dst);
|
2018-04-15 01:29:09 +02:00
|
|
|
|
2018-09-21 15:45:31 -07:00
|
|
|
if self.config.debug && !class.has_constructor {
|
|
|
|
dst.push_str(
|
2018-06-27 22:42:34 -07:00
|
|
|
"
|
2018-09-21 15:45:31 -07:00
|
|
|
constructor() {
|
|
|
|
throw new Error('cannot invoke `new` directly');
|
|
|
|
}
|
2018-09-26 08:26:00 -07:00
|
|
|
",
|
2018-09-21 15:45:31 -07:00
|
|
|
);
|
2018-04-19 16:49:46 -07:00
|
|
|
}
|
2018-02-07 16:41:33 -08:00
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
if class.wrap_needed {
|
2018-09-21 15:45:31 -07:00
|
|
|
dst.push_str(&format!(
|
|
|
|
"
|
|
|
|
static __wrap(ptr) {{
|
|
|
|
const obj = Object.create({}.prototype);
|
|
|
|
obj.ptr = ptr;
|
|
|
|
{}
|
|
|
|
return obj;
|
|
|
|
}}
|
|
|
|
",
|
|
|
|
name,
|
2019-05-26 09:30:33 -05:00
|
|
|
if self.config.weak_refs {
|
|
|
|
format!("{}FinalizationGroup.register(obj, obj.ptr, obj.ptr);", name)
|
|
|
|
} else {
|
|
|
|
String::new()
|
|
|
|
},
|
2018-09-21 15:45:31 -07:00
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2019-05-26 09:30:33 -05:00
|
|
|
if self.config.weak_refs {
|
|
|
|
self.global(&format!(
|
|
|
|
"
|
|
|
|
const {}FinalizationGroup = new FinalizationGroup((items) => {{
|
|
|
|
for (const ptr of items) {{
|
2019-06-04 09:29:17 -07:00
|
|
|
wasm.{}(ptr);
|
2019-05-26 09:30:33 -05:00
|
|
|
}}
|
|
|
|
}});
|
|
|
|
",
|
2019-06-04 09:29:17 -07:00
|
|
|
name,
|
|
|
|
wasm_bindgen_shared::free_function(&name),
|
2019-05-26 09:30:33 -05:00
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2019-11-26 10:39:57 -08:00
|
|
|
// If the class is inspectable, generate `toJSON` and `toString`
|
|
|
|
// to expose all readable properties of the class. Otherwise,
|
|
|
|
// the class shows only the "ptr" property when logged or serialized
|
|
|
|
if class.is_inspectable {
|
|
|
|
// Creates a `toJSON` method which returns an object of all readable properties
|
|
|
|
// This object looks like { a: this.a, b: this.b }
|
|
|
|
dst.push_str(&format!(
|
|
|
|
"
|
|
|
|
toJSON() {{
|
|
|
|
return {{{}}};
|
|
|
|
}}
|
|
|
|
|
|
|
|
toString() {{
|
|
|
|
return JSON.stringify(this);
|
|
|
|
}}
|
|
|
|
",
|
|
|
|
class
|
|
|
|
.readable_properties
|
|
|
|
.iter()
|
|
|
|
.fold(String::from("\n"), |fields, field_name| {
|
|
|
|
format!("{}{name}: this.{name},\n", fields, name = field_name)
|
|
|
|
})
|
|
|
|
));
|
|
|
|
|
|
|
|
if self.config.mode.nodejs() {
|
|
|
|
// `util.inspect` must be imported in Node.js to define [inspect.custom]
|
|
|
|
let module_name = self.import_name(&JsImport {
|
|
|
|
name: JsImportName::Module {
|
|
|
|
module: "util".to_string(),
|
|
|
|
name: "inspect".to_string(),
|
|
|
|
},
|
|
|
|
fields: Vec::new(),
|
|
|
|
})?;
|
|
|
|
|
|
|
|
// Node.js supports a custom inspect function to control the
|
|
|
|
// output of `console.log` and friends. The constructor is set
|
|
|
|
// to display the class name as a typical JavaScript class would
|
|
|
|
dst.push_str(&format!(
|
|
|
|
"
|
|
|
|
[{}.custom]() {{
|
|
|
|
return Object.assign(Object.create({{constructor: this.constructor}}), this.toJSON());
|
|
|
|
}}
|
|
|
|
",
|
|
|
|
module_name
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-27 22:42:34 -07:00
|
|
|
dst.push_str(&format!(
|
|
|
|
"
|
2018-04-19 16:49:46 -07:00
|
|
|
free() {{
|
|
|
|
const ptr = this.ptr;
|
|
|
|
this.ptr = 0;
|
2019-05-26 09:30:33 -05:00
|
|
|
{}
|
2019-06-04 09:29:17 -07:00
|
|
|
wasm.{}(ptr);
|
2018-04-19 16:49:46 -07:00
|
|
|
}}
|
2018-06-15 23:39:51 -07:00
|
|
|
",
|
2019-05-26 09:30:33 -05:00
|
|
|
if self.config.weak_refs {
|
|
|
|
format!("{}FinalizationGroup.unregister(ptr);", name)
|
|
|
|
} else {
|
|
|
|
String::new()
|
|
|
|
},
|
2019-06-04 09:29:17 -07:00
|
|
|
wasm_bindgen_shared::free_function(&name),
|
2018-06-27 22:42:34 -07:00
|
|
|
));
|
2019-06-06 16:11:51 -03:00
|
|
|
ts_dst.push_str(" free(): void;\n");
|
2018-04-19 16:49:46 -07:00
|
|
|
dst.push_str(&class.contents);
|
|
|
|
ts_dst.push_str(&class.typescript);
|
2019-05-30 10:56:59 -07:00
|
|
|
|
|
|
|
let mut fields = class.typescript_fields.keys().collect::<Vec<_>>();
|
|
|
|
fields.sort(); // make sure we have deterministic output
|
|
|
|
for name in fields {
|
2020-04-13 20:51:32 +02:00
|
|
|
let (ty, docs, has_setter, is_optional) = &class.typescript_fields[name];
|
|
|
|
ts_dst.push_str(docs);
|
2019-06-06 16:11:51 -03:00
|
|
|
ts_dst.push_str(" ");
|
|
|
|
if !has_setter {
|
2019-05-30 10:56:59 -07:00
|
|
|
ts_dst.push_str("readonly ");
|
|
|
|
}
|
|
|
|
ts_dst.push_str(name);
|
2020-02-18 23:15:37 +08:00
|
|
|
if *is_optional {
|
|
|
|
ts_dst.push_str("?: ");
|
|
|
|
} else {
|
|
|
|
ts_dst.push_str(": ");
|
|
|
|
}
|
|
|
|
ts_dst.push_str(&ty);
|
2019-05-30 10:56:59 -07:00
|
|
|
ts_dst.push_str(";\n");
|
|
|
|
}
|
2018-04-19 16:49:46 -07:00
|
|
|
dst.push_str("}\n");
|
|
|
|
ts_dst.push_str("}\n");
|
|
|
|
|
2020-03-03 10:34:28 -05:00
|
|
|
self.export(&name, &dst, Some(&class.comments))?;
|
2020-04-13 20:51:32 +02:00
|
|
|
self.typescript.push_str(&class.comments);
|
2018-04-19 16:49:46 -07:00
|
|
|
self.typescript.push_str(&ts_dst);
|
2018-04-25 11:42:22 -07:00
|
|
|
|
|
|
|
Ok(())
|
2018-02-07 16:41:33 -08:00
|
|
|
}
|
|
|
|
|
2018-02-06 15:52:44 -08:00
|
|
|
fn expose_drop_ref(&mut self) {
|
2019-01-14 13:09:05 -08:00
|
|
|
if !self.should_write_global("drop_ref") {
|
2018-04-07 13:06:36 +05:45
|
|
|
return;
|
2018-02-06 15:52:44 -08:00
|
|
|
}
|
2018-11-29 18:15:36 -08:00
|
|
|
self.expose_global_heap();
|
|
|
|
self.expose_global_heap_next();
|
|
|
|
|
|
|
|
// Note that here we check if `idx` shouldn't actually be dropped. This
|
|
|
|
// is due to the fact that `JsValue::null()` and friends can be passed
|
|
|
|
// by value to JS where we'll automatically call this method. Those
|
|
|
|
// constants, however, cannot be dropped. See #1054 for removing this
|
|
|
|
// branch.
|
|
|
|
//
|
|
|
|
// Otherwise the free operation here is pretty simple, just appending to
|
|
|
|
// the linked list of heap slots that are free.
|
2018-06-27 22:42:34 -07:00
|
|
|
self.global(&format!(
|
|
|
|
"
|
2018-11-29 18:15:36 -08:00
|
|
|
function dropObject(idx) {{
|
2018-07-19 14:44:23 -05:00
|
|
|
if (idx < {}) return;
|
2018-11-29 18:15:36 -08:00
|
|
|
heap[idx] = heap_next;
|
|
|
|
heap_next = idx;
|
2018-01-29 21:20:38 -08:00
|
|
|
}}
|
2018-06-15 23:39:51 -07:00
|
|
|
",
|
2018-11-29 18:15:36 -08:00
|
|
|
INITIAL_HEAP_OFFSET + INITIAL_HEAP_VALUES.len(),
|
2018-06-27 22:42:34 -07:00
|
|
|
));
|
2018-02-06 15:52:44 -08:00
|
|
|
}
|
|
|
|
|
2018-11-29 18:15:36 -08:00
|
|
|
fn expose_global_heap(&mut self) {
|
2019-01-14 13:09:05 -08:00
|
|
|
if !self.should_write_global("heap") {
|
2018-04-07 13:06:36 +05:45
|
|
|
return;
|
2018-01-29 21:20:38 -08:00
|
|
|
}
|
2018-10-18 08:43:36 -07:00
|
|
|
assert!(!self.config.anyref);
|
2020-03-02 11:44:14 -06:00
|
|
|
self.global(&format!(
|
|
|
|
"const heap = new Array({}).fill(undefined);",
|
|
|
|
INITIAL_HEAP_OFFSET
|
|
|
|
));
|
2018-11-29 18:15:36 -08:00
|
|
|
self.global(&format!("heap.push({});", INITIAL_HEAP_VALUES.join(", ")));
|
2018-02-06 15:52:44 -08:00
|
|
|
}
|
2018-01-29 21:20:38 -08:00
|
|
|
|
2018-11-29 18:15:36 -08:00
|
|
|
fn expose_global_heap_next(&mut self) {
|
2019-01-14 13:09:05 -08:00
|
|
|
if !self.should_write_global("heap_next") {
|
2018-04-07 13:06:36 +05:45
|
|
|
return;
|
2018-02-06 15:52:44 -08:00
|
|
|
}
|
2018-11-29 18:15:36 -08:00
|
|
|
self.expose_global_heap();
|
|
|
|
self.global("let heap_next = heap.length;");
|
2018-01-29 21:20:38 -08:00
|
|
|
}
|
|
|
|
|
2018-02-06 15:52:44 -08:00
|
|
|
fn expose_get_object(&mut self) {
|
2019-01-14 13:09:05 -08:00
|
|
|
if !self.should_write_global("get_object") {
|
2018-04-07 13:06:36 +05:45
|
|
|
return;
|
2018-02-06 15:52:44 -08:00
|
|
|
}
|
2018-11-29 18:15:36 -08:00
|
|
|
self.expose_global_heap();
|
2018-01-29 21:20:38 -08:00
|
|
|
|
2018-11-29 18:15:36 -08:00
|
|
|
// Accessing a heap object is just a simple index operation due to how
|
|
|
|
// the stack/heap are laid out.
|
|
|
|
self.global("function getObject(idx) { return heap[idx]; }");
|
2018-02-06 15:52:44 -08:00
|
|
|
}
|
|
|
|
|
2019-07-10 14:22:13 -07:00
|
|
|
fn expose_not_defined(&mut self) {
|
|
|
|
if !self.should_write_global("not_defined") {
|
|
|
|
return;
|
|
|
|
}
|
2020-02-18 23:15:37 +08:00
|
|
|
self.global("function notDefined(what) { return () => { throw new Error(`${what} is not defined`); }; }");
|
2019-07-10 14:22:13 -07:00
|
|
|
}
|
|
|
|
|
2018-02-06 15:52:44 -08:00
|
|
|
fn expose_assert_num(&mut self) {
|
2019-01-14 13:09:05 -08:00
|
|
|
if !self.should_write_global("assert_num") {
|
2018-04-07 13:06:36 +05:45
|
|
|
return;
|
2018-02-06 15:52:44 -08:00
|
|
|
}
|
2018-06-27 22:42:34 -07:00
|
|
|
self.global(&format!(
|
|
|
|
"
|
2018-02-06 15:52:44 -08:00
|
|
|
function _assertNum(n) {{
|
2018-06-15 12:55:37 -05:00
|
|
|
if (typeof(n) !== 'number') throw new Error('expected a number argument');
|
2018-02-06 15:52:44 -08:00
|
|
|
}}
|
2018-06-15 23:39:51 -07:00
|
|
|
"
|
2018-06-27 22:42:34 -07:00
|
|
|
));
|
2018-02-06 15:52:44 -08:00
|
|
|
}
|
2018-01-29 21:20:38 -08:00
|
|
|
|
2018-02-06 15:52:44 -08:00
|
|
|
fn expose_assert_bool(&mut self) {
|
2019-01-14 13:09:05 -08:00
|
|
|
if !self.should_write_global("assert_bool") {
|
2018-04-07 13:06:36 +05:45
|
|
|
return;
|
2018-01-29 21:20:38 -08:00
|
|
|
}
|
2018-06-27 22:42:34 -07:00
|
|
|
self.global(&format!(
|
|
|
|
"
|
2018-02-06 15:52:44 -08:00
|
|
|
function _assertBoolean(n) {{
|
2018-06-15 12:55:37 -05:00
|
|
|
if (typeof(n) !== 'boolean') {{
|
2018-02-06 15:52:44 -08:00
|
|
|
throw new Error('expected a boolean argument');
|
2018-06-15 12:55:37 -05:00
|
|
|
}}
|
2018-02-06 15:52:44 -08:00
|
|
|
}}
|
2018-06-15 23:39:51 -07:00
|
|
|
"
|
2018-06-27 22:42:34 -07:00
|
|
|
));
|
2018-02-06 15:52:44 -08:00
|
|
|
}
|
|
|
|
|
2018-11-13 08:10:05 -08:00
|
|
|
fn expose_wasm_vector_len(&mut self) {
|
2019-01-14 13:09:05 -08:00
|
|
|
if !self.should_write_global("wasm_vector_len") {
|
2018-11-13 08:10:05 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
self.global("let WASM_VECTOR_LEN = 0;");
|
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_pass_string_to_wasm(&mut self, memory: MemoryId) -> Result<MemView, Error> {
|
2018-11-13 08:10:05 -08:00
|
|
|
self.expose_wasm_vector_len();
|
2019-08-24 19:41:04 +02:00
|
|
|
|
2018-04-03 12:44:09 -07:00
|
|
|
let debug = if self.config.debug {
|
|
|
|
"
|
2018-06-15 12:55:37 -05:00
|
|
|
if (typeof(arg) !== 'string') throw new Error('expected a string argument');
|
2018-04-03 12:44:09 -07:00
|
|
|
"
|
|
|
|
} else {
|
|
|
|
""
|
|
|
|
};
|
2019-02-20 08:39:46 -08:00
|
|
|
|
2019-03-25 17:42:10 +00:00
|
|
|
// If we are targeting Node.js, it doesn't have `encodeInto` yet
|
|
|
|
// but it does have `Buffer::write` which has similar semantics but
|
|
|
|
// doesn't require creating intermediate view using `subarray`
|
|
|
|
// and also has `Buffer::byteLength` to calculate size upfront.
|
|
|
|
if self.config.mode.nodejs() {
|
2019-12-03 11:16:44 -06:00
|
|
|
let get_buf = self.expose_node_buffer_memory(memory);
|
|
|
|
let ret = MemView {
|
|
|
|
name: "passStringToWasm",
|
|
|
|
num: get_buf.num,
|
|
|
|
};
|
|
|
|
if !self.should_write_global(ret.to_string()) {
|
|
|
|
return Ok(ret);
|
|
|
|
}
|
2019-03-25 17:42:10 +00:00
|
|
|
|
|
|
|
self.global(&format!(
|
|
|
|
"
|
2019-12-03 11:16:44 -06:00
|
|
|
function {}(arg, malloc) {{
|
2019-03-25 17:42:10 +00:00
|
|
|
{}
|
2019-08-24 19:41:04 +02:00
|
|
|
const len = Buffer.byteLength(arg);
|
2019-12-03 11:16:44 -06:00
|
|
|
const ptr = malloc(len);
|
|
|
|
{}().write(arg, ptr, len);
|
2019-08-24 19:41:04 +02:00
|
|
|
WASM_VECTOR_LEN = len;
|
2019-03-25 17:42:10 +00:00
|
|
|
return ptr;
|
|
|
|
}}
|
|
|
|
",
|
2019-12-03 11:16:44 -06:00
|
|
|
ret, debug, get_buf,
|
2019-03-25 17:42:10 +00:00
|
|
|
));
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
return Ok(ret);
|
2019-03-25 17:42:10 +00:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
let mem = self.expose_uint8_memory(memory);
|
|
|
|
let ret = MemView {
|
|
|
|
name: "passStringToWasm",
|
|
|
|
num: mem.num,
|
|
|
|
};
|
|
|
|
if !self.should_write_global(ret.to_string()) {
|
|
|
|
return Ok(ret);
|
|
|
|
}
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
self.expose_text_encoder()?;
|
2019-03-25 17:42:10 +00:00
|
|
|
|
2019-08-24 19:41:04 +02:00
|
|
|
// The first implementation we have for this is to use
|
|
|
|
// `TextEncoder#encode` which has been around for quite some time.
|
|
|
|
let encode = "function (arg, view) {
|
|
|
|
const buf = cachedTextEncoder.encode(arg);
|
|
|
|
view.set(buf);
|
|
|
|
return {
|
|
|
|
read: arg.length,
|
|
|
|
written: buf.length
|
|
|
|
};
|
|
|
|
}";
|
|
|
|
|
|
|
|
// Another possibility is to use `TextEncoder#encodeInto` which is much
|
|
|
|
// newer and isn't implemented everywhere yet. It's more efficient,
|
2019-08-24 19:49:26 +02:00
|
|
|
// however, becaues it allows us to elide an intermediate allocation.
|
2019-08-24 19:41:04 +02:00
|
|
|
let encode_into = "function (arg, view) {
|
|
|
|
return cachedTextEncoder.encodeInto(arg, view);
|
|
|
|
}";
|
|
|
|
|
|
|
|
// Looks like `encodeInto` doesn't currently work when the memory passed
|
|
|
|
// in is backed by a `SharedArrayBuffer`, so force usage of `encode` if
|
|
|
|
// a `SharedArrayBuffer` is in use.
|
2019-12-03 11:16:44 -06:00
|
|
|
let shared = self.module.memories.get(memory).shared;
|
2019-08-24 19:41:04 +02:00
|
|
|
|
|
|
|
match self.config.encode_into {
|
|
|
|
EncodeInto::Always if !shared => {
|
2019-09-10 11:20:19 -07:00
|
|
|
self.global(&format!(
|
|
|
|
"
|
2019-08-24 19:41:04 +02:00
|
|
|
const encodeString = {};
|
2019-09-10 11:20:19 -07:00
|
|
|
",
|
|
|
|
encode_into
|
|
|
|
));
|
2019-08-24 19:41:04 +02:00
|
|
|
}
|
|
|
|
EncodeInto::Test if !shared => {
|
2019-09-10 11:20:19 -07:00
|
|
|
self.global(&format!(
|
|
|
|
"
|
2019-08-24 19:41:04 +02:00
|
|
|
const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
|
|
|
|
? {}
|
|
|
|
: {});
|
2019-09-10 11:20:19 -07:00
|
|
|
",
|
|
|
|
encode_into, encode
|
|
|
|
));
|
2019-08-24 19:41:04 +02:00
|
|
|
}
|
|
|
|
_ => {
|
2019-09-10 11:20:19 -07:00
|
|
|
self.global(&format!(
|
|
|
|
"
|
2019-08-24 19:41:04 +02:00
|
|
|
const encodeString = {};
|
2019-09-10 11:20:19 -07:00
|
|
|
",
|
|
|
|
encode
|
|
|
|
));
|
2019-08-24 19:41:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-17 18:14:53 +01:00
|
|
|
// A fast path that directly writes char codes into WASM memory as long
|
|
|
|
// as it finds only ASCII characters.
|
|
|
|
//
|
|
|
|
// This is much faster for common ASCII strings because it can avoid
|
|
|
|
// calling out into C++ TextEncoder code.
|
|
|
|
//
|
|
|
|
// This might be not very intuitive, but such calls are usually more
|
|
|
|
// expensive in mainstream engines than staying in the JS, and
|
|
|
|
// charCodeAt on ASCII strings is usually optimised to raw bytes.
|
2019-12-03 11:16:44 -06:00
|
|
|
let encode_as_ascii = format!(
|
|
|
|
"\
|
Add reference output tests for JS operations (#1894)
* 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
2019-12-04 12:01:39 -06:00
|
|
|
if (realloc === undefined) {{
|
|
|
|
const buf = cachedTextEncoder.encode(arg);
|
|
|
|
const ptr = malloc(buf.length);
|
|
|
|
{mem}().subarray(ptr, ptr + buf.length).set(buf);
|
|
|
|
WASM_VECTOR_LEN = buf.length;
|
|
|
|
return ptr;
|
|
|
|
}}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
let len = arg.length;
|
|
|
|
let ptr = malloc(len);
|
2019-04-17 18:14:53 +01:00
|
|
|
|
Add reference output tests for JS operations (#1894)
* 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
2019-12-04 12:01:39 -06:00
|
|
|
const mem = {mem}();
|
2019-02-20 08:39:46 -08:00
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
let offset = 0;
|
2019-08-24 19:41:04 +02:00
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
for (; offset < len; offset++) {{
|
|
|
|
const code = arg.charCodeAt(offset);
|
|
|
|
if (code > 0x7F) break;
|
|
|
|
mem[ptr + offset] = code;
|
|
|
|
}}
|
|
|
|
",
|
Add reference output tests for JS operations (#1894)
* 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
2019-12-04 12:01:39 -06:00
|
|
|
mem = mem,
|
2019-12-03 11:16:44 -06:00
|
|
|
);
|
2019-08-24 19:41:04 +02:00
|
|
|
|
|
|
|
// TODO:
|
|
|
|
// When converting a JS string to UTF-8, the maximum size is `arg.length * 3`,
|
|
|
|
// so we just allocate that. This wastes memory, so we should investigate
|
|
|
|
// looping over the string to calculate the precise size, or perhaps using
|
|
|
|
// `shrink_to_fit` on the Rust side.
|
|
|
|
self.global(&format!(
|
Add reference output tests for JS operations (#1894)
* 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
2019-12-04 12:01:39 -06:00
|
|
|
"function {name}(arg, malloc, realloc) {{
|
2019-12-03 11:16:44 -06:00
|
|
|
{debug}
|
|
|
|
{ascii}
|
2019-08-23 01:06:21 +02:00
|
|
|
if (offset !== len) {{
|
|
|
|
if (offset !== 0) {{
|
|
|
|
arg = arg.slice(offset);
|
|
|
|
}}
|
Add reference output tests for JS operations (#1894)
* 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
2019-12-04 12:01:39 -06:00
|
|
|
ptr = realloc(ptr, len, len = offset + arg.length * 3);
|
2019-12-03 11:16:44 -06:00
|
|
|
const view = {mem}().subarray(ptr + offset, ptr + len);
|
2019-08-24 19:41:04 +02:00
|
|
|
const ret = encodeString(arg, view);
|
2019-12-03 11:16:44 -06:00
|
|
|
{debug_end}
|
2019-05-14 14:14:34 +01:00
|
|
|
offset += ret.written;
|
2019-02-20 08:39:46 -08:00
|
|
|
}}
|
2019-08-24 19:41:04 +02:00
|
|
|
|
2019-04-17 18:14:53 +01:00
|
|
|
WASM_VECTOR_LEN = offset;
|
2019-02-20 08:39:46 -08:00
|
|
|
return ptr;
|
2019-08-24 19:41:04 +02:00
|
|
|
}}",
|
2019-12-03 11:16:44 -06:00
|
|
|
name = ret,
|
|
|
|
debug = debug,
|
|
|
|
ascii = encode_as_ascii,
|
|
|
|
mem = mem,
|
|
|
|
debug_end = if self.config.debug {
|
2019-11-06 18:12:47 +01:00
|
|
|
"if (ret.read !== arg.length) throw new Error('failed to pass whole string');"
|
2019-05-13 08:12:32 -07:00
|
|
|
} else {
|
|
|
|
""
|
|
|
|
},
|
2019-08-24 19:41:04 +02:00
|
|
|
));
|
2019-02-28 14:57:55 -08:00
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
Ok(ret)
|
2018-01-29 21:20:38 -08:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_pass_array8_to_wasm(&mut self, memory: MemoryId) -> Result<MemView, Error> {
|
|
|
|
let view = self.expose_uint8_memory(memory);
|
|
|
|
self.pass_array_to_wasm("passArray8ToWasm", view, 1)
|
2018-02-16 18:58:37 -08:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_pass_array16_to_wasm(&mut self, memory: MemoryId) -> Result<MemView, Error> {
|
|
|
|
let view = self.expose_uint16_memory(memory);
|
|
|
|
self.pass_array_to_wasm("passArray16ToWasm", view, 2)
|
2018-02-16 18:58:37 -08:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_pass_array32_to_wasm(&mut self, memory: MemoryId) -> Result<MemView, Error> {
|
|
|
|
let view = self.expose_uint32_memory(memory);
|
|
|
|
self.pass_array_to_wasm("passArray32ToWasm", view, 4)
|
2018-05-05 14:10:25 -07:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_pass_array64_to_wasm(&mut self, memory: MemoryId) -> Result<MemView, Error> {
|
|
|
|
let view = self.expose_uint64_memory(memory);
|
|
|
|
self.pass_array_to_wasm("passArray64ToWasm", view, 8)
|
2018-02-16 18:58:37 -08:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_pass_array_f32_to_wasm(&mut self, memory: MemoryId) -> Result<MemView, Error> {
|
|
|
|
let view = self.expose_f32_memory(memory);
|
|
|
|
self.pass_array_to_wasm("passArrayF32ToWasm", view, 4)
|
2018-02-16 18:58:37 -08:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_pass_array_f64_to_wasm(&mut self, memory: MemoryId) -> Result<MemView, Error> {
|
|
|
|
let view = self.expose_f64_memory(memory);
|
|
|
|
self.pass_array_to_wasm("passArrayF64ToWasm", view, 8)
|
2018-05-05 14:10:25 -07:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_pass_array_jsvalue_to_wasm(&mut self, memory: MemoryId) -> Result<MemView, Error> {
|
|
|
|
let mem = self.expose_uint32_memory(memory);
|
|
|
|
let ret = MemView {
|
|
|
|
name: "passArrayJsValueToWasm",
|
|
|
|
num: mem.num,
|
|
|
|
};
|
|
|
|
if !self.should_write_global(ret.to_string()) {
|
|
|
|
return Ok(ret);
|
2018-07-20 13:47:49 -05:00
|
|
|
}
|
2019-04-25 19:21:13 -07:00
|
|
|
self.expose_wasm_vector_len();
|
2019-12-03 11:16:44 -06:00
|
|
|
match (self.aux.anyref_table, self.aux.anyref_alloc) {
|
|
|
|
(Some(table), Some(alloc)) => {
|
|
|
|
// TODO: using `addToAnyrefTable` goes back and forth between wasm
|
|
|
|
// and JS a lot, we should have a bulk operation for this.
|
|
|
|
let add = self.expose_add_to_anyref_table(table, alloc)?;
|
|
|
|
self.global(&format!(
|
|
|
|
"
|
|
|
|
function {}(array, malloc) {{
|
|
|
|
const ptr = malloc(array.length * 4);
|
|
|
|
const mem = {}();
|
|
|
|
for (let i = 0; i < array.length; i++) {{
|
|
|
|
mem[ptr / 4 + i] = {}(array[i]);
|
|
|
|
}}
|
|
|
|
WASM_VECTOR_LEN = array.length;
|
|
|
|
return ptr;
|
|
|
|
}}
|
|
|
|
",
|
|
|
|
ret, mem, add,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
self.expose_add_heap_object();
|
|
|
|
self.global(&format!(
|
|
|
|
"
|
|
|
|
function {}(array, malloc) {{
|
|
|
|
const ptr = malloc(array.length * 4);
|
|
|
|
const mem = {}();
|
|
|
|
for (let i = 0; i < array.length; i++) {{
|
|
|
|
mem[ptr / 4 + i] = addHeapObject(array[i]);
|
|
|
|
}}
|
|
|
|
WASM_VECTOR_LEN = array.length;
|
|
|
|
return ptr;
|
|
|
|
}}
|
|
|
|
",
|
|
|
|
ret, mem,
|
|
|
|
));
|
|
|
|
}
|
2018-10-18 08:43:36 -07:00
|
|
|
}
|
2019-12-03 11:16:44 -06:00
|
|
|
Ok(ret)
|
2018-07-20 13:47:49 -05:00
|
|
|
}
|
|
|
|
|
2018-06-27 22:42:34 -07:00
|
|
|
fn pass_array_to_wasm(
|
|
|
|
&mut self,
|
|
|
|
name: &'static str,
|
2019-12-03 11:16:44 -06:00
|
|
|
view: MemView,
|
2018-06-27 22:42:34 -07:00
|
|
|
size: usize,
|
2019-12-03 11:16:44 -06:00
|
|
|
) -> Result<MemView, Error> {
|
|
|
|
let ret = MemView {
|
|
|
|
name,
|
|
|
|
num: view.num,
|
|
|
|
};
|
|
|
|
if !self.should_write_global(ret.to_string()) {
|
|
|
|
return Ok(ret);
|
2018-02-16 18:58:37 -08:00
|
|
|
}
|
2018-11-13 08:10:05 -08:00
|
|
|
self.expose_wasm_vector_len();
|
2018-06-27 22:42:34 -07:00
|
|
|
self.global(&format!(
|
|
|
|
"
|
2019-12-03 11:16:44 -06:00
|
|
|
function {}(arg, malloc) {{
|
|
|
|
const ptr = malloc(arg.length * {size});
|
2018-05-05 14:10:25 -07:00
|
|
|
{}().set(arg, ptr / {size});
|
2018-11-13 08:10:05 -08:00
|
|
|
WASM_VECTOR_LEN = arg.length;
|
|
|
|
return ptr;
|
2018-02-16 18:58:37 -08:00
|
|
|
}}
|
2018-06-15 23:39:51 -07:00
|
|
|
",
|
2019-12-03 11:16:44 -06:00
|
|
|
ret,
|
|
|
|
view,
|
2018-06-27 22:42:34 -07:00
|
|
|
size = size
|
|
|
|
));
|
2019-12-03 11:16:44 -06:00
|
|
|
Ok(ret)
|
2018-02-16 18:58:37 -08:00
|
|
|
}
|
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
fn expose_text_encoder(&mut self) -> Result<(), Error> {
|
2019-01-14 13:09:05 -08:00
|
|
|
if !self.should_write_global("text_encoder") {
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
return Ok(());
|
2018-02-06 15:52:44 -08:00
|
|
|
}
|
2019-08-23 05:00:49 +02:00
|
|
|
self.expose_text_processor("TextEncoder", "('utf-8')")
|
2018-02-05 16:39:11 -08:00
|
|
|
}
|
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
fn expose_text_decoder(&mut self) -> Result<(), Error> {
|
2019-01-14 13:09:05 -08:00
|
|
|
if !self.should_write_global("text_decoder") {
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
return Ok(());
|
2018-02-05 16:39:11 -08:00
|
|
|
}
|
2019-10-23 00:26:28 +02:00
|
|
|
|
2019-08-23 05:00:49 +02:00
|
|
|
// `ignoreBOM` is needed so that the BOM will be preserved when sending a string from Rust to JS
|
|
|
|
// `fatal` is needed to catch any weird encoding bugs when sending a string from Rust to JS
|
|
|
|
self.expose_text_processor("TextDecoder", "('utf-8', { ignoreBOM: true, fatal: true })")?;
|
2019-10-23 00:26:28 +02:00
|
|
|
|
|
|
|
// This is needed to workaround a bug in Safari
|
|
|
|
// See: https://github.com/rustwasm/wasm-bindgen/issues/1825
|
|
|
|
self.global("cachedTextDecoder.decode();");
|
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
Ok(())
|
2018-09-28 20:01:46 -07:00
|
|
|
}
|
|
|
|
|
2019-08-23 05:00:49 +02:00
|
|
|
fn expose_text_processor(&mut self, s: &str, args: &str) -> Result<(), Error> {
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
if self.config.mode.nodejs() {
|
|
|
|
let name = self.import_name(&JsImport {
|
|
|
|
name: JsImportName::Module {
|
|
|
|
module: "util".to_string(),
|
|
|
|
name: s.to_string(),
|
|
|
|
},
|
|
|
|
fields: Vec::new(),
|
|
|
|
})?;
|
2019-08-23 05:00:49 +02:00
|
|
|
self.global(&format!("let cached{} = new {}{};", s, name, args));
|
2019-02-25 11:11:30 -08:00
|
|
|
} else if !self.config.mode.always_run_in_browser() {
|
2018-11-27 12:07:59 -08:00
|
|
|
self.global(&format!(
|
|
|
|
"
|
2018-09-28 20:01:46 -07:00
|
|
|
const l{0} = typeof {0} === 'undefined' ? \
|
2020-04-29 20:59:49 +02:00
|
|
|
(0, module.require)('util').{0} : {0};\
|
2018-11-27 12:07:59 -08:00
|
|
|
",
|
|
|
|
s
|
|
|
|
));
|
2019-08-23 05:00:49 +02:00
|
|
|
self.global(&format!("let cached{0} = new l{0}{1};", s, args));
|
2018-10-03 15:54:57 -07:00
|
|
|
} else {
|
2019-08-23 05:00:49 +02:00
|
|
|
self.global(&format!("let cached{0} = new {0}{1};", s, args));
|
2018-03-28 07:37:56 -07:00
|
|
|
}
|
2019-08-23 05:00:49 +02:00
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
Ok(())
|
2018-02-06 15:52:44 -08:00
|
|
|
}
|
2018-02-05 16:39:11 -08:00
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_get_string_from_wasm(&mut self, memory: MemoryId) -> Result<MemView, Error> {
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
self.expose_text_decoder()?;
|
2019-12-03 11:16:44 -06:00
|
|
|
let mem = self.expose_uint8_memory(memory);
|
|
|
|
let ret = MemView {
|
|
|
|
name: "getStringFromWasm",
|
|
|
|
num: mem.num,
|
|
|
|
};
|
|
|
|
|
|
|
|
if !self.should_write_global(ret.to_string()) {
|
|
|
|
return Ok(ret);
|
|
|
|
}
|
2018-08-19 21:33:42 -07:00
|
|
|
|
|
|
|
// Typically we try to give a raw view of memory out to `TextDecoder` to
|
|
|
|
// avoid copying too much data. If, however, a `SharedArrayBuffer` is
|
|
|
|
// being used it looks like that is rejected by `TextDecoder` or
|
|
|
|
// otherwise doesn't work with it. When we detect a shared situation we
|
|
|
|
// use `slice` which creates a new array instead of `subarray` which
|
|
|
|
// creates just a view. That way in shared mode we copy more data but in
|
|
|
|
// non-shared mode there's no need to copy the data except for the
|
|
|
|
// string itself.
|
2019-12-03 11:16:44 -06:00
|
|
|
let is_shared = self.module.memories.get(memory).shared;
|
2018-08-19 21:33:42 -07:00
|
|
|
let method = if is_shared { "slice" } else { "subarray" };
|
|
|
|
|
2018-09-26 08:26:00 -07:00
|
|
|
self.global(&format!(
|
|
|
|
"
|
2019-12-03 11:16:44 -06:00
|
|
|
function {}(ptr, len) {{
|
|
|
|
return cachedTextDecoder.decode({}().{}(ptr, ptr + len));
|
2018-08-19 21:33:42 -07:00
|
|
|
}}
|
2019-12-03 11:16:44 -06:00
|
|
|
",
|
|
|
|
ret, mem, method
|
2018-09-26 08:26:00 -07:00
|
|
|
));
|
2019-12-03 11:16:44 -06:00
|
|
|
Ok(ret)
|
2018-02-05 16:39:11 -08:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_get_cached_string_from_wasm(&mut self, memory: MemoryId) -> Result<MemView, Error> {
|
2019-07-16 23:03:18 +02:00
|
|
|
self.expose_get_object();
|
2019-12-03 11:16:44 -06:00
|
|
|
let get = self.expose_get_string_from_wasm(memory)?;
|
|
|
|
let ret = MemView {
|
|
|
|
name: "getCachedStringFromWasm",
|
|
|
|
num: get.num,
|
|
|
|
};
|
|
|
|
|
|
|
|
if !self.should_write_global(ret.to_string()) {
|
|
|
|
return Ok(ret);
|
|
|
|
}
|
2019-07-16 23:03:18 +02:00
|
|
|
|
2019-07-18 00:11:40 +02:00
|
|
|
// This has support for both `&str` and `Option<&str>`.
|
|
|
|
//
|
|
|
|
// If `ptr` is not `0` then we know that it's a `&str` or `Some(&str)`, so we just decode it.
|
|
|
|
//
|
|
|
|
// If `ptr` is `0` then the `len` is a pointer to the cached `JsValue`, so we return that.
|
|
|
|
//
|
|
|
|
// If `ptr` and `len` are both `0` then that means it's `None`, in that case we rely upon
|
|
|
|
// the fact that `getObject(0)` is guaranteed to be `undefined`.
|
2019-12-03 11:16:44 -06:00
|
|
|
self.global(&format!(
|
Support emitting direct imports in wasm files
Support was previously (re-)added in #1654 for importing direct JS
values into a WebAssembly module by completely skipping JS shim
generation. This commit takes that PR one step further by *also*
embedding a direct import in the wasm file, where supported. The wasm
file currently largely just imports from the JS shim file that we
generate, but this allows it to directly improt from ES modules where
supported and where possible. Note that like #1654 this only happens
when the function signature doesn't actually require any conversions to
happen in JS (such as handling closures).
For imports from ES modules, local snippets, or inline JS they'll all
have their import directives directly embedded into the final
WebAssembly binary without any shims necessary to hook it all up. For
imports from the global namespace or possibly vendor-prefixed items
these still unconditionally require an import shim to be generated
because there's no way to describe that import in an ES-friendly way
(yet).
There's a few consequences of this commit which are also worth noting:
* The logic in `wasm-bindgen` where it gracefully handles (to some
degree) not-defined items now only is guaranteed to be applied to the
global namespace. If you import from a module, it'll be an
instantiation time error rather than today's runtime error when the
import is called.
* Handling imports in the wasm module not registered with
`#[wasm_bindgen]` has become more strict. Previously these imports
were basically ignored, leaving them up for interpretation depending
on the output format. The changes for each output target are:
* `bundler` - not much has changed here. Previously these ignored
imports would have been treated as ES module imports, and after this
commit there might just be some more of these imports for bundlers
to resolve.
* `web` - previously the ignored imports would likely cause
instantiation failures because the import object never actually
included a binding for other imports. After this commit though the
JS glue which instantiates the module now interprets all
unrecognized wasm module imports as ES module imports, emitting an
`import` directive. This matches what we want for the direct import
functionality, and is also largely what we want for modules in
general.
* `nodejs` - previously ignored imports were handled in the
translation shim for Node to generate `require` statements, so they
were actually "correctly handled" sort of with module imports. The
handling of this hasn't changed, and reflects what we want for
direct imports of values where loading a wasm module in Node ends up
translating the module field of each import to a `require`.
* `no-modules` - this is very similar to the `web` target where
previously this didn't really work one way or the other because we'd
never fill in more fields of the import object when instantiating
the module. After this PR though this is a hard-error to have
unrecognized imports from `#[wasm_bindgen]` with the `no-modules`
output type, because we don't know how to handle the imports.
Note that this touches on #1584 and will likely break the current use
case being mentioned there. I think though that this tightening up of
how we handle imports is what we'll want in the long run where
everything is interpreted as modules, and we'll need to figure out
best how wasi fits into this.
This commit is unlikely to have any real major immediate effects. The
goal here is to continue to inch us towards a world where there's less
and less JS glue necessary and `wasm-bindgen` is just a polyfill for web
standards that otherwise all already exist.
Also note that there's no explicitly added tests for this since this is
largely just a refactoring of an internal implementation detail of
`wasm-bindgen`, but the main `wasm` test suite has many instances of
this path being taken, for example having imports like:
(import "tests/wasm/duplicates_a.js" "foo" (func $__wbg_foo_969c253238f136f0 (type 1)))
(import "tests/wasm/duplicates_b.js" "foo" (func $__wbg_foo_027958cb2e320a94 (type 0)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "trivial" (func $__wbg_trivial_75e27c84882af23b (type 1)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "incoming_bool" (func $__wbg_incomingbool_0f2d9f55f73a256f (type 0)))
2019-07-31 11:35:36 -07:00
|
|
|
"
|
2019-12-03 11:16:44 -06:00
|
|
|
function {}(ptr, len) {{
|
|
|
|
if (ptr === 0) {{
|
2019-07-18 00:11:40 +02:00
|
|
|
return getObject(len);
|
2019-12-03 11:16:44 -06:00
|
|
|
}} else {{
|
|
|
|
return {}(ptr, len);
|
|
|
|
}}
|
|
|
|
}}
|
|
|
|
",
|
|
|
|
ret, get,
|
|
|
|
));
|
|
|
|
Ok(ret)
|
2019-07-16 23:03:18 +02:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_get_array_js_value_from_wasm(&mut self, memory: MemoryId) -> Result<MemView, Error> {
|
|
|
|
let mem = self.expose_uint32_memory(memory);
|
|
|
|
let ret = MemView {
|
|
|
|
name: "getArrayJsValueFromWasm",
|
|
|
|
num: mem.num,
|
|
|
|
};
|
|
|
|
if !self.should_write_global(ret.to_string()) {
|
|
|
|
return Ok(ret);
|
2018-02-28 10:56:56 +01:00
|
|
|
}
|
2019-12-03 11:16:44 -06:00
|
|
|
match (self.aux.anyref_table, self.aux.anyref_drop_slice) {
|
|
|
|
(Some(table), Some(drop)) => {
|
|
|
|
let table = self.export_name_of(table);
|
|
|
|
let drop = self.export_name_of(drop);
|
|
|
|
self.global(&format!(
|
|
|
|
"
|
|
|
|
function {}(ptr, len) {{
|
|
|
|
const mem = {}();
|
|
|
|
const slice = mem.subarray(ptr / 4, ptr / 4 + len);
|
|
|
|
const result = [];
|
|
|
|
for (let i = 0; i < slice.length; i++) {{
|
|
|
|
result.push(wasm.{}.get(slice[i]));
|
|
|
|
}}
|
|
|
|
wasm.{}(ptr, len);
|
|
|
|
return result;
|
|
|
|
}}
|
|
|
|
",
|
|
|
|
ret, mem, table, drop,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
self.expose_take_object();
|
|
|
|
self.global(&format!(
|
|
|
|
"
|
|
|
|
function {}(ptr, len) {{
|
|
|
|
const mem = {}();
|
|
|
|
const slice = mem.subarray(ptr / 4, ptr / 4 + len);
|
|
|
|
const result = [];
|
|
|
|
for (let i = 0; i < slice.length; i++) {{
|
|
|
|
result.push(takeObject(slice[i]));
|
|
|
|
}}
|
|
|
|
return result;
|
|
|
|
}}
|
|
|
|
",
|
|
|
|
ret, mem,
|
|
|
|
));
|
|
|
|
}
|
2018-10-18 08:43:36 -07:00
|
|
|
}
|
2019-12-03 11:16:44 -06:00
|
|
|
Ok(ret)
|
2018-02-28 10:56:56 +01:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_get_array_i8_from_wasm(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
let view = self.expose_int8_memory(memory);
|
|
|
|
self.arrayget("getArrayI8FromWasm", view, 1)
|
2018-02-16 18:58:37 -08:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_get_array_u8_from_wasm(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
let view = self.expose_uint8_memory(memory);
|
|
|
|
self.arrayget("getArrayU8FromWasm", view, 1)
|
2018-02-16 18:58:37 -08:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_get_clamped_array_u8_from_wasm(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
let view = self.expose_clamped_uint8_memory(memory);
|
|
|
|
self.arrayget("getClampedArrayU8FromWasm", view, 1)
|
2018-09-24 13:49:12 -07:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_get_array_i16_from_wasm(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
let view = self.expose_int16_memory(memory);
|
|
|
|
self.arrayget("getArrayI16FromWasm", view, 2)
|
2018-02-16 18:58:37 -08:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_get_array_u16_from_wasm(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
let view = self.expose_uint16_memory(memory);
|
|
|
|
self.arrayget("getArrayU16FromWasm", view, 2)
|
2018-02-16 18:58:37 -08:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_get_array_i32_from_wasm(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
let view = self.expose_int32_memory(memory);
|
|
|
|
self.arrayget("getArrayI32FromWasm", view, 4)
|
2018-02-16 18:58:37 -08:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_get_array_u32_from_wasm(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
let view = self.expose_uint32_memory(memory);
|
|
|
|
self.arrayget("getArrayU32FromWasm", view, 4)
|
2018-02-16 18:58:37 -08:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_get_array_i64_from_wasm(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
let view = self.expose_int64_memory(memory);
|
|
|
|
self.arrayget("getArrayI64FromWasm", view, 8)
|
2018-05-05 14:10:25 -07:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_get_array_u64_from_wasm(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
let view = self.expose_uint64_memory(memory);
|
|
|
|
self.arrayget("getArrayU64FromWasm", view, 8)
|
2018-05-05 14:10:25 -07:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_get_array_f32_from_wasm(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
let view = self.expose_f32_memory(memory);
|
|
|
|
self.arrayget("getArrayF32FromWasm", view, 4)
|
2018-02-16 18:58:37 -08:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_get_array_f64_from_wasm(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
let view = self.expose_f64_memory(memory);
|
|
|
|
self.arrayget("getArrayF64FromWasm", view, 8)
|
2018-05-01 10:06:35 -07:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn arrayget(&mut self, name: &'static str, view: MemView, size: usize) -> MemView {
|
|
|
|
let ret = MemView {
|
|
|
|
name,
|
|
|
|
num: view.num,
|
|
|
|
};
|
2019-01-14 13:09:05 -08:00
|
|
|
if !self.should_write_global(name) {
|
2019-12-03 11:16:44 -06:00
|
|
|
return ret;
|
2018-02-16 18:58:37 -08:00
|
|
|
}
|
2018-06-27 22:42:34 -07:00
|
|
|
self.global(&format!(
|
|
|
|
"
|
2018-05-01 10:06:35 -07:00
|
|
|
function {name}(ptr, len) {{
|
|
|
|
return {mem}().subarray(ptr / {size}, ptr / {size} + len);
|
2018-02-16 18:58:37 -08:00
|
|
|
}}
|
2018-06-15 23:39:51 -07:00
|
|
|
",
|
2019-12-03 11:16:44 -06:00
|
|
|
name = ret,
|
|
|
|
mem = view,
|
2018-05-01 10:06:35 -07:00
|
|
|
size = size,
|
|
|
|
));
|
2019-12-03 11:16:44 -06:00
|
|
|
return ret;
|
2018-05-01 10:06:35 -07:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_node_buffer_memory(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
self.memview("getNodeBufferMemory", "Buffer.from", memory)
|
2019-03-25 17:42:10 +00:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_int8_memory(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
self.memview("getInt8Memory", "new Int8Array", memory)
|
2018-02-16 18:58:37 -08:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_uint8_memory(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
self.memview("getUint8Memory", "new Uint8Array", memory)
|
2018-05-01 10:06:35 -07:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_clamped_uint8_memory(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
self.memview("getUint8ClampedMemory", "new Uint8ClampedArray", memory)
|
2018-09-24 13:49:12 -07:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_int16_memory(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
self.memview("getInt16Memory", "new Int16Array", memory)
|
2018-02-06 08:58:15 -08:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_uint16_memory(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
self.memview("getUint16Memory", "new Uint16Array", memory)
|
2018-05-01 10:06:35 -07:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_int32_memory(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
self.memview("getInt32Memory", "new Int32Array", memory)
|
2018-02-16 18:58:37 -08:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_uint32_memory(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
self.memview("getUint32Memory", "new Uint32Array", memory)
|
2018-05-01 10:06:35 -07:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_int64_memory(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
self.memview("getInt64Memory", "new BigInt64Array", memory)
|
2018-05-05 14:10:25 -07:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_uint64_memory(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
self.memview("getUint64Memory", "new BigUint64Array", memory)
|
2018-05-05 14:10:25 -07:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_f32_memory(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
self.memview("getFloat32Memory", "new Float32Array", memory)
|
2018-05-01 10:06:35 -07:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_f64_memory(&mut self, memory: MemoryId) -> MemView {
|
|
|
|
self.memview("getFloat64Memory", "new Float64Array", memory)
|
2018-05-01 10:06:35 -07:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn memview_function(&mut self, t: VectorKind, memory: MemoryId) -> MemView {
|
2018-05-01 10:06:35 -07:00
|
|
|
match t {
|
2019-12-03 11:16:44 -06:00
|
|
|
VectorKind::String => self.expose_uint8_memory(memory),
|
|
|
|
VectorKind::I8 => self.expose_int8_memory(memory),
|
|
|
|
VectorKind::U8 => self.expose_uint8_memory(memory),
|
|
|
|
VectorKind::ClampedU8 => self.expose_clamped_uint8_memory(memory),
|
|
|
|
VectorKind::I16 => self.expose_int16_memory(memory),
|
|
|
|
VectorKind::U16 => self.expose_uint16_memory(memory),
|
|
|
|
VectorKind::I32 => self.expose_int32_memory(memory),
|
|
|
|
VectorKind::U32 => self.expose_uint32_memory(memory),
|
|
|
|
VectorKind::I64 => self.expose_int64_memory(memory),
|
|
|
|
VectorKind::U64 => self.expose_uint64_memory(memory),
|
|
|
|
VectorKind::F32 => self.expose_f32_memory(memory),
|
|
|
|
VectorKind::F64 => self.expose_f64_memory(memory),
|
|
|
|
VectorKind::Anyref => self.expose_uint32_memory(memory),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn memview(&mut self, name: &'static str, js: &str, memory: walrus::MemoryId) -> MemView {
|
|
|
|
let view = self.memview_memory(name, memory);
|
|
|
|
if !self.should_write_global(name.to_string()) {
|
|
|
|
return view;
|
|
|
|
}
|
|
|
|
let mem = self.export_name_of(memory);
|
2018-06-27 22:42:34 -07:00
|
|
|
self.global(&format!(
|
|
|
|
"
|
2018-05-01 10:06:35 -07:00
|
|
|
let cache{name} = null;
|
|
|
|
function {name}() {{
|
2019-12-03 11:16:44 -06:00
|
|
|
if (cache{name} === null || cache{name}.buffer !== wasm.{mem}.buffer) {{
|
|
|
|
cache{name} = {js}(wasm.{mem}.buffer);
|
2018-06-15 12:55:37 -05:00
|
|
|
}}
|
2018-05-01 10:06:35 -07:00
|
|
|
return cache{name};
|
2018-01-29 21:20:38 -08:00
|
|
|
}}
|
2018-06-15 23:39:51 -07:00
|
|
|
",
|
2019-12-03 11:16:44 -06:00
|
|
|
name = view,
|
2018-05-01 10:06:35 -07:00
|
|
|
js = js,
|
2018-08-20 23:33:29 -07:00
|
|
|
mem = mem,
|
2018-05-01 10:06:35 -07:00
|
|
|
));
|
2019-12-03 11:16:44 -06:00
|
|
|
return view;
|
|
|
|
}
|
|
|
|
|
|
|
|
fn memview_memory(&mut self, name: &'static str, memory: walrus::MemoryId) -> MemView {
|
|
|
|
let next = self.memory_indices.len();
|
|
|
|
let num = *self.memory_indices.entry(memory).or_insert(next);
|
|
|
|
MemView { name, num }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn memview_table(&mut self, name: &'static str, table: walrus::TableId) -> MemView {
|
|
|
|
let next = self.table_indices.len();
|
|
|
|
let num = *self.table_indices.entry(table).or_insert(next);
|
|
|
|
MemView { name, num }
|
2018-01-29 21:20:38 -08:00
|
|
|
}
|
|
|
|
|
2018-02-06 15:52:44 -08:00
|
|
|
fn expose_assert_class(&mut self) {
|
2019-01-14 13:09:05 -08:00
|
|
|
if !self.should_write_global("assert_class") {
|
2018-04-07 13:06:36 +05:45
|
|
|
return;
|
2018-01-29 21:20:38 -08:00
|
|
|
}
|
2018-06-15 23:39:51 -07:00
|
|
|
self.global(
|
2018-06-27 22:42:34 -07:00
|
|
|
"
|
2018-06-15 23:39:51 -07:00
|
|
|
function _assertClass(instance, klass) {
|
|
|
|
if (!(instance instanceof klass)) {
|
|
|
|
throw new Error(`expected instance of ${klass.name}`);
|
|
|
|
}
|
2018-02-06 15:52:44 -08:00
|
|
|
return instance.ptr;
|
2018-06-15 23:39:51 -07:00
|
|
|
}
|
|
|
|
",
|
|
|
|
);
|
2018-01-29 21:20:38 -08:00
|
|
|
}
|
|
|
|
|
2018-11-29 18:15:36 -08:00
|
|
|
fn expose_global_stack_pointer(&mut self) {
|
2019-01-14 13:09:05 -08:00
|
|
|
if !self.should_write_global("stack_pointer") {
|
2018-11-29 18:15:36 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
self.global(&format!("let stack_pointer = {};", INITIAL_HEAP_OFFSET));
|
|
|
|
}
|
|
|
|
|
2018-02-06 15:52:44 -08:00
|
|
|
fn expose_borrowed_objects(&mut self) {
|
2019-01-14 13:09:05 -08:00
|
|
|
if !self.should_write_global("borrowed_objects") {
|
2018-04-07 13:06:36 +05:45
|
|
|
return;
|
2018-01-29 21:20:38 -08:00
|
|
|
}
|
2018-11-29 18:15:36 -08:00
|
|
|
self.expose_global_heap();
|
|
|
|
self.expose_global_stack_pointer();
|
|
|
|
// Our `stack_pointer` points to where we should start writing stack
|
|
|
|
// objects, and the `stack_pointer` is incremented in a `finally` block
|
|
|
|
// after executing this. Once we've reserved stack space we write the
|
|
|
|
// value. Eventually underflow will throw an exception, but JS sort of
|
|
|
|
// just handles it today...
|
2018-06-15 23:39:51 -07:00
|
|
|
self.global(
|
2018-06-27 22:42:34 -07:00
|
|
|
"
|
2018-06-15 23:39:51 -07:00
|
|
|
function addBorrowedObject(obj) {
|
2018-11-29 18:15:36 -08:00
|
|
|
if (stack_pointer == 1) throw new Error('out of js stack');
|
|
|
|
heap[--stack_pointer] = obj;
|
|
|
|
return stack_pointer;
|
2018-06-15 23:39:51 -07:00
|
|
|
}
|
2018-11-30 13:04:05 -08:00
|
|
|
",
|
2018-06-15 23:39:51 -07:00
|
|
|
);
|
2018-01-29 21:20:38 -08:00
|
|
|
}
|
|
|
|
|
2018-02-06 15:52:44 -08:00
|
|
|
fn expose_take_object(&mut self) {
|
2019-01-14 13:09:05 -08:00
|
|
|
if !self.should_write_global("take_object") {
|
2018-04-07 13:06:36 +05:45
|
|
|
return;
|
2018-01-29 21:20:38 -08:00
|
|
|
}
|
2018-02-06 15:52:44 -08:00
|
|
|
self.expose_get_object();
|
|
|
|
self.expose_drop_ref();
|
2018-06-15 23:39:51 -07:00
|
|
|
self.global(
|
2018-06-27 22:42:34 -07:00
|
|
|
"
|
2018-06-15 23:39:51 -07:00
|
|
|
function takeObject(idx) {
|
2018-02-06 15:52:44 -08:00
|
|
|
const ret = getObject(idx);
|
2018-11-29 18:15:36 -08:00
|
|
|
dropObject(idx);
|
2018-02-06 15:52:44 -08:00
|
|
|
return ret;
|
2018-06-15 23:39:51 -07:00
|
|
|
}
|
|
|
|
",
|
|
|
|
);
|
2018-01-29 21:20:38 -08:00
|
|
|
}
|
|
|
|
|
2018-02-06 15:52:44 -08:00
|
|
|
fn expose_add_heap_object(&mut self) {
|
2019-01-14 13:09:05 -08:00
|
|
|
if !self.should_write_global("add_heap_object") {
|
2018-04-07 13:06:36 +05:45
|
|
|
return;
|
2018-01-29 21:20:38 -08:00
|
|
|
}
|
2018-11-29 18:15:36 -08:00
|
|
|
self.expose_global_heap();
|
|
|
|
self.expose_global_heap_next();
|
|
|
|
let set_heap_next = if self.config.debug {
|
2018-06-27 22:42:34 -07:00
|
|
|
String::from(
|
|
|
|
"
|
2018-11-29 18:15:36 -08:00
|
|
|
if (typeof(heap_next) !== 'number') throw new Error('corrupt heap');
|
2018-06-15 23:39:51 -07:00
|
|
|
",
|
2018-06-27 22:42:34 -07:00
|
|
|
)
|
2018-01-29 21:20:38 -08:00
|
|
|
} else {
|
2018-11-29 18:15:36 -08:00
|
|
|
String::new()
|
2018-01-29 21:20:38 -08:00
|
|
|
};
|
2018-11-29 18:15:36 -08:00
|
|
|
|
|
|
|
// Allocating a slot on the heap first goes through the linked list
|
|
|
|
// (starting at `heap_next`). Once that linked list is exhausted we'll
|
|
|
|
// be pointing beyond the end of the array, at which point we'll reserve
|
|
|
|
// one more slot and use that.
|
2018-06-27 22:42:34 -07:00
|
|
|
self.global(&format!(
|
|
|
|
"
|
2018-02-06 15:52:44 -08:00
|
|
|
function addHeapObject(obj) {{
|
2018-11-29 18:15:36 -08:00
|
|
|
if (heap_next === heap.length) heap.push(heap.length + 1);
|
|
|
|
const idx = heap_next;
|
|
|
|
heap_next = heap[idx];
|
2018-02-06 15:52:44 -08:00
|
|
|
{}
|
2018-11-29 18:15:36 -08:00
|
|
|
heap[idx] = obj;
|
|
|
|
return idx;
|
2018-01-29 21:20:38 -08:00
|
|
|
}}
|
2018-06-15 23:39:51 -07:00
|
|
|
",
|
2018-11-29 18:15:36 -08:00
|
|
|
set_heap_next
|
2018-06-27 22:42:34 -07:00
|
|
|
));
|
2018-01-29 21:20:38 -08:00
|
|
|
}
|
|
|
|
|
2018-10-18 08:43:36 -07:00
|
|
|
fn expose_handle_error(&mut self) -> Result<(), Error> {
|
2019-02-04 02:08:08 +01:00
|
|
|
if !self.should_write_global("handle_error") {
|
2018-10-18 08:43:36 -07:00
|
|
|
return Ok(());
|
2019-02-04 02:08:08 +01:00
|
|
|
}
|
Add reference output tests for JS operations (#1894)
* 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
2019-12-04 12:01:39 -06:00
|
|
|
let store = self
|
|
|
|
.aux
|
|
|
|
.exn_store
|
|
|
|
.ok_or_else(|| anyhow!("failed to find `__wbindgen_exn_store` intrinsic"))?;
|
|
|
|
let store = self.export_name_of(store);
|
2019-12-03 11:16:44 -06:00
|
|
|
match (self.aux.anyref_table, self.aux.anyref_alloc) {
|
|
|
|
(Some(table), Some(alloc)) => {
|
|
|
|
let add = self.expose_add_to_anyref_table(table, alloc)?;
|
|
|
|
self.global(&format!(
|
|
|
|
"
|
2020-04-22 16:14:00 +02:00
|
|
|
function handleError(f) {{
|
|
|
|
return function () {{
|
|
|
|
try {{
|
|
|
|
return f.apply(this, arguments);
|
|
|
|
|
|
|
|
}} catch (e) {{
|
|
|
|
const idx = {}(e);
|
|
|
|
wasm.{}(idx);
|
|
|
|
}}
|
|
|
|
}};
|
2019-12-03 11:16:44 -06:00
|
|
|
}}
|
|
|
|
",
|
Add reference output tests for JS operations (#1894)
* 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
2019-12-04 12:01:39 -06:00
|
|
|
add, store,
|
2019-12-03 11:16:44 -06:00
|
|
|
));
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
self.expose_add_heap_object();
|
Add reference output tests for JS operations (#1894)
* 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
2019-12-04 12:01:39 -06:00
|
|
|
self.global(&format!(
|
2019-12-03 11:16:44 -06:00
|
|
|
"
|
2020-04-22 16:14:00 +02:00
|
|
|
function handleError(f) {{
|
|
|
|
return function () {{
|
|
|
|
try {{
|
|
|
|
return f.apply(this, arguments);
|
|
|
|
|
|
|
|
}} catch (e) {{
|
|
|
|
wasm.{}(addHeapObject(e));
|
|
|
|
}}
|
|
|
|
}};
|
Add reference output tests for JS operations (#1894)
* 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
2019-12-04 12:01:39 -06:00
|
|
|
}}
|
2019-12-03 11:16:44 -06:00
|
|
|
",
|
Add reference output tests for JS operations (#1894)
* 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
2019-12-04 12:01:39 -06:00
|
|
|
store,
|
|
|
|
));
|
2019-12-03 11:16:44 -06:00
|
|
|
}
|
2018-10-18 08:43:36 -07:00
|
|
|
}
|
|
|
|
Ok(())
|
2019-02-04 02:08:08 +01:00
|
|
|
}
|
|
|
|
|
2019-06-10 07:09:51 -07:00
|
|
|
fn expose_log_error(&mut self) {
|
|
|
|
if !self.should_write_global("log_error") {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
self.global(
|
|
|
|
"\
|
2020-04-22 16:14:00 +02:00
|
|
|
function logError(f) {
|
|
|
|
return function () {
|
2019-06-10 07:09:51 -07:00
|
|
|
try {
|
2020-04-22 16:14:00 +02:00
|
|
|
return f.apply(this, arguments);
|
|
|
|
|
|
|
|
} catch (e) {
|
|
|
|
let error = (function () {
|
|
|
|
try {
|
|
|
|
return e instanceof Error \
|
|
|
|
? `${e.message}\\n\\nStack:\\n${e.stack}` \
|
|
|
|
: e.toString();
|
|
|
|
} catch(_) {
|
|
|
|
return \"<failed to stringify thrown value>\";
|
|
|
|
}
|
|
|
|
}());
|
|
|
|
console.error(\"wasm-bindgen: imported JS function that \
|
|
|
|
was not marked as `catch` threw an error:\", \
|
|
|
|
error);
|
|
|
|
throw e;
|
2019-06-10 07:09:51 -07:00
|
|
|
}
|
2020-04-22 16:14:00 +02:00
|
|
|
};
|
2019-06-10 07:09:51 -07:00
|
|
|
}
|
|
|
|
",
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn pass_to_wasm_function(&mut self, t: VectorKind, memory: MemoryId) -> Result<MemView, Error> {
|
|
|
|
match t {
|
|
|
|
VectorKind::String => self.expose_pass_string_to_wasm(memory),
|
2018-09-24 13:49:12 -07:00
|
|
|
VectorKind::I8 | VectorKind::U8 | VectorKind::ClampedU8 => {
|
2019-12-03 11:16:44 -06:00
|
|
|
self.expose_pass_array8_to_wasm(memory)
|
2018-02-16 18:58:37 -08:00
|
|
|
}
|
2019-12-03 11:16:44 -06:00
|
|
|
VectorKind::U16 | VectorKind::I16 => self.expose_pass_array16_to_wasm(memory),
|
|
|
|
VectorKind::I32 | VectorKind::U32 => self.expose_pass_array32_to_wasm(memory),
|
|
|
|
VectorKind::I64 | VectorKind::U64 => self.expose_pass_array64_to_wasm(memory),
|
|
|
|
VectorKind::F32 => self.expose_pass_array_f32_to_wasm(memory),
|
|
|
|
VectorKind::F64 => self.expose_pass_array_f64_to_wasm(memory),
|
|
|
|
VectorKind::Anyref => self.expose_pass_array_jsvalue_to_wasm(memory),
|
|
|
|
}
|
2018-02-16 18:58:37 -08:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_get_vector_from_wasm(
|
|
|
|
&mut self,
|
|
|
|
ty: VectorKind,
|
|
|
|
memory: MemoryId,
|
|
|
|
) -> Result<MemView, Error> {
|
2018-10-18 08:43:36 -07:00
|
|
|
Ok(match ty {
|
2019-12-03 11:16:44 -06:00
|
|
|
VectorKind::String => self.expose_get_string_from_wasm(memory)?,
|
|
|
|
VectorKind::I8 => self.expose_get_array_i8_from_wasm(memory),
|
|
|
|
VectorKind::U8 => self.expose_get_array_u8_from_wasm(memory),
|
|
|
|
VectorKind::ClampedU8 => self.expose_get_clamped_array_u8_from_wasm(memory),
|
|
|
|
VectorKind::I16 => self.expose_get_array_i16_from_wasm(memory),
|
|
|
|
VectorKind::U16 => self.expose_get_array_u16_from_wasm(memory),
|
|
|
|
VectorKind::I32 => self.expose_get_array_i32_from_wasm(memory),
|
|
|
|
VectorKind::U32 => self.expose_get_array_u32_from_wasm(memory),
|
|
|
|
VectorKind::I64 => self.expose_get_array_i64_from_wasm(memory),
|
|
|
|
VectorKind::U64 => self.expose_get_array_u64_from_wasm(memory),
|
|
|
|
VectorKind::F32 => self.expose_get_array_f32_from_wasm(memory),
|
|
|
|
VectorKind::F64 => self.expose_get_array_f64_from_wasm(memory),
|
|
|
|
VectorKind::Anyref => self.expose_get_array_js_value_from_wasm(memory)?,
|
2018-10-18 08:43:36 -07:00
|
|
|
})
|
2018-02-16 18:58:37 -08:00
|
|
|
}
|
2018-03-31 07:57:47 -07:00
|
|
|
|
2018-04-09 06:16:41 -07:00
|
|
|
fn expose_get_inherited_descriptor(&mut self) {
|
2019-01-14 13:09:05 -08:00
|
|
|
if !self.should_write_global("get_inherited_descriptor") {
|
2018-06-27 22:42:34 -07:00
|
|
|
return;
|
2018-04-09 06:16:41 -07:00
|
|
|
}
|
|
|
|
// It looks like while rare some browsers will move descriptors up the
|
|
|
|
// property chain which runs the risk of breaking wasm-bindgen-generated
|
|
|
|
// code because we're looking for precise descriptor functions rather
|
|
|
|
// than relying on the prototype chain like most "normal JS" projects
|
|
|
|
// do.
|
|
|
|
//
|
|
|
|
// As a result we have a small helper here which will walk the prototype
|
|
|
|
// chain looking for a descriptor. For some more information on this see
|
|
|
|
// #109
|
2018-06-27 22:42:34 -07:00
|
|
|
self.global(
|
|
|
|
"
|
2018-04-09 06:16:41 -07:00
|
|
|
function GetOwnOrInheritedPropertyDescriptor(obj, id) {
|
|
|
|
while (obj) {
|
|
|
|
let desc = Object.getOwnPropertyDescriptor(obj, id);
|
|
|
|
if (desc) return desc;
|
|
|
|
obj = Object.getPrototypeOf(obj);
|
|
|
|
}
|
2019-06-10 07:09:51 -07:00
|
|
|
return {};
|
2018-04-09 06:16:41 -07:00
|
|
|
}
|
2018-06-15 23:39:51 -07:00
|
|
|
",
|
2018-06-27 22:42:34 -07:00
|
|
|
);
|
2018-04-09 06:16:41 -07:00
|
|
|
}
|
2018-04-05 18:30:37 -07:00
|
|
|
|
2018-05-05 14:10:25 -07:00
|
|
|
fn expose_u32_cvt_shim(&mut self) -> &'static str {
|
|
|
|
let name = "u32CvtShim";
|
2019-01-14 13:09:05 -08:00
|
|
|
if !self.should_write_global(name) {
|
2018-06-27 22:42:34 -07:00
|
|
|
return name;
|
2018-05-05 14:10:25 -07:00
|
|
|
}
|
|
|
|
self.global(&format!("const {} = new Uint32Array(2);", name));
|
|
|
|
name
|
|
|
|
}
|
|
|
|
|
|
|
|
fn expose_int64_cvt_shim(&mut self) -> &'static str {
|
|
|
|
let name = "int64CvtShim";
|
2019-01-14 13:09:05 -08:00
|
|
|
if !self.should_write_global(name) {
|
2018-06-27 22:42:34 -07:00
|
|
|
return name;
|
2018-05-05 14:10:25 -07:00
|
|
|
}
|
|
|
|
let n = self.expose_u32_cvt_shim();
|
2018-06-27 22:42:34 -07:00
|
|
|
self.global(&format!(
|
|
|
|
"const {} = new BigInt64Array({}.buffer);",
|
|
|
|
name, n
|
|
|
|
));
|
2018-05-05 14:10:25 -07:00
|
|
|
name
|
|
|
|
}
|
|
|
|
|
|
|
|
fn expose_uint64_cvt_shim(&mut self) -> &'static str {
|
|
|
|
let name = "uint64CvtShim";
|
2019-01-14 13:09:05 -08:00
|
|
|
if !self.should_write_global(name) {
|
2018-06-27 22:42:34 -07:00
|
|
|
return name;
|
2018-05-05 14:10:25 -07:00
|
|
|
}
|
|
|
|
let n = self.expose_u32_cvt_shim();
|
2018-06-27 22:42:34 -07:00
|
|
|
self.global(&format!(
|
|
|
|
"const {} = new BigUint64Array({}.buffer);",
|
|
|
|
name, n
|
|
|
|
));
|
2018-05-05 14:10:25 -07:00
|
|
|
name
|
|
|
|
}
|
|
|
|
|
2018-07-19 14:44:23 -05:00
|
|
|
fn expose_is_like_none(&mut self) {
|
2019-01-14 13:09:05 -08:00
|
|
|
if !self.should_write_global("is_like_none") {
|
2018-09-26 08:26:00 -07:00
|
|
|
return;
|
2018-07-19 14:44:23 -05:00
|
|
|
}
|
2018-09-26 08:26:00 -07:00
|
|
|
self.global(
|
|
|
|
"
|
2018-07-19 14:44:23 -05:00
|
|
|
function isLikeNone(x) {
|
|
|
|
return x === undefined || x === null;
|
|
|
|
}
|
2018-09-26 08:26:00 -07:00
|
|
|
",
|
|
|
|
);
|
2018-07-19 14:44:23 -05:00
|
|
|
}
|
|
|
|
|
2020-02-18 15:37:40 +01:00
|
|
|
fn expose_make_mut_closure(&mut self) -> Result<(), Error> {
|
|
|
|
if !self.should_write_global("make_mut_closure") {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
|
|
|
let table = self.export_function_table()?;
|
|
|
|
|
|
|
|
// For mutable closures they can't be invoked recursively.
|
|
|
|
// To handle that we swap out the `this.a` pointer with zero
|
|
|
|
// while we invoke it. If we finish and the closure wasn't
|
|
|
|
// destroyed, then we put back the pointer so a future
|
|
|
|
// invocation can succeed.
|
|
|
|
self.global(&format!(
|
|
|
|
"
|
|
|
|
function makeMutClosure(arg0, arg1, dtor, f) {{
|
|
|
|
const state = {{ a: arg0, b: arg1, cnt: 1 }};
|
|
|
|
const real = (...args) => {{
|
|
|
|
// First up with a closure we increment the internal reference
|
|
|
|
// count. This ensures that the Rust closure environment won't
|
|
|
|
// be deallocated while we're invoking it.
|
|
|
|
state.cnt++;
|
|
|
|
const a = state.a;
|
|
|
|
state.a = 0;
|
|
|
|
try {{
|
|
|
|
return f(a, state.b, ...args);
|
|
|
|
}} finally {{
|
|
|
|
if (--state.cnt === 0) wasm.{}.get(dtor)(a, state.b);
|
|
|
|
else state.a = a;
|
|
|
|
}}
|
|
|
|
}};
|
|
|
|
real.original = state;
|
|
|
|
return real;
|
|
|
|
}}
|
|
|
|
",
|
|
|
|
table
|
|
|
|
));
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn expose_make_closure(&mut self) -> Result<(), Error> {
|
|
|
|
if !self.should_write_global("make_closure") {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
|
|
|
let table = self.export_function_table()?;
|
|
|
|
|
|
|
|
// For shared closures they can be invoked recursively so we
|
|
|
|
// just immediately pass through `this.a`. If we end up
|
|
|
|
// executing the destructor, however, we clear out the
|
|
|
|
// `this.a` pointer to prevent it being used again the
|
|
|
|
// future.
|
|
|
|
self.global(&format!(
|
|
|
|
"
|
|
|
|
function makeClosure(arg0, arg1, dtor, f) {{
|
|
|
|
const state = {{ a: arg0, b: arg1, cnt: 1 }};
|
|
|
|
const real = (...args) => {{
|
|
|
|
// First up with a closure we increment the internal reference
|
|
|
|
// count. This ensures that the Rust closure environment won't
|
|
|
|
// be deallocated while we're invoking it.
|
|
|
|
state.cnt++;
|
|
|
|
try {{
|
|
|
|
return f(state.a, state.b, ...args);
|
|
|
|
}} finally {{
|
|
|
|
if (--state.cnt === 0) {{
|
|
|
|
wasm.{}.get(dtor)(state.a, state.b);
|
|
|
|
state.a = 0;
|
|
|
|
}}
|
|
|
|
}}
|
|
|
|
}};
|
|
|
|
real.original = state;
|
|
|
|
return real;
|
|
|
|
}}
|
|
|
|
",
|
|
|
|
table
|
|
|
|
));
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2018-04-14 09:37:49 -07:00
|
|
|
fn global(&mut self, s: &str) {
|
2018-04-16 13:31:56 -07:00
|
|
|
let s = s.trim();
|
|
|
|
|
|
|
|
// Ensure a blank line between adjacent items, and ensure everything is
|
|
|
|
// terminated with a newline.
|
2018-06-15 11:20:56 -05:00
|
|
|
while !self.globals.ends_with("\n\n\n") && !self.globals.ends_with("*/\n") {
|
2018-04-14 09:37:49 -07:00
|
|
|
self.globals.push_str("\n");
|
|
|
|
}
|
2018-04-16 13:31:56 -07:00
|
|
|
self.globals.push_str(s);
|
|
|
|
self.globals.push_str("\n");
|
2018-04-14 09:37:49 -07:00
|
|
|
}
|
2018-04-25 07:26:33 -07:00
|
|
|
|
2019-04-30 10:26:03 -03:00
|
|
|
fn require_class_wrap(&mut self, name: &str) {
|
|
|
|
require_class(&mut self.exported_classes, name).wrap_needed = true;
|
2018-09-21 15:45:31 -07:00
|
|
|
}
|
2018-11-12 11:59:13 -08:00
|
|
|
|
2020-04-15 21:28:29 +08:00
|
|
|
fn add_module_import(&mut self, module: String, name: &str, actual: &str) {
|
|
|
|
let rename = if name == actual {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(actual.to_string())
|
|
|
|
};
|
|
|
|
self.js_imports
|
|
|
|
.entry(module)
|
|
|
|
.or_insert(Vec::new())
|
|
|
|
.push((name.to_string(), rename));
|
|
|
|
}
|
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
fn import_name(&mut self, import: &JsImport) -> Result<String, Error> {
|
|
|
|
if let Some(name) = self.imported_names.get(&import.name) {
|
|
|
|
let mut name = name.clone();
|
|
|
|
for field in import.fields.iter() {
|
|
|
|
name.push_str(".");
|
|
|
|
name.push_str(field);
|
2018-11-12 11:59:13 -08:00
|
|
|
}
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
return Ok(name.clone());
|
|
|
|
}
|
2018-11-12 11:59:13 -08:00
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
let mut name = match &import.name {
|
|
|
|
JsImportName::Module { module, name } => {
|
2020-04-15 21:28:29 +08:00
|
|
|
let unique_name = self.generate_identifier(name);
|
|
|
|
self.add_module_import(module.clone(), name, &unique_name);
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
unique_name
|
2018-11-12 11:59:13 -08:00
|
|
|
}
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
|
|
|
|
JsImportName::LocalModule { module, name } => {
|
2020-04-15 21:28:29 +08:00
|
|
|
let unique_name = self.generate_identifier(name);
|
Support emitting direct imports in wasm files
Support was previously (re-)added in #1654 for importing direct JS
values into a WebAssembly module by completely skipping JS shim
generation. This commit takes that PR one step further by *also*
embedding a direct import in the wasm file, where supported. The wasm
file currently largely just imports from the JS shim file that we
generate, but this allows it to directly improt from ES modules where
supported and where possible. Note that like #1654 this only happens
when the function signature doesn't actually require any conversions to
happen in JS (such as handling closures).
For imports from ES modules, local snippets, or inline JS they'll all
have their import directives directly embedded into the final
WebAssembly binary without any shims necessary to hook it all up. For
imports from the global namespace or possibly vendor-prefixed items
these still unconditionally require an import shim to be generated
because there's no way to describe that import in an ES-friendly way
(yet).
There's a few consequences of this commit which are also worth noting:
* The logic in `wasm-bindgen` where it gracefully handles (to some
degree) not-defined items now only is guaranteed to be applied to the
global namespace. If you import from a module, it'll be an
instantiation time error rather than today's runtime error when the
import is called.
* Handling imports in the wasm module not registered with
`#[wasm_bindgen]` has become more strict. Previously these imports
were basically ignored, leaving them up for interpretation depending
on the output format. The changes for each output target are:
* `bundler` - not much has changed here. Previously these ignored
imports would have been treated as ES module imports, and after this
commit there might just be some more of these imports for bundlers
to resolve.
* `web` - previously the ignored imports would likely cause
instantiation failures because the import object never actually
included a binding for other imports. After this commit though the
JS glue which instantiates the module now interprets all
unrecognized wasm module imports as ES module imports, emitting an
`import` directive. This matches what we want for the direct import
functionality, and is also largely what we want for modules in
general.
* `nodejs` - previously ignored imports were handled in the
translation shim for Node to generate `require` statements, so they
were actually "correctly handled" sort of with module imports. The
handling of this hasn't changed, and reflects what we want for
direct imports of values where loading a wasm module in Node ends up
translating the module field of each import to a `require`.
* `no-modules` - this is very similar to the `web` target where
previously this didn't really work one way or the other because we'd
never fill in more fields of the import object when instantiating
the module. After this PR though this is a hard-error to have
unrecognized imports from `#[wasm_bindgen]` with the `no-modules`
output type, because we don't know how to handle the imports.
Note that this touches on #1584 and will likely break the current use
case being mentioned there. I think though that this tightening up of
how we handle imports is what we'll want in the long run where
everything is interpreted as modules, and we'll need to figure out
best how wasi fits into this.
This commit is unlikely to have any real major immediate effects. The
goal here is to continue to inch us towards a world where there's less
and less JS glue necessary and `wasm-bindgen` is just a polyfill for web
standards that otherwise all already exist.
Also note that there's no explicitly added tests for this since this is
largely just a refactoring of an internal implementation detail of
`wasm-bindgen`, but the main `wasm` test suite has many instances of
this path being taken, for example having imports like:
(import "tests/wasm/duplicates_a.js" "foo" (func $__wbg_foo_969c253238f136f0 (type 1)))
(import "tests/wasm/duplicates_b.js" "foo" (func $__wbg_foo_027958cb2e320a94 (type 0)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "trivial" (func $__wbg_trivial_75e27c84882af23b (type 1)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "incoming_bool" (func $__wbg_incomingbool_0f2d9f55f73a256f (type 0)))
2019-07-31 11:35:36 -07:00
|
|
|
let module = self.config.local_module_name(module);
|
2020-04-15 21:28:29 +08:00
|
|
|
self.add_module_import(module, name, &unique_name);
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
unique_name
|
2018-11-12 11:59:13 -08:00
|
|
|
}
|
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
JsImportName::InlineJs {
|
|
|
|
unique_crate_identifier,
|
|
|
|
snippet_idx_in_crate,
|
|
|
|
name,
|
|
|
|
} => {
|
Support emitting direct imports in wasm files
Support was previously (re-)added in #1654 for importing direct JS
values into a WebAssembly module by completely skipping JS shim
generation. This commit takes that PR one step further by *also*
embedding a direct import in the wasm file, where supported. The wasm
file currently largely just imports from the JS shim file that we
generate, but this allows it to directly improt from ES modules where
supported and where possible. Note that like #1654 this only happens
when the function signature doesn't actually require any conversions to
happen in JS (such as handling closures).
For imports from ES modules, local snippets, or inline JS they'll all
have their import directives directly embedded into the final
WebAssembly binary without any shims necessary to hook it all up. For
imports from the global namespace or possibly vendor-prefixed items
these still unconditionally require an import shim to be generated
because there's no way to describe that import in an ES-friendly way
(yet).
There's a few consequences of this commit which are also worth noting:
* The logic in `wasm-bindgen` where it gracefully handles (to some
degree) not-defined items now only is guaranteed to be applied to the
global namespace. If you import from a module, it'll be an
instantiation time error rather than today's runtime error when the
import is called.
* Handling imports in the wasm module not registered with
`#[wasm_bindgen]` has become more strict. Previously these imports
were basically ignored, leaving them up for interpretation depending
on the output format. The changes for each output target are:
* `bundler` - not much has changed here. Previously these ignored
imports would have been treated as ES module imports, and after this
commit there might just be some more of these imports for bundlers
to resolve.
* `web` - previously the ignored imports would likely cause
instantiation failures because the import object never actually
included a binding for other imports. After this commit though the
JS glue which instantiates the module now interprets all
unrecognized wasm module imports as ES module imports, emitting an
`import` directive. This matches what we want for the direct import
functionality, and is also largely what we want for modules in
general.
* `nodejs` - previously ignored imports were handled in the
translation shim for Node to generate `require` statements, so they
were actually "correctly handled" sort of with module imports. The
handling of this hasn't changed, and reflects what we want for
direct imports of values where loading a wasm module in Node ends up
translating the module field of each import to a `require`.
* `no-modules` - this is very similar to the `web` target where
previously this didn't really work one way or the other because we'd
never fill in more fields of the import object when instantiating
the module. After this PR though this is a hard-error to have
unrecognized imports from `#[wasm_bindgen]` with the `no-modules`
output type, because we don't know how to handle the imports.
Note that this touches on #1584 and will likely break the current use
case being mentioned there. I think though that this tightening up of
how we handle imports is what we'll want in the long run where
everything is interpreted as modules, and we'll need to figure out
best how wasi fits into this.
This commit is unlikely to have any real major immediate effects. The
goal here is to continue to inch us towards a world where there's less
and less JS glue necessary and `wasm-bindgen` is just a polyfill for web
standards that otherwise all already exist.
Also note that there's no explicitly added tests for this since this is
largely just a refactoring of an internal implementation detail of
`wasm-bindgen`, but the main `wasm` test suite has many instances of
this path being taken, for example having imports like:
(import "tests/wasm/duplicates_a.js" "foo" (func $__wbg_foo_969c253238f136f0 (type 1)))
(import "tests/wasm/duplicates_b.js" "foo" (func $__wbg_foo_027958cb2e320a94 (type 0)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "trivial" (func $__wbg_trivial_75e27c84882af23b (type 1)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "incoming_bool" (func $__wbg_incomingbool_0f2d9f55f73a256f (type 0)))
2019-07-31 11:35:36 -07:00
|
|
|
let module = self
|
|
|
|
.config
|
|
|
|
.inline_js_module_name(unique_crate_identifier, *snippet_idx_in_crate);
|
2020-04-15 21:28:29 +08:00
|
|
|
let unique_name = self.generate_identifier(name);
|
|
|
|
self.add_module_import(module, name, &unique_name);
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
unique_name
|
|
|
|
}
|
2018-11-19 11:21:05 -08:00
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
JsImportName::VendorPrefixed { name, prefixes } => {
|
|
|
|
self.imports_post.push_str("const l");
|
|
|
|
self.imports_post.push_str(&name);
|
|
|
|
self.imports_post.push_str(" = ");
|
|
|
|
switch(&mut self.imports_post, name, "", prefixes);
|
|
|
|
self.imports_post.push_str(";\n");
|
2018-11-28 09:25:51 -08:00
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
fn switch(dst: &mut String, name: &str, prefix: &str, left: &[String]) {
|
|
|
|
if left.len() == 0 {
|
|
|
|
dst.push_str(prefix);
|
|
|
|
return dst.push_str(name);
|
|
|
|
}
|
|
|
|
dst.push_str("(typeof ");
|
|
|
|
dst.push_str(prefix);
|
|
|
|
dst.push_str(name);
|
|
|
|
dst.push_str(" !== 'undefined' ? ");
|
|
|
|
dst.push_str(prefix);
|
|
|
|
dst.push_str(name);
|
|
|
|
dst.push_str(" : ");
|
|
|
|
switch(dst, name, &left[0], &left[1..]);
|
|
|
|
dst.push_str(")");
|
|
|
|
}
|
|
|
|
format!("l{}", name)
|
|
|
|
}
|
2018-11-28 09:25:51 -08:00
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
JsImportName::Global { name } => {
|
2020-04-15 21:28:29 +08:00
|
|
|
let unique_name = self.generate_identifier(name);
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
if unique_name != *name {
|
|
|
|
bail!("cannot import `{}` from two locations", name);
|
|
|
|
}
|
|
|
|
unique_name
|
Migrate `wasm-bindgen` to using `walrus`
This commit moves `wasm-bindgen` the CLI tool from internally using
`parity-wasm` for wasm parsing/serialization to instead use `walrus`.
The `walrus` crate is something we've been working on recently with an
aim to replace the usage of `parity-wasm` in `wasm-bindgen` to make the
current CLI tool more maintainable as well as more future-proof.
The `walrus` crate provides a much nicer AST to work with as well as a
structured `Module`, whereas `parity-wasm` provides a very raw interface
to the wasm module which isn't really appropriate for our use case. The
many transformations and tweaks that wasm-bindgen does have a huge
amount of ad-hoc index management to carefully craft a final wasm
binary, but this is all entirely taken care for us with the `walrus`
crate.
Additionally, `wasm-bindgen` will ingest and rewrite the wasm file,
often changing the binary offsets of functions. Eventually with DWARF
debug information we'll need to be sure to preserve the debug
information throughout the transformations that `wasm-bindgen` does
today. This is practically impossible to do with the `parity-wasm`
architecture, but `walrus` was designed from the get-go to solve this
problem transparently in the `walrus` crate itself. (it doesn't today,
but this is planned work)
It is the intention that this does not end up regressing any
`wasm-bindgen` use cases, neither in functionality or in speed. As a
large change and refactoring, however, it's likely that at least
something will arise! We'll want to continue to remain vigilant to any
issues that come up with this commit.
Note that the `gc` crate has been deleted as part of this change, as the
`gc` crate is no longer necessary since `walrus` does it automatically.
Additionally the `gc` crate was one of the main problems with preserving
debug information as it often deletes wasm items!
Finally, this also starts moving crates to the 2018 edition where
necessary since `walrus` requires the 2018 edition, and in general it's
more pleasant to work within the 2018 edition!
2019-01-31 09:54:23 -08:00
|
|
|
}
|
2018-10-18 08:43:36 -07:00
|
|
|
};
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
self.imported_names
|
|
|
|
.insert(import.name.clone(), name.clone());
|
2018-11-28 09:25:51 -08:00
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
// After we've got an actual name handle field projections
|
|
|
|
for field in import.fields.iter() {
|
|
|
|
name.push_str(".");
|
|
|
|
name.push_str(field);
|
|
|
|
}
|
|
|
|
Ok(name)
|
2018-11-28 09:25:51 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// If a start function is present, it removes it from the `start` section
|
|
|
|
/// of the wasm module and then moves it to an exported function, named
|
|
|
|
/// `__wbindgen_start`.
|
|
|
|
fn unstart_start_function(&mut self) -> bool {
|
Migrate `wasm-bindgen` to using `walrus`
This commit moves `wasm-bindgen` the CLI tool from internally using
`parity-wasm` for wasm parsing/serialization to instead use `walrus`.
The `walrus` crate is something we've been working on recently with an
aim to replace the usage of `parity-wasm` in `wasm-bindgen` to make the
current CLI tool more maintainable as well as more future-proof.
The `walrus` crate provides a much nicer AST to work with as well as a
structured `Module`, whereas `parity-wasm` provides a very raw interface
to the wasm module which isn't really appropriate for our use case. The
many transformations and tweaks that wasm-bindgen does have a huge
amount of ad-hoc index management to carefully craft a final wasm
binary, but this is all entirely taken care for us with the `walrus`
crate.
Additionally, `wasm-bindgen` will ingest and rewrite the wasm file,
often changing the binary offsets of functions. Eventually with DWARF
debug information we'll need to be sure to preserve the debug
information throughout the transformations that `wasm-bindgen` does
today. This is practically impossible to do with the `parity-wasm`
architecture, but `walrus` was designed from the get-go to solve this
problem transparently in the `walrus` crate itself. (it doesn't today,
but this is planned work)
It is the intention that this does not end up regressing any
`wasm-bindgen` use cases, neither in functionality or in speed. As a
large change and refactoring, however, it's likely that at least
something will arise! We'll want to continue to remain vigilant to any
issues that come up with this commit.
Note that the `gc` crate has been deleted as part of this change, as the
`gc` crate is no longer necessary since `walrus` does it automatically.
Additionally the `gc` crate was one of the main problems with preserving
debug information as it often deletes wasm items!
Finally, this also starts moving crates to the 2018 edition where
necessary since `walrus` requires the 2018 edition, and in general it's
more pleasant to work within the 2018 edition!
2019-01-31 09:54:23 -08:00
|
|
|
let start = match self.module.start.take() {
|
|
|
|
Some(id) => id,
|
|
|
|
None => return false,
|
|
|
|
};
|
|
|
|
self.module.exports.add("__wbindgen_start", start);
|
|
|
|
true
|
2018-11-28 09:25:51 -08:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn expose_add_to_anyref_table(
|
|
|
|
&mut self,
|
|
|
|
table: TableId,
|
|
|
|
alloc: FunctionId,
|
|
|
|
) -> Result<MemView, Error> {
|
|
|
|
let view = self.memview_table("addToAnyrefTable", table);
|
2018-10-18 08:43:36 -07:00
|
|
|
assert!(self.config.anyref);
|
2019-12-03 11:16:44 -06:00
|
|
|
if !self.should_write_global(view.to_string()) {
|
|
|
|
return Ok(view);
|
2018-10-18 08:43:36 -07:00
|
|
|
}
|
2019-12-03 11:16:44 -06:00
|
|
|
let alloc = self.export_name_of(alloc);
|
|
|
|
let table = self.export_name_of(table);
|
|
|
|
self.global(&format!(
|
2018-10-18 08:43:36 -07:00
|
|
|
"
|
2019-12-03 11:16:44 -06:00
|
|
|
function {}(obj) {{
|
|
|
|
const idx = wasm.{}();
|
|
|
|
wasm.{}.set(idx, obj);
|
2018-10-18 08:43:36 -07:00
|
|
|
return idx;
|
2019-12-03 11:16:44 -06:00
|
|
|
}}
|
2018-10-18 08:43:36 -07:00
|
|
|
",
|
2019-12-03 11:16:44 -06:00
|
|
|
view, alloc, table,
|
|
|
|
));
|
2018-10-18 08:43:36 -07:00
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
Ok(view)
|
2018-10-18 08:43:36 -07:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
pub fn generate(&mut self) -> Result<(), Error> {
|
2020-04-15 21:28:29 +08:00
|
|
|
self.prestore_global_import_identifiers()?;
|
Add tests for the interface types output of wasm-bindgen (#1898)
* 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.
2019-12-04 15:19:48 -06:00
|
|
|
for (id, adapter) in crate::sorted_iter(&self.wit.adapters) {
|
2019-12-03 11:16:44 -06:00
|
|
|
let instrs = match &adapter.kind {
|
|
|
|
AdapterKind::Import { .. } => continue,
|
|
|
|
AdapterKind::Local { instructions } => instructions,
|
|
|
|
};
|
|
|
|
self.generate_adapter(*id, adapter, instrs)?;
|
2018-10-18 08:43:36 -07:00
|
|
|
}
|
2018-01-29 21:20:38 -08:00
|
|
|
|
2019-12-03 09:28:42 -08:00
|
|
|
let mut pairs = self.aux.export_map.iter().collect::<Vec<_>>();
|
|
|
|
pairs.sort_by_key(|(k, _)| *k);
|
|
|
|
check_duplicated_getter_and_setter_names(&pairs)?;
|
2019-06-10 07:09:51 -07:00
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
for e in self.aux.enums.iter() {
|
2019-05-01 13:53:31 -07:00
|
|
|
self.generate_enum(e)?;
|
2018-02-22 12:01:38 +01:00
|
|
|
}
|
2018-04-25 11:42:22 -07:00
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
for s in self.aux.structs.iter() {
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
self.generate_struct(s)?;
|
2019-02-27 12:20:33 -08:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
self.typescript.push_str(&self.aux.extra_typescript);
|
2018-01-29 21:20:38 -08:00
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
for path in self.aux.package_jsons.iter() {
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
self.process_package_json(path)?;
|
2018-02-07 16:41:33 -08:00
|
|
|
}
|
2018-06-18 13:48:57 -07:00
|
|
|
|
2018-11-28 09:25:51 -08:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-04-15 21:28:29 +08:00
|
|
|
/// Registers import names for all `Global` imports first before we actually
|
|
|
|
/// process any adapters.
|
|
|
|
///
|
|
|
|
/// `Global` names must be imported as their exact name, so if the same name
|
|
|
|
/// from a global is also imported from a module we have to be sure to
|
|
|
|
/// import the global first to ensure we don't shadow the actual global
|
|
|
|
/// value. Otherwise we have no way of accessing the global value!
|
|
|
|
///
|
|
|
|
/// This function will iterate through the import map up-front and generate
|
|
|
|
/// a cache entry for each import name which is a `Global`.
|
|
|
|
fn prestore_global_import_identifiers(&mut self) -> Result<(), Error> {
|
|
|
|
for import in self.aux.import_map.values() {
|
|
|
|
let js = match import {
|
2020-04-20 22:10:33 +08:00
|
|
|
AuxImport::Value(AuxValue::Bare(js))
|
|
|
|
| AuxImport::Value(AuxValue::ClassGetter(js, ..))
|
|
|
|
| AuxImport::Value(AuxValue::Getter(js, ..))
|
|
|
|
| AuxImport::Value(AuxValue::ClassSetter(js, ..))
|
|
|
|
| AuxImport::Value(AuxValue::Setter(js, ..))
|
|
|
|
| AuxImport::ValueWithThis(js, ..)
|
|
|
|
| AuxImport::Instanceof(js)
|
|
|
|
| AuxImport::Static(js)
|
|
|
|
| AuxImport::StructuralClassGetter(js, ..)
|
|
|
|
| AuxImport::StructuralClassSetter(js, ..)
|
|
|
|
| AuxImport::IndexingGetterOfClass(js)
|
|
|
|
| AuxImport::IndexingSetterOfClass(js)
|
|
|
|
| AuxImport::IndexingDeleterOfClass(js) => js,
|
2020-04-15 21:28:29 +08:00
|
|
|
_ => continue,
|
|
|
|
};
|
|
|
|
if let JsImportName::Global { .. } = js.name {
|
|
|
|
self.import_name(js)?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
fn generate_adapter(
|
2019-06-10 07:09:51 -07:00
|
|
|
&mut self,
|
2019-12-03 11:16:44 -06:00
|
|
|
id: AdapterId,
|
|
|
|
adapter: &Adapter,
|
|
|
|
instrs: &[InstructionData],
|
2019-06-10 07:09:51 -07:00
|
|
|
) -> Result<(), Error> {
|
2019-12-03 11:16:44 -06:00
|
|
|
enum Kind<'a> {
|
|
|
|
Export(&'a AuxExport),
|
|
|
|
Import(walrus::ImportId),
|
|
|
|
Adapter,
|
|
|
|
}
|
|
|
|
|
|
|
|
let kind = match self.aux.export_map.get(&id) {
|
|
|
|
Some(export) => Kind::Export(export),
|
|
|
|
None => {
|
Add reference output tests for JS operations (#1894)
* 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
2019-12-04 12:01:39 -06:00
|
|
|
let core = self.wit.implements.iter().find(|pair| pair.2 == id);
|
2019-12-03 11:16:44 -06:00
|
|
|
match core {
|
Add reference output tests for JS operations (#1894)
* 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
2019-12-04 12:01:39 -06:00
|
|
|
Some((core, _, _)) => Kind::Import(*core),
|
2019-12-03 11:16:44 -06:00
|
|
|
None => Kind::Adapter,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2019-06-10 07:09:51 -07:00
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
let catch = self.aux.imports_with_catch.contains(&id);
|
|
|
|
if let Kind::Import(core) = kind {
|
|
|
|
if !catch && self.attempt_direct_import(core, instrs)? {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
}
|
2019-06-10 07:09:51 -07:00
|
|
|
|
|
|
|
// Construct a JS shim builder, and configure it based on the kind of
|
|
|
|
// export that we're generating.
|
|
|
|
let mut builder = binding::Builder::new(self);
|
2019-12-03 11:16:44 -06:00
|
|
|
builder.log_error(match kind {
|
|
|
|
Kind::Export(_) | Kind::Adapter => false,
|
|
|
|
Kind::Import(_) => builder.cx.config.debug,
|
|
|
|
});
|
|
|
|
builder.catch(catch);
|
|
|
|
let mut arg_names = &None;
|
|
|
|
match kind {
|
|
|
|
Kind::Export(export) => {
|
|
|
|
arg_names = &export.arg_names;
|
|
|
|
match &export.kind {
|
|
|
|
AuxExportKind::Function(_) => {}
|
|
|
|
AuxExportKind::StaticFunction { .. } => {}
|
|
|
|
AuxExportKind::Constructor(class) => builder.constructor(class),
|
|
|
|
AuxExportKind::Getter { .. } | AuxExportKind::Setter { .. } => {
|
|
|
|
builder.method(false)
|
|
|
|
}
|
|
|
|
AuxExportKind::Method { consumed, .. } => builder.method(*consumed),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Kind::Import(_) => {}
|
|
|
|
Kind::Adapter => {}
|
2019-06-10 07:09:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Process the `binding` and generate a bunch of JS/TypeScript/etc.
|
2020-01-07 11:34:02 -06:00
|
|
|
let binding::JsFunction {
|
|
|
|
ts_sig,
|
|
|
|
ts_arg_tys,
|
|
|
|
ts_ret_ty,
|
|
|
|
js_doc,
|
|
|
|
code,
|
2020-02-18 23:15:37 +08:00
|
|
|
might_be_optional_field,
|
2020-04-22 16:14:00 +02:00
|
|
|
catch,
|
|
|
|
log_error,
|
2020-01-07 11:34:02 -06:00
|
|
|
} = builder
|
2019-12-03 11:16:44 -06:00
|
|
|
.process(&adapter, instrs, arg_names)
|
|
|
|
.with_context(|| match kind {
|
|
|
|
Kind::Export(e) => format!("failed to generate bindings for `{}`", e.debug_name),
|
|
|
|
Kind::Import(i) => {
|
|
|
|
let i = builder.cx.module.imports.get(i);
|
|
|
|
format!(
|
|
|
|
"failed to generate bindings for import of `{}::{}`",
|
|
|
|
i.module, i.name
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Kind::Adapter => format!("failed to generates bindings for adapter"),
|
|
|
|
})?;
|
2019-06-10 07:09:51 -07:00
|
|
|
|
2019-07-10 09:44:04 -07:00
|
|
|
// Once we've got all the JS then put it in the right location depending
|
2019-06-10 07:09:51 -07:00
|
|
|
// on what's being exported.
|
2019-12-03 11:16:44 -06:00
|
|
|
match kind {
|
|
|
|
Kind::Export(export) => {
|
2020-04-22 16:14:00 +02:00
|
|
|
assert_eq!(catch, false);
|
|
|
|
assert_eq!(log_error, false);
|
|
|
|
|
2020-03-03 10:34:28 -05:00
|
|
|
let ts_sig = match export.generate_typescript {
|
|
|
|
true => Some(ts_sig.as_str()),
|
|
|
|
false => None,
|
|
|
|
};
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
let docs = format_doc_comments(&export.comments, Some(js_doc));
|
|
|
|
match &export.kind {
|
|
|
|
AuxExportKind::Function(name) => {
|
2020-03-03 10:34:28 -05:00
|
|
|
if let Some(ts_sig) = ts_sig {
|
|
|
|
self.typescript.push_str(&docs);
|
|
|
|
self.typescript.push_str("export function ");
|
|
|
|
self.typescript.push_str(&name);
|
|
|
|
self.typescript.push_str(ts_sig);
|
|
|
|
self.typescript.push_str(";\n");
|
|
|
|
}
|
|
|
|
self.export(&name, &format!("function{}", code), Some(&docs))?;
|
2019-12-03 11:16:44 -06:00
|
|
|
self.globals.push_str("\n");
|
|
|
|
}
|
|
|
|
AuxExportKind::Constructor(class) => {
|
|
|
|
let exported = require_class(&mut self.exported_classes, class);
|
|
|
|
if exported.has_constructor {
|
|
|
|
bail!("found duplicate constructor for class `{}`", class);
|
|
|
|
}
|
|
|
|
exported.has_constructor = true;
|
2020-03-03 10:34:28 -05:00
|
|
|
exported.push(&docs, "constructor", "", &code, ts_sig);
|
2019-12-03 11:16:44 -06:00
|
|
|
}
|
|
|
|
AuxExportKind::Getter { class, field } => {
|
2020-03-03 10:34:28 -05:00
|
|
|
let ret_ty = match export.generate_typescript {
|
|
|
|
true => match &ts_ret_ty {
|
|
|
|
Some(s) => Some(s.as_str()),
|
|
|
|
_ => None,
|
|
|
|
},
|
|
|
|
false => None,
|
|
|
|
};
|
2019-12-03 11:16:44 -06:00
|
|
|
let exported = require_class(&mut self.exported_classes, class);
|
2020-03-03 10:34:28 -05:00
|
|
|
exported.push_getter(&docs, field, &code, ret_ty);
|
2019-12-03 11:16:44 -06:00
|
|
|
}
|
|
|
|
AuxExportKind::Setter { class, field } => {
|
2020-03-03 10:34:28 -05:00
|
|
|
let arg_ty = match export.generate_typescript {
|
|
|
|
true => Some(ts_arg_tys[0].as_str()),
|
|
|
|
false => None,
|
|
|
|
};
|
2019-12-03 11:16:44 -06:00
|
|
|
let exported = require_class(&mut self.exported_classes, class);
|
2020-03-03 10:34:28 -05:00
|
|
|
exported.push_setter(&docs, field, &code, arg_ty, might_be_optional_field);
|
2019-12-03 11:16:44 -06:00
|
|
|
}
|
|
|
|
AuxExportKind::StaticFunction { class, name } => {
|
|
|
|
let exported = require_class(&mut self.exported_classes, class);
|
2020-03-03 10:34:28 -05:00
|
|
|
exported.push(&docs, name, "static ", &code, ts_sig);
|
2019-12-03 11:16:44 -06:00
|
|
|
}
|
|
|
|
AuxExportKind::Method { class, name, .. } => {
|
|
|
|
let exported = require_class(&mut self.exported_classes, class);
|
2020-03-03 10:34:28 -05:00
|
|
|
exported.push(&docs, name, "", &code, ts_sig);
|
2019-12-03 11:16:44 -06:00
|
|
|
}
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
}
|
2019-07-10 14:22:13 -07:00
|
|
|
}
|
2019-12-03 11:16:44 -06:00
|
|
|
Kind::Import(core) => {
|
2020-04-22 16:14:00 +02:00
|
|
|
let code = if catch {
|
|
|
|
format!("handleError(function{})", code)
|
|
|
|
} else if log_error {
|
|
|
|
format!("logError(function{})", code)
|
|
|
|
} else {
|
|
|
|
format!("function{}", code)
|
|
|
|
};
|
|
|
|
|
|
|
|
self.wasm_import_definitions.insert(core, code);
|
2019-12-03 11:16:44 -06:00
|
|
|
}
|
|
|
|
Kind::Adapter => {
|
2020-04-22 16:14:00 +02:00
|
|
|
assert_eq!(catch, false);
|
|
|
|
assert_eq!(log_error, false);
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
self.globals.push_str("function ");
|
|
|
|
self.globals.push_str(&self.adapter_name(id));
|
2020-01-07 11:34:02 -06:00
|
|
|
self.globals.push_str(&code);
|
2019-12-03 11:16:44 -06:00
|
|
|
self.globals.push_str("\n\n");
|
2019-07-10 14:22:13 -07:00
|
|
|
}
|
Support emitting direct imports in wasm files
Support was previously (re-)added in #1654 for importing direct JS
values into a WebAssembly module by completely skipping JS shim
generation. This commit takes that PR one step further by *also*
embedding a direct import in the wasm file, where supported. The wasm
file currently largely just imports from the JS shim file that we
generate, but this allows it to directly improt from ES modules where
supported and where possible. Note that like #1654 this only happens
when the function signature doesn't actually require any conversions to
happen in JS (such as handling closures).
For imports from ES modules, local snippets, or inline JS they'll all
have their import directives directly embedded into the final
WebAssembly binary without any shims necessary to hook it all up. For
imports from the global namespace or possibly vendor-prefixed items
these still unconditionally require an import shim to be generated
because there's no way to describe that import in an ES-friendly way
(yet).
There's a few consequences of this commit which are also worth noting:
* The logic in `wasm-bindgen` where it gracefully handles (to some
degree) not-defined items now only is guaranteed to be applied to the
global namespace. If you import from a module, it'll be an
instantiation time error rather than today's runtime error when the
import is called.
* Handling imports in the wasm module not registered with
`#[wasm_bindgen]` has become more strict. Previously these imports
were basically ignored, leaving them up for interpretation depending
on the output format. The changes for each output target are:
* `bundler` - not much has changed here. Previously these ignored
imports would have been treated as ES module imports, and after this
commit there might just be some more of these imports for bundlers
to resolve.
* `web` - previously the ignored imports would likely cause
instantiation failures because the import object never actually
included a binding for other imports. After this commit though the
JS glue which instantiates the module now interprets all
unrecognized wasm module imports as ES module imports, emitting an
`import` directive. This matches what we want for the direct import
functionality, and is also largely what we want for modules in
general.
* `nodejs` - previously ignored imports were handled in the
translation shim for Node to generate `require` statements, so they
were actually "correctly handled" sort of with module imports. The
handling of this hasn't changed, and reflects what we want for
direct imports of values where loading a wasm module in Node ends up
translating the module field of each import to a `require`.
* `no-modules` - this is very similar to the `web` target where
previously this didn't really work one way or the other because we'd
never fill in more fields of the import object when instantiating
the module. After this PR though this is a hard-error to have
unrecognized imports from `#[wasm_bindgen]` with the `no-modules`
output type, because we don't know how to handle the imports.
Note that this touches on #1584 and will likely break the current use
case being mentioned there. I think though that this tightening up of
how we handle imports is what we'll want in the long run where
everything is interpreted as modules, and we'll need to figure out
best how wasi fits into this.
This commit is unlikely to have any real major immediate effects. The
goal here is to continue to inch us towards a world where there's less
and less JS glue necessary and `wasm-bindgen` is just a polyfill for web
standards that otherwise all already exist.
Also note that there's no explicitly added tests for this since this is
largely just a refactoring of an internal implementation detail of
`wasm-bindgen`, but the main `wasm` test suite has many instances of
this path being taken, for example having imports like:
(import "tests/wasm/duplicates_a.js" "foo" (func $__wbg_foo_969c253238f136f0 (type 1)))
(import "tests/wasm/duplicates_b.js" "foo" (func $__wbg_foo_027958cb2e320a94 (type 0)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "trivial" (func $__wbg_trivial_75e27c84882af23b (type 1)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "incoming_bool" (func $__wbg_incomingbool_0f2d9f55f73a256f (type 0)))
2019-07-31 11:35:36 -07:00
|
|
|
}
|
2019-12-03 11:16:44 -06:00
|
|
|
return Ok(());
|
2018-08-04 09:41:59 -07:00
|
|
|
}
|
|
|
|
|
2019-09-24 07:59:02 -07:00
|
|
|
/// Returns whether we should disable the logic, in debug mode, to catch an
|
|
|
|
/// error, log it, and rethrow it. This is only intended for user-defined
|
|
|
|
/// imports, not all imports of everything.
|
|
|
|
fn import_never_log_error(&self, import: &AuxImport) -> bool {
|
|
|
|
match import {
|
|
|
|
// Some intrinsics are intended to exactly throw errors, and in
|
|
|
|
// general we shouldn't have exceptions in our intrinsics to debug,
|
|
|
|
// so skip these.
|
|
|
|
AuxImport::Intrinsic(_) => true,
|
|
|
|
|
|
|
|
// Otherwise assume everything else gets a debug log of errors
|
|
|
|
// thrown in debug mode.
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
/// Attempts to directly hook up the `id` import in the wasm module with
|
|
|
|
/// the `instrs` specified.
|
|
|
|
///
|
|
|
|
/// If this succeeds it returns `Ok(true)`, otherwise if it cannot be
|
|
|
|
/// directly imported then `Ok(false)` is returned.
|
|
|
|
fn attempt_direct_import(
|
|
|
|
&mut self,
|
|
|
|
id: ImportId,
|
|
|
|
instrs: &[InstructionData],
|
|
|
|
) -> Result<bool, Error> {
|
|
|
|
// First up extract the ID of the single called adapter, if any.
|
|
|
|
let mut call = None;
|
|
|
|
for instr in instrs {
|
|
|
|
match instr.instr {
|
|
|
|
Instruction::CallAdapter(id) => {
|
|
|
|
if call.is_some() {
|
|
|
|
return Ok(false);
|
|
|
|
} else {
|
|
|
|
call = Some(id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Instruction::CallExport(_)
|
|
|
|
| Instruction::CallTableElement(_)
|
|
|
|
| Instruction::Standard(wit_walrus::Instruction::CallCore(_))
|
|
|
|
| Instruction::Standard(wit_walrus::Instruction::CallAdapter(_)) => {
|
|
|
|
return Ok(false)
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let adapter = match call {
|
|
|
|
Some(id) => id,
|
|
|
|
None => return Ok(false),
|
|
|
|
};
|
|
|
|
match &self.wit.adapters[&adapter].kind {
|
|
|
|
AdapterKind::Import { kind, .. } => match kind {
|
|
|
|
AdapterJsImportKind::Normal => {}
|
|
|
|
// method/constructors need glue because we either need to
|
|
|
|
// invoke them as `new` or we need to invoke them with
|
|
|
|
// method-call syntax to get the `this` parameter right.
|
|
|
|
AdapterJsImportKind::Method | AdapterJsImportKind::Constructor => return Ok(false),
|
|
|
|
},
|
|
|
|
// This is an adapter-to-adapter call, so it needs a shim.
|
|
|
|
AdapterKind::Local { .. } => return Ok(false),
|
2019-07-10 14:22:13 -07:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
// Next up check to make sure that this import is to a bare JS value
|
|
|
|
// itself, no extra fluff intended.
|
|
|
|
let js = match &self.aux.import_map[&adapter] {
|
|
|
|
AuxImport::Value(AuxValue::Bare(js)) => js,
|
|
|
|
_ => return Ok(false),
|
|
|
|
};
|
|
|
|
|
|
|
|
// Make sure this isn't variadic in any way which means we need some
|
|
|
|
// sort of adapter glue.
|
|
|
|
if self.aux.imports_with_variadic.contains(&adapter) {
|
|
|
|
return Ok(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure that every single instruction can be represented without JS
|
|
|
|
// glue being generated, aka it's covered by the JS ECMAScript bindings
|
|
|
|
// for wasm.
|
|
|
|
if !self.representable_without_js_glue(instrs) {
|
|
|
|
return Ok(false);
|
|
|
|
}
|
2019-07-10 14:22:13 -07:00
|
|
|
|
Support emitting direct imports in wasm files
Support was previously (re-)added in #1654 for importing direct JS
values into a WebAssembly module by completely skipping JS shim
generation. This commit takes that PR one step further by *also*
embedding a direct import in the wasm file, where supported. The wasm
file currently largely just imports from the JS shim file that we
generate, but this allows it to directly improt from ES modules where
supported and where possible. Note that like #1654 this only happens
when the function signature doesn't actually require any conversions to
happen in JS (such as handling closures).
For imports from ES modules, local snippets, or inline JS they'll all
have their import directives directly embedded into the final
WebAssembly binary without any shims necessary to hook it all up. For
imports from the global namespace or possibly vendor-prefixed items
these still unconditionally require an import shim to be generated
because there's no way to describe that import in an ES-friendly way
(yet).
There's a few consequences of this commit which are also worth noting:
* The logic in `wasm-bindgen` where it gracefully handles (to some
degree) not-defined items now only is guaranteed to be applied to the
global namespace. If you import from a module, it'll be an
instantiation time error rather than today's runtime error when the
import is called.
* Handling imports in the wasm module not registered with
`#[wasm_bindgen]` has become more strict. Previously these imports
were basically ignored, leaving them up for interpretation depending
on the output format. The changes for each output target are:
* `bundler` - not much has changed here. Previously these ignored
imports would have been treated as ES module imports, and after this
commit there might just be some more of these imports for bundlers
to resolve.
* `web` - previously the ignored imports would likely cause
instantiation failures because the import object never actually
included a binding for other imports. After this commit though the
JS glue which instantiates the module now interprets all
unrecognized wasm module imports as ES module imports, emitting an
`import` directive. This matches what we want for the direct import
functionality, and is also largely what we want for modules in
general.
* `nodejs` - previously ignored imports were handled in the
translation shim for Node to generate `require` statements, so they
were actually "correctly handled" sort of with module imports. The
handling of this hasn't changed, and reflects what we want for
direct imports of values where loading a wasm module in Node ends up
translating the module field of each import to a `require`.
* `no-modules` - this is very similar to the `web` target where
previously this didn't really work one way or the other because we'd
never fill in more fields of the import object when instantiating
the module. After this PR though this is a hard-error to have
unrecognized imports from `#[wasm_bindgen]` with the `no-modules`
output type, because we don't know how to handle the imports.
Note that this touches on #1584 and will likely break the current use
case being mentioned there. I think though that this tightening up of
how we handle imports is what we'll want in the long run where
everything is interpreted as modules, and we'll need to figure out
best how wasi fits into this.
This commit is unlikely to have any real major immediate effects. The
goal here is to continue to inch us towards a world where there's less
and less JS glue necessary and `wasm-bindgen` is just a polyfill for web
standards that otherwise all already exist.
Also note that there's no explicitly added tests for this since this is
largely just a refactoring of an internal implementation detail of
`wasm-bindgen`, but the main `wasm` test suite has many instances of
this path being taken, for example having imports like:
(import "tests/wasm/duplicates_a.js" "foo" (func $__wbg_foo_969c253238f136f0 (type 1)))
(import "tests/wasm/duplicates_b.js" "foo" (func $__wbg_foo_027958cb2e320a94 (type 0)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "trivial" (func $__wbg_trivial_75e27c84882af23b (type 1)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "incoming_bool" (func $__wbg_incomingbool_0f2d9f55f73a256f (type 0)))
2019-07-31 11:35:36 -07:00
|
|
|
// If there's no field projection happening here and this is a direct
|
|
|
|
// import from an ES-looking module, then we can actually just hook this
|
|
|
|
// up directly in the wasm file itself. Note that this is covered in the
|
|
|
|
// various output formats as well:
|
|
|
|
//
|
|
|
|
// * `bundler` - they think wasm is an ES module anyway
|
|
|
|
// * `web` - we're sure to emit more `import` directives during
|
|
|
|
// `gen_init` and we update the import object accordingly.
|
|
|
|
// * `nodejs` - the polyfill we have for requiring a wasm file as a node
|
|
|
|
// module will naturally emit `require` directives for the module
|
|
|
|
// listed on each wasm import.
|
|
|
|
// * `no-modules` - imports aren't allowed here anyway from other
|
|
|
|
// modules and an error is generated.
|
|
|
|
if js.fields.len() == 0 {
|
|
|
|
match &js.name {
|
|
|
|
JsImportName::Module { module, name } => {
|
|
|
|
let import = self.module.imports.get_mut(id);
|
|
|
|
import.module = module.clone();
|
|
|
|
import.name = name.clone();
|
2019-12-03 11:16:44 -06:00
|
|
|
return Ok(true);
|
Support emitting direct imports in wasm files
Support was previously (re-)added in #1654 for importing direct JS
values into a WebAssembly module by completely skipping JS shim
generation. This commit takes that PR one step further by *also*
embedding a direct import in the wasm file, where supported. The wasm
file currently largely just imports from the JS shim file that we
generate, but this allows it to directly improt from ES modules where
supported and where possible. Note that like #1654 this only happens
when the function signature doesn't actually require any conversions to
happen in JS (such as handling closures).
For imports from ES modules, local snippets, or inline JS they'll all
have their import directives directly embedded into the final
WebAssembly binary without any shims necessary to hook it all up. For
imports from the global namespace or possibly vendor-prefixed items
these still unconditionally require an import shim to be generated
because there's no way to describe that import in an ES-friendly way
(yet).
There's a few consequences of this commit which are also worth noting:
* The logic in `wasm-bindgen` where it gracefully handles (to some
degree) not-defined items now only is guaranteed to be applied to the
global namespace. If you import from a module, it'll be an
instantiation time error rather than today's runtime error when the
import is called.
* Handling imports in the wasm module not registered with
`#[wasm_bindgen]` has become more strict. Previously these imports
were basically ignored, leaving them up for interpretation depending
on the output format. The changes for each output target are:
* `bundler` - not much has changed here. Previously these ignored
imports would have been treated as ES module imports, and after this
commit there might just be some more of these imports for bundlers
to resolve.
* `web` - previously the ignored imports would likely cause
instantiation failures because the import object never actually
included a binding for other imports. After this commit though the
JS glue which instantiates the module now interprets all
unrecognized wasm module imports as ES module imports, emitting an
`import` directive. This matches what we want for the direct import
functionality, and is also largely what we want for modules in
general.
* `nodejs` - previously ignored imports were handled in the
translation shim for Node to generate `require` statements, so they
were actually "correctly handled" sort of with module imports. The
handling of this hasn't changed, and reflects what we want for
direct imports of values where loading a wasm module in Node ends up
translating the module field of each import to a `require`.
* `no-modules` - this is very similar to the `web` target where
previously this didn't really work one way or the other because we'd
never fill in more fields of the import object when instantiating
the module. After this PR though this is a hard-error to have
unrecognized imports from `#[wasm_bindgen]` with the `no-modules`
output type, because we don't know how to handle the imports.
Note that this touches on #1584 and will likely break the current use
case being mentioned there. I think though that this tightening up of
how we handle imports is what we'll want in the long run where
everything is interpreted as modules, and we'll need to figure out
best how wasi fits into this.
This commit is unlikely to have any real major immediate effects. The
goal here is to continue to inch us towards a world where there's less
and less JS glue necessary and `wasm-bindgen` is just a polyfill for web
standards that otherwise all already exist.
Also note that there's no explicitly added tests for this since this is
largely just a refactoring of an internal implementation detail of
`wasm-bindgen`, but the main `wasm` test suite has many instances of
this path being taken, for example having imports like:
(import "tests/wasm/duplicates_a.js" "foo" (func $__wbg_foo_969c253238f136f0 (type 1)))
(import "tests/wasm/duplicates_b.js" "foo" (func $__wbg_foo_027958cb2e320a94 (type 0)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "trivial" (func $__wbg_trivial_75e27c84882af23b (type 1)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "incoming_bool" (func $__wbg_incomingbool_0f2d9f55f73a256f (type 0)))
2019-07-31 11:35:36 -07:00
|
|
|
}
|
|
|
|
JsImportName::LocalModule { module, name } => {
|
|
|
|
let module = self.config.local_module_name(module);
|
|
|
|
let import = self.module.imports.get_mut(id);
|
|
|
|
import.module = module;
|
|
|
|
import.name = name.clone();
|
2019-12-03 11:16:44 -06:00
|
|
|
return Ok(true);
|
Support emitting direct imports in wasm files
Support was previously (re-)added in #1654 for importing direct JS
values into a WebAssembly module by completely skipping JS shim
generation. This commit takes that PR one step further by *also*
embedding a direct import in the wasm file, where supported. The wasm
file currently largely just imports from the JS shim file that we
generate, but this allows it to directly improt from ES modules where
supported and where possible. Note that like #1654 this only happens
when the function signature doesn't actually require any conversions to
happen in JS (such as handling closures).
For imports from ES modules, local snippets, or inline JS they'll all
have their import directives directly embedded into the final
WebAssembly binary without any shims necessary to hook it all up. For
imports from the global namespace or possibly vendor-prefixed items
these still unconditionally require an import shim to be generated
because there's no way to describe that import in an ES-friendly way
(yet).
There's a few consequences of this commit which are also worth noting:
* The logic in `wasm-bindgen` where it gracefully handles (to some
degree) not-defined items now only is guaranteed to be applied to the
global namespace. If you import from a module, it'll be an
instantiation time error rather than today's runtime error when the
import is called.
* Handling imports in the wasm module not registered with
`#[wasm_bindgen]` has become more strict. Previously these imports
were basically ignored, leaving them up for interpretation depending
on the output format. The changes for each output target are:
* `bundler` - not much has changed here. Previously these ignored
imports would have been treated as ES module imports, and after this
commit there might just be some more of these imports for bundlers
to resolve.
* `web` - previously the ignored imports would likely cause
instantiation failures because the import object never actually
included a binding for other imports. After this commit though the
JS glue which instantiates the module now interprets all
unrecognized wasm module imports as ES module imports, emitting an
`import` directive. This matches what we want for the direct import
functionality, and is also largely what we want for modules in
general.
* `nodejs` - previously ignored imports were handled in the
translation shim for Node to generate `require` statements, so they
were actually "correctly handled" sort of with module imports. The
handling of this hasn't changed, and reflects what we want for
direct imports of values where loading a wasm module in Node ends up
translating the module field of each import to a `require`.
* `no-modules` - this is very similar to the `web` target where
previously this didn't really work one way or the other because we'd
never fill in more fields of the import object when instantiating
the module. After this PR though this is a hard-error to have
unrecognized imports from `#[wasm_bindgen]` with the `no-modules`
output type, because we don't know how to handle the imports.
Note that this touches on #1584 and will likely break the current use
case being mentioned there. I think though that this tightening up of
how we handle imports is what we'll want in the long run where
everything is interpreted as modules, and we'll need to figure out
best how wasi fits into this.
This commit is unlikely to have any real major immediate effects. The
goal here is to continue to inch us towards a world where there's less
and less JS glue necessary and `wasm-bindgen` is just a polyfill for web
standards that otherwise all already exist.
Also note that there's no explicitly added tests for this since this is
largely just a refactoring of an internal implementation detail of
`wasm-bindgen`, but the main `wasm` test suite has many instances of
this path being taken, for example having imports like:
(import "tests/wasm/duplicates_a.js" "foo" (func $__wbg_foo_969c253238f136f0 (type 1)))
(import "tests/wasm/duplicates_b.js" "foo" (func $__wbg_foo_027958cb2e320a94 (type 0)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "trivial" (func $__wbg_trivial_75e27c84882af23b (type 1)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "incoming_bool" (func $__wbg_incomingbool_0f2d9f55f73a256f (type 0)))
2019-07-31 11:35:36 -07:00
|
|
|
}
|
|
|
|
JsImportName::InlineJs {
|
|
|
|
unique_crate_identifier,
|
|
|
|
snippet_idx_in_crate,
|
|
|
|
name,
|
|
|
|
} => {
|
|
|
|
let module = self
|
|
|
|
.config
|
|
|
|
.inline_js_module_name(unique_crate_identifier, *snippet_idx_in_crate);
|
|
|
|
let import = self.module.imports.get_mut(id);
|
|
|
|
import.module = module;
|
|
|
|
import.name = name.clone();
|
2019-12-03 11:16:44 -06:00
|
|
|
return Ok(true);
|
Support emitting direct imports in wasm files
Support was previously (re-)added in #1654 for importing direct JS
values into a WebAssembly module by completely skipping JS shim
generation. This commit takes that PR one step further by *also*
embedding a direct import in the wasm file, where supported. The wasm
file currently largely just imports from the JS shim file that we
generate, but this allows it to directly improt from ES modules where
supported and where possible. Note that like #1654 this only happens
when the function signature doesn't actually require any conversions to
happen in JS (such as handling closures).
For imports from ES modules, local snippets, or inline JS they'll all
have their import directives directly embedded into the final
WebAssembly binary without any shims necessary to hook it all up. For
imports from the global namespace or possibly vendor-prefixed items
these still unconditionally require an import shim to be generated
because there's no way to describe that import in an ES-friendly way
(yet).
There's a few consequences of this commit which are also worth noting:
* The logic in `wasm-bindgen` where it gracefully handles (to some
degree) not-defined items now only is guaranteed to be applied to the
global namespace. If you import from a module, it'll be an
instantiation time error rather than today's runtime error when the
import is called.
* Handling imports in the wasm module not registered with
`#[wasm_bindgen]` has become more strict. Previously these imports
were basically ignored, leaving them up for interpretation depending
on the output format. The changes for each output target are:
* `bundler` - not much has changed here. Previously these ignored
imports would have been treated as ES module imports, and after this
commit there might just be some more of these imports for bundlers
to resolve.
* `web` - previously the ignored imports would likely cause
instantiation failures because the import object never actually
included a binding for other imports. After this commit though the
JS glue which instantiates the module now interprets all
unrecognized wasm module imports as ES module imports, emitting an
`import` directive. This matches what we want for the direct import
functionality, and is also largely what we want for modules in
general.
* `nodejs` - previously ignored imports were handled in the
translation shim for Node to generate `require` statements, so they
were actually "correctly handled" sort of with module imports. The
handling of this hasn't changed, and reflects what we want for
direct imports of values where loading a wasm module in Node ends up
translating the module field of each import to a `require`.
* `no-modules` - this is very similar to the `web` target where
previously this didn't really work one way or the other because we'd
never fill in more fields of the import object when instantiating
the module. After this PR though this is a hard-error to have
unrecognized imports from `#[wasm_bindgen]` with the `no-modules`
output type, because we don't know how to handle the imports.
Note that this touches on #1584 and will likely break the current use
case being mentioned there. I think though that this tightening up of
how we handle imports is what we'll want in the long run where
everything is interpreted as modules, and we'll need to figure out
best how wasi fits into this.
This commit is unlikely to have any real major immediate effects. The
goal here is to continue to inch us towards a world where there's less
and less JS glue necessary and `wasm-bindgen` is just a polyfill for web
standards that otherwise all already exist.
Also note that there's no explicitly added tests for this since this is
largely just a refactoring of an internal implementation detail of
`wasm-bindgen`, but the main `wasm` test suite has many instances of
this path being taken, for example having imports like:
(import "tests/wasm/duplicates_a.js" "foo" (func $__wbg_foo_969c253238f136f0 (type 1)))
(import "tests/wasm/duplicates_b.js" "foo" (func $__wbg_foo_027958cb2e320a94 (type 0)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "trivial" (func $__wbg_trivial_75e27c84882af23b (type 1)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "incoming_bool" (func $__wbg_incomingbool_0f2d9f55f73a256f (type 0)))
2019-07-31 11:35:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Fall through below to requiring a JS shim to create an item
|
|
|
|
// that we can import. These are plucked from the global
|
|
|
|
// environment so there's no way right now to describe these
|
|
|
|
// imports in an ES module-like fashion.
|
|
|
|
JsImportName::Global { .. } | JsImportName::VendorPrefixed { .. } => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
self.expose_not_defined();
|
|
|
|
let name = self.import_name(js)?;
|
|
|
|
let js = format!(
|
|
|
|
"typeof {name} == 'function' ? {name} : notDefined('{name}')",
|
|
|
|
name = name,
|
|
|
|
);
|
|
|
|
self.wasm_import_definitions.insert(id, js);
|
2019-12-03 11:16:44 -06:00
|
|
|
Ok(true)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn representable_without_js_glue(&self, instrs: &[InstructionData]) -> bool {
|
|
|
|
use Instruction::*;
|
|
|
|
let standard_enabled = self.config.wasm_interface_types;
|
|
|
|
|
|
|
|
let mut last_arg = None;
|
|
|
|
let mut saw_call = false;
|
|
|
|
for instr in instrs {
|
|
|
|
match instr.instr {
|
|
|
|
// Is an adapter section getting emitted? If so, then every
|
|
|
|
// standard operation is natively supported!
|
|
|
|
Standard(_) if standard_enabled => {}
|
|
|
|
|
|
|
|
// Fetching arguments is just that, a fetch, so no need for
|
|
|
|
// glue. Note though that the arguments must be fetched in order
|
|
|
|
// for this to actually work,
|
|
|
|
Standard(wit_walrus::Instruction::ArgGet(i)) => {
|
|
|
|
if saw_call {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
match (i, last_arg) {
|
|
|
|
(0, None) => last_arg = Some(0),
|
|
|
|
(n, Some(i)) if n == i + 1 => last_arg = Some(n),
|
|
|
|
_ => return false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Similarly calling a function is the same as in JS, no glue
|
|
|
|
// needed.
|
|
|
|
CallAdapter(_) => saw_call = true,
|
|
|
|
|
|
|
|
// Conversions to wasm integers are always supported since
|
|
|
|
// they're coerced into i32/f32/f64 appropriately.
|
|
|
|
Standard(wit_walrus::Instruction::IntToWasm { .. }) => {}
|
|
|
|
|
|
|
|
// Converts from wasm to JS, however, only supports most
|
|
|
|
// integers. Converting into a u32 isn't supported because we
|
|
|
|
// need to generate glue to change the sign.
|
|
|
|
Standard(wit_walrus::Instruction::WasmToInt {
|
|
|
|
output: wit_walrus::ValType::U32,
|
|
|
|
..
|
|
|
|
}) => return false,
|
|
|
|
Standard(wit_walrus::Instruction::WasmToInt { .. }) => {}
|
|
|
|
|
|
|
|
// JS spec automatically coerces boolean values to i32 of 0 or 1
|
|
|
|
// depending on true/false
|
|
|
|
I32FromBool => {}
|
|
|
|
|
|
|
|
_ => return false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
Support emitting direct imports in wasm files
Support was previously (re-)added in #1654 for importing direct JS
values into a WebAssembly module by completely skipping JS shim
generation. This commit takes that PR one step further by *also*
embedding a direct import in the wasm file, where supported. The wasm
file currently largely just imports from the JS shim file that we
generate, but this allows it to directly improt from ES modules where
supported and where possible. Note that like #1654 this only happens
when the function signature doesn't actually require any conversions to
happen in JS (such as handling closures).
For imports from ES modules, local snippets, or inline JS they'll all
have their import directives directly embedded into the final
WebAssembly binary without any shims necessary to hook it all up. For
imports from the global namespace or possibly vendor-prefixed items
these still unconditionally require an import shim to be generated
because there's no way to describe that import in an ES-friendly way
(yet).
There's a few consequences of this commit which are also worth noting:
* The logic in `wasm-bindgen` where it gracefully handles (to some
degree) not-defined items now only is guaranteed to be applied to the
global namespace. If you import from a module, it'll be an
instantiation time error rather than today's runtime error when the
import is called.
* Handling imports in the wasm module not registered with
`#[wasm_bindgen]` has become more strict. Previously these imports
were basically ignored, leaving them up for interpretation depending
on the output format. The changes for each output target are:
* `bundler` - not much has changed here. Previously these ignored
imports would have been treated as ES module imports, and after this
commit there might just be some more of these imports for bundlers
to resolve.
* `web` - previously the ignored imports would likely cause
instantiation failures because the import object never actually
included a binding for other imports. After this commit though the
JS glue which instantiates the module now interprets all
unrecognized wasm module imports as ES module imports, emitting an
`import` directive. This matches what we want for the direct import
functionality, and is also largely what we want for modules in
general.
* `nodejs` - previously ignored imports were handled in the
translation shim for Node to generate `require` statements, so they
were actually "correctly handled" sort of with module imports. The
handling of this hasn't changed, and reflects what we want for
direct imports of values where loading a wasm module in Node ends up
translating the module field of each import to a `require`.
* `no-modules` - this is very similar to the `web` target where
previously this didn't really work one way or the other because we'd
never fill in more fields of the import object when instantiating
the module. After this PR though this is a hard-error to have
unrecognized imports from `#[wasm_bindgen]` with the `no-modules`
output type, because we don't know how to handle the imports.
Note that this touches on #1584 and will likely break the current use
case being mentioned there. I think though that this tightening up of
how we handle imports is what we'll want in the long run where
everything is interpreted as modules, and we'll need to figure out
best how wasi fits into this.
This commit is unlikely to have any real major immediate effects. The
goal here is to continue to inch us towards a world where there's less
and less JS glue necessary and `wasm-bindgen` is just a polyfill for web
standards that otherwise all already exist.
Also note that there's no explicitly added tests for this since this is
largely just a refactoring of an internal implementation detail of
`wasm-bindgen`, but the main `wasm` test suite has many instances of
this path being taken, for example having imports like:
(import "tests/wasm/duplicates_a.js" "foo" (func $__wbg_foo_969c253238f136f0 (type 1)))
(import "tests/wasm/duplicates_b.js" "foo" (func $__wbg_foo_027958cb2e320a94 (type 0)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "trivial" (func $__wbg_trivial_75e27c84882af23b (type 1)))
(import "./snippets/wasm-bindgen-3dff2bc911f0a20c/inline0.js" "incoming_bool" (func $__wbg_incomingbool_0f2d9f55f73a256f (type 0)))
2019-07-31 11:35:36 -07:00
|
|
|
}
|
|
|
|
|
2019-06-10 07:09:51 -07:00
|
|
|
/// Generates a JS snippet appropriate for invoking `import`.
|
|
|
|
///
|
|
|
|
/// This is generating code for `binding` where `bindings` has more type
|
|
|
|
/// infomation. The `args` array is the list of JS expressions representing
|
|
|
|
/// the arguments to pass to JS. Finally `variadic` indicates whether the
|
|
|
|
/// last argument is a list to be splatted in a variadic way, and `prelude`
|
|
|
|
/// is a location to push some more initialization JS if necessary.
|
|
|
|
///
|
|
|
|
/// The returned value here is a JS expression which evaluates to the
|
|
|
|
/// purpose of `AuxImport`, which depends on the kind of import.
|
|
|
|
fn invoke_import(
|
|
|
|
&mut self,
|
|
|
|
import: &AuxImport,
|
2019-12-03 11:16:44 -06:00
|
|
|
kind: AdapterJsImportKind,
|
2019-06-10 07:09:51 -07:00
|
|
|
args: &[String],
|
|
|
|
variadic: bool,
|
|
|
|
prelude: &mut String,
|
|
|
|
) -> Result<String, Error> {
|
|
|
|
let variadic_args = |js_arguments: &[String]| {
|
|
|
|
Ok(if !variadic {
|
|
|
|
format!("{}", js_arguments.join(", "))
|
|
|
|
} else {
|
|
|
|
let (last_arg, args) = match js_arguments.split_last() {
|
|
|
|
Some(pair) => pair,
|
|
|
|
None => bail!("a function with no arguments cannot be variadic"),
|
|
|
|
};
|
|
|
|
if args.len() > 0 {
|
|
|
|
format!("{}, ...{}", args.join(", "), last_arg)
|
|
|
|
} else {
|
|
|
|
format!("...{}", last_arg)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
};
|
|
|
|
match import {
|
2019-12-03 11:16:44 -06:00
|
|
|
AuxImport::Value(val) => match kind {
|
|
|
|
AdapterJsImportKind::Constructor => {
|
2019-06-10 07:09:51 -07:00
|
|
|
let js = match val {
|
|
|
|
AuxValue::Bare(js) => self.import_name(js)?,
|
|
|
|
_ => bail!("invalid import set for constructor"),
|
|
|
|
};
|
|
|
|
Ok(format!("new {}({})", js, variadic_args(&args)?))
|
|
|
|
}
|
2019-12-03 11:16:44 -06:00
|
|
|
AdapterJsImportKind::Method => {
|
2019-06-10 07:09:51 -07:00
|
|
|
let descriptor = |anchor: &str, extra: &str, field: &str, which: &str| {
|
|
|
|
format!(
|
|
|
|
"GetOwnOrInheritedPropertyDescriptor({}{}, '{}').{}",
|
|
|
|
anchor, extra, field, which
|
|
|
|
)
|
|
|
|
};
|
|
|
|
let js = match val {
|
|
|
|
AuxValue::Bare(js) => self.import_name(js)?,
|
|
|
|
AuxValue::Getter(class, field) => {
|
|
|
|
self.expose_get_inherited_descriptor();
|
|
|
|
let class = self.import_name(class)?;
|
|
|
|
descriptor(&class, ".prototype", field, "get")
|
|
|
|
}
|
|
|
|
AuxValue::ClassGetter(class, field) => {
|
|
|
|
self.expose_get_inherited_descriptor();
|
|
|
|
let class = self.import_name(class)?;
|
|
|
|
descriptor(&class, "", field, "get")
|
|
|
|
}
|
|
|
|
AuxValue::Setter(class, field) => {
|
|
|
|
self.expose_get_inherited_descriptor();
|
|
|
|
let class = self.import_name(class)?;
|
|
|
|
descriptor(&class, ".prototype", field, "set")
|
|
|
|
}
|
|
|
|
AuxValue::ClassSetter(class, field) => {
|
|
|
|
self.expose_get_inherited_descriptor();
|
|
|
|
let class = self.import_name(class)?;
|
|
|
|
descriptor(&class, "", field, "set")
|
|
|
|
}
|
|
|
|
};
|
|
|
|
Ok(format!("{}.call({})", js, variadic_args(&args)?))
|
|
|
|
}
|
2019-12-03 11:16:44 -06:00
|
|
|
AdapterJsImportKind::Normal => {
|
2019-06-10 07:09:51 -07:00
|
|
|
let js = match val {
|
|
|
|
AuxValue::Bare(js) => self.import_name(js)?,
|
2019-07-10 12:49:44 -07:00
|
|
|
_ => bail!("invalid import set for free function"),
|
2019-06-10 07:09:51 -07:00
|
|
|
};
|
|
|
|
Ok(format!("{}({})", js, variadic_args(&args)?))
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2019-09-26 12:33:04 -05:00
|
|
|
AuxImport::ValueWithThis(class, name) => {
|
|
|
|
let class = self.import_name(class)?;
|
|
|
|
Ok(format!("{}.{}({})", class, name, variadic_args(&args)?))
|
|
|
|
}
|
|
|
|
|
2019-06-10 07:09:51 -07:00
|
|
|
AuxImport::Instanceof(js) => {
|
2019-12-03 11:16:44 -06:00
|
|
|
assert!(kind == AdapterJsImportKind::Normal);
|
2019-06-10 07:09:51 -07:00
|
|
|
assert!(!variadic);
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
let js = self.import_name(js)?;
|
|
|
|
Ok(format!("{} instanceof {}", args[0], js))
|
|
|
|
}
|
|
|
|
|
|
|
|
AuxImport::Static(js) => {
|
2019-12-03 11:16:44 -06:00
|
|
|
assert!(kind == AdapterJsImportKind::Normal);
|
2019-06-10 07:09:51 -07:00
|
|
|
assert!(!variadic);
|
|
|
|
assert_eq!(args.len(), 0);
|
|
|
|
self.import_name(js)
|
|
|
|
}
|
|
|
|
|
|
|
|
AuxImport::Closure {
|
|
|
|
dtor,
|
|
|
|
mutable,
|
2019-12-03 11:16:44 -06:00
|
|
|
adapter,
|
2020-02-18 15:37:40 +01:00
|
|
|
nargs: _,
|
2019-06-10 07:09:51 -07:00
|
|
|
} => {
|
2019-12-03 11:16:44 -06:00
|
|
|
assert!(kind == AdapterJsImportKind::Normal);
|
2019-06-10 07:09:51 -07:00
|
|
|
assert!(!variadic);
|
|
|
|
assert_eq!(args.len(), 3);
|
2020-02-18 15:37:40 +01:00
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
let call = self.adapter_name(*adapter);
|
2019-06-10 07:09:51 -07:00
|
|
|
|
|
|
|
if *mutable {
|
2020-02-18 15:37:40 +01:00
|
|
|
self.expose_make_mut_closure()?;
|
|
|
|
|
|
|
|
Ok(format!(
|
|
|
|
"makeMutClosure({arg0}, {arg1}, {dtor}, {call})",
|
|
|
|
arg0 = &args[0],
|
|
|
|
arg1 = &args[1],
|
|
|
|
dtor = dtor,
|
|
|
|
call = call,
|
|
|
|
))
|
2019-06-10 07:09:51 -07:00
|
|
|
} else {
|
2020-02-18 15:37:40 +01:00
|
|
|
self.expose_make_closure()?;
|
|
|
|
|
|
|
|
Ok(format!(
|
|
|
|
"makeClosure({arg0}, {arg1}, {dtor}, {call})",
|
|
|
|
arg0 = &args[0],
|
|
|
|
arg1 = &args[1],
|
|
|
|
dtor = dtor,
|
|
|
|
call = call,
|
|
|
|
))
|
2019-06-10 07:09:51 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
AuxImport::StructuralMethod(name) => {
|
2019-12-03 11:16:44 -06:00
|
|
|
assert!(kind == AdapterJsImportKind::Normal);
|
2019-06-10 07:09:51 -07:00
|
|
|
let (receiver, args) = match args.split_first() {
|
|
|
|
Some(pair) => pair,
|
|
|
|
None => bail!("structural method calls must have at least one argument"),
|
|
|
|
};
|
|
|
|
Ok(format!("{}.{}({})", receiver, name, variadic_args(args)?))
|
|
|
|
}
|
|
|
|
|
|
|
|
AuxImport::StructuralGetter(field) => {
|
2019-12-03 11:16:44 -06:00
|
|
|
assert!(kind == AdapterJsImportKind::Normal);
|
2019-06-10 07:09:51 -07:00
|
|
|
assert!(!variadic);
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
Ok(format!("{}.{}", args[0], field))
|
|
|
|
}
|
|
|
|
|
|
|
|
AuxImport::StructuralClassGetter(class, field) => {
|
2019-12-03 11:16:44 -06:00
|
|
|
assert!(kind == AdapterJsImportKind::Normal);
|
2019-06-10 07:09:51 -07:00
|
|
|
assert!(!variadic);
|
|
|
|
assert_eq!(args.len(), 0);
|
|
|
|
let class = self.import_name(class)?;
|
|
|
|
Ok(format!("{}.{}", class, field))
|
|
|
|
}
|
|
|
|
|
|
|
|
AuxImport::StructuralSetter(field) => {
|
2019-12-03 11:16:44 -06:00
|
|
|
assert!(kind == AdapterJsImportKind::Normal);
|
2019-06-10 07:09:51 -07:00
|
|
|
assert!(!variadic);
|
|
|
|
assert_eq!(args.len(), 2);
|
|
|
|
Ok(format!("{}.{} = {}", args[0], field, args[1]))
|
|
|
|
}
|
|
|
|
|
|
|
|
AuxImport::StructuralClassSetter(class, field) => {
|
2019-12-03 11:16:44 -06:00
|
|
|
assert!(kind == AdapterJsImportKind::Normal);
|
2019-06-10 07:09:51 -07:00
|
|
|
assert!(!variadic);
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
let class = self.import_name(class)?;
|
|
|
|
Ok(format!("{}.{} = {}", class, field, args[0]))
|
|
|
|
}
|
|
|
|
|
|
|
|
AuxImport::IndexingGetterOfClass(class) => {
|
2019-12-03 11:16:44 -06:00
|
|
|
assert!(kind == AdapterJsImportKind::Normal);
|
2019-06-10 07:09:51 -07:00
|
|
|
assert!(!variadic);
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
let class = self.import_name(class)?;
|
|
|
|
Ok(format!("{}[{}]", class, args[0]))
|
|
|
|
}
|
|
|
|
|
|
|
|
AuxImport::IndexingGetterOfObject => {
|
2019-12-03 11:16:44 -06:00
|
|
|
assert!(kind == AdapterJsImportKind::Normal);
|
2019-06-10 07:09:51 -07:00
|
|
|
assert!(!variadic);
|
|
|
|
assert_eq!(args.len(), 2);
|
|
|
|
Ok(format!("{}[{}]", args[0], args[1]))
|
|
|
|
}
|
|
|
|
|
|
|
|
AuxImport::IndexingSetterOfClass(class) => {
|
2019-12-03 11:16:44 -06:00
|
|
|
assert!(kind == AdapterJsImportKind::Normal);
|
2019-06-10 07:09:51 -07:00
|
|
|
assert!(!variadic);
|
|
|
|
assert_eq!(args.len(), 2);
|
|
|
|
let class = self.import_name(class)?;
|
|
|
|
Ok(format!("{}[{}] = {}", class, args[0], args[1]))
|
|
|
|
}
|
|
|
|
|
|
|
|
AuxImport::IndexingSetterOfObject => {
|
2019-12-03 11:16:44 -06:00
|
|
|
assert!(kind == AdapterJsImportKind::Normal);
|
2019-06-10 07:09:51 -07:00
|
|
|
assert!(!variadic);
|
|
|
|
assert_eq!(args.len(), 3);
|
|
|
|
Ok(format!("{}[{}] = {}", args[0], args[1], args[2]))
|
|
|
|
}
|
|
|
|
|
|
|
|
AuxImport::IndexingDeleterOfClass(class) => {
|
2019-12-03 11:16:44 -06:00
|
|
|
assert!(kind == AdapterJsImportKind::Normal);
|
2019-06-10 07:09:51 -07:00
|
|
|
assert!(!variadic);
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
let class = self.import_name(class)?;
|
|
|
|
Ok(format!("delete {}[{}]", class, args[0]))
|
|
|
|
}
|
|
|
|
|
|
|
|
AuxImport::IndexingDeleterOfObject => {
|
2019-12-03 11:16:44 -06:00
|
|
|
assert!(kind == AdapterJsImportKind::Normal);
|
2019-06-10 07:09:51 -07:00
|
|
|
assert!(!variadic);
|
|
|
|
assert_eq!(args.len(), 2);
|
|
|
|
Ok(format!("delete {}[{}]", args[0], args[1]))
|
|
|
|
}
|
|
|
|
|
|
|
|
AuxImport::WrapInExportedClass(class) => {
|
2019-12-03 11:16:44 -06:00
|
|
|
assert!(kind == AdapterJsImportKind::Normal);
|
2019-06-10 07:09:51 -07:00
|
|
|
assert!(!variadic);
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
self.require_class_wrap(class);
|
|
|
|
Ok(format!("{}.__wrap({})", class, args[0]))
|
|
|
|
}
|
|
|
|
|
|
|
|
AuxImport::Intrinsic(intrinsic) => {
|
2019-12-03 11:16:44 -06:00
|
|
|
assert!(kind == AdapterJsImportKind::Normal);
|
2019-06-10 07:09:51 -07:00
|
|
|
assert!(!variadic);
|
|
|
|
self.invoke_intrinsic(intrinsic, args, prelude)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Same as `invoke_import` above, except more specialized and only used for
|
|
|
|
/// generating the JS expression needed to implement a particular intrinsic.
|
|
|
|
fn invoke_intrinsic(
|
|
|
|
&mut self,
|
|
|
|
intrinsic: &Intrinsic,
|
|
|
|
args: &[String],
|
|
|
|
prelude: &mut String,
|
|
|
|
) -> Result<String, Error> {
|
|
|
|
let expr = match intrinsic {
|
|
|
|
Intrinsic::JsvalEq => {
|
|
|
|
assert_eq!(args.len(), 2);
|
|
|
|
format!("{} === {}", args[0], args[1])
|
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::IsFunction => {
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
format!("typeof({}) === 'function'", args[0])
|
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::IsUndefined => {
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
format!("{} === undefined", args[0])
|
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::IsNull => {
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
format!("{} === null", args[0])
|
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::IsObject => {
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
prelude.push_str(&format!("const val = {};\n", args[0]));
|
|
|
|
format!("typeof(val) === 'object' && val !== null")
|
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::IsSymbol => {
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
format!("typeof({}) === 'symbol'", args[0])
|
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::IsString => {
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
format!("typeof({}) === 'string'", args[0])
|
|
|
|
}
|
|
|
|
|
2019-07-02 18:44:06 +02:00
|
|
|
Intrinsic::IsFalsy => {
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
format!("!{}", args[0])
|
|
|
|
}
|
|
|
|
|
2019-06-10 07:09:51 -07:00
|
|
|
Intrinsic::ObjectCloneRef => {
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
args[0].clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::ObjectDropRef => {
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
args[0].clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::CallbackDrop => {
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
prelude.push_str(&format!("const obj = {}.original;\n", args[0]));
|
|
|
|
prelude.push_str("if (obj.cnt-- == 1) {\n");
|
|
|
|
prelude.push_str("obj.a = 0;\n");
|
|
|
|
prelude.push_str("return true;\n");
|
|
|
|
prelude.push_str("}\n");
|
|
|
|
"false".to_string()
|
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::CallbackForget => {
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
args[0].clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::NumberNew => {
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
args[0].clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::StringNew => {
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
args[0].clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::SymbolNamedNew => {
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
format!("Symbol({})", args[0])
|
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::SymbolAnonymousNew => {
|
|
|
|
assert_eq!(args.len(), 0);
|
|
|
|
"Symbol()".to_string()
|
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::NumberGet => {
|
2019-12-03 11:16:44 -06:00
|
|
|
assert_eq!(args.len(), 1);
|
2019-06-10 07:09:51 -07:00
|
|
|
prelude.push_str(&format!("const obj = {};\n", args[0]));
|
2019-12-03 11:16:44 -06:00
|
|
|
format!("typeof(obj) === 'number' ? obj : undefined")
|
2019-06-10 07:09:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::StringGet => {
|
2019-12-03 11:16:44 -06:00
|
|
|
assert_eq!(args.len(), 1);
|
2019-06-10 07:09:51 -07:00
|
|
|
prelude.push_str(&format!("const obj = {};\n", args[0]));
|
2019-12-03 11:16:44 -06:00
|
|
|
format!("typeof(obj) === 'string' ? obj : undefined")
|
2019-06-10 07:09:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::BooleanGet => {
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
prelude.push_str(&format!("const v = {};\n", args[0]));
|
|
|
|
format!("typeof(v) === 'boolean' ? (v ? 1 : 0) : 2")
|
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::Throw => {
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
format!("throw new Error({})", args[0])
|
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::Rethrow => {
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
format!("throw {}", args[0])
|
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::Module => {
|
|
|
|
assert_eq!(args.len(), 0);
|
|
|
|
if !self.config.mode.no_modules() && !self.config.mode.web() {
|
|
|
|
bail!(
|
|
|
|
"`wasm_bindgen::module` is currently only supported with \
|
|
|
|
`--target no-modules` and `--target web`"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
format!("init.__wbindgen_wasm_module")
|
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::Memory => {
|
|
|
|
assert_eq!(args.len(), 0);
|
2019-12-03 11:16:44 -06:00
|
|
|
let mut memories = self.module.memories.iter();
|
|
|
|
let memory = memories
|
|
|
|
.next()
|
|
|
|
.ok_or_else(|| anyhow!("no memory found to return in memory intrinsic"))?
|
|
|
|
.id();
|
|
|
|
if memories.next().is_some() {
|
|
|
|
bail!(
|
|
|
|
"multiple memories found, unsure which to return \
|
|
|
|
from memory intrinsic"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
drop(memories);
|
|
|
|
format!("wasm.{}", self.export_name_of(memory))
|
2019-06-10 07:09:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::FunctionTable => {
|
|
|
|
assert_eq!(args.len(), 0);
|
2019-12-03 13:01:40 -06:00
|
|
|
let name = self.export_function_table()?;
|
|
|
|
format!("wasm.{}", name)
|
2019-06-10 07:09:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::DebugString => {
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
self.expose_debug_string();
|
|
|
|
format!("debugString({})", args[0])
|
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::JsonParse => {
|
|
|
|
assert_eq!(args.len(), 1);
|
|
|
|
format!("JSON.parse({})", args[0])
|
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::JsonSerialize => {
|
|
|
|
assert_eq!(args.len(), 1);
|
2019-09-23 08:08:34 -07:00
|
|
|
// Turns out `JSON.stringify(undefined) === undefined`, so if
|
|
|
|
// we're passed `undefined` reinterpret it as `null` for JSON
|
|
|
|
// purposes.
|
|
|
|
prelude.push_str(&format!("const obj = {};\n", args[0]));
|
|
|
|
"JSON.stringify(obj === undefined ? null : obj)".to_string()
|
2019-06-10 07:09:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::AnyrefHeapLiveCount => {
|
|
|
|
assert_eq!(args.len(), 0);
|
Add reference output tests for JS operations (#1894)
* 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
2019-12-04 12:01:39 -06:00
|
|
|
self.expose_global_heap();
|
|
|
|
prelude.push_str(
|
|
|
|
"
|
|
|
|
let free_count = 0;
|
|
|
|
let next = heap_next;
|
|
|
|
while (next < heap.length) {
|
|
|
|
free_count += 1;
|
|
|
|
next = heap[next];
|
|
|
|
}
|
|
|
|
",
|
|
|
|
);
|
|
|
|
format!(
|
|
|
|
"heap.length - free_count - {} - {}",
|
|
|
|
INITIAL_HEAP_OFFSET,
|
|
|
|
INITIAL_HEAP_VALUES.len(),
|
|
|
|
)
|
2019-06-10 07:09:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Intrinsic::InitAnyrefTable => {
|
2019-12-03 11:16:44 -06:00
|
|
|
let table = self
|
|
|
|
.aux
|
|
|
|
.anyref_table
|
|
|
|
.ok_or_else(|| anyhow!("must enable anyref to use anyref intrinsic"))?;
|
|
|
|
let name = self.export_name_of(table);
|
2019-08-01 11:59:05 -07:00
|
|
|
// Grow the table to insert our initial values, and then also
|
|
|
|
// set the 0th slot to `undefined` since that's what we've
|
|
|
|
// historically used for our ABI which is that the index of 0
|
|
|
|
// returns `undefined` for types like `None` going out.
|
|
|
|
let mut base = format!(
|
2019-06-10 07:09:51 -07:00
|
|
|
"
|
2019-12-03 11:16:44 -06:00
|
|
|
const table = wasm.{};
|
2019-08-01 11:59:05 -07:00
|
|
|
const offset = table.grow({});
|
|
|
|
table.set(0, undefined);
|
2019-06-10 07:09:51 -07:00
|
|
|
",
|
2019-12-03 11:16:44 -06:00
|
|
|
name,
|
2019-08-01 11:59:05 -07:00
|
|
|
INITIAL_HEAP_VALUES.len(),
|
|
|
|
);
|
|
|
|
for (i, value) in INITIAL_HEAP_VALUES.iter().enumerate() {
|
|
|
|
base.push_str(&format!("table.set(offset + {}, {});\n", i, value));
|
|
|
|
}
|
|
|
|
base
|
2019-06-10 07:09:51 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
Ok(expr)
|
|
|
|
}
|
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
fn generate_enum(&mut self, enum_: &AuxEnum) -> Result<(), Error> {
|
2020-03-03 10:34:28 -05:00
|
|
|
let docs = format_doc_comments(&enum_.comments, None);
|
2018-02-22 12:01:38 +01:00
|
|
|
let mut variants = String::new();
|
|
|
|
|
2020-03-03 10:34:28 -05:00
|
|
|
if enum_.generate_typescript {
|
|
|
|
self.typescript.push_str(&docs);
|
|
|
|
self.typescript
|
|
|
|
.push_str(&format!("export enum {} {{", enum_.name));
|
|
|
|
}
|
2020-04-13 20:51:32 +02:00
|
|
|
for (name, value, comments) in enum_.variants.iter() {
|
|
|
|
let variant_docs = if comments.is_empty() {
|
|
|
|
String::new()
|
|
|
|
} else {
|
|
|
|
format_doc_comments(&comments, None)
|
|
|
|
};
|
|
|
|
if !variant_docs.is_empty() {
|
|
|
|
variants.push_str("\n");
|
|
|
|
variants.push_str(&variant_docs);
|
|
|
|
}
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
variants.push_str(&format!("{}:{},", name, value));
|
2020-03-03 10:34:28 -05:00
|
|
|
if enum_.generate_typescript {
|
2020-04-13 20:51:32 +02:00
|
|
|
self.typescript.push_str("\n");
|
|
|
|
if !variant_docs.is_empty() {
|
|
|
|
self.typescript.push_str(&variant_docs);
|
|
|
|
}
|
|
|
|
self.typescript.push_str(&format!(" {},", name));
|
2020-03-03 10:34:28 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if enum_.generate_typescript {
|
|
|
|
self.typescript.push_str("\n}\n");
|
2018-02-22 12:01:38 +01:00
|
|
|
}
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
self.export(
|
2018-06-27 22:42:34 -07:00
|
|
|
&enum_.name,
|
|
|
|
&format!("Object.freeze({{ {} }})", variants),
|
2020-03-03 10:34:28 -05:00
|
|
|
Some(&docs),
|
2019-05-01 13:53:31 -07:00
|
|
|
)?;
|
2018-02-23 17:30:18 +01:00
|
|
|
|
2019-05-01 13:53:31 -07:00
|
|
|
Ok(())
|
2018-02-22 12:01:38 +01:00
|
|
|
}
|
2018-03-21 09:55:16 -07:00
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
fn generate_struct(&mut self, struct_: &AuxStruct) -> Result<(), Error> {
|
|
|
|
let class = require_class(&mut self.exported_classes, &struct_.name);
|
2018-10-10 10:21:19 -07:00
|
|
|
class.comments = format_doc_comments(&struct_.comments, None);
|
2019-11-26 10:39:57 -08:00
|
|
|
class.is_inspectable = struct_.is_inspectable;
|
2018-10-10 10:21:19 -07:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
fn process_package_json(&mut self, path: &Path) -> Result<(), Error> {
|
2020-04-27 17:14:05 +02:00
|
|
|
if self.config.mode.no_modules() {
|
2019-03-26 08:00:16 -07:00
|
|
|
bail!(
|
|
|
|
"NPM dependencies have been specified in `{}` but \
|
2020-04-27 17:14:05 +02:00
|
|
|
this is incompatible with the `no-modules` target",
|
2019-05-30 10:56:59 -07:00
|
|
|
path.display(),
|
2019-03-26 08:00:16 -07:00
|
|
|
);
|
2019-02-27 12:20:33 -08:00
|
|
|
}
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
|
|
|
|
let contents =
|
|
|
|
fs::read_to_string(path).context(format!("failed to read `{}`", path.display()))?;
|
2019-02-27 12:20:33 -08:00
|
|
|
let json: serde_json::Value = serde_json::from_str(&contents)?;
|
|
|
|
let object = match json.as_object() {
|
|
|
|
Some(s) => s,
|
|
|
|
None => bail!(
|
|
|
|
"expected `package.json` to have an JSON object in `{}`",
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
path.display()
|
2019-02-27 12:20:33 -08:00
|
|
|
),
|
|
|
|
};
|
|
|
|
let mut iter = object.iter();
|
2020-01-21 20:04:40 +01:00
|
|
|
let mut value = None;
|
|
|
|
while let Some((key, v)) = iter.next() {
|
|
|
|
if key == "dependencies" {
|
|
|
|
value = Some(v);
|
|
|
|
break;
|
|
|
|
}
|
2019-02-27 12:20:33 -08:00
|
|
|
}
|
2020-01-21 20:04:40 +01:00
|
|
|
let value = if let Some(value) = value {
|
|
|
|
value
|
|
|
|
} else {
|
|
|
|
return Ok(());
|
|
|
|
};
|
2019-02-27 12:20:33 -08:00
|
|
|
let value = match value.as_object() {
|
|
|
|
Some(s) => s,
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
None => bail!(
|
|
|
|
"expected `dependencies` to be a JSON object in `{}`",
|
|
|
|
path.display()
|
|
|
|
),
|
2019-02-27 12:20:33 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
for (name, value) in value.iter() {
|
|
|
|
let value = match value.as_str() {
|
|
|
|
Some(s) => s,
|
|
|
|
None => bail!(
|
|
|
|
"keys in `dependencies` are expected to be strings in `{}`",
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
path.display()
|
2019-02-27 12:20:33 -08:00
|
|
|
),
|
|
|
|
};
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
if let Some((prev, _prev_version)) = self.npm_dependencies.get(name) {
|
2019-02-27 12:20:33 -08:00
|
|
|
bail!(
|
|
|
|
"dependency on NPM package `{}` specified in two `package.json` files, \
|
|
|
|
which at the time is not allowed:\n * {}\n * {}",
|
|
|
|
name,
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
path.display(),
|
|
|
|
prev.display(),
|
2019-02-27 12:20:33 -08:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
self.npm_dependencies
|
|
|
|
.insert(name.to_string(), (path.to_path_buf(), value.to_string()));
|
2019-02-27 12:20:33 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2018-11-12 11:59:13 -08:00
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
fn expose_debug_string(&mut self) {
|
|
|
|
if !self.should_write_global("debug_string") {
|
|
|
|
return;
|
2018-11-12 11:59:13 -08:00
|
|
|
}
|
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
self.global(
|
|
|
|
"
|
|
|
|
function debugString(val) {
|
|
|
|
// primitive types
|
|
|
|
const type = typeof val;
|
|
|
|
if (type == 'number' || type == 'boolean' || val == null) {
|
|
|
|
return `${val}`;
|
|
|
|
}
|
|
|
|
if (type == 'string') {
|
|
|
|
return `\"${val}\"`;
|
|
|
|
}
|
|
|
|
if (type == 'symbol') {
|
|
|
|
const description = val.description;
|
|
|
|
if (description == null) {
|
|
|
|
return 'Symbol';
|
|
|
|
} else {
|
|
|
|
return `Symbol(${description})`;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (type == 'function') {
|
|
|
|
const name = val.name;
|
|
|
|
if (typeof name == 'string' && name.length > 0) {
|
|
|
|
return `Function(${name})`;
|
|
|
|
} else {
|
|
|
|
return 'Function';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// objects
|
|
|
|
if (Array.isArray(val)) {
|
|
|
|
const length = val.length;
|
|
|
|
let debug = '[';
|
|
|
|
if (length > 0) {
|
|
|
|
debug += debugString(val[0]);
|
|
|
|
}
|
|
|
|
for(let i = 1; i < length; i++) {
|
|
|
|
debug += ', ' + debugString(val[i]);
|
|
|
|
}
|
|
|
|
debug += ']';
|
|
|
|
return debug;
|
|
|
|
}
|
|
|
|
// Test for built-in
|
|
|
|
const builtInMatches = /\\[object ([^\\]]+)\\]/.exec(toString.call(val));
|
|
|
|
let className;
|
|
|
|
if (builtInMatches.length > 1) {
|
|
|
|
className = builtInMatches[1];
|
|
|
|
} else {
|
|
|
|
// Failed to match the standard '[object ClassName]'
|
|
|
|
return toString.call(val);
|
|
|
|
}
|
|
|
|
if (className == 'Object') {
|
|
|
|
// we're a user defined class or Object
|
|
|
|
// JSON.stringify avoids problems with cycles, and is generally much
|
|
|
|
// easier than looping through ownProperties of `val`.
|
|
|
|
try {
|
|
|
|
return 'Object(' + JSON.stringify(val) + ')';
|
|
|
|
} catch (_) {
|
|
|
|
return 'Object';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// errors
|
|
|
|
if (val instanceof Error) {
|
2019-05-30 08:47:16 -07:00
|
|
|
return `${val.name}: ${val.message}\\n${val.stack}`;
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
}
|
|
|
|
// TODO we could test for more things here, like `Set`s and `Map`s.
|
|
|
|
return className;
|
|
|
|
}
|
|
|
|
",
|
|
|
|
);
|
2018-07-30 10:50:43 -07:00
|
|
|
}
|
2019-06-04 08:52:54 -07:00
|
|
|
|
2019-12-03 13:01:40 -06:00
|
|
|
fn export_function_table(&mut self) -> Result<String, Error> {
|
2020-01-21 13:02:13 -06:00
|
|
|
match self.aux.function_table {
|
2019-12-03 13:01:40 -06:00
|
|
|
Some(id) => Ok(self.export_name_of(id)),
|
2019-06-04 08:52:54 -07:00
|
|
|
None => bail!("no function table found in module"),
|
2019-12-03 13:01:40 -06:00
|
|
|
}
|
2019-06-04 08:52:54 -07:00
|
|
|
}
|
2019-12-03 11:16:44 -06:00
|
|
|
|
|
|
|
fn export_name_of(&mut self, id: impl Into<walrus::ExportItem>) -> String {
|
|
|
|
let id = id.into();
|
|
|
|
let export = self.module.exports.iter().find(|e| {
|
|
|
|
use walrus::ExportItem::*;
|
|
|
|
|
|
|
|
match (e.item, id) {
|
|
|
|
(Function(a), Function(b)) => a == b,
|
|
|
|
(Table(a), Table(b)) => a == b,
|
|
|
|
(Memory(a), Memory(b)) => a == b,
|
|
|
|
(Global(a), Global(b)) => a == b,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if let Some(export) = export {
|
|
|
|
return export.name.clone();
|
|
|
|
}
|
Add reference output tests for JS operations (#1894)
* 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
2019-12-04 12:01:39 -06:00
|
|
|
let default_name = format!("__wbindgen_export_{}", self.next_export_idx);
|
2019-12-03 11:16:44 -06:00
|
|
|
self.next_export_idx += 1;
|
Add reference output tests for JS operations (#1894)
* 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
2019-12-04 12:01:39 -06:00
|
|
|
let name = match id {
|
|
|
|
walrus::ExportItem::Function(f) => match &self.module.funcs.get(f).name {
|
|
|
|
Some(s) => to_js_identifier(s),
|
|
|
|
None => default_name,
|
|
|
|
},
|
|
|
|
_ => default_name,
|
|
|
|
};
|
2019-12-03 11:16:44 -06:00
|
|
|
self.module.exports.add(&name, id);
|
|
|
|
return name;
|
Add reference output tests for JS operations (#1894)
* 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
2019-12-04 12:01:39 -06:00
|
|
|
|
|
|
|
// Not really an exhaustive list, but works for our purposes.
|
|
|
|
fn to_js_identifier(name: &str) -> String {
|
|
|
|
name.chars()
|
|
|
|
.map(|c| {
|
|
|
|
if c.is_ascii() && (c.is_alphabetic() || c.is_numeric()) {
|
|
|
|
c
|
|
|
|
} else {
|
|
|
|
'_'
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect()
|
|
|
|
}
|
2019-12-03 11:16:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
fn adapter_name(&self, id: AdapterId) -> String {
|
|
|
|
format!("__wbg_adapter_{}", id.0)
|
|
|
|
}
|
2020-04-15 21:28:29 +08:00
|
|
|
|
|
|
|
fn generate_identifier(&mut self, name: &str) -> String {
|
|
|
|
let cnt = self
|
|
|
|
.defined_identifiers
|
|
|
|
.entry(name.to_string())
|
|
|
|
.or_insert(0);
|
|
|
|
*cnt += 1;
|
|
|
|
// We want to mangle `default` at once, so we can support default exports and don't generate
|
|
|
|
// invalid glue code like this: `import { default } from './module';`.
|
|
|
|
if *cnt == 1 && name != "default" {
|
|
|
|
name.to_string()
|
|
|
|
} else {
|
|
|
|
format!("{}{}", name, cnt)
|
|
|
|
}
|
|
|
|
}
|
2018-07-30 10:50:43 -07:00
|
|
|
}
|
|
|
|
|
2019-06-17 15:09:39 -03:00
|
|
|
fn check_duplicated_getter_and_setter_names(
|
2019-12-03 09:28:42 -08:00
|
|
|
exports: &[(&AdapterId, &AuxExport)],
|
2019-06-17 15:09:39 -03:00
|
|
|
) -> Result<(), Error> {
|
|
|
|
let verify_exports =
|
|
|
|
|first_class, first_field, second_class, second_field| -> Result<(), Error> {
|
|
|
|
let both_are_in_the_same_class = first_class == second_class;
|
|
|
|
let both_are_referencing_the_same_field = first_field == second_field;
|
|
|
|
if both_are_in_the_same_class && both_are_referencing_the_same_field {
|
|
|
|
bail!(format!(
|
|
|
|
"There can be only one getter/setter definition for `{}` in `{}`",
|
|
|
|
first_field, first_class
|
|
|
|
));
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
};
|
|
|
|
for (idx, (_, first_export)) in exports.iter().enumerate() {
|
|
|
|
for (_, second_export) in exports.iter().skip(idx + 1) {
|
|
|
|
match (&first_export.kind, &second_export.kind) {
|
|
|
|
(
|
|
|
|
AuxExportKind::Getter {
|
|
|
|
class: first_class,
|
|
|
|
field: first_field,
|
|
|
|
},
|
|
|
|
AuxExportKind::Getter {
|
|
|
|
class: second_class,
|
|
|
|
field: second_field,
|
|
|
|
},
|
|
|
|
) => verify_exports(first_class, first_field, second_class, second_field)?,
|
|
|
|
(
|
|
|
|
AuxExportKind::Setter {
|
|
|
|
class: first_class,
|
|
|
|
field: first_field,
|
|
|
|
},
|
|
|
|
AuxExportKind::Setter {
|
|
|
|
class: second_class,
|
|
|
|
field: second_field,
|
|
|
|
},
|
|
|
|
) => verify_exports(first_class, first_field, second_class, second_field)?,
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
fn format_doc_comments(comments: &str, js_doc_comments: Option<String>) -> String {
|
|
|
|
let body: String = comments.lines().map(|c| format!("*{}\n", c)).collect();
|
2018-07-09 11:07:57 -05:00
|
|
|
let doc = if let Some(docs) = js_doc_comments {
|
2018-07-13 22:36:51 -07:00
|
|
|
docs.lines().map(|l| format!("* {} \n", l)).collect()
|
2018-07-09 11:07:57 -05:00
|
|
|
} else {
|
|
|
|
String::new()
|
|
|
|
};
|
|
|
|
format!("/**\n{}{}*/\n", body, doc)
|
2018-06-27 22:42:34 -07:00
|
|
|
}
|
2018-12-11 20:42:37 +02:00
|
|
|
|
2019-04-30 10:26:03 -03:00
|
|
|
fn require_class<'a>(
|
|
|
|
exported_classes: &'a mut Option<BTreeMap<String, ExportedClass>>,
|
|
|
|
name: &str,
|
|
|
|
) -> &'a mut ExportedClass {
|
|
|
|
exported_classes
|
|
|
|
.as_mut()
|
|
|
|
.expect("classes already written")
|
|
|
|
.entry(name.to_string())
|
|
|
|
.or_insert_with(ExportedClass::default)
|
|
|
|
}
|
|
|
|
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
impl ExportedClass {
|
2020-03-03 10:34:28 -05:00
|
|
|
fn push(
|
|
|
|
&mut self,
|
|
|
|
docs: &str,
|
|
|
|
function_name: &str,
|
|
|
|
function_prefix: &str,
|
|
|
|
js: &str,
|
|
|
|
ts: Option<&str>,
|
|
|
|
) {
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
self.contents.push_str(docs);
|
|
|
|
self.contents.push_str(function_prefix);
|
|
|
|
self.contents.push_str(function_name);
|
|
|
|
self.contents.push_str(js);
|
|
|
|
self.contents.push_str("\n");
|
2020-03-03 10:34:28 -05:00
|
|
|
if let Some(ts) = ts {
|
|
|
|
self.typescript.push_str(docs);
|
|
|
|
self.typescript.push_str(" ");
|
|
|
|
self.typescript.push_str(function_prefix);
|
|
|
|
self.typescript.push_str(function_name);
|
|
|
|
self.typescript.push_str(ts);
|
|
|
|
self.typescript.push_str(";\n");
|
|
|
|
}
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
}
|
2019-05-30 10:56:59 -07:00
|
|
|
|
2019-06-06 16:11:51 -03:00
|
|
|
/// Used for adding a getter to a class, mainly to ensure that TypeScript
|
2019-05-30 10:56:59 -07:00
|
|
|
/// generation is handled specially.
|
2020-03-03 10:34:28 -05:00
|
|
|
fn push_getter(&mut self, docs: &str, field: &str, js: &str, ret_ty: Option<&str>) {
|
|
|
|
self.push_accessor(docs, field, js, "get ");
|
|
|
|
if let Some(ret_ty) = ret_ty {
|
2020-04-13 20:51:32 +02:00
|
|
|
self.push_accessor_ts(docs, field, ret_ty, false);
|
2020-03-03 10:34:28 -05:00
|
|
|
}
|
2019-11-26 10:39:57 -08:00
|
|
|
self.readable_properties.push(field.to_string());
|
2019-06-06 16:11:51 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Used for adding a setter to a class, mainly to ensure that TypeScript
|
|
|
|
/// generation is handled specially.
|
2020-02-18 23:15:37 +08:00
|
|
|
fn push_setter(
|
|
|
|
&mut self,
|
|
|
|
docs: &str,
|
|
|
|
field: &str,
|
|
|
|
js: &str,
|
2020-03-03 10:34:28 -05:00
|
|
|
ret_ty: Option<&str>,
|
2020-02-18 23:15:37 +08:00
|
|
|
might_be_optional_field: bool,
|
|
|
|
) {
|
2020-03-03 10:34:28 -05:00
|
|
|
self.push_accessor(docs, field, js, "set ");
|
|
|
|
if let Some(ret_ty) = ret_ty {
|
2020-04-13 20:51:32 +02:00
|
|
|
let is_optional = self.push_accessor_ts(docs, field, ret_ty, true);
|
2020-03-03 10:34:28 -05:00
|
|
|
*is_optional = might_be_optional_field;
|
|
|
|
}
|
2019-06-06 16:11:51 -03:00
|
|
|
}
|
|
|
|
|
2020-04-13 20:51:32 +02:00
|
|
|
fn push_accessor_ts(
|
|
|
|
&mut self,
|
|
|
|
docs: &str,
|
|
|
|
field: &str,
|
|
|
|
ret_ty: &str,
|
|
|
|
is_setter: bool,
|
|
|
|
) -> &mut bool {
|
|
|
|
let (ty, accessor_docs, has_setter, is_optional) = self
|
2019-05-30 10:56:59 -07:00
|
|
|
.typescript_fields
|
|
|
|
.entry(field.to_string())
|
|
|
|
.or_insert_with(Default::default);
|
2020-02-18 23:15:37 +08:00
|
|
|
|
2019-06-06 16:11:51 -03:00
|
|
|
*ty = ret_ty.to_string();
|
2020-04-13 20:51:32 +02:00
|
|
|
// Deterministic output: always use the getter's docs if available
|
|
|
|
if !docs.is_empty() && (accessor_docs.is_empty() || !is_setter) {
|
|
|
|
*accessor_docs = docs.to_owned();
|
|
|
|
}
|
|
|
|
*has_setter |= is_setter;
|
|
|
|
is_optional
|
2019-05-30 10:56:59 -07:00
|
|
|
}
|
2020-03-03 10:34:28 -05:00
|
|
|
|
|
|
|
fn push_accessor(&mut self, docs: &str, field: &str, js: &str, prefix: &str) {
|
|
|
|
self.contents.push_str(docs);
|
|
|
|
self.contents.push_str(prefix);
|
|
|
|
self.contents.push_str(field);
|
|
|
|
self.contents.push_str(js);
|
|
|
|
self.contents.push_str("\n");
|
|
|
|
}
|
First refactor for WebIDL bindings
This commit starts the `wasm-bindgen` CLI tool down the road to being a
true polyfill for WebIDL bindings. This refactor is probably the first
of a few, but is hopefully the largest and most sprawling and everything
will be a bit more targeted from here on out.
The goal of this refactoring is to separate out the massive
`crates/cli-support/src/js/mod.rs` into a number of separate pieces of
functionality. It currently takes care of basically everything
including:
* Binding intrinsics
* Handling anyref transformations
* Generating all JS for imports/exports
* All the logic for how to import and how to name imports
* Execution and management of wasm-bindgen closures
Many of these are separable concerns and most overlap with WebIDL
bindings. The internal refactoring here is intended to make it more
clear who's responsible for what as well as making some existing
operations much more straightforward. At a high-level, the following
changes are done:
1. A `src/webidl.rs` module is introduced. The purpose of this module is
to take all of the raw wasm-bindgen custom sections from the module
and transform them into a WebIDL bindings section.
This module has a placeholder `WebidlCustomSection` which is nowhere
near the actual custom section but if you squint is in theory very
similar. It's hoped that this will eventually become the true WebIDL
custom section, currently being developed in an external crate.
Currently, however, the WebIDL bindings custom section only covers a
subset of the functionality we export to wasm-bindgen users. To avoid
leaving them high and dry this module also contains an auxiliary
custom section named `WasmBindgenAux`. This custom section isn't
intended to have a binary format, but is intended to represent a
theoretical custom section necessary to couple with WebIDL bindings to
achieve all our desired functionality in `wasm-bindgen`. It'll never
be standardized, but it'll also never be serialized :)
2. The `src/webidl.rs` module now takes over quite a bit of
functionality from `src/js/mod.rs`. Namely it handles synthesis of an
`export_map` and an `import_map` mapping export/import IDs to exactly
what's expected to be hooked up there. This does not include type
information (as that's in the bindings section) but rather includes
things like "this is the method of class A" or "this import is from
module `foo`" and things like that. These could arguably be subsumed
by future JS features as well, but that's for another time!
3. All handling of wasm-bindgen "descriptor functions" now happens in a
dedicated `src/descriptors.rs` module. The output of this module is
its own custom section (intended to be immediately consumed by the
WebIDL module) which is in theory what we want to ourselves emit one
day but rustc isn't capable of doing so right now.
4. Invocations and generations of imports are completely overhauled.
Using the `import_map` generated in the WebIDL step all imports are
now handled much more precisely in one location rather than
haphazardly throughout the module. This means we have precise
information about each import of the module and we only modify
exactly what we're looking at. This also vastly simplifies intrinsic
generation since it's all simply a codegen part of the `rust2js.rs`
module now.
5. Handling of direct imports which don't have a JS shim generated is
slightly different from before and is intended to be
future-compatible with WebIDL bindings in its full glory, but we'll
need to update it to handle cases for constructors and method calls
eventually as well.
6. Intrinsic definitions now live in their own file (`src/intrinsic.rs`)
and have a separated definition for their symbol name and signature.
The actual implementation of each intrinsic lives in `rust2js.rs`
There's a number of TODO items to finish before this merges. This
includes reimplementing the anyref pass and actually implementing import
maps for other targets. Those will come soon in follow-up commits, but
the entire `tests/wasm/main.rs` suite is currently passing and this
seems like a good checkpoint.
2019-05-23 09:15:26 -07:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:16:44 -06:00
|
|
|
struct MemView {
|
|
|
|
name: &'static str,
|
|
|
|
num: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for MemView {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
write!(f, "{}{}", self.name, self.num)
|
|
|
|
}
|
|
|
|
}
|