Merge latest upstream main changes

Summary:
- Better CLI arguments parsing
- Builtin compression support for large source files

Change-Id: Ia0bf37ae5405adb218a2da2c072a1f9cf0ee9f95
Reviewed-on: https://chromium-review.googlesource.com/c/external/github.com/WebKit/JetStream/+/7021129
Reviewed-by: Marja Hölttä <marja@chromium.org>
This commit is contained in:
Camillo Bruni 2025-10-08 13:20:36 +02:00
parent 254b4522a9
commit 43fec888d2
26 changed files with 520 additions and 84460 deletions

View file

@ -39,6 +39,9 @@ jobs:
- name: Install Node Packages
run: npm ci
- name: Decompress compressed files
run: npm run decompress
- name: Cache jsvu Binaries
uses: actions/cache@v4
with:

5
.gitignore vendored
View file

@ -8,3 +8,8 @@ node_modules
# v8.log is generated by the d8-shell if profiling is enabled
v8.log
# Decompressed files go here
RexBench/FlightPlanner/waypoints.js
SeaMonster/inspector-json-payload.js
wasm/argon2/build/argon2.wasm

33
.prettierignore Normal file
View file

@ -0,0 +1,33 @@
.*
node_modules
package-lock.json
dist
build
*bundle*.js
third_party
/Octane/*
/ARES-6/*
/cdjs/*
/8bitbench/*
/class-fields/*
/code-load/*
/SunSpider
/SeaMonster
/WSL
/worker/bomb-subtests
/wasm/dotnet/build-*
/wasm/tfjs-model-*
/simple/*
/generators/*
/threejs/*
# Ignore everything in RexBench, then selectively un-ignore.
/RexBench/*
!/RexBench/*/
/RexBench/*/*
!/RexBench/*/benchmark.js
!benchmark.js
!*/benchmark.js
!/**/*.md

12
.prettierrc Normal file
View file

@ -0,0 +1,12 @@
{
"arrowParens": "always",
"bracketSameLine": false,
"bracketSpacing": true,
"htmlWhitespaceSensitivity": "css",
"printWidth": 100,
"semi": true,
"singleQuote": false,
"tabWidth": 4,
"trailingComma": "es5",
"useTabs": false
}

View file

