diff --git a/.travis.yml b/.travis.yml index 0400ab68..9e87b531 100644 --- a/.travis.yml +++ b/.travis.yml @@ -51,9 +51,12 @@ matrix: (cd examples/dom && sed -i 's/: "webpack-dev-server"/: "webpack"/' package.json && ./build.sh) - | (cd examples/wasm-in-wasm && sed -i 's/: "webpack-dev-server"/: "webpack"/' package.json && ./build.sh) + - | + (cd examples/char && sed -i 's/: "webpack-dev-server"/: "webpack"/' package.json && ./build.sh) - | (cd examples/closures && sed -i 's/: "webpack-dev-server"/: "webpack"/' package.json && ./build.sh) + install: - curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash - source ~/.nvm/nvm.sh diff --git a/Cargo.toml b/Cargo.toml index 84112a47..3bae5e9e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ members = [ "examples/no_modules", "examples/add", "examples/asm.js", + "examples/char", ] [profile.release] diff --git a/crates/cli-support/src/descriptor.rs b/crates/cli-support/src/descriptor.rs index 0b07579c..d43324d3 100644 --- a/crates/cli-support/src/descriptor.rs +++ b/crates/cli-support/src/descriptor.rs @@ -32,6 +32,7 @@ tys! { ANYREF ENUM RUST_STRUCT + CHAR } #[derive(Debug)] @@ -57,6 +58,7 @@ pub enum Descriptor { Anyref, Enum, RustStruct(String), + Char, } #[derive(Debug)] @@ -122,6 +124,7 @@ impl Descriptor { .collect(); Descriptor::RustStruct(name) } + CHAR => Descriptor::Char, other => panic!("unknown descriptor: {}", other), } } diff --git a/crates/cli-support/src/js/js2rust.rs b/crates/cli-support/src/js/js2rust.rs index a338618d..63a5b8c8 100644 --- a/crates/cli-support/src/js/js2rust.rs +++ b/crates/cli-support/src/js/js2rust.rs @@ -3,7 +3,7 @@ use failure::Error; use super::{indent, Context}; use descriptor::{Descriptor, Function}; -/// Helper struct for manfuacturing a shim in JS used to translate JS types to +/// Helper struct for manufacturing a shim in JS used to translate JS types to /// Rust, aka pass from JS back into Rust pub struct Js2Rust<'a, 'b: 'a> { cx: &'a mut Context<'b>, @@ -210,6 +210,10 @@ impl<'a, 'b> Js2Rust<'a, 'b> { } self.rust_arguments.push(format!("{} ? 1 : 0", name)); } + Descriptor::Char => { + self.js_arguments.push((name.clone(), "string".to_string())); + self.rust_arguments.push(format!("{}.codePointAt(0)", name)) + }, Descriptor::Anyref => { self.js_arguments.push((name.clone(), "any".to_string())); self.cx.expose_add_heap_object(); @@ -299,6 +303,10 @@ impl<'a, 'b> Js2Rust<'a, 'b> { self.ret_ty = "boolean".to_string(); self.ret_expr = format!("return (RET) !== 0;"); } + Descriptor::Char => { + self.ret_ty = "string".to_string(); + self.ret_expr = format!("return String.fromCodePoint(RET)") + } Descriptor::Anyref => { self.ret_ty = "any".to_string(); self.cx.expose_take_object(); @@ -316,7 +324,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> { /// invoking, like `wasm.bar` or `this.f`. /// /// Returns two strings, the first of which is the JS expression for the - /// generated function shim and the second is a TyepScript signature of rthe + /// generated function shim and the second is a TypeScript signature of the /// JS expression. pub fn finish(&self, prefix: &str, invoc: &str) -> (String, String) { let js_args = self.js_arguments diff --git a/crates/cli-support/src/js/rust2js.rs b/crates/cli-support/src/js/rust2js.rs index 3f08935d..841811a2 100644 --- a/crates/cli-support/src/js/rust2js.rs +++ b/crates/cli-support/src/js/rust2js.rs @@ -3,7 +3,7 @@ use failure::Error; use descriptor::{Descriptor, Function}; use super::{indent, Context, Js2Rust}; -/// Helper struct for manfuacturing a shim in JS used to translate Rust types to +/// Helper struct for manufacturing a shim in JS used to translate Rust types to /// JS, then invoking an imported JS function. pub struct Rust2Js<'a, 'b: 'a> { cx: &'a mut Context<'b>, @@ -211,6 +211,9 @@ impl<'a, 'b> Rust2Js<'a, 'b> { let invoc_arg = match *arg { ref d if d.is_number() => abi, Descriptor::Boolean => format!("{} !== 0", abi), + Descriptor::Char => { + format!("String.fromCodePoint({})", abi) + } Descriptor::Anyref => { self.cx.expose_take_object(); format!("takeObject({})", abi) @@ -269,6 +272,7 @@ impl<'a, 'b> Rust2Js<'a, 'b> { } self.ret_expr = match *ty { Descriptor::Boolean => "return JS ? 1 : 0;".to_string(), + Descriptor::Char => "return JS.codePointAt(0)".to_string(), Descriptor::Anyref => { self.cx.expose_add_heap_object(); "return addHeapObject(JS);".to_string() diff --git a/examples/README.md b/examples/README.md index a3708c15..f62f9f2e 100644 --- a/examples/README.md +++ b/examples/README.md @@ -33,5 +33,6 @@ The examples here are: numbers. * `asm.js` - an example of using the `wasm2asm` tool from [binaryen] to convert the generated WebAssembly to normal JS +* `char` - an example of passing the rust `char` type to and from the js `string` type [binaryen]: https://github.com/WebAssembly/binaryen diff --git a/examples/char/.gitignore b/examples/char/.gitignore new file mode 100644 index 00000000..937451e4 --- /dev/null +++ b/examples/char/.gitignore @@ -0,0 +1,4 @@ +package-lock.json +char.js +char_bg.js +char_bg.wasm diff --git a/examples/char/Cargo.toml b/examples/char/Cargo.toml new file mode 100644 index 00000000..d4243cb9 --- /dev/null +++ b/examples/char/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "char" +version = "0.1.0" +authors = ["Robert Masen "] + +[lib] +crate-type = ["cdylib"] + +[dependencies] +# Here we're using a path dependency to use what's already in this repository, +# but you'd use the commented out version below if you're copying this into your +# project. +wasm-bindgen = { path = "../.." } +#wasm-bindgen = "0.2" diff --git a/examples/char/README.md b/examples/char/README.md new file mode 100644 index 00000000..69a64d9a --- /dev/null +++ b/examples/char/README.md @@ -0,0 +1,13 @@ +# Char + +This directory is an example of how the `#[wasm_bindgen]` macro will convert the rust `char` type to a single code-point js `string`. + +You can build the example locally with: + +``` +$ ./build.sh +``` + +Opening your web browser should display a single counter with a random character for it's `key` and 0 for its `count`. You can click the `+` button to increase a counter's count. By clicking on the "add counter" button you should see a new counter added to the list with a different random character for it's `key`. + +Under the hood javascript is choosing a random character from an Array of characters and passing that to the rust Counter struct's constructor so the character you are seeing on the page has made the full round trip from js to rust and back to js. \ No newline at end of file diff --git a/examples/char/build.sh b/examples/char/build.sh new file mode 100755 index 00000000..a8a03cdf --- /dev/null +++ b/examples/char/build.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +set -ex + +# Build the `hello_world.wasm` file using Cargo/rustc +cargo +nightly build --target wasm32-unknown-unknown + +# Run the `wasm-bindgen` CLI tool to postprocess the wasm file emitted by the +# Rust compiler to emit the JS support glue that's necessary +# +# Here we're using the version of the CLI in this repository, but for external +# usage you'd use the commented out version below +cargo +nightly run --manifest-path ../../crates/cli/Cargo.toml \ + --bin wasm-bindgen -- \ + ../../target/wasm32-unknown-unknown/debug/char.wasm --out-dir . +# wasm-bindgen ../../target/wasm32-unknown-unknown/hello_world.wasm --out-dir . + +# Finally, package everything up using Webpack and start a server so we can +# browse the result + +npm install +npm run serve diff --git a/examples/char/chars.js b/examples/char/chars.js new file mode 100644 index 00000000..563ad71d --- /dev/null +++ b/examples/char/chars.js @@ -0,0 +1,85 @@ +export let chars = [ +"!","#","$","%","&","'","(",")","*","+",",", +"-",".","/","0","1","2","3","4","5","6","7", +"8","9",":",";","<","=",">","?","@","A","B", +"C","D","E","F","G","H","I","J","K","L","M", +"N","O","P","Q","R","S","T","U","V","W","X", +"Y","Z","[","]","^","_","`","a","b","c", +"d","e","f","g","h","i","j","k","l","m","n", +"o","p","q","r","s","t","u","v","w","x","y", +"z","{","|","}","~"," ","¡","¢","£","¤","¥", +"¦","§","¨","©","ª","«","¬","®","¯","°", +"±","²","³","´","µ","¶","·","¸","¹","º","»", +"¼","½","¾","¿","À","Á","Â","Ã","Ä","Å","Æ", +"Ç","È","É","Ê","Ë","Ì","Í","Î","Ï","Ð","Ñ", +"Ò","Ó","Ô","Õ","Ö","×","Ø","Ù","Ú","Û","Ü", +"Ý","Þ","ß","à","á","â","ã","ä","å","æ","ç", +"è","é","ê","ë","ì","í","î","ï","ð","ñ","ò", +"ó","ô","õ","ö","÷","ø","ù","ú","û","ü","ý", +"þ","ÿ","Ā","ā","Ă","ă","Ą","ą","Ć","ć","Ĉ", +"ĉ","Ċ","ċ","Č","č","Ď","ď","Đ","đ","Ē","ē", +"Ĕ","ĕ","Ė","ė","Ę","ę","Ě","ě","Ĝ","ĝ","Ğ", +"ğ","Ġ","ġ","Ģ","ģ","Ĥ","ĥ","Ħ","ħ","Ĩ","ĩ", +"Ī","ī","Ĭ","ĭ","Į","į","İ","ı","IJ","ij","Ĵ", +"ĵ","Ķ","ķ","ĸ","Ĺ","ĺ","Ļ","ļ","Ľ","ľ","Ŀ", +"ŀ","Ł","ł","Ń","ń","Ņ","ņ","Ň","ň","ʼn","Ŋ", +"ŋ","Ō","ō","Ŏ","ŏ","Ő","ő","Œ","œ","Ŕ","ŕ", +"Ŗ","ŗ","Ř","ř","Ś","ś","Ŝ","ŝ","Ş","ş","Š", +"š","Ţ","ţ","Ť","ť","Ŧ","ŧ","Ũ","ũ","Ū","ū", +"Ŭ","ŭ","Ů","ů","Ű","ű","Ų","ų","Ŵ","ŵ","Ŷ", +"ŷ","Ÿ","Ź","ź","Ż","ż","Ž","ž","ſ","ƀ","Ɓ", +"Ƃ","ƃ","Ƅ","ƅ","Ɔ","Ƈ","ƈ","Ɖ","Ɗ","Ƌ","ƌ", +"ƍ","Ǝ","Ə","Ɛ","Ƒ","ƒ","Ɠ","Ɣ","ƕ","Ɩ","Ɨ", +"Ƙ","ƙ","ƚ","ƛ","Ɯ","Ɲ","ƞ","Ɵ","Ơ","ơ","Ƣ", +"ƣ","Ƥ","ƥ","Ʀ","Ƨ","ƨ","Ʃ","ƪ","ƫ","Ƭ","ƭ", +"Ʈ","Ư","ư","Ʊ","Ʋ","Ƴ","ƴ","Ƶ","ƶ","Ʒ","Ƹ", +"ƹ","ƺ","ƻ","Ƽ","ƽ","ƾ","ƿ","ǀ","ǁ","ǂ","ǃ", +"DŽ","Dž","dž","LJ","Lj","lj","NJ","Nj","nj","Ǎ","ǎ", +"Ǐ","ǐ","Ǒ","ǒ","Ǔ","ǔ","Ǖ","ǖ","Ǘ","ǘ","Ǚ", +"ǚ","Ǜ","ǜ","ǝ","Ǟ","ǟ","Ǡ","ǡ","Ǣ","ǣ","Ǥ", +"ǥ","Ǧ","ǧ","Ǩ","ǩ","Ǫ","ǫ","Ǭ","ǭ","Ǯ","ǯ", +"ǰ","DZ","Dz","dz","Ǵ","ǵ","Ƕ","Ƿ","Ǹ","ǹ","Ǻ", +"ǻ","Ǽ","ǽ","Ǿ","ǿ","Ȁ","ȁ","Ȃ","ȃ","Ȅ","ȅ", +"Ȇ","ȇ","Ȉ","ȉ","Ȋ","ȋ","Ȍ","ȍ","Ȏ","ȏ","Ȑ", +"ȑ","Ȓ","ȓ","Ȕ","ȕ","Ȗ","ȗ","Ș","ș","Ț","ț", +"Ȝ","ȝ","Ȟ","ȟ","Ƞ","ȡ","Ȣ","ȣ","Ȥ","ȥ","Ȧ", +"ȧ","Ȩ","ȩ","Ȫ","ȫ","Ȭ","ȭ","Ȯ","ȯ","Ȱ","ȱ", +"Ȳ","ȳ","ȴ","ȵ","ȶ","ȷ","ȸ","ȹ","Ⱥ","Ȼ","ȼ", +"Ƚ","Ⱦ","ȿ","ɀ","Ɂ","ɂ","Ƀ","Ʉ","Ʌ","Ɇ","ɇ", +"Ɉ","ɉ","Ɋ","ɋ","Ɍ","ɍ","Ɏ","ɏ","ɐ","ɑ","ɒ", +"ɓ","ɔ","ɕ","ɖ","ɗ","ɘ","ə","ɚ","ɛ","ɜ","ɝ", +"ɞ","ɟ","ɠ","ɡ","ɢ","ɣ","ɤ","ɥ","ɦ","ɧ","ɨ", +"ɩ","ɪ","ɫ","ɬ","ɭ","ɮ","ɯ","ɰ","ɱ","ɲ","ɳ", +"ɴ","ɵ","ɶ","ɷ","ɸ","ɹ","ɺ","ɻ","ɼ","ɽ","ɾ", +"ɿ","ʀ","ʁ","ʂ","ʃ","ʄ","ʅ","ʆ","ʇ","ʈ","ʉ", +"ʊ","ʋ","ʌ","ʍ","ʎ","ʏ","ʐ","ʑ","ʒ","ʓ","ʔ", +"ʕ","ʖ","ʗ","ʘ","ʙ","ʚ","ʛ","ʜ","ʝ","ʞ","ʟ", +"ʠ","ʡ","ʢ","ʣ","ʤ","ʥ","ʦ","ʧ","ʨ","ʩ","ʪ", +"ʫ","ʬ","ʭ","ʮ","ʯ","Ͳ","ͳ","ʹ","͵","Ͷ","ͷ", +"ͺ","ͻ","ͼ","ͽ",";","Ϳ","΄","΅","Ά","·","Έ","Ή", +"Ί","Ό","Ύ","Ώ", +"ΐ","Α","Β","Γ","Δ","Ε","Ζ","Η","Θ","Ι","Κ", +"Λ","Μ","Ν","Ξ","Ο","Π","Ρ","Σ","Τ","Υ","Φ", +"Χ","Ψ","Ω","Ϊ","Ϋ","ά","έ","ή","ί","ΰ","α", +"β","γ","δ","ε","ζ","η","θ","ι","κ","λ","μ", +"ν","ξ","ο","π","ρ","ς","σ","τ","υ","φ","χ", +"ψ","ω","ϊ","ϋ","ό","ύ","ώ","Ϗ","ϐ","ϑ","ϒ", +"ϓ","ϔ","ϕ","ϖ","ϗ","Ϙ","ϙ","Ϛ","ϛ","Ϝ","ϝ", +"Ϟ","ϟ","Ϡ","ϡ","Ϣ","ϣ","Ϥ","ϥ","Ϧ","ϧ","Ϩ", +"ϩ","Ϫ","ϫ","Ϭ","ϭ","Ϯ","ϯ","ϰ","ϱ","ϲ","ϳ", +"Օ","Ֆ","🕧","🕨","🕩","🕪","🕫","🕬","🕭","🕮", +"🕯","🕰","🕱","🕲","🕳","🕴","🕵","🕶","🕷","🕸", +"🕹","🕺","🕻","🕼","🕽","🕾","🕿","🖀","🖁","🖂", +"🖃","🖄","🖅","🖆","🖇","🖈","🖉","🖊","🖋", +"🖌","🖍","🖎","🖏","🖐","🖑","🖒","🖓","🖔","🖕", +"🖖","🖗","🖘","🖙","🖚","🖛","🖜","🖝","🖞","🖟", +"🖠","🖡","🖢","🖣","🖤","🖥","🖦","🖧","🖨","🖩", +"🖪","🖫","🖬","🖭","🖮","🖯","🖰","🖱","🖲","🖳", +"🖴","🖵","🖶","🖷","🖸","🖹","🖺","🖻","🖼","🖽", +"🖾","🖿","🗀","🗁","🗂","🗃","🗄","🗅","🗆","🗇", +"🗈","🗉","🗊","🗋","🗌","🗍","🗎","🗏","🗐","🗑","🗒", +"🗓","🗔","🗕","🗖","🗗","🗘","🗙","🗚","🗛","🗜", +"🗝","🗞","🗟","🗠","🗡","🗢","🗣","🗤","🗥","🗦", +"🗧","🗨","🗩","🗪","🗫","🗬","🗭","🗮","🗯","🗰", +"🗱","🗲","🗳","🗴","🗵","🗶","🗷","🗸","🗹","🗺", +"🗻","🗼","🗽","🗾","🗿","😀"]; \ No newline at end of file diff --git a/examples/char/index.html b/examples/char/index.html new file mode 100644 index 00000000..a60f8698 --- /dev/null +++ b/examples/char/index.html @@ -0,0 +1,56 @@ + + + + Counter + + + + +
+ +
+ + + \ No newline at end of file diff --git a/examples/char/index.js b/examples/char/index.js new file mode 100644 index 00000000..dc041853 --- /dev/null +++ b/examples/char/index.js @@ -0,0 +1,73 @@ +import {chars} from './chars.js' +let imp = import('./char.js') +let mod; + +let counters = []; +imp.then(wasm => { + mod = wasm; + addCounter(); + let b = document.getElementById('add-counter'); + if (!b) throw new Error('Unable to find #add-counter'); + b.addEventListener('click', ev => addCounter()) +}); + +function addCounter() { + let ctr = mod.Counter.new(randomChar(), 0); + counters.push(ctr); + update(); +} + +function update() { + let container = document.getElementById('container'); + if (!container) throw new Error('Unable to find #container in dom'); + while (container.hasChildNodes()) { + if (container.lastChild.id == "add-counter") break; + container.removeChild(container.lastChild); + } + for (var i = 0; i < counters.length; i++) { + let counter = counters[i]; + container.appendChild(newCounter(counter.key(), counter.count(), ev => { + counter.increment(); + update(); + })) + } +} + +function randomChar() { + console.log('randomChar'); + let idx = Math.floor(Math.random() * (chars.length - 1)); + console.log('index', idx); + let ret = chars.splice(idx, 1)[0]; + console.log('char', ret); + return ret; +} + +function newCounter(key, value, cb) { + let container = document.createElement('div'); + container.setAttribute('class', 'counter'); + let title = document.createElement('h1'); + title.appendChild(document.createTextNode('Counter ' + key)); + container.appendChild(title); + container.appendChild(newField('Count', value)); + let plus = document.createElement('button'); + plus.setAttribute('type', 'button'); + plus.setAttribute('class', 'plus-button'); + plus.appendChild(document.createTextNode('+')); + plus.addEventListener('click', cb); + container.appendChild(plus); + return container; +} + +function newField(key, value) { + let ret = document.createElement('div'); + ret.setAttribute('class', 'field'); + let name = document.createElement('span'); + name.setAttribute('class', 'name'); + name.appendChild(document.createTextNode(key)); + ret.appendChild(name); + let val = document.createElement('span'); + val.setAttribute('class', 'value'); + val.appendChild(document.createTextNode(value)); + ret.appendChild(val); + return ret; +} \ No newline at end of file diff --git a/examples/char/package.json b/examples/char/package.json new file mode 100644 index 00000000..8f2c63dc --- /dev/null +++ b/examples/char/package.json @@ -0,0 +1,10 @@ +{ + "scripts": { + "serve": "webpack-dev-server" + }, + "devDependencies": { + "webpack": "^4.8.3", + "webpack-cli": "^2.1.3", + "webpack-dev-server": "^3.1.4" + } +} diff --git a/examples/char/src/lib.rs b/examples/char/src/lib.rs new file mode 100644 index 00000000..b15d0ed3 --- /dev/null +++ b/examples/char/src/lib.rs @@ -0,0 +1,49 @@ +#![feature(proc_macro, wasm_custom_section, wasm_import_module)] + +extern crate wasm_bindgen; + +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +extern { + #[wasm_bindgen(js_namespace = console)] + fn log(s: &str); +} + +#[derive(Debug)] +#[wasm_bindgen] +pub struct Counter { + key: char, + count: i32 +} + +#[wasm_bindgen] +impl Counter { + pub fn default() -> Counter { + log("Counter::default"); + Self::new('a', 0) + } + pub fn new(key: char, count: i32) -> Counter { + log(&format!("Counter::new({}, {})", key, count)); + Counter { key: key, count: count } + } + + pub fn key(&self) -> char { + log("Counter.key()"); + self.key + } + + pub fn count(&self) -> i32 { + log("Counter.count"); + self.count + } + + pub fn increment(&mut self) { + log("Counter.increment"); + self.count += 1; + } + + pub fn update_key(&mut self, key: char) { + self.key = key; + } +} \ No newline at end of file diff --git a/examples/char/webpack.config.js b/examples/char/webpack.config.js new file mode 100644 index 00000000..5910e2ae --- /dev/null +++ b/examples/char/webpack.config.js @@ -0,0 +1,10 @@ +const path = require('path'); + +module.exports = { + entry: "./index.js", + output: { + path: path.resolve(__dirname, "dist"), + filename: "index.js", + }, + mode: "development" +}; diff --git a/src/convert.rs b/src/convert.rs index 1a1279bc..0b0b69a1 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -1,10 +1,11 @@ -//! This is mostly an internal module, no stability guarantees are provied. Use +//! This is mostly an internal module, no stability guarantees are provided. Use //! at your own risk. use core::mem::{self, ManuallyDrop}; use core::ops::{Deref, DerefMut}; use core::slice; use core::str; +use core::char; use {JsValue, throw}; use describe::*; @@ -134,6 +135,18 @@ impl FromWasmAbi for bool { unsafe fn from_abi(js: u32, _extra: &mut Stack) -> bool { js != 0 } } +impl IntoWasmAbi for char { + type Abi = u32; + fn into_abi(self, _extra: &mut Stack) -> u32 { self as u32 } +} + +impl FromWasmAbi for char { + type Abi = u32; + unsafe fn from_abi(js: u32, _extra: &mut Stack) -> char { + char::from_u32_unchecked(js) + } +} + impl IntoWasmAbi for *const T { type Abi = u32; @@ -526,4 +539,4 @@ stack_closures! { (A B C D E) (A B C D E F) (A B C D E F G) -} +} \ No newline at end of file diff --git a/src/describe.rs b/src/describe.rs index 39446542..bc98c980 100644 --- a/src/describe.rs +++ b/src/describe.rs @@ -37,6 +37,7 @@ tys! { ANYREF ENUM RUST_STRUCT + CHAR } pub fn inform(a: u32) { @@ -71,6 +72,7 @@ simple! { f32 => F32 f64 => F64 bool => BOOLEAN + char => CHAR str => STRING JsValue => ANYREF } diff --git a/tests/all/char.rs b/tests/all/char.rs new file mode 100644 index 00000000..ce4fb7dd --- /dev/null +++ b/tests/all/char.rs @@ -0,0 +1,60 @@ +use super::project; + +#[test] +fn works() { + project() + .file("src/lib.rs", r#" + #![feature(proc_macro, wasm_custom_section, wasm_import_module)] + + extern crate wasm_bindgen; + + use wasm_bindgen::prelude::*; + + #[wasm_bindgen(module = "./test")] + extern { + fn js_parrot(c: char) -> char; + } + + #[wasm_bindgen] + pub fn single_char() -> char { 'a' } + #[wasm_bindgen] + pub fn wide_char() -> char { '💩' } + + #[wasm_bindgen] + pub fn parrot(c: char) -> char { c } + + #[wasm_bindgen] + pub fn short_test(a: char) { assert_eq!(a, 'a'); } + #[wasm_bindgen] + pub fn wide_test(p: char) { assert_eq!(p, '💩'); } + + #[wasm_bindgen] + pub fn char_round(c: char)-> char { js_parrot(c) } + "#) + .file("test.js", r#" + import * as wasm from './out'; + + function assertEq(a, b) { + console.log(a, '?=', b); + if (a === b) + return; + throw new Error('not equal'); + } + + export function test() { + assertEq(wasm.single_char(), 'a'); + assertEq(wasm.wide_char(), '💩'); + assertEq(wasm.parrot('Ղ'), 'Ղ'); + assertEq(wasm.parrot('ҝ'), 'ҝ'); + assertEq(wasm.parrot('Δ'), 'Δ'); + assertEq(wasm.parrot('䉨'), '䉨'); + assertEq(wasm.char_round('a'), 'a'); + assertEq(wasm.char_round('㊻'), '㊻'); + wasm.short_test('a'); + wasm.wide_test('💩'); + } + + export function js_parrot(a) { return a; } + "#) + .test(); +} diff --git a/tests/all/main.rs b/tests/all/main.rs index 749d016b..18e312bb 100644 --- a/tests/all/main.rs +++ b/tests/all/main.rs @@ -382,3 +382,4 @@ mod slice; mod structural; mod non_wasm; mod u64; +mod char; \ No newline at end of file