Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
experimental.transpileToJS option implemented
  • Loading branch information
BaderBC committed Jul 7, 2024
commit b2aa2457aa24262137649ec7b6ed8248186f956d
97 changes: 49 additions & 48 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,48 +1,49 @@
{
"name": "@wasm-tool/rollup-plugin-rust",
"author": "Pauan <[email protected]>",
"description": "Rollup plugin for bundling and importing Rust crates.",
"version": "2.4.5",
"license": "MIT",
"repository": "github:wasm-tool/rollup-plugin-rust",
"homepage": "https://github.com/wasm-tool/rollup-plugin-rust#readme",
"bugs": "https://github.com/wasm-tool/rollup-plugin-rust/issues",
"main": "src/index.js",
"scripts": {
"test:foo": "cd tests/src/foo && yarn install",
"test": "yarn test:foo && cd tests && rimraf dist/js && rollup --bundleConfigAsCjs --config",
"test:watch": "yarn test:foo && cd tests && rimraf dist/js && rollup --bundleConfigAsCjs --config --watch",
"test:serve": "live-server tests/dist"
},
"directories": {
"example": "example"
},
"keywords": [
"rollup-plugin",
"vite-plugin",
"rust-wasm",
"wasm",
"rust",
"rollup",
"plugin",
"webassembly",
"wasm-bindgen",
"wasm-pack"
],
"dependencies": {
"@iarna/toml": "^2.2.5",
"@rollup/pluginutils": "^5.0.2",
"binaryen": "^111.0.0",
"chalk": "^4.0.0",
"glob": "^10.2.2",
"node-fetch": "^2.0.0",
"rimraf": "^5.0.0",
"tar": "^6.1.11"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^24.1.0",
"@rollup/plugin-node-resolve": "^15.0.2",
"live-server": "^1.2.1",
"rollup": "^3.21.0"
}
}
{
"name": "@wasm-tool/rollup-plugin-rust",
"author": "Pauan <[email protected]>",
"description": "Rollup plugin for bundling and importing Rust crates.",
"version": "2.4.5",
"license": "MIT",
"repository": "github:wasm-tool/rollup-plugin-rust",
"homepage": "https://github.com/wasm-tool/rollup-plugin-rust#readme",
"bugs": "https://github.com/wasm-tool/rollup-plugin-rust/issues",
"main": "src/index.js",
"scripts": {
"test:foo": "cd tests/src/foo && yarn install",
"test": "yarn test:foo && cd tests && rimraf dist/js && rollup --bundleConfigAsCjs --config",
"test:watch": "yarn test:foo && cd tests && rimraf dist/js && rollup --bundleConfigAsCjs --config --watch",
"test:serve": "live-server tests/dist"
},
"directories": {
"example": "example"
},
"keywords": [
"rollup-plugin",
"vite-plugin",
"rust-wasm",
"wasm",
"rust",
"rollup",
"plugin",
"webassembly",
"wasm-bindgen",
"wasm-pack"
],
"dependencies": {
"@iarna/toml": "^2.2.5",
"@rollup/pluginutils": "^5.0.2",
"binaryen": "^111.0.0",
"chalk": "^4.0.0",
"glob": "^10.2.2",
"node-fetch": "^2.0.0",
"replace-in-files": "^3.0.0",
"rimraf": "^5.0.0",
"tar": "^6.1.11"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^24.1.0",
"@rollup/plugin-node-resolve": "^15.2.3",
"live-server": "^1.2.1",
"rollup": "^3.29.4"
}
}
124 changes: 113 additions & 11 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ const $toml = require("@iarna/toml");
const { createFilter } = require("@rollup/pluginutils");
const { glob, rm, mv, mkdir, read, readString, writeString, exec, spawn, lock, debug, getEnv } = require("./utils");
const { run_wasm_bindgen } = require("./wasm-bindgen");

const replaceInFiles = require("replace-in-files");
const wasm2jsPath = require.resolve('binaryen/bin/wasm2js');
const rollup = require('rollup');
const { nodeResolve } = require("@rollup/plugin-node-resolve");

const PREFIX = "./.__rollup-plugin-rust__";
const ENTRY_SUFFIX = "?rollup-plugin-rust-entry";
Expand Down Expand Up @@ -112,6 +115,55 @@ async function load_wasm(out_dir, options) {
return await read(wasm_path);
}

async function bundleJS(path) {
const bundle = await rollup.rollup({
input: path,
plugins: [ nodeResolve() ],
});

const { output } = await bundle.generate({
format: 'es',
});

return output[0].code;
}

async function run_wasm2js(out_dir, name, options) {
const wasm2js_args = [
$path.join(out_dir, "index_bg.wasm"),
"-o", $path.join(out_dir, name+".js"),
];

if (options.verbose) {
debug(`Running ${wasm2js_args.join(" ")}`);
}

let jsContent;
try {
await spawn(wasm2jsPath, wasm2js_args, { cwd: out_dir, stdio: "inherit" });

await replaceInFiles({
files: [
$path.join(out_dir, "index.js"),
$path.join(out_dir, "index_bg.js"),
],
from: /index_bg\.wasm/g,
to: name + ".js",
});

jsContent = await bundleJS($path.join(out_dir, "index.js"));
} catch (e) {
if (options.verbose) {
throw e;
} else {
const e = new Error("wasm2js failed");
e.stack = null;
throw e;
}
}

return {name, compiledOutput: jsContent.toString(), out_dir};
}

