Skip to content

Commit

Permalink
Add a raw_module attribute to #[wasm_bindgen]
Browse files Browse the repository at this point in the history
This allows subverting the checks and resolution performed by the
`module` attribute added as part of [RFC 6] and has been discussed in rustwasm#1343.

Closes rustwasm#1343

[RFC 6]: rustwasm/rfcs#6
  • Loading branch information
alexcrichton committed Mar 15, 2019
1 parent 9e74085 commit 62850a4
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 16 deletions.
5 changes: 5 additions & 0 deletions crates/backend/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ pub struct Import {
pub enum ImportModule {
None,
Named(String, Span),
RawNamed(String, Span),
Inline(usize, Span),
}

Expand All @@ -96,6 +97,10 @@ impl Hash for ImportModule {
2u8.hash(h);
idx.hash(h);
}
ImportModule::RawNamed(name, _) => {
3u8.hash(h);
name.hash(h);
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions crates/backend/src/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ fn shared_import<'a>(i: &'a ast::Import, intern: &'a Interner) -> Result<Import<
ast::ImportModule::Named(m, span) => {
ImportModule::Named(intern.resolve_import_module(m, *span)?)
}
ast::ImportModule::RawNamed(m, _span) => {
ImportModule::Named(intern.intern_str(m))
}
ast::ImportModule::Inline(idx, _) => ImportModule::Inline(*idx as u32),
ast::ImportModule::None => ImportModule::None,
},
Expand Down
37 changes: 21 additions & 16 deletions crates/macro-support/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ macro_rules! attrgen {
(static_method_of, StaticMethodOf(Span, Ident)),
(js_namespace, JsNamespace(Span, Ident)),
(module, Module(Span, String, Span)),
(raw_module, RawModule(Span, String, Span)),
(inline_js, InlineJs(Span, String, Span)),
(getter, Getter(Span, Option<Ident>)),
(setter, Setter(Span, Option<Ident>)),
Expand Down Expand Up @@ -1085,24 +1086,28 @@ impl MacroParse<BindgenAttrs> for syn::ItemForeignMod {
));
}
}
let module = match opts.module() {
Some((name, span)) => {
if opts.inline_js().is_some() {
let msg = "cannot specify both `module` and `inline_js`";
errors.push(Diagnostic::span_error(span, msg));
}
ast::ImportModule::Named(name.to_string(), span)
let module = if let Some((name, span)) = opts.module() {
if opts.inline_js().is_some() {
let msg = "cannot specify both `module` and `inline_js`";
errors.push(Diagnostic::span_error(span, msg));
}
None => {
match opts.inline_js() {
Some((js, span)) => {
let i = program.inline_js.len();
program.inline_js.push(js.to_string());
ast::ImportModule::Inline(i, span)
}
None => ast::ImportModule::None
}
if opts.raw_module().is_some() {
let msg = "cannot specify both `module` and `raw_module`";
errors.push(Diagnostic::span_error(span, msg));
}
ast::ImportModule::Named(name.to_string(), span)
} else if let Some((name, span)) = opts.raw_module() {
if opts.inline_js().is_some() {
let msg = "cannot specify both `raw_module` and `inline_js`";
errors.push(Diagnostic::span_error(span, msg));
}
ast::ImportModule::RawNamed(name.to_string(), span)
} else if let Some((js, span)) = opts.inline_js() {
let i = program.inline_js.len();
program.inline_js.push(js.to_string());
ast::ImportModule::Inline(i, span)
} else {
ast::ImportModule::None
};
for item in self.items.into_iter() {
if let Err(e) = item.macro_parse(program, module.clone()) {
Expand Down
1 change: 1 addition & 0 deletions guide/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
- [`js_namespace`](./reference/attributes/on-js-imports/js_namespace.md)
- [`method`](./reference/attributes/on-js-imports/method.md)
- [`module = "blah"`](./reference/attributes/on-js-imports/module.md)
- [`raw_module = "blah"`](./reference/attributes/on-js-imports/raw_module.md)
- [`static_method_of = Blah`](./reference/attributes/on-js-imports/static_method_of.md)
- [`structural`](./reference/attributes/on-js-imports/structural.md)
- [`variadic`](./reference/attributes/on-js-imports/variadic.md)
Expand Down
5 changes: 5 additions & 0 deletions guide/src/reference/attributes/on-js-imports/module.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,8 @@ generates JavaScript import glue like:
```js
let illmatic = this.illmatic;
```

Note that if the string specified with `module` starts with `./`, `../`, or `/`
then it's interpreted as a path to a [local JS snippet](../../js-snippets.html).
If this doesn't work for your use case you might be interested in the
[`raw_module` attribute](raw_module.html)
19 changes: 19 additions & 0 deletions guide/src/reference/attributes/on-js-imports/raw_module.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# `raw_module = "blah"`

This attribute performs exactly the same purpose as the [`module`
attribute](module.html) on JS imports, but it does not attempt to interpret
paths starting with `./`, `../`, or `/` as JS snippets. For example:

```rust
#[wasm_bindgen(raw_module = "./some/js/file.js")]
extern "C" {
fn the_function();
}
```

Note that if you use this attribute with a relative or absolute path, it's
likely up to the final bundler or project to assign meaning to that path. This
typically means that the JS file or module will be resolved relative to the
final location of the wasm file itself. That means that `raw_module` is likely
unsuitable for libraries on crates.io, but may be usable within end-user
applications.

0 comments on commit 62850a4

Please sign in to comment.