diff --git a/libraries/ghci/GHCi/ObjLink.hs b/libraries/ghci/GHCi/ObjLink.hs
index a7232f1ccbe8b0e6d1192bdff4cebf7a3a90eaf3..1875918a9210ea5ac126a810fe7266eb5e37ecc6 100644
--- a/libraries/ghci/GHCi/ObjLink.hs
+++ b/libraries/ghci/GHCi/ObjLink.hs
@@ -76,7 +76,7 @@ loadDLL f =
       evaluate =<< js_loadDLL (toJSString f)
       pure $ Right nullPtr
 
-foreign import javascript safe "__exports.__dyld.loadDLL($1)"
+foreign import javascript safe "__ghc_wasm_jsffi_dyld.loadDLL($1)"
   js_loadDLL :: JSString -> IO ()
 
 loadArchive :: String -> IO ()
@@ -96,7 +96,7 @@ lookupSymbol sym = do
   r <- js_lookupSymbol $ toJSString sym
   evaluate $ if r == nullPtr then Nothing else Just r
 
-foreign import javascript unsafe "__exports.__dyld.lookupSymbol($1)"
+foreign import javascript unsafe "__ghc_wasm_jsffi_dyld.lookupSymbol($1)"
   js_lookupSymbol :: JSString -> IO (Ptr a)
 
 lookupSymbolInDLL :: Ptr LoadedDLL -> String -> IO (Maybe (Ptr a))
@@ -114,7 +114,7 @@ addLibrarySearchPath p = do
   evaluate =<< js_addLibrarySearchPath (toJSString p)
   pure nullPtr
 
-foreign import javascript safe "__exports.__dyld.addLibrarySearchPath($1)"
+foreign import javascript safe "__ghc_wasm_jsffi_dyld.addLibrarySearchPath($1)"
   js_addLibrarySearchPath :: JSString -> IO ()
 
 removeLibrarySearchPath :: Ptr () -> IO Bool
@@ -128,7 +128,7 @@ findSystemLibrary f = m `catch` \(_ :: JSException) -> pure Nothing
       p <- evaluate $ fromJSString p'
       pure $ Just p
 
-foreign import javascript safe "__exports.__dyld.findSystemLibrary($1)"
+foreign import javascript safe "__ghc_wasm_jsffi_dyld.findSystemLibrary($1)"
   js_findSystemLibrary :: JSString -> IO JSString
 
 #else
diff --git a/testsuite/tests/th/wasm/all.T b/testsuite/tests/th/wasm/all.T
index 9bc4793eaa08b33c6390dc3dbd0d94800a106d7b..c02fa5ff366bafb5aa07c3831fff15c6ca21b7b8 100644
--- a/testsuite/tests/th/wasm/all.T
+++ b/testsuite/tests/th/wasm/all.T
@@ -2,4 +2,4 @@ setTestOpts([
   unless(arch('wasm32'), skip)
 ])
 
-test('T25473', [expect_broken(25473)], multimod_compile, ['T25473B', '-v0'])
+test('T25473', [], multimod_compile, ['T25473B', '-v0'])
diff --git a/utils/jsffi/dyld.mjs b/utils/jsffi/dyld.mjs
index 2f67a8e89e1b565086cc3ce017ecb20d154f4473..3c1c2106557af837d978f495343e2fe1e7acf8e3 100755
--- a/utils/jsffi/dyld.mjs
+++ b/utils/jsffi/dyld.mjs
@@ -293,9 +293,13 @@ class DyLD {
   #loadedSos = new Set();
 
   // Mapping from export names to export funcs. It's also passed as
-  // __exports in JSFFI code, hence the "memory" special field. __dyld
-  // is used by ghci to call into here.
-  exportFuncs = { memory: this.#memory, __dyld: this };
+  // __exports in JSFFI code, hence the "memory" special field.
+  exportFuncs = { memory: this.#memory };
+
+  // The FinalizationRegistry used by JSFFI.
+  #finalizationRegistry = new FinalizationRegistry((sp) =>
+    this.exportFuncs.rts_freeStablePtr(sp)
+  );
 
   // The GOT.func table.
   #gotFunc = {};
@@ -623,17 +627,22 @@ class DyLD {
 
       const mod = await modp;
 
-      // Fulfill the ghc_wasm_jsffi imports
+      // Fulfill the ghc_wasm_jsffi imports. Use new Function()
+      // instead of eval() to prevent bindings in this local scope to
+      // be accessed by JSFFI code snippets.
       Object.assign(
         import_obj.ghc_wasm_jsffi,
         new Function(
-          "return (__exports) => ({".concat(
+          "__exports",
+          "__ghc_wasm_jsffi_dyld",
+          "__ghc_wasm_jsffi_finalization_registry",
+          "return {".concat(
             ...parseSections(mod).map(
               (rec) => `${rec[0]}: ${parseRecord(rec)}, `
             ),
-            "});"
+            "};"
           )
-        )()(this.exportFuncs)
+        )(this.exportFuncs, this, this.#finalizationRegistry)
       );
 
       // Fulfill the rest of the imports