From 17ef371dcf198494af8da8ff91a947e316791662 Mon Sep 17 00:00:00 2001
From: Cheng Shao <terrorjack@type.dance>
Date: Sun, 16 Mar 2025 17:50:22 +0000
Subject: [PATCH] wasm: use console.assert in dyld script

This commit uses console.assert() instead of node-specific strict
assert in the dyld script, in order to make it runnable in the
browser. console.assert() only warns and doesn't crash upon assertion
failure, but this is fine; we can always trivially define a strict
assert function shall it be necessary when debugging, and there hasn't
been such an assertion failure seen in the wild for long enough.

(cherry picked from commit 27bb73c6a53fec758f20a62d5d3d4db0135e4a68)
---
 utils/jsffi/dyld.mjs | 26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/utils/jsffi/dyld.mjs b/utils/jsffi/dyld.mjs
index a3cc7a5dcce..2ec1958cfad 100755
--- a/utils/jsffi/dyld.mjs
+++ b/utils/jsffi/dyld.mjs
@@ -89,7 +89,6 @@
 // -opti GHC flag to pass process arguments, like RTS flags or -opti-v
 // to dump the iserv messages.
 
-import assert from "node:assert/strict";
 import fs from "node:fs";
 import path from "node:path";
 import stream from "node:stream";
@@ -112,7 +111,7 @@ class Parser {
 
   skip(len) {
     this.#offset += len;
-    assert(this.#offset <= this.#buf.length);
+    console.assert(this.#offset <= this.#buf.length);
   }
 
   readUInt8() {
@@ -139,7 +138,7 @@ class Parser {
     const len = this.readULEB128();
     const r = this.#buf.subarray(this.#offset, this.#offset + len);
     this.#offset += len;
-    assert(this.#offset <= this.#buf.length);
+    console.assert(this.#offset <= this.#buf.length);
     return r;
   }
 
@@ -154,10 +153,10 @@ function parseDyLink0(buf) {
   // magic, version
   p0.skip(8);
   // section id
-  assert(p0.readUInt8() === 0);
+  console.assert(p0.readUInt8() === 0);
   const p1 = new Parser(p0.readBuffer());
   // custom section name
-  assert(p1.readString() === "dylink.0");
+  console.assert(p1.readString() === "dylink.0");
 
   const r = { neededSos: [], exportInfo: [], importInfo: [] };
   while (!p1.eof()) {
@@ -356,7 +355,10 @@ class DyLD {
         })
       )
     ).find(({ status }) => status === "fulfilled");
-    assert(r, `findSystemLibrary(${f}): not found in ${[...this.#rpaths]}`);
+    console.assert(
+      r,
+      `findSystemLibrary(${f}): not found in ${[...this.#rpaths]}`
+    );
     return r.value;
   }
 
@@ -441,7 +443,7 @@ class DyLD {
       // __memory_base & __table_base, different for each .so
       let memory_base;
       let table_base = this.#table.grow(tableSize);
-      assert(tableP2Align === 0);
+      console.assert(tableP2Align === 0);
 
       // libc.so is always the first one to be ever loaded and has VIP
       // treatment. It will never be unloaded even if we support
@@ -453,7 +455,7 @@ class DyLD {
         // __heap_base/__heap_end so that dlmalloc can initialize
         // global state. wasm-ld aligns __heap_base to page sized so
         // we follow suit.
-        assert(memP2Align <= Math.log2(DyLD.#pageSize));
+        console.assert(memP2Align <= Math.log2(DyLD.#pageSize));
         memory_base = DyLD.#pageSize;
         const data_pages = Math.ceil(memSize / DyLD.#pageSize);
         this.#memory.grow(data_pages + 1);
@@ -579,7 +581,7 @@ class DyLD {
         // Invariant: each function symbol can be defined only once.
         // This is incorrect for weak symbols which are allowed to
         // appear multiple times but this is sufficient in practice.
-        assert(
+        console.assert(
           !this.exportFuncs[k],
           `duplicate symbol ${k} when loading ${soname}`
         );
@@ -595,7 +597,7 @@ class DyLD {
           if (this.#gotFunc[k]) {
             // ghc-prim/ghc-internal may export functions imported by
             // rts
-            assert(this.#gotFunc[k].value === DyLD.#poison);
+            console.assert(this.#gotFunc[k].value === DyLD.#poison);
             this.#table.set(this.#gotFunc[k].value, v);
           }
           continue;
@@ -605,7 +607,7 @@ class DyLD {
         if (v instanceof WebAssembly.Global) {
           const addr = v.value + memory_base;
           if (this.#gotMem[k]) {
-            assert(this.#gotMem[k].value === DyLD.#poison);
+            console.assert(this.#gotMem[k].value === DyLD.#poison);
             this.#gotMem[k].value = addr;
           } else {
             this.#gotMem[k] = new WebAssembly.Global(
@@ -675,7 +677,7 @@ class DyLD {
     }
     // Not in GOT.func yet, create the entry on demand
     if (this.exportFuncs[sym]) {
-      assert(!this.#gotFunc[sym]);
+      console.assert(!this.#gotFunc[sym]);
       const addr = this.#table.grow(1, this.exportFuncs[sym]);
       this.#gotFunc[sym] = new WebAssembly.Global(
         { value: "i32", mutable: true },
-- 
GitLab