From b18fbf52f98d0128c52b3a90ddca727a6d5d4d45 Mon Sep 17 00:00:00 2001
From: Josh Meredith <joshmeredith2008@gmail.com>
Date: Thu, 1 Dec 2022 11:01:57 +0000
Subject: [PATCH] Update JavaScript fileStat to match Emscripten layout

---
 libraries/base/jsbits/base.js            | 77 ++++++++++++++++++------
 testsuite/tests/callarity/unittest/all.T |  2 +-
 testsuite/tests/corelint/all.T           |  2 +-
 testsuite/tests/ghc-api/all.T            |  6 +-
 4 files changed, 65 insertions(+), 22 deletions(-)

diff --git a/libraries/base/jsbits/base.js b/libraries/base/jsbits/base.js
index dd491bac00ab..1a2dc3495a44 100644
--- a/libraries/base/jsbits/base.js
+++ b/libraries/base/jsbits/base.js
@@ -452,48 +452,91 @@ function h$base_c_s_isfifo(mode) {
 }
 
 #ifndef GHCJS_BROWSER
+// The `fileStat` is filled according to the layout of Emscripten's `stat`
+// struct - defined in stat.h. We must use this layout due to this header
+// file being used to retrieve the offsets for hsc files that peek into
+// memory locations of structs directly. For more information see:
+// https://gitlab.haskell.org/ghc/ghc/-/issues/22573
 function h$base_fillStat(fs, b, off) {
     if(off%4) throw "h$base_fillStat: not aligned";
     var o = off>>2;
-    b.i3[o+0] = fs.mode;
+
+    b.i3[o+0] = fs.dev;
+    b.i3[o+1] = 0; // __st_dev_padding;
+    b.i3[o+2] = 0; // __st_ino_truncated;
+    b.i3[o+3] = fs.mode;
+    h$long_from_number(fs.nlink, (h,l) => {
+      b.i3[o+4] = h;
+      b.i3[o+5] = l;
+    });
+    b.i3[o+6] = fs.uid;
+    b.i3[o+7] = fs.gid;
+    b.i3[o+8] = fs.rdev;
+    b.i3[o+9] = 0; // __st_rdev_padding;
     h$long_from_number(fs.size, (h,l) => {
-      b.i3[o+1] = h;
-      b.i3[o+2] = l;
+      b.i3[o+10] = h;
+      b.i3[o+11] = l;
+    });
+    b.i3[o+12] = fs.blksize;
+    b.i3[o+13] = fs.blocks;
+    atimeS = Math.floor(fs.atimeMs/1000);
+    h$long_from_number(atimeS, (h,l) => {
+      b.i3[o+14] = h;
+      b.i3[o+15] = l;
+    });
+    atimeNs = (fs.atimeMs/1000 - atimeS) * 1000000000;
+    h$long_from_number(atimeNs, (h,l) => {
+      b.i3[o+16] = h;
+      b.i3[o+17] = l;
+    });
+    mtimeS = Math.floor(fs.mtimeMs/1000);
+    h$long_from_number(mtimeS, (h,l) => {
+      b.i3[o+18] = h;
+      b.i3[o+19] = l;
+    });
+    mtimeNs = (fs.mtimeMs/1000 - mtimeS) * 1000000000;
+    h$long_from_number(mtimeNs, (h,l) => {
+      b.i3[o+20] = h;
+      b.i3[o+21] = l;
+    });
+    ctimeS = Math.floor(fs.ctimeMs/1000);
+    h$long_from_number(ctimeS, (h,l) => {
+      b.i3[o+22] = h;
+      b.i3[o+23] = l;
+    });
+    ctimeNs = (fs.ctimeMs/1000 - ctimeS) * 1000000000;
+    h$long_from_number(ctimeNs, (h,l) => {
+      b.i3[o+24] = h;
+      b.i3[o+25] = l;
     });
-
-    b.i3[o+3] = 0; // fixme
-    b.i3[o+4] = 0; // fixme
-    b.i3[o+5] = fs.dev;
     h$long_from_number(fs.ino, (h,l) => {
-      b.i3[o+6] = h;
-      b.i3[o+7] = l;
+      b.i3[o+26] = h;
+      b.i3[o+27] = l;
     });
-    b.i3[o+8] = fs.uid;
-    b.i3[o+9] = fs.gid;
 }
 #endif
 
 // [mode,size1,size2,mtime1,mtime2,dev,ino1,ino2,uid,gid] all 32 bit
