Merge branch 'master' into non-rustup-env

master
Jesper Håkansson 6 years ago
commit 740b8b896e
  1. 3
      .appveyor.yml
  2. 7
      .travis.yml
  3. 468
      Cargo.lock
  4. 3
      binary-install/Cargo.toml
  5. 102
      binary-install/src/lib.rs
  6. 142
      binary-install/tests/all/cache.rs
  7. 125
      binary-install/tests/all/download.rs
  8. 7
      binary-install/tests/all/main.rs
  9. 79
      binary-install/tests/all/utils/mod.rs
  10. 1
      clippy.toml
  11. 44
      docs/_theme/header.hbs
  12. 1
      docs/src/SUMMARY.md
  13. 24
      docs/src/commands/build.md
  14. 35
      docs/src/tutorial/template-deep-dive/src-lib-rs.md
  15. 54
      docs/src/tutorial/template-deep-dive/wee_alloc.md
  16. 13
      src/bindgen.rs
  17. 4
      src/build.rs
  18. 13
      src/child.rs
  19. 58
      src/command/build.rs
  20. 8
      src/command/login.rs
  21. 11
      src/command/mod.rs
  22. 6
      src/command/publish/mod.rs
  23. 2
      src/command/test.rs
  24. 2
      src/command/utils.rs
  25. 2
      src/installer.rs
  26. 2
      src/lockfile.rs
  27. 7
      src/main.rs
  28. 66
      src/manifest/mod.rs
  29. 4
      src/npm.rs
  30. 8
      src/progressbar.rs
  31. 4
      src/readme.rs
  32. 4
      tests/all/bindgen.rs
  33. 5
      tests/all/build.rs
  34. 10
      tests/all/license.rs
  35. 12
      tests/all/lockfile.rs
  36. 59
      tests/all/manifest.rs
  37. 19
      tests/all/test.rs
  38. 51
      tests/all/utils/fixture.rs

@ -17,6 +17,9 @@ build: false
test_script:
- cargo test --release --tests --locked
- cargo test --release --doc
- cd binary-install
- cargo test
- cd ..
before_deploy:
- ps: |

@ -47,10 +47,13 @@ matrix:
install:
- *INSTALL_NODE_VIA_NVM
script:
- cargo test --locked
- cargo test --all --locked
- rustup component add rustfmt-preview
- cargo fmt --version
- cargo fmt --all -- --check
- rustup component add clippy-preview
- cargo clippy --version
- cargo clippy
- name: Book
rust: stable
@ -59,7 +62,7 @@ matrix:
- (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.2" mdbook)
- cargo install-update -a
script:
- (cd docs && mdbook build)
- (cd docs && mv _theme theme && mdbook build)
- rustc ./docs/_installer/build-installer.rs
- ./build-installer
deploy:

468
Cargo.lock generated

File diff suppressed because it is too large Load Diff

@ -18,3 +18,6 @@ is_executable = "0.1.2"
siphasher = "0.2.3"
tar = "0.4.16"
zip = "0.5.0"
[dev-dependencies]
tempfile = "3.0.5"

@ -23,11 +23,13 @@ use std::path::{Path, PathBuf};
/// Global cache for wasm-pack, currently containing binaries downloaded from
/// urls like wasm-bindgen and such.
#[derive(Debug)]
pub struct Cache {
destination: PathBuf,
}
/// Representation of a downloaded tarball/zip
#[derive(Debug)]
pub struct Download {
root: PathBuf,
}
@ -81,22 +83,10 @@ impl Cache {
binaries: &[&str],
url: &str,
) -> Result<Option<Download>, Error> {
let mut hasher = SipHasher13::new();
url.hash(&mut hasher);
let result = hasher.finish();
let hex = hex::encode(&[
(result >> 0) as u8,
(result >> 8) as u8,
(result >> 16) as u8,
(result >> 24) as u8,
(result >> 32) as u8,
(result >> 40) as u8,
(result >> 48) as u8,
(result >> 56) as u8,
]);
let dirname = format!("{}-{}", name, hex);
let dirname = hashed_dirname(url, name);
let destination = self.destination.join(&dirname);
if destination.exists() {
return Ok(Some(Download { root: destination }));
}
@ -270,3 +260,87 @@ fn curl(url: &str) -> Result<Vec<u8>, Error> {
)
}
}
fn hashed_dirname(url: &str, name: &str) -> String {
let mut hasher = SipHasher13::new();
url.hash(&mut hasher);
let result = hasher.finish();
let hex = hex::encode(&[
(result >> 0) as u8,
(result >> 8) as u8,
(result >> 16) as u8,
(result >> 24) as u8,
(result >> 32) as u8,
(result >> 40) as u8,
(result >> 48) as u8,
(result >> 56) as u8,
]);
format!("{}-{}", name, hex)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_returns_same_hash_for_same_name_and_url() {
let name = "wasm-pack";
let url = "http://localhost:7878/wasm-pack-v0.6.0.tar.gz";
let first = hashed_dirname(url, name);
let second = hashed_dirname(url, name);
assert!(!first.is_empty());
assert!(!second.is_empty());
assert_eq!(first, second);
}
#[test]
fn it_returns_different_hashes_for_different_urls() {
let name = "wasm-pack";
let url = "http://localhost:7878/wasm-pack-v0.5.1.tar.gz";
let second_url = "http://localhost:7878/wasm-pack-v0.6.0.tar.gz";
let first = hashed_dirname(url, name);
let second = hashed_dirname(second_url, name);
assert_ne!(first, second);
}
#[test]
fn it_returns_cache_dir() {
let name = "wasm-pack";
let cache = Cache::new(name);
let expected = dirs::cache_dir()
.unwrap()
.join(PathBuf::from(".".to_owned() + name));
assert!(cache.is_ok());
assert_eq!(cache.unwrap().destination, expected);
}
#[test]
fn it_returns_destination_if_binary_already_exists() {
use std::fs;
let binary_name = "wasm-pack";
let binaries = vec![binary_name];
let dir = tempfile::TempDir::new().unwrap();
let cache = Cache::at(dir.path());
let url = &format!("{}/{}.tar.gz", "http://localhost:7878", binary_name);
let dirname = hashed_dirname(&url, &binary_name);
let full_path = dir.path().join(dirname);
// Create temporary directory and binary to simulate that
// a cached binary already exists.
fs::create_dir_all(full_path).unwrap();
let dl = cache.download(true, binary_name, &binaries, url);
assert!(dl.is_ok());
assert!(dl.unwrap().is_some())
}
}