async function compile_rust(cx, dir, id, target_dir, source, options) {
const toml = $toml.parse(source);
Expand Down Expand Up @@ -152,9 +204,13 @@ async function compile_rust(cx, dir, id, target_dir, source, options) {
await run_wasm_opt(cx, out_dir, options);
}

const wasm = await load_wasm(out_dir, options);
const compiledOutput = await load_wasm(out_dir, options);

if(options.experimental.transpileToJS) {
return run_wasm2js(out_dir, name, options);
}

return { name, wasm, out_dir };
return { name, compiledOutput, out_dir };
});

} catch (e) {
Expand Down Expand Up @@ -204,7 +260,7 @@ async function build(cx, state, id, options) {
}


function compile_js_inline(options, import_path, real_path, wasm, is_entry) {
function compile_js_inline(options, import_path, real_path, compiledOutput, is_entry) {
let export_code;

if (!is_entry && options.experimental.directExports) {
Expand All @@ -214,6 +270,23 @@ function compile_js_inline(options, import_path, real_path, wasm, is_entry) {
export_code = "";
}

if(options.experimental.transpileToJS) {
if (!options.experimental.directExports) {
throw new Error("transpileToJS can only be used with experimental.directExports: true");
}
if(!options.experimental.synchronous) {
throw new Error("transpileToJS can only be used with experimental.synchronous: true");
}

return {
code: compiledOutput,
map: { mappings: '' },
moduleSideEffects: true,
meta: {
"rollup-plugin-rust": { root: false, real_path }
},
};
}

let main_code;
let sideEffects;
Expand Down Expand Up @@ -258,7 +331,7 @@ function compile_js_inline(options, import_path, real_path, wasm, is_entry) {
}


const wasm_string = JSON.stringify(wasm.toString("base64"));
const wasm_string = JSON.stringify(compiledOutput.toString("base64"));

const code = `
${export_code}
Expand Down Expand Up @@ -309,6 +382,9 @@ function compile_js_inline(options, import_path, real_path, wasm, is_entry) {

function compile_js_load(cx, state, options, import_path, real_path, name, wasm, is_entry) {
let fileId;
if(options.experimental.transpileToJS) {
throw new Error("transpileToJS can only be used with inlineWasm: true");
}

if (options.outDir == null) {
fileId = cx.emitFile({
Expand Down Expand Up @@ -433,19 +509,19 @@ function compile_js_load(cx, state, options, import_path, real_path, name, wasm,
}


function compile_js(cx, state, name, wasm, is_entry, out_dir, options) {
function compile_js(cx, state, name, compiledOutput, is_entry, out_dir, options) {
const real_path = $path.join(out_dir, "index.js");

// This returns a fake file path, this ensures that the directory is the
// same as the Cargo.toml file, which is necessary in order to make npm
// package imports work correctly.
const import_path = `"${PREFIX}${name}/index.js"`;

if (options.inlineWasm) {
return compile_js_inline(options, import_path, real_path, wasm, is_entry);
if (options.inlineWasm || options.transpileToJS) {
return compile_js_inline(options, import_path, real_path, compiledOutput, is_entry);

} else {
return compile_js_load(cx, state, options, import_path, real_path, name, wasm, is_entry);
return compile_js_load(cx, state, options, import_path, real_path, name, compiledOutput, is_entry);
}
}

Expand Down Expand Up @@ -514,11 +590,37 @@ async function load_cargo_toml(cx, state, id, is_entry, meta, options) {

await compile_dts(cx, state, result.name, result.out_dir, options);

return compile_js(cx, state, result.name, result.wasm, is_entry, result.out_dir, options);
return compile_js(cx, state, result.name, result.compiledOutput, is_entry, result.out_dir, options);
}


/**
* @typedef {Object} ExperimentalRustOptions
* @property {boolean} [directExports]
* @property {boolean} [synchronous]
* @property {string} [typescriptDeclarationDir]
* @property {boolean} [transpileToJS]
*/

/**
* @typedef {Object} RustOptions
* @property {string} [serverPath]
* @property {boolean} [nodejs]
* @property {boolean} [debug]
* @property {boolean} [verbose]
* @property {boolean} [inlineWasm]
* @property {string[]} [cargoArgs]
* @property {string[]} [wasmBindgenArgs]
* @property {string[]} [wasmOptArgs]
* @property {string[]} [watchPatterns]
* @property {(string)=>string} [importHook]
* @property {ExperimentalRustOptions} [experimental]
*/

/**
* @param {RustOptions} options
*/
module.exports = function rust(options = {}) {

// TODO should the filter affect the watching ?
// TODO should the filter affect the Rust compilation ?
const filter = createFilter(options.include, options.exclude);
Expand Down
5 changes: 4 additions & 1 deletion src/wasm-bindgen.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,12 @@ async function run_wasm_bindgen(dir, wasm_path, out_dir, options) {
let wasm_bindgen_args = [
"--out-dir", out_dir,
"--out-name", "index",
"--target", "web",
"--omit-default-module-path",
];

if (!options.experimental.transpileToJs) {
wasm_bindgen_args.concat(["--target", "web"]);
}

if (options.experimental.typescriptDeclarationDir == null) {
wasm_bindgen_args.push("--no-typescript");
Expand Down