Skip to content

Commit

Permalink
Adds rust_to_wasm support to transpile_web_ui
Browse files Browse the repository at this point in the history
  • Loading branch information
szilardszaloki committed Jan 15, 2025
1 parent 742deb6 commit 123f48d
Show file tree
Hide file tree
Showing 8 changed files with 468 additions and 267 deletions.
2 changes: 2 additions & 0 deletions components/brave_extension/extension/brave_extension/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ transpile_web_ui("brave_extension") {

public_asset_path = "/out/"

sync_wasm = true

deps =
[ "//brave/components/brave_extension:web_discovery_project_resources" ]
}
Expand Down
46 changes: 46 additions & 0 deletions components/common/rust_to_wasm.gni
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Copyright (c) 2025 The Brave Authors. All rights reserved.
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at https://mozilla.org/MPL/2.0/.

import("//brave/tools/crates/sources.gni")

template("rust_to_wasm") {
assert(defined(invoker.rust_packages),
"Need rust_packages in $target_name listing the Config.toml files.")

action_foreach(target_name) {
deps = [ "//brave/tools/crates:build_wasm_pack" ]
if (defined(invoker.deps)) {
deps += invoker.deps
}

inputs = [ wasm_pack_exe ]
sources = invoker.rust_packages
inputs += sources

script = "//build/gn_run_binary.py"

args = [
rebase_path(wasm_pack_exe),
"build",
"{{source_dir}}",
"--out-dir",
rebase_path("$root_out_dir/{{source_gen_dir}}/pkg"),
"--out-name",
"index",
"--",
"--target-dir",
rebase_path("$root_out_dir/{{source_gen_dir}}/target"),
]

outputs = [
"{{source_gen_dir}}/pkg/index_bg.js",
"{{source_gen_dir}}/pkg/index_bg.wasm",
"{{source_gen_dir}}/pkg/index_bg.wasm.d.ts",
"{{source_gen_dir}}/pkg/index.d.ts",
"{{source_gen_dir}}/pkg/index.js",
"{{source_gen_dir}}/pkg/package.json",
]
}
}
24 changes: 24 additions & 0 deletions components/common/typescript.gni
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# You can obtain one at https://mozilla.org/MPL/2.0/.

import("//brave/resources/brave_grit.gni")
import("rust_to_wasm.gni")

