Add codegen to make test work.

This commit is contained in:
Richard Dodd
2018-08-19 13:39:16 +01:00
parent d9fd2147a0
commit a4835304eb
3 changed files with 50 additions and 7 deletions

View File

@ -1614,7 +1614,6 @@ impl<'a> Context<'a> {
}
fn global(&mut self, s: &str) {
let s = s;
let s = s.trim();
// Ensure a blank line between adjacent items, and ensure everything is
@ -1941,6 +1940,7 @@ impl<'a, 'b> SubContext<'a, 'b> {
let js = Rust2Js::new(self.cx)
.catch(import.catch)
.variadic(import.variadic)
.process(descriptor.unwrap_function())?
.finish(&target);
self.cx.export(&import.shim, &js, None);

View File

@ -36,6 +36,9 @@ pub struct Rust2Js<'a, 'b: 'a> {
/// Whether or not we're catching JS exceptions
catch: bool,
/// Whether or not the last argument is a slice representing variadic arguments.
variadic: bool,
}
impl<'a, 'b> Rust2Js<'a, 'b> {
@ -50,6 +53,7 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
arg_idx: 0,
ret_expr: String::new(),
catch: false,
variadic: false,
}
}
@ -62,6 +66,15 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
self
}
pub fn variadic(&mut self, variadic: bool) -> &mut Self {
if variadic {
self.cx.expose_uint32_memory();
self.cx.expose_add_heap_object();
}
self.variadic = variadic;
self
}
/// Generates all bindings necessary for the signature in `Function`,
/// creating necessary argument conversions and return value processing.
pub fn process(&mut self, function: &Function) -> Result<&mut Self, Error> {
@ -72,6 +85,7 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
Ok(self)
}
/// Get a generated name for an argument.
fn shim_argument(&mut self) -> String {
let s = format!("arg{}", self.arg_idx);
self.arg_idx += 1;
@ -516,6 +530,7 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
}
pub fn finish(&self, invoc: &str) -> String {
use std::fmt::Write;
let mut ret = String::new();
ret.push_str("function(");
ret.push_str(&self.shim_arguments.join(", "));
@ -528,10 +543,31 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
ret.push_str(") {\n");
ret.push_str(&self.prelude);
let mut invoc = self.ret_expr.replace(
"JS",
&format!("{}({})", invoc, self.js_arguments.join(", ")),
);
let mut invoc = if self.variadic {
if self.js_arguments.is_empty() {
unreachable!("the last argument of a variadic must be a slice");
}
let last_arg = self.js_arguments.len() - 1; // check implies > 0
// The variadic part of the arguments could be passed as as a typed array in
// javascript, so we cannot just do `.concat(..)`, as this seems to convert the
// contents to strings (javascript is very strange).
write!(ret, "\
let args = [{}];\n\
{}.forEach(extra_arg => args.push(extra_arg));\n\
",
self.js_arguments[..last_arg].join(", "),
self.js_arguments[last_arg]
).unwrap();
self.ret_expr.replace(
"JS",
&format!("{}.apply(this, args)", invoc),
)
} else {
self.ret_expr.replace(
"JS",
&format!("{}({})", invoc, self.js_arguments.join(", ")),
)
};
if self.catch {
let catch = "\
const view = getUint32Memory();\n\