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: test_script:
- cargo test --release --tests --locked - cargo test --release --tests --locked
- cargo test --release --doc - cargo test --release --doc
- cd binary-install
- cargo test
- cd ..
before_deploy: before_deploy:
- ps: | - ps: |

@ -47,10 +47,13 @@ matrix:
install: install:
- *INSTALL_NODE_VIA_NVM - *INSTALL_NODE_VIA_NVM
script: script:
- cargo test --locked - cargo test --all --locked
- rustup component add rustfmt-preview - rustup component add rustfmt-preview
- cargo fmt --version - cargo fmt --version
- cargo fmt --all -- --check - cargo fmt --all -- --check
- rustup component add clippy-preview
- cargo clippy --version
- cargo clippy
- name: Book - name: Book
rust: stable rust: stable
@ -59,7 +62,7 @@ matrix:
- (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.2" mdbook) - (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.2" mdbook)
- cargo install-update -a - cargo install-update -a
script: script:
- (cd docs && mdbook build) - (cd docs && mv _theme theme && mdbook build)
- rustc ./docs/_installer/build-installer.rs - rustc ./docs/_installer/build-installer.rs
- ./build-installer - ./build-installer
deploy: 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" siphasher = "0.2.3"
tar = "0.4.16" tar = "0.4.16"
zip = "0.5.0" 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 /// Global cache for wasm-pack, currently containing binaries downloaded from
/// urls like wasm-bindgen and such. /// urls like wasm-bindgen and such.
#[derive(Debug)]
pub struct Cache { pub struct Cache {
destination: PathBuf, destination: PathBuf,
} }
/// Representation of a downloaded tarball/zip /// Representation of a downloaded tarball/zip
#[derive(Debug)]
pub struct Download { pub struct Download {
root: PathBuf, root: PathBuf,
} }
@ -81,22 +83,10 @@ impl Cache {
binaries: &[&str], binaries: &[&str],
url: &str, url: &str,
) -> Result<Option<Download>, Error> { ) -> Result<Option<Download>, Error> {
let mut hasher = SipHasher13::new(); let dirname = hashed_dirname(url, name);
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 destination = self.destination.join(&dirname); let destination = self.destination.join(&dirname);
if destination.exists() { if destination.exists() {
return Ok(Some(Download { root: destination })); 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) - [`Cargo.toml`](./tutorial/template-deep-dive/cargo-toml.md)
- [`src/lib.rs`](./tutorial/template-deep-dive/src-lib-rs.md) - [`src/lib.rs`](./tutorial/template-deep-dive/src-lib-rs.md)
- [`src/utils.rs`](./tutorial/template-deep-dive/src-utils-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) - [Packaging and Publishing](./tutorial/packaging-and-publishing.md)
- [Using your Library](./tutorial/using-your-library.md) - [Using your Library](./tutorial/using-your-library.md)
- [`Cargo.toml` Configuration](./cargo-toml-configuration.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 ## Target
The `build` command accepts a `--target` argument. This will customize the output files The `build` command accepts a `--target` argument. This will customize the JS
to align with a particular type of JS module. This allows wasm-pack to generate either that is emitted and how the WebAssembly files are instantiated and loaded. For
ES6 modules or CommonJS modules for use in browser and in NodeJS. Defaults to `browser`. more documentation on the various strategies here, see the [documentation on
The options are: using the compiled output][deploy].
``` ```
wasm-pack build --target nodejs wasm-pack build --target nodejs
``` ```
| Option | Description | | Option | Usage | Description |
|-----------|-----------------------------------------------------------------------------------------------------------------| |-----------|------------|-----------------------------------------------------------------------------------------------------|
| `nodejs` | Outputs JS that uses CommonJS modules, for use with a `require` statement. `main` key in `package.json`. | | *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. |
| `no-modules` | Outputs JS that use no modules. `browser` key in `package.json`. | | `nodejs` | [Node.js][deploy-nodejs] | Outputs JS that uses CommonJS modules, for use with a `require` statement. `main` 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. | | `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 ## 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. `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!`. 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
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
```rust ```rust
cfg_if! { 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. 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). 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`. 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 ```rust
extern crate wee_alloc; use wasm_bindgen::prelude::*;
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
``` ```
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. 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.
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.
[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 binary_install::{Cache, Download};
use child; use child;
use command::build::BuildProfile; use command::build::{BuildProfile, Target};
use emoji; use emoji;
use failure::{self, ResultExt}; use failure::{self, ResultExt};
use log::debug; use log::debug;
@ -176,11 +176,11 @@ pub fn wasm_bindgen_build(
bindgen: &Download, bindgen: &Download,
out_dir: &Path, out_dir: &Path,
disable_dts: bool, disable_dts: bool,
target: &str, target: &Target,
profile: BuildProfile, profile: BuildProfile,
step: &Step, step: &Step,
) -> Result<(), failure::Error> { ) -> Result<(), failure::Error> {
let msg = format!("{}Running WASM-bindgen...", emoji::RUNNER); let msg = format!("{}Running wasm-bindgen...", emoji::RUNNER);
PBAR.step(step, &msg); PBAR.step(step, &msg);
let release_or_debug = match profile { let release_or_debug = match profile {
@ -203,9 +203,10 @@ pub fn wasm_bindgen_build(
"--typescript" "--typescript"
}; };
let target_arg = match target { let target_arg = match target {
"nodejs" => "--nodejs", Target::Nodejs => "--nodejs",
"no-modules" => "--no-modules", Target::NoModules => "--no-modules",
_ => "--browser", Target::Web => "--web",
Target::Bundler => "--browser",
}; };
let bindgen_path = bindgen.binary("wasm-bindgen")?; let bindgen_path = bindgen.binary("wasm-bindgen")?;
let mut cmd = Command::new(bindgen_path); 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 /// Ensure that `rustup` has the `wasm32-unknown-unknown` target installed for
/// current toolchain /// current toolchain
pub fn check_for_wasm32_target(step: &Step) -> Result<(), Error> { 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); PBAR.step(step, &msg);
// Check if wasm32 target is present, otherwise bail. // Check if wasm32 target is present, otherwise bail.
@ -142,7 +142,7 @@ pub fn cargo_build_wasm(
step: &Step, step: &Step,
extra_options: &Vec<String>, extra_options: &Vec<String>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let msg = format!("{}Compiling to WASM...", emoji::CYCLONE); let msg = format!("{}Compiling to Wasm...", emoji::CYCLONE);
PBAR.step(step, &msg); PBAR.step(step, &msg);
let mut cmd = Command::new("cargo"); let mut cmd = Command::new("cargo");
cmd.current_dir(path).arg("build").arg("--lib"); cmd.current_dir(path).arg("build").arg("--lib");

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

@ -26,7 +26,7 @@ pub struct Build {
pub crate_data: manifest::CrateData, pub crate_data: manifest::CrateData,
pub scope: Option<String>, pub scope: Option<String>,
pub disable_dts: bool, pub disable_dts: bool,
pub target: String, pub target: Target,
pub profile: BuildProfile, pub profile: BuildProfile,
pub mode: BuildMode, pub mode: BuildMode,
pub out_dir: PathBuf, 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 /// The build profile controls whether optimizations, debug info, and assertions
/// are enabled or disabled. /// are enabled or disabled.
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
@ -99,8 +137,8 @@ pub struct BuildOptions {
pub disable_dts: bool, pub disable_dts: bool,
#[structopt(long = "target", short = "t", default_value = "browser")] #[structopt(long = "target", short = "t", default_value = "browser")]
/// Sets the target environment. [possible values: browser, nodejs, no-modules] /// Sets the target environment. [possible values: browser, nodejs, web, no-modules]
pub target: String, pub target: Target,
#[structopt(long = "debug")] #[structopt(long = "debug")]
/// Deprecated. Renamed to `--dev`. /// Deprecated. Renamed to `--dev`.
@ -133,9 +171,9 @@ impl Default for BuildOptions {
Self { Self {
path: None, path: None,
scope: None, scope: None,
mode: BuildMode::Normal, mode: BuildMode::default(),
disable_dts: false, disable_dts: false,
target: String::new(), target: Target::default(),
debug: false, debug: false,
dev: false, dev: false,
release: false, release: false,
@ -165,12 +203,6 @@ impl Build {
_ => bail!("Can only supply one of the --dev, --release, or --profiling flags"), _ => 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 { Ok(Build {
crate_path, crate_path,
crate_data, crate_data,
@ -193,7 +225,7 @@ impl Build {
/// Execute this `Build` command. /// Execute this `Build` command.
pub fn run(&mut self) -> Result<(), Error> { 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()); let mut step_counter = Step::new(process_steps.len());
@ -221,7 +253,7 @@ impl Build {
Ok(()) Ok(())
} }
fn get_process_steps(mode: &BuildMode) -> Vec<(&'static str, BuildStep)> { fn get_process_steps(mode: BuildMode) -> Vec<(&'static str, BuildStep)> {
macro_rules! steps { macro_rules! steps {
($($name:ident),+) => { ($($name:ident),+) => {
{ {

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

@ -90,7 +90,7 @@ pub enum Command {
pub fn run_wasm_pack(command: Command) -> result::Result<(), Error> { 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 // Run the correct command based off input and store the result of it so that we can clear
// the progress bar then return it // the progress bar then return it
let status = match command { match command {
Command::Build(build_opts) => { Command::Build(build_opts) => {
info!("Running build command..."); info!("Running build command...");
Build::try_from_opts(build_opts).and_then(|mut b| b.run()) 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!("Running publish command...");
info!("Path: {:?}", &path); info!("Path: {:?}", &path);
publish(target, path, access) publish(&target, path, access)
} }
Command::Login { Command::Login {
registry, 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: {:?}",
&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) => { Command::Test(test_opts) => {
info!("Running test command..."); info!("Running test command...");
Test::try_from_opts(test_opts).and_then(|t| t.run()) 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; pub mod access;
use self::access::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 command::utils::{find_pkg_directory, set_crate_path};
use dialoguer::{Confirmation, Input, Select}; use dialoguer::{Confirmation, Input, Select};
use failure::Error; use failure::Error;
@ -10,12 +10,13 @@ use log::info;
use npm; use npm;
use std::path::PathBuf; use std::path::PathBuf;
use std::result; use std::result;
use std::str::FromStr;
use PBAR; use PBAR;
/// Creates a tarball from a 'pkg' directory /// Creates a tarball from a 'pkg' directory
/// and publishes it to the NPM registry /// and publishes it to the NPM registry
pub fn publish( pub fn publish(
_target: String, _target: &str,
path: Option<PathBuf>, path: Option<PathBuf>,
access: Option<Access>, access: Option<Access>,
) -> result::Result<(), Error> { ) -> result::Result<(), Error> {
@ -45,6 +46,7 @@ pub fn publish(
.default(0) .default(0)
.interact()? .interact()?
.to_string(); .to_string();
let target = Target::from_str(&target)?;
let build_opts = BuildOptions { let build_opts = BuildOptions {
path: Some(crate_path.clone()), path: Some(crate_path.clone()),
target, target,

@ -250,7 +250,7 @@ impl Test {
fn step_build_tests(&mut self, step: &Step) -> Result<(), Error> { fn step_build_tests(&mut self, step: &Step) -> Result<(), Error> {
info!("Compiling tests to wasm..."); 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); PBAR.step(step, &msg);
build::cargo_build_wasm_tests(&self.crate_path, !self.release)?; 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 /// If an explicit path is given, then use it, otherwise assume the current
/// directory is the crate path. /// directory is the crate path.
pub fn set_crate_path(path: Option<PathBuf>) -> Result<PathBuf, failure::Error> { 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. /// Construct our `pkg` directory in the crate.

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

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

@ -35,7 +35,12 @@ fn run() -> Result<(), failure::Error> {
if let Ok(me) = env::current_exe() { if let Ok(me) = env::current_exe() {
// If we're actually running as the installer then execute our // If we're actually running as the installer then execute our
// self-installation, otherwise just continue as usual. // 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(); installer::install();
} }
} }

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

@ -6,7 +6,7 @@ use failure::{self, ResultExt};
use log::info; use log::info;
/// The default npm registry used when we aren't working with a custom registry. /// 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. /// Run the `npm pack` command.
pub fn npm_pack(path: &str) -> Result<(), failure::Error> { 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. /// Run the `npm login` command.
pub fn npm_login( pub fn npm_login(
registry: &String, registry: &str,
scope: &Option<String>, scope: &Option<String>,
always_auth: bool, always_auth: bool,
auth_type: &Option<String>, auth_type: &Option<String>,

@ -82,7 +82,7 @@ impl ProgressOutput {
} }
/// Add an error message. /// Add an error message.
pub fn error(&self, message: String) { pub fn error(&self, message: &str) {
let err = format!( let err = format!(
"{} {}: {}", "{} {}: {}",
emoji::ERROR, emoji::ERROR,
@ -142,3 +142,9 @@ impl Drop for ProgressOutput {
self.done(); 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); PBAR.step(step, &msg);
let crate_readme_path = path.join("README.md"); let crate_readme_path = path.join("README.md");
let new_readme_path = out_dir.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"); PBAR.warn("origin crate has no README");
}; }
Ok(()) Ok(())
} }

@ -11,7 +11,7 @@ use wasm_pack::bindgen;
fn can_download_prebuilt_wasm_bindgen() { fn can_download_prebuilt_wasm_bindgen() {
let dir = tempfile::TempDir::new().unwrap(); let dir = tempfile::TempDir::new().unwrap();
let cache = Cache::at(dir.path()); 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").unwrap().is_file());
assert!(dl.binary("wasm-bindgen-test-runner").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() { fn downloading_prebuilt_wasm_bindgen_handles_http_errors() {
let dir = tempfile::TempDir::new().unwrap(); 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 cache = Cache::at(dir.path());
let result = bindgen::download_prebuilt_wasm_bindgen(&cache, bad_version, true); let result = bindgen::download_prebuilt_wasm_bindgen(&cache, bad_version, true);
assert!(result.is_err()); assert!(result.is_err());

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

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

@ -8,7 +8,7 @@ fn it_gets_wasm_bindgen_version() {
fixture.cargo_check(); fixture.cargo_check();
let data = CrateData::new(&fixture.path).unwrap(); let data = CrateData::new(&fixture.path).unwrap();
let lock = Lockfile::new(&data).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] #[test]
@ -17,7 +17,7 @@ fn it_gets_wasm_bindgen_test_version() {
fixture.cargo_check(); fixture.cargo_check();
let data = CrateData::new(&fixture.path).unwrap(); let data = CrateData::new(&fixture.path).unwrap();
let lock = Lockfile::new(&data).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] #[test]
@ -46,7 +46,7 @@ fn it_gets_wasm_bindgen_version_in_crate_inside_workspace() {
crate-type = ["cdylib"] crate-type = ["cdylib"]
[dependencies] [dependencies]
wasm-bindgen = "=0.2.21" wasm-bindgen = "=0.2.37"
"#, "#,
) )
.file( .file(
@ -62,7 +62,7 @@ fn it_gets_wasm_bindgen_version_in_crate_inside_workspace() {
fixture.cargo_check(); fixture.cargo_check();
let data = CrateData::new(&fixture.path.join("blah")).unwrap(); let data = CrateData::new(&fixture.path.join("blah")).unwrap();
let lock = Lockfile::new(&data).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] #[test]
@ -91,7 +91,7 @@ fn it_gets_wasm_bindgen_version_from_dependencies() {
crate-type = ["cdylib"] crate-type = ["cdylib"]
[dependencies] [dependencies]
wasm-bindgen = "=0.2.21" wasm-bindgen = "=0.2.37"
"#, "#,
) )
.file( .file(
@ -130,5 +130,5 @@ fn it_gets_wasm_bindgen_version_from_dependencies() {
fixture.cargo_check(); fixture.cargo_check();
let data = CrateData::new(&fixture.path.join("parent")).unwrap(); let data = CrateData::new(&fixture.path.join("parent")).unwrap();
let lock = Lockfile::new(&data).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::fs;
use std::path::PathBuf; use std::path::PathBuf;
use utils::{self, fixture}; use utils::{self, fixture};
use wasm_pack::{self, license, manifest, readme}; use wasm_pack::command::build::Target;
use wasm_pack::{self, license, manifest};
#[test] #[test]
fn it_gets_the_crate_name_default_path() { 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); let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
assert!(crate_data assert!(crate_data
.write_package_json(&out_dir, &None, false, "", &step) .write_package_json(&out_dir, &None, false, &Target::Bundler, &step)
.is_ok()); .is_ok());
let package_json_path = &fixture.path.join("pkg").join("package.json"); let package_json_path = &fixture.path.join("pkg").join("package.json");
fs::metadata(package_json_path).unwrap(); 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); let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
assert!(crate_data assert!(crate_data
.write_package_json(&out_dir, &None, false, "", &step) .write_package_json(&out_dir, &None, false, &Target::Bundler, &step)
.is_ok()); .is_ok());
let package_json_path = &fixture.path.join("pkg").join("package.json"); let package_json_path = &fixture.path.join("pkg").join("package.json");
fs::metadata(package_json_path).unwrap(); 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); let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
assert!(crate_data 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()); .is_ok());
let package_json_path = &fixture.path.join("pkg").join("package.json"); let package_json_path = &fixture.path.join("pkg").join("package.json");
fs::metadata(package_json_path).unwrap(); 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); let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
assert!(crate_data assert!(crate_data
.write_package_json(&out_dir, &None, false, "nodejs", &step) .write_package_json(&out_dir, &None, false, &Target::Nodejs, &step)
.is_ok()); .is_ok());
let package_json_path = &out_dir.join("package.json"); let package_json_path = &out_dir.join("package.json");
fs::metadata(package_json_path).unwrap(); 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); let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
assert!(crate_data 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()); .is_ok());
let package_json_path = &out_dir.join("package.json"); let package_json_path = &out_dir.join("package.json");
fs::metadata(package_json_path).unwrap(); 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); let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
assert!(crate_data assert!(crate_data
.write_package_json(&out_dir, &None, false, "", &step) .write_package_json(&out_dir, &None, false, &Target::Bundler, &step)
.is_ok()); .is_ok());
let package_json_path = &fixture.path.join(&out_dir).join("package.json"); 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); let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
assert!(crate_data assert!(crate_data
.write_package_json(&out_dir, &None, true, "", &step) .write_package_json(&out_dir, &None, true, &Target::Bundler, &step)
.is_ok()); .is_ok());
let package_json_path = &out_dir.join("package.json"); let package_json_path = &out_dir.join("package.json");
fs::metadata(package_json_path).unwrap(); 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); let step = wasm_pack::progressbar::Step::new(2);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
crate_data crate_data
.write_package_json(&out_dir, &None, true, "", &step) .write_package_json(&out_dir, &None, true, &Target::Bundler, &step)
.unwrap(); .unwrap();
let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).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); let step = wasm_pack::progressbar::Step::new(2);
wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
crate_data crate_data
.write_package_json(&out_dir, &None, true, "", &step) .write_package_json(&out_dir, &None, true, &Target::Bundler, &step)
.unwrap(); .unwrap();
let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).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(); wasm_pack::command::utils::create_pkg_dir(&out_dir, &step).unwrap();
license::copy_from_crate(&crate_data, &fixture.path, &out_dir, &step).unwrap(); license::copy_from_crate(&crate_data, &fixture.path, &out_dir, &step).unwrap();
crate_data crate_data
.write_package_json(&out_dir, &None, false, "", &step) .write_package_json(&out_dir, &None, false, &Target::Bundler, &step)
.unwrap(); .unwrap();
let package_json_path = &fixture.path.join("pkg").join("package.json"); 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, 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"] crate-type = ["cdylib"]
[dependencies] [dependencies]
wasm-bindgen = "=0.2.21" wasm-bindgen = "0.2"
[dev-dependencies] [dev-dependencies]
# no wasm-bindgen-test dep here! # no wasm-bindgen-test dep here!
@ -218,10 +218,10 @@ fn renamed_crate_name_works() {
name = 'bar' name = 'bar'
[dependencies] [dependencies]
wasm-bindgen = "=0.2.21" wasm-bindgen = "0.2"
[dev-dependencies] [dev-dependencies]
wasm-bindgen-test = "=0.2.21" wasm-bindgen-test = "0.2"
"#, "#,
) )
.file( .file(
@ -258,10 +258,10 @@ fn cdylib_not_required() {
authors = [] authors = []
[dependencies] [dependencies]
wasm-bindgen = "=0.2.21" wasm-bindgen = "0.2"
[dev-dependencies] [dev-dependencies]
wasm-bindgen-test = "=0.2.21" wasm-bindgen-test = "0.2"
"#, "#,
) )
.file( .file(
@ -293,7 +293,7 @@ fn cdylib_not_required() {
} }
#[test] #[test]
fn test_output_is_printed_once() { fn test_output_is_printed_once_in_both_stdout_and_failures() {
let fixture = fixture::Fixture::new(); let fixture = fixture::Fixture::new();
fixture fixture
.readme() .readme()
@ -322,6 +322,9 @@ fn test_output_is_printed_once() {
) )
.install_local_wasm_bindgen(); .install_local_wasm_bindgen();
let _lock = fixture.lock(); let _lock = fixture.lock();
// there will be only one log in stdout, and only one log in failures
let log_cnt = 1;
fixture fixture
.wasm_pack() .wasm_pack()
.arg("test") .arg("test")
@ -329,6 +332,8 @@ fn test_output_is_printed_once() {
.assert() .assert()
.failure() .failure()
.stderr(predicate::function(|err: &str| { .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. /// Add `WTFPL LICENSE` file to the fixture.
pub fn wtfpl_license(&self) -> &Self { pub fn wtfpl_license(&self) -> &Self {
self.file( self.file(
@ -127,10 +137,15 @@ impl Fixture {
crate-type = ["cdylib"] crate-type = ["cdylib"]
[dependencies] [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] [dev-dependencies]
wasm-bindgen-test = "=0.2.21" wasm-bindgen-test = "0.2"
"#, "#,
name name
), ),
@ -201,7 +216,7 @@ impl Fixture {
pub fn install_local_wasm_bindgen(&self) -> PathBuf { pub fn install_local_wasm_bindgen(&self) -> PathBuf {
static INSTALL_WASM_BINDGEN: Once = ONCE_INIT; static INSTALL_WASM_BINDGEN: Once = ONCE_INIT;
let cache = self.cache(); let cache = self.cache();
let version = "0.2.21"; let version = "0.2.37";
let download = || { let download = || {
if let Ok(download) = if let Ok(download) =
@ -351,10 +366,10 @@ pub fn no_cdylib() -> Fixture {
# crate-type = ["cdylib"] # crate-type = ["cdylib"]
[dependencies] [dependencies]
wasm-bindgen = "=0.2.21" wasm-bindgen = "0.2"
[dev-dependencies] [dev-dependencies]
wasm-bindgen-test = "=0.2.21" wasm-bindgen-test = "0.2"
"#, "#,
); );
fixture fixture
@ -403,14 +418,14 @@ pub fn wbg_test_diff_versions() -> Fixture {
crate-type = ["cdylib", "rlib"] crate-type = ["cdylib", "rlib"]
[dependencies] [dependencies]
# We depend on wasm-bindgen 0.2.21 # We depend on the latest wasm-bindgen 0.2
wasm-bindgen = "=0.2.21" wasm-bindgen = "0.2"
[dev-dependencies] [dev-dependencies]
# And we depend on wasm-bindgen-test 0.2.19. This should still # And we depend on wasm-bindgen-test 0.2.29. This should still
# work, and we should end up with `wasm-bindgen` at 0.2.21 and # work, and we should end up with the latest `wasm-bindgen` and
# wasm-bindgen-test at 0.2.19, and everything should still work. # wasm-bindgen-test at 0.2.29, and everything should still work.
wasm-bindgen-test = "0.2.19" wasm-bindgen-test = "0.2.29"
"#, "#,
) )
.file( .file(
@ -522,12 +537,12 @@ pub fn transitive_dependencies() -> Fixture {
crate-type = ["cdylib"] crate-type = ["cdylib"]
[dependencies] [dependencies]
wasm-bindgen = "=0.2.21" wasm-bindgen = "0.2"
project_a = { path = "../project_a" } project_a = { path = "../project_a" }
project_b = { path = "../project_b" } project_b = { path = "../project_b" }
[dev-dependencies] [dev-dependencies]
wasm-bindgen-test = "=0.2.21" wasm-bindgen-test = "0.2"
"#, "#,
); );
fixture.file( fixture.file(
@ -572,11 +587,11 @@ pub fn transitive_dependencies() -> Fixture {
crate-type = ["cdylib"] crate-type = ["cdylib"]
[dependencies] [dependencies]
wasm-bindgen = "=0.2.21" wasm-bindgen = "0.2"
project_b = { path = "../project_b" } project_b = { path = "../project_b" }
[dev-dependencies] [dev-dependencies]
wasm-bindgen-test = "=0.2.21" wasm-bindgen-test = "0.2"
"#, "#,
); );
fixture.file( fixture.file(
@ -622,10 +637,10 @@ pub fn transitive_dependencies() -> Fixture {
crate-type = ["cdylib"] crate-type = ["cdylib"]
[dependencies] [dependencies]
wasm-bindgen = "=0.2.21" wasm-bindgen = "0.2"
[dev-dependencies] [dev-dependencies]
wasm-bindgen-test = "=0.2.21" wasm-bindgen-test = "0.2"
"#, "#,
); );
fixture.file( fixture.file(
@ -662,7 +677,7 @@ pub fn single_license() -> Fixture {
fixture fixture
.readme() .readme()
.cargo_toml("single_license") .cargo_toml("single_license")
.wtfpl_license() .license()
.hello_world_src_lib(); .hello_world_src_lib();
fixture fixture
} }

Loading…
Cancel
Save