mirror of
https://github.com/rustwasm/wasm-bindgen.git
synced 2024-11-24 14:42:35 +03:00
Generate node.js require
directives for --nodejs
This commit is contained in:
parent
67737a2661
commit
a0bfb8103b
@ -15,7 +15,7 @@ pub struct Project {
|
||||
files: Vec<(String, String)>,
|
||||
debug: bool,
|
||||
js: bool,
|
||||
detect_node: bool,
|
||||
node: bool,
|
||||
}
|
||||
|
||||
pub fn project() -> Project {
|
||||
@ -29,7 +29,7 @@ pub fn project() -> Project {
|
||||
Project {
|
||||
debug: true,
|
||||
js: false,
|
||||
detect_node: false,
|
||||
node: false,
|
||||
files: vec![
|
||||
("Cargo.toml".to_string(), format!(r#"
|
||||
[package]
|
||||
@ -134,8 +134,8 @@ impl Project {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn detect_node(&mut self, detect_node: bool) -> &mut Project {
|
||||
self.detect_node = detect_node;
|
||||
pub fn node(&mut self, node: bool) -> &mut Project {
|
||||
self.node = node;
|
||||
self
|
||||
}
|
||||
|
||||
@ -194,6 +194,7 @@ impl Project {
|
||||
cli::Bindgen::new()
|
||||
.input_path(&as_a_module)
|
||||
.typescript(true)
|
||||
.nodejs(self.node)
|
||||
.debug(self.debug)
|
||||
.generate(&root)
|
||||
.expect("failed to run bindgen");
|
||||
@ -216,21 +217,28 @@ impl Project {
|
||||
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
|
||||
if self.node {
|
||||
let mut cmd = Command::new("node");
|
||||
cmd.arg(root.join("out.js"))
|
||||
.current_dir(&root);
|
||||
run(&mut cmd, "node");
|
||||
} else {
|
||||
Command::new("yarn")
|
||||
};
|
||||
cmd.arg("webpack").current_dir(&root);
|
||||
run(&mut cmd, "node");
|
||||
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");
|
||||
|
||||
let mut cmd = Command::new("node");
|
||||
cmd.arg(root.join("bundle.js"))
|
||||
.current_dir(&root);
|
||||
run(&mut cmd, "node");
|
||||
let mut cmd = Command::new("node");
|
||||
cmd.arg(root.join("bundle.js"))
|
||||
.current_dir(&root);
|
||||
run(&mut cmd, "node");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ use super::Bindgen;
|
||||
pub struct Context<'a> {
|
||||
pub globals: String,
|
||||
pub imports: String,
|
||||
pub footer: String,
|
||||
pub typescript: String,
|
||||
pub exposed_globals: HashSet<&'static str>,
|
||||
pub required_internal_exports: HashSet<&'static str>,
|
||||
@ -52,10 +53,14 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
let contents = f(self);
|
||||
let contents = contents.trim();
|
||||
let global = if contents.starts_with("function") {
|
||||
format!("export function {} {}\n", name, &contents[8..])
|
||||
let global = if self.config.nodejs {
|
||||
format!("module.exports.{} = {};\n", name, contents)
|
||||
} else {
|
||||
format!("export const {} = {};\n", name, contents)
|
||||
if contents.starts_with("function") {
|
||||
format!("export function {} {}\n", name, &contents[8..])
|
||||
} else {
|
||||
format!("export const {} = {};\n", name, contents)
|
||||
}
|
||||
};
|
||||
self.globals.push_str(&global);
|
||||
};
|
||||
@ -212,16 +217,26 @@ impl<'a> Context<'a> {
|
||||
|
||||
self.rewrite_imports(module_name);
|
||||
|
||||
let import_wasm = if self.config.nodejs {
|
||||
self.footer.push_str(&format!("wasm = require('./{}_bg');",
|
||||
module_name));
|
||||
format!("var wasm;")
|
||||
} else {
|
||||
format!("import * as wasm from './{}_bg';", module_name)
|
||||
};
|
||||
|
||||
let js = format!("
|
||||
/* tslint:disable */
|
||||
import * as wasm from './{module_name}_bg'; // imports from wasm file
|
||||
{import_wasm}
|
||||
{imports}
|
||||
|
||||
{globals}
|
||||
{footer}
|
||||
",
|
||||
module_name = module_name,
|
||||
import_wasm = import_wasm,
|
||||
globals = self.globals,
|
||||
imports = self.imports,
|
||||
footer = self.footer,
|
||||
);
|
||||
|
||||
self.unexport_unused_internal_exports();
|
||||
@ -1019,8 +1034,17 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
||||
&export.function.name,
|
||||
false,
|
||||
&export.function);
|
||||
self.cx.globals.push_str("export ");
|
||||
if self.cx.config.nodejs {
|
||||
self.cx.globals.push_str("module.exports.");
|
||||
self.cx.globals.push_str(&export.function.name);
|
||||
self.cx.globals.push_str(" = ");
|
||||
} else {
|
||||
self.cx.globals.push_str("export ");
|
||||
}
|
||||
self.cx.globals.push_str(&js);
|
||||
if self.cx.config.nodejs {
|
||||
self.cx.globals.push_str(";");
|
||||
}
|
||||
self.cx.globals.push_str("\n");
|
||||
self.cx.typescript.push_str("export ");
|
||||
self.cx.typescript.push_str(&ts);
|
||||
@ -1517,9 +1541,17 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
||||
dst.push_str(&extra);
|
||||
dst.push_str(&format!("{}\n}}", invoc));
|
||||
|
||||
self.cx.globals.push_str("export ");
|
||||
self.cx.globals.push_str(&dst);
|
||||
self.cx.globals.push_str("\n");
|
||||
if self.cx.config.nodejs {
|
||||
self.cx.globals.push_str("module.exports.");
|
||||
self.cx.globals.push_str(&import.shim);
|
||||
self.cx.globals.push_str(" = ");
|
||||
self.cx.globals.push_str(&dst);
|
||||
self.cx.globals.push_str(";\n");
|
||||
} else {
|
||||
self.cx.globals.push_str("export ");
|
||||
self.cx.globals.push_str(&dst);
|
||||
self.cx.globals.push_str("\n");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_enum(&mut self, enum_: &shared::Enum) {
|
||||
@ -1546,9 +1578,15 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
||||
let name = import.js_namespace.as_ref().map(|s| &**s).unwrap_or(item);
|
||||
|
||||
if self.cx.imported_names.insert(name.to_string()) {
|
||||
self.cx.imports.push_str(&format!("
|
||||
import {{ {} }} from '{}';
|
||||
", name, module));
|
||||
if self.cx.config.nodejs {
|
||||
self.cx.imports.push_str(&format!("
|
||||
const {} = require('{}').{};
|
||||
", name, module, name));
|
||||
} else {
|
||||
self.cx.imports.push_str(&format!("
|
||||
import {{ {} }} from '{}';
|
||||
", name, module));
|
||||
}
|
||||
}
|
||||
}
|
||||
match import.js_namespace {
|
||||
|
@ -4,6 +4,7 @@ extern crate serde_json;
|
||||
extern crate wasm_gc;
|
||||
|
||||
use std::char;
|
||||
use std::collections::BTreeSet;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
@ -86,6 +87,7 @@ impl Bindgen {
|
||||
let mut cx = js::Context {
|
||||
globals: String::new(),
|
||||
imports: String::new(),
|
||||
footer: String::new(),
|
||||
typescript: format!("/* tslint:disable */\n"),
|
||||
exposed_globals: Default::default(),
|
||||
required_internal_exports: Default::default(),
|
||||
@ -118,6 +120,13 @@ impl Bindgen {
|
||||
}
|
||||
|
||||
let wasm_path = out_dir.join(format!("{}_bg", stem)).with_extension("wasm");
|
||||
|
||||
if self.nodejs {
|
||||
let js_path = wasm_path.with_extension("js");
|
||||
let shim = self.generate_node_wasm_import(&module, &wasm_path);
|
||||
File::create(&js_path)?.write_all(shim.as_bytes())?;
|
||||
}
|
||||
|
||||
let wasm_bytes = parity_wasm::serialize(module).map_err(|e| {
|
||||
Error(format!("{:?}", e))
|
||||
})?;
|
||||
@ -127,6 +136,30 @@ impl Bindgen {
|
||||
File::create(&wasm_path)?.write_all(&bytes)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_node_wasm_import(&self, m: &Module, path: &Path) -> String {
|
||||
let mut imports = BTreeSet::new();
|
||||
if let Some(i) = m.import_section() {
|
||||
for i in i.entries() {
|
||||
imports.insert(i.module());
|
||||
}
|
||||
}
|
||||
|
||||
let mut shim = String::new();
|
||||
shim.push_str("let imports = {};\n");
|
||||
for module in imports {
|
||||
shim.push_str(&format!("imports['{0}'] = require('{0}');\n", module));
|
||||
}
|
||||
|
||||
shim.push_str(&format!("
|
||||
const bytes = require('fs').readFileSync('{}');
|
||||
const wasmModule = new WebAssembly.Module(bytes);
|
||||
const wasmInstance = new WebAssembly.Instance(wasmModule, imports);
|
||||
module.exports = wasmInstance.exports;
|
||||
", path.file_name().unwrap().to_str().unwrap()));
|
||||
|
||||
shim
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_programs(module: &mut Module) -> Vec<shared::Program> {
|
||||
|
@ -3,7 +3,6 @@ extern crate test_support;
|
||||
#[test]
|
||||
fn works() {
|
||||
test_support::project()
|
||||
.detect_node(true)
|
||||
.file("src/lib.rs", r#"
|
||||
#![feature(proc_macro, wasm_custom_section)]
|
||||
|
||||
|
40
tests/node.rs
Normal file
40
tests/node.rs
Normal file
@ -0,0 +1,40 @@
|
||||
extern crate test_support;
|
||||
|
||||
#[test]
|
||||
fn works() {
|
||||
test_support::project()
|
||||
.node(true)
|
||||
.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 hit();
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn run() {
|
||||
hit();
|
||||
}
|
||||
"#)
|
||||
.file("test.js", r#"
|
||||
const assert = require('assert');
|
||||
const run = require('./out');
|
||||
|
||||
var called = false;
|
||||
|
||||
module.exports.hit = function() {
|
||||
called = true;
|
||||
};
|
||||
|
||||
module.exports.test = function() {
|
||||
run();
|
||||
assert.strictEqual(called, true);
|
||||
};
|
||||
"#)
|
||||
.test();
|
||||
}
|
@ -3,7 +3,6 @@ extern crate test_support;
|
||||
#[test]
|
||||
fn works() {
|
||||
test_support::project()
|
||||
.detect_node(true)
|
||||
.file("src/lib.rs", r#"
|
||||
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user