# JS / TS imports via `require` or `import` will be added to a list and
# provided to GN so it knows which projects to re-build when you modify a file
Expand Down Expand Up @@ -34,6 +35,7 @@ brave_common_web_compile_inputs = [
rebase_path("../webpack/gen-webpack-grd.js"),
rebase_path("../webpack/path-map.js"),
rebase_path("../webpack/webpack-plugin-depfile.js"),
rebase_path("../webpack/xhr-compile-async-wasm-plugin.js"),

# typescript config changes warrant a re-build of all typescript builds
"//brave/tsconfig.json",
Expand Down Expand Up @@ -84,6 +86,12 @@ brave_common_web_compile_inputs = [
# If true, the resulting bundle will be a JS module that can import other
# modules using `import` syntax.
template("transpile_web_ui") {
if (defined(invoker.rust_packages)) {
rust_to_wasm("build_rust_packages") {
rust_packages = invoker.rust_packages
}
}

action(target_name) {
script = "//brave/script/transpile-web-ui.py"

Expand All @@ -109,6 +117,10 @@ template("transpile_web_ui") {
deps += invoker.deps
}

if (defined(invoker.rust_packages)) {
deps += [ ":build_rust_packages" ]
}

# This depfile will be generated by the build script.
# We keep it outside the output_dir since we don't want
# it to be included in the packaged output.
Expand Down Expand Up @@ -192,6 +204,18 @@ template("transpile_web_ui") {
args += [ "--production" ]
}

if (defined(invoker.module_library_type) && invoker.module_library_type) {
args += [ "--module_library_type" ]
}

if (defined(invoker.sync_wasm) && invoker.sync_wasm) {
args += [ "--sync_wasm" ]
}

if (defined(invoker.xhr_wasm_loading) && invoker.xhr_wasm_loading) {
args += [ "--xhr_wasm_loading" ]
}

forward_variables_from(invoker,
[
"public_deps",
Expand Down
23 changes: 19 additions & 4 deletions components/webpack/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
const path = require('path')
const webpack = require('webpack')
const GenerateDepfilePlugin = require('./webpack-plugin-depfile')
const XHRCompileAsyncWasmPlugin = require('./xhr-compile-async-wasm-plugin.js')
const { fallback, provideNodeGlobals } = require('./polyfill')
const pathMap = require('./path-map')(process.env.ROOT_GEN_DIR)

Expand Down Expand Up @@ -73,9 +74,25 @@ module.exports = async function (env, argv) {
chunkFilename: '[name].chunk.js',
publicPath: '/'
}
if (env.module_library_type) {
output.library = { type: 'module' }
}
if (env.output_public_path) {
output.publicPath = env.output_public_path
}
if (env.xhr_wasm_loading) {
output.enabledWasmLoadingTypes = [ 'xhr' ]
output.wasmLoading = 'xhr'
}

const experiments = {
outputModule: Boolean(env.output_module)
}
if (env.sync_wasm) {
experiments.syncWebAssembly = true
} else {
experiments.asyncWebAssembly = true
}

return {
entry,
Expand All @@ -89,10 +106,7 @@ module.exports = async function (env, argv) {
// Define NO_CONCATENATE for analyzing module size.
concatenateModules: !process.env.NO_CONCATENATE
},
experiments: {
syncWebAssembly: true,
outputModule: Boolean(env.output_module)
},
experiments,
externals: [
function ({ context, request }, callback) {
if (env.output_module) {
Expand Down Expand Up @@ -133,6 +147,7 @@ module.exports = async function (env, argv) {
...Object.keys(pathMap)
.filter(p => p.startsWith('chrome://'))
.map(p => prefixReplacer(p, pathMap[p])),
env.xhr_wasm_loading && new XHRCompileAsyncWasmPlugin(),
],
module: {
rules: [
Expand Down
75 changes: 75 additions & 0 deletions components/webpack/xhr-compile-async-wasm-plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/* Copyright (c) 2025 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */

const { WEBASSEMBLY_MODULE_TYPE_ASYNC } = require("webpack/lib/ModuleTypeConstants");
const AsyncWasmLoadingRuntimeModule = require("webpack/lib/wasm-async/AsyncWasmLoadingRuntimeModule");

const PLUGIN_NAME = "XHRCompileAsyncWasmPlugin";

class XHRCompileAsyncWasmPlugin {
type = "xhr";

apply(compiler) {
const { webpack } = compiler;
const { RuntimeGlobals, Template, wasm } = webpack;
wasm.EnableWasmLoadingPlugin.setEnabled(compiler, this.type);

compiler.hooks.thisCompilation.tap(PLUGIN_NAME, compilation => {
const { outputOptions, runtimeTemplate } = compilation;
const globalWasmLoading = outputOptions.wasmLoading;

const isEnabledForChunk = chunk => {
const options = chunk.getEntryOptions();
const wasmLoading =
options && options.wasmLoading !== undefined
? options.wasmLoading
: globalWasmLoading;
return wasmLoading === this.type;
};

const generateLoadBinaryCode = path =>
Template.asString([
`new Promise(${runtimeTemplate.basicFunction(
"resolve",
[
"const request = new XMLHttpRequest();",
`request.onload = ${runtimeTemplate.returningFunction(
"resolve({ arrayBuffer() { return request.response }})",
""
)};`,
`request.open("GET", ${RuntimeGlobals.publicPath} + ${path});`,
'request.responseType = "arraybuffer";',
"request.send();",
]
)})`
]);

compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.instantiateWasm)
.tap(PLUGIN_NAME, (chunk, set, { chunkGraph }) => {
if (!isEnabledForChunk(chunk)) return;
if (
!chunkGraph.hasModuleInGraph(
chunk,
m => m.type === WEBASSEMBLY_MODULE_TYPE_ASYNC
)
) {
return;
}
set.add(RuntimeGlobals.publicPath);
compilation.addRuntimeModule(
chunk,
new class extends AsyncWasmLoadingRuntimeModule {
constructor(generateLoadBinaryCode) {
super({ generateLoadBinaryCode, supportsStreaming: false });
}
}(generateLoadBinaryCode)
);
});
});
}
}

module.exports = XHRCompileAsyncWasmPlugin;
Loading

0 comments on commit 123f48d

Please sign in to comment.