Fork me on GitHub
#clojurescript
<
2022-10-01
>
Daniel Lundsgaard Skovenborg22:10:11

I'm getting goog.Timer.defaultTimerObject.setTimeout is not a function when using optimizations. The reason is that this code in goog/timer/timer.js, which is supposed to set goog.Timer.defaultTimerObject to window :

goog.Timer.defaultTimerObject = goog.global;
runs before this code from cljs.core which is supposed to set goog.global to window:
(cond
    (identical? "window" *global*) (set! goog/global js/window)
...
Instead it is run after the code in goog/base.js which sets goog.global = this; which works fine in development, but in the code produced by webpack this is not binded to window. The problem is similar to https://clojurians.slack.com/archives/C03S1L9DN/p1635190065077900, but I can't see how I can set goog.global to js/window as :closure-defines only accepts fn, number, string, or boolean values. I believe this is the problem the code in cljs.core tries to solve as I get the following warning from FigWheel if cljs.core/*global* is set to another value. Any idea how to solve this besides running a sed -i 's/goog\.global=this||self/goog.global=self/' or (even worse but required for advanced optimizations) sed -i 's/=this||self/=self/' on the resulting file (which works but is kind of nasty)?

Daniel Lundsgaard Skovenborg22:10:53

A little more robust but still nasty (ensuring that we only hit an assignment; also notice that only the first occurrence will be replaced): perl -p -i -e 's/(?<!=)=this\|\|self/=self/'

Daniel Lundsgaard Skovenborg19:10:33

In case anyone finds this thread, here's a function I now use in my Bash build-script:

function fix_goog_global() {
  local f=$1
  local num_to_replace
  # Nasty hack to solve goog.global not being set correctly by ClojureScript (cljs/core.cljs bottom) before being used
  # by other code (like "goog.Timer.defaultTimerObject = goog.global;" in goog/timer/timer.js).
  # Using  does not seem to be a possibility because goog/base.js is not
  # loaded as a module but with a raw "document.write('<script ..."; the imports-loader complains that the module does
  # not exist.
  # Terminate if there's any doubt that we are replacing the right thing.
  num_to_replace=$(grep -oE '[^=]=this\|\|self[,;]' "$f" | wc -l)
  if [[ "$num_to_replace" -ne 1 ]]; then
    echo "Found $num_to_replace occurences of '=this||self' to replace!"
    exit 1
  fi
  perl -p -i -e 's/(?<!=)=this\|\|self(?=[,;])/=self/' "$f"
}