From 519980f0a74cbfbee2ac9bb59ccc6d9e07b2b801 Mon Sep 17 00:00:00 2001 From: mvlabat Date: Sat, 8 Dec 2018 11:54:38 +0200 Subject: [PATCH 1/6] Add support for importing reserved JS words --- crates/cli-support/Cargo.toml | 1 + crates/cli-support/src/js/mod.rs | 77 +++++++++++++++++++++++++++++++- crates/cli-support/src/lib.rs | 2 + tests/wasm/import_class.js | 7 ++- tests/wasm/import_class.rs | 13 ++++++ 5 files changed, 96 insertions(+), 4 deletions(-) diff --git a/crates/cli-support/Cargo.toml b/crates/cli-support/Cargo.toml index 69dff1e034b..751c9b7b614 100644 --- a/crates/cli-support/Cargo.toml +++ b/crates/cli-support/Cargo.toml @@ -13,6 +13,7 @@ Shared support for the wasm-bindgen-cli package, an internal dependency [dependencies] base64 = "0.9" failure = "0.1.2" +lazy_static = "1.0.0" parity-wasm = "0.35" tempfile = "3.0" wasm-bindgen-gc = { path = '../gc', version = '=0.2.29' } diff --git a/crates/cli-support/src/js/mod.rs b/crates/cli-support/src/js/mod.rs index 65258e06c9e..05863680dcd 100644 --- a/crates/cli-support/src/js/mod.rs +++ b/crates/cli-support/src/js/mod.rs @@ -118,6 +118,58 @@ const INITIAL_HEAP_VALUES: &[&str] = &["undefined", "null", "true", "false"]; // Must be kept in sync with `src/lib.rs` of the `wasm-bindgen` crate const INITIAL_HEAP_OFFSET: usize = 32; +lazy_static! { + static ref JS_KEYWORDS: HashSet<&'static str> = { + let mut keywords = HashSet::new(); + keywords.insert("await"); + keywords.insert("break"); + keywords.insert("case"); + keywords.insert("catch"); + keywords.insert("class"); + keywords.insert("const"); + keywords.insert("continue"); + keywords.insert("debugger"); + keywords.insert("default"); + keywords.insert("delete"); + keywords.insert("do"); + keywords.insert("else"); + keywords.insert("enum"); + keywords.insert("export"); + keywords.insert("extends"); + keywords.insert("false"); + keywords.insert("finally"); + keywords.insert("for"); + keywords.insert("function"); + keywords.insert("if"); + keywords.insert("implements"); + keywords.insert("import"); + keywords.insert("in"); + keywords.insert("instanceof"); + keywords.insert("interface"); + keywords.insert("new"); + keywords.insert("null"); + keywords.insert("package"); + keywords.insert("private"); + keywords.insert("protected"); + keywords.insert("public"); + keywords.insert("return"); + keywords.insert("super"); + keywords.insert("switch"); + keywords.insert("this"); + keywords.insert("throw"); + keywords.insert("true"); + keywords.insert("try"); + keywords.insert("typeof"); + keywords.insert("undefined"); + keywords.insert("var"); + keywords.insert("void"); + keywords.insert("while"); + keywords.insert("with"); + keywords.insert("yield"); + keywords + }; +} + impl<'a> Context<'a> { fn export(&mut self, name: &str, contents: &str, comments: Option) { let contents = contents.trim(); @@ -1858,7 +1910,7 @@ impl<'a> Context<'a> { let class = self.import_identifier(name); let op = match &method_data.kind { decode::MethodKind::Constructor => { - return Ok(ImportTarget::Constructor(class.to_string())) + return Ok(ImportTarget::Constructor(class.to_string())); } decode::MethodKind::Operation(op) => op, }; @@ -2649,7 +2701,7 @@ impl<'a> Import<'a> { fn generate_identifier(name: &str, used_names: &mut HashMap) -> String { let cnt = used_names.entry(name.to_string()).or_insert(0); *cnt += 1; - if *cnt == 1 { + if *cnt == 1 && !JS_KEYWORDS.contains(name) { name.to_string() } else { format!("{}{}", name, cnt) @@ -2668,3 +2720,24 @@ fn format_doc_comments(comments: &[&str], js_doc_comments: Option) -> St }; format!("/**\n{}{}*/\n", body, doc) } + +#[test] +fn test_generate_identifier() { + let mut used_names: HashMap = HashMap::new(); + assert_eq!( + generate_identifier("someVar", &mut used_names), + "someVar".to_string() + ); + assert_eq!( + generate_identifier("someVar", &mut used_names), + "someVar2".to_string() + ); + assert_eq!( + generate_identifier("default", &mut used_names), + "default1".to_string() + ); + assert_eq!( + generate_identifier("default", &mut used_names), + "default2".to_string() + ); +} diff --git a/crates/cli-support/src/lib.rs b/crates/cli-support/src/lib.rs index 41145965cda..62a04960cb4 100644 --- a/crates/cli-support/src/lib.rs +++ b/crates/cli-support/src/lib.rs @@ -1,5 +1,7 @@ #![doc(html_root_url = "https://docs.rs/wasm-bindgen-cli-support/0.2")] +#[macro_use] +extern crate lazy_static; extern crate parity_wasm; #[macro_use] extern crate wasm_bindgen_shared as shared; diff --git a/tests/wasm/import_class.js b/tests/wasm/import_class.js index ebc29759266..b86ab92be04 100644 --- a/tests/wasm/import_class.js +++ b/tests/wasm/import_class.js @@ -30,7 +30,7 @@ class Construct { Construct.internal_string = ''; exports.Construct = Construct; -exports.NewConstructors = class { +class NewConstructor { constructor(field) { this.field = field; } @@ -38,7 +38,10 @@ exports.NewConstructors = class { get() { return this.field + 1; } -}; +} + +exports.NewConstructors = NewConstructor; +exports.default = NewConstructor; let switch_called = false; class SwitchMethods { diff --git a/tests/wasm/import_class.rs b/tests/wasm/import_class.rs index 60c7668d2a2..447238c3370 100644 --- a/tests/wasm/import_class.rs +++ b/tests/wasm/import_class.rs @@ -29,6 +29,13 @@ extern "C" { #[wasm_bindgen(method)] fn get(this: &NewConstructors) -> i32; + #[wasm_bindgen(js_name = default)] + type RenamedTypes; + #[wasm_bindgen(constructor)] + fn new(arg: i32) -> RenamedTypes; + #[wasm_bindgen(method)] + fn get(this: &RenamedTypes) -> i32; + fn switch_methods_a(); fn switch_methods_b(); type SwitchMethods; @@ -125,6 +132,12 @@ fn new_constructors() { assert_eq!(f.get(), 2); } +#[wasm_bindgen_test] +fn rename_type() { + let f = RenamedTypes::new(1); + assert_eq!(f.get(), 2); +} + #[wasm_bindgen_test] fn switch_methods() { assert!(!switch_methods_called()); From 4ae4a7134b4b4ebfb795b51b74092e6d9eeca916 Mon Sep 17 00:00:00 2001 From: mvlabat Date: Sun, 9 Dec 2018 11:06:38 +0200 Subject: [PATCH 2/6] Fix import_class tests for RenamedTypes --- tests/wasm/import_class.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/wasm/import_class.rs b/tests/wasm/import_class.rs index 447238c3370..080e8f1ce91 100644 --- a/tests/wasm/import_class.rs +++ b/tests/wasm/import_class.rs @@ -31,9 +31,9 @@ extern "C" { #[wasm_bindgen(js_name = default)] type RenamedTypes; - #[wasm_bindgen(constructor)] + #[wasm_bindgen(constructor, js_class = default)] fn new(arg: i32) -> RenamedTypes; - #[wasm_bindgen(method)] + #[wasm_bindgen(method, js_class = default)] fn get(this: &RenamedTypes) -> i32; fn switch_methods_a(); From 7e6a3e6473a5843998ba3c55e8bfba40c6de3dec Mon Sep 17 00:00:00 2001 From: mvlabat Date: Sun, 9 Dec 2018 11:44:46 +0200 Subject: [PATCH 3/6] Add some more js reserved words (including global properties) --- crates/cli-support/src/js/mod.rs | 103 ++++++++++++++++--------------- 1 file changed, 54 insertions(+), 49 deletions(-) diff --git a/crates/cli-support/src/js/mod.rs b/crates/cli-support/src/js/mod.rs index 05863680dcd..7f35e2f93a9 100644 --- a/crates/cli-support/src/js/mod.rs +++ b/crates/cli-support/src/js/mod.rs @@ -119,54 +119,59 @@ const INITIAL_HEAP_VALUES: &[&str] = &["undefined", "null", "true", "false"]; const INITIAL_HEAP_OFFSET: usize = 32; lazy_static! { - static ref JS_KEYWORDS: HashSet<&'static str> = { - let mut keywords = HashSet::new(); - keywords.insert("await"); - keywords.insert("break"); - keywords.insert("case"); - keywords.insert("catch"); - keywords.insert("class"); - keywords.insert("const"); - keywords.insert("continue"); - keywords.insert("debugger"); - keywords.insert("default"); - keywords.insert("delete"); - keywords.insert("do"); - keywords.insert("else"); - keywords.insert("enum"); - keywords.insert("export"); - keywords.insert("extends"); - keywords.insert("false"); - keywords.insert("finally"); - keywords.insert("for"); - keywords.insert("function"); - keywords.insert("if"); - keywords.insert("implements"); - keywords.insert("import"); - keywords.insert("in"); - keywords.insert("instanceof"); - keywords.insert("interface"); - keywords.insert("new"); - keywords.insert("null"); - keywords.insert("package"); - keywords.insert("private"); - keywords.insert("protected"); - keywords.insert("public"); - keywords.insert("return"); - keywords.insert("super"); - keywords.insert("switch"); - keywords.insert("this"); - keywords.insert("throw"); - keywords.insert("true"); - keywords.insert("try"); - keywords.insert("typeof"); - keywords.insert("undefined"); - keywords.insert("var"); - keywords.insert("void"); - keywords.insert("while"); - keywords.insert("with"); - keywords.insert("yield"); - keywords + static ref JS_RESERVED_WORDS: HashSet<&'static str> = { + let mut words = HashSet::with_capacity(49); + words.insert("Infinity"); + words.insert("NaN"); + words.insert("arguments"); + words.insert("await"); + words.insert("break"); + words.insert("case"); + words.insert("catch"); + words.insert("class"); + words.insert("const"); + words.insert("continue"); + words.insert("debugger"); + words.insert("default"); + words.insert("delete"); + words.insert("do"); + words.insert("else"); + words.insert("enum"); + words.insert("export"); + words.insert("extends"); + words.insert("false"); + words.insert("finally"); + words.insert("for"); + words.insert("function"); + words.insert("if"); + words.insert("implements"); + words.insert("import"); + words.insert("in"); + words.insert("instanceof"); + words.insert("interface"); + words.insert("let"); + words.insert("new"); + words.insert("null"); + words.insert("package"); + words.insert("private"); + words.insert("protected"); + words.insert("public"); + words.insert("require"); + words.insert("return"); + words.insert("super"); + words.insert("switch"); + words.insert("this"); + words.insert("throw"); + words.insert("true"); + words.insert("try"); + words.insert("typeof"); + words.insert("undefined"); + words.insert("var"); + words.insert("void"); + words.insert("while"); + words.insert("with"); + words.insert("yield"); + words }; } @@ -2701,7 +2706,7 @@ impl<'a> Import<'a> { fn generate_identifier(name: &str, used_names: &mut HashMap) -> String { let cnt = used_names.entry(name.to_string()).or_insert(0); *cnt += 1; - if *cnt == 1 && !JS_KEYWORDS.contains(name) { + if *cnt == 1 && !JS_RESERVED_WORDS.contains(name) { name.to_string() } else { format!("{}{}", name, cnt) From 46b4a2d8f0f676af531915ebe02f7be6828e240f Mon Sep 17 00:00:00 2001 From: mvlabat Date: Sun, 9 Dec 2018 12:38:11 +0200 Subject: [PATCH 4/6] Remove globals from the reserved words, add eval --- crates/cli-support/src/js/mod.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/crates/cli-support/src/js/mod.rs b/crates/cli-support/src/js/mod.rs index 7f35e2f93a9..cda935b7202 100644 --- a/crates/cli-support/src/js/mod.rs +++ b/crates/cli-support/src/js/mod.rs @@ -120,9 +120,7 @@ const INITIAL_HEAP_OFFSET: usize = 32; lazy_static! { static ref JS_RESERVED_WORDS: HashSet<&'static str> = { - let mut words = HashSet::with_capacity(49); - words.insert("Infinity"); - words.insert("NaN"); + let mut words = HashSet::with_capacity(47); words.insert("arguments"); words.insert("await"); words.insert("break"); @@ -137,6 +135,7 @@ lazy_static! { words.insert("do"); words.insert("else"); words.insert("enum"); + words.insert("eval"); words.insert("export"); words.insert("extends"); words.insert("false"); @@ -156,7 +155,6 @@ lazy_static! { words.insert("private"); words.insert("protected"); words.insert("public"); - words.insert("require"); words.insert("return"); words.insert("super"); words.insert("switch"); @@ -165,7 +163,6 @@ lazy_static! { words.insert("true"); words.insert("try"); words.insert("typeof"); - words.insert("undefined"); words.insert("var"); words.insert("void"); words.insert("while"); From 082a12f88c4735272c499455d084fe78a36d1b67 Mon Sep 17 00:00:00 2001 From: mvlabat Date: Sun, 9 Dec 2018 14:06:50 +0200 Subject: [PATCH 5/6] Prevent mangling names for non-module imports --- crates/cli-support/src/js/mod.rs | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/crates/cli-support/src/js/mod.rs b/crates/cli-support/src/js/mod.rs index cda935b7202..4b443856993 100644 --- a/crates/cli-support/src/js/mod.rs +++ b/crates/cli-support/src/js/mod.rs @@ -1824,7 +1824,12 @@ impl<'a> Context<'a> { .or_insert_with(Default::default) .entry(import.name()) .or_insert_with(|| { - let name = generate_identifier(import.name(), imported_identifiers); + let name = match &import { + Import::Module { .. } => { + generate_identifier(import.name(), imported_identifiers, true) + } + _ => generate_identifier(import.name(), imported_identifiers, false), + }; match &import { Import::Module { module, .. } => { if use_node_require { @@ -2700,10 +2705,14 @@ impl<'a> Import<'a> { } } -fn generate_identifier(name: &str, used_names: &mut HashMap) -> String { +fn generate_identifier( + name: &str, + used_names: &mut HashMap, + mangle_reserved_names: bool, +) -> String { let cnt = used_names.entry(name.to_string()).or_insert(0); *cnt += 1; - if *cnt == 1 && !JS_RESERVED_WORDS.contains(name) { + if *cnt == 1 && !(mangle_reserved_names && JS_RESERVED_WORDS.contains(name)) { name.to_string() } else { format!("{}{}", name, cnt) @@ -2727,19 +2736,23 @@ fn format_doc_comments(comments: &[&str], js_doc_comments: Option) -> St fn test_generate_identifier() { let mut used_names: HashMap = HashMap::new(); assert_eq!( - generate_identifier("someVar", &mut used_names), + generate_identifier("someVar", &mut used_names, true), "someVar".to_string() ); assert_eq!( - generate_identifier("someVar", &mut used_names), + generate_identifier("someVar", &mut used_names, true), "someVar2".to_string() ); assert_eq!( - generate_identifier("default", &mut used_names), + generate_identifier("default", &mut used_names, true), "default1".to_string() ); assert_eq!( - generate_identifier("default", &mut used_names), + generate_identifier("default", &mut used_names, true), "default2".to_string() ); + assert_eq!( + generate_identifier("eval", &mut used_names, false), + "eval".to_string() + ); } From e9ff83c673686d61503a5df57ab18dc90c85c700 Mon Sep 17 00:00:00 2001 From: mvlabat Date: Sun, 9 Dec 2018 14:10:38 +0200 Subject: [PATCH 6/6] Add tests pass for cli-support crate --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index de257e3fedb..4788a5adec4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -120,6 +120,11 @@ matrix: - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then aws s3 sync ~/$TRAVIS_BUILD_NUMBER s3://wasm-bindgen-ci/$TRAVIS_BUILD_NUMBER; fi if: branch = master + # The `cli-support` crate's tests pass + - name: "test cli-support crate" + script: cargo test -p wasm-bindgen-cli-support + if: branch = master + # The `web-sys` crate's tests pass - name: "test web-sys crate" install: