Fork me on GitHub
#shadow-cljs
<
2023-02-24
>
alexdavis15:02:19

I'm trying to use the library '@tanstack/router' which has some syntax that shadow-cljs/closure-compiler does not like. specifically this line

if (!this.#hasLoaders()) {
which I think is using the # to denote a https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields, causes the error
Errors encountered while trying to parse file
  .../node_modules/@tanstack/router/build/esm/index.js
  {:line 538, :column 14, :message "'identifier' expected"}
Is this a known issue? is there anything I can do to get it to work?

thheller15:02:54

that is the closure compiler yeah, only thing you can do is use the latest shadow-cljs/closure-compiler versions. if they don't like it your only option is using webpack via https://code.thheller.com/blog/shadow-cljs/2020/05/08/how-about-webpack-now.html#option-2-js-provider-external

alexdavis15:02:57

ok thanks, just found this issue https://github.com/google/closure-compiler/issues/2731 > Getting this support completed is top of my mind for the coming quarter. Probably I'll just use a different router

Braden Shepherdson16:02:51

A TS type check of all our code (which includes some TS) is failing because of this busted syntax in cljs_env.js (dev mode):

addNewerLanguageTranspilationCheck("es_2019", function() {
  return evalCheck('let r;try{r\x3d"
"}catch{};r');
});
that character in the double quotes is a 0x2029 paragraph separator. it's causing lots of problems in other places (eg. making NeoVim duplicate characters, Slack apparently renders it as a line break but vim doesn't, etc.)

Braden Shepherdson16:02:05

tsc thinks it's a line break too, and fails with an unterminated string literal. I think what evalCheck is testing would still work if it were spelled "\u2029".

Braden Shepherdson16:02:26

(I don't know if that cljs_env.js is coming from shadow-cljs or upstream; sorry if this is misdirected.)

thheller18:02:09

this is coming from the closure library, nothing I can really change

thheller18:02:26

can't you configure tsc to just ignore all the cljs output? I mean its not gonna find anything useful there?

Braden Shepherdson18:02:39

okay, that's what I suspected. perhaps I can tweak the TS config to do the right thing.

Braden Shepherdson18:02:04

it complains about missing imports if I delete the CLJS. but perhaps I can make it there-but-don't-check-it. anyway, it's out of scope here.

Braden Shepherdson15:02:05

I actually already have a thread sort of about this. if you include CLJS output in a TypeScript build, tsc will fail to parse cljs_env.js. • the checks for which JS version is in use eval little fragments of JS to check what the engine supports: • the one for es_2019 uses a change to JS https://github.com/tc39/proposal-json-superset that added support for U+2028 LINE SEPARATOR and U+2029 PARAGRAPH SEPARATOR as legal whitespace inside string literals, since JSON already does and JS is supposed to be a superset of JSON; this was a gap in that goal. • the eval'd code in that test has a literal U+2029 character in it

addNewerLanguageTranspilationCheck("es_2019", function() {
  return evalCheck('let r;try{r\x3d"
"}catch{};r');
});
notice that Slack can't handle it neatly either. it renders as a line break, invisible, or a space, or worse, depending on your editor. in my NeoVim it's a space but it makes the rest of the line buggy. • TypeScript also claims to be a superset of JS, but it doesn't parse those characters in strings, at least as of 4.7.2. if this issue can be a "bug" anywhere, it's a TS bug, but that's a long road to fix. changing the code in cljs_env.js to use \u2029 instead of the literal character fixes the TS issue without damaging the test for ES2019, since by the time the eval is running the inner string literal contains a real U+2029 character. (also worth pointing out this makes the cljs_env.js file itself ES2019+, which seems to ruin the point of these input language checks!)

thheller15:02:45

hmm weird. I can't find the source of this psecific problem?

thheller16:02:01

can you send me your cljs_env.js? wonder where it comes from

Braden Shepherdson16:02:09

I couldn't find where we got these checks from either.

thheller16:02:39

ah it is no longer in the goog/base.js

thheller16:02:00

but it is in the version currently used by cljs. so a bump in the closure library would take care of it I guess

Braden Shepherdson16:02:25

ah, so this was patched by Closure?

thheller16:02:02

yes, unfortunately bumping the closure library version has been less than reliable and often comes with a bunch of breaking changes

thheller16:02:23

not sure we can seamlessy get a newer version. but this is something for #C07UQ678E I guess

thheller16:02:08

maybe do start that question there again but mentioning goog/base.js instead of cljs_env.js

thheller16:02:25

this was the commit where all the problematic code was removed

thheller16:02:33

I mean if you want an immediate fix you can probably take this file https://github.com/google/closure-library/blob/master/closure/goog/base.js and put it in your classpath

Braden Shepherdson16:02:42

hm. is there a clean way to force the version of the Closure compiler/library used by CLJS?

thheller16:02:31

well, its just a maven dep. but there is no newer release as of yet as David does them.

Braden Shepherdson16:02:27

I see. well, okay. this is definitely an obscure corner case, so a hack in the meantime seems appropriate. I'm tempted to just put a little script into our type-check command to change the character.

thheller16:02:06

I asked if he can make a new release. shouldn't take long, until then manually copying is your ownly option

thheller16:02:30

I mean why is this running through tsc in the first place? its never gonna do anything useful with it?

Braden Shepherdson16:02:05

we're using tsc --noEmit to type-check the TS + JS + CLJS (output) codebase.

thheller16:02:05

seems like it would speed things up if it would ignore it?

thheller16:02:34

but what does that give you for the CLJS output? ever got anything useful from doing that?

Braden Shepherdson16:02:41

if I exclude or delete the CLJS output it fails because there are imports in the JS and TS for things that don't exist. it doesn't really examine the JS files, but it does parse them.

thheller16:02:22

hmm yeah I don't know anything about tsc, so not sure what to do here

Braden Shepherdson16:02:26

I agree it's dumb, and that's why I'm fine with some hack like editing the file.

Braden Shepherdson16:02:56

as I say, using the \u2029 escape fixes the outer parse without breaking the check it's trying to do inside eval, so that seems safe enough.

thheller16:02:39

well we don't need any of the code that was deleted in the commit I linked

thheller16:02:44

so just having it gone would best 😛

Braden Shepherdson16:02:38

for sure. I'll follow the update and delete this hack once it lands.

thheller17:02:45

give org.clojure/google-closure-library 0.0-20230227-c7c0a541 a shot. maybe that works out of the box. I'm deep in something else right now, so will be a bit before I test myself

thheller17:02:58

just adding it as a dep should be fine

Braden Shepherdson17:02:46

it works. thanks! also as a bonus I realized this is probably why the line numbers and breakpoints have been weird and off-by -one in the devtools for this build.

Braden Shepherdson17:02:11

because this literal paragraph break character confuses ~everything, including editors and Slack.

thheller17:02:23

hehe. I don't know why it was there either or why the compiler replaces the \u variant. good that it is gone, it was useless code anyways

Braden Shepherdson17:02:59

oh, I hadn't even spotted that in the commit. several parts of this code are encoded weirdly by the time it reaches the cljs_env.js on disk. it turns the = signs into \x2d or whatever the right ASCII code is.

denik17:02:46

@thheller these warnings print on every re-compilation step obfuscating whether the built was successful. I think it’s sensible to show a warning once for every redef during a watch process.

thheller19:02:38

fixing warnings is usually the best thing to do but I guess these libs might not be super maintained given https://github.com/thi-ng/math/pull/3

‼️ 2
lilactown21:02:31

it would be great to be able to control whether they're printed

lilactown21:02:47

similar to how we can control which warnings are consider errors

thheller21:02:01

I think only printing warnings from libraries once is reasonable

thheller21:02:27

not like you are able to fix them anyways without restarting and changing the dependency

👍 2
Maris22:02:37

window.SLLogger = logger; // default global logger
This ^ is code from sumo-logger package from npm. What should I do if I want to use it from shadow-cljs ? Require and js/SLLogger.config ?

thheller22:02:15

how do you use it in JS? what is logger in that example above? why is it set as a global? do you do that or does the library do that?

Maris22:02:29

in JS:

SLLogger.log({
    "userType": "silver",
    "referralSource": referralSource,
    "campaignId": campaignId
  });

thheller22:02:52

and what is SLLogger there?

thheller22:02:32

is there a const SLLogger = require("sumo-logger") or whatever?

thheller22:02:05

I mean I'd expect (:require ["sumo-logger" :as sumo]) and (sumo/log #js {...}) to work

thheller22:02:18

but thats just a guess

Maris22:02:19

no const , it gets assigned to global var ( window )

thheller22:02:32

but that global var has to come from something 😛

Maris22:02:34

var logger = new SumoLogger();
window.SLLogger = logger; // default global logger

thheller22:02:48

ok, where is SumoLogger coming from 😛

thheller22:02:15

I mean the code has to be loaded from something.

Maris22:02:28

It is a function

function SumoLogger() {
    this.sendErrors = false;

thheller22:02:41

(:require ["sumo-logger" :as sumo]) (def logger (sumo. opts)) (.log logger "event message to log", ...)

thheller22:02:02

yes, but how do you get access to it 😛

thheller22:02:28

var sumoLogic = require('sumo-logger');
    var opts = {
        endpoint: 'your HTTP Source endpoint',
        clientUrl: '' // NODE version only,
        // ... any other options ...
    };
    
    // Instantiate the SumoLogger
    var sumoLogger = new SumoLogger(opts);
    
    // Push a message to be logged
    sumoLogger.log('event message to log', {
      sessionKey: 'your session key value',
      url: ''
    });
    
    // Flush any logs, typically this line would be in your shutdown code
    sumoLogger.flushLogs();

Maris22:02:28

It was js/SLLogger.log when it was still using library from CLJSJS

thheller22:02:35

this I was looking for

thheller22:02:51

so that translates to roughly the above

👍 2
thheller22:02:27

wait no it doesn't god these docs are trash 😛

🙁 2
thheller22:02:23

var sumoLogic = require('sumo-logger'); I'm guessing thats just a mistake in the docs

thheller22:02:37

otherwise the example still doesn't clarify where SumoLogger is coming from

thheller22:02:54

but my snippet should still work

Maris22:02:29

thats for node.js , it is different ( I am not using nodejs )

thheller22:02:47

but you are using the npm package

Maris22:02:36

yeah, sumologic has different version for nodejs env

thheller22:02:40

now I see it

thheller22:02:52

> Add <script src="path/to/sumologic.logger.min.js"></source> or <script src="path/to/sumologic.logger.js"></source> to your pages.

thheller22:02:33

yeah what a piece of nonsense that package is 😛

2
thheller22:02:07

(:require ["sumo-logger/src/sumologic.logger.min.js"]) and then just the global js/SLLogger I guess

thheller22:02:34

uhm the first link you gave was to a super old version

thheller22:02:46

which one do you actually use?

Maris22:02:09

"sumo-logger" "2.5.5"

thheller22:02:20

well yeah thats entirely different

thheller22:02:28

(:require ["sumo-logger" :as sumo]) (def logger (sumo. opts)) (.log logger "event message to log", ...)

thheller22:02:32

should be fine for that version

thheller22:02:17

1.0 was definitely different