@ -0,0 +1,142 @@
use binary_install::Cache;
use std::path::Path;
use utils;
#[test]
fn it_returns_none_if_install_is_not_permitted() {
let binary_name = "wasm-pack";
let binaries = vec![binary_name];
let dir = tempfile::TempDir::new().unwrap();
let cache = Cache::at(dir.path());
let dl = cache.download(
false,
binary_name,
&binaries,
&format!("{}/{}.tar.gz", "", binary_name),
);
assert!(dl.is_ok());
assert!(dl.unwrap().is_none())
}
#[test]
fn it_downloads_tarball() {
let binary_name = "wasm-pack";
let binaries = vec![binary_name];
// Create a temporary tarball.
let tarball = utils::create_tarball(binary_name).ok();
// Spin up a local TcpListener.
let server_port = utils::start_server(tarball, None).recv().unwrap();
let url = format!("http://{}:{}", utils::TEST_SERVER_HOST, server_port);
let dir = tempfile::TempDir::new().unwrap();
let cache = Cache::at(dir.path());
let dl = cache.download(
true,
binary_name,
&binaries,
&format!("{}/{}.tar.gz", &url, binary_name),
);
assert!(dl.is_ok());
assert!(dl.unwrap().is_some())
}
#[test]
fn it_returns_error_when_it_failed_to_download() {
let server_port = 7881;
let url = format!("http://{}:{}", utils::TEST_SERVER_HOST, server_port);
let binary_name = "wasm-pack";
let binaries = vec![binary_name];
let dir = tempfile::TempDir::new().unwrap();
let cache = Cache::at(dir.path());
let full_url = &format!("{}/{}.tar.gz", &url, binary_name);
let dl = cache.download(true, binary_name, &binaries, full_url);
assert!(dl.is_err());
assert_eq!(
&format!("failed to download from {}", full_url),
&format!("{}", dl.unwrap_err())
);
}
#[test]
fn it_returns_error_when_it_failed_to_extract_tarball() {
let binary_name = "wasm-pack";
let binaries = vec![binary_name];
let dir = tempfile::TempDir::new().unwrap();
let cache = Cache::at(dir.path());
// Spin up a local TcpListener.
let server_port = utils::start_server(None, None).recv().unwrap();
let url = format!("http://{}:{}", utils::TEST_SERVER_HOST, server_port);
let full_url = &format!("{}/{}.tar.gz", &url, binary_name);
let dl = cache.download(true, binary_name, &binaries, full_url);
assert!(dl.is_err());
assert_eq!(
&format!("failed to extract tarball from {}", full_url),
&format!("{}", dl.unwrap_err())
);
}
#[test]
fn it_returns_error_when_it_failed_to_extract_zip() {
let binary_name = "wasm-pack";
let binaries = vec![binary_name];
let dir = tempfile::TempDir::new().unwrap();
let cache = Cache::at(dir.path());
// Spin up a local TcpListener.
let server_port = utils::start_server(None, None).recv().unwrap();
let url = format!("http://{}:{}", utils::TEST_SERVER_HOST, server_port);
let full_url = &format!("{}/{}.zip", &url, binary_name);
let dl = cache.download(true, binary_name, &binaries, full_url);
assert!(dl.is_err());
assert_eq!(
&format!("failed to extract zip from {}", full_url),
&format!("{}", dl.unwrap_err())
);
}
#[test]
#[should_panic(expected = "don't know how to extract http://localhost:7884/wasm-pack.bin")]
fn it_panics_if_not_tarball_or_zip() {
let server_port = 7884;
let binary_name = "wasm-pack";
let binaries = vec![binary_name];
let dir = tempfile::TempDir::new().unwrap();
let cache = Cache::at(dir.path());
// Spin up a local TcpListener.
utils::start_server(None, Some(server_port)).recv().unwrap();
let url = format!("http://{}:{}", utils::TEST_SERVER_HOST, server_port);
let full_url = &format!("{}/{}.bin", &url, binary_name);
let _ = cache.download(true, binary_name, &binaries, full_url);
}
#[test]
fn it_joins_path_with_destination() {
let dir = tempfile::TempDir::new().unwrap();
let cache = Cache::at(dir.path());
assert_eq!(dir.path().join("hello"), cache.join(Path::new("hello")));
}

@ -0,0 +1,125 @@
use binary_install::Download;
use std::fs::OpenOptions;
#[test]
#[cfg(unix)]
fn it_returns_binary_name_for_unix() {
use std::os::unix::fs::OpenOptionsExt;
let binary_name = "wasm-pack";
let dir = tempfile::TempDir::new().unwrap();
let download = Download::at(dir.path());
let full_path = dir.path().join(binary_name);
let mut options = OpenOptions::new();
options.create(true);
options.write(true);
// Make the "binary" an executable.
options.mode(0o755);
options.open(&full_path).unwrap();
let binary = download.binary(binary_name);
assert!(binary.is_ok());
assert_eq!(full_path, binary.unwrap());
}
#[test]
#[cfg(not(windows))]
fn it_bails_if_not_file_for_unix() {
let binary_name = "wasm-pack";
let dir = tempfile::TempDir::new().unwrap();
let download = Download::at(dir.path());
let full_path = dir.path().join(binary_name);
let mut options = OpenOptions::new();
options.create(true);
options.write(true);
let binary = download.binary(binary_name);
assert!(binary.is_err());
assert_eq!(
format!("{} binary does not exist", full_path.to_str().unwrap()),
binary.unwrap_err().to_string()
);
}
#[test]
#[cfg(windows)]
fn it_bails_if_not_file_for_windows() {
let binary_name = "wasm-pack.exe";
let dir = tempfile::TempDir::new().unwrap();
let download = Download::at(dir.path());
let full_path = dir.path().join(binary_name);
let mut options = OpenOptions::new();
options.create(true);
options.write(true);
let binary = download.binary(binary_name);
assert!(binary.is_err());
assert_eq!(
format!("{} binary does not exist", full_path.to_str().unwrap()),
binary.unwrap_err().to_string()
);
}
#[test]
#[cfg(not(windows))]
fn it_bails_if_not_executable_for_unix() {
let binary_name = "wasm-pack";
let dir = tempfile::TempDir::new().unwrap();
let download = Download::at(dir.path());
let full_path = dir.path().join(binary_name);
let mut options = OpenOptions::new();
options.create(true);
options.write(true);
options.open(&full_path).unwrap();
let binary = download.binary(binary_name);
assert!(binary.is_err());
assert_eq!(
format!("{} is not executable", full_path.to_str().unwrap()),
binary.unwrap_err().to_string()
);
}
#[test]
#[cfg(windows)]
fn it_bails_if_not_executable_for_windows() {
let binary_name = "wasm-pack.exe";
let dir = tempfile::TempDir::new().unwrap();
let download = Download::at(dir.path());
let full_path = dir.path().join(binary_name);
let mut options = OpenOptions::new();
options.create(true);
options.write(true);
options.open(&full_path).unwrap();
let binary = download.binary(binary_name);
assert!(binary.is_err());
assert_eq!(
format!("{} is not executable", full_path.to_str().unwrap()),
binary.unwrap_err().to_string()
);
}

@ -0,0 +1,7 @@
extern crate binary_install;
extern crate flate2;
extern crate tar;
mod cache;
mod download;
mod utils;

@ -0,0 +1,79 @@
use flate2::write::GzEncoder;
use flate2::Compression;
use std::fs::{File, OpenOptions};
use std::io::{self, Read, Write};
use std::net::TcpListener;
use std::sync::mpsc::{channel, Receiver};
use std::thread;
pub const TEST_SERVER_HOST: &'static str = "localhost";
pub fn start_server(tarball: Option<Vec<u8>>, server_port: Option<u16>) -> Receiver<u16> {
let (sender, receiver) = channel();
thread::spawn(move || {
TcpListener::bind(format!(
"{}:{}",
TEST_SERVER_HOST,
server_port.unwrap_or_else(|| 0)
))
.map(|listener| {
sender.send(listener.local_addr().unwrap().port()).unwrap();
for stream in listener.incoming() {
let mut stream = stream.unwrap();
let mut buffer = [0; 512];
stream.read(&mut buffer).unwrap();
let response = "HTTP/1.1 200 OK\r\n\r\n";
stream.write(response.as_bytes()).unwrap();
match tarball.to_owned() {
Some(tar) => {
stream.write(tar.as_ref()).unwrap();
}
None => {}
}
stream.flush().unwrap();
}
})
.unwrap();
});
receiver
}
pub fn create_tarball(binary_name: &str) -> Result<Vec<u8>, io::Error> {
let temp_dir = tempfile::TempDir::new().unwrap();
let full_path = temp_dir.path().join(binary_name.to_owned() + ".tar.gz");
let tar = OpenOptions::new()
.create(true)
.read(true)
.write(true)
.open(&full_path)?;
let mut file = OpenOptions::new()
.create(true)
.read(true)
.write(true)
.open(temp_dir.path().join(binary_name))?;
let mut encoder = GzEncoder::new(tar, Compression::default());
{
let mut archive = tar::Builder::new(&mut encoder);
archive.append_file(binary_name, &mut file)?;
}
let mut contents = vec![];
encoder.finish()?;
File::open(temp_dir.path().join(&full_path))?.read_to_end(&mut contents)?;
Ok(contents)
}

