Skip to content

Commit

Permalink
Merge pull request #7254 from xtuc/feat-remove-extra-wasm-decodings
Browse files Browse the repository at this point in the history
Remove extra wasm decoding
  • Loading branch information
sokra committed May 11, 2018
2 parents 0eeea0f + e2c8f3d commit 8d2f421
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 131 deletions.
15 changes: 12 additions & 3 deletions declarations.d.ts
Expand Up @@ -33,19 +33,28 @@ declare module "chrome-trace-event" {
declare module "@webassemblyjs/ast" {
export function traverse(
ast: any,
visitor: { [name: string]: (context: { node: Node }) => void }
visitor: {
ModuleImport?: (p: NodePath<ModuleImport>) => void;
ModuleExport?: (p: NodePath<ModuleExport>) => void;
Start?: (p: NodePath<Start>) => void;
}
);
export class Node {
index: number;
export class NodePath<T> {
node: T;
}
export class Node {}
export class Identifier extends Node {
value: string;
}
export class Start extends Node {
index: Identifier;
}
export class ModuleImport extends Node {
module: string;
descr: {
type: string;
valtype: string;
id: string;
};
name: string;
}
Expand Down
39 changes: 23 additions & 16 deletions lib/wasm/WebAssemblyGenerator.js
Expand Up @@ -7,7 +7,7 @@
const Generator = require("../Generator");
const { RawSource } = require("webpack-sources");

const { edit, add } = require("@webassemblyjs/wasm-edit");
const { editWithAST, addWithAST } = require("@webassemblyjs/wasm-edit");
const { decode } = require("@webassemblyjs/wasm-parser");
const t = require("@webassemblyjs/ast");

Expand All @@ -18,9 +18,19 @@ function compose(...fns) {
}

// Utility functions
const isGlobalImport = moduleImport => moduleImport.descr.type === "GlobalType";
const isFuncImport = moduleImport =>
moduleImport.descr.type === "FuncImportDescr";

/**
* @param {t.ModuleImport} n the import
* @returns {boolean} true, if a global was imported
*/
const isGlobalImport = n => n.descr.type === "GlobalType";

/**
* @param {t.ModuleImport} n the import
* @returns {boolean} true, if a func was imported
*/
const isFuncImport = n => n.descr.type === "FuncImportDescr";

const initFuncId = t.identifier("__webpack_init__");

// TODO replace with @callback
Expand All @@ -35,7 +45,7 @@ const initFuncId = t.identifier("__webpack_init__");
* @returns {ArrayBufferTransform} transform
*/
const removeStartFunc = state => bin => {
return edit(bin, {
return editWithAST(state.ast, bin, {
Start(path) {
path.remove();
}
Expand Down Expand Up @@ -149,7 +159,7 @@ function getNextFuncIndex(ast, countImportedFunc) {
const rewriteImportedGlobals = state => bin => {
const newGlobals = [];

bin = edit(bin, {
bin = editWithAST(state.ast, bin, {
ModuleImport(path) {
if (isGlobalImport(path.node) === true) {
const globalType = path.node.descr;
Expand All @@ -168,7 +178,7 @@ const rewriteImportedGlobals = state => bin => {
});

// Add global declaration instructions
return add(bin, newGlobals);
return addWithAST(state.ast, bin, newGlobals);
};

/**
Expand All @@ -177,17 +187,17 @@ const rewriteImportedGlobals = state => bin => {
* The init function fills the globals given input arguments.
*
* @param {Object} state transformation state
* @param {Object} state.ast - Module's ast
* @param {t.IndexLiteral} state.startAtFuncIndex index of the start function
* @param {t.ModuleImport[]} state.importedGlobals list of imported globals
* @param {TODO} state.funcSectionMetadata ??
* @param {t.IndexLiteral} state.nextFuncIndex index of the next function
* @param {t.IndexLiteral} state.nextTypeIndex index of the next type
* @returns {ArrayBufferTransform} transform
*/
const addInitFunction = ({
ast,
startAtFuncIndex,
importedGlobals,
funcSectionMetadata,
nextFuncIndex,
nextTypeIndex
}) => bin => {
Expand Down Expand Up @@ -229,35 +239,32 @@ const addInitFunction = ({
// Export section
const moduleExport = t.moduleExport(initFuncId.value, "Func", nextFuncIndex);

return add(bin, [func, moduleExport, funcindex, functype]);
return addWithAST(ast, bin, [func, moduleExport, funcindex, functype]);
};

class WebAssemblyGenerator extends Generator {
generate(module) {
const bin = module.originalSource().source();

// FIXME(sven): this module is parsed twice, we could preserve the AST
// from wasm/WebAssemblyParser.js
const ast = decode(bin, {
ignoreDataSection: true,
ignoreCodeSection: true
});

const importedGlobals = getImportedGlobals(ast);
const funcSectionMetadata = t.getSectionMetadata(ast, "func");
const countImportedFunc = getCountImportedFunc(ast);
const startAtFuncIndex = getStartFuncIndex(ast);
const nextFuncIndex = getNextFuncIndex(ast, countImportedFunc);
const nextTypeIndex = getNextTypeIndex(ast);

const transform = compose(
removeStartFunc({}),
removeStartFunc({ ast }),

rewriteImportedGlobals({}),
rewriteImportedGlobals({ ast }),

addInitFunction({
ast,
importedGlobals,
funcSectionMetadata,
startAtFuncIndex,
nextFuncIndex,
nextTypeIndex
Expand Down
25 changes: 12 additions & 13 deletions lib/wasm/WebAssemblyParser.js
Expand Up @@ -10,17 +10,19 @@ const { decode } = require("@webassemblyjs/wasm-parser");
const { Tapable } = require("tapable");
const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency");

/** @typedef {import("../Module")} Module */

/**
* @param {t.ModuleImport} moduleImport the import
* @param {t.ModuleImport} n the import
* @returns {boolean} true, if a memory was imported
*/
const isMemoryImport = moduleImport => moduleImport.descr.type === "Memory";
const isMemoryImport = n => n.descr.type === "Memory";

/**
* @param {t.ModuleImport} moduleImport the import
* @param {t.ModuleImport} n the import
* @returns {boolean} true, if a table was imported
*/
const isTableImport = moduleImport => moduleImport.descr.type === "Table";
const isTableImport = n => n.descr.type === "Table";

const decoderOpts = {
ignoreCodeSection: true,
Expand All @@ -45,27 +47,24 @@ class WebAssemblyParser extends Tapable {
const exports = (state.module.buildMeta.providedExports = []);
t.traverse(ast, {
ModuleExport({ node }) {
const moduleExport = /** @type {t.ModuleExport} */ (node);
exports.push(moduleExport.name);
exports.push(node.name);
},

ModuleImport({ node }) {
const moduleImport = /** @type {t.ModuleImport} */ (node);

let onlyDirectImport = false;

if (isMemoryImport(moduleImport) === true) {
if (isMemoryImport(node) === true) {
onlyDirectImport = true;
}

if (isTableImport(moduleImport) === true) {
if (isTableImport(node) === true) {
onlyDirectImport = true;
}

const dep = new WebAssemblyImportDependency(
moduleImport.module,
moduleImport.name,
moduleImport.descr,
node.module,
node.name,
node.descr,
onlyDirectImport
);

Expand Down
6 changes: 3 additions & 3 deletions package.json
Expand Up @@ -5,9 +5,9 @@
"description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.",
"license": "MIT",
"dependencies": {
"@webassemblyjs/ast": "1.3.2",
"@webassemblyjs/wasm-edit": "1.3.2",
"@webassemblyjs/wasm-parser": "1.3.2",
"@webassemblyjs/ast": "1.4.2",
"@webassemblyjs/wasm-edit": "1.4.2",
"@webassemblyjs/wasm-parser": "1.4.2",
"acorn": "^5.0.0",
"acorn-dynamic-import": "^3.0.0",
"ajv": "^6.1.0",
Expand Down

0 comments on commit 8d2f421

Please sign in to comment.