Add support for version specifications

This commit adds a `#[wasm_bindgen(version = "...")]` attribute support. This
information is eventually written into a `__wasm_pack_unstable` section.
Currently this is a strawman for the proposal in ashleygwilliams/wasm-pack#101
This commit is contained in:
Alex Crichton
2018-04-25 07:26:33 -07:00
parent d9a71b43db
commit 412bebca72
7 changed files with 183 additions and 0 deletions

View File

@ -5,6 +5,7 @@ use std::mem;
use failure::{Error, ResultExt};
use parity_wasm::elements::*;
use parity_wasm;
use serde_json;
use shared;
use wasm_gc;
@ -29,6 +30,7 @@ pub struct Context<'a> {
pub exported_classes: HashMap<String, ExportedClass>,
pub function_table_needed: bool,
pub run_descriptor: &'a Fn(&str) -> Vec<u32>,
pub module_versions: Vec<(String, String)>,
}
#[derive(Default)]
@ -341,6 +343,7 @@ impl<'a> Context<'a> {
self.export_table();
self.gc()?;
self.add_wasm_pack_section();
while js.contains("\n\n\n") {
js = js.replace("\n\n\n", "\n\n");
@ -1333,6 +1336,28 @@ impl<'a> Context<'a> {
self.globals.push_str(s);
self.globals.push_str("\n");
}
fn add_wasm_pack_section(&mut self) {
if self.module_versions.len() == 0 {
return
}
#[derive(Serialize)]
struct WasmPackSchema<'a> {
version: &'a str,
modules: &'a [(String, String)],
}
let contents = serde_json::to_string(&WasmPackSchema {
version: "0.0.1",
modules: &self.module_versions,
}).unwrap();
let mut section = CustomSection::default();
*section.name_mut() = "__wasm_pack_unstable".to_string();
*section.payload_mut() = contents.into_bytes();
self.module.sections_mut().push(Section::Custom(section));
}
}
impl<'a, 'b> SubContext<'a, 'b> {
@ -1423,6 +1448,7 @@ impl<'a, 'b> SubContext<'a, 'b> {
}
fn generate_import(&mut self, import: &shared::Import) -> Result<(), Error> {
self.validate_import_module(import)?;
match import.kind {
shared::ImportKind::Function(ref f) => {
self.generate_import_function(import, f)
@ -1443,6 +1469,40 @@ impl<'a, 'b> SubContext<'a, 'b> {
Ok(())
}
fn validate_import_module(&mut self, import: &shared::Import)
-> Result<(), Error>
{
let version = match import.version {
Some(ref s) => s,
None => return Ok(()),
};
let module = match import.module {
Some(ref s) => s,
None => return Ok(()),
};
if module.starts_with("./") {
return Ok(())
}
let pkg = if module.starts_with("@") {
// Translate `@foo/bar/baz` to `@foo/bar` and `@foo/bar` to itself
let first_slash = match module.find('/') {
Some(i) => i,
None => {
bail!("packages starting with `@` must be of the form \
`@foo/bar`, but found: `{}`", module)
}
};
match module[first_slash + 1..].find('/') {
Some(i) => &module[..i],
None => module,
}
} else {
module.split('/').next().unwrap()
};
self.cx.module_versions.push((pkg.to_string(), version.clone()));
Ok(())
}
fn generate_import_static(
&mut self,
info: &shared::Import,

View File

@ -1,5 +1,7 @@
extern crate parity_wasm;
extern crate wasm_bindgen_shared as shared;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate wasm_gc;
extern crate wasmi;
@ -131,6 +133,7 @@ impl Bindgen {
config: &self,
module: &mut module,
function_table_needed: false,
module_versions: Default::default(),
run_descriptor: &|name| {
let mut v = MyExternals(Vec::new());
let ret = instance