Don't put anything before ES module imports

Because of some incorrect use of `js.push_str(..)`, we could sometimes emit code
before the ES modules imports, which is syntactically invalid:

    const __exports = {};
    import { Thing } from '...'; // Syntax error!

This has been fixed by making sure that the correct `imports` or `imports_post`
string is built up. We now also assert that the `js` string is empty at the
location where we add imports if we're using ES modules.
This commit is contained in:
Nick Fitzgerald 2019-04-04 15:53:43 -07:00
parent 863a8b9cea
commit dff9b9b1e3
2 changed files with 20 additions and 2 deletions

View File

@ -354,7 +354,8 @@ impl<'a> Context<'a> {
| OutputMode::Node { | OutputMode::Node {
experimental_modules: true, experimental_modules: true,
} => { } => {
js.push_str(&format!("import * as wasm from './{}_bg';\n", module_name)); self.imports
.push_str(&format!("import * as wasm from './{}_bg';\n", module_name));
if needs_manual_start { if needs_manual_start {
self.footer.push_str("wasm.__wbindgen_start();\n"); self.footer.push_str("wasm.__wbindgen_start();\n");
} }
@ -365,7 +366,7 @@ impl<'a> Context<'a> {
// expose the same initialization function as `--target no-modules` // expose the same initialization function as `--target no-modules`
// as the default export of the module. // as the default export of the module.
OutputMode::Web => { OutputMode::Web => {
js.push_str("const __exports = {};\n"); self.imports_post.push_str("const __exports = {};\n");
self.imports_post.push_str("let wasm;\n"); self.imports_post.push_str("let wasm;\n");
init = self.gen_init(&module_name, needs_manual_start); init = self.gen_init(&module_name, needs_manual_start);
self.footer.push_str("export default init;\n"); self.footer.push_str("export default init;\n");
@ -377,6 +378,10 @@ impl<'a> Context<'a> {
ts.push_str(&init_ts); ts.push_str(&init_ts);
// Emit all the JS for importing all our functionality // Emit all the JS for importing all our functionality
assert!(
!self.config.mode.uses_es_modules() || js.is_empty(),
"ES modules require imports to be at the start of the file"
);
js.push_str(&self.imports); js.push_str(&self.imports);
js.push_str("\n"); js.push_str("\n");
js.push_str(&self.imports_post); js.push_str(&self.imports_post);

View File

@ -42,6 +42,19 @@ enum OutputMode {
Node { experimental_modules: bool }, Node { experimental_modules: bool },
} }
impl OutputMode {
fn uses_es_modules(&self) -> bool {
match self {
OutputMode::Bundler { .. }
| OutputMode::Web
| OutputMode::Node {
experimental_modules: true,
} => true,
_ => false,
}
}
}
enum Input { enum Input {
Path(PathBuf), Path(PathBuf),
Module(Module, String), Module(Module, String),