Skip to content

Commit e3ffd3b

Browse files
committed
playground: ship findutils locate and updatedb in WASM
Build the locate and updatedb binaries from uutils/findutils alongside find and advertise them in the playground. The standalone WASM matrix now takes a list of bins per module, emitting one .wasm per binary. xargs is intentionally omitted: it must spawn child processes, which the browser WASI sandbox does not support.
1 parent 4b4be7e commit e3ffd3b

3 files changed

Lines changed: 50 additions & 33 deletions

File tree

.github/workflows/website.yml

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,13 @@ jobs:
118118
name: wasm-coreutils
119119
path: wasm-out
120120

121-
# grep, find, diffutils and sed each ship a single standalone binary built the
122-
# same way, so they share one matrix job. grep/find pull in the Oniguruma C
123-
# library (onig_sys) and need a WASI sysroot to compile its bundled C sources;
124-
# diffutils and sed are pure Rust and set needs_wasi: false. The `order` field
125-
# keeps the merged command/version lists in a stable sequence in `build`.
121+
# grep, findutils, diffutils and sed ship standalone binaries built the same
122+
# way, so they share one matrix job. Each entry lists its `bins` (findutils
123+
# provides three: find, locate, updatedb); every bin emits its own .wasm.
124+
# grep/findutils pull in the Oniguruma C library (onig_sys) and need a WASI
125+
# sysroot to compile its bundled C sources; diffutils and sed are pure Rust and
126+
# set needs_wasi: false. The `order` field keeps the merged command/version
127+
# lists in a stable sequence in `build`.
126128
wasm-standalone:
127129
name: Build ${{ matrix.name }} WASM
128130
runs-on: ubuntu-latest
@@ -132,28 +134,31 @@ jobs:
132134
include:
133135
- name: grep
134136
repo: uutils/grep
135-
bin: grep
137+
bins: grep
136138
needs_wasi: true
137139
commands: '"grep"'
138140
version_const: UUTILS_GREP_VERSION
139141
order: 10
142+
# findutils ships several standalone binaries; build find, locate and
143+
# updatedb so the playground can offer them. (xargs is omitted: it must
144+
# spawn child processes, which the browser WASI sandbox can't do.)
140145
- name: find
141146
repo: uutils/findutils
142-
bin: find
147+
bins: find locate updatedb
143148
needs_wasi: true
144-
commands: '"find"'
149+
commands: '"find","locate","updatedb"'
145150
version_const: UUTILS_FINDUTILS_VERSION
146151
order: 20
147152
- name: diffutils
148153
repo: uutils/diffutils
149-
bin: diffutils
154+
bins: diffutils
150155
needs_wasi: false
151156
commands: '"diff","cmp"'
152157
version_const: UUTILS_DIFFUTILS_VERSION
153158
order: 30
154159
- name: sed
155160
repo: uutils/sed
156-
bin: sed
161+
bins: sed
157162
needs_wasi: false
158163
commands: '"sed"'
159164
version_const: UUTILS_SED_VERSION
@@ -187,17 +192,21 @@ jobs:
187192
export CC_wasm32_wasip1="$WASI_SDK_PATH/bin/clang"
188193
export CFLAGS_wasm32_wasip1="--sysroot=$WASI_SDK_PATH/share/wasi-sysroot"
189194
fi
190-
wasm="${{ matrix.bin }}.wasm"
191195
cd ${{ matrix.name }}
192-
cargo build --release --target wasm32-wasip1 --bin ${{ matrix.bin }}
193-
test -f "target/wasm32-wasip1/release/${wasm}"
194196
mkdir -p ../wasm-out
195-
cp "target/wasm32-wasip1/release/${wasm}" "../wasm-out/${wasm}"
196-
# Optimize WASM size if wasm-opt is available
197-
if command -v wasm-opt &> /dev/null; then
198-
wasm-opt -Oz "../wasm-out/${wasm}" -o "../wasm-out/${wasm}"
199-
fi
200-
echo "${{ matrix.name }} WASM binary size: $(du -h ../wasm-out/${wasm} | cut -f1)"
197+
# A module may ship several standalone binaries (findutils → find,
198+
# locate, updatedb); build each and emit its own .wasm file.
199+
for bin in ${{ matrix.bins }}; do
200+
wasm="${bin}.wasm"
201+
cargo build --release --target wasm32-wasip1 --bin "${bin}"
202+
test -f "target/wasm32-wasip1/release/${wasm}"
203+
cp "target/wasm32-wasip1/release/${wasm}" "../wasm-out/${wasm}"
204+
# Optimize WASM size if wasm-opt is available
205+
if command -v wasm-opt &> /dev/null; then
206+
wasm-opt -Oz "../wasm-out/${wasm}" -o "../wasm-out/${wasm}"
207+
fi
208+
echo "${bin} WASM binary size: $(du -h ../wasm-out/${wasm} | cut -f1)"
209+
done
201210
# Advertise this module's commands in the playground's command list.
202211
echo '${{ matrix.commands }}' > ../wasm-out/commands-${{ matrix.order }}-${{ matrix.name }}.txt
203212
# Record the commit used to build this WASM module.

