JS: Google Closure Compiler hard errors (fixes #24602)
Still WIP but any review comments are welcome! Still in makeup process, the best time to add review comments.
You can test:
$ ../ghc-js/_build/stage1/bin/javascript-unknown-ghcjs-ghc -fforce-recomp HelloJS.hs
$ google-closure-compiler --debug --warning_level VERBOSE --formatting PRETTY_PRINT --isolation_mode IIFE --assume_function_wrapper --emit_use_strict --externs ./HelloJS.jsexe/all.js.externs --compilation_level ADVANCED_OPTIMIZATIONS ./HelloJS.jsexe/all.js --js_output_file ./HelloJS.jsexe/all.min.debug.js
...
0 error(s), 683 warning(s), 94.2% typed
The series of commits is large. Let's break it on independent parts and connect commits to errors on which they are targeted.
#24602 (closed))
JS: fix typos and namings (fixesErrors fixed by this commit
./HelloJS.jsexe/all.js:9747:68: ERROR - [JSC_UNDEFINED_VARIABLE] variable null_ is undeclared
9747| var p = (((ptr_d).arr && (ptr_d).arr[off]) ? (ptr_d).arr[off] : null_); var o = (ptr_d).dv.getInt32(off,true);;
^^^^^
./HelloJS.jsexe/all.js:12808:11: ERROR - [JSC_UNDEFINED_VARIABLE] variable h$vt_int is undeclared
12808| case h$vt_int:
^^^^^^^^
./HelloJS.jsexe/all.js:10273:26: ERROR - [JSC_UNDEFINED_VARIABLE] variable j is undeclared
10273| for(j=x.length-1;j>=0;j--) {
^
./HelloJS.jsexe/all.js:12247:9: ERROR - [JSC_UNDEFINED_VARIABLE] variable ptr is undeclared
12247| return ptr = h$initHeapBufferLen(str_d, str_o, str_d.len);
^^^
./HelloJS.jsexe/all.js:13834:33: ERROR - [JSC_UNDEFINED_VARIABLE] variable arr is undeclared
13834| return h$charCodeArrayToString(arr);
^^^
./HelloJS.jsexe/all.js:13925:12: ERROR - [JSC_UNDEFINED_VARIABLE] variable h$EINVAL is undeclared
13925| h$errno = h$EINVAL;
^^^^^^^^
You may noted that I've also changed term of
, global "h$vt_double" ||= toJExpr IntV
IntV
WaitReadOp -> \[] [fd] -> pure $ PRPrimCall $ returnS (app "h$waidRead" [fd])
h$waidRead
I think these were typos.
#24602 (closed))
JS: trivial checks for variable presence (fixesErrors fixed by this commit
./HelloJS.jsexe/all.js:8432:27: ERROR - [JSC_UNDEFINED_VARIABLE] variable Buffer is undeclared
8432| h$fs.read(real_fd, Buffer.alloc(n), 0, n, pos, function(err, bytesRead, nbuf) {
^^^^^^
./HelloJS.jsexe/all.js:8495:8: ERROR - [JSC_UNDEFINED_VARIABLE] variable putstr is undeclared
8495| putstr(h$decodeUtf8(buf, n, buf_offset));
^^^^^^
./HelloJS.jsexe/all.js:8499:8: ERROR - [JSC_UNDEFINED_VARIABLE] variable printErr is undeclared
8499| printErr(h$decodeUtf8(buf, n, buf_offset));
^^^^^^^^
./HelloJS.jsexe/all.js:8507:37: ERROR - [JSC_UNDEFINED_VARIABLE] variable debug is undeclared
8507| var h$base_stderrLeftover = { f: debug, val: null };
^^^^^
./HelloJS.jsexe/all.js:7795:8: ERROR - [JSC_UNDEFINED_VARIABLE] variable java is undeclared
7795| java.lang.System.out.print(s);
^^^^
./HelloJS.jsexe/all.js:12498:25: ERROR - [JSC_UNDEFINED_VARIABLE] variable h$setCcs_e is undeclared
12498| if(h$stack[h$sp] !== h$setCcs_e) {
^^^^^^^^^^
JS: fs module imported twice (by emscripten and by ghc-internal)
Errors fixed by this commit
./HelloJS.jsexe/all.js:57067:4: ERROR - [JSC_VAR_MULTIPLY_DECLARED_ERROR] Variable fs declared more than once. First occurrence: ./HelloJS.jsexe/all.js:7767:8
57067| var fs, nodePath;
Better solution is to use some JavaScript module system. It will be investigated at other issues.
fds and h
fdReady to be declared for static code analysis
JS: thread.js requires hErrors fixed by this commit
./HelloJS.jsexe/all.js:14112:2: ERROR - [JSC_UNDEFINED_VARIABLE] variable h$fds is undeclared
14112| h$fds[fd].waitRead.push(h$currentThread);
^^^^^
./HelloJS.jsexe/all.js:33154:5: ERROR - [JSC_UNDEFINED_VARIABLE] variable h$fdReady is undeclared
33154| h$r1=h$fdReady(a,1,f,(c>>>0),0);
^^^^^^^^^
I am not sure does it enough for now or not. I've just copied some old pieces of GHCJS from publicly available sources. Also I didn't put details to h$fds
. I took minimal and left only its object initialization: var h$fds = {};
.
So, any shedding light is important here. Does it OK for now or it requires better attention?
#24602 (closed))
JS: heap and stack overflows reporting defined as js hard failure (fixesErrors fixed by this commit
./HelloJS.jsexe/all.js:47403:0: ERROR - [JSC_UNDEFINED_VARIABLE] variable h$reportStackOverflow is undeclared
47403| h$reportStackOverflow(c);
^^^^^^^^^^^^^^^^^^^^^
./HelloJS.jsexe/all.js:47407:8: ERROR - [JSC_UNDEFINED_VARIABLE] variable h$reportHeapOverflow is undeclared
47407| case(2):h$reportHeapOverflow();
^^^^^^^^^^^^^^^^^^^^
These errors were treated as a hard failure for browser application. The fix is trivial: just throw
error. Please, suggest better way if needed due to STG semantics.
Stubs
Errors fixed by these commits. They are common by sense.
./HelloJS.jsexe/all.js:12941:22: ERROR - [JSC_UNDEFINED_VARIABLE] variable h$checkInvariants_e is undeclared
12941| h$stack[h$sp] = h$checkInvariants_e;
^^^^^^^^^^^^^^^^^^^
./HelloJS.jsexe/all.js:24517:13: ERROR - [JSC_UNDEFINED_VARIABLE] variable h$stg_cloneMyStackzh is undeclared
24517| if(c) {var g=h$stg_cloneMyStackzh();
^^^^^^^^^^^^^^^^^^^^
./HelloJS.jsexe/all.js:24518:6: ERROR - [JSC_UNDEFINED_VARIABLE] variable h$stg_decodeStackzh is undeclared
24518| var i=h$stg_decodeStackzh(g);
^^^^^^^^^^^^^^^^^^^
./HelloJS.jsexe/all.js:25814:6: ERROR - [JSC_UNDEFINED_VARIABLE] variable h$libdwLookupLocation is undeclared
25814| var h=h$libdwLookupLocation(d,e,a,c,f,g);
^^^^^^^^^^^^^^^^^^^^^
./HelloJS.jsexe/all.js:26282:21: ERROR - [JSC_UNDEFINED_VARIABLE] variable h$libdwPoolRelease is undeclared
26282| h$r3=h$mkFunctionPtr(h$libdwPoolRelease);
^^^^^^^^^^^^^^^^^^
./HelloJS.jsexe/all.js:26290:2: ERROR - [JSC_UNDEFINED_VARIABLE] variable h$libdwPoolTake is undeclared
26290| a=h$libdwPoolTake();
^^^^^^^^^^^^^^^
./HelloJS.jsexe/all.js:26307:2: ERROR - [JSC_UNDEFINED_VARIABLE] variable h$libdwGetBacktrace is undeclared
26307| c=h$libdwGetBacktrace(a,b);
^^^^^^^^^^^^^^^^^^^
./HelloJS.jsexe/all.js:26335:21: ERROR - [JSC_UNDEFINED_VARIABLE] variable h$backtraceFree is undeclared
26335| h$r3=h$mkFunctionPtr(h$backtraceFree);
^^^^^^^^^^^^^^^
./HelloJS.jsexe/all.js:37760:5: ERROR - [JSC_UNDEFINED_VARIABLE] variable h$lookupIPE is undeclared
37760| h$r1=h$lookupIPE(a,c,d,0);
^^^^^^^^^^^
Stubs commits:
-
STM
:h$stmCheckInvariants
-
RTS/Libdw
:h$libdwLookupLocation
,h$libdwPoolRelease
,h$libdwPoolTake
,h$libdwGetBacktrace
,h$backtraceFree
,h$libdwLookupLocation
,h$libdwPoolRelease
,h$libdwPoolTake
,h$libdwGetBacktrace
,h$backtraceFree
-
RTS/StackCloningDecoding
:h$stg_cloneMyStackzh
,h$stg_decodeStackzh
RTS h$lookupIPE
These errors were fixed just by introducing stubbed functions with throw
for further implementation. Again, please let me known which functions should be actually ported (and from where) in this commit, I could try to do that.
Here I think there is a good reason to squash them into single commit if we do not need to apply actual implementation in this MR. Squashed.
Google Closure Externs support
The error from which this mini-journey was started
./HelloJS.jsexe/all.js:57052:22: ERROR - [JSC_UNDEFINED_VARIABLE] variable __dirname is undeclared
57052| scriptDirectory = __dirname + '/';
^^^^^^^^^
It is the heaviest part of this MR by sense:
- JS: Add special preprocessor for js files due of needing to keep jsdoc comments (fixes #24602 (closed))
- JS: Add externs to linker (fixes #24602 (closed))
Our js files have defined google closure compiler types at jsdoc entries but these jsdoc entries are removed by cpp preprocessor. I considered that reusing them in javascript-backend would be a nice thing. Right now haskell processor uses -traditional
option to deal with comments and //
operators. Its application has the long story: 1997, 1999, 2000, 2001, 2003 1, 2003 2, 2003 3, 2013, 2014 1, 2014 2, 2014 3, 2014 4, 2015, 2022 first usage in context of javascript-backend, 2023 1, 2023 2, 2023 3, 2024, . But now there are following compiler options: -C
and -CC
. You can read about them at GCC and CLang. It seems that -CC
works better for javascript jsdoc than -traditional
. At least it leaves /* ... */
comments w/o changes.
After enabling jsdoc and built-in google closure compiler types I was needed to deal with the following:
- Define NodeJS-environment types. I've just copied minimal set of externs from semi-official repo.
- Define Emscripten-environment types:
HEAP8
. Emscripten already provides some externs in our code but it supposed to be run in some module system. And its definitions do not work well in plain bundle. - We have some functions which purpose is to add to functions some contextual information via function properties. These functions should be marked as
modifies
to let google closure compiler remove calls if these functions are not used actually by call graph. Such functions are:h$o
,h$sti
,h$init_closure
,h$setObjInfo
. - STG primitives such as registries and stuff from
GHC.StgToJS
.dXX
properties were already present at externs generator function but by unknown reason they are started from7
, not from1
. This message is related:// fixme does closure compiler bite us here?
.