@ -0,0 +1 @@
too-many-arguments-threshold = 8

@ -0,0 +1,44 @@
<style>
header.warning {
background-color: rgb(242, 222, 222);
border-bottom-color: rgb(238, 211, 215);
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-bottom-style: solid;
border-bottom-width: 0.666667px;
border-image-outset: 0 0 0 0;
border-image-repeat: stretch stretch;
border-image-slice: 100% 100% 100% 100%;
border-image-source: none;
border-image-width: 1 1 1 1;
border-left-color: rgb(238, 211, 215);
border-left-style: solid;
border-left-width: 0.666667px;
border-right-color: rgb(238, 211, 215);
border-right-style: solid;
border-right-width: 0.666667px;
border-top-color: rgb(238, 211, 215);
border-top-left-radius: 4px;
border-top-right-radius: 4px;
border-top-style: solid;
border-top-width: 0.666667px;
color: rgb(185, 74, 72);
margin-bottom: 0px;
margin-left: 0px;
margin-right: 0px;
margin-top: 30px;
padding-bottom: 8px;
padding-left: 14px;
padding-right: 35px;
padding-top: 8px;
text-align: center;
}
</style>
<header class='warning'>
This is the <strong>unpublished</strong> documentation of
<code>wasm-pack</code>, the published documentation is available
<a href="https://rustwasm.github.io/docs/wasm-pack/">
on the main Rust and WebAssembly documentation site
</a>. Features documented here may not be available in released versions of
<code>wasm-pack</code>.
</header>

@ -16,6 +16,7 @@
- [`Cargo.toml`](./tutorial/template-deep-dive/cargo-toml.md)
- [`src/lib.rs`](./tutorial/template-deep-dive/src-lib-rs.md)
- [`src/utils.rs`](./tutorial/template-deep-dive/src-utils-rs.md)
- [`wee_alloc`](./tutorial/template-deep-dive/wee_alloc.md)
- [Packaging and Publishing](./tutorial/packaging-and-publishing.md)
- [Using your Library](./tutorial/using-your-library.md)
- [`Cargo.toml` Configuration](./cargo-toml-configuration.md)

@ -47,20 +47,26 @@ The exact meaning of the profile flags may evolve as the platform matures.
## Target
The `build` command accepts a `--target` argument. This will customize the output files
to align with a particular type of JS module. This allows wasm-pack to generate either
ES6 modules or CommonJS modules for use in browser and in NodeJS. Defaults to `browser`.
The options are:
The `build` command accepts a `--target` argument. This will customize the JS
that is emitted and how the WebAssembly files are instantiated and loaded. For
more documentation on the various strategies here, see the [documentation on
using the compiled output][deploy].
```
wasm-pack build --target nodejs
```
| Option | Description |
|-----------|-----------------------------------------------------------------------------------------------------------------|
| `nodejs` | Outputs JS that uses CommonJS modules, for use with a `require` statement. `main` key in `package.json`. |
| `no-modules` | Outputs JS that use no modules. `browser` key in `package.json`. |
| `browser` | Outputs JS that uses ES6 modules, primarily for use with `import` statements and/or bundlers such as `webpack`. `module` key in `package.json`. `sideEffects: false` by default. |
| Option | Usage | Description |
|-----------|------------|-----------------------------------------------------------------------------------------------------|
| *not specified* or `bundler` | [Bundler][bundlers] | Outputs JS that is suitable for interoperation with a Bundler like Webpack. You'll `import` the JS and the `module` key is specified in `package.json`. `sideEffects: false` is by default. |
| `nodejs` | [Node.js][deploy-nodejs] | Outputs JS that uses CommonJS modules, for use with a `require` statement. `main` key in `package.json`. |
| `web` | [Native in browser][deploy-web] | Outputs JS that can be natively imported as an ES module in a browser, but the WebAssembly must be manually instantiated and loaded. |
| `no-modules` | [Native in browser][deploy-web] | Same as `web`, except the JS is included on a page and modifies global state, and doesn't support as many `wasm-bindgen` features as `web` |
[deploy]: https://rustwasm.github.io/docs/wasm-bindgen/reference/deployment.html
[bundlers]: https://rustwasm.github.io/docs/wasm-bindgen/reference/deployment.html#bundlers
[deploy-nodejs]: https://rustwasm.github.io/docs/wasm-bindgen/reference/deployment.html#nodejs
[deploy-web]: https://rustwasm.github.io/docs/wasm-bindgen/reference/deployment.html#without-a-bundler
## Scope

