Skip to content

Commit 0d592ff

Browse files
committed
Add a raw_module attribute to #[wasm_bindgen]
This allows subverting the checks and resolution performed by the `module` attribute added as part of [RFC 6] and has been discussed in #1343. Closes #1343 [RFC 6]: rustwasm/rfcs#6
1 parent 9e74085 commit 0d592ff

File tree

8 files changed

+61
-21
lines changed

8 files changed

+61
-21
lines changed

crates/backend/src/ast.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ pub struct Import {
7979
pub enum ImportModule {
8080
None,
8181
Named(String, Span),
82+
RawNamed(String, Span),
8283
Inline(usize, Span),
8384
}
8485

@@ -96,6 +97,10 @@ impl Hash for ImportModule {
9697
2u8.hash(h);
9798
idx.hash(h);
9899
}
100+
ImportModule::RawNamed(name, _) => {
101+
3u8.hash(h);
102+
name.hash(h);
103+
}
99104
}
100105
}
101106
}

crates/backend/src/encode.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ fn shared_import<'a>(i: &'a ast::Import, intern: &'a Interner) -> Result<Import<
208208
ast::ImportModule::Named(m, span) => {
209209
ImportModule::Named(intern.resolve_import_module(m, *span)?)
210210
}
211+
ast::ImportModule::RawNamed(m, _span) => ImportModule::RawNamed(intern.intern_str(m)),
211212
ast::ImportModule::Inline(idx, _) => ImportModule::Inline(*idx as u32),
212213
ast::ImportModule::None => ImportModule::None,
213214
},

crates/cli-support/src/js/mod.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2836,6 +2836,7 @@ impl<'a, 'b> SubContext<'a, 'b> {
28362836
// not sure how to import them.
28372837
let is_local_snippet = match import.module {
28382838
decode::ImportModule::Named(s) => self.cx.local_modules.contains_key(s),
2839+
decode::ImportModule::RawNamed(_) => false,
28392840
decode::ImportModule::Inline(_) => true,
28402841
decode::ImportModule::None => false,
28412842
};
@@ -2921,11 +2922,13 @@ impl<'a, 'b> SubContext<'a, 'b> {
29212922
name,
29222923
field,
29232924
},
2924-
decode::ImportModule::Named(module) => Import::Module {
2925-
module,
2926-
name,
2927-
field,
2928-
},
2925+
decode::ImportModule::Named(module) | decode::ImportModule::RawNamed(module) => {
2926+
Import::Module {
2927+
module,
2928+
name,
2929+
field,
2930+
}
2931+
}
29292932
decode::ImportModule::Inline(idx) => {
29302933
let offset = *self
29312934
.cx

crates/macro-support/src/parser.rs

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ macro_rules! attrgen {
3333
(static_method_of, StaticMethodOf(Span, Ident)),
3434
(js_namespace, JsNamespace(Span, Ident)),
3535
(module, Module(Span, String, Span)),
36+
(raw_module, RawModule(Span, String, Span)),
3637
(inline_js, InlineJs(Span, String, Span)),
3738
(getter, Getter(Span, Option<Ident>)),
3839
(setter, Setter(Span, Option<Ident>)),
@@ -1085,24 +1086,28 @@ impl MacroParse<BindgenAttrs> for syn::ItemForeignMod {
10851086
));
10861087
}
10871088
}
1088-
let module = match opts.module() {
1089-
Some((name, span)) => {
1090-
if opts.inline_js().is_some() {
1091-
let msg = "cannot specify both `module` and `inline_js`";
1092-
errors.push(Diagnostic::span_error(span, msg));
1093-
}
1094-
ast::ImportModule::Named(name.to_string(), span)
1089+
let module = if let Some((name, span)) = opts.module() {
1090+
if opts.inline_js().is_some() {
1091+
let msg = "cannot specify both `module` and `inline_js`";
1092+
errors.push(Diagnostic::span_error(span, msg));
10951093
}
1096-
None => {
1097-
match opts.inline_js() {
1098-
Some((js, span)) => {
1099-
let i = program.inline_js.len();
1100-
program.inline_js.push(js.to_string());
1101-
ast::ImportModule::Inline(i, span)
1102-
}
1103-
None => ast::ImportModule::None
1104-
}
1094+
if opts.raw_module().is_some() {
1095+
let msg = "cannot specify both `module` and `raw_module`";
1096+
errors.push(Diagnostic::span_error(span, msg));
11051097
}
1098+
ast::ImportModule::Named(name.to_string(), span)
1099+
} else if let Some((name, span)) = opts.raw_module() {
1100+
if opts.inline_js().is_some() {
1101+
let msg = "cannot specify both `raw_module` and `inline_js`";
1102+
errors.push(Diagnostic::span_error(span, msg));
1103+
}
1104+
ast::ImportModule::RawNamed(name.to_string(), span)
1105+
} else if let Some((js, span)) = opts.inline_js() {
1106+
let i = program.inline_js.len();
1107+
program.inline_js.push(js.to_string());
1108+
ast::ImportModule::Inline(i, span)
1109+
} else {
1110+
ast::ImportModule::None
11061111
};
11071112
for item in self.items.into_iter() {
11081113
if let Err(e) = item.macro_parse(program, module.clone()) {

crates/shared/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ macro_rules! shared_api {
2828
enum ImportModule<'a> {
2929
None,
3030
Named(&'a str),
31+
RawNamed(&'a str),
3132
Inline(u32),
3233
}
3334

guide/src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
- [`js_namespace`](./reference/attributes/on-js-imports/js_namespace.md)
6767
- [`method`](./reference/attributes/on-js-imports/method.md)
6868
- [`module = "blah"`](./reference/attributes/on-js-imports/module.md)
69+
- [`raw_module = "blah"`](./reference/attributes/on-js-imports/raw_module.md)
6970
- [`static_method_of = Blah`](./reference/attributes/on-js-imports/static_method_of.md)
7071
- [`structural`](./reference/attributes/on-js-imports/structural.md)
7172
- [`variadic`](./reference/attributes/on-js-imports/variadic.md)

guide/src/reference/attributes/on-js-imports/module.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,8 @@ generates JavaScript import glue like:
3131
```js
3232
let illmatic = this.illmatic;
3333
```
34+
35+
Note that if the string specified with `module` starts with `./`, `../`, or `/`
36+
then it's interpreted as a path to a [local JS snippet](../../js-snippets.html).
37+
If this doesn't work for your use case you might be interested in the
38+
[`raw_module` attribute](raw_module.html)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# `raw_module = "blah"`
2+
3+
This attribute performs exactly the same purpose as the [`module`
4+
attribute](module.html) on JS imports, but it does not attempt to interpret
5+
paths starting with `./`, `../`, or `/` as JS snippets. For example:
6+
7+
```rust
8+
#[wasm_bindgen(raw_module = "./some/js/file.js")]
9+
extern "C" {
10+
fn the_function();
11+
}
12+
```
13+
14+
Note that if you use this attribute with a relative or absolute path, it's
15+
likely up to the final bundler or project to assign meaning to that path. This
16+
typically means that the JS file or module will be resolved relative to the
17+
final location of the wasm file itself. That means that `raw_module` is likely
18+
unsuitable for libraries on crates.io, but may be usable within end-user
19+
applications.

0 commit comments

Comments
 (0)