@ -31,7 +31,17 @@ const defaultIterationCount = 120;
const defaultWorstCaseCount = 4;
if (!JetStreamParams.prefetchResources)
console.warn("Disabling resource prefetching!");
console.warn("Disabling resource prefetching! All compressed files must have been decompressed using `npm run decompress`");
if (!isInBrowser && JetStreamParams.prefetchResources) {
// Use the wasm compiled zlib as a polyfill when decompression stream is
// not available in JS shells.
load("./wasm/zlib/shell.js");
// Load a polyfill for TextEncoder/TextDecoder in shells. Used when
// decompressing a prefetched resource and converting it to text.
load("./polyfills/fast-text-encoding/1.0.3/text.js");
}
// Used for the promise representing the current benchmark run.
this.currentResolve = null;
@ -140,6 +150,20 @@ function shellFriendlyScore(time) {
}
// Files can be zlib compressed to reduce the size of the JetStream source code.
// We don't use http compression because we support running from the shell and
// don't want to require a complicated server setup.
//
// zlib was chosen because we already have it in tree for the wasm-zlib test.
function isCompressed(name) {
return name.endsWith(".z");
}
function uncompressedName(name) {
console.assert(isCompressed(name));
return name.slice(0, -2);
}
// TODO: Cleanup / remove / merge. This is only used for caching loads in the
// non-browser setting. In the browser we use exclusively `loadCache`,
// `loadBlob`, `doLoadBlob`, `prefetchResourcesForBrowser` etc., see below.
@ -152,6 +176,13 @@ class ShellFileLoader {
// share common code.
load(url) {
console.assert(!isInBrowser);
let compressed = isCompressed(url);
if (compressed && !JetStreamParams.prefetchResources) {
url = uncompressedName(url);
}
// If we aren't supposed to prefetch this then return code snippet that will load the url on-demand.
if (!JetStreamParams.prefetchResources)
return `load("${url}");`
@ -159,7 +190,14 @@ class ShellFileLoader {
return this.requests.get(url);
}
const contents = readFile(url);
let contents;
if (compressed) {
const compressedBytes = new Int8Array(read(url, "binary"));
const decompressedBytes = zlib.decompress(compressedBytes);
contents = new TextDecoder().decode(decompressedBytes);
} else {
contents = readFile(url);
}
this.requests.set(url, contents);
return contents;
}
@ -211,10 +249,14 @@ class Driver {
performance.mark("update-ui");
benchmark.updateUIAfterRun();
if (isInBrowser && JetStreamParams.prefetchResources) {
if (isInBrowser) {
const cache = JetStream.blobDataCache;
for (const file of benchmark.files) {
const blobData = cache[file];
// If we didn't prefetch this resource, then no need to free it
if (!blobData.blob) {
continue
}
blobData.refCount--;
if (!blobData.refCount)
cache[file] = undefined;
@ -374,6 +416,9 @@ class Driver {
async prefetchResources() {
if (!isInBrowser) {
if (JetStreamParams.prefetchResources) {
await zlib.initialize();
}
for (const benchmark of this.benchmarks)
benchmark.prefetchResourcesForShell();
return;
@ -491,7 +536,7 @@ class Driver {
if (!isInBrowser)
return;
if (!JetStreamParams.shouldReport)
if (!JetStreamParams.report)
return;
const content = this.resultsJSON();
@ -589,6 +634,11 @@ class Scripts {
}
class ShellScripts extends Scripts {
constructor() {
super();
this.prefetchedResources = Object.create(null);;
}
run() {
let globalObject;
let realm;
@ -615,6 +665,19 @@ class ShellScripts extends Scripts {
currentReject
};
// Pass the prefetched resources to the benchmark global.
if (JetStreamParams.prefetchResources) {
// Pass the 'TextDecoder' polyfill into the benchmark global. Don't
// use 'TextDecoder' as that will get picked up in the kotlin test
// without full support.
globalObject.ShellTextDecoder = TextDecoder;
// Store shellPrefetchedResources on ShellPrefetchedResources so that
// getBinary and getString can find them.
globalObject.ShellPrefetchedResources = this.prefetchedResources;
} else {
console.assert(Object.values(this.prefetchedResources).length === 0, "Unexpected prefetched resources");
}
globalObject.performance ??= performance;
for (const script of this.scripts)
globalObject.loadString(script);
@ -622,6 +685,12 @@ class ShellScripts extends Scripts {
return isD8 ? realm : globalObject;
}
addPrefetchedResources(prefetchedResources) {
for (let [file, bytes] of Object.entries(prefetchedResources)) {
this.prefetchedResources[file] = bytes;
}
}
add(text) {
this.scripts.push(text);
}
@ -654,7 +723,6 @@ class BrowserScripts extends Scripts {
return magicFrame;
}
add(text) {
this.scripts.push(`<script>${text}</script>`);
}
@ -674,6 +742,7 @@ class Benchmark {
this.allowUtf16 = !!plan.allowUtf16;
this.scripts = null;
this.preloads = null;
this.shellPrefetchedResources = null;
this.results = [];
this._state = BenchmarkState.READY;
}
@ -834,6 +903,9 @@ class Benchmark {
if (!!this.plan.exposeBrowserTest)
scripts.addBrowserTest();
if (this.shellPrefetchedResources) {
scripts.addPrefetchedResources(this.shellPrefetchedResources);
}
if (this.plan.preload) {
let preloadCode = "";
for (let [ variableName, blobURLOrPath ] of this.preloads)
@ -852,7 +924,7 @@ class Benchmark {
} else {
const cache = JetStream.blobDataCache;
for (const file of this.plan.files) {
scripts.addWithURL(JetStreamParams.prefetchResources ? cache[file].blobURL : file);
scripts.addWithURL(cache[file].blobURL);
}
}
@ -903,10 +975,19 @@ class Benchmark {
async doLoadBlob(resource) {
const blobData = JetStream.blobDataCache[resource];
const compressed = isCompressed(resource);
if (compressed && !JetStreamParams.prefetchResources) {
resource = uncompressedName(resource);
}
// If we aren't supposed to prefetch this then set the blobURL to just
// be the resource URL.
if (!JetStreamParams.prefetchResources) {
blobData.blobURL = resource;
return blobData;
}
let response;
let tries = 3;
while (tries--) {
@ -922,7 +1003,15 @@ class Benchmark {
continue;
throw new Error("Fetch failed");
}
const blob = await response.blob();
// If we need to decompress this, then run it through a decompression
// stream.
if (compressed) {
const stream = response.body.pipeThrough(new DecompressionStream("deflate"))
response = new Response(stream);
}
let blob = await response.blob();
blobData.blob = blob;
blobData.blobURL = URL.createObjectURL(blob);
return blobData;
@ -1058,7 +1147,27 @@ class Benchmark {
this.scripts = this.plan.files.map(file => shellFileLoader.load(file));
console.assert(this.preloads === null, "This initialization should be called only once.");
this.preloads = Object.entries(this.plan.preload ?? {});
this.preloads = [];
this.shellPrefetchedResources = Object.create(null);
if (!this.plan.preload) {
return;
}
for (let [name, file] of Object.entries(this.plan.preload)) {
const compressed = isCompressed(file);
if (compressed && !JetStreamParams.prefetchResources) {
file = uncompressedName(file);
}
if (JetStreamParams.prefetchResources) {
let bytes = new Int8Array(read(file, "binary"));
if (compressed) {
bytes = zlib.decompress(bytes);
}
this.shellPrefetchedResources[file] = bytes;
}
this.preloads.push([name, file]);
}
}
allScoreIdentifiers() {
@ -1382,15 +1491,23 @@ class AsyncBenchmark extends DefaultBenchmark {
} else {
str += `
JetStream.getBinary = async function(path) {
if ("ShellPrefetchedResources" in globalThis) {
return ShellPrefetchedResources[path];
}
return new Int8Array(read(path, "binary"));
};
JetStream.getString = async function(path) {
if ("ShellPrefetchedResources" in globalThis) {
return new ShellTextDecoder().decode(ShellPrefetchedResources[path]);
}
return read(path);
};
JetStream.dynamicImport = async function(path) {
try {
// TODO: this skips the prefetched resources, but I'm
// not sure of a way around that.
return await import(path);
} catch (e) {
// In shells, relative imports require different paths, so try with and
@ -1614,7 +1731,11 @@ class WasmLegacyBenchmark extends Benchmark {
`;
} else {
str += `
Module[key] = new Int8Array(read(path, "binary"));
if (ShellPrefetchedResources) {
Module[key] = ShellPrefetchedResources[path];
} else {
Module[key] = new Int8Array(read(path, "binary"));
}
if (andThen == doRun) {
globalObject.read = (...args) => {
console.log("should not be inside read: ", ...args);
@ -1931,7 +2052,7 @@ let BENCHMARKS = [
name: "FlightPlanner",
files: [
"./RexBench/FlightPlanner/airways.js",
"./RexBench/FlightPlanner/waypoints.js",
"./RexBench/FlightPlanner/waypoints.js.z",
"./RexBench/FlightPlanner/flight_planner.js",
"./RexBench/FlightPlanner/expectations.js",
"./RexBench/FlightPlanner/benchmark.js",
@ -2042,7 +2163,7 @@ let BENCHMARKS = [
new DefaultBenchmark({
name: "json-stringify-inspector",
files: [
"./SeaMonster/inspector-json-payload.js",
"./SeaMonster/inspector-json-payload.js.z",
"./SeaMonster/json-stringify-inspector.js",
],
iterations: 20,
@ -2052,7 +2173,7 @@ let BENCHMARKS = [
new DefaultBenchmark({
name: "json-parse-inspector",
files: [
"./SeaMonster/inspector-json-payload.js",
"./SeaMonster/inspector-json-payload.js.z",
"./SeaMonster/json-parse-inspector.js",
],
iterations: 20,
@ -2459,7 +2580,7 @@ let BENCHMARKS = [
"./wasm/argon2/benchmark.js",
],
preload: {
wasmBinary: "./wasm/argon2/build/argon2.wasm",
wasmBinary: "./wasm/argon2/build/argon2.wasm.z",
},
iterations: 30,
worstCaseCount: 3,

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

4
cli.js
View file

@ -21,7 +21,7 @@
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
*/
load("./shell-config.js");
@ -68,7 +68,7 @@ const CLI_PARAMS = {
help: "Start the benchmark automatically.",
param: "startAutomatically",
},
report: { help: "Report results to a server.", param: "shouldReport" },
report: { help: "Report results to a server.", param: "report" },
"start-delay": {
help: "Delay before starting the benchmark.",
param: "startDelay",

2
netlify.toml Normal file
View file

@ -0,0 +1,2 @@
[build]
command = "npm run decompress"

3
package-lock.json generated
View file

@ -24,7 +24,7 @@
"http-server": "^14.1.1",
"jsvu": "^2.5.1",
"local-web-server": "^5.4.0",
"prettier": "^2.8.3",
"prettier": "^2.8.8",
"selenium-webdriver": "^4.35.0"
},
"engines": {
@ -4932,6 +4932,7 @@
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
"dev": true,
"license": "MIT",
"bin": {
"prettier": "bin-prettier.js"
},

View file

@ -17,8 +17,10 @@
"scripts": {
"server": "node tests/server.mjs",
"compress": "node utils/compress.mjs",
"decompress": "node utils/compress.mjs -d -k",
"lint:check": "eslint **/*.{js,mjs,jsx,ts,tsx}",
"pretty:check": "prettier --check ./",
"pretty:format": "prettier --write ./",
"format:check": "npm run pretty:check && npm run lint:check",
"test:chrome": "node tests/run-browser.mjs --browser chrome",
"test:firefox": "node tests/run-browser.mjs --browser firefox",
@ -42,7 +44,7 @@
"http-server": "^14.1.1",
"jsvu": "^2.5.1",
"local-web-server": "^5.4.0",
"prettier": "^2.8.3",
"prettier": "^2.8.8",
"selenium-webdriver": "^4.35.0"
},
"dependencies": {

View file

@ -31,7 +31,7 @@ class Params {
// Enable a detailed developer menu to change the current Params.
developerMode = false;
startAutomatically = false;
shouldReport = false;
report = false;
startDelay = undefined;
testList = [];
@ -64,7 +64,7 @@ class Params {
_copyFromSearchParams(sourceParams) {
this.startAutomatically = this._parseBooleanParam(sourceParams, "startAutomatically");
this.developerMode = this._parseBooleanParam(sourceParams, "developerMode");
this.shouldReport = this._parseBooleanParam(sourceParams, "shouldReport");
this.report = this._parseBooleanParam(sourceParams, "report");
this.prefetchResources = this._parseBooleanParam(sourceParams, "prefetchResources");
this.RAMification = this._parseBooleanParam(sourceParams, "RAMification");
this.dumpJSONResults = this._parseBooleanParam(sourceParams, "dumpJSONResults");
@ -75,7 +75,7 @@ class Params {
this.customPostIterationCode = this._parseStringParam(sourceParams, "customPostIterationCode");
this.startDelay = this._parseIntParam(sourceParams, "startDelay", 0);
if (this.shouldReport && !this.startDelay)
if (this.report && !this.startDelay)
this.startDelay = 4000;
for (const paramKey of ["tag", "tags", "test", "tests"])

View file

@ -109,7 +109,7 @@ async function runTests() {
let success = true;
success &&= await runTest("Run UnitTests", () => sh(shellBinary, UNIT_TEST_PATH));
success &&= await runCLITest("Run Single Suite", shellBinary, "proxy-mobx");
success &&= await runCLITest("Run Tag No Prefetch", shellBinary, "proxy", "--no-prefetch");
success &&= await runCLITest("Run Tag No Prefetch", shellBinary, "proxy", "argon2-wasm", "--no-prefetch");
success &&= await runCLITest("Run Grouped with Details", shellBinary, "SunSpider", "--group-details");
success &&= await runCLITest("Run Disabled Suite", shellBinary, "disabled");
success &&= await runCLITest("Run Default Suite", shellBinary);

View file

@ -1199,7 +1199,7 @@ struct CustomHashTraits : public GenericHashTraits<T> {
if (!HashFunctions::safeToCompareToEmptyOrDeleted)
return;
ASSERT(!HashTranslator::equal(KeyTraits::emptyValue(), key));
typename std::aligned_storage<sizeof(ValueType), std::alignment_of<ValueType>::value>::type deletedValueBuffer;
alignas(ValueType) std::byte deletedValueBuffer[sizeof(ValueType)];
ValueType* deletedValuePtr = reinterpret_cast_ptr<ValueType*>(&deletedValueBuffer);
ValueType& deletedValue = *deletedValuePtr;
Traits::constructDeletedValue(deletedValue);

View file

@ -1,5 +1,5 @@
Built on 2025-01-23T14:26:43Z
Built on 2025-10-03T09:23:48Z
Toolchain versions
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.73 (ac676d5e437525d15df5fd46bc2c208ec6d376a3)
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 4.0.15-git
Building...
Building done

View file

@ -1,10 +1,15 @@
// This code implements the `-sMODULARIZE` settings by taking the generated
// JS program code (INNER_JS_CODE) and wrapping it in a factory function.
// Single threaded MINIMAL_RUNTIME programs do not need access to
// document.currentScript, so a simple export declaration is enough.
var setupModule = (() => {
// When MODULARIZE this JS may be executed later,
// after document.currentScript is gone, so we save it.
// In EXPORT_ES6 mode we can just use 'import.meta.url'.
var _scriptName = typeof document != 'undefined' ? document.currentScript?.src : undefined;
if (typeof __filename != 'undefined') _scriptName = _scriptName || __filename;
return (
function(moduleArg = {}) {
var moduleRtn;
return async function(moduleArg = {}) {
var moduleRtn;
// include: shell.js
// The Module object: Our interface to the outside world. We import
@ -22,14 +27,6 @@ function(moduleArg = {}) {
// can continue to use Module afterwards as well.
var Module = moduleArg;
// Set up the promise that indicates the Module is initialized
var readyPromiseResolve, readyPromiseReject;
var readyPromise = new Promise((resolve, reject) => {
readyPromiseResolve = resolve;
readyPromiseReject = reject;
});
// Determine the runtime environment we are in. You can customize this by
// setting the ENVIRONMENT setting at compile time (see settings.js).
// Attempt to auto-detect the environment
@ -39,19 +36,10 @@ var ENVIRONMENT_IS_WORKER = typeof WorkerGlobalScope != "undefined";
// N.b. Electron.js environment is simultaneously a NODE-environment, but
// also a web environment.
var ENVIRONMENT_IS_NODE = typeof process == "object" && typeof process.versions == "object" && typeof process.versions.node == "string" && process.type != "renderer";
if (ENVIRONMENT_IS_NODE) {}
var ENVIRONMENT_IS_NODE = typeof process == "object" && process.versions?.node && process.type != "renderer";
// --pre-jses are emitted after the Module integration code, so that they can
// refer to Module (if they choose; they can also define Module)
// Sometimes an existing Module object exists with properties
// meant to overwrite the default module functionality. Here
// we collect those properties and reapply _after_ we configure
// the current environment's defaults to avoid having to be so
// defensive during initialization.
var moduleOverrides = Object.assign({}, Module);
var arguments_ = [];
var thisProgram = "./this.program";
@ -60,6 +48,13 @@ var quit_ = (status, toThrow) => {
throw toThrow;
};
if (typeof __filename != "undefined") {
// Node
_scriptName = __filename;
} else if (ENVIRONMENT_IS_WORKER) {
_scriptName = self.location.href;
}
// `/` should be present at the end if `scriptDirectory` is not empty
var scriptDirectory = "";
@ -77,31 +72,25 @@ if (ENVIRONMENT_IS_NODE) {
// These modules will usually be used on Node.js. Load them eagerly to avoid
// the complexity of lazy-loading.
var fs = require("fs");
var nodePath = require("path");
scriptDirectory = __dirname + "/";
// include: node_shell_read.js
readBinary = filename => {
// We need to re-wrap `file://` strings to URLs. Normalizing isn't
// necessary in that case, the path should already be absolute.
filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename);
// We need to re-wrap `file://` strings to URLs.
filename = isFileURI(filename) ? new URL(filename) : filename;
var ret = fs.readFileSync(filename);
return ret;
};
readAsync = (filename, binary = true) => {
readAsync = async (filename, binary = true) => {
// See the comment in the `readBinary` function.
filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename);
return new Promise((resolve, reject) => {
fs.readFile(filename, binary ? undefined : "utf8", (err, data) => {
if (err) reject(err); else resolve(binary ? data.buffer : data);
});
});
filename = isFileURI(filename) ? new URL(filename) : filename;
var ret = fs.readFileSync(filename, binary ? undefined : "utf8");
return ret;
};
// end include: node_shell_read.js
if (!Module["thisProgram"] && process.argv.length > 1) {
if (process.argv.length > 1) {
thisProgram = process.argv[1].replace(/\\/g, "/");
}
arguments_ = process.argv.slice(2);
// MODULARIZE will export the module in the proper place outside, we don't need to export here
quit_ = (status, toThrow) => {
process.exitCode = status;
throw toThrow;
@ -110,29 +99,9 @@ if (ENVIRONMENT_IS_NODE) {
// Node.js workers are detected as a combination of ENVIRONMENT_IS_WORKER and
// ENVIRONMENT_IS_NODE.
if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
if (ENVIRONMENT_IS_WORKER) {
// Check worker, not web, since window could be polyfilled
scriptDirectory = self.location.href;
} else if (typeof document != "undefined" && document.currentScript) {
// web
scriptDirectory = document.currentScript.src;
}
// When MODULARIZE, this JS may be executed later, after document.currentScript
// is gone, so we saved it, and we use it here instead of any other info.
if (_scriptName) {
scriptDirectory = _scriptName;
}
// blob urls look like blob:http://site.com/etc/etc and we cannot infer anything from them.
// otherwise, slice off the final part of the url to find the script directory.
// if scriptDirectory does not contain a slash, lastIndexOf will return -1,
// and scriptDirectory will correctly be replaced with an empty string.
// If scriptDirectory contains a query (starting with ?) or a fragment (starting with #),
// they are removed because they could contain a slash.
if (scriptDirectory.startsWith("blob:")) {
scriptDirectory = "";
} else {
scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, "").lastIndexOf("/") + 1);
}
try {
scriptDirectory = new URL(".", _scriptName).href;
} catch {}
{
// include: web_or_worker_shell_read.js
if (ENVIRONMENT_IS_WORKER) {
@ -144,7 +113,7 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
return new Uint8Array(/** @type{!ArrayBuffer} */ (xhr.response));
};
}
readAsync = url => {
readAsync = async url => {
// Fetch has some additional restrictions over XHR, like it can't be used on a file:// url.
// See https://github.com/github/fetch/pull/92#issuecomment-140665932
// Cordova or Electron apps are typically loaded from a file:// url.
@ -166,39 +135,21 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
xhr.send(null);
});
}
return fetch(url, {
var response = await fetch(url, {
credentials: "same-origin"
}).then(response => {
if (response.ok) {
return response.arrayBuffer();
}
return Promise.reject(new Error(response.status + " : " + response.url));
});
if (response.ok) {
return response.arrayBuffer();
}
throw new Error(response.status + " : " + response.url);
};
}
} else // end include: web_or_worker_shell_read.js
{}
} else {}
var out = Module["print"] || console.log.bind(console);
var out = console.log.bind(console);
var err = Module["printErr"] || console.error.bind(console);
var err = console.error.bind(console);
// Merge back in the overrides
Object.assign(Module, moduleOverrides);
// Free the object hierarchy contained in the overrides, this lets the GC
// reclaim data used.
moduleOverrides = null;
// Emit code to handle expected values on the Module object. This applies Module.x
// to the proper local x. This has two benefits: first, we only emit it if it is
// expected to arrive, and second, by using a local everywhere else that can be
// minified.
if (Module["arguments"]) arguments_ = Module["arguments"];
if (Module["thisProgram"]) thisProgram = Module["thisProgram"];
// perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message
// end include: shell.js
// include: preamble.js
// === Preamble library stuff ===
@ -209,11 +160,9 @@ if (Module["thisProgram"]) thisProgram = Module["thisProgram"];
// You can also build docs locally as HTML or other formats in site/
// An online HTML version (which may be of a different version of Emscripten)
// is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html
var wasmBinary = Module["wasmBinary"];
var wasmBinary;
// Wasm globals
var wasmMemory;
//========================================
// Runtime essentials
//========================================
@ -226,39 +175,48 @@ var ABORT = false;
// but only when noExitRuntime is false.
var EXITSTATUS;
// Memory management
var /** @type {!Int8Array} */ HEAP8, /** @type {!Uint8Array} */ HEAPU8, /** @type {!Int16Array} */ HEAP16, /** @type {!Uint16Array} */ HEAPU16, /** @type {!Int32Array} */ HEAP32, /** @type {!Uint32Array} */ HEAPU32, /** @type {!Float32Array} */ HEAPF32, /** @type {!Float64Array} */ HEAPF64;
/**
* Indicates whether filename is delivered via file protocol (as opposed to http/https)
* @noinline
*/ var isFileURI = filename => filename.startsWith("file://");
// include: runtime_shared.js
function updateMemoryViews() {
var b = wasmMemory.buffer;
Module["HEAP8"] = HEAP8 = new Int8Array(b);
Module["HEAP16"] = HEAP16 = new Int16Array(b);
Module["HEAPU8"] = HEAPU8 = new Uint8Array(b);
Module["HEAPU16"] = HEAPU16 = new Uint16Array(b);
Module["HEAP32"] = HEAP32 = new Int32Array(b);
Module["HEAPU32"] = HEAPU32 = new Uint32Array(b);
Module["HEAPF32"] = HEAPF32 = new Float32Array(b);
Module["HEAPF64"] = HEAPF64 = new Float64Array(b);
}
// end include: runtime_shared.js
// include: runtime_common.js
// include: runtime_stack_check.js
// end include: runtime_stack_check.js
var __ATPRERUN__ = [];
// include: runtime_exceptions.js
// end include: runtime_exceptions.js
// include: runtime_debug.js
// end include: runtime_debug.js
var readyPromiseResolve, readyPromiseReject;
// functions called before the runtime is initialized
var __ATINIT__ = [];
// Memory management
var wasmMemory;
// functions called during startup
var __ATMAIN__ = [];
var /** @type {!Int8Array} */ HEAP8, /** @type {!Uint8Array} */ HEAPU8, /** @type {!Int16Array} */ HEAP16, /** @type {!Uint16Array} */ HEAPU16, /** @type {!Int32Array} */ HEAP32, /** @type {!Uint32Array} */ HEAPU32, /** @type {!Float32Array} */ HEAPF32, /** @type {!Float64Array} */ HEAPF64;
// functions called during shutdown
var __ATPOSTRUN__ = [];
// BigInt64Array type is not correctly defined in closure
var /** not-@type {!BigInt64Array} */ HEAP64, /* BigUint64Array type is not correctly defined in closure
/** not-@type {!BigUint64Array} */ HEAPU64;
// functions called after the main() is called
var runtimeInitialized = false;
function updateMemoryViews() {
var b = wasmMemory.buffer;
HEAP8 = new Int8Array(b);
HEAP16 = new Int16Array(b);
HEAPU8 = new Uint8Array(b);
HEAPU16 = new Uint16Array(b);
HEAP32 = new Int32Array(b);
HEAPU32 = new Uint32Array(b);
HEAPF32 = new Float32Array(b);
HEAPF64 = new Float64Array(b);
HEAP64 = new BigInt64Array(b);
HEAPU64 = new BigUint64Array(b);
}
// include: memoryprofiler.js
// end include: memoryprofiler.js
// end include: runtime_common.js
function preRun() {
if (Module["preRun"]) {
if (typeof Module["preRun"] == "function") Module["preRun"] = [ Module["preRun"] ];
@ -266,78 +224,28 @@ function preRun() {
addOnPreRun(Module["preRun"].shift());
}
}
callRuntimeCallbacks(__ATPRERUN__);
// Begin ATPRERUNS hooks
callRuntimeCallbacks(onPreRuns);
}
function initRuntime() {
runtimeInitialized = true;
callRuntimeCallbacks(__ATINIT__);
// No ATINITS hooks
wasmExports["__wasm_call_ctors"]();
}
function preMain() {
callRuntimeCallbacks(__ATMAIN__);
}
function preMain() {}
function postRun() {
// PThreads reuse the runtime from the main thread.
if (Module["postRun"]) {
if (typeof Module["postRun"] == "function") Module["postRun"] = [ Module["postRun"] ];
while (Module["postRun"].length) {
addOnPostRun(Module["postRun"].shift());
}
}
callRuntimeCallbacks(__ATPOSTRUN__);
}
function addOnPreRun(cb) {
__ATPRERUN__.unshift(cb);
}
function addOnInit(cb) {
__ATINIT__.unshift(cb);
}
function addOnPostRun(cb) {
__ATPOSTRUN__.unshift(cb);
}
// include: runtime_math.js
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc
// end include: runtime_math.js
// A counter of dependencies for calling run(). If we need to
// do asynchronous work before running, increment this and
// decrement it. Incrementing must happen in a place like
// Module.preRun (used by emcc to add file preloading).
// Note that you can add dependencies in preRun, even though
// it happens right before run - run will be postponed until
// the dependencies are met.
var runDependencies = 0;
var runDependencyWatcher = null;
var dependenciesFulfilled = null;
function addRunDependency(id) {
runDependencies++;
Module["monitorRunDependencies"]?.(runDependencies);
}
function removeRunDependency(id) {
runDependencies--;
Module["monitorRunDependencies"]?.(runDependencies);
if (runDependencies == 0) {
if (runDependencyWatcher !== null) {
clearInterval(runDependencyWatcher);
runDependencyWatcher = null;
}
if (dependenciesFulfilled) {
var callback = dependenciesFulfilled;
dependenciesFulfilled = null;
callback();
}
}
// Begin ATPOSTRUNS hooks
callRuntimeCallbacks(onPostRuns);
}
/** @param {string|number=} what */ function abort(what) {
@ -361,42 +269,19 @@ function removeRunDependency(id) {
// though it can.
// TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed.
/** @suppress {checkTypes} */ var e = new WebAssembly.RuntimeError(what);
readyPromiseReject(e);
readyPromiseReject?.(e);
// Throw the error whether or not MODULARIZE is set because abort is used
// in code paths apart from instantiation where an exception is expected
// to be thrown when abort is called.
throw e;
}
// include: memoryprofiler.js
// end include: memoryprofiler.js
// include: URIUtils.js
// Prefix of data URIs emitted by SINGLE_FILE and related options.
var dataURIPrefix = "data:application/octet-stream;base64,";
/**
* Indicates whether filename is a base64 data URI.
* @noinline
*/ var isDataURI = filename => filename.startsWith(dataURIPrefix);
/**
* Indicates whether filename is delivered via file protocol (as opposed to http/https)
* @noinline
*/ var isFileURI = filename => filename.startsWith("file://");
// end include: URIUtils.js
// include: runtime_exceptions.js
// end include: runtime_exceptions.js
function findWasmBinary() {
var f = "HashSet.wasm";
if (!isDataURI(f)) {
return locateFile(f);
}
return f;
}
var wasmBinaryFile;
function findWasmBinary() {
return locateFile("HashSet.wasm");
}
function getBinarySync(file) {
if (file == wasmBinaryFile && wasmBinary) {
return new Uint8Array(wasmBinary);
@ -404,53 +289,51 @@ function getBinarySync(file) {
if (readBinary) {
return readBinary(file);
}
// Throwing a plain string here, even though it not normally adviables since
// this gets turning into an `abort` in instantiateArrayBuffer.
throw "both async and sync fetching of the wasm failed";
}
function getBinaryPromise(binaryFile) {
async function getWasmBinary(binaryFile) {
// If we don't have the binary yet, load it asynchronously using readAsync.
if (!wasmBinary) {
// Fetch the binary using readAsync
return readAsync(binaryFile).then(response => new Uint8Array(/** @type{!ArrayBuffer} */ (response)), // Fall back to getBinarySync if readAsync fails
() => getBinarySync(binaryFile));
try {
var response = await readAsync(binaryFile);
return new Uint8Array(response);
} catch {}
}
// Otherwise, getBinarySync should be able to get it synchronously
return Promise.resolve().then(() => getBinarySync(binaryFile));
return getBinarySync(binaryFile);
}
function instantiateArrayBuffer(binaryFile, imports, receiver) {
return getBinaryPromise(binaryFile).then(binary => WebAssembly.instantiate(binary, imports)).then(receiver, reason => {
async function instantiateArrayBuffer(binaryFile, imports) {
try {
var binary = await getWasmBinary(binaryFile);
var instance = await WebAssembly.instantiate(binary, imports);
return instance;
} catch (reason) {
err(`failed to asynchronously prepare wasm: ${reason}`);
abort(reason);
});
}
}
function instantiateAsync(binary, binaryFile, imports, callback) {
if (!binary && typeof WebAssembly.instantiateStreaming == "function" && !isDataURI(binaryFile) && // Don't use streaming for file:// delivered objects in a webview, fetch them synchronously.
!isFileURI(binaryFile) && // Avoid instantiateStreaming() on Node.js environment for now, as while
// Node.js v18.1.0 implements it, it does not have a full fetch()
// implementation yet.
// Reference:
// https://github.com/emscripten-core/emscripten/pull/16917
!ENVIRONMENT_IS_NODE && typeof fetch == "function") {
return fetch(binaryFile, {
credentials: "same-origin"
}).then(response => {
// Suppress closure warning here since the upstream definition for
// instantiateStreaming only allows Promise<Repsponse> rather than
// an actual Response.
// TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure is fixed.
/** @suppress {checkTypes} */ var result = WebAssembly.instantiateStreaming(response, imports);
return result.then(callback, function(reason) {
// We expect the most common failure cause to be a bad MIME type for the binary,
// in which case falling back to ArrayBuffer instantiation should work.
err(`wasm streaming compile failed: ${reason}`);
err("falling back to ArrayBuffer instantiation");
return instantiateArrayBuffer(binaryFile, imports, callback);
async function instantiateAsync(binary, binaryFile, imports) {
if (!binary && !isFileURI(binaryFile) && !ENVIRONMENT_IS_NODE) {
try {
var response = fetch(binaryFile, {
credentials: "same-origin"
});
});
var instantiationResult = await WebAssembly.instantiateStreaming(response, imports);
return instantiationResult;
} catch (reason) {
// We expect the most common failure cause to be a bad MIME type for the binary,
// in which case falling back to ArrayBuffer instantiation should work.
err(`wasm streaming compile failed: ${reason}`);
err("falling back to ArrayBuffer instantiation");
}
}
return instantiateArrayBuffer(binaryFile, imports, callback);
return instantiateArrayBuffer(binaryFile, imports);
}
function getWasmImports() {
@ -463,7 +346,7 @@ function getWasmImports() {
// Create the wasm instance.
// Receives the wasm imports, returns the exports.
function createWasm() {
async function createWasm() {
// Load the wasm module and create an instance of using native support in the JS engine.
// handle a generated wasm instance, receiving its exports and
// performing other necessary setup
@ -471,19 +354,16 @@ function createWasm() {
wasmExports = instance.exports;
wasmMemory = wasmExports["memory"];
updateMemoryViews();
addOnInit(wasmExports["__wasm_call_ctors"]);
removeRunDependency("wasm-instantiate");
assignWasmExports(wasmExports);
return wasmExports;
}
// wait for the pthread pool (if any)
addRunDependency("wasm-instantiate");
// Prefer streaming instantiation if available.
function receiveInstantiationResult(result) {
// 'result' is a ResultObject object which has both the module and instance.
// receiveInstance() will swap in the exports (to Module.asm) so they can be called
// TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line.
// When the regression is fixed, can restore the above PTHREADS-enabled path.
receiveInstance(result["instance"]);
return receiveInstance(result["instance"]);
}
var info = getWasmImports();
// User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback
@ -493,24 +373,20 @@ function createWasm() {
// Also pthreads and wasm workers initialize the wasm instance through this
// path.
if (Module["instantiateWasm"]) {
try {
return Module["instantiateWasm"](info, receiveInstance);
} catch (e) {
err(`Module.instantiateWasm callback failed with error: ${e}`);
// If instantiation fails, reject the module ready promise.
readyPromiseReject(e);
}
return new Promise((resolve, reject) => {
Module["instantiateWasm"](info, (mod, inst) => {
resolve(receiveInstance(mod, inst));
});
});
}
wasmBinaryFile ??= findWasmBinary();
// If instantiation fails, reject the module ready promise.
instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult).catch(readyPromiseReject);
return {};
var result = await instantiateAsync(wasmBinary, wasmBinaryFile, info);
var exports = receiveInstantiationResult(result);
return exports;
}
// include: runtime_debug.js
// end include: runtime_debug.js
// === Body ===
// end include: preamble.js
// Begin JS library code
class ExitStatus {
name="ExitStatus";
constructor(status) {
@ -526,12 +402,18 @@ var callRuntimeCallbacks = callbacks => {
}
};
var noExitRuntime = Module["noExitRuntime"] || true;
var onPostRuns = [];
var addOnPostRun = cb => onPostRuns.push(cb);
var onPreRuns = [];
var addOnPreRun = cb => onPreRuns.push(cb);
var noExitRuntime = true;
var __abort_js = () => abort("");
var __emscripten_memcpy_js = (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num);
var _emscripten_date_now = () => Date.now();
var abortOnCannotGrowMemory = requestedSize => {
@ -547,10 +429,14 @@ var _emscripten_resize_heap = requestedSize => {
var _fd_close = fd => 52;
var convertI32PairToI53Checked = (lo, hi) => ((hi + 2097152) >>> 0 < 4194305 - !!lo) ? (lo >>> 0) + hi * 4294967296 : NaN;
var INT53_MAX = 9007199254740992;
function _fd_seek(fd, offset_low, offset_high, whence, newOffset) {
var offset = convertI32PairToI53Checked(offset_low, offset_high);
var INT53_MIN = -9007199254740992;
var bigintToI53Checked = num => (num < INT53_MIN || num > INT53_MAX) ? NaN : Number(num);
function _fd_seek(fd, offset, whence, newOffset) {
offset = bigintToI53Checked(offset);
return 70;
}
@ -558,6 +444,17 @@ var printCharBuffers = [ null, [], [] ];
var UTF8Decoder = typeof TextDecoder != "undefined" ? new TextDecoder : undefined;
var findStringEnd = (heapOrArray, idx, maxBytesToRead, ignoreNul) => {
var maxIdx = idx + maxBytesToRead;
if (ignoreNul) return maxIdx;
// TextDecoder needs to know the byte length in advance, it doesn't stop on
// null terminator by itself.
// As a tiny code save trick, compare idx against maxIdx using a negation,
// so that maxBytesToRead=undefined/NaN means Infinity.
while (heapOrArray[idx] && !(idx >= maxIdx)) ++idx;
return idx;
};
/**
* Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given
* array that contains uint8 values, returns a copy of that string as a
@ -565,22 +462,15 @@ var UTF8Decoder = typeof TextDecoder != "undefined" ? new TextDecoder : undefine
* heapOrArray is either a regular array, or a JavaScript typed array view.
* @param {number=} idx
* @param {number=} maxBytesToRead
* @param {boolean=} ignoreNul - If true, the function will not stop on a NUL character.
* @return {string}
*/ var UTF8ArrayToString = (heapOrArray, idx = 0, maxBytesToRead = NaN) => {
var endIdx = idx + maxBytesToRead;
var endPtr = idx;
// TextDecoder needs to know the byte length in advance, it doesn't stop on
// null terminator by itself. Also, use the length info to avoid running tiny
// strings through TextDecoder, since .subarray() allocates garbage.
// (As a tiny code save trick, compare endPtr against endIdx using a negation,
// so that undefined/NaN means Infinity)
while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr;
*/ var UTF8ArrayToString = (heapOrArray, idx = 0, maxBytesToRead, ignoreNul) => {
var endPtr = findStringEnd(heapOrArray, idx, maxBytesToRead, ignoreNul);
// When using conditional TextDecoder, skip it for short strings as the overhead of the native call is not worth it.
if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));
}
var str = "";
// If building with TextDecoder, we have already computed the string length
// above, so test loop end condition against that
while (idx < endPtr) {
// For UTF8 byte structure, see:
// http://en.wikipedia.org/wiki/UTF-8#Description
@ -631,12 +521,10 @@ var printChar = (stream, curr) => {
* maximum number of bytes to read. You can omit this parameter to scan the
* string until the first 0 byte. If maxBytesToRead is passed, and the string
* at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the
* string will cut short at that byte index (i.e. maxBytesToRead will not
* produce a string of exact length [ptr, ptr+maxBytesToRead[) N.B. mixing
* frequent uses of UTF8ToString() with and without maxBytesToRead may throw
* JS JIT optimizations off, so it is worth to consider consistently using one
* string will cut short at that byte index.
* @param {boolean=} ignoreNul - If true, the function will not stop on a NUL character.
* @return {string}
*/ var UTF8ToString = (ptr, maxBytesToRead) => ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : "";
*/ var UTF8ToString = (ptr, maxBytesToRead, ignoreNul) => ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead, ignoreNul) : "";
var _fd_write = (fd, iov, iovcnt, pnum) => {
// hack to support printf in SYSCALLS_REQUIRE_FILESYSTEM=0
@ -715,19 +603,10 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
var endIdx = outIdx + maxBytesToWrite - 1;
// -1 for string null terminator.
for (var i = 0; i < str.length; ++i) {
// Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code
// unit, not a Unicode code point of the character! So decode
// UTF16->UTF32->UTF8.
// See http://unicode.org/faq/utf_bom.html#utf16-3
// For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description
// and https://www.ietf.org/rfc/rfc2279.txt
// and https://tools.ietf.org/html/rfc3629
var u = str.charCodeAt(i);
// possibly a lead surrogate
if (u >= 55296 && u <= 57343) {
var u1 = str.charCodeAt(++i);
u = 65536 + ((u & 1023) << 10) | (u1 & 1023);
}
var u = str.codePointAt(i);
if (u <= 127) {
if (outIdx >= endIdx) break;
heap[outIdx++] = u;
@ -746,6 +625,9 @@ var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
heap[outIdx++] = 128 | ((u >> 12) & 63);
heap[outIdx++] = 128 | ((u >> 6) & 63);
heap[outIdx++] = 128 | (u & 63);
// Gotcha: if codePoint is over 0xFFFF, it is represented as a surrogate pair in UTF-16.
// We need to manually skip over the second code unit for correct iteration.
i++;
}
}
// Null-terminate the pointer to the buffer.
@ -764,9 +646,44 @@ var stringToUTF8OnStack = str => {
return ret;
};
// End JS library code
// include: postlibrary.js
// This file is included after the automatically-generated JS library code
// but before the wasm module is created.
{
// Begin ATMODULES hooks
if (Module["noExitRuntime"]) noExitRuntime = Module["noExitRuntime"];
if (Module["print"]) out = Module["print"];
if (Module["printErr"]) err = Module["printErr"];
if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"];
// End ATMODULES hooks
if (Module["arguments"]) arguments_ = Module["arguments"];
if (Module["thisProgram"]) thisProgram = Module["thisProgram"];
if (Module["preInit"]) {
if (typeof Module["preInit"] == "function") Module["preInit"] = [ Module["preInit"] ];
while (Module["preInit"].length > 0) {
Module["preInit"].shift()();
}
}
}
// Begin runtime exports
// End runtime exports
// Begin JS library exports
// End JS library exports
// end include: postlibrary.js
// Imports from the Wasm binary.
var _main, __emscripten_stack_restore, __emscripten_stack_alloc, _emscripten_stack_get_current;
function assignWasmExports(wasmExports) {
Module["_main"] = _main = wasmExports["__main_argc_argv"];
__emscripten_stack_restore = wasmExports["_emscripten_stack_restore"];
__emscripten_stack_alloc = wasmExports["_emscripten_stack_alloc"];
_emscripten_stack_get_current = wasmExports["emscripten_stack_get_current"];
}
var wasmImports = {
/** @export */ _abort_js: __abort_js,
/** @export */ _emscripten_memcpy_js: __emscripten_memcpy_js,
/** @export */ emscripten_date_now: _emscripten_date_now,
/** @export */ emscripten_resize_heap: _emscripten_resize_heap,
/** @export */ fd_close: _fd_close,
@ -774,31 +691,8 @@ var wasmImports = {
/** @export */ fd_write: _fd_write
};
var wasmExports = createWasm();
var ___wasm_call_ctors = () => (___wasm_call_ctors = wasmExports["__wasm_call_ctors"])();
var _main = Module["_main"] = (a0, a1) => (_main = Module["_main"] = wasmExports["__main_argc_argv"])(a0, a1);
var __emscripten_stack_restore = a0 => (__emscripten_stack_restore = wasmExports["_emscripten_stack_restore"])(a0);
var __emscripten_stack_alloc = a0 => (__emscripten_stack_alloc = wasmExports["_emscripten_stack_alloc"])(a0);
var _emscripten_stack_get_current = () => (_emscripten_stack_get_current = wasmExports["emscripten_stack_get_current"])();
var dynCall_jiji = Module["dynCall_jiji"] = (a0, a1, a2, a3, a4) => (dynCall_jiji = Module["dynCall_jiji"] = wasmExports["dynCall_jiji"])(a0, a1, a2, a3, a4);
// include: postamble.js
// === Auto-generated postamble setup entry stuff ===
var calledRun;
dependenciesFulfilled = function runCaller() {
// If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false)
if (!calledRun) run();
if (!calledRun) dependenciesFulfilled = runCaller;
};
// try this again later, after new deps are fulfilled
function callMain(args = []) {
var entryFunction = _main;
args.unshift(thisProgram);
@ -821,26 +715,18 @@ function callMain(args = []) {
}
function run(args = arguments_) {
if (runDependencies > 0) {
return;
}
preRun();
// a preRun added a dependency, run will be called later
if (runDependencies > 0) {
return;
}
function doRun() {
// run may have just been called through dependencies being fulfilled just in this very frame,
// or while the async setStatus time below was happening
if (calledRun) return;
calledRun = true;
Module["calledRun"] = true;
if (ABORT) return;
initRuntime();
preMain();
readyPromiseResolve(Module);
readyPromiseResolve?.(Module);
Module["onRuntimeInitialized"]?.();
if (shouldRunNow) callMain(args);
var noInitialRun = Module["noInitialRun"] || false;
if (!noInitialRun) callMain(args);
postRun();
}
if (Module["setStatus"]) {
@ -854,17 +740,11 @@ function run(args = arguments_) {
}
}
if (Module["preInit"]) {
if (typeof Module["preInit"] == "function") Module["preInit"] = [ Module["preInit"] ];
while (Module["preInit"].length > 0) {
Module["preInit"].pop()();
}
}
var wasmExports;
// shouldRunNow refers to calling main(), not run().
var shouldRunNow = true;
if (Module["noInitialRun"]) shouldRunNow = false;
// In modularize mode the generated code is within a factory function so we
// can use await here (since it's not top-level-await).
wasmExports = await (createWasm());
run();
@ -874,14 +754,27 @@ run();
// and return either the Module itself, or a promise of the module.
// We assign to the `moduleRtn` global here and configure closure to see
// this as and extern so it won't get minified.
moduleRtn = readyPromise;
return moduleRtn;
if (runtimeInitialized) {
moduleRtn = Module;
} else {
// Set up the promise that indicates the Module is initialized
moduleRtn = new Promise((resolve, reject) => {
readyPromiseResolve = resolve;
readyPromiseReject = reject;
});
}
);
return moduleRtn;
};
})();
if (typeof exports === 'object' && typeof module === 'object')
// Export using a UMD style export, or ES6 exports if selected
if (typeof exports === 'object' && typeof module === 'object') {
module.exports = setupModule;
else if (typeof define === 'function' && define['amd'])
// This default export looks redundant, but it allows TS to import this
// commonjs style module.
module.exports.default = setupModule;
} else if (typeof define === 'function' && define['amd'])
define([], () => setupModule);

View file

@ -2,42 +2,40 @@
1:emscripten_date_now
2:__wasi_fd_close
3:__wasi_fd_write
4:_emscripten_memcpy_js
4:__wasi_fd_seek
5:emscripten_resize_heap
6:legalimport$__wasi_fd_seek
7:__wasm_call_ctors
8:WTF::HashTable<JSC::DFG::Node*\2c\20JSC::DFG::Node*\2c\20WTF::IdentityExtractor\2c\20WTF::PtrHash<JSC::DFG::Node*>\2c\20WTF::HashTraits<JSC::DFG::Node*>\2c\20WTF::HashTraits<JSC::DFG::Node*>>::add\28JSC::DFG::Node*&&\29
9:WTF::HashTable<unsigned\20int\2c\20unsigned\20int\2c\20WTF::IdentityExtractor\2c\20WTF::IntHash<unsigned\20int>\2c\20WTF::UnsignedWithZeroKeyHashTraits<unsigned\20int>\2c\20WTF::UnsignedWithZeroKeyHashTraits<unsigned\20int>>::add\28unsigned\20int&&\29
10:main
11:WTF::HashTable<JSC::DFG::Node*\2c\20JSC::DFG::Node*\2c\20WTF::IdentityExtractor\2c\20WTF::PtrHash<JSC::DFG::Node*>\2c\20WTF::HashTraits<JSC::DFG::Node*>\2c\20WTF::HashTraits<JSC::DFG::Node*>>::rehash\28unsigned\20int\2c\20JSC::DFG::Node**\29
12:WTF::HashTable<unsigned\20int\2c\20unsigned\20int\2c\20WTF::IdentityExtractor\2c\20WTF::IntHash<unsigned\20int>\2c\20WTF::UnsignedWithZeroKeyHashTraits<unsigned\20int>\2c\20WTF::UnsignedWithZeroKeyHashTraits<unsigned\20int>>::rehash\28unsigned\20int\2c\20unsigned\20int*\29
13:abort
14:__memset
15:__gettimeofday
16:fiprintf
17:__stdio_close
18:__stdio_write
19:__stdio_seek
20:__emscripten_stdout_close
21:__emscripten_stdout_seek
22:__towrite
23:frexp
24:__vfprintf_internal
25:printf_core
26:out
27:getint
28:pop_arg
29:fmt_u
30:pad
31:fmt_fp
32:__wasi_syscall_ret
33:wctomb
34:emscripten_builtin_malloc
35:emscripten_builtin_free
36:emscripten_builtin_calloc
37:sbrk
38:operator\20new\28unsigned\20long\29
39:_emscripten_stack_restore
40:_emscripten_stack_alloc
41:emscripten_stack_get_current
42:legalstub$dynCall_jiji
6:__wasm_call_ctors
7:WTF::HashTable<JSC::DFG::Node*, JSC::DFG::Node*, WTF::IdentityExtractor, WTF::PtrHash<JSC::DFG::Node*>, WTF::HashTraits<JSC::DFG::Node*>, WTF::HashTraits<JSC::DFG::Node*>>::add(JSC::DFG::Node*&&)
8:WTF::HashTable<unsigned int, unsigned int, WTF::IdentityExtractor, WTF::IntHash<unsigned int>, WTF::UnsignedWithZeroKeyHashTraits<unsigned int>, WTF::UnsignedWithZeroKeyHashTraits<unsigned int>>::add(unsigned int&&)
9:main
10:WTF::HashTable<JSC::DFG::Node*, JSC::DFG::Node*, WTF::IdentityExtractor, WTF::PtrHash<JSC::DFG::Node*>, WTF::HashTraits<JSC::DFG::Node*>, WTF::HashTraits<JSC::DFG::Node*>>::rehash(unsigned int, JSC::DFG::Node**)
11:WTF::HashTable<unsigned int, unsigned int, WTF::IdentityExtractor, WTF::IntHash<unsigned int>, WTF::UnsignedWithZeroKeyHashTraits<unsigned int>, WTF::UnsignedWithZeroKeyHashTraits<unsigned int>>::rehash(unsigned int, unsigned int*)
12:abort
13:__gettimeofday
14:fiprintf
15:__stdio_close
16:__stdio_write
17:__stdio_seek
18:__emscripten_stdout_close
19:__emscripten_stdout_seek
20:__towrite
21:frexp
22:__memset
23:__vfprintf_internal
24:printf_core
25:out
26:getint
27:pop_arg
28:fmt_u
29:pad
30:fmt_fp
31:__wasi_syscall_ret
32:wctomb
33:emscripten_builtin_malloc
34:emscripten_builtin_free
35:emscripten_builtin_calloc
36:sbrk
37:operator new(unsigned long)
38:_emscripten_stack_restore
39:_emscripten_stack_alloc
40:emscripten_stack_get_current

Binary file not shown.

View file

@ -1,5 +1,5 @@
Built on 2025-02-11T16:03:39Z
Built on 2025-09-11T20:06:12Z
Toolchain versions
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 4.0.0-git
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 4.0.0 (97c7c2adab1791b9487d1f376934a3bdc28f8a67)
Building...
Building done

View file

@ -39,5 +39,7 @@ emcc -o build/argon2.js \
-Iinclude \
${SOURCES[@]} | tee -a "$BUILD_LOG"
node ../../utils/compress.mjs build/argon2.wasm
echo "Building done" | tee -a "$BUILD_LOG"
ls -lth build/

Binary file not shown.

BIN
wasm/argon2/build/argon2.wasm.z Executable file

Binary file not shown.

43
wasm/zlib/shell.js Normal file
View file

@ -0,0 +1,43 @@
// zlib-based utility for use in shells where CompressionStream and
// DecompressionStream are not available.
function module() {
"use strict";
let zlibPromise = null;
let zlibModule = null;
async function initialize() {
if (zlibPromise) {
zlibModule = await zlibPromise;
return zlibModule;
}
load('wasm/zlib/build/zlib.js');
zlibPromise = setupModule({
wasmBinary: new Int8Array(read('wasm/zlib/build/zlib.wasm', "binary")),
});
zlibModule = await zlibPromise;
return zlibModule;
}
function decompress(bytes) {
zlibModule.FS.writeFile('in', bytes);
const inputzStr = zlibModule.stringToNewUTF8('in');
const inputzoutStr = zlibModule.stringToNewUTF8('out');
if (zlibModule._decompressFile(inputzStr, inputzoutStr) !== 0) {
throw new Error();
}
const output = zlibModule.FS.readFile('out');
zlibModule._free(inputzStr);
zlibModule._free(inputzoutStr);
return output;
}
return {
initialize: initialize,
decompress: decompress,
};
}
globalThis.zlib = module();

View file

@ -39,7 +39,15 @@ class Benchmark {
const loadPromises = Object.entries(preload).map(
async ([name, url]) => {
if (name.endsWith(".wasm")) {
this.files[name] = (await JetStream.getBinary(url)).buffer;
const buffer = (await JetStream.getBinary(url)).buffer;
if (!(buffer instanceof ArrayBuffer)) {
// The returned array buffer is from a different global when
// prefetching resources and running in the shell. This is fine,
// except for the source map code doing an instanceof
// check that fails for the prototype being in a different realm.
Object.setPrototypeOf(buffer, ArrayBuffer.prototype);
}
this.files[name] = buffer;
} else {
this.files[name] = await JetStream.getString(url);
}