Dramatically improving the build time of web-sys (#2012)

* Pre-generating web-sys

* Fixing build errors

* Minor refactor for the unit tests

* Changing to generate #[wasm_bindgen} annotations

* Fixing code generation

* Adding in main bin to wasm-bindgen-webidl

* Fixing more problems

* Adding in support for unstable APIs

* Fixing bug with code generation

* More code generation fixes

* Improving the webidl program

* Removing unnecessary cfg from the generated code

* Splitting doc comments onto separate lines

* Improving the generation for unstable features

* Adding in support for string values in enums

* Now runs rustfmt on the mod.rs file

* Fixing codegen for constructors

* Fixing webidl-tests

* Fixing build errors

* Another fix for build errors

* Renaming typescript_name to typescript_type

* Adding in docs for typescript_type

* Adding in CI script to verify that web-sys is up to date

* Fixing CI script

* Fixing CI script

* Don't suppress git diff output

* Remove duplicate definitions of `Location`

Looks to be a preexisting bug in wasm-bindgen?

* Regenerate webidl

* Try to get the git diff command right

* Handle named constructors in WebIDL

* Remove stray rustfmt.toml

* Add back NamedConstructorBar definition in tests

* Run stable rustfmt over everything

* Don't run Cargo in a build script

Instead refactor things so webidl-tests can use the Rust-code-generation
as a library in a build script. Also fixes `cargo fmt` in the
repository.

* Fixup generated code

* Running web-sys checks on stable

* Improving the code generation a little

* Running rustfmt

Co-authored-by: Alex Crichton <alex@alexcrichton.com>
This commit is contained in:
Pauan
2020-03-03 00:39:36 +01:00
committed by GitHub
parent eb04cf2dda
commit 3f4acc453b
1344 changed files with 142082 additions and 2883 deletions

View File

@ -4,7 +4,7 @@ use crate::wit::{Adapter, AdapterId, AdapterJsImportKind, AuxValue};
use crate::wit::{AdapterKind, Instruction, InstructionData};
use crate::wit::{AuxEnum, AuxExport, AuxExportKind, AuxImport, AuxStruct};
use crate::wit::{JsImport, JsImportName, NonstandardWitSection, WasmBindgenAux};
use crate::{Bindgen, EncodeInto, OutputMode};
use crate::{reset_indentation, Bindgen, EncodeInto, OutputMode, PLACEHOLDER_MODULE};
use anyhow::{anyhow, bail, Context as _, Error};
use std::borrow::Cow;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
@ -188,6 +188,85 @@ impl<'a> Context<'a> {
self.finalize_js(module_name, needs_manual_start)
}
fn generate_node_imports(&self) -> String {
let mut imports = BTreeSet::new();
for import in self.module.imports.iter() {
imports.insert(&import.module);
}
let mut shim = String::new();
shim.push_str("let imports = {};\n");
if self.config.mode.nodejs_experimental_modules() {
for (i, module) in imports.iter().enumerate() {
if module.as_str() != PLACEHOLDER_MODULE {
shim.push_str(&format!("import * as import{} from '{}';\n", i, module));
}
}
}
for (i, module) in imports.iter().enumerate() {
if module.as_str() == PLACEHOLDER_MODULE {
shim.push_str(&format!(
"imports['{0}'] = module.exports;\n",
PLACEHOLDER_MODULE
));
} else {
if self.config.mode.nodejs_experimental_modules() {
shim.push_str(&format!("imports['{}'] = import{};\n", module, i));
} else {
shim.push_str(&format!("imports['{0}'] = require('{0}');\n", module));
}
}
}
reset_indentation(&shim)
}
fn generate_node_wasm_loading(&self, path: &Path) -> String {
let mut shim = String::new();
if self.config.mode.nodejs_experimental_modules() {
// On windows skip the leading `/` which comes out when we parse a
// url to use `C:\...` instead of `\C:\...`
shim.push_str(&format!(
"
import * as path from 'path';
import * as fs from 'fs';
import * as url from 'url';
import * as process from 'process';
let file = path.dirname(url.parse(import.meta.url).pathname);
if (process.platform === 'win32') {{
file = file.substring(1);
}}
const bytes = fs.readFileSync(path.join(file, '{}'));
",
path.file_name().unwrap().to_str().unwrap()
));
} else {
shim.push_str(&format!(
"
const path = require('path').join(__dirname, '{}');
const bytes = require('fs').readFileSync(path);
",
path.file_name().unwrap().to_str().unwrap()
));
}
shim.push_str(
"
const wasmModule = new WebAssembly.Module(bytes);
const wasmInstance = new WebAssembly.Instance(wasmModule, imports);
wasm = wasmInstance.exports;
module.exports.__wasm = wasm;
",
);
reset_indentation(&shim)
}
/// Performs the task of actually generating the final JS module, be it
/// `--target no-modules`, `--target web`, or for bundlers. This is the very
/// last step performed in `finalize`.
@ -224,11 +303,12 @@ impl<'a> Context<'a> {
OutputMode::Node {
experimental_modules: false,
} => {
js.push_str(&self.generate_node_imports());
js.push_str("let wasm;\n");
for (id, js) in crate::sorted_iter(&self.wasm_import_definitions) {
let import = self.module.imports.get_mut(*id);
import.module = format!("./{}.js", module_name);
footer.push_str("\nmodule.exports.");
footer.push_str(&import.name);
footer.push_str(" = ");
@ -236,7 +316,13 @@ impl<'a> Context<'a> {
footer.push_str(";\n");
}
footer.push_str(&format!("wasm = require('./{}_bg');\n", module_name));
footer.push_str(
&self.generate_node_wasm_loading(&Path::new(&format!(
"./{}_bg.wasm",
module_name
))),
);
if needs_manual_start {
footer.push_str("wasm.__wbindgen_start();\n");
}

View File

@ -1,7 +1,7 @@
#![doc(html_root_url = "https://docs.rs/wasm-bindgen-cli-support/0.2")]
use anyhow::{bail, Context, Error};
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::collections::{BTreeMap, HashMap, HashSet};
use std::env;
use std::fs;
use std::mem;
@ -9,6 +9,8 @@ use std::path::{Path, PathBuf};
use std::str;
use walrus::Module;
pub(crate) const PLACEHOLDER_MODULE: &str = "__wbindgen_placeholder__";
mod anyref;
mod decode;
mod descriptor;
@ -667,13 +669,6 @@ impl Output {
.with_context(|| format!("failed to write `{}`", ts_path.display()))?;
}
if gen.mode.nodejs() {
let js_path = wasm_path.with_extension(extension);
let shim = gen.generate_node_wasm_import(&self.module, &wasm_path);
fs::write(&js_path, shim)
.with_context(|| format!("failed to write `{}`", js_path.display()))?;
}
if gen.typescript {
let ts_path = wasm_path.with_extension("d.ts");
let ts = wasm2es6js::typescript(&self.module)?;
@ -685,77 +680,6 @@ impl Output {
}
}
impl JsGenerated {
fn generate_node_wasm_import(&self, m: &Module, path: &Path) -> String {
let mut imports = BTreeSet::new();
for import in m.imports.iter() {
imports.insert(&import.module);
}
let mut shim = String::new();
if self.mode.nodejs_experimental_modules() {
for (i, module) in imports.iter().enumerate() {
shim.push_str(&format!("import * as import{} from '{}';\n", i, module));
}
// On windows skip the leading `/` which comes out when we parse a
// url to use `C:\...` instead of `\C:\...`
shim.push_str(&format!(
"
import * as path from 'path';
import * as fs from 'fs';
import * as url from 'url';
import * as process from 'process';
let file = path.dirname(url.parse(import.meta.url).pathname);
if (process.platform === 'win32') {{
file = file.substring(1);
}}
const bytes = fs.readFileSync(path.join(file, '{}'));
",
path.file_name().unwrap().to_str().unwrap()
));
} else {
shim.push_str(&format!(
"
const path = require('path').join(__dirname, '{}');
const bytes = require('fs').readFileSync(path);
",
path.file_name().unwrap().to_str().unwrap()
));
}
shim.push_str("let imports = {};\n");
for (i, module) in imports.iter().enumerate() {
if self.mode.nodejs_experimental_modules() {
shim.push_str(&format!("imports['{}'] = import{};\n", module, i));
} else {
shim.push_str(&format!("imports['{0}'] = require('{0}');\n", module));
}
}
shim.push_str(&format!(
"
const wasmModule = new WebAssembly.Module(bytes);
const wasmInstance = new WebAssembly.Instance(wasmModule, imports);
",
));
if self.mode.nodejs_experimental_modules() {
for entry in m.exports.iter() {
shim.push_str("export const ");
shim.push_str(&entry.name);
shim.push_str(" = wasmInstance.exports.");
shim.push_str(&entry.name);
shim.push_str(";\n");
}
} else {
shim.push_str("module.exports = wasmInstance.exports;\n");
}
reset_indentation(&shim)
}
}
fn gc_module_and_adapters(module: &mut Module) {
loop {
// Fist up, cleanup the native wasm module. Note that roots can come

View File

@ -1,7 +1,7 @@
use crate::decode;
use crate::descriptor::{Descriptor, Function};
use crate::descriptors::WasmBindgenDescriptorsSection;
use crate::intrinsic::Intrinsic;
use crate::{decode, PLACEHOLDER_MODULE};
use anyhow::{anyhow, bail, Error};
use std::collections::{HashMap, HashSet};
use std::str;
@ -9,8 +9,6 @@ use walrus::MemoryId;
use walrus::{ExportId, FunctionId, ImportId, Module};
use wasm_bindgen_shared::struct_function_export_name;
const PLACEHOLDER_MODULE: &str = "__wbindgen_placeholder__";
mod incoming;
mod nonstandard;
mod outgoing;