From f4c51138bf72af23e686d6b1777beef7660fb35c Mon Sep 17 00:00:00 2001
From: Cheng Shao <terrorjack@type.dance>
Date: Mon, 24 Feb 2025 14:01:21 +0000
Subject: [PATCH] wasm: make JSVal internal Weak# point to lifted JSVal

JSVal has an internal Weak# with the unlifted JSVal# object as key to
arrange its builtin finalization logic. The Weak# used to designate
Unit_closure as a dummy value; now this commit designates the lifted
JSVal closure as the Weak# value. This allows the implementation of
mkWeakJSVal which can be used to observe the liveliness of a JSVal and
attach a user-specified finalizer.

(cherry picked from commit 4f34243101684a0ad15f5986abec00c675b48955)
---
 libraries/ghc-internal/src/GHC/Internal/Wasm/Prim/Types.hs | 2 +-
 rts/wasm/JSFFI.c                                           | 5 +++--
 testsuite/tests/jsffi/jsffigc.hs                           | 2 +-
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/libraries/ghc-internal/src/GHC/Internal/Wasm/Prim/Types.hs b/libraries/ghc-internal/src/GHC/Internal/Wasm/Prim/Types.hs
index b2cc19b9f5e..46f5b6deac5 100644
--- a/libraries/ghc-internal/src/GHC/Internal/Wasm/Prim/Types.hs
+++ b/libraries/ghc-internal/src/GHC/Internal/Wasm/Prim/Types.hs
@@ -82,7 +82,7 @@ newtype JSVal#
   = JSVal# (Any :: UnliftedType)
 
 data JSVal
-  = forall a . JSVal JSVal# (Weak# JSVal#) (StablePtr# a)
+  = forall a . JSVal JSVal# (Weak# JSVal) (StablePtr# a)
 
 freeJSVal :: JSVal -> IO ()
 freeJSVal v@(JSVal _ w sp) = do
diff --git a/rts/wasm/JSFFI.c b/rts/wasm/JSFFI.c
index 56e260d9500..ba824200021 100644
--- a/rts/wasm/JSFFI.c
+++ b/rts/wasm/JSFFI.c
@@ -107,7 +107,6 @@ HaskellObj rts_mkJSVal(Capability *cap, HsJSVal v) {
   SET_HDR(w, &stg_WEAK_info, CCS_SYSTEM);
   w->cfinalizers = (StgClosure *)cfin;
   w->key = p;
-  w->value = Unit_closure;
   w->finalizer = &stg_NO_FINALIZER_closure;
   w->link = cap->weak_ptr_list_hd;
   cap->weak_ptr_list_hd = w;
@@ -120,7 +119,9 @@ HaskellObj rts_mkJSVal(Capability *cap, HsJSVal v) {
   box->payload[0] = p;
   box->payload[1] = (HaskellObj)w;
   box->payload[2] = NULL;
-  return TAG_CLOSURE(1, box);
+
+  w->value = TAG_CLOSURE(1, box);
+  return w->value;
 }
 
 __attribute__((import_module("ghc_wasm_jsffi"), import_name("getJSVal")))
diff --git a/testsuite/tests/jsffi/jsffigc.hs b/testsuite/tests/jsffi/jsffigc.hs
index a7427cad17c..f260e10f6eb 100644
--- a/testsuite/tests/jsffi/jsffigc.hs
+++ b/testsuite/tests/jsffi/jsffigc.hs
@@ -27,7 +27,7 @@ foreign export javascript "testDynExportFree sync"
 -- JSVal#. Do not use this in your own codebase since this is purely
 -- an implementation detail of JSVal and subject to change!
 jsvalWeak :: JSVal -> Weak JSVal
-jsvalWeak (JSVal _ w _) = Weak $ unsafeCoerce# Weak w
+jsvalWeak (JSVal _ w _) = Weak w
 
 probeWeak :: Weak v -> IO ()
 probeWeak wk = print =<< isJust <$> deRefWeak wk
-- 
GitLab