diff --git a/Cargo.lock b/Cargo.lock index 8ec1f81d..89bf7d6c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -58,6 +58,11 @@ name = "bitflags" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "byteorder" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cc" version = "1.0.10" @@ -294,6 +299,14 @@ dependencies = [ "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parity-wasm" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot" version = "0.5.4" @@ -640,6 +653,7 @@ dependencies = [ "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "indicatif 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", "quicli 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", @@ -692,6 +706,7 @@ dependencies = [ "checksum backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe525f66f42d207968308ee86bc2dd60aa5fab535b22e616323a173d097d8e" "checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" +"checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87" "checksum cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8b9d2900f78631a5876dc5d6c9033ede027253efcd33dd36b1309fc6cab97ee0" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" "checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536" @@ -722,6 +737,7 @@ dependencies = [ "checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" +"checksum parity-wasm 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79df7454d764da3aaf4e8f696e5c4b97eb82b47abfc89850bfdcf7badfad357e" "checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd" "checksum parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "538ef00b7317875071d5e00f603f24d16f0b474c1a5fc0ccb8b454ca72eafa79" "checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118" diff --git a/Cargo.toml b/Cargo.toml index bceac2c2..62b38062 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ readme = "README.md" console = "0.6.1" failure = "0.1.1" indicatif = "0.9.0" +parity-wasm = "0.28" quicli = "0.2" serde = "1.0" serde_derive = "1.0" diff --git a/src/lib.rs b/src/lib.rs index e9b6f6fe..ad94d78c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ extern crate failure; extern crate indicatif; #[macro_use] extern crate lazy_static; +extern crate parity_wasm; extern crate quicli; #[macro_use] extern crate serde_derive; diff --git a/src/manifest.rs b/src/manifest.rs index 9ea770fa..60d68fa2 100644 --- a/src/manifest.rs +++ b/src/manifest.rs @@ -1,9 +1,13 @@ +use std::collections::BTreeMap; use std::fs::File; use std::io::prelude::*; +use std::path::Path; use console::style; use emoji; -use failure::Error; +use failure::{Error, ResultExt}; +use parity_wasm; +use parity_wasm::elements::*; use serde_json; use toml; use PBAR; @@ -33,6 +37,7 @@ struct NpmPackage { repository: Option, files: Vec, main: String, + dependencies: Option>, } #[derive(Serialize)] @@ -42,24 +47,100 @@ struct Repository { url: String, } -fn read_cargo_toml(path: &str) -> Result { - let manifest_path = format!("{}/Cargo.toml", path); - let mut cargo_file = File::open(manifest_path)?; +fn read_cargo_toml(path: &Path) -> Result { + let mut cargo_file = File::open(path.join("Cargo.toml"))?; let mut cargo_contents = String::new(); cargo_file.read_to_string(&mut cargo_contents)?; Ok(toml::from_str(&cargo_contents)?) } +/// Locates the `__wasm_pack_unstable` module section inside the wasm file +/// specified, parsing it and returning dependencies found. +/// +/// Crates compiled with `wasm-bindgen` can declare dependencies on NPM packages +/// in their code and this is communicated to us, `wasm-pack`, via a custom +/// section in the final binary. +fn read_npm_dependencies(wasm: &Path) -> Result, Error> { + #[derive(Deserialize)] + #[serde(untagged)] + enum Schema<'a> { + V1 { + version: &'a str, + modules: Vec<(String, String)>, + }, + Unknown { + version: &'a str, + }, + } + + let mut module = parity_wasm::deserialize_file(wasm) + .with_context(|_| format!("failed to parse `{}` as wasm", wasm.display()))?; + let wasm_pack_module; + let deps = { + let result = module + .sections() + .iter() + .enumerate() + .filter_map(|(i, s)| match *s { + Section::Custom(ref cs) => Some((i, cs)), + _ => None, + }) + .find(|&(_i, section)| section.name() == "__wasm_pack_unstable"); + let data = match result { + Some((i, section)) => { + wasm_pack_module = i; + section.payload() + } + None => return Ok(BTreeMap::new()), + }; + let schema = serde_json::from_slice(data).with_context(|_| { + "the wasm file emitted by `wasm-bindgen` contains a \ + `__wasm_pack_unstable` section which should describe \ + js dependencies, but it's in a format that this \ + `wasm-pack` tool does not understand; does `wasm-pack` \ + need to be updated?" + })?; + let modules = match schema { + Schema::V1 { + version, + ref modules, + } if version == "0.0.1" => + { + modules.clone() + } + Schema::Unknown { version } | Schema::V1 { version, .. } => bail!( + "the wasm file emitted by `wasm-bindgen` contains a \ + `__wasm_pack_unstable` section which should describe \ + js dependencies, but it's schema version is `{}` \ + while this `wasm-pack` tool only understands the \ + schema version 0.0.1; does `wasm-pack` need to be updated?", + version + ), + }; + + modules.into_iter().collect() + }; + + // Delete the `__wasm_pack_unstable` custom section and rewrite the wasm + // file that we're emitting. + module.sections_mut().remove(wasm_pack_module); + parity_wasm::serialize_to_file(wasm, module) + .with_context(|_| format!("failed to write wasm to `{}`", wasm.display()))?; + + Ok(deps) +} + impl CargoManifest { - fn into_npm(mut self, scope: Option) -> NpmPackage { + fn into_npm(mut self, pkg: &Path, scope: Option) -> Result { let filename = self.package.name.replace("-", "_"); let wasm_file = format!("{}_bg.wasm", filename); let js_file = format!("{}.js", filename); + let dependencies = read_npm_dependencies(&pkg.join(&wasm_file))?; if let Some(s) = scope { self.package.name = format!("@{}/{}", s, self.package.name); } - NpmPackage { + Ok(NpmPackage { name: self.package.name, collaborators: self.package.authors, description: self.package.description, @@ -71,12 +152,18 @@ impl CargoManifest { }), files: vec![wasm_file], main: js_file, - } + dependencies: if dependencies.len() == 0 { + None + } else { + Some(dependencies) + }, + }) } } /// Generate a package.json file inside in `./pkg`. pub fn write_package_json(path: &str, scope: Option) -> Result<(), Error> { + let path = Path::new(path); let step = format!( "{} {}Writing a package.json...", style("[4/7]").bold().dim(), @@ -91,10 +178,10 @@ pub fn write_package_json(path: &str, scope: Option) -> Result<(), Error }; let pb = PBAR.message(&step); - let pkg_file_path = format!("{}/pkg/package.json", path); + let pkg_file_path = path.join("pkg/package.json"); let mut pkg_file = File::create(pkg_file_path)?; let crate_data = read_cargo_toml(path)?; - let npm_data = crate_data.into_npm(scope); + let npm_data = crate_data.into_npm(&path.join("pkg"), scope)?; if npm_data.description.is_none() { PBAR.warn(&warn_fmt("description")); @@ -113,5 +200,5 @@ pub fn write_package_json(path: &str, scope: Option) -> Result<(), Error } pub fn get_crate_name(path: &str) -> Result { - Ok(read_cargo_toml(path)?.package.name) + Ok(read_cargo_toml(Path::new(path))?.package.name) } diff --git a/tests/fixtures/dependencies/Cargo.lock b/tests/fixtures/dependencies/Cargo.lock new file mode 100644 index 00000000..6f3f9b88 --- /dev/null +++ b/tests/fixtures/dependencies/Cargo.lock @@ -0,0 +1,176 @@ +[[package]] +name = "dtoa" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "itoa" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num-traits" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro2" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scopes-hello-world" +version = "0.1.0" +dependencies = [ + "wasm-bindgen 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde" +version = "1.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde_derive" +version = "1.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.12.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive_internals" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.12.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.12.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasm-bindgen" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "wasm-bindgen-macro 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-backend 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" +"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" +"checksum num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3c2bd9b9d21e48e956b763c9f37134dc62d9e95da6edb3f672cacb6caf3cd3" +"checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0" +"checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118" +"checksum quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408" +"checksum quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0ff51282f28dc1b53fd154298feaa2e77c5ea0dba68e1fd8b03b72fbe13d2a" +"checksum serde 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "c73f63e08b33f6e59dfb3365b009897ebc3a3edc4af6e4f3ce8e483cf3d80ce7" +"checksum serde_derive 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "9cd9e89b8be5b611971734eaf887f1da0ce1a5b51491f04b09fe855649a84f3b" +"checksum serde_derive_internals 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a79b781fe5c4a7037a10a485249a499ea02927046360afe7e04885aad2f9c10c" +"checksum serde_json 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "fab6c4d75bedcf880711c85e39ebf8ccc70d0eba259899047ec5d7436643ee17" +"checksum syn 0.12.14 (registry+https://github.com/rust-lang/crates.io-index)" = "8c5bc2d6ff27891209efa5f63e9de78648d7801f085e4653701a692ce938d6fd" +"checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum wasm-bindgen 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3d40bb360252b92b57cf5ee800c92d30ae842e41d3d84bcc4fc1d3deb72d5b02" +"checksum wasm-bindgen-backend 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7f1a0ad26bc8fac6cbf68097e3dd4ffa40a288dda34e83bfaa7ff4626b69085d" +"checksum wasm-bindgen-macro 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3a600fa1ce92e2e8db8f89a15baf679e5bac39561e55e750cda9fb6a317e64c3" +"checksum wasm-bindgen-shared 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "aba2057a4e843cb2d754a923d46bb62aeab1531c58a78160f392e7ded8de3637" diff --git a/tests/fixtures/dependencies/Cargo.toml b/tests/fixtures/dependencies/Cargo.toml new file mode 100644 index 00000000..bad6f67f --- /dev/null +++ b/tests/fixtures/dependencies/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "dependencies" +description = "an example rust->wasm crate" +version = "0.1.0" +authors = ["Michael Gattozzi "] +license = "WTFPL" +repository = "https://github.com/ashleygwilliams/wasm-pack" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +wasm-bindgen = "0.2.4" diff --git a/tests/fixtures/dependencies/README.md b/tests/fixtures/dependencies/README.md new file mode 100644 index 00000000..97b39af9 --- /dev/null +++ b/tests/fixtures/dependencies/README.md @@ -0,0 +1,2 @@ +# scopes-hello-world +> an example rust -> wasm project diff --git a/tests/fixtures/dependencies/scopes-hello-world_bg.wasm b/tests/fixtures/dependencies/scopes-hello-world_bg.wasm new file mode 100644 index 00000000..fbc5109d Binary files /dev/null and b/tests/fixtures/dependencies/scopes-hello-world_bg.wasm differ diff --git a/tests/fixtures/dependencies/scopes_hello_world_bg.wasm b/tests/fixtures/dependencies/scopes_hello_world_bg.wasm new file mode 100644 index 00000000..fbc5109d Binary files /dev/null and b/tests/fixtures/dependencies/scopes_hello_world_bg.wasm differ diff --git a/tests/fixtures/dependencies/src/lib.rs b/tests/fixtures/dependencies/src/lib.rs new file mode 100644 index 00000000..9e44b28c --- /dev/null +++ b/tests/fixtures/dependencies/src/lib.rs @@ -0,0 +1,15 @@ +#![feature(proc_macro, wasm_import_module, wasm_custom_section)] + +extern crate wasm_bindgen; + +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +extern { + fn alert(s: &str); +} + +#[wasm_bindgen] +pub fn greet(name: &str) { + alert(&format!("Hello, {}!", name)); +} diff --git a/tests/manifest/add.wasm b/tests/manifest/add.wasm new file mode 100644 index 00000000..fbc5109d Binary files /dev/null and b/tests/manifest/add.wasm differ diff --git a/tests/manifest/dependencies.wasm b/tests/manifest/dependencies.wasm new file mode 100644 index 00000000..267a4353 Binary files /dev/null and b/tests/manifest/dependencies.wasm differ diff --git a/tests/manifest/main.rs b/tests/manifest/main.rs index 813087d6..06072fa4 100644 --- a/tests/manifest/main.rs +++ b/tests/manifest/main.rs @@ -8,19 +8,20 @@ mod utils; use std::fs; +use utils::FailureExt; use wasm_pack::manifest; #[test] fn it_gets_the_crate_name_default_path() { assert!(manifest::get_crate_name(".").is_ok()); - assert_eq!(manifest::get_crate_name(".").unwrap(), "wasm-pack"); + assert_eq!(manifest::get_crate_name(".").unwrap_pretty(), "wasm-pack"); } #[test] fn it_gets_the_crate_name_provided_path() { assert!(manifest::get_crate_name("tests/fixtures/js-hello-world").is_ok()); assert_eq!( - manifest::get_crate_name("tests/fixtures/js-hello-world").unwrap(), + manifest::get_crate_name("tests/fixtures/js-hello-world").unwrap_pretty(), "js-hello-world" ); } @@ -28,12 +29,13 @@ fn it_gets_the_crate_name_provided_path() { #[test] fn it_creates_a_package_json_default_path() { let path = ".".to_string(); - wasm_pack::command::create_pkg_dir(&path).unwrap(); + wasm_pack::command::create_pkg_dir(&path).unwrap_pretty(); + utils::mock_wasm(path.as_ref(), "wasm_pack"); assert!(manifest::write_package_json(&path, None).is_ok()); let package_json_path = format!("{}/pkg/package.json", &path); assert!(fs::metadata(package_json_path).is_ok()); assert!(utils::read_package_json(&path).is_ok()); - let pkg = utils::read_package_json(&path).unwrap(); + let pkg = utils::read_package_json(&path).unwrap_pretty(); assert_eq!(pkg.name, "wasm-pack"); assert_eq!(pkg.repository.ty, "git"); assert_eq!( @@ -42,28 +44,48 @@ fn it_creates_a_package_json_default_path() { ); assert_eq!(pkg.files, ["wasm_pack_bg.wasm"]); assert_eq!(pkg.main, "wasm_pack.js"); + assert!(pkg.dependencies.is_none()); } #[test] fn it_creates_a_package_json_provided_path() { let path = "tests/fixtures/js-hello-world".to_string(); - wasm_pack::command::create_pkg_dir(&path).unwrap(); + wasm_pack::command::create_pkg_dir(&path).unwrap_pretty(); + utils::mock_wasm(path.as_ref(), "js_hello_world"); assert!(manifest::write_package_json(&path, None).is_ok()); let package_json_path = format!("{}/pkg/package.json", &path); assert!(fs::metadata(package_json_path).is_ok()); assert!(utils::read_package_json(&path).is_ok()); - let pkg = utils::read_package_json(&path).unwrap(); + let pkg = utils::read_package_json(&path).unwrap_pretty(); assert_eq!(pkg.name, "js-hello-world"); } #[test] fn it_creates_a_package_json_provided_path_with_scope() { let path = "tests/fixtures/scopes".to_string(); - wasm_pack::command::create_pkg_dir(&path).unwrap(); - assert!(manifest::write_package_json(&path, Some("test".to_string())).is_ok()); + wasm_pack::command::create_pkg_dir(&path).unwrap_pretty(); + utils::mock_wasm(path.as_ref(), "scopes_hello_world"); + manifest::write_package_json(&path, Some("test".to_string())).unwrap_pretty(); let package_json_path = format!("{}/pkg/package.json", &path); assert!(fs::metadata(package_json_path).is_ok()); assert!(utils::read_package_json(&path).is_ok()); - let pkg = utils::read_package_json(&path).unwrap(); + let pkg = utils::read_package_json(&path).unwrap_pretty(); assert_eq!(pkg.name, "@test/scopes-hello-world"); } + +#[test] +fn it_creates_package_json_with_dependencies() { + let path = "tests/fixtures/dependencies".to_string(); + wasm_pack::command::create_pkg_dir(&path).unwrap_pretty(); + utils::mock_wasm_with_deps(path.as_ref(), "dependencies"); + manifest::write_package_json(&path, None).unwrap_pretty(); + let package_json_path = format!("{}/pkg/package.json", &path); + assert!(fs::metadata(package_json_path).is_ok()); + assert!(utils::read_package_json(&path).is_ok()); + let pkg = utils::read_package_json(&path).unwrap_pretty(); + let deps = pkg.dependencies.as_ref().unwrap(); + assert_eq!(deps.len(), 1); + let (k, v) = deps.iter().next().unwrap(); + assert_eq!(k, "foo"); + assert_eq!(v, "^1.0.2"); +} diff --git a/tests/manifest/utils.rs b/tests/manifest/utils.rs index aa97d98d..cad11d2f 100644 --- a/tests/manifest/utils.rs +++ b/tests/manifest/utils.rs @@ -1,9 +1,26 @@ +use std::collections::BTreeMap; use std::fs::File; use std::io::prelude::*; +use std::path::Path; use failure::Error; use serde_json; +pub trait FailureExt { + fn unwrap_pretty(self) -> T; +} + +impl FailureExt for Result { + fn unwrap_pretty(self) -> T { + self.unwrap_or_else(|e| { + for e in e.causes() { + println!("err: {}", e); + } + panic!("unwrap failed"); + }) + } +} + #[derive(Deserialize)] pub struct NpmPackage { pub name: String, @@ -13,6 +30,7 @@ pub struct NpmPackage { pub repository: Repository, pub files: Vec, pub main: String, + pub dependencies: Option>, } #[derive(Deserialize)] @@ -30,3 +48,17 @@ pub fn read_package_json(path: &str) -> Result { Ok(serde_json::from_str(&pkg_contents)?) } + +const WASM: &[u8] = include_bytes!("add.wasm"); + +pub fn mock_wasm(path: &Path, name: &str) { + let path = path.join("pkg").join(format!("{}_bg.wasm", name)); + File::create(&path).unwrap().write_all(WASM).unwrap(); +} + +const DEP_WASM: &[u8] = include_bytes!("dependencies.wasm"); + +pub fn mock_wasm_with_deps(path: &Path, name: &str) { + let path = path.join("pkg").join(format!("{}_bg.wasm", name)); + File::create(&path).unwrap().write_all(DEP_WASM).unwrap(); +}