content/playground.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ template = "page.html"
2929
document.addEventListener("DOMContentLoaded", function() {
3030
initPlayground("wasm-playground");
3131
// Build a "Load" button per optional standalone module (grep, find,
32-
// diffutils). These ship as their own WASM modules and load on demand to
32+
// locate, updatedb, diffutils, sed). These ship as their own WASM
33+
// modules and load on demand to
3334
// keep the initial page download light; running a command auto-loads its
3435
// module too (e.g. diff/cmp both come from the diffutils module).
3536
var loaderBar = document.getElementById("playground-loaders");

static/js/wasm-terminal.js

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,19 @@ if (typeof SharedArrayBuffer === "undefined") {
1515

1616
const WASM_URL = "/wasm/uutils.wasm";
1717
// Some utilities ship as their own standalone WASM modules rather than as part
18-
// of the coreutils multicall binary (grep lives in uutils/grep, find in
19-
// uutils/findutils, diff and cmp in uutils/diffutils, sed in uutils/sed). Each
20-
// module is loaded on demand and is optional — see loadStandalone. A single
21-
// module can provide several commands (diffutils → diff, cmp), which the
22-
// diffutils binary dispatches on argv[0], so each command is invoked directly
23-
// by its own name.
18+
// of the coreutils multicall binary (grep lives in uutils/grep, find/locate/
19+
// updatedb in uutils/findutils, diff and cmp in uutils/diffutils, sed in
20+
// uutils/sed). Each module is loaded on demand and is optional — see
21+
// loadStandalone. A single module can provide several commands (diffutils →
22+
// diff, cmp), which the binary dispatches on argv[0], so each command is invoked
23+
// directly by its own name. findutils ships separate binaries, so each is its
24+
// own module. (xargs is intentionally absent: it must spawn child processes,
25+
// which the browser WASI sandbox can't do.)
2426
const STANDALONE_MODULES = {
2527
grep: { url: "/wasm/grep.wasm", commands: ["grep"] },
2628
find: { url: "/wasm/find.wasm", commands: ["find"] },
29+
locate: { url: "/wasm/locate.wasm", commands: ["locate"] },
30+
updatedb: { url: "/wasm/updatedb.wasm", commands: ["updatedb"] },
2731
diffutils: { url: "/wasm/diffutils.wasm", commands: ["diff", "cmp"] },
2832
sed: { url: "/wasm/sed.wasm", commands: ["sed"] },
2933
};
@@ -75,7 +79,7 @@ const FALLBACK_COMMANDS = [
7579
"sha1sum", "sha224sum", "sha256sum", "sha384sum", "sha512sum",
7680
"shred", "shuf", "sleep", "sum", "tee", "true", "truncate",
7781
"uname", "unexpand", "uniq", "unlink", "vdir", "wc",
78-
"grep", "find", "diff", "cmp", "sed",
82+
"grep", "find", "locate", "updatedb", "diff", "cmp", "sed",
7983
];
8084
const AVAILABLE_COMMANDS =
8185
(typeof WASM_COMMANDS !== "undefined" && Array.isArray(WASM_COMMANDS) && WASM_COMMANDS.length > 0)
@@ -233,7 +237,8 @@ async function initWasm() {
233237
if (wasmReady) return;
234238
try {
235239
// Only the coreutils multicall binary loads eagerly; the standalone
236-
// modules (grep, find, diffutils) are fetched on demand — see loadStandalone.
240+
// modules (grep, find, locate, updatedb, diffutils, sed) are fetched
241+
// on demand — see loadStandalone.
237242
await Promise.all([loadWasiShim(), loadWasm()]);
238243
wasmReady = true;
239244
} catch (e) {
@@ -626,8 +631,9 @@ async function executeCommandLine(line) {
626631
return `uutils: command not found: ${cmd}\nType 'help' for available commands.\n`;
627632
}
628633

629-
// Some utilities (grep, find, diff, cmp) are separate WASM modules rather
630-
// than part of the coreutils multicall binary, and are loaded on demand.
634+
// Some utilities (grep, find, locate, updatedb, diff, cmp, sed) are
635+
// separate WASM modules rather than part of the coreutils multicall binary,
636+
// and are loaded on demand.
631637
// Fetch the module the first time one of its commands is used (no-op once
632638
// cached; diff and cmp share the single diffutils module).
633639
const moduleName = STANDALONE_COMMAND_MODULE[cmd];
@@ -955,7 +961,7 @@ async function initPlayground(containerId) {
955961
terminal.writeln("");
956962
terminal.writeln("Type \x1b[1;32mhelp\x1b[0m for available commands.");
957963
terminal.writeln("Sample data files: names.txt, numbers.txt, fruits.txt, csv.txt, words.txt");
958-
terminal.writeln("\x1b[2mgrep, find, sed and diff/cmp load on demand — just run them, or use the buttons below.\x1b[0m");
964+
terminal.writeln("\x1b[2mgrep, find/locate/updatedb, sed and diff/cmp load on demand — just run them, or use the buttons below.\x1b[0m");
959965
} catch (e) {
960966
terminal.writeln(" \x1b[1;31mfailed\x1b[0m");
961967
terminal.writeln("Failed to load WASM binary. Commands are not available.");
@@ -1003,8 +1009,9 @@ window.uutilsExecute = executeCommandLine;
10031009
window.runInTerminal = runInTerminal;
10041010
window.setLocale = setLocale;
10051011

1006-
// On-demand loading of the optional standalone modules (grep, find, diffutils),
1007-
// used by the "Load" buttons on the playground page. Keyed by module name; one
1012+
// On-demand loading of the optional standalone modules (grep, find, locate,
1013+
// updatedb, diffutils, sed), used by the "Load" buttons on the
1014+
// playground page. Keyed by module name; one
10081015
// module may back several commands (diffutils → diff, cmp).
10091016
window.uutilsPrograms = Object.keys(STANDALONE_MODULES);
10101017
window.loadProgram = (mod) => loadStandalone(mod);

0 commit comments

Comments
 (0)