-/** @const */ var h$base_sizeof_stat = 40;
+/** @const */ var h$base_sizeof_stat = 112;
 
 function h$base_st_mtime(stat, stat_off) {
-    RETURN_UBX_TUP2(stat.i3[(stat_off>>2)+3], stat.i3[(stat_off>>2)+4]);
+    RETURN_UBX_TUP2(stat.i3[(stat_off>>2)+18], stat.i3[(stat_off>>2)+19]);
 }
 
 function h$base_st_size(stat, stat_off) {
-    RETURN_UBX_TUP2(stat.i3[(stat_off>>2)+1], stat.i3[(stat_off>>2)+2]);
+    RETURN_UBX_TUP2(stat.i3[(stat_off>>2)+10], stat.i3[(stat_off>>2)+11]);
 }
 
 function h$base_st_mode(stat, stat_off) {
-    return stat.i3[stat_off>>2];
+    return stat.i3[(stat_off>>2)+3];
 }
 
 function h$base_st_dev(stat, stat_off) {
-    return stat.i3[(stat_off>>2)+5];
+    return stat.i3[(stat_off>>2)+0];
 }
 
 function h$base_st_ino(stat, stat_off) {
-    RETURN_UBX_TUP2(stat.i3[(stat_off>>2)+6], stat.i3[(stat_off>>2)+7]);
+    RETURN_UBX_TUP2(stat.i3[(stat_off>>2)+26], stat.i3[(stat_off>>2)+27]);
 }
 
 /** @const */ var h$base_echo            = 1;
diff --git a/testsuite/tests/callarity/unittest/all.T b/testsuite/tests/callarity/unittest/all.T
index bbdff0d67665..e39c1d7597e2 100644
--- a/testsuite/tests/callarity/unittest/all.T
+++ b/testsuite/tests/callarity/unittest/all.T
@@ -5,4 +5,4 @@ setTestOpts(f)
 setTestOpts(extra_hc_opts('-package ghc'))
 setTestOpts(extra_run_opts('"' + config.libdir + '"'))
 
-test('CallArity1', js_broken(22362), compile_and_run, [''])
+test('CallArity1', normal, compile_and_run, [''])
diff --git a/testsuite/tests/corelint/all.T b/testsuite/tests/corelint/all.T
index 43c2cdd8f477..4271974c83fd 100644
--- a/testsuite/tests/corelint/all.T
+++ b/testsuite/tests/corelint/all.T
@@ -7,6 +7,6 @@ test('T21152', normal, compile, ['-g3'])
 setTestOpts(extra_hc_opts('-package ghc'))
 setTestOpts(extra_run_opts('"' + config.libdir + '"'))
 
-test('LintEtaExpand', js_broken(22362), compile_and_run, [''])
+test('LintEtaExpand', normal, compile_and_run, [''])
 ## These tests use the GHC API.
 ## Test cases which don't use the GHC API should be added nearer the top.
diff --git a/testsuite/tests/ghc-api/all.T b/testsuite/tests/ghc-api/all.T
index 4e6aa167488f..3ab61f2f6a96 100644
--- a/testsuite/tests/ghc-api/all.T
+++ b/testsuite/tests/ghc-api/all.T
@@ -4,14 +4,14 @@ test('T8639_api', req_rts_linker,
               makefile_test, ['T8639_api'])
 test('T8628', req_rts_linker,
               makefile_test, ['T8628'])
-test('T9595', [extra_run_opts('"' + config.libdir + '"'), js_broken(22362)],
+test('T9595', [extra_run_opts('"' + config.libdir + '"')],
               compile_and_run,
               ['-package ghc'])
 test('T10508_api', [ extra_run_opts('"' + config.libdir + '"'),
                      req_rts_linker ],
                    compile_and_run,
                    ['-package ghc'])
-test('T10942', [extra_run_opts('"' + config.libdir + '"'), js_broken(22362)],
+test('T10942', [extra_run_opts('"' + config.libdir + '"')],
                    compile_and_run,
                    ['-package ghc'])
 test('T9015', extra_run_opts('"' + config.libdir + '"'),
@@ -26,7 +26,7 @@ test('T18181',
      compile_and_run,
      ['-package ghc'])
 test('T18522-dbg-ppr',
-  [extra_run_opts('"' + config.libdir + '"'), js_broken(22362)],
+  [extra_run_opts('"' + config.libdir + '"'), fragile(22362)],
   compile_and_run,
   ['-package ghc'])
 test('T19156', [ extra_run_opts('"' + config.libdir + '"')
-- 
GitLab