Fork me on GitHub
#shadow-cljs
<
2022-07-20
>
lsenjov00:07:46

What does check actually do? ie shadow-cljs check app There's an example in the docs, but doesn't actually say what it does

thheller04:07:29

@lsenjov it runs the closure compiler type checker over the code. unfortunately that is very noisy and produces very many false positives, so I never made it an official documented feature

👍 1
thheller04:07:47

externs inference does a better job most of the time

ullrich09:07:04

Hello friends 👋 We’ve recently updated a project from ClojureScript 1.10.879 to 1.11.60 and from ShadowCLJS 2.15.12 to 2.19.6. Since the upgrade we’re seeing a new runtime issue though: Property '$jscomp' doesn't exist The project is a React-Native app, using the Hermes JS engine. Unfortunately https://hermesengine.dev/docs/language-features/ so we need to target ES5, but so far we could live with that. As far as I understand $jscomp points to an issue with polyfills not working correctly. Not sure which one specifically though. That $jscomp error goes away when targeting ES6, but is replaced with other ES6 issues, in particular Property 'Long' doesn't exist. I was wondering if there’s a way to pull in polyfills explicitly using force-library-injection, but I don’t know which polyfill would bring Long and did not find any in https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/js/polyfills.txt inside the Closure project. Any suggestions how to dig deeper into the issue? I’ve already tried cleaning .shadow-cljs . Thanks 🙌

thheller09:07:48

can't say without more context. $jscomp for polyfills or other compiler generated code that is correct.

thheller09:07:39

Property '$jscomp' doesn't exist when does it say that? did you check the generated source if its actually defined? just search for $jscomp= or $jscomp =? maybe it is defined just not in a way that hermes find it?

thheller09:07:13

since you are using react-native doesn't metro perform the polyfilling for you? why have the CLJS do it?

thheller09:07:16

Long isn't a polyfill? its just a regular closure library class so I'm not sure how this relates?

ullrich13:07:29

I’ve done some more digging, here’s some more info and what I’ve found so far: • The error at app runtime, even before a debugger can attach. There’s no stacktrace, just a oneline log in metro • I compared the shadow output before and after the update and did some divide and conquer and found that after the update there’s a new SHADOW_ENV.evalLoad("goog.iter.es6.js"... that wasn’t present before. Inside of it there’s a call to $jscomp.inherits(...) which seems to be the one that triggers the error in metro (confirmed by changing the code, renaming $jscomp to something else which changes the error output)

ullrich13:07:17

It seems that the es6 iter is required from various collection types now, i.e. from goog.structs.map which in the updated version has two new requires: goog.iter.es6 and goog.collections.iters

thheller13:07:46

yes, a variety of things in the closure library got modernized and use es6 features

thheller13:07:05

but $jscomp should be defined regardless. did you check if it is ever assigned anywhere?

thheller13:07:36

I maybe assumed that react-native is just capable of es6+ and polyfilling isn't necessary and never handled $jscomp setup because of that

thheller13:07:05

but in the other targets this is automated so should be for react-native too

thheller13:07:39

might be enough to try to prepend global.$jscomp = {} to the generated output as a test

thheller13:07:00

my guess is the assignment actually exists but is not exported as a global

thheller13:07:03

and as such the code cannot find it

ullrich13:07:31

goog.base contains this

var jscomp = goog.global["$jscomp"];
  if (!jscomp) {
    goog.global["$jscomp"] = jscomp = {};
  }
but it’s part of the goog.transpile_()

thheller13:07:43

no, thats not it

ullrich13:07:45

Adding global.$jscomp = goog did the trick.

thheller13:07:24

thats not correct, it is not goog. should be {}

ullrich13:07:53

^^ but that would not help when the code is calling $jscomp.inherits(...)

thheller13:07:40

well, I'm assuming that the polyfills are actually added to the code somewhere

thheller13:07:51

goog.inherits is not what $jscomp.inherits normally would be

thheller13:07:08

and most certainly goog does not contain any of the other polyfills you might need

thheller13:07:37

if they aren't added anywhere else either then polyfill output is just ignored

thheller13:07:59

just search for $jscomp. uses in the code. it should include some assignments not just uses

thheller13:07:24

feel free to open an issue about this, cannot look into it right now myself

👍 1
ullrich13:07:55

Thanks for your help already @U05224H0W. I’ll dig some more.

ullrich14:07:03

It seems to occur everywhere where a ES6 class is with extend is compiled with ES5 output format. Trying to come up with a small repro.

thheller14:07:27

I think you can stop your investigation. I think I just assumed that react-native was capable of es6+ and never bothered to include any polyfill code at all

thheller14:07:02

busy with other stuff so can't look at it right now

ullrich14:07:40

@U05224H0W it actually reproduces in browser trargets as well. Trying shadow vs standard CLJS compiler now and will provide a small repro.

ullrich14:07:31

Reproduced the issue with standard clojurescript compiler in node env. Here’s a tiny repo with a demo https://github.com/stigi/clojurescript-es5-issue

thheller14:07:31

this doesn't mean anything for shadow-cljs though

thheller14:07:55

it handles all of this on its own and doesn't use anything from the regular CLJS tools

ullrich15:07:31

Updated the repo with shadow reproduction steps. Not sure on which project to open an issue now. My guess would be https://github.com/google/closure-compiler then.

thheller15:07:09

well for shadow-cljs in the shadow-cljs repo

thheller15:07:47

it might be an issue in the closure compiler but I'd want to confirm that on the shadow-cljs side first

🙌 1
👍 1
thheller15:07:42

there was a closure compiler issue before where it didn't properly keep track of which polyfills were added and rewrote but didn't add polyfills

ullrich15:07:43

We also stumbled across this https://github.com/google/closure-compiler/issues/3879#issuecomment-948583193 that I’m working my way through right now.

ullrich19:07:51

FYI: compiler option :force-library-injection #{"es6/util/inherits"} did the trick.

ullrich22:07:41

Put up a https://github.com/thheller/shadow-cljs/pull/1035 that fixes one more issue in the react-native target that did not yet make $jscomp available on the global scope (node target already did so though).