@ -72,19 +72,7 @@ use cfg_if::cfg_if;
`use` allows us to conveniently refer to parts of a crate or module. For example, suppose the crate `cfg_if` contains a function `func`. It is always possible to call this function directly by writing `cfg_if::func()`. However, this is often tedious to write. If we first specify `use cfg_if::func;`, then `func` can be called by just writing `func()` instead.
With this in mind, this `use` allows us to call the macro `cfg_if!` inside the crate `cfg_if` without writing `cfg_if::cfg_if!`.
```rust
use wasm_bindgen::prelude::*;
```
Many modules contain a prelude, a list of things that should be automatically imported. This allows common features of the module to be conveniently accessed without a lengthy prefix. For example, in this file we can use `#[wasm_bindgen]` only because it is brought into scope by the prelude.
The asterisk at the end of this `use` indicates that everything inside the module `wasm_bindgen::prelude` (i.e. the module `prelude` inside the crate `wasm_bindgen`) can be referred to without prefixing it with `wasm_bindgen::prelude`.
For example, `#[wasm_bindgen]` could also be written as `#[wasm_bindgen::prelude::wasm_bindgen]`, although this is not recommended.
## 3. `wee_alloc` optional dependecy
With this in mind, this `use` allows us to call the macro `cfg_if!` inside the crate `cfg_if` without writing `cfg_if::cfg_if!`. We use `cfg_if!` to configure `wee_alloc`, which we will talk more about in a [separate section](./wee_alloc.md):
```rust
cfg_if! {
@ -96,8 +84,6 @@ cfg_if! {
}
```
This code block is intended to initialize `wee_alloc` as the global memory allocator, but only if the `wee_alloc` feature is enabled in `Cargo.toml`.
We immediately notice that `cfg_if!` is a macro because it ends in `!`, similarly to other Rust macros such as `println!` and `vec!`. A macro is directly replaced by other code during compile time.
During compile time, `cfg_if!` evaluates the `if` statement. This tests whether the feature `wee_alloc` is present in the `[features]` section of `Cargo.toml` (among other possible ways to set it).
@ -105,23 +91,12 @@ During compile time, `cfg_if!` evaluates the `if` statement. This tests whether
As we saw earlier, the `default` vector in `[features]` only contains `"console_error_panic_hook"` and not `"wee_alloc"`. So, in this case, the `cfg_if!` block will be replaced by no code at all, and hence the default memory allocator will be used instead of `wee_alloc`.
```rust
extern crate wee_alloc;
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
use wasm_bindgen::prelude::*;
```
However, suppose `"wee_alloc"` is appended to the `default` vector in `Cargo.toml`. Then, the `cfg_if!` block is instead replaced with the contents of the `if` block, shown above.
This code sets the `wee_alloc` allocator to be used as the global memory allocator.
### What is `wee_alloc`?
Reducing the size of compiled WebAssembly code is important, since it is often transmitted over the Internet or placed on embedded devices.
> `wee_alloc` is a tiny allocator designed for WebAssembly that has a (pre-compression) code-size footprint of only a single kilobyte.
Many modules contain a prelude, a list of things that should be automatically imported. This allows common features of the module to be conveniently accessed without a lengthy prefix. For example, in this file we can use `#[wasm_bindgen]` only because it is brought into scope by the prelude.
[An analysis](http://fitzgeraldnick.com/2018/02/09/wee-alloc.html) suggests that over half of the bare minimum WebAssembly memory footprint is required by Rust's default memory allocator. Yet, WebAssembly code often does not require a sophisticated allocator, since it often just requests a couple of large initial allocations.
The asterisk at the end of this `use` indicates that everything inside the module `wasm_bindgen::prelude` (i.e. the module `prelude` inside the crate `wasm_bindgen`) can be referred to without prefixing it with `wasm_bindgen::prelude`.
`wee_alloc` trades off size for speed. Although it has a tiny code-size footprint, it is relatively slow if additional allocations are needed.
For example, `#[wasm_bindgen]` could also be written as `#[wasm_bindgen::prelude::wasm_bindgen]`, although this is not recommended.
For more details, see the [`wee_alloc` repository](https://github.com/rustwasm/wee_alloc).

@ -0,0 +1,54 @@
# wee_alloc
1. [What is `wee_alloc`?](#what-is-wee_alloc)
2. [Enabling `wee_alloc`](#enabling-wee_alloc)
3. [Rust nightly](#rust-nightly)
## What is `wee_alloc`?
Reducing the size of compiled WebAssembly code is important, since it is often transmitted over the Internet or placed on embedded devices.
> `wee_alloc` is a tiny allocator designed for WebAssembly that has a (pre-compression) code-size footprint of only a single kilobyte.
[An analysis](http://fitzgeraldnick.com/2018/02/09/wee-alloc.html) suggests that over half of the bare minimum WebAssembly memory footprint is required by Rust's default memory allocator. Yet, WebAssembly code often does not require a sophisticated allocator, since it often just requests a couple of large initial allocations.
`wee_alloc` trades off size for speed. Although it has a tiny code-size footprint, it is relatively slow if additional allocations are needed.
For even more details, see the [`wee_alloc` repository](https://github.com/rustwasm/wee_alloc).
## Enabling `wee_alloc`
In `lib.rs`, we have the configuration for `wee_alloc` inside a `cfg_if!` macro:
```rust
cfg_if! {
if #[cfg(feature = "wee_alloc")] {
extern crate wee_alloc;
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
}
}
```
This code block is intended to initialize `wee_alloc` as the global memory allocator, but only if the `wee_alloc` feature is enabled in `Cargo.toml`.
To do so we need to append `"wee_alloc"` to the `default` vector in `Cargo.toml`. Then, the `cfg_if!` block is replaced with the contents of the `if` block, shown above.
```toml
[features]
default = ["console_error_panic_hook", "wee_alloc"]
```
## Rust nightly
`wee_alloc` currently relies on features only available in Rust nightly. As such it requires you to use the nightly toolchain for compilation. If you have [Rustup](https://rustup.rs/) set up, you can install the nightly toolchain as follows:
```
rustup toolchain add nightly
```
To use `wasm-pack` with Rust nightly run:
```
rustup run nightly wasm-pack build
```

@ -2,7 +2,7 @@
use binary_install::{Cache, Download};
use child;
use command::build::BuildProfile;
use command::build::{BuildProfile, Target};
use emoji;
use failure::{self, ResultExt};
use log::debug;
@ -176,11 +176,11 @@ pub fn wasm_bindgen_build(
bindgen: &Download,
out_dir: &Path,
disable_dts: bool,
target: &str,
target: &Target,
profile: BuildProfile,
step: &Step,
) -> Result<(), failure::Error> {
let msg = format!("{}Running WASM-bindgen...", emoji::RUNNER);
let msg = format!("{}Running wasm-bindgen...", emoji::RUNNER);
PBAR.step(step, &msg);
let release_or_debug = match profile {
@ -203,9 +203,10 @@ pub fn wasm_bindgen_build(
"--typescript"
};
let target_arg = match target {
"nodejs" => "--nodejs",
"no-modules" => "--no-modules",
_ => "--browser",
Target::Nodejs => "--nodejs",
Target::NoModules => "--no-modules",
Target::Web => "--web",
Target::Bundler => "--browser",
};
let bindgen_path = bindgen.binary("wasm-bindgen")?;
let mut cmd = Command::new(bindgen_path);

@ -125,7 +125,7 @@ fn rustup_add_wasm_target() -> Result<bool, Error> {
/// Ensure that `rustup` has the `wasm32-unknown-unknown` target installed for
/// current toolchain
pub fn check_for_wasm32_target(step: &Step) -> Result<(), Error> {
let msg = format!("{}Checking for WASM target...", emoji::TARGET);
let msg = format!("{}Checking for the Wasm target...", emoji::TARGET);
PBAR.step(step, &msg);
// Check if wasm32 target is present, otherwise bail.
@ -142,7 +142,7 @@ pub fn cargo_build_wasm(
step: &Step,
extra_options: &Vec<String>,
) -> Result<(), Error> {
let msg = format!("{}Compiling to WASM...", emoji::CYCLONE);
let msg = format!("{}Compiling to Wasm...", emoji::CYCLONE);
PBAR.step(step, &msg);
let mut cmd = Command::new("cargo");
cmd.current_dir(path).arg("build").arg("--lib");

@ -41,7 +41,7 @@ pub fn new_command(program: &str) -> Command {
/// given sender.
fn read_and_send<R, F>(
mut reader: R,
sender: mpsc::Sender<OutputFragment>,
sender: &mpsc::Sender<OutputFragment>,
mut map: F,
) -> io::Result<()>
where
@ -104,10 +104,7 @@ where
.rev()
.find(|(_, ch)| *ch == b'\n')
{
let next_in_progress: Vec<u8> = self.in_progress[last_newline + 1..]
.iter()
.cloned()
.collect();
let next_in_progress: Vec<u8> = self.in_progress[last_newline + 1..].to_vec();
let mut these_lines = mem::replace(&mut self.in_progress, next_in_progress);
these_lines.truncate(last_newline + 1);
let these_lines = String::from_utf8(these_lines)?;
@ -153,9 +150,9 @@ pub fn run(mut command: Command, command_name: &str) -> Result<String, Error> {
// waiting on the child process.
let stdout_handle =
thread::spawn(move || read_and_send(stdout, stdout_send, OutputFragment::Stdout));
thread::spawn(move || read_and_send(stdout, &stdout_send, OutputFragment::Stdout));
let stderr_handle =
thread::spawn(move || read_and_send(stderr, stderr_send, OutputFragment::Stderr));
thread::spawn(move || read_and_send(stderr, &stderr_send, OutputFragment::Stderr));
let mut stdout = OutputAccumulator::new(|line| {
info!("{} (stdout): {}", command_name, line);
@ -182,7 +179,7 @@ pub fn run(mut command: Command, command_name: &str) -> Result<String, Error> {
let exit = child.wait()?;
if exit.success() {
return Ok(stdout);
Ok(stdout)
} else {
drop((stdout, stderr));
bail!("failed to execute `{}`: exited with {}", command_name, exit)

@ -26,7 +26,7 @@ pub struct Build {
pub crate_data: manifest::CrateData,
pub scope: Option<String>,
pub disable_dts: bool,
pub target: String,
pub target: Target,
pub profile: BuildProfile,
pub mode: BuildMode,
pub out_dir: PathBuf,
@ -66,6 +66,44 @@ impl FromStr for BuildMode {
}
}
/// What sort of output we're going to be generating and flags we're invoking
/// `wasm-bindgen` with.
#[derive(Clone, Copy, Debug)]
pub enum Target {
/// Default output mode or `--target bundler`, indicates output will be
/// used with a bundle in a later step.
Bundler,
/// Correspond to `--target web` where the output is natively usable as an
/// ES module in a browser and the wasm is manually instantiated.
Web,
/// Correspond to `--target nodejs` where the output is natively usable as
/// a Node.js module loaded with `require`.
Nodejs,
/// Correspond to `--target no-modules` where the output is natively usable
/// in a browser but pollutes the global namespace and must be manually
/// instantiated.
NoModules,
}
impl Default for Target {
fn default() -> Target {
Target::Bundler
}
}
impl FromStr for Target {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Error> {
match s {
"bundler" | "browser" => Ok(Target::Bundler),
"web" => Ok(Target::Web),
"nodejs" => Ok(Target::Nodejs),
"no-modules" => Ok(Target::NoModules),
_ => bail!("Unknown target: {}", s),
}
}
}
/// The build profile controls whether optimizations, debug info, and assertions
/// are enabled or disabled.
#[derive(Clone, Copy, Debug)]
@ -99,8 +137,8 @@ pub struct BuildOptions {
pub disable_dts: bool,
#[structopt(long = "target", short = "t", default_value = "browser")]
/// Sets the target environment. [possible values: browser, nodejs, no-modules]
pub target: String,
/// Sets the target environment. [possible values: browser, nodejs, web, no-modules]
pub target: Target,
#[structopt(long = "debug")]
/// Deprecated. Renamed to `--dev`.
@ -133,9 +171,9 @@ impl Default for BuildOptions {
Self {
path: None,
scope: None,
mode: BuildMode::Normal,
mode: BuildMode::default(),
disable_dts: false,
target: String::new(),
target: Target::default(),
debug: false,
dev: false,
release: false,
@ -165,12 +203,6 @@ impl Build {
_ => bail!("Can only supply one of the --dev, --release, or --profiling flags"),
};
// `possible_values` in clap isn't supported by `structopt`
let possible_targets = ["browser", "nodejs", "no-modules"];
if !possible_targets.contains(&build_opts.target.as_str()) {
bail!("Supported targets: browser, nodejs, no-modules");
}
Ok(Build {
crate_path,
crate_data,
@ -193,7 +225,7 @@ impl Build {
/// Execute this `Build` command.
pub fn run(&mut self) -> Result<(), Error> {
let process_steps = Build::get_process_steps(&self.mode);
let process_steps = Build::get_process_steps(self.mode);
let mut step_counter = Step::new(process_steps.len());
@ -221,7 +253,7 @@ impl Build {
Ok(())
}
fn get_process_steps(mode: &BuildMode) -> Vec<(&'static str, BuildStep)> {
fn get_process_steps(mode: BuildMode) -> Vec<(&'static str, BuildStep)> {
macro_rules! steps {
($($name:ident),+) => {
{

@ -5,11 +5,11 @@ use PBAR;
pub fn login(
registry: Option<String>,
scope: Option<String>,
scope: &Option<String>,
always_auth: bool,
auth_type: Option<String>,
auth_type: &Option<String>,
) -> result::Result<(), failure::Error> {
let registry = registry.unwrap_or(npm::DEFAULT_NPM_REGISTRY.to_string());
let registry = registry.unwrap_or_else(|| npm::DEFAULT_NPM_REGISTRY.to_string());
info!("Logging in to npm...");
info!(
@ -20,6 +20,6 @@ pub fn login(
npm::npm_login(&registry, &scope, always_auth, &auth_type)?;
info!("Logged you in!");
PBAR.message(&format!("👋 logged you in!"));
PBAR.message(&"👋 logged you in!".to_string());
Ok(())
}

@ -90,7 +90,7 @@ pub enum Command {
pub fn run_wasm_pack(command: Command) -> result::Result<(), Error> {
// Run the correct command based off input and store the result of it so that we can clear
// the progress bar then return it
let status = match command {
match command {
Command::Build(build_opts) => {
info!("Running build command...");
Build::try_from_opts(build_opts).and_then(|mut b| b.run())
@ -107,7 +107,7 @@ pub fn run_wasm_pack(command: Command) -> result::Result<(), Error> {
} => {
info!("Running publish command...");
info!("Path: {:?}", &path);
publish(target, path, access)
publish(&target, path, access)
}
Command::Login {
registry,
@ -120,14 +120,11 @@ pub fn run_wasm_pack(command: Command) -> result::Result<(), Error> {
"Registry: {:?}, Scope: {:?}, Always Auth: {}, Auth Type: {:?}",
&registry, &scope, &always_auth, &auth_type
);
login(registry, scope, always_auth, auth_type)
login(registry, &scope, always_auth, &auth_type)
}
Command::Test(test_opts) => {
info!("Running test command...");
Test::try_from_opts(test_opts).and_then(|t| t.run())
}
};
// Return the actual status of the program to the main function
status
}
}

@ -2,7 +2,7 @@
pub mod access;
use self::access::Access;
use command::build::{Build, BuildOptions};
use command::build::{Build, BuildOptions, Target};
use command::utils::{find_pkg_directory, set_crate_path};
use dialoguer::{Confirmation, Input, Select};
use failure::Error;
@ -10,12 +10,13 @@ use log::info;
use npm;
use std::path::PathBuf;
use std::result;
use std::str::FromStr;
use PBAR;
/// Creates a tarball from a 'pkg' directory
/// and publishes it to the NPM registry
pub fn publish(
_target: String,
_target: &str,
path: Option<PathBuf>,
access: Option<Access>,
) -> result::Result<(), Error> {
@ -45,6 +46,7 @@ pub fn publish(
.default(0)
.interact()?
.to_string();
let target = Target::from_str(&target)?;
let build_opts = BuildOptions {
path: Some(crate_path.clone()),
target,

@ -250,7 +250,7 @@ impl Test {
fn step_build_tests(&mut self, step: &Step) -> Result<(), Error> {
info!("Compiling tests to wasm...");
let msg = format!("{}Compiling tests to WASM...", emoji::CYCLONE);
let msg = format!("{}Compiling tests to Wasm...", emoji::CYCLONE);
PBAR.step(step, &msg);
build::cargo_build_wasm_tests(&self.crate_path, !self.release)?;

@ -11,7 +11,7 @@ use PBAR;
/// If an explicit path is given, then use it, otherwise assume the current
/// directory is the crate path.
pub fn set_crate_path(path: Option<PathBuf>) -> Result<PathBuf, failure::Error> {
Ok(path.unwrap_or(PathBuf::from(".")))
Ok(path.unwrap_or_else(|| PathBuf::from(".")))
}
/// Construct our `pkg` directory in the crate.

@ -114,7 +114,7 @@ fn confirm_can_overwrite(dst: &Path) -> Result<(), failure::Error> {
.read_line(&mut line)
.with_context(|_| "failed to read stdin")?;
if line.starts_with("y") || line.starts_with("Y") {
if line.starts_with('y') || line.starts_with('Y') {
return Ok(());
}

@ -1,5 +1,7 @@
//! Reading Cargo.lock lock file.
#![allow(clippy::new_ret_no_self)]
use std::fs;
use std::path::PathBuf;

@ -35,7 +35,12 @@ fn run() -> Result<(), failure::Error> {
if let Ok(me) = env::current_exe() {
// If we're actually running as the installer then execute our
// self-installation, otherwise just continue as usual.
if me.file_stem().and_then(|s| s.to_str()) == Some("wasm-pack-init") {
if me
.file_stem()
.and_then(|s| s.to_str())
.expect("executable should have a filename")
.starts_with("wasm-pack-init")
{
installer::install();
}
}

@ -1,5 +1,7 @@
//! Reading and writing Cargo.toml and package.json manifests.
#![allow(clippy::new_ret_no_self, clippy::needless_pass_by_value)]
mod npm;
use std::fs;
@ -9,7 +11,7 @@ use self::npm::{
repository::Repository, CommonJSPackage, ESModulesPackage, NoModulesPackage, NpmPackage,
};
use cargo_metadata::Metadata;
use command::build::BuildProfile;
use command::build::{BuildProfile, Target};
use emoji;
use failure::{Error, ResultExt};
use progressbar::Step;
@ -20,7 +22,7 @@ use strsim::levenshtein;
use toml;
use PBAR;
const WASM_PACK_METADATA_KEY: &'static str = "package.metadata.wasm-pack";
const WASM_PACK_METADATA_KEY: &str = "package.metadata.wasm-pack";
/// Store for metadata learned about a crate
pub struct CrateData {
@ -148,7 +150,7 @@ impl CargoWasmPackProfile {
D: serde::Deserializer<'de>,
{
let mut profile = <Option<Self>>::deserialize(deserializer)?.unwrap_or_default();
profile.update_with_defaults(Self::default_dev());
profile.update_with_defaults(&Self::default_dev());
Ok(profile)
}
@ -157,7 +159,7 @@ impl CargoWasmPackProfile {
D: serde::Deserializer<'de>,
{
let mut profile = <Option<Self>>::deserialize(deserializer)?.unwrap_or_default();
profile.update_with_defaults(Self::default_release());
profile.update_with_defaults(&Self::default_release());
Ok(profile)
}
@ -166,11 +168,11 @@ impl CargoWasmPackProfile {
D: serde::Deserializer<'de>,
{
let mut profile = <Option<Self>>::deserialize(deserializer)?.unwrap_or_default();
profile.update_with_defaults(Self::default_profiling());
profile.update_with_defaults(&Self::default_profiling());
Ok(profile)
}
fn update_with_defaults(&mut self, defaults: Self) {
fn update_with_defaults(&mut self, defaults: &Self) {
macro_rules! d {
( $( $path:ident ).* ) => {
self. $( $path ).* .get_or_insert(defaults. $( $path ).* .unwrap());
@ -252,7 +254,7 @@ impl CrateData {
for e in errors[..errors.len() - 1].iter().rev() {
err = err.context(e.to_string()).into();
}
return err;
err
}
}
@ -375,19 +377,18 @@ impl CrateData {
out_dir: &Path,
scope: &Option<String>,
disable_dts: bool,
target: &str,
target: &Target,
step: &Step,
) -> Result<(), Error> {
let msg = format!("{}Writing a package.json...", emoji::MEMO);
PBAR.step(step, &msg);
let pkg_file_path = out_dir.join("package.json");
let npm_data = if target == "nodejs" {
self.to_commonjs(scope, disable_dts, out_dir)
} else if target == "no-modules" {
self.to_nomodules(scope, disable_dts, out_dir)
} else {
self.to_esmodules(scope, disable_dts, out_dir)
let npm_data = match target {
Target::Nodejs => self.to_commonjs(scope, disable_dts, out_dir),
Target::NoModules => self.to_nomodules(scope, disable_dts, out_dir),
Target::Bundler => self.to_esmodules(scope, disable_dts, out_dir),
Target::Web => self.to_web(scope, disable_dts, out_dir),
};
let npm_json = serde_json::to_string_pretty(&npm_data)?;
@ -428,17 +429,13 @@ impl CrateData {
None
};
let readme_file = out_dir.join("README.md");
if readme_file.is_file() {
files.push("README.md".to_string());
}
if let Ok(entries) = fs::read_dir(out_dir) {
let file_names = entries
.filter_map(|e| e.ok())
.filter(|e| e.metadata().map(|m| m.is_file()).unwrap_or(false))
.filter_map(|e| e.file_name().into_string().ok())
.filter(|f| f.starts_with("LICENSE"));
.filter(|f| f.starts_with("LICENSE"))
.filter(|f| f != "LICENSE");
for file_name in file_names {
files.push(file_name);
}
@ -524,6 +521,35 @@ impl CrateData {
})
}
fn to_web(&self, scope: &Option<String>, disable_dts: bool, out_dir: &Path) -> NpmPackage {
let data = self.npm_data(scope, false, disable_dts, out_dir);
let pkg = &self.data.packages[self.current_idx];
self.check_optional_fields();
NpmPackage::ESModulesPackage(ESModulesPackage {
name: data.name,
collaborators: pkg.authors.clone(),
description: self.manifest.package.description.clone(),
version: pkg.version.clone(),
license: self.license(),
repository: self
.manifest
.package
.repository
.clone()
.map(|repo_url| Repository {
ty: "git".to_string(),
url: repo_url,
}),
files: data.files,
module: data.main,
homepage: data.homepage,
types: data.dts_file,
side_effects: "false".to_string(),
})
}
fn to_nomodules(
&self,
scope: &Option<String>,

@ -6,7 +6,7 @@ use failure::{self, ResultExt};
use log::info;
/// The default npm registry used when we aren't working with a custom registry.
pub const DEFAULT_NPM_REGISTRY: &'static str = "https://registry.npmjs.org/";
pub const DEFAULT_NPM_REGISTRY: &str = "https://registry.npmjs.org/";
/// Run the `npm pack` command.
pub fn npm_pack(path: &str) -> Result<(), failure::Error> {
@ -33,7 +33,7 @@ pub fn npm_publish(path: &str, access: Option<Access>) -> Result<(), failure::Er
/// Run the `npm login` command.
pub fn npm_login(
registry: &String,
registry: &str,
scope: &Option<String>,
always_auth: bool,
auth_type: &Option<String>,

@ -82,7 +82,7 @@ impl ProgressOutput {
}
/// Add an error message.
pub fn error(&self, message: String) {
pub fn error(&self, message: &str) {
let err = format!(
"{} {}: {}",
emoji::ERROR,
@ -142,3 +142,9 @@ impl Drop for ProgressOutput {
self.done();
}
}
impl Default for ProgressOutput {
fn default() -> Self {
Self::new()
}
}

@ -23,8 +23,8 @@ pub fn copy_from_crate(path: &Path, out_dir: &Path, step: &Step) -> Result<(), f
PBAR.step(step, &msg);
let crate_readme_path = path.join("README.md");
let new_readme_path = out_dir.join("README.md");
if let Err(_) = fs::copy(&crate_readme_path, &new_readme_path) {
if fs::copy(&crate_readme_path, &new_readme_path).is_err() {
PBAR.warn("origin crate has no README");
};
}
Ok(())
}

@ -11,7 +11,7 @@ use wasm_pack::bindgen;
fn can_download_prebuilt_wasm_bindgen() {
let dir = tempfile::TempDir::new().unwrap();
let cache = Cache::at(dir.path());
let dl = bindgen::download_prebuilt_wasm_bindgen(&cache, "0.2.21", true).unwrap();
let dl = bindgen::download_prebuilt_wasm_bindgen(&cache, "0.2.37", true).unwrap();
assert!(dl.binary("wasm-bindgen").unwrap().is_file());
assert!(dl.binary("wasm-bindgen-test-runner").unwrap().is_file())
}
@ -24,7 +24,7 @@ fn can_download_prebuilt_wasm_bindgen() {
))]
fn downloading_prebuilt_wasm_bindgen_handles_http_errors() {
let dir = tempfile::TempDir::new().unwrap();
let bad_version = "0.2.21-some-trailing-version-stuff-that-does-not-exist";
let bad_version = "0.2.37-some-trailing-version-stuff-that-does-not-exist";
let cache = Cache::at(dir.path());
let result = bindgen::download_prebuilt_wasm_bindgen(&cache, bad_version, true);
assert!(result.is_err());

@ -17,7 +17,6 @@ fn build_in_non_crate_directory_doesnt_panic() {
#[test]
fn it_should_build_js_hello_world_example() {
let fixture = utils::fixture::js_hello_world();
fixture.install_local_wasm_bindgen();
fixture.wasm_pack().arg("build").assert().success();
}
@ -47,7 +46,7 @@ fn it_should_build_crates_in_a_workspace() {
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "=0.2.21"
wasm-bindgen = "0.2"
"#,
)
.file(
@ -87,7 +86,7 @@ fn renamed_crate_name_works() {
name = 'bar'
[dependencies]
wasm-bindgen = "=0.2.21"
wasm-bindgen = "0.2"
"#,
)
.file(

@ -17,8 +17,8 @@ fn it_copies_a_license_default_path() {
let step = wasm_pack::progressbar::Step::new(1);
assert!(license::copy_from_crate(&crate_data.unwrap(), &fixture.path, &out_dir, &step).is_ok());
let crate_license_path = fixture.path.join("LICENSE-WTFPL");
let pkg_license_path = out_dir.join("LICENSE-WTFPL");
let crate_license_path = fixture.path.join("LICENSE");
let pkg_license_path = out_dir.join("LICENSE");
println!(
"wasm-pack: should have copied LICENSE from '{}' to '{}'",
crate_license_path.display(),
@ -42,10 +42,10 @@ fn it_copies_a_license_provided_path() {
let step = wasm_pack::progressbar::Step::new(1);
assert!(license::copy_from_crate(&crate_data.unwrap(), &fixture.path, &out_dir, &step).is_ok());
let crate_license_path = fixture.path.join("LICENSE-WTFPL");
let pkg_license_path = out_dir.join("LICENSE-WTFPL");
let crate_license_path = fixture.path.join("LICENSE");
let pkg_license_path = out_dir.join("LICENSE");
println!(
"wasm-pack: should have copied LICENSE-WTFPL from '{}' to '{}'",
"wasm-pack: should have copied LICENSE from '{}' to '{}'",
crate_license_path.display(),
pkg_license_path.display()
);

@ -8,7 +8,7 @@ fn it_gets_wasm_bindgen_version() {
fixture.cargo_check();
let data = CrateData::new(&fixture.path).unwrap();
let lock = Lockfile::new(&data).unwrap();
assert_eq!(lock.wasm_bindgen_version(), Some("0.2.21"),);
assert_eq!(lock.wasm_bindgen_version(), Some("0.2.37"),);
}
#[test]
@ -17,7 +17,7 @@ fn it_gets_wasm_bindgen_test_version() {
fixture.cargo_check();
let data = CrateData::new(&fixture.path).unwrap();
let lock = Lockfile::new(&data).unwrap();
assert_eq!(lock.wasm_bindgen_test_version(), Some("0.2.21"),);
assert_eq!(lock.wasm_bindgen_test_version(), Some("0.2.37"),);
}
#[test]
@ -46,7 +46,7 @@ fn it_gets_wasm_bindgen_version_in_crate_inside_workspace() {
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "=0.2.21"
wasm-bindgen = "=0.2.37"
"#,
)
.file(
@ -62,7 +62,7 @@ fn it_gets_wasm_bindgen_version_in_crate_inside_workspace() {
fixture.cargo_check();
let data = CrateData::new(&fixture.path.join("blah")).unwrap();
let lock = Lockfile::new(&data).unwrap();
assert_eq!(lock.wasm_bindgen_version(), Some("0.2.21"),);
assert_eq!(lock.wasm_bindgen_version(), Some("0.2.37"),);
}
#[test]
@ -91,7 +91,7 @@ fn it_gets_wasm_bindgen_version_from_dependencies() {
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "=0.2.21"
wasm-bindgen = "=0.2.37"
"#,
)
.file(
@ -130,5 +130,5 @@ fn it_gets_wasm_bindgen_version_from_dependencies() {
fixture.cargo_check();
let data = CrateData::new(&fixture.path.join("parent")).unwrap();
let lock = Lockfile::new(&data).unwrap();
assert_eq!(lock.wasm_bindgen_version(), Some("0.2.21"),);
assert_eq!(lock.wasm_bindgen_version(), Some("0.2.37"),);
}

@ -3,7 +3,8 @@ use std::collections::HashSet;
use std::fs;
use std::path::PathBuf;
use utils::{self, fixture};
use wasm_pack::{self, license, manifest, readme};
use wasm_pack::command::build::Target;
use wasm_pack::{self, license, manifest};
#[test]
fn it_gets_the_crate_name_default_path() {
@ -66,7 +67,7 @@ fn it_creates_a_package_json_default_path() {
let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
assert!(crate_data
.write_package_json(&out_dir, &None, false, "", &step)
.write_package_json(&out_dir, &None, false, &Target::Bundler, &step)
.is_ok());
let package_json_path = &fixture.path.join("pkg").join("package.json");
fs::metadata(package_json_path).unwrap();
@ -102,7 +103,7 @@ fn it_creates_a_package_json_provided_path() {
let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
assert!(crate_data
.write_package_json(&out_dir, &None, false, "", &step)
.write_package_json(&out_dir, &None, false, &Target::Bundler, &step)
.is_ok());
let package_json_path = &fixture.path.join("pkg").join("package.json");
fs::metadata(package_json_path).unwrap();
@ -131,7 +132,13 @@ fn it_creates_a_package_json_provided_path_with_scope() {
let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
assert!(crate_data
.write_package_json(&out_dir, &Some("test".to_string()), false, "", &step)
.write_package_json(
&out_dir,
&Some("test".to_string()),
false,
&Target::Bundler,
&step
)
.is_ok());
let package_json_path = &fixture.path.join("pkg").join("package.json");
fs::metadata(package_json_path).unwrap();
@ -160,7 +167,7 @@ fn it_creates_a_pkg_json_with_correct_files_on_node() {
let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
assert!(crate_data
.write_package_json(&out_dir, &None, false, "nodejs", &step)
.write_package_json(&out_dir, &None, false, &Target::Nodejs, &step)
.is_ok());
let package_json_path = &out_dir.join("package.json");
fs::metadata(package_json_path).unwrap();
@ -196,7 +203,7 @@ fn it_creates_a_pkg_json_with_correct_files_on_nomodules() {
let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
assert!(crate_data
.write_package_json(&out_dir, &None, false, "no-modules", &step)
.write_package_json(&out_dir, &None, false, &Target::NoModules, &step)
.is_ok());
let package_json_path = &out_dir.join("package.json");
fs::metadata(package_json_path).unwrap();
@ -231,7 +238,7 @@ fn it_creates_a_pkg_json_in_out_dir() {
let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
assert!(crate_data
.write_package_json(&out_dir, &None, false, "", &step)
.write_package_json(&out_dir, &None, false, &Target::Bundler, &step)
.is_ok());
let package_json_path = &fixture.path.join(&out_dir).join("package.json");
@ -247,7 +254,7 @@ fn it_creates_a_package_json_with_correct_keys_when_types_are_skipped() {
let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
assert!(crate_data
.write_package_json(&out_dir, &None, true, "", &step)
.write_package_json(&out_dir, &None, true, &Target::Bundler, &step)
.is_ok());
let package_json_path = &out_dir.join("package.json");
fs::metadata(package_json_path).unwrap();
@ -310,7 +317,7 @@ fn it_sets_homepage_field_if_available_in_cargo_toml() {
let step = wasm_pack::progressbar::Step::new(2);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
crate_data
.write_package_json(&out_dir, &None, true, "", &step)
.write_package_json(&out_dir, &None, true, &Target::Bundler, &step)
.unwrap();
let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap();
@ -327,7 +334,7 @@ fn it_sets_homepage_field_if_available_in_cargo_toml() {
let step = wasm_pack::progressbar::Step::new(2);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
crate_data
.write_package_json(&out_dir, &None, true, "", &step)
.write_package_json(&out_dir, &None, true, &Target::Bundler, &step)
.unwrap();
let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap();
@ -430,7 +437,7 @@ fn it_lists_license_files_in_files_field_of_package_json() {
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
license::copy_from_crate(&crate_data, &fixture.path, &out_dir, &step).unwrap();
crate_data
.write_package_json(&out_dir, &None, false, "", &step)
.write_package_json(&out_dir, &None, false, &Target::Bundler, &step)
.unwrap();
let package_json_path = &fixture.path.join("pkg").join("package.json");
@ -449,33 +456,3 @@ fn it_lists_license_files_in_files_field_of_package_json() {
pkg.files,
);
}
#[test]
fn it_lists_readme_in_files_field_of_package_json() {
let fixture = utils::fixture::Fixture::new();
fixture
.readme()
.hello_world_src_lib()
.cargo_toml("readme-test-for-package-json");
let out_dir = fixture.path.join("pkg");
let crate_data = manifest::CrateData::new(&fixture.path).unwrap();
let step = wasm_pack::progressbar::Step::new(3);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
readme::copy_from_crate(&fixture.path, &out_dir, &step).unwrap();
crate_data
.write_package_json(&out_dir, &None, false, "", &step)
.unwrap();
let package_json_path = &fixture.path.join("pkg").join("package.json");
fs::metadata(package_json_path).unwrap();
let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap();
assert!(
pkg.files.contains(&"README.md".to_string()),
"README.md is not in files: {:?}",
pkg.files,
);
}

@ -178,7 +178,7 @@ fn complains_about_missing_wasm_bindgen_test_dependency() {
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "=0.2.21"
wasm-bindgen = "0.2"
[dev-dependencies]
# no wasm-bindgen-test dep here!
@ -218,10 +218,10 @@ fn renamed_crate_name_works() {
name = 'bar'
[dependencies]
wasm-bindgen = "=0.2.21"
wasm-bindgen = "0.2"
[dev-dependencies]
wasm-bindgen-test = "=0.2.21"
wasm-bindgen-test = "0.2"
"#,
)
.file(
@ -258,10 +258,10 @@ fn cdylib_not_required() {
authors = []
[dependencies]
wasm-bindgen = "=0.2.21"
wasm-bindgen = "0.2"
[dev-dependencies]
wasm-bindgen-test = "=0.2.21"
wasm-bindgen-test = "0.2"
"#,
)
.file(
@ -293,7 +293,7 @@ fn cdylib_not_required() {
}
#[test]
fn test_output_is_printed_once() {
fn test_output_is_printed_once_in_both_stdout_and_failures() {
let fixture = fixture::Fixture::new();
fixture
.readme()
@ -322,6 +322,9 @@ fn test_output_is_printed_once() {
)
.install_local_wasm_bindgen();
let _lock = fixture.lock();
// there will be only one log in stdout, and only one log in failures
let log_cnt = 1;
fixture
.wasm_pack()
.arg("test")
@ -329,6 +332,8 @@ fn test_output_is_printed_once() {
.assert()
.failure()
.stderr(predicate::function(|err: &str| {
err.matches("YABBA DABBA DOO").count() == 1
// but the err string will capture both stdout and failures,
// so we will get a log that count twice
err.matches("YABBA DABBA DOO").count() == log_cnt * 2
}));
}

@ -67,6 +67,16 @@ impl Fixture {
)
}
/// Add `LICENSE` file to the fixture.
pub fn license(&self) -> &Self {
self.file(
"LICENSE",
r#"
I'm a license!
"#,
)
}
/// Add `WTFPL LICENSE` file to the fixture.
pub fn wtfpl_license(&self) -> &Self {
self.file(
@ -127,10 +137,15 @@ impl Fixture {
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "=0.2.21"
# Note that this uses and `=` dependency because there are
# various tests which assert that the version of wasm
# bindgen downloaded is what we expect, and if `=` is
# removed then it will download whatever the newest version
# of wasm-bindgen is which may not be what's listed here.
wasm-bindgen = "=0.2.37"
[dev-dependencies]
wasm-bindgen-test = "=0.2.21"
wasm-bindgen-test = "0.2"
"#,
name
),
@ -201,7 +216,7 @@ impl Fixture {
pub fn install_local_wasm_bindgen(&self) -> PathBuf {
static INSTALL_WASM_BINDGEN: Once = ONCE_INIT;
let cache = self.cache();
let version = "0.2.21";
let version = "0.2.37";
let download = || {
if let Ok(download) =
@ -351,10 +366,10 @@ pub fn no_cdylib() -> Fixture {
# crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "=0.2.21"
wasm-bindgen = "0.2"
[dev-dependencies]
wasm-bindgen-test = "=0.2.21"
wasm-bindgen-test = "0.2"
"#,
);
fixture
@ -403,14 +418,14 @@ pub fn wbg_test_diff_versions() -> Fixture {
crate-type = ["cdylib", "rlib"]
[dependencies]
# We depend on wasm-bindgen 0.2.21
wasm-bindgen = "=0.2.21"
# We depend on the latest wasm-bindgen 0.2
wasm-bindgen = "0.2"
[dev-dependencies]
# And we depend on wasm-bindgen-test 0.2.19. This should still
# work, and we should end up with `wasm-bindgen` at 0.2.21 and
# wasm-bindgen-test at 0.2.19, and everything should still work.
wasm-bindgen-test = "0.2.19"
# And we depend on wasm-bindgen-test 0.2.29. This should still
# work, and we should end up with the latest `wasm-bindgen` and
# wasm-bindgen-test at 0.2.29, and everything should still work.
wasm-bindgen-test = "0.2.29"
"#,
)
.file(
@ -522,12 +537,12 @@ pub fn transitive_dependencies() -> Fixture {
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "=0.2.21"
wasm-bindgen = "0.2"
project_a = { path = "../project_a" }
project_b = { path = "../project_b" }
[dev-dependencies]
wasm-bindgen-test = "=0.2.21"
wasm-bindgen-test = "0.2"
"#,
);
fixture.file(
@ -572,11 +587,11 @@ pub fn transitive_dependencies() -> Fixture {
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "=0.2.21"
wasm-bindgen = "0.2"
project_b = { path = "../project_b" }
[dev-dependencies]
wasm-bindgen-test = "=0.2.21"
wasm-bindgen-test = "0.2"
"#,
);
fixture.file(
@ -622,10 +637,10 @@ pub fn transitive_dependencies() -> Fixture {
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "=0.2.21"
wasm-bindgen = "0.2"
[dev-dependencies]
wasm-bindgen-test = "=0.2.21"
wasm-bindgen-test = "0.2"
"#,
);
fixture.file(
@ -662,7 +677,7 @@ pub fn single_license() -> Fixture {
fixture
.readme()
.cargo_toml("single_license")
.wtfpl_license()
.license()
.hello_world_src_lib();
fixture
}

Loading…
Cancel
Save