Merge pull request #48 from alexcrichton/no-glboal

Don't run `npm install` during tests
This commit is contained in:
Alex Crichton 2018-03-02 21:29:02 -06:00 committed by GitHub
commit 30986dacad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 4924 additions and 177 deletions

View File

@ -10,5 +10,6 @@ build: false
test_script: test_script:
- rustup target add wasm32-unknown-unknown - rustup target add wasm32-unknown-unknown
- yarn
- cargo test - cargo test
- cargo install --debug --path crates/wasm-bindgen-cli - cargo install --debug --path crates/wasm-bindgen-cli

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
/target/ /target/
**/*.rs.bk **/*.rs.bk
Cargo.lock Cargo.lock
node_modules

View File

@ -9,6 +9,7 @@ install:
- curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash - curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash
- source ~/.nvm/nvm.sh - source ~/.nvm/nvm.sh
- nvm install 9 - nvm install 9
- yarn
script: script:
- rustup target add wasm32-unknown-unknown - rustup target add wasm32-unknown-unknown

View File

@ -2,11 +2,10 @@ extern crate wasm_bindgen_cli_support as cli;
use std::env; use std::env;
use std::fs::{self, File}; use std::fs::{self, File};
use std::io::{Write, Read}; use std::io::{self, Write, Read};
use std::path::{PathBuf, Path}; use std::path::{PathBuf, Path};
use std::process::Command; use std::process::Command;
use std::sync::atomic::*; use std::sync::atomic::*;
use std::sync::{Once, ONCE_INIT};
use std::time::Instant; use std::time::Instant;
static CNT: AtomicUsize = ATOMIC_USIZE_INIT; static CNT: AtomicUsize = ATOMIC_USIZE_INIT;
@ -51,55 +50,63 @@ pub fn project() -> Project {
("Cargo.lock".to_string(), lockfile), ("Cargo.lock".to_string(), lockfile),
("run.ts".to_string(), r#" ("run.js".to_string(), r#"
import * as process from "process"; import * as process from "process";
import * as out from "./out_wasm"; const test = import("./test");
import * as test from "./test";
out.booted.then(() => { test.then(test => {
test.test(); test.test();
if ((out as any).assertHeapAndStackEmpty)
(out as any).assertHeapAndStackEmpty();
}).catch(error => { }).catch(error => {
console.error(error); console.error(error);
process.exit(1); process.exit(1);
}); });
"#.to_string()), "#.to_string()),
("rollup.config.js".to_string(), r#" ("webpack.config.js".to_string(), r#"
import typescript from 'rollup-plugin-typescript2'; const path = require('path');
export default { module.exports = {
input: './run.ts', entry: './run.js',
mode: "development",
plugins: [ devtool: "source-map",
typescript() module: {
], rules: [
output: { {
file: 'bundle.js', test: /\.ts$/,
format: 'cjs' use: 'ts-loader',
} exclude: /node_modules/
}
]
},
resolve: {
extensions: [ '.ts', '.js', '.wasm' ]
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, '.')
},
target: 'node'
};
"#.to_string()),
("tsconfig.json".to_string(), r#"
{
"compilerOptions": {
"noEmitOnError": true,
"noImplicitAny": true,
"noImplicitThis": true,
"noUnusedParameters": true,
"noUnusedLocals": true,
"noImplicitReturns": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"alwaysStrict": true,
"strict": true,
"target": "es5",
"lib": ["es2015"]
}
} }
"#.to_string()), "#.to_string()),
("tsconfig.json".to_string(), r#"
{
"compilerOptions": {
"noEmitOnError": true,
"noImplicitAny": true,
"noImplicitThis": true,
"noUnusedParameters": true,
"noUnusedLocals": true,
"noImplicitReturns": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"alwaysStrict": true,
"strict": true,
"target": "es5"
}
}
"#.to_string()),
], ],
} }
} }
@ -116,40 +123,6 @@ pub fn root() -> PathBuf {
return me return me
} }
fn rollup() -> PathBuf {
static INIT: Once = ONCE_INIT;
let mut me = env::current_exe().unwrap();
me.pop(); // chop off exe name
me.pop(); // chop off `deps`
me.pop(); // chop off `debug` / `release`
let install_dir = me.clone();
me.push("node_modules/rollup/bin/rollup");
INIT.call_once(|| {
if !me.exists() {
let mut npm = if cfg!(windows) {
let mut n = Command::new("cmd");
n.arg("/c").arg("npm");
n
} else {
Command::new("npm")
};
run(npm
.arg("install")
.arg("rollup")
.arg("rollup-plugin-typescript2")
.arg("typescript")
.arg("@types/node")
//.arg("@types/webassembly-js-api")
.current_dir(&install_dir), "npm");
assert!(me.exists());
}
});
return me
}
impl Project { impl Project {
pub fn file(&mut self, name: &str, contents: &str) -> &mut Project { pub fn file(&mut self, name: &str, contents: &str) -> &mut Project {
self.files.push((name.to_string(), contents.to_string())); self.files.push((name.to_string(), contents.to_string()));
@ -216,13 +189,24 @@ impl Project {
.expect("failed to convert wasm to js"); .expect("failed to convert wasm to js");
File::create(root.join("out_wasm.d.ts")).unwrap() File::create(root.join("out_wasm.d.ts")).unwrap()
.write_all(obj.typescript().as_bytes()).unwrap(); .write_all(obj.typescript().as_bytes()).unwrap();
File::create(root.join("out_wasm.js")).unwrap()
.write_all(obj.js().as_bytes()).unwrap();
let mut cmd = Command::new("node");
cmd.arg(rollup()) // move files from the root into each test, it looks like this may be
.current_dir(&root) // needed for webpack to work well when invoked concurrently.
.arg("-c"); fs::hard_link("package.json", root.join("package.json")).unwrap();
fs::hard_link("yarn.lock", root.join("yarn.lock")).unwrap();
let cwd = env::current_dir().unwrap();
symlink_dir(&cwd.join("node_modules"), &root.join("node_modules")).unwrap();
let mut cmd = if cfg!(windows) {
let mut c = Command::new("cmd");
c.arg("/c");
c.arg("yarn");
c
} else {
Command::new("yarn")
};
cmd.arg("webpack").current_dir(&root);
run(&mut cmd, "node"); run(&mut cmd, "node");
let mut cmd = Command::new("node"); let mut cmd = Command::new("node");
@ -232,6 +216,18 @@ impl Project {
} }
} }
#[cfg(unix)]
fn symlink_dir(a: &Path, b: &Path) -> io::Result<()> {
use std::os::unix::fs::symlink;
symlink(a, b)
}
#[cfg(windows)]
fn symlink_dir(a: &Path, b: &Path) -> io::Result<()> {
use std::os::windows::fs::symlink_dir;
symlink_dir(a, b)
}
fn run(cmd: &mut Command, program: &str) { fn run(cmd: &mut Command, program: &str) {
println!("···················································"); println!("···················································");
println!("running {:?}", cmd); println!("running {:?}", cmd);

View File

@ -50,7 +50,13 @@ impl<'a> Context<'a> {
if !self.wasm_import_needed(name) { if !self.wasm_import_needed(name) {
return return
} }
let global = format!("export const {} = {};\n", name, f(self)); let contents = f(self);
let contents = contents.trim();
let global = if contents.starts_with("function") {
format!("export function {} {}\n", name, &contents[8..])
} else {
format!("export const {} = {};\n", name, contents)
};
self.globals.push_str(&global); self.globals.push_str(&global);
}; };
@ -83,18 +89,20 @@ impl<'a> Context<'a> {
bind("__wbindgen_object_drop_ref", &|me| { bind("__wbindgen_object_drop_ref", &|me| {
me.expose_drop_ref(); me.expose_drop_ref();
"dropRef".to_string() "function(i) { dropRef(i); }".to_string()
}); });
bind("__wbindgen_string_new", &|me| { bind("__wbindgen_string_new", &|me| {
me.expose_add_heap_object(); me.expose_add_heap_object();
me.expose_get_string_from_wasm(); me.expose_get_string_from_wasm();
String::from("(p, l) => addHeapObject(getStringFromWasm(p, l))") String::from("function(p, l) {
return addHeapObject(getStringFromWasm(p, l));
}")
}); });
bind("__wbindgen_number_new", &|me| { bind("__wbindgen_number_new", &|me| {
me.expose_add_heap_object(); me.expose_add_heap_object();
String::from("addHeapObject") String::from("function(i) { return addHeapObject(i); }")
}); });
bind("__wbindgen_number_get", &|me| { bind("__wbindgen_number_get", &|me| {
@ -113,32 +121,40 @@ impl<'a> Context<'a> {
bind("__wbindgen_undefined_new", &|me| { bind("__wbindgen_undefined_new", &|me| {
me.expose_add_heap_object(); me.expose_add_heap_object();
String::from("() => addHeapObject(undefined)") String::from("function() { return addHeapObject(undefined); }")
}); });
bind("__wbindgen_null_new", &|me| { bind("__wbindgen_null_new", &|me| {
me.expose_add_heap_object(); me.expose_add_heap_object();
String::from("() => addHeapObject(null)") String::from("function() {
return addHeapObject(null);
}")
}); });
bind("__wbindgen_is_null", &|me| { bind("__wbindgen_is_null", &|me| {
me.expose_get_object(); me.expose_get_object();
String::from("(idx) => getObject(idx) === null ? 1 : 0") String::from("function(idx) {
return getObject(idx) === null ? 1 : 0;
}")
}); });
bind("__wbindgen_is_undefined", &|me| { bind("__wbindgen_is_undefined", &|me| {
me.expose_get_object(); me.expose_get_object();
String::from("(idx) => getObject(idx) === undefined ? 1 : 0") String::from("function(idx) {
return getObject(idx) === undefined ? 1 : 0;
}")
}); });
bind("__wbindgen_boolean_new", &|me| { bind("__wbindgen_boolean_new", &|me| {
me.expose_add_heap_object(); me.expose_add_heap_object();
String::from("(v) => addHeapObject(v == 1)") String::from("function(v) {
return addHeapObject(v == 1);
}")
}); });
bind("__wbindgen_boolean_get", &|me| { bind("__wbindgen_boolean_get", &|me| {
me.expose_get_object(); me.expose_get_object();
String::from("(i) => { String::from("function(i) {
let v = getObject(i); let v = getObject(i);
if (typeof(v) == 'boolean') { if (typeof(v) == 'boolean') {
return v ? 1 : 0; return v ? 1 : 0;
@ -151,7 +167,7 @@ impl<'a> Context<'a> {
bind("__wbindgen_symbol_new", &|me| { bind("__wbindgen_symbol_new", &|me| {
me.expose_get_string_from_wasm(); me.expose_get_string_from_wasm();
me.expose_add_heap_object(); me.expose_add_heap_object();
format!("(ptr, len) => {{ format!("function(ptr, len) {{
let a; let a;
console.log(ptr, len); console.log(ptr, len);
if (ptr === 0) {{ if (ptr === 0) {{
@ -165,7 +181,9 @@ impl<'a> Context<'a> {
bind("__wbindgen_is_symbol", &|me| { bind("__wbindgen_is_symbol", &|me| {
me.expose_get_object(); me.expose_get_object();
String::from("(i) => typeof(getObject(i)) == 'symbol' ? 1 : 0") String::from("function(i) {
return typeof(getObject(i)) == 'symbol' ? 1 : 0;
}")
}); });
bind("__wbindgen_throw", &|me| { bind("__wbindgen_throw", &|me| {
@ -181,7 +199,7 @@ impl<'a> Context<'a> {
me.expose_pass_string_to_wasm(); me.expose_pass_string_to_wasm();
me.expose_get_object(); me.expose_get_object();
me.expose_uint32_memory(); me.expose_uint32_memory();
String::from("(i, len_ptr) => { String::from("function(i, len_ptr) {
let obj = getObject(i); let obj = getObject(i);
if (typeof(obj) !== 'string') if (typeof(obj) !== 'string')
return 0; return 0;
@ -295,45 +313,46 @@ impl<'a> Context<'a> {
let renamed_import = format!("__wbindgen_{}", import.field()); let renamed_import = format!("__wbindgen_{}", import.field());
let mut bind_math = |expr: &str| { let mut bind_math = |expr: &str| {
globals.push_str(&format!(" globals.push_str(&format!("
export const {} = {}; export function {}{}
", renamed_import, expr)); ", renamed_import, expr));
}; };
// FIXME(#32): try to not use function shims
match import.field() { match import.field() {
"Math_acos" => bind_math("Math.acos"), "Math_acos" => bind_math("(x) { return Math.acos(x); }"),
"Math_asin" => bind_math("Math.asin"), "Math_asin" => bind_math("(x) { return Math.asin(x); }"),
"Math_atan" => bind_math("Math.atan"), "Math_atan" => bind_math("(x) { return Math.atan(x); }"),
"Math_atan2" => bind_math("Math.atan2"), "Math_atan2" => bind_math("(x, y) { return Math.atan2(x, y); }"),
"Math_cbrt" => bind_math("Math.cbrt"), "Math_cbrt" => bind_math("(x) { return Math.cbrt(x); }"),
"Math_cosh" => bind_math("Math.cosh"), "Math_cosh" => bind_math("(x) { return Math.cosh(x); }"),
"Math_expm1" => bind_math("Math.expm1"), "Math_expm1" => bind_math("(x) { return Math.expm1(x); }"),
"Math_hypot" => bind_math("Math.hypot"), "Math_hypot" => bind_math("(x, y) { return Math.hypot(x, y); }"),
"Math_log1p" => bind_math("Math.log1p"), "Math_log1p" => bind_math("(x) { return Math.log1p(x); }"),
"Math_sinh" => bind_math("Math.sinh"), "Math_sinh" => bind_math("(x) { return Math.sinh(x); }"),
"Math_tan" => bind_math("Math.tan"), "Math_tan" => bind_math("(x) { return Math.tan(x); }"),
"Math_tanh" => bind_math("Math.tanh"), "Math_tanh" => bind_math("(x) { return Math.tanh(x); }"),
"cos" => bind_math("Math.cos"), "cos" => bind_math("(x) { return Math.cos(x); }"),
"cosf" => bind_math("Math.cos"), "cosf" => bind_math("(x) { return Math.cos(x); }"),
"exp" => bind_math("Math.exp"), "exp" => bind_math("(x) { return Math.exp(x); }"),
"expf" => bind_math("Math.exp"), "expf" => bind_math("(x) { return Math.exp(x); }"),
"log2" => bind_math("Math.log2"), "log2" => bind_math("(x) { return Math.log2(x); }"),
"log2f" => bind_math("Math.log2"), "log2f" => bind_math("(x) { return Math.log2(x); }"),
"log10" => bind_math("Math.log10"), "log10" => bind_math("(x) { return Math.log10(x); }"),
"log10f" => bind_math("Math.log10"), "log10f" => bind_math("(x) { return Math.log10(x); }"),
"log" => bind_math("Math.log"), "log" => bind_math("(x) { return Math.log(x); }"),
"logf" => bind_math("Math.log"), "logf" => bind_math("(x) { return Math.log(x); }"),
"round" => bind_math("Math.round"), "round" => bind_math("(x) { return Math.round(x); }"),
"roundf" => bind_math("Math.round"), "roundf" => bind_math("(x) { return Math.round(x); }"),
"sin" => bind_math("Math.sin"), "sin" => bind_math("(x) { return Math.sin(x); }"),
"sinf" => bind_math("Math.sin"), "sinf" => bind_math("(x) { return Math.sin(x); }"),
"pow" => bind_math("Math.pow"), "pow" => bind_math("(x, y) { return Math.pow(x, y); }"),
"powf" => bind_math("Math.pow"), "powf" => bind_math("(x, y) { return Math.pow(x, y); }"),
"exp2" => bind_math("(a) => Math.pow(2, a)"), "exp2" => bind_math("(a) { return Math.pow(2, a); }"),
"exp2f" => bind_math("(a) => Math.pow(2, a)"), "exp2f" => bind_math("(a) { return Math.pow(2, a); }"),
"fmod" => bind_math("(a, b) => a % b"), "fmod" => bind_math("(a, b) { return a % b; }"),
"fmodf" => bind_math("(a, b) => a % b"), "fmodf" => bind_math("(a, b) { return a % b; }"),
"fma" => bind_math("(a, b, c) => (a * b) + c"), "fma" => bind_math("(a, b, c) { return (a * b) + c; }"),
"fmaf" => bind_math("(a, b, c) => (a * b) + c"), "fmaf" => bind_math("(a, b, c) { return (a * b) + c; }"),
_ => continue, _ => continue,
} }

10
package.json Normal file
View File

@ -0,0 +1,10 @@
{
"license": "MIT",
"devDependencies": {
"@types/node": "^9.4.6",
"ts-loader": "^4.0.1",
"typescript": "^2.7.2",
"webpack": "^4.0.1",
"webpack-cli": "^2.0.10"
}
}

View File

@ -53,7 +53,7 @@ fn import_class() {
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "./test")] #[wasm_bindgen(module = "./another")]
extern { extern {
type Foo; type Foo;
#[wasm_bindgen(static = Foo)] #[wasm_bindgen(static = Foo)]
@ -67,21 +67,23 @@ fn import_class() {
} }
"#) "#)
.file("test.ts", r#" .file("test.ts", r#"
import * as wasm from "./out"; import { bar } from "./out";
import { called } from "./another";
import * as assert from "assert"; import * as assert from "assert";
let called = false; export function test() {
bar();
assert.strictEqual(called, true);
}
"#)
.file("another.ts", r#"
export let called = false;
export class Foo { export class Foo {
static bar() { static bar() {
called = true; called = true;
} }
} }
export function test() {
wasm.bar();
assert.strictEqual(called, true);
}
"#) "#)
.test(); .test();
} }
@ -96,7 +98,7 @@ fn construct() {
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "./test")] #[wasm_bindgen(module = "./another")]
extern { extern {
type Foo; type Foo;
#[wasm_bindgen(static = Foo)] #[wasm_bindgen(static = Foo)]
@ -119,10 +121,19 @@ fn construct() {
} }
"#) "#)
.file("test.ts", r#" .file("test.ts", r#"
import * as wasm from "./out"; import { run } from "./out";
import { called } from "./another";
import * as assert from "assert"; import * as assert from "assert";
let called = false; export function test() {
run();
assert.strictEqual(called, true);
}
"#)
.file("another.ts", r#"
import * as assert from "assert";
export let called = false;
export class Foo { export class Foo {
private internal_string: string = ''; private internal_string: string = '';
@ -146,11 +157,6 @@ fn construct() {
called = true; called = true;
} }
} }
export function test() {
wasm.run();
assert.strictEqual(called, true);
}
"#) "#)
.test(); .test();
} }
@ -165,7 +171,7 @@ fn new_constructors() {
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "./test")] #[wasm_bindgen(module = "./another")]
extern { extern {
type Foo; type Foo;
#[wasm_bindgen(constructor)] #[wasm_bindgen(constructor)]
@ -184,6 +190,11 @@ fn new_constructors() {
.file("test.ts", r#" .file("test.ts", r#"
import { run } from "./out"; import { run } from "./out";
export function test() {
run();
}
"#)
.file("another.ts", r#"
export class Foo { export class Foo {
constructor(private field: number) { constructor(private field: number) {
} }
@ -192,10 +203,6 @@ fn new_constructors() {
return this.field + 1; return this.field + 1;
} }
} }
export function test() {
run();
}
"#) "#)
.test(); .test();
} }
@ -210,7 +217,7 @@ fn switch_methods() {
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "./test")] #[wasm_bindgen(module = "./another")]
extern { extern {
type Foo; type Foo;
@ -238,43 +245,45 @@ fn switch_methods() {
"#) "#)
.file("test.ts", r#" .file("test.ts", r#"
import { a, b } from "./out"; import { a, b } from "./out";
import { Foo, called } from "./another";
import * as assert from "assert"; import * as assert from "assert";
let called = false; export function test() {
assert.strictEqual(called.a, false);
a();
assert.strictEqual(called.a, true);
called.a = false;
Foo.a = function() {};
assert.strictEqual(called.a, false);
a();
assert.strictEqual(called.a, true);
called.a = false;
assert.strictEqual(called.a, false);
b();
assert.strictEqual(called.a, true);
called.a = false;
Foo.prototype.b = function() {};
assert.strictEqual(called.a, false);
b();
assert.strictEqual(called.a, true);
}
"#)
.file("another.ts", r#"
export let called = { a: false };
export class Foo { export class Foo {
constructor() { constructor() {
} }
static a() { static a() {
called = true; called.a = true;
} }
b() { b() {
called = true; called.a = true;
} }
} }
export function test() {
assert.strictEqual(called, false);
a();
assert.strictEqual(called, true);
called = false;
Foo.a = function() {};
assert.strictEqual(called, false);
a();
assert.strictEqual(called, true);
called = false;
assert.strictEqual(called, false);
b();
assert.strictEqual(called, true);
called = false;
Foo.prototype.b = function() {};
assert.strictEqual(called, false);
b();
assert.strictEqual(called, true);
}
"#) "#)
.test(); .test();
} }
@ -289,7 +298,7 @@ fn properties() {
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "./test")] #[wasm_bindgen(module = "./another")]
extern { extern {
type Foo; type Foo;
@ -315,6 +324,11 @@ fn properties() {
.file("test.ts", r#" .file("test.ts", r#"
import { run } from "./out"; import { run } from "./out";
export function test() {
run();
}
"#)
.file("another.ts", r#"
export class Foo { export class Foo {
constructor(private num: number) { constructor(private num: number) {
this.num = 1; this.num = 1;
@ -328,10 +342,6 @@ fn properties() {
this.num = val; this.num = val;
} }
} }
export function test() {
run();
}
"#) "#)
.test(); .test();
} }

4709
yarn.lock Normal file

File diff suppressed because it is too large Load Diff